diff --git a/CHANGELOG.md b/CHANGELOG.md
index ddf9320cb..471066ac3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -352,7 +352,7 @@
- Fix window sizes and input field sizes for flat skin [\#381](https://github.com/ZoneMinder/ZoneMinder/pull/381) ([m-bene](https://github.com/m-bene))
- Fix reload loop on switching skins [\#380](https://github.com/ZoneMinder/ZoneMinder/pull/380) ([m-bene](https://github.com/m-bene))
- Ability to skip frames in motion detection. [\#377](https://github.com/ZoneMinder/ZoneMinder/pull/377) ([Sune1337](https://github.com/Sune1337))
-- same dvr controlls in event as in monitor [\#375](https://github.com/ZoneMinder/ZoneMinder/pull/375) ([m-bene](https://github.com/m-bene))
+- same dvr controls in event as in monitor [\#375](https://github.com/ZoneMinder/ZoneMinder/pull/375) ([m-bene](https://github.com/m-bene))
- do not quote column names in parse filter [\#374](https://github.com/ZoneMinder/ZoneMinder/pull/374) ([m-bene](https://github.com/m-bene))
- Fix 'Undefined index: filter' php warnings for filter view when [\#373](https://github.com/ZoneMinder/ZoneMinder/pull/373) ([m-bene](https://github.com/m-bene))
- Reduce window size to exclude task bar area [\#371](https://github.com/ZoneMinder/ZoneMinder/pull/371) ([m-bene](https://github.com/m-bene))
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0a1385a25..1d6ba16d3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -133,9 +133,9 @@ set(ZM_NO_CURL "OFF" CACHE BOOL
"Set to ON to skip cURL checks and force building ZM without cURL. default: OFF")
set(ZM_NO_X10 "OFF" CACHE BOOL
"Set to ON to build ZoneMinder without X10 support. default: OFF")
-set(ZM_ONVIF "OFF" CACHE BOOL
+set(ZM_ONVIF "ON" CACHE BOOL
"Set to ON to enable basic ONVIF support. This is EXPERIMENTAL and may not
- work with all cameras claiming to be ONVIF compliant. default: OFF")
+ work with all cameras claiming to be ONVIF compliant. default: ON")
set(ZM_PERL_MM_PARMS INSTALLDIRS=vendor NO_PACKLIST=1 NO_PERLLOCAL=1 CACHE STRING
"By default, ZoneMinder's Perl modules are installed into the Vendor folders,
as defined by your installation of Perl. You can change that here. Consult Perl's
diff --git a/Dockerfile b/Dockerfile
index 382330a09..26df17d2b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
# ZoneMinder
-FROM ubuntu:precise
+FROM ubuntu:trusty
MAINTAINER Kyle Johnson
# Let the container know that there is no tty
@@ -10,10 +10,10 @@ ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y \
libpolkit-gobject-1-dev 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 \
+ libwww-perl libdbd-mysql-perl libsys-mmap-perl yasm cmake libjpeg-turbo8-dev \
libjpeg-turbo8 libtheora-dev libvorbis-dev libvpx-dev libx264-dev libmp4v2-dev libav-tools mysql-client \
apache2 php5 php5-mysql apache2-mpm-prefork libapache2-mod-php5 php5-cli openssh-server \
- mysql-server libvlc-dev libvlc5 libvlccore-dev libvlccore5 vlc-data libcurl4-openssl-dev \
+ mysql-server libvlc-dev libvlc5 libvlccore-dev libvlccore7 vlc-data libcurl4-openssl-dev \
libavformat-dev libswscale-dev libavutil-dev libavcodec-dev libavfilter-dev \
libavresample-dev libavdevice-dev libpostproc-dev libv4l-dev libtool libnetpbm10-dev \
libmime-lite-perl dh-autoreconf dpatch
@@ -25,10 +25,11 @@ ADD . /ZoneMinder
WORKDIR /ZoneMinder
# Setup the ZoneMinder build environment
-RUN aclocal && autoheader && automake --force-missing --add-missing && autoconf
+#RUN aclocal && autoheader && automake --force-missing --add-missing && autoconf
# Configure ZoneMinder
-RUN ./configure --with-libarch=lib/$DEB_HOST_GNU_TYPE --disable-debug --host=$DEB_HOST_GNU_TYPE --build=$DEB_BUILD_GNU_TYPE --with-mysql=/usr --with-webdir=/var/www/zm --with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin --with-webuser=www-data --with-webgroup=www-data --enable-mmap=yes ZM_SSL_LIB=openssl ZM_DB_USER=zm ZM_DB_PASS=zm
+#RUN ./configure --with-libarch=lib/$DEB_HOST_GNU_TYPE --disable-debug --host=$DEB_HOST_GNU_TYPE --build=$DEB_BUILD_GNU_TYPE --with-mysql=/usr --with-webdir=/var/www/zm --with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin --with-webuser=www-data --with-webgroup=www-data --enable-mmap=yes --enable-onvif ZM_SSL_LIB=openssl ZM_DB_USER=zm ZM_DB_PASS=zm
+RUN cmake .
# Build ZoneMinder
RUN make
@@ -36,6 +37,9 @@ RUN make
# Install ZoneMinder
RUN make install
+# ensure writable folders
+RUN ./zmlinkcontent.sh
+
# Adding the start script
ADD utils/docker/start.sh /tmp/start.sh
@@ -43,15 +47,23 @@ ADD utils/docker/start.sh /tmp/start.sh
# TODO - Files ADD'ed have 755 already...why do we need this?
RUN chmod 755 /tmp/start.sh
-# Creating SSH privledge escalation dir
+# give files in /usr/local/share/zoneminder/
+RUN chown -R www-data:www-data /usr/local/share/zoneminder/
+
+# Creating SSH privilege escalation dir
RUN mkdir /var/run/sshd
# Adding apache virtual hosts file
-ADD utils/docker/apache-vhost /etc/apache2/sites-enabled/000-default
+ADD utils/docker/apache-vhost /etc/apache2/sites-available/000-default.conf
+ADD utils/docker/phpdate.ini /etc/php5/apache2/conf.d/25-phpdate.ini
# Set the root passwd
RUN echo 'root:root' | chpasswd
+# Add a user we can actually login with
+RUN useradd -m -s /bin/bash -G sudo zoneminder
+RUN echo 'zoneminder:zoneminder' | chpasswd
+
# Expose ssh and http ports
EXPOSE 80
EXPOSE 22
diff --git a/INSTALL b/INSTALL
index 35deec3c4..bcb7f78df 100644
--- a/INSTALL
+++ b/INSTALL
@@ -18,7 +18,7 @@ Important differences
---------------------
* Unlike the autotools way, the cmake way does not require any options. It attempts to detect some things by its own (system directories, libarch, web user and group) and uses defaults for others (installation paths and such).
* Unlike the autotools way, which links the binaries to a fixed list of libraries, the cmake way only links to libraries that it found on the system. If a library is not found, but required, a fatal error will be shown during the configuration step.
-* Unlike the autotools way, the cmake way does not modify the system in any way it shouldnt. It only does what its supposed to do: Install files to your system. Nothing else and nothing leaks out of the DESTDIR environment variable (if used). This means that depending on your configuration, there might be an extra required step after installation: to link WEB_PATH/events and WEB_PATH/images folders to the correct places.
+* Unlike the autotools way, the cmake way does not modify the system in any way it shouldn't. It only does what its supposed to do: Install files to your system. Nothing else and nothing leaks out of the DESTDIR environment variable (if used). This means that depending on your configuration, there might be an extra required step after installation: to link WEB_PATH/events and WEB_PATH/images folders to the correct places.
Configuration
-------------
diff --git a/README.md b/README.md
index 0077255b8..457f51844 100644
--- a/README.md
+++ b/README.md
@@ -239,7 +239,7 @@ Now clone the ZoneMinder git repository:
```bash
git clone https://github.com/ZoneMinder/ZoneMinder
```
-This will create a sub-folder called ZoneMinder, which will contain the latest developement.
+This will create a sub-folder called ZoneMinder, which will contain the latest development.
We want to turn this into a tarball, but first we need to figure out what to name it. Look here:
```bash
diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in
index 044fec234..3614bfedd 100644
--- a/db/zm_create.sql.in
+++ b/db/zm_create.sql.in
@@ -590,8 +590,10 @@ INSERT INTO Controls VALUES (NULL,'ONVIF Camera','Ffmpeg','onvif',0,0,1,1,0,0,0,
INSERT INTO `Controls` VALUES (NULL,'Foscam 9831W','Ffmpeg','FI9831W',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,16,1,1,1,1,0,0,0,1,1,0,360,0,360,1,0,4,0,0,1,0,90,0,90,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Foscam FI8918W','Ffmpeg','FI8918W',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,0,1,1,1,0,0,0,1,1,0,360,0,360,1,0,4,0,0,1,0,90,0,90,1,0,4,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'SunEyes SP-P1802SWPTZ','Libvlc','SPP1802SWPTZ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,64,0,0,1,0,0,0,0,1,0,64,0,0,0,0);
-
-
+INSERT INTO `Controls` VALUES (NULL,'Wanscam HW0025','Libvlc','WanscamHW0025', 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 350, 0, 0, 1, 0, 10, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0);
+INSERT INTO `Controls` VALUES (NULL,'IPCC 7210W','Libvlc','IPCC7210W', 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 350, 0, 0, 1, 0, 10, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0);
+INSERT INTO `Controls` VALUES (NULL,'Vivotek ePTZ','Remote','Vivotek_ePTZ',0,0,1,1,0,0,0,1,0,0,0,0,1,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,5,0,0,1,0,0,0,0,1,0,5,0,0,0,0);
+INSERT INTO `Controls` VALUES (NULL,'Netcat ONVIF','Ffmpeg','Netcat',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,100,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,100,5,5,0,0,0,1,255,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
--
-- Add some monitor preset values
diff --git a/db/zm_update-1.28.109.sql b/db/zm_update-1.28.109.sql
index be6dca9f1..dfbacdf5b 100644
--- a/db/zm_update-1.28.109.sql
+++ b/db/zm_update-1.28.109.sql
@@ -1,5 +1,5 @@
--
--- This updates a 1.28.106 database to 1.28.107
+-- This updates a 1.28.108 database to 1.28.109
--
--
diff --git a/db/zm_update-1.28.110.sql b/db/zm_update-1.28.110.sql
index a9fe04633..7a573bbf3 100644
--- a/db/zm_update-1.28.110.sql
+++ b/db/zm_update-1.28.110.sql
@@ -1,5 +1,5 @@
--
--- This updates a 1.28.106 database to 1.28.107
+-- This updates a 1.28.109 database to 1.28.110
--
--
diff --git a/distros/fedora/CMakeLists.txt b/distros/fedora/CMakeLists.txt
index f49d451f1..e6fc72add 100644
--- a/distros/fedora/CMakeLists.txt
+++ b/distros/fedora/CMakeLists.txt
@@ -10,7 +10,7 @@ configure_file(zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmp
configure_file(zoneminder.logrotate.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.logrotate @ONLY)
# Download jscalendar & move files into position
-file(DOWNLOAD http://downloads.sourceforge.net/jscalendar/jscalendar-1.0.zip ${CMAKE_CURRENT_SOURCE_DIR}/jscalendar-1.0.zip STATUS download_jsc)
+file(DOWNLOAD http://iweb.dl.sourceforge.net/project/jscalendar/jscalendar/1.0/jscalendar-1.0.zip ${CMAKE_CURRENT_SOURCE_DIR}/jscalendar-1.0.zip STATUS download_jsc)
if(download_jsc EQUAL 0)
message(STATUS "Jscalander successfully downloaded. Installing...")
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/jscalendar.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ERROR_VARIABLE unzip_jsc)
@@ -39,7 +39,7 @@ install(CODE "execute_process(COMMAND ln -sf ../../../../../../var/lib/zoneminde
# Fedora requires cambozola as a separate package so just link to it
install(CODE "execute_process(COMMAND ln -sf ../../java/cambozola.jar \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/cambozola.jar\")")
-# Install auxillary files required to run zoneminder on Fedora
+# Install auxiliary files required to run zoneminder on Fedora
install(FILES zoneminder.conf DESTINATION /etc/httpd/conf.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES zoneminder.logrotate DESTINATION /etc/logrotate.d RENAME zoneminder PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES ../../misc/zoneminder-tmpfiles.conf DESTINATION /etc/tmpfiles.d RENAME zoneminder.conf PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
diff --git a/distros/fedora/README.Fedora b/distros/fedora/README.Fedora
index 0f88a9a16..18d091772 100644
--- a/distros/fedora/README.Fedora
+++ b/distros/fedora/README.Fedora
@@ -5,27 +5,19 @@ What's New
"/cgi-bin-zm/zms". This has been to done to avoid this bug:
https://bugzilla.redhat.com/show_bug.cgi?id=973067
- IMPORTANT: ZoneMinder will not update this value during an upgrade. You must
- manually update ZM_PATH_ZMS yourself under Options. This does not affect
- new installs.
+ IMPORTANT: You must manually inspect the value for PATH_ZMS under Options
+ and verify it is set to "/cgi-bin-zm/nph-zms". Failure to do so will result
+ in a broken system. You have been warned.
-2. The ZoneMinder config file, zm.conf, has been moved under /etc/zm.
-
-3. Due to the active state of the ZoneMinder project, we now recommend granting
+2. Due to the active state of the ZoneMinder project, we now recommend granting
ALL permission to the ZoneMinder mysql account. This change must be done
manually before ZoneMinder will run. See the installation steps below.
-4. A new permission group called "Groups" has been added. This allows the
- system administrator to assign "view", "edit", or "none" permission to
- normal users, without giving them access to the rest of the ZoneMinder
- system. During an upgrade, existing accounts will default to a Groups
- permission of "none".
-
-5. This package now requires the HTTPS protocol to access the web portal.
+3. This package uses the HTTPS protocol by default to access the web portal.
Requests using HTTP will auto-redirect to HTTPS. See README.https for
more information.
-6. This package ships with the new ZoneMinder API enabled.
+4. This package ships with the new ZoneMinder API enabled.
New installs
============
@@ -86,13 +78,22 @@ New installs
SELINUX line from "enforcing" to "disabled". This change will take
effect after a reboot.
+6. Install mod_ssl or configure /etc/httpd/conf.d/zoneminder.conf to meet your
+ needs. This package comes preconfigured for HTTPS using the default self
+ signed certificate on your system. The recommended way to complete this step
+ is to simply install mod_ssl:
-6. Now start the web server:
+ sudo yum install mod_ssl
+
+ If this does not meet your needs, then read README.https to
+ learn about alternatives. When in doubt, install mod_ssl.
+
+7. Now start the web server:
sudo systemctl enable httpd
sudo systemctl start httpd
-7. Now start zoneminder:
+8. Now start zoneminder:
sudo systemctl enable zoneminder
sudo systemctl start zoneminder
@@ -131,6 +132,7 @@ Upgrades
/etc/httpd/conf.d. You will have a file called "zoneminder.conf" and there
may also be a file called "zoneminder.conf.rpmnew". If the rpmnew file
exists, inspect it and merge anything new in that file with zoneminder.conf.
+ Verify the SSL REquirements meet your needs. Read README.https if necessary.
4. Upgrade the database before starting ZoneMinder.
diff --git a/distros/fedora/zonemidner.f22.spec b/distros/fedora/zonemidner.f22.spec
new file mode 120000
index 000000000..808e7cb9f
--- /dev/null
+++ b/distros/fedora/zonemidner.f22.spec
@@ -0,0 +1 @@
+zoneminder.f23.spec
\ No newline at end of file
diff --git a/distros/fedora/zoneminder.f22.spec b/distros/fedora/zoneminder.f22.spec
deleted file mode 100644
index 9beef6319..000000000
--- a/distros/fedora/zoneminder.f22.spec
+++ /dev/null
@@ -1,409 +0,0 @@
-%define zmuid $(id -un)
-%define zmgid $(id -gn)
-%define zmuid_final apache
-%define zmgid_final apache
-
-%global _hardened_build 1
-
-### Delete the lines below to build with ffmpeg and/or x10
-%define _without_ffmpeg 1
-%define _without_x10 1
-
-Name: zoneminder
-Version: 1.29.0
-Release: 1%{?dist}
-Summary: A camera monitoring and analysis tool
-Group: System Environment/Daemons
-# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
-# Mootools is inder the MIT license: http://mootools.net/
-License: GPLv2+ and LGPLv2+ and MIT
-URL: http://www.zoneminder.com/
-
-#Source: https://github.com/ZoneMinder/ZoneMinder/archive/v%{version}.tar.gz
-Source: ZoneMinder-%{version}.tar.gz
-
-BuildRequires: cmake gnutls-devel systemd-units bzip2-devel
-BuildRequires: mariadb-devel pcre-devel libjpeg-turbo-devel
-BuildRequires: perl(Archive::Tar) perl(Archive::Zip) perl-podlators
-BuildRequires: perl(Date::Manip) perl(DBD::mysql)
-BuildRequires: perl(ExtUtils::MakeMaker) perl(LWP::UserAgent)
-BuildRequires: perl(MIME::Entity) perl(MIME::Lite)
-BuildRequires: perl(PHP::Serialization) perl(Sys::Mmap)
-BuildRequires: perl(Time::HiRes) perl(Net::SFTP::Foreign)
-BuildRequires: perl(Expect) perl(Sys::Syslog)
-BuildRequires: gcc gcc-c++ vlc-devel libcurl-devel libv4l-devel
-%{!?_without_ffmpeg:BuildRequires: ffmpeg-devel}
-%{!?_without_x10:BuildRequires: perl(X10::ActiveHome) perl(Astro::SunTime)}
-# cmake needs the following installed at build time due to the way it auto-detects certain parameters
-BuildRequires: httpd polkit-devel
-%{!?_without_ffmpeg:BuildRequires: ffmpeg}
-
-Requires: httpd php php-gd php-mysql cambozola polkit net-tools psmisc
-Requires: libjpeg-turbo vlc-core libcurl
-Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
-Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip)
-Requires: perl(MIME::Entity) perl(MIME::Lite) perl(Net::SMTP) perl(Net::FTP)
-Requires: perl(LWP::Protocol::https)
-%{!?_without_ffmpeg:Requires: ffmpeg}
-
-Requires(post): systemd-units systemd-sysv
-Requires(post): /usr/bin/gpasswd
-Requires(post): /usr/bin/less
-Requires(preun): systemd-units
-Requires(postun): systemd-units
-
-%description
-ZoneMinder is a set of applications which is intended to provide a complete
-solution allowing you to capture, analyse, record and monitor any cameras you
-have attached to a Linux based machine. It is designed to run on kernels which
-support the Video For Linux (V4L) interface and has been tested with cameras
-attached to BTTV cards, various USB cameras and IP network cameras. It is
-designed to support as many cameras as you can attach to your computer without
-too much degradation of performance.
-
-%prep
-%setup -q -n ZoneMinder-%{version}
-
-# Change the following default values
-./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin-zm/nph-zms
-./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
-./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm
-./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload
-./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes
-./utils/zmeditconfigdata.sh ZM_CHECK_FOR_UPDATES no
-./utils/zmeditconfigdata.sh ZM_DYN_SHOW_DONATE_REMINDER no
-
-%build
-%cmake \
- -DZM_TARGET_DISTRO="f22" \
-%{?_without_ffmpeg:-DZM_NO_FFMPEG=ON} \
-%{?_without_x10:-DZM_NO_X10=ON} \
- .
-
-make %{?_smp_mflags}
-
-%install
-export DESTDIR=%{buildroot}
-make install
-
-%post
-if [ $1 -eq 1 ] ; then
- # Initial installation
- /bin/systemctl daemon-reload >/dev/null 2>&1 || :
-fi
-
-# Allow zoneminder access to local video sources, serial ports, and x10
-/usr/bin/gpasswd -a %{zmuid_final} video
-/usr/bin/gpasswd -a %{zmuid_final} dialout
-
-# Upgrade from a previous version of zoneminder
-if [ $1 -eq 2 ] ; then
- # Freshen the database
- /usr/bin/zmupdate.pl -f
-
- # We can't run this automatically when new sql account permissions need to
- # be manually added first
- # Run zmupdate non-interactively
- #/usr/bin/zmupdate.pl --nointeractive
-fi
-
-# Warn the end user to read the README file
-echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, read README.Fedora to finish the\ninstallation or upgrade!\n"
-echo -e "\nThe README file is located here: %{_docdir}/%{name}\n"
-
-%preun
-if [ $1 -eq 0 ] ; then
- # Package removal, not upgrade
- /bin/systemctl --no-reload disable zoneminder.service > /dev/null 2>&1 || :
- /bin/systemctl stop zoneminder.service > /dev/null 2>&1 || :
-fi
-
-%postun
-/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-if [ $1 -ge 1 ] ; then
- # Package upgrade, not uninstall
- /bin/systemctl try-restart zoneminder.service >/dev/null 2>&1 || :
-fi
-
-%triggerun -- zoneminder < 1.25.0-4
-# Save the current service runlevel info
-# User must manually run systemd-sysv-convert --apply zoneminder
-# to migrate them to systemd targets
-/usr/bin/systemd-sysv-convert --save zoneminder >/dev/null 2>&1 ||:
-
-# Run these because the SysV package being removed won't do them
-/sbin/chkconfig --del zoneminder >/dev/null 2>&1 || :
-/bin/systemctl try-restart zoneminder.service >/dev/null 2>&1 || :
-
-
-%files
-%defattr(-,root,root,-)
-%doc AUTHORS COPYING README.md distros/fedora/README.Fedora distros/fedora/README.https distros/fedora/jscalendar-doc
-%config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf
-%config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf
-%config(noreplace) /etc/tmpfiles.d/zoneminder.conf
-%config(noreplace) /etc/logrotate.d/zoneminder
-
-%{_unitdir}/zoneminder.service
-
-%{_bindir}/zma
-%{_bindir}/zmaudit.pl
-%{_bindir}/zmc
-%{_bindir}/zmcontrol.pl
-%{_bindir}/zmdc.pl
-%{_bindir}/zmf
-%{_bindir}/zmfilter.pl
-%{_bindir}/zmpkg.pl
-%{_bindir}/zmstreamer
-%{_bindir}/zmtrack.pl
-%{_bindir}/zmtrigger.pl
-%{_bindir}/zmu
-%{_bindir}/zmupdate.pl
-%{_bindir}/zmvideo.pl
-%{_bindir}/zmwatch.pl
-%{_bindir}/zmcamtool.pl
-%{_bindir}/zmsystemctl.pl
-%{!?_without_x10:%{_bindir}/zmx10.pl}
-
-%{perl_vendorlib}/ZoneMinder*
-%{_mandir}/man*/*
-%dir %{_libexecdir}/zoneminder
-%{_libexecdir}/zoneminder/cgi-bin
-%dir %{_datadir}/zoneminder
-%{_datadir}/zoneminder/db
-%{_datadir}/zoneminder/www
-
-%{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy
-%{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules
-
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/lib/zoneminder
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/lib/zoneminder/events
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/lib/zoneminder/images
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/lib/zoneminder/sock
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/lib/zoneminder/swap
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/lib/zoneminder/temp
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/log/zoneminder
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/spool/zoneminder-upload
-%dir %attr(755,%{zmuid_final},%{zmgid_final}) /run/zoneminder
-
-
-%changelog
-* Sat Feb 14 2015 Andrew Bauer - 1.28.1
-- Bump version for 1.28.1 release on Fedora 21.
-
-* Sun Oct 5 2014 Andrew Bauer - 1.28.0
-- Bump version for 1.28.0 release.
-
-* Fri Mar 14 2014 Andrew Bauer - 1.27
-- Tweak build requirements for cmake
-
-* Sat Feb 01 2014 Andrew Bauer - 1.27
-- Add zmcamtool.pl. Bump version for 1.27 release.
-
-* Mon Dec 16 2013 Andrew Bauer - 1.26.5
-- This is a bug fixe release
-- RTSP fixes, cmake enhancements, couple other misc fixes
-
-* Mon Oct 07 2013 Andrew Bauer - 1.26.4
-- Initial cmake build.
-
-* Sat Oct 05 2013 Andrew Bauer - 1.26.4
-- Fedora specific path changes have been moved to zoneminder-1.26.0-defaults.patch
-- All files are now part of the zoneminder source tree. Update specfile accordingly.
-
-* Sat Sep 21 2013 Andrew Bauer - 1.26.3
-- Initial rebuild for ZoneMinder 1.26.3 release.
-
-* Fri Feb 15 2013 Fedora Release Engineering - 1.25.0-13
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
-
-* Mon Jan 21 2013 Adam Tkac - 1.25.0-12
-- rebuild due to "jpeg8-ABI" feature drop
-
-* Mon Jan 7 2013 Remi Collet - 1.25.0-11
-- fix configuration file for httpd 2.4, #871502
-
-* Fri Dec 21 2012 Adam Tkac - 1.25.0-10
-- rebuild against new libjpeg
-
-* Thu Aug 09 2012 Jason L Tibbitts III - 1.25.0-9
-- Add patch to work around v4l2 api breakage in 3.5 kernel.
-
-* Sun Jul 22 2012 Fedora Release Engineering - 1.25.0-8
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
-
-* Sat Jun 23 2012 Petr Pisar - 1.25.0-7
-- Perl 5.16 rebuild
-
-* Wed Mar 21 2012 Jason L Tibbitts III - 1.25.0-6
-- Fix stupid thinko in sql modifications.
-
-* Sat Feb 25 2012 Jason L Tibbitts III - 1.25.0-5
-- Clean up macro usage.
-
-* Sat Feb 25 2012 Jason L Tibbitts III - 1.25.0-4
-- Convert to systemd.
-- Add tmpfiles.d configuration since the initscript isn't around to create
- /run/zoneminder.
-- Remove some pointless executable permissions.
-- Add logrotate file.
-
-* Wed Feb 22 2012 Jason L Tibbitts III - 1.25.0-3
-- Update README.Fedora to reference systemctl and mention timezone info in
- php.ini.
-- Add proper default for EYEZM_LOG_TO_FILE.
-
-
-* Thu Feb 09 2012 Jason L Tibbitts III - 1.25.0-2
-- Rebuild for new pcre.
-
-* Thu Jan 19 2012 Jason L Tibbitts III - 1.25.0-1
-- Update to 1.25.0
-- Fix gcc4.7 build problems.
-- Drop gcc4.4 build fixes; for whatever reason they now break the build.
-- Clean up old patches.
-- Force setting of ZM_TMPDIR and ZM_RUNDIR.
-
-* Sat Jan 14 2012 Fedora Release Engineering - 1.24.4-4
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
-
-* Thu Sep 15 2011 Jason L Tibbitts III - 1.24.4-3
-- Re-add the dist-tag that somehow got lost.
-
-* Thu Sep 15 2011 Jason L Tibbitts III - 1.24.4-2
-- Add patch for bug 711780 - fix syntax issue in Mapped.pm.
-- Undo that patch, and undo another which was the cause of the whole mess.
-- Fix up other patches so ZM_PATH_BUILD is both defined and useful.
-- Make sure database creation mods actually take.
-- Update Fedora-specific docs with some additional info.
-- Use bundled mootools (javascript, so no guideline violation).
-- Update download location.
-- Update the gcrypt patch to actually work.
-- Upstream changed the tarball without changing the version to patch a
- vulnerability, so redownload.
-
-* Sun Aug 14 2011 Jason L Tibbitts III - 1.24.4-1
-- Initial attempt to upgrade to 1.24.4.
-- Add patch from BZ 460310 to build against libgcrypt instead of requiring the
- gnutls openssl libs.
-
-* Thu Jul 21 2011 Petr Sabata - 1.24.3-7.20110324svn3310
-- Perl mass rebuild
-
-* Wed Jul 20 2011 Petr Sabata - 1.24.3-6.20110324svn3310
-- Perl mass rebuild
-
-* Mon May 09 2011 Jason L Tibbitts III - 1.24.3-5.20110324svn3310
-- Bump for gnutls update.
-
-* Thu Mar 24 2011 Jason L Tibbitts III - 1.24.3-4.20110324svn3310
-- Update to latest 1.24.3 subversion. Turns out that what upstream was calling
- 1.24.3 is really just an occasionally updated devel snapshot.
-- Rebase various patches.
-
-* Wed Mar 23 2011 Dan Horák - 1.24.3-3
-- rebuilt for mysql 5.5.10 (soname bump in libmysqlclient)
-
-* Tue Feb 08 2011 Fedora Release Engineering - 1.24.3-2
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
-
-* Tue Jan 25 2011 Jason L Tibbitts III - 1.24.3-1
-- Update to latest upstream version.
-- Rebase patches.
-- Initial incomplete attempt to disable v4l1 support.
-
-* Fri Jan 21 2011 Jason L Tibbitts III - 1.24.2-6
-- Unbundle cambozola; instead link to the separately pacakged copy.
-- Remove BuildRoot:, %%clean and buildroot cleaning in %%install.
-- Git rid of mixed space/tab usage by removing all tabs.
-- Remove unnecessary Conflicts: line.
-- Attempt to force short_open_tag on for the code directories.
-- Move default location of sockets, swaps, logfiles and some temporary files to
- make more sense and allow things to work better with a future selinux policy.
-- Fix errors in README.Fedora.
-
-* Wed Jun 02 2010 Marcela Maslanova - 1.24.2-5
-- Mass rebuild with perl-5.12.0
-
-* Fri Dec 4 2009 Stepan Kasal - 1.24.2-4
-- rebuild against perl 5.10.1
-- use Perl vendorarch and archlib variables correctly
-
-* Mon Jul 27 2009 Fedora Release Engineering - 1.24.2-3
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
-
-* Wed Jul 22 2009 Jason L Tibbitts III - 1.24.2-2
-- Bump release since 1.24.2-1 was mistakenly tagged a few months ago.
-
-* Wed Jul 22 2009 Jason L Tibbitts III - 1.24.2-1
-- Initial update to 1.24.2.
-- Rebase patches.
-- Update mootools download location.
-- Update to mootools 1.2.3.
-- Add additional dependencies for some optional features.
-
-* Sat Apr 11 2009 Martin Ebourne - 1.24.1-3
-- Remove unused Sys::Mmap perl dependency RPM is finding
-
-* Sat Apr 11 2009 Martin Ebourne - 1.24.1-2
-- Update gcc44 patch to disable -frepo, seems to be broken with gcc44
-- Added noffmpeg patch to make building outside mock easier
-
-* Sat Mar 21 2009 Martin Ebourne - 1.24.1-1
-- Patch for gcc 4.4 compilation errors
-- Upgrade to 1.24.1
-
-* Wed Feb 25 2009 Fedora Release Engineering - 1.23.3-4
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
-
-* Sat Jan 24 2009 Caolán McNamara - 1.23.3-3
-- rebuild for dependencies
-
-* Mon Dec 15 2008 Martin Ebourne - 1.23.3-2
-- Fix permissions on zm.conf
-
-* Fri Jul 11 2008 Jason L Tibbitts III - 1.23.3-1
-- Initial attempt at packaging 1.23.
-
-* Tue Jul 1 2008 Martin Ebourne - 1.22.3-15
-- Add perl module compat dependency, bz #453590
-
-* Tue May 6 2008 Martin Ebourne - 1.22.3-14
-- Remove default runlevel, bz #441315
-
-* Mon Apr 28 2008 Jason L Tibbitts III - 1.22.3-13
-- Backport patch for CVE-2008-1381 from 1.23.3 to 1.22.3.
-
-* Tue Feb 19 2008 Fedora Release Engineering - 1.22.3-12
-- Autorebuild for GCC 4.3
-
-* Thu Jan 3 2008 Martin Ebourne - 1.22.3-11
-- Fix compilation on gcc 4.3
-
-* Thu Dec 6 2007 Martin Ebourne - 1.22.3-10
-- Rebuild for new openssl
-
-* Thu Aug 2 2007 Martin Ebourne - 1.22.3-8
-- Fix licence tag
-
-* Thu Jul 12 2007 Martin Ebourne - 1.22.3-7
-- Fixes from testing by Jitz including missing dependencies and database creation
-
-* Sat Jun 30 2007 Martin Ebourne - 1.22.3-6
-- Disable crashtrace on ppc
-
-* Sat Jun 30 2007 Martin Ebourne - 1.22.3-5
-- Fix uid for directories in /var/lib/zoneminder
-
-* Tue Jun 26 2007 Martin Ebourne - 1.22.3-4
-- Added perl Archive::Tar dependency
-- Disabled web interface due to lack of access control on the event images
-
-* Sun Jun 10 2007 Martin Ebourne - 1.22.3-3
-- Changes recommended in review by Jason Tibbitts
-
-* Mon Apr 2 2007 Martin Ebourne - 1.22.3-2
-- Standardised on package name of zoneminder
-
-* Thu Dec 28 2006 Martin Ebourne - 1.22.3-1
-- First version. Uses some parts from zm-1.20.1 by Corey DeLasaux and Serg Oskin
diff --git a/distros/fedora/zoneminder.f23.spec b/distros/fedora/zoneminder.f23.spec
index 14b653117..435a3ba58 100644
--- a/distros/fedora/zoneminder.f23.spec
+++ b/distros/fedora/zoneminder.f23.spec
@@ -10,7 +10,7 @@
%define _without_x10 1
Name: zoneminder
-Version: 1.29.0
+Version: 1.30.0
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@@ -38,7 +38,7 @@ BuildRequires: gcc gcc-c++ vlc-devel libcurl-devel libv4l-devel
BuildRequires: httpd polkit-devel
%{!?_without_ffmpeg:BuildRequires: ffmpeg}
-Requires: httpd php php-gd php-mysql cambozola polkit net-tools psmisc mod_ssl
+Requires: httpd php php-gd php-mysql cambozola polkit net-tools psmisc
Requires: libjpeg-turbo vlc-core libcurl
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip)
@@ -72,6 +72,7 @@ too much degradation of performance.
./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes
./utils/zmeditconfigdata.sh ZM_CHECK_FOR_UPDATES no
./utils/zmeditconfigdata.sh ZM_DYN_SHOW_DONATE_REMINDER no
+./utils/zmeditconfigdata.sh ZM_OPT_FAST_DELETE no
%build
%cmake \
@@ -87,6 +88,10 @@ export DESTDIR=%{buildroot}
make install
%post
+
+# Add any new PTZ control configurations to the database (will not overwrite)
+%{_bindir}/zmcamtool.pl --import >/dev/null 2>&1 || :
+
if [ $1 -eq 1 ] ; then
# Initial installation
/bin/systemctl daemon-reload >/dev/null 2>&1 || :
@@ -98,8 +103,12 @@ fi
# Upgrade from a previous version of zoneminder
if [ $1 -eq 2 ] ; then
+
+ # Add any new PTZ control configurations to the database (will not overwrite)
+ %{_bindir}/zmcamtool.pl --import >/dev/null 2>&1 || :
+
# Freshen the database
- /usr/bin/zmupdate.pl -f
+ %{_bindir}/zmupdate.pl -f >/dev/null 2>&1 || :
# We can't run this automatically when new sql account permissions need to
# be manually added first
@@ -163,9 +172,14 @@ fi
%{_bindir}/zmwatch.pl
%{_bindir}/zmcamtool.pl
%{_bindir}/zmsystemctl.pl
+%{_bindir}/zmtelemetry.pl
%{!?_without_x10:%{_bindir}/zmx10.pl}
+%{_bindir}/zmonvif-probe.pl
%{perl_vendorlib}/ZoneMinder*
+%{perl_vendorlib}/ONVIF*
+%{perl_vendorlib}/WSDiscovery*
+%{perl_vendorlib}/WSSecurity*
%{_mandir}/man*/*
%dir %{_libexecdir}/zoneminder
%{_libexecdir}/zoneminder/cgi-bin
@@ -188,6 +202,9 @@ fi
%changelog
+* Thu Mar 3 2016 Andrew Bauer - 1.30.0
+- Bump version fo 1.30.0 release.
+
* Sat Nov 21 2015 Andrew Bauer - 1.29.0
- Bump version for 1.29.0 release on Fedora 23.
diff --git a/distros/opensuse/CMakeLists.txt b/distros/opensuse/CMakeLists.txt
index d468c7287..10654f26d 100644
--- a/distros/opensuse/CMakeLists.txt
+++ b/distros/opensuse/CMakeLists.txt
@@ -38,7 +38,7 @@ install(CODE "execute_process(COMMAND ln -sf ../../../../${zm_webdir}/temp \"\$E
# Opensuse cambazola? requires cambozola as a separate package so just link to it
#install(CODE "execute_process(COMMAND ln -sf ../../java/cambozola.jar \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/cambozola.jar\")")
-# Install auxillary files required to run zoneminder on OpenSuse
+# Install auxiliary files required to run zoneminder on OpenSuse
install(FILES zoneminder.conf DESTINATION /etc/apache2/conf.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES zoneminder.logrotate DESTINATION /etc/logrotate.d RENAME zoneminder PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES zoneminder.tmpfiles DESTINATION /etc/tmpfiles.d RENAME zoneminder.conf PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/distros/opensuse/README.OpenSuse b/distros/opensuse/README.OpenSuse
index 823ccd442..27103d960 100644
--- a/distros/opensuse/README.OpenSuse
+++ b/distros/opensuse/README.OpenSuse
@@ -138,7 +138,7 @@ Upgrades
has select, insert, update, and delete permission.
3. You will need to upgrade the ZoneMinder database as described in the
- manual. Only if the previous step was succesful, may you run zmupdate like
+ manual. Only if the previous step was successful, may you run zmupdate like
so (as root):
/opt/zoneminder/bin/zmupdate.pl
diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt
index 74aa5641f..5de834109 100644
--- a/distros/redhat/CMakeLists.txt
+++ b/distros/redhat/CMakeLists.txt
@@ -16,7 +16,7 @@ else(ZM_TARGET_DISTRO STREQUAL "el7")
endif(ZM_TARGET_DISTRO STREQUAL "el7")
# Download jscalendar & move files into position
-file(DOWNLOAD http://skylineservers.dl.sourceforge.net/project/jscalendar/jscalendar/1.0/jscalendar-1.0.zip ${CMAKE_CURRENT_SOURCE_DIR}/jscalendar-1.0.zip LOG jsc_log STATUS download_jsc)
+file(DOWNLOAD http://iweb.dl.sourceforge.net/project/jscalendar/jscalendar/1.0/jscalendar-1.0.zip ${CMAKE_CURRENT_SOURCE_DIR}/jscalendar-1.0.zip LOG jsc_log STATUS download_jsc)
#message(STATUS "Log of jscalender script was: ${jsc_log}")
if(download_jsc EQUAL 0)
message(STATUS "Jscalander successfully downloaded. Installing...")
@@ -57,7 +57,7 @@ install(CODE "execute_process(COMMAND ln -sf ../../../../../../var/lib/zoneminde
# Link to Cambozola, which is now packaged in zmrepo
install(CODE "execute_process(COMMAND ln -sf ../../java/cambozola.jar \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/cambozola.jar\")")
-# Install auxillary files required to run zoneminder on CentOS
+# Install auxiliary files required to run zoneminder on CentOS
install(FILES redalert.wav DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/sounds PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
if(ZM_TARGET_DISTRO STREQUAL "el7")
install(FILES zoneminder.el7.conf DESTINATION /etc/httpd/conf.d RENAME zoneminder.conf PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
diff --git a/distros/redhat/README.CentOS b/distros/redhat/README.CentOS
index f0e627c90..35718a691 100644
--- a/distros/redhat/README.CentOS
+++ b/distros/redhat/README.CentOS
@@ -5,16 +5,14 @@ What's New
ALL permission to the ZoneMinder mysql account. This change must be done
manually before ZoneMinder will run. See the installation steps below.
-2. A new permission group called "Groups" has been added. This allows the
- system administrator to assign "view", "edit", or "none" permission to
- normal users, without giving them access to the rest of the ZoneMinder
- system. During an upgrade, existing accounts will default to a Groups
- permission of "none".
-
-3. This package now requires the HTTPS protocol to access the web portal.
+2. This package uses the HTTPS protocol by default to access the web portal.
Requests using HTTP will auto-redirect to HTTPS. See README.https for
more information.
+3. The php package that ships with CentOS 6 does not support the new ZoneMinder
+ API. If you require API functionality (such as using a mobile app) then you
+ should consider an upgrade to CentOS 7 or use Fedora.
+
New installs
============
@@ -40,7 +38,7 @@ New installs
3. If you have chosen to change the zoneminder mysql credentials to something
other than zmuser/zmpass then you must now edit /etc/zm.conf. Change
- ZM_DB_USER and ZM_DB_PASS to the values you created in step 2.
+ ZM_DB_USER and ZM_DB_PASS to the values you created in the previous step.
Additionally, you must also edit
/usr/share/zoneminder/www/api/app/Config/database.php in a similar manner.
@@ -55,11 +53,15 @@ New installs
If you are not sure of the proper timezone specification to use, look at
http://php.net/date.timezone
-5. Verify the default ZoneMinder Apache configuration meets your needs:
+5. Install mod_ssl or configure /etc/httpd/conf.d/zoneminder.conf to meet your
+ needs. This package comes preconfigured for HTTPS using the default self
+ signed certificate on your system. The recommended way to complete this step
+ is to simply install mod_ssl:
- /etc/httpd/conf.d/zoneminder.conf
+ sudo yum install mod_ssl
- When in doubt, leave this configuration as it is.
+ If this does not meet your needs, then read README.https to
+ learn about alternatives. When in doubt, install mod_ssl.
6. Configure the web server to start automatically:
@@ -122,6 +124,7 @@ New installs
/etc/httpd/conf.d. You will have a file called "zoneminder.conf" and there
may also be a file called "zoneminder.conf.rpmnew". If the rpmnew file
exists, inspect it and merge anything new in that file with zoneminder.conf.
+ Verify the SSL REquirements meet your needs. Read README.https if necessary.
4. Upgrade the database before starting ZoneMinder.
diff --git a/distros/redhat/README.Centos7 b/distros/redhat/README.Centos7
index f4566b01c..de0bd52d6 100644
--- a/distros/redhat/README.Centos7
+++ b/distros/redhat/README.Centos7
@@ -1,17 +1,19 @@
What's New
==========
-1. Due to the active state of the ZoneMinder project, we now recommend granting
+1. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
+ "/cgi-bin-zm/zms". This has been to done to avoid this bug:
+ https://bugzilla.redhat.com/show_bug.cgi?id=973067
+
+ IMPORTANT: You must manually verify the value of PATH_ZMS under Options.
+ Make sure it is set to "/cgi-bin-zm/nph-zms". Failure to do so will result
+ in a broken system. You have been warned.
+
+2. Due to the active state of the ZoneMinder project, we now recommend granting
ALL permission to the ZoneMinder mysql account. This change must be done
manually before ZoneMinder will run. See the installation steps below.
-2. A new permission group called "Groups" has been added. This allows the
- system administrator to assign "view", "edit", or "none" permission to
- normal users, without giving them access to the rest of the ZoneMinder
- system. During an upgrade, existing accounts will default to a Groups
- permission of "none".
-
-3. This package now requires the HTTPS protocol to access the web portal.
+3. This package uses the HTTPS protocol by default to access the web portal.
Requests using HTTP will auto-redirect to HTTPS. See README.https for
more information.
@@ -74,12 +76,22 @@ New installs
SELINUX line from "enforcing" to "disabled". This change will take
effect after a reboot.
-6. Now start the web server:
+6. Install mod_ssl or configure /etc/httpd/conf.d/zoneminder.conf to meet your
+ needs. This package comes preconfigured for HTTPS using the default self
+ signed certificate on your system. The recommended way to complete this step
+ is to simply install mod_ssl:
+
+ sudo yum install mod_ssl
+
+ If this does not meet your needs, then read README.https to
+ learn about alternatives. When in doubt, install mod_ssl.
+
+7. Now start the web server:
sudo systemctl enable httpd
sudo systemctl start httpd
-7. Now start zoneminder:
+8. Now start zoneminder:
sudo systemctl enable zoneminder
sudo systemctl start zoneminder
@@ -118,6 +130,7 @@ Upgrades
/etc/httpd/conf.d. You will have a file called "zoneminder.conf" and there
may also be a file called "zoneminder.conf.rpmnew". If the rpmnew file
exists, inspect it and merge anything new in that file with zoneminder.conf.
+ Verify the SSL REquirements meet your needs. Read README.https if necessary.
4. Upgrade the database before starting ZoneMinder.
diff --git a/distros/redhat/zoneminder.el6.spec b/distros/redhat/zoneminder.el6.spec
index 82406d431..69e3b972f 100644
--- a/distros/redhat/zoneminder.el6.spec
+++ b/distros/redhat/zoneminder.el6.spec
@@ -4,7 +4,7 @@
%define zmgid_final apache
Name: zoneminder
-Version: 1.29.0
+Version: 1.30.0
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@@ -30,7 +30,7 @@ BuildRequires: libcurl-devel vlc-devel ffmpeg-devel polkit-devel
# cmake needs the following installed at build time due to the way it auto-detects certain parameters
BuildRequires: httpd ffmpeg
-Requires: httpd php php-gd php-mysql mysql-server libjpeg-turbo cambozola polkit net-tools mod_ssl
+Requires: httpd php php-gd php-mysql mysql-server libjpeg-turbo cambozola polkit net-tools
Requires: psmisc perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip)
Requires: perl(MIME::Entity) perl(MIME::Lite) perl(Net::SMTP) perl(Net::FTP)
@@ -69,6 +69,7 @@ too much degradation of performance.
./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes
./utils/zmeditconfigdata.sh ZM_CHECK_FOR_UPDATES no
./utils/zmeditconfigdata.sh ZM_DYN_SHOW_DONATE_REMINDER no
+./utils/zmeditconfigdata.sh ZM_OPT_FAST_DELETE no
%build
# Have to override CMAKE_INSTALL_LIBDIR for cmake < 2.8.7 due to this bug:
@@ -98,8 +99,12 @@ echo -e "\nCreating and installing a ZoneMinder SELinux policy module. Please wa
# Upgrade from a previous version of zoneminder
if [ $1 -eq 2 ] ; then
+
+ # Add any new PTZ control configurations to the database (will not overwrite)
+ %{_bindir}/zmcamtool.pl --import >/dev/null 2>&1 || :
+
# Freshen the database
- /usr/bin/zmupdate.pl -f
+ %{_bindir}/zmupdate.pl -f >/dev/null 2>&1 || :
# We can't run this automatically when new sql account permissions need to
# be manually added first
@@ -154,14 +159,16 @@ rm -rf %{_docdir}/%{name}-%{version}
%{_bindir}/zmwatch.pl
%{_bindir}/zmcamtool.pl
%{_bindir}/zmsystemctl.pl
+%{_bindir}/zmtelemetry.pl
%{_bindir}/zmx10.pl
-#%{_bindir}/zmonvif-probe.pl
+%{_bindir}/zmonvif-probe.pl
%{perl_vendorlib}/ZoneMinder*
%{perl_vendorarch}/auto/ZoneMinder/.packlist
-#%{perl_vendorlib}/ONVIF*
-#%{perl_vendorlib}/WSDiscovery*
-#%{perl_vendorlib}/WSSecurity*
+%{perl_vendorarch}/auto/ONVIF/.packlist
+%{perl_vendorlib}/ONVIF*
+%{perl_vendorlib}/WSDiscovery*
+%{perl_vendorlib}/WSSecurity*
%{_mandir}/man*/*
%dir %{_libexecdir}/%{name}
%{_libexecdir}/%{name}/cgi-bin
@@ -182,6 +189,9 @@ rm -rf %{_docdir}/%{name}-%{version}
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/spool/zoneminder-upload
%changelog
+* Thu Mar 3 2016 Andrew Bauer - 1.30.0
+- Bump version fo 1.30.0 release.
+
* Tue Sep 8 2015 Andrew Bauer - 1.28.1
- Require https, freshen dB on updates.
diff --git a/distros/redhat/zoneminder.el7.spec b/distros/redhat/zoneminder.el7.spec
index c350553b3..485c214c2 100644
--- a/distros/redhat/zoneminder.el7.spec
+++ b/distros/redhat/zoneminder.el7.spec
@@ -6,7 +6,7 @@
%global _hardened_build 1
Name: zoneminder
-Version: 1.29.0
+Version: 1.30.0
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@@ -32,7 +32,7 @@ BuildRequires: ffmpeg ffmpeg-devel perl(X10::ActiveHome) perl(Astro::SunTime)
# cmake needs the following installed at build time due to the way it auto-detects certain parameters
BuildRequires: httpd polkit-devel
-Requires: httpd php php-gd php-mysql mariadb-server cambozola polkit net-tools mod_ssl
+Requires: httpd php php-gd php-mysql mariadb-server cambozola polkit net-tools
Requires: psmisc libjpeg-turbo vlc-core libcurl
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip)
@@ -65,6 +65,7 @@ too much degradation of performance.
./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes
./utils/zmeditconfigdata.sh ZM_CHECK_FOR_UPDATES no
./utils/zmeditconfigdata.sh ZM_DYN_SHOW_DONATE_REMINDER no
+./utils/zmeditconfigdata.sh ZM_OPT_FAST_DELETE no
%build
%cmake \
@@ -96,8 +97,12 @@ fi
# Upgrade from a previous version of zoneminder
if [ $1 -eq 2 ] ; then
+
+ # Add any new PTZ control configurations to the database (will not overwrite)
+ %{_bindir}/zmcamtool.pl --import >/dev/null 2>&1 || :
+
# Freshen the database
- /usr/bin/zmupdate.pl -f
+ %{_bindir}/zmupdate.pl -f >/dev/null 2>&1 || :
# We can't run this automatically when new sql account permissions need to
# be manually added first
@@ -163,12 +168,16 @@ fi
%{_bindir}/zmwatch.pl
%{_bindir}/zmcamtool.pl
%{_bindir}/zmsystemctl.pl
+%{_bindir}/zmtelemetry.pl
%{_bindir}/zmx10.pl
+%{_bindir}/zmonvif-probe.pl
%{perl_vendorlib}/ZoneMinder*
%{perl_vendorarch}/auto/ZoneMinder/.packlist
-#%{perl_vendorlib}/%{_arch}-linux-thread-multi/auto/ZoneMinder*
-#%{perl_archlib}/ZoneMinder*
+%{perl_vendorarch}/auto/ONVIF/.packlist
+%{perl_vendorlib}/ONVIF*
+%{perl_vendorlib}/WSDiscovery*
+%{perl_vendorlib}/WSSecurity*
%{_mandir}/man*/*
%dir %{_libexecdir}/zoneminder
%{_libexecdir}/zoneminder/cgi-bin
@@ -191,6 +200,9 @@ fi
%changelog
+* Thu Mar 3 2016 Andrew Bauer - 1.30.0
+- Bump version fo 1.30.0 release.
+
* Mon Sep 7 2015 Andrew Bauer - 1.28.1
- Require https, disable selinux module, freshen dB on updates.
diff --git a/distros/ubuntu1204_cmake/changelog b/distros/ubuntu1204_cmake/changelog
index 124ba61d2..74cf1d0b8 100644
--- a/distros/ubuntu1204_cmake/changelog
+++ b/distros/ubuntu1204_cmake/changelog
@@ -525,7 +525,7 @@ zoneminder (1.22.3-7) unstable; urgency=low
zoneminder (1.22.3-6) unstable; urgency=low
- * Removed a similar bash only statment from zmpkg.pl
+ * Removed a similar bash only statement from zmpkg.pl
(closes:414882)
-- Peter Howard Sat, 14 Apr 2007 11:46:56 +1000
diff --git a/distros/ubuntu1204_cmake/control b/distros/ubuntu1204_cmake/control
index 4b4877562..fd7a53049 100644
--- a/distros/ubuntu1204_cmake/control
+++ b/distros/ubuntu1204_cmake/control
@@ -51,7 +51,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libwww-perl
,mysql-client | virtual-mysql-client
,perl-modules
- ,php5-mysql
+ ,php5-mysql, php5-gd
,policykit-1
,rsyslog | system-log-daemon
,zip
diff --git a/distros/ubuntu1504_cmake/changelog b/distros/ubuntu1504_cmake/changelog
index 124ba61d2..74cf1d0b8 100644
--- a/distros/ubuntu1504_cmake/changelog
+++ b/distros/ubuntu1504_cmake/changelog
@@ -525,7 +525,7 @@ zoneminder (1.22.3-7) unstable; urgency=low
zoneminder (1.22.3-6) unstable; urgency=low
- * Removed a similar bash only statment from zmpkg.pl
+ * Removed a similar bash only statement from zmpkg.pl
(closes:414882)
-- Peter Howard Sat, 14 Apr 2007 11:46:56 +1000
diff --git a/docs/faq.rst b/docs/faq.rst
index 6c0bc227c..5aa736ee8 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -238,7 +238,7 @@ The second approach is to use diagnostic images which are saved copies of the in
There are two kinds of diagnostic images which are and are written (and continuously overwritten) to the top level monitor event directory. If an event occurs then the files are additionally copied to the event directory and renamed with the appropriate frame number as a prefix.
-The first set are produced by the monitor on the image as a whole. The diag-r.jpg image is the current reference image against which all individual frames are compared and the diag-d.jpg image is the delta image highlighting the difference between the reference image and the last analysed image. In this images identicial pixels will be black and the more different a pixel is the whiter it will be. Viewing this image and determining the colour of the pixels is a good way of getting a feel for the pixel differences you might expect (often more than you think).
+The first set are produced by the monitor on the image as a whole. The diag-r.jpg image is the current reference image against which all individual frames are compared and the diag-d.jpg image is the delta image highlighting the difference between the reference image and the last analysed image. In this images identical pixels will be black and the more different a pixel is the whiter it will be. Viewing this image and determining the colour of the pixels is a good way of getting a feel for the pixel differences you might expect (often more than you think).
The second set of diag images are labelled as diag--.jpg where zoneid is the id of the zone in question (Smile) and the stage is where in the alarm check process the image is generated from. So if you have several zones you can expect to see multiple files. Also these files are only interested in what is happening in their zone only and will ignore anything else outside of the zone. The stages that each number represents are as follows,
@@ -617,14 +617,14 @@ How can I trouble shoot the hardware and/or software?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here are some commands to get information about your hardware. Some commands are distribution dependent.
-* ``[[lspci]] -vv`` -- Returns lots of detailed info. Check for conflicting interrupts or port assignments. You can sometimes alter interrupts/ ports in bios. Try a different pci slot to get a clue if it is HW conflict (comand provided by the pciutils package).
+* ``[[lspci]] -vv`` -- Returns lots of detailed info. Check for conflicting interrupts or port assignments. You can sometimes alter interrupts/ ports in bios. Try a different pci slot to get a clue if it is HW conflict (command provided by the pciutils package).
* ``[[scanpci]] -v`` -- Gives you information from your hardware EPROM
* ``[[lsusb]] -vv`` -- Returns lots of detail about USB devices (camand provided by usbutils package).
* ``[[dmesg]]`` -- Shows you how your hardware initialized (or didn't) on boot-up. You will get the most use of this.
* ``[[v4l-info]]`` -- to see how driver is talking to card. look for unusual values.
* ``[[modinfo bttv]]`` -- some bttv driver stats.
* ``[[zmu]] -m 0 -q -v`` -- Returns various information regarding a monitor configuration.
-* ``[[ipcs]] `` -- Provides information on the ipc facilities for which the calling process has read acccess.
+* ``[[ipcs]] `` -- Provides information on the ipc facilities for which the calling process has read access.
* ``[[ipcrm]] `` -- The ipcrm command can be used to remove an IPC object from the kernel.
* ``cat /proc/interrupts`` -- This will dispaly what interrupts your hardware is using.
diff --git a/docs/index.rst b/docs/index.rst
index 46713b754..46da979cf 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,7 +13,7 @@ ZoneMinder Documentation
Welcome to ZoneMinder's documentation, the following resources are available
:doc:`installationguide/index`
- Many distrubution repos only hold older versions of ZoneMinder, current versions contain many bug fixes and updated functionality. Instructions here for installing updated packages or compiling from source.
+ Many distribution repos only hold older versions of ZoneMinder, current versions contain many bug fixes and updated functionality. Instructions here for installing updated packages or compiling from source.
:doc:`userguide/index`
Guide to setting up ZoneMinder for the first time and detailed guides for using the ZoneMinder front end.
diff --git a/docs/installationguide/ubuntu.rst b/docs/installationguide/ubuntu.rst
index 1d5412077..bad2b651d 100644
--- a/docs/installationguide/ubuntu.rst
+++ b/docs/installationguide/ubuntu.rst
@@ -1,5 +1,5 @@
-Ubuntu
-======
+Ubuntu Instruction
+===================
.. contents::
@@ -286,192 +286,106 @@ 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
+**Step 1:** Grab the package installer script
+
+::
+
+ wget https://raw.githubusercontent.com/ZoneMinder/ZoneMinder/master/utils/do_debian_package.sh
+ chmod a+x do_debian_package.sh
+
+
+**Step 2:** Update the system
::
sudo apt-get update
- sudo apt-get install cmake git
-**Step 2:** Next up make sure you have all the dependencies
+
+**Step 3** Create the package
+
+To build the latest master snapshot:
::
- 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
+ ./do_debian_package.sh `lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'` `date +%Y%m%d`01 local master
-(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:
+To build the latest stable release:
::
- git clone https://github.com/ZoneMinder/ZoneMinder.git
- cd ZoneMinder/
- git submodule init
- git submodule update
- cmake .
- make
- sudo make install
+ ./do_debian_package.sh `lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'` `date +%Y%m%d`01 local stable
-**Step 4:** Now make sure your symlinks to events and images are set correctly:
+
+Note that the ``lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`` part simply extracts your distribution name - like "vivid", "trusty" etc. You can always replace it by your distro name if you know it. As far as the script goes, it checks if your distro is "trusty" in which case it pulls in pre-systemd release configurations and if its not "trusty" it assumes its based on systemd and pulls in systemd related config files.
+
+(At the end the script will ask if you want to retain the checked out version of zoneminder. If you are a developer and are making local changes, make sure you select "y" so that the next time you do the build process mentioned here, it keeps your changes. Selecting any other value than "y" or "Y" will delete the checked out code and only retain the package)
+
+This should now create a bunch of .deb files
+
+**Step 4:** Install the package
::
- sudo ./zmlinkcontent.sh
+ sudo gdebi zoneminder__.deb
+ (example sudo gdebi zoneminder_1.29.0-vivid-2016012001_amd64.deb)
-**Step 5:** Now lets make sure ZM has DB permissions to write to the DB:
+
+**This will report DB errors - ignore - you need to configure the DB and some other stuff**
+
+**Step 5:** Post install configuration
::
+ 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 6:** Now lets create the DB & its tables that ZM needs
-
-::
-
- mysql -uroot -p
- Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
- AllowOverride All
- Require all granted
-
+ sudo chown www-data /etc/zm/zm.conf
+ sudo chown -R www-data /usr/share/zoneminder/www/api/
- 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:
+**Step 8:** Restart all services
::
- sudo chown -R www-data:www-data /usr/local/share/zoneminder/
+ sudo service apache2 restart
+ sudo service zoneminder restart
-
-**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:
+Check if ZM is running properly
::
- 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:
-
-``vi /etc/mysql/my.cnf``
-Under [mysqld] add
-``innodb_file_per_table``
-
-Save and exit.
-
-Restart MySQL
-``service mysql restart``
+ sudo service zoneminder status
+
+
+**Step 9:** Make sure streaming works - set PATH_ZMS
+
+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 10:** Make sure everything works
+
+* point your browser to http://yourzmip/zm - you should see ZM console running
+* point your browser to http://yourzmip/zm/api/host/getVersion.json - you should see an API version
+* Configure your monitors and make sure its all a-ok
diff --git a/docs/userguide/definezone.rst b/docs/userguide/definezone.rst
index d3eaeb8c6..0cacd3b91 100644
--- a/docs/userguide/definezone.rst
+++ b/docs/userguide/definezone.rst
@@ -35,7 +35,7 @@ Type
Suppresses the detection of motion within it. This can be layered on top of any other zone type, preventing motion within the Inactive zone from being effective for any other zone type. Use inactive zones to cover areas in which nothing notable will ever happen or where you get false alarms that don't relate to what you are trying to monitor. Inactive zones may be overlaid on other zones to blank out areas, and are processed first (with the exception of Privacy zones, see below). As a general practice, you should try and make zones abut each other instead of overlapping to avoid repeated duplicate processing of the same area.
* Privacy
- Blackens the pixels within it. This can be used if you want to hide some regions in the image if the situation does not allow an other solution. This zone type is different to all the others in that it gets processed as soon as possible during capture (even before the timestamp gets into the image) and not in the analyzing process. So if you add, change or delete a Privacy zone, you don't see the changes in the image until the capture process gets restarted. This will be done automatically, but needs a few seconds.
+ Blackens the pixels within it. This can be used if you want to hide some regions in the image if the situation does not allow another solution. This zone type is different to all the others in that it gets processed as soon as possible during capture (even before the timestamp gets into the image) and not in the analyzing process. So if you add, change or delete a Privacy zone, you don't see the changes in the image until the capture process gets restarted. This will be done automatically, but needs a few seconds.
Preset
The preset chooser sets sensible default values based on computational needs (fast v. best) and sensitivity (low, medium, high.) It is not required that you select a preset, and you can alter any of the parameters after choosing a preset. For a small number of monitors with ZoneMinder running on modern equipment, Best, high sensitivity can be chosen as a good starting point.
diff --git a/docs/userguide/filterevents.rst b/docs/userguide/filterevents.rst
index 4d7a50fd5..bc0dcffe2 100644
--- a/docs/userguide/filterevents.rst
+++ b/docs/userguide/filterevents.rst
@@ -90,7 +90,7 @@ Saving filters
.. image:: images/filter-save.png
:width: 400px
-When saving filters, if you want the filter to run in the background make sure you select the "Run filter in background" option. When checked, ZoneMinder will make sure the filter is checked regularly. For example, if you want to be notified of new events by email, you sould make sure this is checked. Filters that are configured to run in the background have a "*" next to it.
+When saving filters, if you want the filter to run in the background make sure you select the "Run filter in background" option. When checked, ZoneMinder will make sure the filter is checked regularly. For example, if you want to be notified of new events by email, you should make sure this is checked. Filters that are configured to run in the background have a "*" next to it.
For example:
diff --git a/docs/userguide/gettingstarted.rst b/docs/userguide/gettingstarted.rst
index 2bc3dcd7f..73f6e2783 100644
--- a/docs/userguide/gettingstarted.rst
+++ b/docs/userguide/gettingstarted.rst
@@ -65,9 +65,9 @@ own empty screen.
* **B**: Click here to explore the various options of ZoneMinder and how to configure them. You already used this to enable authentication and change style above. Over time, you will find this to have many other things you will want to customize.
* **C**: This link, when clicked, opens up a color coded log window of what is going on in Zoneminder and often gives you good insight into what is going wrong or right. Note that the color here is red - that is an indication that some error occurred in ZoneMinder. You should click it and investigate.
* **D**: This is the core of ZoneMinder - recording events. It gives you a count of how many events were recorded over the hour, day, week, month.
-* **E**: These are the "Zones". Zones are areas within the camera that you mark as 'hotspots' for motion detection. Simply put, when you first configure your monitors (cameras), by default Zoneminder uses the entire field of view of the camera to detect motion. You may not want this. You may want to create "zones" specifically for detecting motion and ignore others. For example, lets consider a room with a fan that spins. You surely don't want to consider the fan moving continously a reason for triggering a record? Probably not - in that case, you'd leave the fan out while making your zones.
+* **E**: These are the "Zones". Zones are areas within the camera that you mark as 'hotspots' for motion detection. Simply put, when you first configure your monitors (cameras), by default Zoneminder uses the entire field of view of the camera to detect motion. You may not want this. You may want to create "zones" specifically for detecting motion and ignore others. For example, lets consider a room with a fan that spins. You surely don't want to consider the fan moving continuously a reason for triggering a record? Probably not - in that case, you'd leave the fan out while making your zones.
* **F**: This is the "source" column that tells you the type of the camera - if its an IP camera, a USB camera or more. In this example, they are all IP cameras. Note the color red on item F ? Well that means there is something wrong with that camera. No wonder the log also shows red. Good indication for you to tap on logs and investigate
-* **G**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Modect = Don't record till an externa entity via zmtrigger tells Zoneminder to (this is advanced usage).
+* **G**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Nodect = Don't record till an externa entity via zmtrigger tells Zoneminder to (this is advanced usage).
* **H**: If you click on these links you can view a "Montage" of all your configured monitors or cycle through each one
diff --git a/docs/userguide/options/options_config.rst b/docs/userguide/options/options_config.rst
index 7918361ba..0f419e2ab 100644
--- a/docs/userguide/options/options_config.rst
+++ b/docs/userguide/options/options_config.rst
@@ -25,9 +25,9 @@ FORCED_ALARM_SCORE - The 'zmu' utility can be used to force an alarm on a monito
BULK_FRAME_INTERVAL - Traditionally ZoneMinder writes an entry into the Frames database table for each frame that is captured and saved. This works well in motion detection scenarios but when in a DVR situation ('Record' or 'Mocord' mode) this results in a huge number of frame writes and a lot of database and disk bandwidth for very little additional information. Setting this to a non-zero value will enabled ZoneMinder to group these non-alarm frames into one 'bulk' frame entry which saves a lot of bandwidth and space. The only disadvantage of this is that timing information for individual frames is lost but in constant frame rate situations this is usually not significant. This setting is ignored in Modect mode and individual frames are still written if an alarm occurs in Mocord mode also.
-EVENT_CLOSE_MODE - When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The 'time' setting means that the event will be closed at the end of the section regardless of alarm activity. The 'idle' setting means that the event will be closed at the end of the section if there is no alarm activity occuring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The 'alarm' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.
+EVENT_CLOSE_MODE - When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The 'time' setting means that the event will be closed at the end of the section regardless of alarm activity. The 'idle' setting means that the event will be closed at the end of the section if there is no alarm activity occurring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The 'alarm' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.
-CREATE_ANALYSIS_IMAGES - By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occured. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.
+CREATE_ANALYSIS_IMAGES - By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occurred. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.
WEIGHTED_ALARM_CENTRES - ZoneMinder will always calculate the centre point of an alarm in a zone to give some indication of where on the screen it is. This can be used by the experimental motion tracking feature or your own custom extensions. In the alarmed or filtered pixels mode this is a simple midpoint between the extents of the detected pxiesl. However in the blob method this can instead be calculated using weighted pixel locations to give more accurate positioning for irregularly shaped blobs. This method, while more precise is also slower and so is turned off by default.
diff --git a/docs/userguide/options/options_servers.rst b/docs/userguide/options/options_servers.rst
index 4736c305a..83e146871 100644
--- a/docs/userguide/options/options_servers.rst
+++ b/docs/userguide/options/options_servers.rst
@@ -1,5 +1,5 @@
Options - Servers
----------------
+-----------------
.. image:: images/Options_Servers.png
diff --git a/docs/userguide/options/options_system.rst b/docs/userguide/options/options_system.rst
index 83aa28bec..7df3d259a 100644
--- a/docs/userguide/options/options_system.rst
+++ b/docs/userguide/options/options_system.rst
@@ -25,9 +25,9 @@ FILTER_EXECUTE_INTERVAL - ZoneMinder allows you to save filters to the database
MAX_RESTART_DELAY - The zmdc (zm daemon control) process controls when processeses are started or stopped and will attempt to restart any that fail. If a daemon fails frequently then a delay is introduced between each restart attempt. If the daemon stills fails then this delay is increased to prevent extra load being placed on the system by continual restarts. This option controls what this maximum delay is.
-WATCH_CHECK_INTERVAL - The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines how often the daemons are checked.
+WATCH_CHECK_INTERVAL - The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinitely). This option determines how often the daemons are checked.
-WATCH_MAX_DELAY - The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines the maximum delay to allow since the last captured frame. The daemon will be restarted if it has not captured any images after this period though the actual restart may take slightly longer in conjunction with the check interval value above.
+WATCH_MAX_DELAY - The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinitely). This option determines the maximum delay to allow since the last captured frame. The daemon will be restarted if it has not captured any images after this period though the actual restart may take slightly longer in conjunction with the check interval value above.
RUN_AUDIT - The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. This option controls whether zmaudit is run in the background and performs these checks and fixes continuously. This is recommended for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to not have zmaudit running unconditionally and schedule occasional checks at other, more convenient, times.
diff --git a/docs/userguide/options/options_upload.rst b/docs/userguide/options/options_upload.rst
index 16e3f5588..da4baa076 100644
--- a/docs/userguide/options/options_upload.rst
+++ b/docs/userguide/options/options_upload.rst
@@ -19,7 +19,7 @@ UPLOAD_PORT - You can use filters to instruct ZoneMinder to upload events to a r
UPLOAD_USER - You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the username that ZoneMinder should use to log in for transfer.
-UPLOAD_PASS - You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the password that ZoneMinder should use to log in for transfer. If you are using certicate based logins for SFTP servers you can leave this option blank.
+UPLOAD_PASS - You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the password that ZoneMinder should use to log in for transfer. If you are using certificate based logins for SFTP servers you can leave this option blank.
UPLOAD_LOC_DIR - You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.
diff --git a/docs/userguide/options/options_x10.rst b/docs/userguide/options/options_x10.rst
index dc41d8dd6..0662ebe7e 100644
--- a/docs/userguide/options/options_x10.rst
+++ b/docs/userguide/options/options_x10.rst
@@ -5,7 +5,7 @@ Options - X10
OPT_X10 - If you have an X10 Home Automation setup in your home you can use ZoneMinder to initiate or react to X10 signals if your computer has the appropriate interface controller. This option indicates whether X10 options will be available in the browser client.
-X10_DEVICE - If you have an X10 controller device (e.g. XM10U) connected to your computer this option details which port it is conected on, the default of /dev/ttyS0 maps to serial or com port 1.
+X10_DEVICE - If you have an X10 controller device (e.g. XM10U) connected to your computer this option details which port it is connected on, the default of /dev/ttyS0 maps to serial or com port 1.
X10_HOUSE_CODE - X10 devices are grouped together by identifying them as all belonging to one House Code. This option details what that is. It should be a single letter between A and P.
diff --git a/docs/userguide/viewevents.rst b/docs/userguide/viewevents.rst
index 83fa3df76..70eea0032 100644
--- a/docs/userguide/viewevents.rst
+++ b/docs/userguide/viewevents.rst
@@ -20,7 +20,7 @@ Here is an example of viewing an event stream:
* **A**: Administrative Event options on the event including viewing individual frames
* **B**: The actual image stream
* **C**: Navigation control
-* **D**: You can switch between watching a single event or Continous mode (where it advances to the next event after playback is complete)
+* **D**: You can switch between watching a single event or Continuous mode (where it advances to the next event after playback is complete)
* **E**: Event progress bar - how much of the current event has been played back
You will notice for the first time that alarm images now contain an overlay outlining the blobs that represent the alarmed area. This outline is in the colour defined for that zone and lets you see what it was that caused the alarm. Clicking on one of the thumbnails will take you to a full size window where you can see the image in all its detail and scroll through the various images that make up the event. If you have the ZM_RECORD_EVENT_STATS option on, you will be able to click the 'Stats' link here and get some analysis of the cause of the event.
diff --git a/onvif/README b/onvif/README
new file mode 100644
index 000000000..25065e18a
--- /dev/null
+++ b/onvif/README
@@ -0,0 +1,102 @@
+ZoneMinder ONVIF support
+
+Copyright (C) 2016 Jan M. Hochstein
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+--------------------------------------------------------------------------
+
+1. PURPOSE
+----------
+
+The files in this folder and its subfolders add ONVIF support to zoneminder.
+The ONVIF consortium (www.onvif.org) publishes the ONVIF specifications. These
+specifications describe ways of connecting to and communicating with network
+video devices. Hardware and software that adhere to these specifications are
+meant to be interoperable.
+
+
+2. SUBFOLDERS
+-------------
+
+doc/ - Documentation
+modules/ - perl modules necessary for SOAP communication
+proxy/ - perl SOAP proxy modules generated according to the ONVIF
+ specifications
+scripts/ - application logic
+wsdl/ - (empty) this is only used during the proxy generation process
+
+
+3. LICENSE
+----------
+Any files in this folder and its subfolders are published under the same
+license as this file if they do not carry additional license information.
+
+
+4. PROXY GENERATION
+-------------------
+
+SOAP messages use XML format and need to comply to the schema expected by the
+receiver. While it is possible to build messages through string concatenation
+it is impractical for all but testing purposes.
+Here we use SOAP proxy modules generated by the script wsdl2perl.pl from the
+SOAP::WSDL module (http://search.cpan.org/~mkutter/SOAP-WSDL-2.00.10/)
+version 2.00.10.
+
+A - Get the input files.
+
+ Download these files and any web service (.wsdl) or schema (.xsd)
+ files referenced therein into the wsdl/ subfolder.
+
+ http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl
+ http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl
+ http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl
+ http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
+
+ The complete list of files we have during build is:
+
+ analytics.wsdl
+ b-2.xsd
+ bf-2.xsd
+ br-2.xsd
+ brw-2.wsdl
+ bw-2.wsdl
+ devicemgmt.wsdl
+ media.wsdl
+ onvif.xsd
+ ptz.wsdl
+ r-2.xsd
+ rw-2.wsdl
+ soap-envelop.xsd
+ t-1.xsd
+ wsdd-discovery-1.1-schema-os.xsd
+ wsdd-discovery-1.1-wsdl-os.wsdl
+ wsdiscovery-udp.wsdl
+ wsdl11soap12.xsd
+ wsdl.xsd
+ wsnotification.wsdl
+ xmlmime.xsd
+ xop-include.xsd
+
+B - Generate the proxy modules using these commands.
+
+ wsdl2perl.pl -p ONVIF::Device:: -b proxy/lib file:wsdl/devicemgmt.wsdl
+ wsdl2perl.pl -p ONVIF::Media:: -b proxy/lib file:wsdl/media.wsdl
+ wsdl2perl.pl -p ONVIF::PTZ:: -b proxy/lib file:wsdl/ptz.wsdl
+ wsdl2perl.pl -p ONVIF::Event:: -b proxy/lib file:wsdl/event.wsdl
+ wsdl2perl.pl -p ONVIF::Analytics:: -b proxy/lib file:wsdl/analytics.wsdl
+ wsdl2perl.pl -p WSDiscovery:: -b proxy/lib file:wsdl/wsdiscovery-udp.wsdl
+ wsdl2perl.pl -p WSNotification:: -b proxy/lib file:wsdl/wsnotification.wsdl
+
+ I had to tweak SOAP::WSDL a little bit to get correct proxies.
diff --git a/onvif/modules/lib/ONVIF/Client.pm b/onvif/modules/lib/ONVIF/Client.pm
index 2d16c9d13..eaf78747d 100644
--- a/onvif/modules/lib/ONVIF/Client.pm
+++ b/onvif/modules/lib/ONVIF/Client.pm
@@ -1,7 +1,7 @@
# ==========================================================================
#
# ZoneMinder ONVIF Client module
-# Copyright (C) Jan M. Hochstein
+# Copyright (C) 2014 Jan M. Hochstein
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
diff --git a/onvif/modules/lib/ONVIF/Deserializer/MessageParser.pm b/onvif/modules/lib/ONVIF/Deserializer/MessageParser.pm
index c9234ae76..b0ce6f0fd 100644
--- a/onvif/modules/lib/ONVIF/Deserializer/MessageParser.pm
+++ b/onvif/modules/lib/ONVIF/Deserializer/MessageParser.pm
@@ -1,4 +1,27 @@
-#!/usr/bin/perl
+# ==========================================================================
+#
+# ZoneMinder ONVIF Client module
+# Copyright (C) 2014 Jan M. Hochstein
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the implementation of a SOAP message parser
+#
+
package ONVIF::Deserializer::MessageParser;
use strict; use warnings;
diff --git a/onvif/modules/lib/ONVIF/Deserializer/XSD.pm b/onvif/modules/lib/ONVIF/Deserializer/XSD.pm
index 6d96aa406..b4694d90d 100644
--- a/onvif/modules/lib/ONVIF/Deserializer/XSD.pm
+++ b/onvif/modules/lib/ONVIF/Deserializer/XSD.pm
@@ -1,3 +1,27 @@
+# ==========================================================================
+#
+# ZoneMinder ONVIF Client module
+# Copyright (C) 2014 Jan M. Hochstein
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the implementation of a SOAP deserializer
+#
+
package ONVIF::Deserializer::XSD;
use strict;
use warnings;
diff --git a/onvif/modules/lib/ONVIF/Serializer/Base.pm b/onvif/modules/lib/ONVIF/Serializer/Base.pm
index b6edf360f..7bab331cf 100644
--- a/onvif/modules/lib/ONVIF/Serializer/Base.pm
+++ b/onvif/modules/lib/ONVIF/Serializer/Base.pm
@@ -1,4 +1,27 @@
-#!/usr/bin/perl -w
+# ==========================================================================
+#
+# ZoneMinder ONVIF Client module
+# Copyright (C) 2014 Jan M. Hochstein
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the base class for the SOAP serializers
+#
+
package ONVIF::Serializer::Base;
use strict;
use warnings;
diff --git a/onvif/modules/lib/ONVIF/Serializer/SOAP11.pm b/onvif/modules/lib/ONVIF/Serializer/SOAP11.pm
index 2813a0688..442a11d7a 100644
--- a/onvif/modules/lib/ONVIF/Serializer/SOAP11.pm
+++ b/onvif/modules/lib/ONVIF/Serializer/SOAP11.pm
@@ -1,4 +1,27 @@
-#!/usr/bin/perl -w
+# ==========================================================================
+#
+# ZoneMinder ONVIF Client module
+# Copyright (C) 2014 Jan M. Hochstein
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the SOAP 1.1 serializer
+#
+
package ONVIF::Serializer::SOAP11;
use strict;
use warnings;
diff --git a/onvif/modules/lib/ONVIF/Serializer/SOAP12.pm b/onvif/modules/lib/ONVIF/Serializer/SOAP12.pm
index d378a3614..2805ea40f 100644
--- a/onvif/modules/lib/ONVIF/Serializer/SOAP12.pm
+++ b/onvif/modules/lib/ONVIF/Serializer/SOAP12.pm
@@ -1,4 +1,27 @@
-#!/usr/bin/perl -w
+# ==========================================================================
+#
+# ZoneMinder ONVIF Client module
+# Copyright (C) 2014 Jan M. Hochstein
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the SOAP 1.2 serializer
+#
+
package ONVIF::Serializer::SOAP12;
use strict;
use warnings;
diff --git a/onvif/modules/lib/WSDiscovery/TransportUDP.pm b/onvif/modules/lib/WSDiscovery/TransportUDP.pm
index 9bc6c74c9..375f9628d 100644
--- a/onvif/modules/lib/WSDiscovery/TransportUDP.pm
+++ b/onvif/modules/lib/WSDiscovery/TransportUDP.pm
@@ -1,7 +1,7 @@
# ==========================================================================
#
# Perl WS-Discovery implementation
-# Copyright (C) Jan M. Hochstein
+# Copyright (C) 2014 Jan M. Hochstein
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
diff --git a/onvif/modules/lib/WSSecurity/SecuritySerializer.pm b/onvif/modules/lib/WSSecurity/SecuritySerializer.pm
index a2daac028..11a918af7 100644
--- a/onvif/modules/lib/WSSecurity/SecuritySerializer.pm
+++ b/onvif/modules/lib/WSSecurity/SecuritySerializer.pm
@@ -1,7 +1,7 @@
# ==========================================================================
#
# Perl WS-Security header for SOAP::WSDL
-# Copyright (C) Jan M. Hochstein
+# Copyright (C) 2014 Jan M. Hochstein
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -26,7 +26,7 @@ use strict;
use warnings;
use SOAP::WSDL::Factory::Serializer;
use Time::Local;
-use Digest::SHA1;
+use Digest::SHA;
use MIME::Base64;
@@ -94,7 +94,7 @@ sub ws_authen {
my $nonce = $nonce_generator->();
my $timestamp = timestamp();
- my $pwDigest = Digest::SHA1::sha1( $nonce . $timestamp . $password );
+ my $pwDigest = Digest::SHA::sha1( $nonce . $timestamp . $password );
my $passwordHash = MIME::Base64::encode_base64($pwDigest,"");
my $nonceHash = MIME::Base64::encode_base64($nonce,"");
diff --git a/onvif/scripts/CMakeLists.txt b/onvif/scripts/CMakeLists.txt
index 09775b3f2..3405fa756 100644
--- a/onvif/scripts/CMakeLists.txt
+++ b/onvif/scripts/CMakeLists.txt
@@ -1,4 +1,9 @@
# CMakeLists.txt for the ZoneMinder perl scripts.
+# If this is an out-of-source build, copy the files we need to the binary directory
+if(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
+ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/zmonvif-probe.pl" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
+endif(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
+
# Install the perl scripts
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmonvif-probe.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/onvif/scripts/zmonvif-probe.pl b/onvif/scripts/zmonvif-probe.pl
index fb550f475..8740fb7e6 100755
--- a/onvif/scripts/zmonvif-probe.pl
+++ b/onvif/scripts/zmonvif-probe.pl
@@ -3,7 +3,7 @@
# ==========================================================================
#
# ZoneMinder ONVIF Control Protocol Module
-# Copyright (C) Jan M. Hochstein
+# Copyright (C) 2014 Jan M. Hochstein
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
diff --git a/onvif/wsdl/b-2.xsd b/onvif/wsdl/b-2.xsd
deleted file mode 100644
index 6af08aee9..000000000
--- a/onvif/wsdl/b-2.xsd
+++ /dev/null
@@ -1,586 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/bf-2.xsd b/onvif/wsdl/bf-2.xsd
deleted file mode 100644
index 4efefea72..000000000
--- a/onvif/wsdl/bf-2.xsd
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
-
-
-
-
- Get access to the xml: attribute groups for xml:lang as declared on 'schema'
- and 'documentation' below
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/devicemgmt.wsdl b/onvif/wsdl/devicemgmt.wsdl
deleted file mode 100644
index d7f7379c1..000000000
--- a/onvif/wsdl/devicemgmt.wsdl
+++ /dev/null
@@ -1,3786 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if the service capabilities (untyped) should be included in the response.
-
-
-
-
-
-
-
-
-
-
- Each Service element contains information about one service.
-
-
-
-
-
-
-
-
-
-
- Namespace of the service being described. This parameter allows to match the service capabilities to the service. Note that only one set of capabilities is supported per namespace.
-
-
-
-
- The transport addresses where the service can be reached. The scheme and IP part shall match the one used in the request (i.e. the GetServices request).
-
-
-
-
-
-
-
- The placeholder for the service capabilities. The service capability element shall be returned here. For example for the device service that would be the tds:DeviceServiceCapabilities element (not complextype).
-
-
-
-
-
-
-
- The version of the service (not the ONVIF core spec version).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The capabilities for the device service is returned in the Capabilities element.
-
-
-
-
-
-
-
-
-
-
- Network capabilities.
-
-
-
-
- Security capabilities.
-
-
-
-
- System capabilities.
-
-
-
-
- Capabilities that do not fit in any of the other categories.
-
-
-
-
-
-
-
-
-
- Indicates support for IP filtering.
-
-
-
-
- Indicates support for zeroconf.
-
-
-
-
- Indicates support for IPv6.
-
-
-
-
- Indicates support for dynamic DNS configuration.
-
-
-
-
- Indicates support for IEEE 802.11 configuration.
-
-
-
-
- Indicates the maximum number of Dot1X configurations supported by the device
-
-
-
-
- Indicates support for retrieval of hostname from DHCP.
-
-
-
-
- Maximum number of NTP servers supported by the devices SetNTP command.
-
-
-
-
- Indicates support for Stateful IPv6 DHCP.
-
-
-
-
-
-
-
-
-
-
-
- Indicates support for TLS 1.0.
-
-
-
-
- Indicates support for TLS 1.1.
-
-
-
-
- Indicates support for TLS 1.2.
-
-
-
-
- Indicates support for onboard key generation.
-
-
-
-
- Indicates support for access policy configuration.
-
-
-
-
- Indicates support for the ONVIF default access policy.
-
-
-
-
- Indicates support for IEEE 802.1X configuration.
-
-
-
-
- Indicates support for remote user configuration. Used when accessing another device.
-
-
-
-
- Indicates support for WS-Security X.509 token.
-
-
-
-
- Indicates support for WS-Security SAML token.
-
-
-
-
- Indicates support for WS-Security Kerberos token.
-
-
-
-
- Indicates support for WS-Security Username token.
-
-
-
-
- Indicates support for WS over HTTP digest authenticated communication layer.
-
-
-
-
- Indicates support for WS-Security REL token.
-
-
-
-
- EAP Methods supported by the device. The int values refer to the IANA EAP Registry.
-
-
-
-
- The maximum number of users that the device supports.
-
-
-
-
-
-
-
-
- Indicates support for WS Discovery resolve requests.
-
-
-
-
- Indicates support for WS-Discovery Bye.
-
-
-
-
- Indicates support for remote discovery.
-
-
-
-
- Indicates support for system backup through MTOM.
-
-
-
-
- Indicates support for retrieval of system logging through MTOM.
-
-
-
-
- Indicates support for firmware upgrade through MTOM.
-
-
-
-
- Indicates support for system backup through MTOM.
-
-
-
-
- Indicates support for system backup through HTTP.
-
-
-
-
- Indicates support for retrieval of system logging through HTTP.
-
-
-
-
- Indicates support for retrieving support information through HTTP.
-
-
-
-
-
-
-
-
- Lists of commands supported by SendAuxiliaryCommand.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The manufactor of the device.
-
-
-
-
- The device model.
-
-
-
-
- The firmware version in the device.
-
-
-
-
- The serial number of the device.
-
-
-
-
- The hardware ID of the device.
-
-
-
-
-
-
-
-
-
-
-
- Defines if the date and time is set via NTP or manually.
-
-
-
-
- Automatically adjust Daylight savings if defined in TimeZone.
-
-
-
-
- The time zone in POSIX 1003.1 format
-
-
-
-
- Date and time in UTC. If time is obtained via NTP, UTCDateTime has no meaning
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains information whether system date and time are set manually or by NTP, daylight savings is on or off, time zone in POSIX 1003.1 format and system date and time in UTC and also local system date and time.
-
-
-
-
-
-
-
-
-
-
-
- Specifies the factory default action type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the reboot message sent by the device.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the arbitary device diagnostics information.
-
-
-
-
-
-
-
-
-
-
-
- Specifies the type of system log to get.
-
-
-
-
-
-
-
-
-
-
- Contains the system log information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a list of URI definining the device scopes. Scope parameters can be of two types: fixed and configurable. Fixed parameters can not be altered.
-
-
-
-
-
-
-
-
-
-
-
- Contains a list of scope parameters that will replace all existing configurable scope parameters.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a list of new configurable scope parameters that will be added to the existing configurable scope.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a list of URIs that should be removed from the device scope.
- Note that the response message always will match the request or an error will be returned. The use of the response is for that reason deprecated.
-
-
-
-
-
-
-
-
-
-
-
- Contains a list of URIs that has been removed from the device scope
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicator of discovery mode: Discoverable, NonDiscoverable.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicator of discovery mode: Discoverable, NonDiscoverable.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicator of discovery mode: Discoverable, NonDiscoverable.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicator of discovery mode: Discoverable, NonDiscoverable.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a list of the onvif users and following information is included in each entry: username and user level.
-
-
-
-
-
-
-
-
-
-
-
- Creates new device users and corresponding credentials. Each user entry includes: username, password and user level. Either all users are created successfully or a fault message MUST be returned without creating any user. If trying to create several users with exactly the same username the request is rejected and no users are created. If password is missing, then fault message Too weak password is returned.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Deletes users on an device and there may exist users that cannot be deleted to ensure access to the unit. Either all users are deleted successfully or a fault message MUST be returned and no users be deleted. If a username exists multiple times in the request, then a fault message is returned.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Updates the credentials for one or several users on an device. Either all change requests are processed successfully or a fault message MUST be returned. If the request contains the same username multiple times, a fault message is returned.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of categories to retrieve capability information on.
-
-
-
-
-
-
-
-
-
-
-
-
- Capability information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the hostname information.
-
-
-
-
-
-
-
-
-
-
-
- The hostname to set.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True if the hostname shall be obtained via DHCP.
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not a reboot is required after configuration updates.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- DNS information.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicate if the DNS address is to be retrieved using DHCP.
-
-
-
-
-
-
- DNS search domain.
-
-
-
-
-
-
- DNS address(es) set manually.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- NTP information.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicate if NTP address information is to be retrieved using DHCP.
-
-
-
-
-
-
- Manual NTP settings.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Dynamic DNS information.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Dynamic DNS type.
-
-
-
-
-
-
- DNS name.
-
-
-
-
-
-
- DNS record time to live.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of network interfaces.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Symbolic network interface name.
-
-
-
-
-
-
- Network interface name.
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not a reboot is required after configuration updates.
- If a device responds with RebootNeeded set to false, the device can be reached
- via the new IP address without further action. A client should be aware that a device
- may not be responsive for a short period of time until it signals availability at
- the new address via the discovery Hello messages.
- If a device responds with RebootNeeded set to true, it will be further available under
- its previous IP address. The settings will only be activated when the device is
- rebooted via the SystemReboot command.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains an array of defined protocols supported by the device. There are three protocols defined; HTTP, HTTPS and RTSP. The following parameters can be retrieved for each protocol: port and enable/disable.
-
-
-
-
-
-
-
-
-
-
-
- Configures one or more defined network protocols supported by the device. There are currently three protocols defined; HTTP, HTTPS and RTSP. The following parameters can be set for each protocol: port and enable/disable.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Gets the default IPv4 and IPv6 gateway settings from the device.
-
-
-
-
-
-
-
-
-
-
-
- Sets IPv4 gateway address used as default setting.
-
-
-
-
- Sets IPv6 gateway address used as default setting.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the zero-configuration.
-
-
-
-
-
-
-
-
-
-
-
- Unique identifier referencing the physical interface.
-
-
-
-
- Specifies if the zero-configuration should be enabled or not.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Certificate id.
-
-
-
-
- Identification of the entity associated with the public-key.
-
-
-
-
- Certificate validity start date.
-
-
-
-
- Certificate expiry start date.
-
-
-
-
-
-
-
-
-
-
-
- base64 encoded DER representation of certificate.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Id and base64 encoded DER representation of all available certificates.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if a certificate is used in an optional HTTPS configuration of the device.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if a certificate is to be used in an optional HTTPS configuration of the device.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of ids of certificates to delete.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of ids of certificates to delete.
-
-
-
-
-
-
- Relative Dinstinguished Name(RDN) CommonName(CN).
-
-
-
-
-
-
- Optional base64 encoded DER attributes.
-
-
-
-
-
-
-
-
-
-
-
-
- base64 encoded DER representation of certificate.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional id and base64 encoded DER representation of certificate.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not client certificates are required by device.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not client certificates are required by device.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Returns information about services on the device.
-
-
-
-
- Returns the capabilities of the device service. The result is returned in a typed answer.
-
-
-
-
- This operation gets basic device information from the device.
-
-
-
-
- This operation sets the device system date and time. The device shall support the
- configuration of the daylight saving setting and of the manual system date and time (if
- applicable) or indication of NTP time (if applicable) through the SetSystemDateAndTime
- command.
- If system time and date are set manually, the client shall include UTCDateTime in the request.
- A TimeZone token which is not formed according to the rules of IEEE 1003.1 section 8.3 is considered as invalid timezone.
- The DayLightSavings flag should be set to true to activate any DST settings of the TimeZone string.
- Clear the DayLightSavings flag if the DST portion of the TimeZone settings should be ignored.
-
-
-
-
-
- This operation gets the device system date and time. The device shall support the return of
- the daylight saving setting and of the manual system date and time (if applicable) or indication
- of NTP time (if applicable) through the GetSystemDateAndTime command.
- A device shall provide the UTCDateTime information.
-
-
-
-
- This operation reloads the parameters on the device to their factory default values.
-
-
-
-
- This operation upgrades a device firmware version. After a successful upgrade the response
- message is sent before the device reboots. The device should support firmware upgrade
- through the UpgradeSystemFirmware command. The exact format of the firmware data is
- outside the scope of this standard.
-
-
-
-
- This operation reboots the device.
-
-
-
-
- This operation restores the system backup configuration files(s) previously retrieved from a
- device. The device should support restore of backup configuration file(s) through the
- RestoreSystem command. The exact format of the backup configuration file(s) is outside the
- scope of this standard. If the command is supported, it shall accept backup files returned by
- the GetSystemBackup command.
-
-
-
-
- This operation is retrieves system backup configuration file(s) from a device. The device
- should support return of back up configuration file(s) through the GetSystemBackup command.
- The backup is returned with reference to a name and mime-type together with binary data.
- The exact format of the backup configuration files is outside the scope of this standard.
-
-
-
-
- This operation gets a system log from the device. The exact format of the system logs is outside the scope of this standard.
-
-
-
-
- This operation gets arbitary device diagnostics information from the device.
-
-
-
-
- This operation requests the scope parameters of a device. The scope parameters are used in
- the device discovery to match a probe message, see Section 7. The Scope parameters are of
- two different types:
-
Fixed
-
Configurable
-
- Fixed scope parameters are permanent device characteristics and cannot be removed through the device management interface.
- The scope type is indicated in the scope list returned in the get scope parameters response. A device shall support
- retrieval of discovery scope parameters through the GetScopes command. As some scope parameters are mandatory,
- the device shall return a non-empty scope list in the response.
-
-
-
-
- This operation sets the scope parameters of a device. The scope parameters are used in the
- device discovery to match a probe message.
- This operation replaces all existing configurable scope parameters (not fixed parameters). If
- this shall be avoided, one should use the scope add command instead. The device shall
- support configuration of discovery scope parameters through the SetScopes command.
-
-
-
-
- This operation adds new configurable scope parameters to a device. The scope parameters
- are used in the device discovery to match a probe message. The device shall
- support addition of discovery scope parameters through the AddScopes command.
-
-
-
-
- This operation deletes scope-configurable scope parameters from a device. The scope
- parameters are used in the device discovery to match a probe message, see Section 7. The
- device shall support deletion of discovery scope parameters through the RemoveScopes
- command.
- Table
-
-
-
-
- This operation gets the discovery mode of a device. See Section 7.2 for the definition of the
- different device discovery modes. The device shall support retrieval of the discovery mode
- setting through the GetDiscoveryMode command.
-
-
-
-
- This operation sets the discovery mode operation of a device. See Section 7.2 for the
- definition of the different device discovery modes. The device shall support configuration of
- the discovery mode setting through the SetDiscoveryMode command.
-
-
-
-
- This operation gets the remote discovery mode of a device. See Section 7.4 for the definition
- of remote discovery extensions. A device that supports remote discovery shall support
- retrieval of the remote discovery mode setting through the GetRemoteDiscoveryMode
- command.
-
-
-
-
- This operation sets the remote discovery mode of operation of a device. See Section 7.4 for
- the definition of remote discovery remote extensions. A device that supports remote discovery
- shall support configuration of the discovery mode setting through the
- SetRemoteDiscoveryMode command.
-
-
-
-
- This operation gets the remote DP address or addresses from a device. If the device supports
- remote discovery, as specified in Section 7.4, the device shall support retrieval of the remote
- DP address(es) through the GetDPAddresses command.
-
-
-
-
- This operation sets the remote DP address or addresses on a device. If the device supports
- remote discovery, as specified in Section 7.4, the device shall support configuration of the
- remote DP address(es) through the SetDPAddresses command.
-
-
-
-
- A client can ask for the device service endpoint reference address property that can be used
- to derive the password equivalent for remote user operation. The device shall support the
- GetEndpointReference command returning the address property of the device service
- endpoint reference.
-
-
-
-
- This operation returns the configured remote user (if any). A device supporting remote user
- handling shall support this operation. The user is only valid for the WS-UserToken profile or
- as a HTTP / RTSP user.
- The algorithm to use for deriving the password is described in section 5.12.2.1 of the core specification.
-
-
-
-
- This operation sets the remote user. A device supporting remote user handling shall support this
- operation. The user is only valid for the WS-UserToken profile or as a HTTP / RTSP user.
- The password that is set shall always be the original (not derived) password.
- If UseDerivedPassword is set password derivation shall be done by the device when connecting to a
- remote device.The algorithm to use for deriving the password is described in section 5.12.2.1 of the core specification.
- To remove the remote user SetRemoteUser should be called without the RemoteUser parameter.
-
-
-
-
- This operation lists the registered users and corresponding credentials on a device. The
- device shall support retrieval of registered device users and their credentials for the user
- token through the GetUsers command.
-
-
-
-
- This operation creates new device users and corresponding credentials on a device for authentication purposes.
- The device shall support creation of device users and their credentials through the CreateUsers
- command. Either all users are created successfully or a fault message shall be returned
- without creating any user.
- ONVIF compliant devices are recommended to support password length of at least 28 bytes,
- as clients may follow the password derivation mechanism which results in 'password
- equivalent' of length 28 bytes, as described in section 3.1.2 of the ONVIF security white paper.
-
-
-
-
- This operation deletes users on a device. The device shall support deletion of device users and their credentials
- through the DeleteUsers command. A device may have one or more fixed users
- that cannot be deleted to ensure access to the unit. Either all users are deleted successfully or a
- fault message shall be returned and no users be deleted.
-
-
-
-
- This operation updates the settings for one or several users on a device for authentication purposes.
- The device shall support update of device users and their credentials through the SetUser command.
- Either all change requests are processed successfully or a fault message shall be returned and no change requests be processed.
-
-
-
-
- It is possible for an endpoint to request a URL that can be used to retrieve the complete
- schema and WSDL definitions of a device. The command gives in return a URL entry point
- where all the necessary product specific WSDL and schema definitions can be retrieved. The
- device shall provide a URL for WSDL and schema download through the GetWsdlUrl command.
-
-
-
-
- Any endpoint can ask for the capabilities of a device using the capability exchange request
- response operation. The device shall indicate all its ONVIF compliant capabilities through the
- GetCapabilities command.
- The capability list includes references to the addresses (XAddr) of the service implementing
- the interface operations in the category. Apart from the addresses, the
- capabilities only reflect optional functions.
-
-
-
-
- This operation is used by an endpoint to get the hostname from a device. The device shall
- return its hostname configurations through the GetHostname command.
-
-
-
-
- This operation sets the hostname on a device. It shall be possible to set the device hostname
- configurations through the SetHostname command.
- A device shall accept string formated according to RFC 1123 section 2.1 or alternatively to RFC 952,
- other string shall be considered as invalid strings.
-
-
-
-
-
- This operation controls whether the hostname is set manually or retrieved via DHCP.
-
-
-
-
- This operation gets the DNS settings from a device. The device shall return its DNS
- configurations through the GetDNS command.
-
-
-
-
- This operation sets the DNS settings on a device. It shall be possible to set the device DNS
- configurations through the SetDNS command.
-
-
-
-
- This operation gets the NTP settings from a device. If the device supports NTP, it shall be
- possible to get the NTP server settings through the GetNTP command.
-
-
-
-
- This operation sets the NTP settings on a device. If the device supports NTP, it shall be
- possible to set the NTP server settings through the SetNTP command.
- A device shall accept string formated according to RFC 1123 section 2.1 or alternatively to RFC 952,
- other string shall be considered as invalid strings.
- Changes to the NTP server list will not affect the clock mode DateTimeType. Use SetSystemDateAndTime to activate NTP operation.
-
-
-
-
-
- This operation gets the dynamic DNS settings from a device. If the device supports dynamic
- DNS as specified in [RFC 2136] and [RFC 4702], it shall be possible to get the type, name
- and TTL through the GetDynamicDNS command.
-
-
-
-
- This operation sets the dynamic DNS settings on a device. If the device supports dynamic
- DNS as specified in [RFC 2136] and [RFC 4702], it shall be possible to set the type, name
- and TTL through the SetDynamicDNS command.
-
-
-
-
- This operation gets the network interface configuration from a device. The device shall
- support return of network interface configuration settings as defined by the NetworkInterface
- type through the GetNetworkInterfaces command.
-
-
-
-
- This operation sets the network interface configuration on a device. The device shall support
- network configuration of supported network interfaces through the SetNetworkInterfaces
- command.
- For interoperability with a client unaware of the IEEE 802.11 extension a device shall retain
- its IEEE 802.11 configuration if the IEEE 802.11 configuration element isn’t present in the
- request.
-
-
-
-
- This operation gets defined network protocols from a device. The device shall support the
- GetNetworkProtocols command returning configured network protocols.
-
-
-
-
- This operation configures defined network protocols on a device. The device shall support
- configuration of defined network protocols through the SetNetworkProtocols command.
-
-
-
-
- This operation gets the default gateway settings from a device. The device shall support the
- GetNetworkDefaultGateway command returning configured default gateway address(es).
-
-
-
-
- This operation sets the default gateway settings on a device. The device shall support
- configuration of default gateway through the SetNetworkDefaultGateway command.
-
-
-
-
- This operation gets the zero-configuration from a device. If the device supports dynamic IP
- configuration according to [RFC3927], it shall support the return of IPv4 zero configuration
- address and status through the GetZeroConfiguration command.
- Devices supporting zero configuration on more than one interface shall use the extension to list the additional interface settings.
-
-
-
-
- This operation sets the zero-configuration. Use GetCapalities to get if zero-zero-configuration is supported or not.
-
-
-
-
- This operation gets the IP address filter settings from a device. If the device supports device
- access control based on IP filtering rules (denied or accepted ranges of IP addresses), the
- device shall support the GetIPAddressFilter command.
-
-
-
-
- This operation sets the IP address filter settings on a device. If the device supports device
- access control based on IP filtering rules (denied or accepted ranges of IP addresses), the
- device shall support configuration of IP filtering rules through the SetIPAddressFilter
- command.
-
-
-
-
- This operation adds an IP filter address to a device. If the device supports device access
- control based on IP filtering rules (denied or accepted ranges of IP addresses), the device
- shall support adding of IP filtering addresses through the AddIPAddressFilter command.
-
-
-
-
- This operation deletes an IP filter address from a device. If the device supports device access
- control based on IP filtering rules (denied or accepted ranges of IP addresses), the device
- shall support deletion of IP filtering addresses through the RemoveIPAddressFilter command.
-
-
-
-
- Access to different services and sub-sets of services should be subject to access control. The
- WS-Security framework gives the prerequisite for end-point authentication. Authorization
- decisions can then be taken using an access security policy. This standard does not mandate
- any particular policy description format or security policy but this is up to the device
- manufacturer or system provider to choose policy and policy description format of choice.
- However, an access policy (in arbitrary format) can be requested using this command. If the
- device supports access policy settings based on WS-Security authentication, then the device
- shall support this command.
-
-
-
-
- This command sets the device access security policy (for more details on the access security
- policy see the Get command). If the device supports access policy settings
- based on WS-Security authentication, then the device shall support this command.
-
-
-
-
- This operation generates a private/public key pair and also can create a self-signed device
- certificate as a result of key pair generation. The certificate is created using a suitable
- onboard key pair generation mechanism.
- If a device supports onboard key pair generation, the device that supports TLS shall support
- this certificate creation command. And also, if a device supports onboard key pair generation,
- the device that support IEEE 802.1X shall support this command for the purpose of key pair
- generation. Certificates and key pairs are identified using certificate IDs. These IDs are either
- chosen by the certificate generation requester or by the device (in case that no ID value is
- given).
-
-
-
-
- This operation gets all device server certificates (including self-signed) for the purpose of TLS
- authentication and all device client certificates for the purpose of IEEE 802.1X authentication.
- This command lists only the TLS server certificates and IEEE 802.1X client certificates for the
- device (neither trusted CA certificates nor trusted root certificates). The certificates are
- returned as binary data. A device that supports TLS shall support this command and the
- certificates shall be encoded using ASN.1 [X.681], [X.682], [X.683] DER [X.690] encoding
- rules.
-
-
-
-
- This operation is specific to TLS functionality. This operation gets the status
- (enabled/disabled) of the device TLS server certificates. A device that supports TLS shall
- support this command.
-
-
-
-
- This operation is specific to TLS functionality. This operation sets the status (enable/disable)
- of the device TLS server certificates. A device that supports TLS shall support this command.
- Typically only one device server certificate is allowed to be enabled at a time.
-
-
-
-
- This operation deletes a certificate or multiple certificates. The device MAY also delete a
- private/public key pair which is coupled with the certificate to be deleted. The device that
- support either TLS or IEEE 802.1X shall support the deletion of a certificate or multiple
- certificates through this command. Either all certificates are deleted successfully or a fault
- message shall be returned without deleting any certificate.
-
-
-
-
- This operation requests a PKCS #10 certificate signature request from the device. The
- returned information field shall be either formatted exactly as specified in [PKCS#10] or PEM
- encoded [PKCS#10] format. In order for this command to work, the device must already have
- a private/public key pair. This key pair should be referred by CertificateID as specified in the
- input parameter description. This CertificateID refers to the key pair generated using
- CreateCertificate command.
- A device that support onboard key pair generation that supports either TLS or IEEE 802.1X
- using client certificate shall support this command.
-
-
-
-
- TLS server certificate(s) or IEEE 802.1X client certificate(s) created using the PKCS#10
- certificate request command can be loaded into the device using this command (see Section
- 8.4.13). The certificate ID in the request shall be present. The device may sort the received
- certificate(s) based on the public key and subject information in the certificate(s).
- The certificate ID in the request will be the ID value the client wish to have. The device is
- supposed to scan the generated key pairs present in the device to identify which is the
- correspondent key pair with the loaded certificate and then make the link between the
- certificate and the key pair.
- A device that supports onboard key pair generation that support either TLS or IEEE 802.1X
- shall support this command.
- The certificates shall be encoded using ASN.1 [X.681], [X.682], [X.683] DER [X.690] encoding
- rules.
- This command is applicable to any device type, although the parameter name is called for
- historical reasons NVTCertificate.
-
-
-
-
- This operation is specific to TLS functionality. This operation gets the status
- (enabled/disabled) of the device TLS client authentication. A device that supports TLS shall
- support this command.
-
-
-
-
- This operation is specific to TLS functionality. This operation sets the status
- (enabled/disabled) of the device TLS client authentication. A device that supports TLS shall
- support this command.
-
-
-
-
- This operation gets a list of all available relay outputs and their settings.
- This method has been depricated with version 2.0. Refer to the DeviceIO service.
-
-
-
-
- This operation sets the settings of a relay output.
- This method has been depricated with version 2.0. Refer to the DeviceIO service.
-
-
-
-
- This operation sets the state of a relay output.
- This method has been depricated with version 2.0. Refer to the DeviceIO service.
-
-
-
-
- Manage auxiliary commands supported by a device, such as controlling an Infrared (IR) lamp,
- a heater or a wiper or a thermometer that is connected to the device.
- The supported commands can be retrieved via the AuxiliaryCommands capability.
- Although the name of the auxiliary commands can be freely defined, commands starting with the prefix tt: are
- reserved to define frequently used commands and these reserved commands shall all share the "tt:command|parameter" syntax.
-
-
tt:Wiper|On – Request to start the wiper.
-
tt:Wiper|Off – Request to stop the wiper.
-
tt:Washer|On – Request to start the washer.
-
tt:Washer|Off – Request to stop the washer.
-
tt:WashingProcedure|On – Request to start the washing procedure.
-
tt: WashingProcedure |Off – Request to stop the washing procedure.
-
tt:IRLamp|On – Request to turn ON an IR illuminator attached to the unit.
-
tt:IRLamp|Off – Request to turn OFF an IR illuminator attached to the unit.
-
tt:IRLamp|Auto – Request to configure an IR illuminator attached to the unit so that it automatically turns ON and OFF.
-
- A device that indicates auxiliary service capability shall support this command.
-
-
-
-
- CA certificates will be loaded into a device and be used for the sake of following two cases.
- The one is for the purpose of TLS client authentication in TLS server function. The other one
- is for the purpose of Authentication Server authentication in IEEE 802.1X function. This
- operation gets all CA certificates loaded into a device. A device that supports either TLS client
- authentication or IEEE 802.1X shall support this command and the returned certificates shall
- be encoded using ASN.1 [X.681], [X.682], [X.683] DER [X.690] encoding rules.
-
-
-
-
- There might be some cases that a Certificate Authority or some other equivalent creates a
- certificate without having PKCS#10 certificate signing request. In such cases, the certificate
- will be bundled in conjunction with its private key. This command will be used for such use
- case scenarios. The certificate ID in the request is optionally set to the ID value the client
- wish to have. If the certificate ID is not specified in the request, device can choose the ID
- accordingly.
- This operation imports a private/public key pair into the device.
- The certificates shall be encoded using ASN.1 [X.681], [X.682], [X.683] DER [X.690] encoding
- rules.
- A device that does not support onboard key pair generation and support either TLS or IEEE
- 802.1X using client certificate shall support this command. A device that support onboard key
- pair generation MAY support this command. The security policy of a device that supports this
- operation should make sure that the private key is sufficiently protected.
-
-
-
-
- This operation requests the information of a certificate specified by certificate ID. The device
- should respond with its “Issuer DN”, “Subject DN”, “Key usage”, "Extended key usage”, “Key
- Length”, “Version”, “Serial Number”, “Signature Algorithm” and “Validity” data as the
- information of the certificate, as long as the device can retrieve such information from the
- specified certificate.
- A device that supports either TLS or IEEE 802.1X should support this command.
-
-
-
-
- This command is used when it is necessary to load trusted CA certificates or trusted root
- certificates for the purpose of verification for its counterpart i.e. client certificate verification in
- TLS function or server certificate verification in IEEE 802.1X function.
- A device that support either TLS or IEEE 802.1X shall support this command. As for the
- supported certificate format, either DER format or PEM format is possible to be used. But a
- device that support this command shall support at least DER format as supported format type.
- The device may sort the received certificate(s) based on the public key and subject
- information in the certificate(s). Either all CA certificates are loaded successfully or a fault
- message shall be returned without loading any CA certificate.
-
-
-
-
- This operation newly creates IEEE 802.1X configuration parameter set of the device. The
- device shall support this command if it supports IEEE 802.1X. If the device receives this
- request with already existing configuration token (Dot1XConfigurationToken) specification, the
- device should respond with 'ter:ReferenceToken ' error to indicate there is some configuration
- conflict.
-
-
-
-
- While the CreateDot1XConfiguration command is trying to create a new configuration
- parameter set, this operation modifies existing IEEE 802.1X configuration parameter set of
- the device. A device that support IEEE 802.1X shall support this command.
-
-
-
-
- This operation gets one IEEE 802.1X configuration parameter set from the device by
- specifying the configuration token (Dot1XConfigurationToken).
- A device that supports IEEE 802.1X shall support this command.
- Regardless of whether the 802.1X method in the retrieved configuration has a password or
- not, the device shall not include the Password element in the response.
-
-
-
-
- This operation gets all the existing IEEE 802.1X configuration parameter sets from the device.
- The device shall respond with all the IEEE 802.1X configurations so that the client can get to
- know how many IEEE 802.1X configurations are existing and how they are configured.
- A device that support IEEE 802.1X shall support this command.
- Regardless of whether the 802.1X method in the retrieved configuration has a password or
- not, the device shall not include the Password element in the response.
-
-
-
-
- This operation deletes an IEEE 802.1X configuration parameter set from the device. Which
- configuration should be deleted is specified by the 'Dot1XConfigurationToken' in the request.
- A device that support IEEE 802.1X shall support this command.
-
-
-
-
- This operation returns the IEEE802.11 capabilities. The device shall support
- this operation.
-
-
-
-
- This operation returns the status of a wireless network interface. The device shall support this
- command.
-
-
-
-
- This operation returns a lists of the wireless networks in range of the device. A device should
- support this operation.
-
-
-
-
- This operation is used to retrieve URIs from which system information may be downloaded
- using HTTP. URIs may be returned for the following system information:
- System Logs. Multiple system logs may be returned, of different types. The exact format of
- the system logs is outside the scope of this specification.
- Support Information. This consists of arbitrary device diagnostics information from a device.
- The exact format of the diagnostic information is outside the scope of this specification.
- System Backup. The received file is a backup file that can be used to restore the current
- device configuration at a later date. The exact format of the backup configuration file is
- outside the scope of this specification.
- If the device allows retrieval of system logs, support information or system backup data, it
- should make them available via HTTP GET. If it does, it shall support the GetSystemUris
- command.
-
-
-
-
- This operation initiates a firmware upgrade using the HTTP POST mechanism. The response
- to the command includes an HTTP URL to which the upgrade file may be uploaded. The
- actual upgrade takes place as soon as the HTTP POST operation has completed. The device
- should support firmware upgrade through the StartFirmwareUpgrade command. The exact
- format of the firmware data is outside the scope of this specification.
- Firmware upgrade over HTTP may be achieved using the following steps:
-
Client calls StartFirmwareUpgrade.
-
Server responds with upload URI and optional delay value.
-
Client waits for delay duration if specified by server.
-
Client transmits the firmware image to the upload URI using HTTP POST.
-
Server reprograms itself using the uploaded image, then reboots.
-
- If the firmware upgrade fails because the upgrade file was invalid, the HTTP POST response
- shall be “415 Unsupported Media Type”. If the firmware upgrade fails due to an error at the
- device, the HTTP POST response shall be “500 Internal Server Error”.
- The value of the Content-Type header in the HTTP POST request shall be “application/octetstream”.
-
-
-
-
- This operation initiates a system restore from backed up configuration data using the HTTP
- POST mechanism. The response to the command includes an HTTP URL to which the backup
- file may be uploaded. The actual restore takes place as soon as the HTTP POST operation
- has completed. Devices should support system restore through the StartSystemRestore
- command. The exact format of the backup configuration data is outside the scope of this
- specification.
- System restore over HTTP may be achieved using the following steps:
-
Client calls StartSystemRestore.
-
Server responds with upload URI.
-
Client transmits the configuration data to the upload URI using HTTP POST.
-
Server applies the uploaded configuration, then reboots if necessary.
-
- If the system restore fails because the uploaded file was invalid, the HTTP POST response
- shall be “415 Unsupported Media Type”. If the system restore fails due to an error at the
- device, the HTTP POST response shall be “500 Internal Server Error”.
- The value of the Content-Type header in the HTTP POST request shall be “application/octetstream”.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/media.wsdl b/onvif/wsdl/media.wsdl
deleted file mode 100644
index de3fdb30d..000000000
--- a/onvif/wsdl/media.wsdl
+++ /dev/null
@@ -1,3688 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The capabilities for the media service is returned in the Capabilities element.
-
-
-
-
-
-
-
-
-
-
- Media profile capabilities.
-
-
-
-
- Streaming capabilities.
-
-
-
-
-
-
- Indicates if GetSnapshotUri is supported.
-
-
-
-
- Indicates whether or not Rotation feature is supported.
-
-
-
-
- Indicates the support for changing video source mode.
-
-
-
-
- Indicates if OSD is supported.
-
-
-
-
-
-
-
-
-
-
-
-
- Maximum number of profiles supported.
-
-
-
-
-
-
-
-
-
-
-
- Indicates support for RTP multicast.
-
-
-
-
- Indicates support for RTP over TCP.
-
-
-
-
- Indicates support for RTP/RTSP/TCP.
-
-
-
-
- Indicates support for non aggregate RTSP control.
-
-
-
-
- Indicates the device does not support live media streaming via RTSP.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of existing Video Sources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of existing Audio Sources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of existing Audio Outputs
-
-
-
-
-
-
-
-
-
-
-
- friendly name of the profile to be created
-
-
-
-
- Optional token, specifying the unique identifier of the new profile. A device supports at least a token length of 12 characters and characters "A-Z" | "a-z" | "0-9" | "-.".
-
-
-
-
-
-
-
-
-
-
- returns the new created profile
-
-
-
-
-
-
-
-
-
-
-
- this command requests a specific profile
-
-
-
-
-
-
-
-
-
-
- returns the requested media profile
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- lists all profiles that exist in the media service
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the VideoEncoderConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-VideoEncoderConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the VideoSourceConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-VideoSourceConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the AudioEncoderConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-AudioEncoderConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the AudioSourceConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-AudioSourceConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the PTZConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-PTZConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the VideoAnalyticsConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-VideoAnalyticsConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the MetadataConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-MetadataConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the profile where the configuration should be added
-
-
-
-
- Contains a reference to the AudioOutputConfiguration to add
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a reference to the media profile from which the
-AudioOutputConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a reference to the profile where the configuration should be added.
-
-
-
-
- This element contains a reference to the AudioDecoderConfiguration to add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a reference to the media profile from which the AudioDecoderConfiguration shall be removed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a reference to the profile that should be deleted.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of video encoder configurations.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of video source configurations.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of audio encoder configurations.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of audio source configurations.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of VideoAnalytics configurations.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of metadata configurations
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of audio output configurations
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a list of audio decoder configurations
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested video source configuration.
-
-
-
-
-
-
-
-
-
-
-
- The requested video source configuration.
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested video encoder configuration.
-
-
-
-
-
-
-
-
-
-
- The requested video encoder configuration.
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested audio source configuration.
-
-
-
-
-
-
-
-
-
-
- The requested audio source configuration.
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested audio encoder configuration.
-
-
-
-
-
-
-
-
-
-
- The requested audio encoder configuration
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested video analytics configuration.
-
-
-
-
-
-
-
-
-
-
- The requested video analytics configuration.
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested metadata configuration.
-
-
-
-
-
-
-
-
-
-
- The requested metadata configuration.
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested audio output configuration.
-
-
-
-
-
-
-
-
-
-
-
- The requested audio output configuration.
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested audio decoder configuration.
-
-
-
-
-
-
-
-
-
-
-
- The requested audio decoder configuration
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of video encoder configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of video source configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of audio encoder configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of audio source configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of video analytics configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of metadata configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of audio output configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- Contains a list of audio decoder configurations that are compatible with the specified media profile.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified video encoder configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified video source configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified audio encoder configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified audio source configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified video analytics configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified metadata configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified audio output configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified audio decoder configuration. The configuration shall exist in the device.
-
-
-
-
- The ForcePersistence element is obsolete and should always be assumed to be true.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional video source configurationToken that specifies an existing configuration that the options are intended for.
-
-
-
-
- Optional ProfileToken that specifies an existing media profile that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- This message contains the video source configuration options. If a video source configuration is specified, the options shall concern that particular configuration. If a media profile is specified, the options shall be compatible with that media profile. If no tokens are specified, the options shall be considered generic for the device.
-
-
-
-
-
-
-
-
-
-
-
- Optional video encoder configuration token that specifies an existing configuration that the options are intended for.
-
-
-
-
- Optional ProfileToken that specifies an existing media profile that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional audio source configuration token that specifies an existing configuration that the options are intended for.
-
-
-
-
- Optional ProfileToken that specifies an existing media profile that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- This message contains the audio source configuration options. If a audio source configuration is specified, the options shall concern that particular configuration. If a media profile is specified, the options shall be compatible with that media profile. If no tokens are specified, the options shall be considered generic for the device.
-
-
-
-
-
-
-
-
-
-
-
- Optional audio encoder configuration token that specifies an existing configuration that the options are intended for.
-
-
-
-
- Optional ProfileToken that specifies an existing media profile that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- This message contains the audio encoder configuration options. If a audio encoder configuration is specified, the options shall concern that particular configuration. If a media profile is specified, the options shall be compatible with that media profile. If no tokens are specified, the options shall be considered generic for the device.
-
-
-
-
-
-
-
-
-
-
-
- Optional metadata configuration token that specifies an existing configuration that the options are intended for.
-
-
-
-
- Optional ProfileToken that specifies an existing media profile that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- This message contains the metadata configuration options. If a metadata configuration is specified, the options shall concern that particular configuration. If a media profile is specified, the options shall be compatible with that media profile. If no tokens are specified, the options shall be considered generic for the device.
-
-
-
-
-
-
-
-
-
-
-
- Optional audio output configuration token that specifies an existing configuration that the options are intended for.
-
-
-
-
- Optional ProfileToken that specifies an existing media profile that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- This message contains the audio output configuration options. If a audio output configuration is specified, the options shall concern that particular configuration. If a media profile is specified, the options shall be compatible with that media profile. If no tokens are specified, the options shall be considered generic for the device.
-
-
-
-
-
-
-
-
-
-
-
- Optional audio decoder configuration token that specifies an existing configuration that the options are intended for.
-
-
-
-
- Optional ProfileToken that specifies an existing media profile that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- This message contains the audio decoder configuration options. If a audio decoder configuration is specified, the options shall concern that particular configuration. If a media profile is specified, the options shall be compatible with that media profile. If no tokens are specified, the options shall be considered generic for the device.
-
-
-
-
-
-
-
-
-
-
-
- Token of the video source configuration
-
-
-
-
-
-
-
-
-
-
- The minimum guaranteed total number of encoder instances (applications) per VideoSourceConfiguration. The device is able to deliver the TotalNumber of streams
-
-
-
-
- If a device limits the number of instances for respective Video Codecs the response contains the information how many Jpeg streams can be set up at the same time per VideoSource.
-
-
-
-
- If a device limits the number of instances for respective Video Codecs the response contains the information how many H264 streams can be set up at the same time per VideoSource.
-
-
-
-
- If a device limits the number of instances for respective Video Codecs the response contains the information how many Mpeg4 streams can be set up at the same time per VideoSource.
-
-
-
-
-
-
-
-
-
-
-
- Stream Setup that should be used with the uri
-
-
-
-
- The ProfileToken element indicates the media profile to use and will define the configuration of the content of the stream.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of the Profile that is used to define the multicast stream.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of the Profile that is used to define the multicast stream.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a Profile reference for which a Synchronization Point is requested.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The ProfileToken element indicates the media profile to use and will define the source and dimensions of the snapshot.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains a video source reference for which a video source mode is requested.
-
-
-
-
-
-
-
-
-
-
- Return the information for specified video source mode.
-
-
-
-
-
-
-
-
-
-
-
- Contains a video source reference for which a video source mode is requested.
-
-
-
-
- Indicate video source mode.
-
-
-
-
-
-
-
-
-
-
- The response contains information about rebooting after returning response. When Reboot is set true, a device will reboot automatically after setting mode.
-
-
-
-
-
-
-
-
- Indication which encodings are supported for this video source. The list may contain one or more enumeration values of tt:VideoEncoding.
-
-
-
-
-
-
-
-
- Max frame rate in frames per second for this video source mode.
-
-
-
-
- Max horizontal and vertical resolution for this video source mode.
-
-
-
-
- Indication which encodings are supported for this video source. The list may contain one or more enumeration values of tt:VideoEncoding.
-
-
-
-
- After setting the mode if a device starts to reboot this value is true. If a device change the mode without rebooting this value is false. If true, configured parameters may not be guaranteed by the device after rebooting.
-
-
-
-
- Informative description of this video source mode. This field should be described in English.
-
-
-
-
-
-
- Indicate token for video source mode.
-
-
-
-
- Indication of whether this mode is active. If active this value is true. In case of non-indication, it means as false. The value of true shall be had by only one video source mode.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the Video Source Configuration, which has OSDs associated with are requested. If token not exist, request all available OSDs.
-
-
-
-
-
-
-
-
-
-
- This element contains a list of requested OSDs.
-
-
-
-
-
-
-
-
-
-
-
- The GetOSD command fetches the OSD configuration if the OSD token is known.
-
-
-
-
-
-
-
-
-
-
-
- The requested OSD configuration.
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the modified OSD configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Video Source Configuration Token that specifies an existing video source configuration that the options shall be compatible with.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contain the initial OSD configuration for create.
-
-
-
-
-
-
-
-
-
-
-
- Returns Token of the newly created OSD
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a reference to the OSD configuration that should be deleted.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Returns the capabilities of the media service. The result is returned in a typed answer.
-
-
-
-
-
- This command lists all available physical video inputs of the device.
-
-
-
-
- This command lists all available physical audio inputs of the device.
-
-
-
-
- This command lists all available physical audio outputs of the device.
-
-
-
-
-
- This operation creates a new empty media profile. The media profile shall be created in the
-device and shall be persistent (remain after reboot). A created profile shall be deletable and a device shall set the “fixed” attribute to false in the
-returned Profile.
-
-
-
-
- If the profile token is already known, a profile can be fetched through the GetProfile command.
-
-
-
-
- Any endpoint can ask for the existing media profiles of a device using the GetProfiles
-command. Pre-configured or dynamically configured profiles can be retrieved using this
-command. This command lists all configured profiles in a device. The client does not need to
-know the media profile in order to use the command.
-
-
-
-
- This operation adds a VideoEncoderConfiguration to an existing media profile. If a
-configuration exists in the media profile, it will be replaced. The change shall be persistent. A device shall
-support adding a compatible VideoEncoderConfiguration to a Profile containing a VideoSourceConfiguration and shall
-support streaming video data of such a profile.
-
-
-
-
-
- This operation removes a VideoEncoderConfiguration from an existing media profile. If the
-media profile does not contain a VideoEncoderConfiguration, the operation has no effect. The removal shall be persistent.
-
-
-
-
- This operation adds a VideoSourceConfiguration to an existing media profile. If such a
-configuration exists in the media profile, it will be replaced. The change shall be persistent.
-
-
-
-
- This operation removes a VideoSourceConfiguration from an existing media profile. If the
-media profile does not contain a VideoSourceConfiguration, the operation has no effect. The removal shall be persistent. Video source configurations should only be removed after removing a
-VideoEncoderConfiguration from the media profile.
-
-
-
-
- This operation adds an AudioEncoderConfiguration to an existing media profile. If a
-configuration exists in the media profile, it will be replaced. The change shall be persistent. A device shall
-support adding a compatible AudioEncoderConfiguration to a profile containing an AudioSourceConfiguration and shall
-support streaming audio data of such a profile.
-
-
-
-
-
- This operation removes an AudioEncoderConfiguration from an existing media profile. If the
-media profile does not contain an AudioEncoderConfiguration, the operation has no effect.
-The removal shall be persistent.
-
-
-
-
- This operation adds an AudioSourceConfiguration to an existing media profile. If a
-configuration exists in the media profile, it will be replaced. The change shall be persistent.
-
-
-
-
- This operation removes an AudioSourceConfiguration from an existing media profile. If the
-media profile does not contain an AudioSourceConfiguration, the operation has no effect. The
-removal shall be persistent. Audio source configurations should only be removed after removing an
-AudioEncoderConfiguration from the media profile.
-
-
-
-
- This operation adds a PTZConfiguration to an existing media profile. If a configuration exists
-in the media profile, it will be replaced. The change shall be persistent. Adding a PTZConfiguration to a media profile means that streams using that media profile can
-contain PTZ status (in the metadata), and that the media profile can be used for controlling
-PTZ movement.
-
-
-
-
- This operation removes a PTZConfiguration from an existing media profile. If the media profile
-does not contain a PTZConfiguration, the operation has no effect. The removal shall be persistent.
-
-
-
-
- This operation adds a VideoAnalytics configuration to an existing media profile. If a
-configuration exists in the media profile, it will be replaced. The change shall be persistent. Adding a VideoAnalyticsConfiguration to a media profile means that streams using that media
-profile can contain video analytics data (in the metadata) as defined by the submitted configuration reference. A profile containing only a video analytics configuration but no video source configuration is incomplete. Therefore, a client should first add a video source configuration to a profile before adding a video analytics configuration. The device can deny adding of a video analytics
-configuration before a video source configuration.
-
-
-
-
- This operation removes a VideoAnalyticsConfiguration from an existing media profile. If the media profile does not contain a VideoAnalyticsConfiguration, the operation has no effect.
-The removal shall be persistent.
-
-
-
-
- This operation adds a Metadata configuration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. Adding a MetadataConfiguration to a Profile means that streams using that profile contain metadata. Metadata can consist of events, PTZ status, and/or video analytics data.
-
-
-
-
- This operation removes a MetadataConfiguration from an existing media profile. If the media profile does not contain a MetadataConfiguration, the operation has no effect. The removal shall be persistent.
-
-
-
-
- This operation adds an AudioOutputConfiguration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent.
-
-
-
-
- This operation removes an AudioOutputConfiguration from an existing media profile. If the media profile does not contain an AudioOutputConfiguration, the operation has no effect. The removal shall be persistent.
-
-
-
-
- This operation adds an AudioDecoderConfiguration to an existing media profile. If a configuration exists in the media profile, it shall be replaced. The change shall be persistent.
-
-
-
-
- This operation removes an AudioDecoderConfiguration from an existing media profile. If the media profile does not contain an AudioDecoderConfiguration, the operation has no effect. The removal shall be persistent.
-
-
-
-
- This operation deletes a profile. This change shall always be persistent. Deletion of a profile is only possible for non-fixed profiles
-
-
-
-
-
- This operation lists all existing video source configurations for a device. The client need not know anything about the video source configurations in order to use the command.
-
-
-
-
- This operation lists all existing video encoder configurations of a device. This command lists all configured video encoder configurations in a device. The client need not know anything apriori about the video encoder configurations in order to use the command.
-
-
-
-
- This operation lists all existing audio source configurations of a device. This command lists all audio source configurations in a device. The client need not know anything apriori about the audio source configurations in order to use the command.
-
-
-
-
- This operation lists all existing device audio encoder configurations. The client need not know anything apriori about the audio encoder configurations in order to use the command.
-
-
-
-
- This operation lists all video analytics configurations of a device. This command lists all configured video analytics in a device. The client need not know anything apriori about the video analytics in order to use the command.
-
-
-
-
- This operation lists all existing metadata configurations. The client need not know anything apriori about the metadata in order to use the command.
-
-
-
-
- This command lists all existing AudioOutputConfigurations of a device. The NVC need not know anything apriori about the audio configurations to use this command.
-
-
-
-
- This command lists all existing AudioDecoderConfigurations of a device. The NVC need not know anything apriori about the audio decoder configurations in order to
-use this command.
-
-
-
-
- If the video source configuration token is already known, the video source configuration can be fetched through the GetVideoSourceConfiguration command.
-
-
-
-
- If the video encoder configuration token is already known, the encoder configuration can be fetched through the GetVideoEncoderConfiguration command.
-
-
-
-
- The GetAudioSourceConfiguration command fetches the audio source configurations if the audio source configuration token is already known. An
-
-
-
-
- The GetAudioEncoderConfiguration command fetches the encoder configuration if the audio encoder configuration token is known.
-
-
-
-
- The GetVideoAnalyticsConfiguration command fetches the video analytics configuration if the video analytics token is known.
-
-
-
-
- The GetMetadataConfiguration command fetches the metadata configuration if the metadata token is known.
-
-
-
-
- If the audio output configuration token is already known, the output configuration can be fetched through the GetAudioOutputConfiguration command.
-
-
-
-
- If the audio decoder configuration token is already known, the decoder configuration can be fetched through the GetAudioDecoderConfiguration command.
-
-
-
-
-
- This operation lists all the video encoder configurations of the device that are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddVideoEncoderConfiguration command on the media profile. The result will vary depending on the capabilities, configurations and settings in the device.
-
-
-
-
- This operation requests all the video source configurations of the device that are compatible
-with a certain media profile. Each of the returned configurations shall be a valid input
-parameter for the AddVideoSourceConfiguration command on the media profile. The result
-will vary depending on the capabilities, configurations and settings in the device.
-
-
-
-
- This operation requests all audio encoder configurations of a device that are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddAudioSourceConfiguration command on the media profile. The result varies depending on the capabilities, configurations and settings in the device.
-
-
-
-
- This operation requests all audio source configurations of the device that are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddAudioEncoderConfiguration command on the media profile. The result varies depending on the capabilities, configurations and settings in the device.
-
-
-
-
- This operation requests all video analytic configurations of the device that are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddVideoAnalyticsConfiguration command on the media profile. The result varies depending on the capabilities, configurations and settings in the device.
-
-
-
-
- This operation requests all the metadata configurations of the device that are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddMetadataConfiguration command on the media profile. The result varies depending on the capabilities, configurations and settings in the device.
-
-
-
-
- This command lists all audio output configurations of a device that are compatible with a certain media profile. Each returned configuration shall be a valid input for the
-AddAudioOutputConfiguration command.
-
-
-
-
- This operation lists all the audio decoder configurations of the device that are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddAudioDecoderConfiguration command on the media profile.
-
-
-
-
-
- This operation modifies a video source configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. Running streams using this configuration may be immediately updated according to the new settings. The changes are not guaranteed to take effect unless the client requests a new stream URI and restarts any affected stream. NVC methods for changing a running stream are out of scope for this specification.
-
-
-
-
- This operation modifies a video encoder configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. Changes in the Multicast settings shall always be persistent. Running streams using this configuration may be immediately updated according to the new settings. The changes are not guaranteed to take effect unless the client requests a new stream URI and restarts any affected stream. NVC methods for changing a running stream are out of scope for this specification. SessionTimeout is provided as a hint for keeping rtsp session by a device. If necessary the device may adapt parameter values for SessionTimeout elements without returning an error. For the time between keep alive calls the client shall adhere to the timeout value signaled via RTSP.
-
-
-
-
- This operation modifies an audio source configuration. The ForcePersistence flag indicates if
-the changes shall remain after reboot of the device. Running streams using this configuration
-may be immediately updated according to the new settings. The changes are not guaranteed
-to take effect unless the client requests a new stream URI and restarts any affected stream
-NVC methods for changing a running stream are out of scope for this specification.
-
-
-
-
- This operation modifies an audio encoder configuration. The ForcePersistence flag indicates if
-the changes shall remain after reboot of the device. Running streams using this configuration may be immediately updated
-according to the new settings. The changes are not guaranteed to take effect unless the client
-requests a new stream URI and restarts any affected streams. NVC methods for changing a
-running stream are out of scope for this specification.
-
-
-
-
- A video analytics configuration is modified using this command. The ForcePersistence flag
-indicates if the changes shall remain after reboot of the device or not. Running streams using
-this configuration shall be immediately updated according to the new settings. Otherwise
-inconsistencies can occur between the scene description processed by the rule engine and
-the notifications produced by analytics engine and rule engine which reference the very same
-video analytics configuration token.
-
-
-
-
- This operation modifies a metadata configuration. The ForcePersistence flag indicates if the
-changes shall remain after reboot of the device. Changes in the Multicast settings shall
-always be persistent. Running streams using this configuration may be updated immediately
-according to the new settings. The changes are not guaranteed to take effect unless the client
-requests a new stream URI and restarts any affected streams. NVC methods for changing a
-running stream are out of scope for this specification.
-
-
-
-
- This operation modifies an audio output configuration. The ForcePersistence flag indicates if
-the changes shall remain after reboot of the device.
-
-
-
-
- This operation modifies an audio decoder configuration. The ForcePersistence flag indicates if
-the changes shall remain after reboot of the device.
-
-
-
-
-
- This operation returns the available options (supported values and ranges for video source configuration parameters) when the video source parameters are
-reconfigured If a video source configuration is specified, the options shall concern that
-particular configuration. If a media profile is specified, the options shall be compatible with
-that media profile.
-
-
-
-
- This operation returns the available options (supported values and ranges for video encoder
- configuration parameters) when the video encoder parameters are reconfigured.
- For JPEG, MPEG4 and H264 extension elements have been defined that provide additional information. A device must provide the
- XxxOption information for all encodings supported and should additionally provide the corresponding XxxOption2 information.
- This response contains the available video encoder configuration options. If a video encoder configuration is specified,
- the options shall concern that particular configuration. If a media profile is specified, the options shall be
- compatible with that media profile. If no tokens are specified, the options shall be considered generic for the device.
-
-
-
-
-
- This operation returns the available options (supported values and ranges for audio source configuration parameters) when the audio source parameters are
-reconfigured. If an audio source configuration is specified, the options shall concern that
-particular configuration. If a media profile is specified, the options shall be compatible with
-that media profile.
-
-
-
-
- This operation returns the available options (supported values and ranges for audio encoder configuration parameters) when the audio encoder parameters are
-reconfigured.
-
-
-
-
- This operation returns the available options (supported values and ranges for metadata configuration parameters) for changing the metadata configuration.
-
-
-
-
- This operation returns the available options (supported values and ranges for audio output configuration parameters) for configuring an audio output.
-
-
-
-
- This command list the audio decoding capabilities for a given profile and configuration of a
-device.
-
-
-
-
-
- The GetGuaranteedNumberOfVideoEncoderInstances command can be used to request the
-minimum number of guaranteed video encoder instances (applications) per Video Source
-Configuration.
-
-
-
-
-
- This operation requests a URI that can be used to initiate a live media stream using RTSP as
-the control protocol. The returned URI shall remain valid indefinitely even if the profile is
-changed. The ValidUntilConnect, ValidUntilReboot and Timeout Parameter shall be set
-accordingly (ValidUntilConnect=false, ValidUntilReboot=false, timeout=PT0S).
- The correct syntax for the StreamSetup element for these media stream setups defined in 5.1.1 of the streaming specification are as follows:
-
-
RTP unicast over UDP: StreamType = "RTP_unicast", TransportProtocol = "UDP"
-
RTP over RTSP over HTTP over TCP: StreamType = "RTP_unicast", TransportProtocol = "HTTP"
-
RTP over RTSP over TCP: StreamType = "RTP_unicast", TransportProtocol = "RTSP"
-
-
-If a multicast stream is requested the VideoEncoderConfiguration, AudioEncoderConfiguration and MetadataConfiguration element inside the corresponding
-media profile must be configured with valid multicast settings.
-For full compatibility with other ONVIF services a device should not generate Uris longer than
-128 octets.
-
-
-
-
- This command starts multicast streaming using a specified media profile of a device.
-Streaming continues until StopMulticastStreaming is called for the same Profile. The
-streaming shall continue after a reboot of the device until a StopMulticastStreaming request is
-received. The multicast address, port and TTL are configured in the
-VideoEncoderConfiguration, AudioEncoderConfiguration and MetadataConfiguration
-respectively.
-
-
-
-
- This command stop multicast streaming using a specified media profile of a device
-
-
-
-
- Synchronization points allow clients to decode and correctly use all data after the
-synchronization point.
-For example, if a video stream is configured with a large I-frame distance and a client loses a
-single packet, the client does not display video until the next I-frame is transmitted. In such
-cases, the client can request a Synchronization Point which enforces the device to add an I-Frame as soon as possible. Clients can request Synchronization Points for profiles. The device
-shall add synchronization points for all streams associated with this profile.
-Similarly, a synchronization point is used to get an update on full PTZ or event status through
-the metadata stream.
-If a video stream is associated with the profile, an I-frame shall be added to this video stream.
-If a PTZ metadata stream is associated to the profile,
-the PTZ position shall be repeated within the metadata stream.
-
-
-
-
- A client uses the GetSnapshotUri command to obtain a JPEG snapshot from the
-device. The returned URI shall remain valid indefinitely even if the profile is changed. The
-ValidUntilConnect, ValidUntilReboot and Timeout Parameter shall be set accordingly
-(ValidUntilConnect=false, ValidUntilReboot=false, timeout=PT0S). The URI can be used for
-acquiring a JPEG image through a HTTP GET operation. The image encoding will always be
-JPEG regardless of the encoding setting in the media profile. The Jpeg settings
-(like resolution or quality) may be taken from the profile if suitable. The provided
-image will be updated automatically and independent from calls to GetSnapshotUri.
-
-
-
-
- A device returns the information for current video source mode and settable video source modes of specified video source. A device that indicates a capability of VideoSourceModes shall support this command.
-
-
-
-
- SetVideoSourceMode changes the media profile structure relating to video source for the specified video source mode. A device that indicates a capability of VideoSourceModes shall support this command. The behavior after changing the mode is not defined in this specification.
-
-
-
-
-
- Get the OSDs.
-
-
-
-
- Get the OSD.
-
-
-
-
- Get the OSD Options.
-
-
-
-
- Set the OSD
-
-
-
-
- Create the OSD.
-
-
-
-
- Delete the OSD.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/onvif-local.xsd b/onvif/wsdl/onvif-local.xsd
deleted file mode 100644
index 17f722d6e..000000000
--- a/onvif/wsdl/onvif-local.xsd
+++ /dev/null
@@ -1,8578 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- Base class for physical entities like inputs and outputs.
-
-
-
- Unique identifier referencing the physical entity.
-
-
-
-
-
-
- Unique identifier for a physical or logical resource.
- Tokens should be assigned such that they are unique within a device. Tokens must be at least unique within its class.
- Length up to 64 characters.
-
-
-
-
-
-
-
-
- User readable name. Length up to 64 characters.
-
-
-
-
-
-
-
-
- Rectangle defined by lower left corner position and size. Units are pixel.
-
-
-
-
-
-
-
-
-
- Range of a rectangle. The rectangle itself is defined by lower left corner position and size. Units are pixel.
-
-
-
-
- Range of X-axis.
-
-
-
-
- Range of Y-axis.
-
-
-
-
- Range of width.
-
-
-
-
- Range of height.
-
-
-
-
-
-
-
- Range of values greater equal Min value and less equal Max value.
-
-
-
-
-
-
-
-
-
- Range of values greater equal Min value and less equal Max value.
-
-
-
-
-
-
-
-
-
- Range of duration greater equal Min duration and less equal Max duration.
-
-
-
-
-
-
-
-
-
- List of values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical video input.
-
-
-
-
-
-
- Frame rate in frames per second.
-
-
-
-
- Horizontal and vertical resolution
-
-
-
-
- Optional configuration of the image sensor.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional configuration of the image sensor. To be used if imaging service 2.00 is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical audio input.
-
-
-
-
-
-
- number of available audio channels. (1: mono, 2: stereo)
-
-
-
-
-
-
-
-
-
-
-
-
- A media profile consists of a set of media configurations. Media profiles are used by a client
- to configure properties of a media stream from an NVT.
- An NVT shall provide at least one media profile at boot. An NVT should provide “ready to use”
- profiles for the most common media configurations that the device offers.
- A profile consists of a set of interconnected configuration entities. Configurations are provided
- by the NVT and can be either static or created dynamically by the NVT. For example, the
- dynamic configurations can be created by the NVT depending on current available encoding
- resources.
-
-
-
-
-
- User readable name of the profile.
-
-
-
-
- Optional configuration of the Video input.
-
-
-
-
- Optional configuration of the Audio input.
-
-
-
-
- Optional configuration of the Video encoder.
-
-
-
-
- Optional configuration of the Audio encoder.
-
-
-
-
- Optional configuration of the video analytics module and rule engine.
-
-
-
-
- Optional configuration of the pan tilt zoom unit.
-
-
-
-
- Optional configuration of the metadata stream.
-
-
-
-
- Extensions defined in ONVIF 2.0
-
-
-
-
-
- Unique identifier of the profile.
-
-
-
-
- A value of true signals that the profile cannot be deleted. Default is false.
-
-
-
-
-
-
-
-
-
-
- Optional configuration of the Audio output.
-
-
-
-
- Optional configuration of the Audio decoder.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Base type defining the common properties of a configuration.
-
-
-
-
- User readable name. Length up to 64 characters.
-
-
-
-
- Number of internal references currently using this configuration. This parameter is read-only and cannot be changed by a set request. For example the value increases if the configuration is added to a media profile or attached to a PaneConfiguration.
-
-
-
-
-
- Token that uniquely refernces this configuration. Length up to 64 characters.
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the physical input.
-
-
-
-
- Rectangle specifying the Video capturing area. The capturing area shall not be larger than the whole Video source area.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure rotation of captured image.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable Rotation feature.
-
-
-
-
- Optional parameter to configure how much degree of clockwise rotation of image for On mode. Omitting this parameter for On mode means 180 degree rotation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported range for the capturing area.
-
-
-
-
- List of physical inputs.
-
-
-
-
-
-
-
-
-
-
-
-
- Options of parameters for Rotation feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options of Rotate mode parameter.
-
-
-
-
- List of supported degree value for rotation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Used video codec, either Jpeg, H.264 or Mpeg4
-
-
-
-
- Configured video resolution
-
-
-
-
- Relative value for the video quantizers and the quality of the video. A high value within supported quality range means higher quality
-
-
-
-
- Optional element to configure rate control related parameters.
-
-
-
-
- Optional element to configure Mpeg4 related parameters.
-
-
-
-
- Optional element to configure H.264 related parameters.
-
-
-
-
- Defines the multicast settings that could be used for video streaming.
-
-
-
-
- The rtsp session timeout for the related video stream
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Number of the columns of the Video image.
-
-
-
-
- Number of the lines of the Video image.
-
-
-
-
-
-
-
-
-
- Maximum output framerate in fps. If an EncodingInterval is provided the resulting encoded framerate will be reduced by the given factor.
-
-
-
-
- Interval at which images are encoded and transmitted. (A value of 1 means that every frame is encoded, a value of 2 means that every 2nd frame is encoded ...)
-
-
-
-
- the maximum output bitrate in kbps
-
-
-
-
-
-
-
-
-
- Determines the interval in which the I-Frames will be coded. An entry of 1 indicates I-Frames are continuously generated. An entry of 2 indicates that every 2nd image is an I-Frame, and 3 only every 3rd frame, etc. The frames in between are coded as P or B Frames.
-
-
-
-
- the Mpeg4 profile, either simple profile (SP) or advanced simple profile (ASP)
-
-
-
-
-
-
-
-
-
- Group of Video frames length. Determines typically the interval in which the I-Frames will be coded. An entry of 1 indicates I-Frames are continuously generated. An entry of 2 indicates that every 2nd image is an I-Frame, and 3 only every 3rd frame, etc. The frames in between are coded as P or B Frames.
-
-
-
-
- the H.264 profile, either baseline, main, extended or high
-
-
-
-
-
-
-
-
-
- Range of the quality values. A high value means higher quality.
-
-
-
-
- Optional JPEG encoder settings ranges (See also Extension element).
-
-
-
-
- Optional MPEG-4 encoder settings ranges (See also Extension element).
-
-
-
-
- Optional H.264 encoder settings ranges (See also Extension element).
-
-
-
-
-
-
-
-
-
-
-
-
- Optional JPEG encoder settings ranges.
-
-
-
-
- Optional MPEG-4 encoder settings ranges.
-
-
-
-
- Optional H.264 encoder settings ranges.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported image sizes.
-
-
-
-
- Supported frame rate in fps (frames per second).
-
-
-
-
- Supported encoding interval range. The encoding interval corresponds to the number of frames devided by the encoded frames. An encoding interval value of "1" means that all frames are encoded.
-
-
-
-
-
-
-
-
-
-
-
- Supported range of encoded bitrate in kbps.
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported image sizes.
-
-
-
-
- Supported group of Video frames length. This value typically corresponds to the I-Frame distance.
-
-
-
-
- Supported frame rate in fps (frames per second).
-
-
-
-
- Supported encoding interval range. The encoding interval corresponds to the number of frames devided by the encoded frames. An encoding interval value of "1" means that all frames are encoded.
-
-
-
-
- List of supported MPEG-4 profiles.
-
-
-
-
-
-
-
-
-
-
-
- Supported range of encoded bitrate in kbps.
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported image sizes.
-
-
-
-
- Supported group of Video frames length. This value typically corresponds to the I-Frame distance.
-
-
-
-
- Supported frame rate in fps (frames per second).
-
-
-
-
- Supported encoding interval range. The encoding interval corresponds to the number of frames devided by the encoded frames. An encoding interval value of "1" means that all frames are encoded.
-
-
-
-
- List of supported H.264 profiles.
-
-
-
-
-
-
-
-
-
-
-
- Supported range of encoded bitrate in kbps.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the Audio Source the configuration applies to
-
-
-
-
-
-
-
-
-
-
-
-
-
- Tokens of the audio source the configuration can be used for.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Audio codec used for encoding the audio input (either G.711, G.726 or AAC)
-
-
-
-
- The output bitrate in kbps.
-
-
-
-
- The output sample rate in kHz.
-
-
-
-
- Defines the multicast settings that could be used for video streaming.
-
-
-
-
- The rtsp session timeout for the related audio stream
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- list of supported AudioEncoderConfigurations
-
-
-
-
-
-
-
-
-
-
- The enoding used for audio data (either G.711, G.726 or AAC)
-
-
-
-
- List of supported bitrates in kbps for the specified Encoding
-
-
-
-
- List of supported Sample Rates in kHz for the specified Encoding
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- optional element to configure which PTZ related data is to include in the metadata stream
-
-
-
-
-
- Defines whether the streamed metadata will include metadata from the analytics engines (video, cell motion, audio etc.)
-
-
-
-
- Defines the multicast settings that could be used for video streaming.
-
-
-
-
- The rtsp session timeout for the related audio stream
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True if the metadata stream shall contain the PTZ status (IDLE, MOVING or UNKNOWN)
-
-
-
-
- True if the metadata stream shall contain the PTZ position
-
-
-
-
-
-
-
-
- Subcription handling in the same way as base notification subscription.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True if the device is able to stream pan or tilt status information.
-
-
-
-
- True if the device is able to stream zoom status inforamtion.
-
-
-
-
-
- True if the device is able to stream the pan or tilt position.
-
-
-
-
- True if the device is able to stream zoom position information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical video outputs.
-
-
-
-
-
-
-
- Resolution of the display in Pixel.
-
-
-
-
- Refresh rate of the display in Hertz.
-
-
-
-
- Aspect ratio of the display as physical extent of width divided by height.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the Video Output the configuration applies to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the device is able to decode Jpeg streams this element describes the supported codecs and configurations
-
-
-
-
- If the device is able to decode H.264 streams this element describes the supported codecs and configurations
-
-
-
-
- If the device is able to decode Mpeg4 streams this element describes the supported codecs and configurations
-
-
-
-
-
-
-
-
-
-
-
- List of supported H.264 Video Resolutions
-
-
-
-
- List of supported H264 Profiles (either baseline, main, extended or high)
-
-
-
-
- Supported H.264 bitrate range in kbps
-
-
-
-
- Supported H.264 framerate range in fps
-
-
-
-
-
-
-
-
-
-
-
- List of supported Jpeg Video Resolutions
-
-
-
-
- Supported Jpeg bitrate range in kbps
-
-
-
-
- Supported Jpeg framerate range in fps
-
-
-
-
-
-
-
-
-
-
-
- List of supported Mpeg4 Video Resolutions
-
-
-
-
- List of supported Mpeg4 Profiles (either SP or ASP)
-
-
-
-
- Supported Mpeg4 bitrate range in kbps
-
-
-
-
- Supported Mpeg4 framerate range in fps
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical audio outputs.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the phsycial Audio output.
-
-
-
-
-
- An audio channel MAY support different types of audio transmission. While for full duplex
- operation no special handling is required, in half duplex operation the transmission direction
- needs to be switched.
- The optional SendPrimacy parameter inside the AudioOutputConfiguration indicates which
- direction is currently active. An NVC can switch between different modes by setting the
- AudioOutputConfiguration.
- The following modes for the Send-Primacy are defined:
-
www.onvif.org/ver20/HalfDuplex/Server
- The server is allowed to send audio data to the client. The client shall not send
- audio data via the backchannel to the NVT in this mode.
-
www.onvif.org/ver20/HalfDuplex/Client
- The client is allowed to send audio data via the backchannel to the server. The
- NVT shall not send audio data to the client in this mode.
-
www.onvif.org/ver20/HalfDuplex/Auto
- It is up to the device how to deal with sending and receiving audio data.
-
- Acoustic echo cancellation is out of ONVIF scope.
-
-
-
-
- Volume setting of the output. The applicable range is defined via the option AudioOutputOptions.OutputLevelRange.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Tokens of the physical Audio outputs (typically one).
-
-
-
-
-
- An audio channel MAY support different types of audio transmission. While for full duplex
- operation no special handling is required, in half duplex operation the transmission direction
- needs to be switched.
- The optional SendPrimacy parameter inside the AudioOutputConfiguration indicates which
- direction is currently active. An NVC can switch between different modes by setting the
- AudioOutputConfiguration.
- The following modes for the Send-Primacy are defined:
-
www.onvif.org/ver20/HalfDuplex/Server
- The server is allowed to send audio data to the client. The client shall not send
- audio data via the backchannel to the NVT in this mode.
-
www.onvif.org/ver20/HalfDuplex/Client
- The client is allowed to send audio data via the backchannel to the server. The
- NVT shall not send audio data to the client in this mode.
-
www.onvif.org/ver20/HalfDuplex/Auto
- It is up to the device how to deal with sending and receiving audio data.
-
- Acoustic echo cancellation is out of ONVIF scope.
-
-
-
-
- Minimum and maximum level range supported for this Output.
-
-
-
-
-
-
-
-
-
-
-
- The Audio Decoder Configuration does not contain any that parameter to configure the
-decoding .A decoder shall decode every data it receives (according to its capabilities).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the device is able to decode AAC encoded audio this section describes the supported configurations
-
-
-
-
- If the device is able to decode G711 encoded audio this section describes the supported configurations
-
-
-
-
- If the device is able to decode G726 encoded audio this section describes the supported configurations
-
-
-
-
-
-
-
-
-
-
-
- List of supported bitrates in kbps
-
-
-
-
- List of supported sample rates in kHz
-
-
-
-
-
-
-
-
-
-
-
- List of supported bitrates in kbps
-
-
-
-
- List of supported sample rates in kHz
-
-
-
-
-
-
-
-
-
-
-
- List of supported bitrates in kbps
-
-
-
-
- List of supported sample rates in kHz
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The multicast address (if this address is set to 0 no multicast streaming is enaled)
-
-
-
-
- The RTP mutlicast destination port. A device may support RTCP. In this case the port value shall be even to allow the corresponding RTCP stream to be mapped to the next higher (odd) destination port number as defined in the RTSP specification.
-
-
-
-
- In case of IPv6 the TTL value is assumed as the hop limit. Note that for IPV6 and administratively scoped IPv4 multicast the primary use for hop limit / TTL is to prevent packets from (endlessly) circulating and not limiting scope. In these cases the address contains the scope.
-
-
-
-
- Read only property signalling that streaming is persistant. Use the methods StartMulticastStreaming and StopMulticastStreaming to switch its state.
-
-
-
-
-
-
-
-
-
-
-
- Defines if a multicast or unicast stream is requested
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Defines the network protocol for streaming, either UDP=RTP/UDP, RTSP=RTP/RTSP/TCP or HTTP=RTP/RTSP/HTTP/TCP
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Stable Uri to be used for requesting the media stream
-
-
-
-
- Indicates if the Uri is only valid until the connection is established. The value shall be set to "false".
-
-
-
-
- Indicates if the Uri is invalid after a reboot of the device. The value shall be set to "false".
-
-
-
-
- Duration how long the Uri is valid. This parameter shall be set to PT0S to indicate that this stream URI is indefinitely valid even if the profile changes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if the scope is fixed or configurable.
-
-
-
-
- Scope item URI.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not an interface is enabled.
-
-
-
-
- Network interface information
-
-
-
-
- Link configuration.
-
-
-
-
- IPv4 network interface configuration.
-
-
-
-
- IPv6 network interface configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Extension point prepared for future 802.3 configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Configured link settings.
-
-
-
-
- Current active link settings.
-
-
-
-
- Integer indicating interface type, for example: 6 is ethernet.
-
-
-
-
-
-
-
-
-
- Auto negotiation on/off.
-
-
-
-
- Speed.
-
-
-
-
- Duplex type, Half or Full.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- For valid numbers, please refer to http://www.iana.org/assignments/ianaiftype-mib.
-
-
-
-
-
-
-
-
-
- Network interface name, for example eth0.
-
-
-
-
- Network interface MAC address.
-
-
-
-
- Maximum transmission unit.
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv6 is enabled.
-
-
-
-
- IPv6 configuration.
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv4 is enabled.
-
-
-
-
- IPv4 configuration.
-
-
-
-
-
-
-
-
-
- List of manually added IPv4 addresses.
-
-
-
-
- Link local address.
-
-
-
-
- IPv4 address configured by using DHCP.
-
-
-
-
- Indicates whether or not DHCP is used.
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether router advertisment is used.
-
-
-
-
- DHCP configuration.
-
-
-
-
- List of manually entered IPv6 addresses.
-
-
-
-
- List of link local IPv6 addresses.
-
-
-
-
- List of IPv6 addresses configured by using DHCP.
-
-
-
-
- List of IPv6 addresses configured by using router advertisment.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Network protocol type string.
-
-
-
-
- Indicates if the protocol is enabled or not.
-
-
-
-
- The port that is used by the protocol.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Network host type: IPv4, IPv6 or DNS.
-
-
-
-
- IPv4 address.
-
-
-
-
- IPv6 address.
-
-
-
-
- DNS name.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if the address is an IPv4 or IPv6 address.
-
-
-
-
- IPv4 address.
-
-
-
-
- IPv6 address
-
-
-
-
-
-
-
-
-
- IPv4 address
-
-
-
-
- Prefix/submask length
-
-
-
-
-
-
-
-
-
-
-
-
-
- IPv6 address
-
-
-
-
- Prefix/submask length
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether the hostname is obtained from DHCP or not.
-
-
-
-
- Indicates the hostname.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not DNS information is retrieved from DHCP.
-
-
-
-
- Search domain.
-
-
-
-
- List of DNS addresses received from DHCP.
-
-
-
-
- List of manually entered DNS addresses.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if NTP information is to be retrieved by using DHCP.
-
-
-
-
- List of NTP addresses retrieved by using DHCP.
-
-
-
-
- List of manually entered NTP addresses.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Dynamic DNS type.
-
-
-
-
- DNS name.
-
-
-
-
- Time to live.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not an interface is enabled.
-
-
-
-
- Link configuration.
-
-
-
-
- Maximum transmission unit.
-
-
-
-
- IPv4 network interface configuration.
-
-
-
-
- IPv6 network interface configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv6 is enabled.
-
-
-
-
- Indicates whether router advertisment is used.
-
-
-
-
- List of manually added IPv6 addresses.
-
-
-
-
- DHCP configuration.
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv4 is enabled.
-
-
-
-
- List of manually added IPv4 addresses.
-
-
-
-
- Indicates whether or not DHCP is used.
-
-
-
-
-
-
-
-
-
- IPv4 address string.
-
-
-
-
- IPv6 address string.
-
-
-
-
-
-
-
-
-
- Unique identifier of network interface.
-
-
-
-
- Indicates whether the zero-configuration is enabled or not.
-
-
-
-
- The zero-configuration IPv4 address(es)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- According to IEEE802.11-2007 H.4.1 the RSNA PSK consists of 256 bits, or 64 octets when represented in hex
- Either Key or Passphrase shall be given, if both are supplied Key shall be used by the device and Passphrase ignored.
-
-
-
-
-
-
- According to IEEE802.11-2007 H.4.1 a pass-phrase is a sequence of between 8 and 63 ASCII-encoded characters and
- each character in the pass-phrase must have an encoding in the range of 32 to 126 (decimal),inclusive.
- If only Passpharse is supplied the Key shall be derived using the algorithm described in IEEE802.11-2007 section H.4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- See IEEE802.11 7.3.2.25.2 for details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Analytics capabilities
-
-
-
-
- Device capabilities
-
-
-
-
- Event capabilities
-
-
-
-
- Imaging capabilities
-
-
-
-
- Media capabilities
-
-
-
-
- PTZ capabilities
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Analytics service URI.
-
-
-
-
- Indicates whether or not rules are supported.
-
-
-
-
- Indicates whether or not modules are supported.
-
-
-
-
-
-
-
-
-
-
-
- Device service URI.
-
-
-
-
- Network capabilities.
-
-
-
-
- System capabilities.
-
-
-
-
- I/O capabilities.
-
-
-
-
- Security capabilities.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Event service URI.
-
-
-
-
- Indicates whether or not WS Subscription policy is supported.
-
-
-
-
- Indicates whether or not WS Pull Point is supported.
-
-
-
-
- Indicates whether or not WS Pausable Subscription Manager Interface is supported.
-
-
-
-
-
-
-
-
-
-
-
- Number of input connectors.
-
-
-
-
- Number of relay outputs.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Media service URI.
-
-
-
-
- Streaming capabilities.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not RTP multicast is supported.
-
-
-
-
- Indicates whether or not RTP over TCP is supported.
-
-
-
-
- Indicates whether or not RTP/RTSP/TCP is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Maximum number of profiles.
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not IP filtering is supported.
-
-
-
-
- Indicates whether or not zeroconf is supported.
-
-
-
-
- Indicates whether or not IPv6 is supported.
-
-
-
-
- Indicates whether or not is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not TLS 1.1 is supported.
-
-
-
-
- Indicates whether or not TLS 1.2 is supported.
-
-
-
-
- Indicates whether or not onboard key generation is supported.
-
-
-
-
- Indicates whether or not access policy configuration is supported.
-
-
-
-
- Indicates whether or not WS-Security X.509 token is supported.
-
-
-
-
- Indicates whether or not WS-Security SAML token is supported.
-
-
-
-
- Indicates whether or not WS-Security Kerberos token is supported.
-
-
-
-
- Indicates whether or not WS-Security REL token is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- EAP Methods supported by the device. The int values refer to the IANA EAP Registry.
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not WS Discovery resolve requests are supported.
-
-
-
-
- Indicates whether or not WS-Discovery Bye is supported.
-
-
-
-
- Indicates whether or not remote discovery is supported.
-
-
-
-
- Indicates whether or not system backup is supported.
-
-
-
-
- Indicates whether or not system logging is supported.
-
-
-
-
- Indicates whether or not firmware upgrade is supported.
-
-
-
-
- Indicates supported ONVIF version(s).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Major version number.
-
-
-
-
- Two digit minor version number (e.g. X.0.1 maps to "01" and X.2.1 maps to "21" where X stands for Major version number).
-
-
-
-
-
-
-
-
-
- Imaging service URI.
-
-
-
-
-
-
-
-
-
-
- PTZ service URI.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indication that the SetLayout command supports only predefined layouts.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The address of the replay service.
-
-
-
-
-
-
-
-
-
-
-
- The address of the receiver service.
-
-
-
-
- Indicates whether the device can receive RTP multicast streams.
-
-
-
-
- Indicates whether the device can receive RTP/TCP streams
-
-
-
-
- Indicates whether the device can receive RTP/RTSP/TCP streams.
-
-
-
-
- The maximum number of receivers supported by the device.
-
-
-
-
- The maximum allowed length for RTSP URIs.
-
-
-
-
-
-
-
-
-
-
-
-
- Obsolete property.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enumeration describing the available system log modes.
-
-
-
-
- Indicates that a system log is requested.
-
-
-
-
- Indicates that a access log is requested.
-
-
-
-
-
-
-
-
-
- The log information as attachment data.
-
-
-
-
- The log information as character data.
-
-
-
-
-
-
-
-
-
- The support information as attachment data.
-
-
-
-
- The support information as character data.
-
-
-
-
-
-
-
-
-
- base64 encoded binary data.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enumeration describing the available factory default modes.
-
-
-
-
- Indicates that a hard factory default is requested.
-
-
-
-
- Indicates that a soft factory default is requested.
-
-
-
-
-
-
-
-
-
- Indicates that the date and time are set manually.
-
-
-
-
- Indicates that the date and time are set through NTP
-
-
-
-
-
-
-
- General date time inforamtion returned by the GetSystemDateTime method.
-
-
-
-
- Indicates if the time is set manully or through NTP.
-
-
-
-
- Informative indicator whether daylight savings is currently on/off.
-
-
-
-
- Timezone information in Posix format.
-
-
-
-
- Current system date and time in UTC format. This field is mandatory since version 2.0.
-
-
-
-
- Date and time in local format.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Range is 1 to 12.
-
-
-
-
- Range is 1 to 31.
-
-
-
-
-
-
-
-
-
- Range is 0 to 23.
-
-
-
-
- Range is 0 to 59.
-
-
-
-
- Range is 0 to 61 (typically 59).
-
-
-
-
-
-
-
-
- The TZ format is specified by POSIX, please refer to POSIX 1003.1 section 8.3
- Example: Europe, Paris TZ=CET-1CEST,M3.5.0/2,M10.5.0/3
- CET = designation for standard time when daylight saving is not in force
- -1 = offset in hours = negative so 1 hour east of Greenwich meridian
- CEST = designation when daylight saving is in force ("Central European Summer Time")
- , = no offset number between code and comma, so default to one hour ahead for daylight saving
- M3.5.0 = when daylight saving starts = the last Sunday in March (the "5th" week means the last in the month)
- /2, = the local time when the switch occurs = 2 a.m. in this case
- M10.5.0 = when daylight saving ends = the last Sunday in October.
- /3, = the local time when the switch occurs = 3 a.m. in this case
-
-
-
-
-
- Posix timezone string.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Username string.
-
-
-
-
- Password string.
-
-
-
-
- User level string.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Certificate id.
-
-
-
-
- base64 encoded DER representation of certificate.
-
-
-
-
-
-
-
-
-
- Certificate id.
-
-
-
-
- Indicates whether or not a certificate is used in a HTTPS configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Validity Range is from "NotBefore" to "NotAfter"; the corresponding DateTimeRange is from "From" to "Until"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- EAP Method type as defined in IANA EAP Registry.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Confgiuration information for TLS Method.
-
-
-
-
- Password for those EAP Methods that require a password. The password shall never be returned on a get method.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'Bistable' or 'Monostable'
-
-
Bistable – After setting the state, the relay remains in this state.
-
Monostable – After setting the state, the relay returns to its idle state after the specified time.
-
-
-
-
-
-
- Time after which the relay returns to its idle state if it is in monostable mode. If the Mode field is set to bistable mode the value of the parameter can be ignored.
-
-
-
-
-
- 'open' or 'closed'
-
-
'open' means that the relay is open when the relay state is set to 'inactive' through the trigger command and closed when the state is set to 'active' through the same command.
-
'closed' means that the relay is closed when the relay state is set to 'inactive' through the trigger command and open when the state is set to 'active' through the same command.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A unique identifier that is used to reference PTZ Nodes.
-
-
-
-
-
-
- A list of Coordinate Systems available for the PTZ Node. For each Coordinate System, the PTZ Node MUST specify its allowed range.
-
-
-
-
-
-
- All preset operations MUST be available for this PTZ Node if one preset is supported.
-
-
-
-
-
-
- A boolean operator specifying the availability of a home position. If set to true, the Home Position Operations MUST be available for this PTZ Node.
-
-
-
-
-
-
- A list of supported Auxiliary commands. If the list is not empty, the Auxiliary Operations MUST be available for this PTZ Node.
-
-
-
-
-
-
-
-
- Indication whether the HomePosition of a Node is fixed or it can be changed via the SetHomePosition command.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Detail of supported Preset Tour feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates number of preset tours that can be created. Required preset tour operations shall be available for this PTZ Node if one or more preset tour is supported.
-
-
-
-
- Indicates which preset tour operations are available for this PTZ Node.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A mandatory reference to the PTZ Node that the PTZ Configuration belongs to.
-
-
-
-
-
-
- If the PTZ Node supports absolute Pan/Tilt movements, it shall specify one Absolute Pan/Tilt Position Space as default.
-
-
-
-
-
-
- If the PTZ Node supports absolute zoom movements, it shall specify one Absolute Zoom Position Space as default.
-
-
-
-
-
-
- If the PTZ Node supports relative Pan/Tilt movements, it shall specify one RelativePan/Tilt Translation Space as default.
-
-
-
-
-
-
- If the PTZ Node supports relative zoom movements, it shall specify one Relative Zoom Translation Space as default.
-
-
-
-
-
-
- If the PTZ Node supports continuous Pan/Tilt movements, it shall specify one Continuous Pan/Tilt Velocity Space as default.
-
-
-
-
-
-
- If the PTZ Node supports continuous zoom movements, it shall specify one Continuous Zoom Velocity Space as default.
-
-
-
-
-
-
- If the PTZ Node supports absolute or relative PTZ movements, it shall specify corresponding default Pan/Tilt and Zoom speeds.
-
-
-
-
-
-
- If the PTZ Node supports continuous movements, it shall specify a default timeout, after which the movement stops.
-
-
-
-
-
-
- The Pan/Tilt limits element should be present for a PTZ Node that supports an absolute Pan/Tilt. If the element is present it signals the support for configurable Pan/Tilt limits. If limits are enabled, the Pan/Tilt movements shall always stay within the specified range. The Pan/Tilt limits are disabled by setting the limits to –INF or +INF.
-
-
-
-
-
-
- The Zoom limits element should be present for a PTZ Node that supports absolute zoom. If the element is present it signals the supports for configurable Zoom limits. If limits are enabled the zoom movements shall always stay within the specified range. The Zoom limits are disabled by settings the limits to -INF and +INF.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure PT Control Direction related features.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure related parameters for E-Flip.
-
-
-
-
- Optional element to configure related parameters for reversing of PT Control Direction.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable E-Flip feature.
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable Reverse feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A list of supported coordinate systems including their range limitations.
-
-
-
-
-
-
- A timeout Range within which Timeouts are accepted by the PTZ Node.
-
-
-
-
-
-
- Supported options for PT Direction Control.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options for EFlip feature.
-
-
-
-
- Supported options for Reverse feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Options of EFlip mode parameter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Options of Reverse mode parameter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A range of pan tilt limits.
-
-
-
-
-
-
-
-
-
-
-
- A range of zoom limit
-
-
-
-
-
-
-
-
-
-
-
- The Generic Pan/Tilt Position space is provided by every PTZ node that supports absolute Pan/Tilt, since it does not relate to a specific physical range.
- Instead, the range should be defined as the full range of the PTZ unit normalized to the range -1 to 1 resulting in the following space description.
-
-
-
-
-
-
- The Generic Zoom Position Space is provided by every PTZ node that supports absolute Zoom, since it does not relate to a specific physical range.
- Instead, the range should be defined as the full range of the Zoom normalized to the range 0 (wide) to 1 (tele).
- There is no assumption about how the generic zoom range is mapped to magnification, FOV or other physical zoom dimension.
-
-
-
-
-
-
- The Generic Pan/Tilt translation space is provided by every PTZ node that supports relative Pan/Tilt, since it does not relate to a specific physical range.
- Instead, the range should be defined as the full positive and negative translation range of the PTZ unit normalized to the range -1 to 1,
- where positive translation would mean clockwise rotation or movement in right/up direction resulting in the following space description.
-
-
-
-
-
-
- The Generic Zoom Translation Space is provided by every PTZ node that supports relative Zoom, since it does not relate to a specific physical range.
- Instead, the corresponding absolute range should be defined as the full positive and negative translation range of the Zoom normalized to the range -1 to1,
- where a positive translation maps to a movement in TELE direction. The translation is signed to indicate direction (negative is to wide, positive is to tele).
- There is no assumption about how the generic zoom range is mapped to magnification, FOV or other physical zoom dimension. This results in the following space description.
-
-
-
-
-
-
- The generic Pan/Tilt velocity space shall be provided by every PTZ node, since it does not relate to a specific physical range.
- Instead, the range should be defined as a range of the PTZ unit’s speed normalized to the range -1 to 1, where a positive velocity would map to clockwise
- rotation or movement in the right/up direction. A signed speed can be independently specified for the pan and tilt component resulting in the following space description.
-
-
-
-
-
-
- The generic zoom velocity space specifies a zoom factor velocity without knowing the underlying physical model. The range should be normalized from -1 to 1,
- where a positive velocity would map to TELE direction. A generic zoom velocity space description resembles the following.
-
-
-
-
-
-
- The speed space specifies the speed for a Pan/Tilt movement when moving to an absolute position or to a relative translation.
- In contrast to the velocity spaces, speed spaces do not contain any directional information. The speed of a combined Pan/Tilt
- movement is represented by a single non-negative scalar value.
-
-
-
-
-
-
- The speed space specifies the speed for a Zoom movement when moving to an absolute position or to a relative translation.
- In contrast to the velocity spaces, speed spaces do not contain any directional information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A URI of coordinate systems.
-
-
-
-
-
-
- A range of x-axis.
-
-
-
-
-
-
- A range of y-axis.
-
-
-
-
-
-
-
-
-
-
-
- A URI of coordinate systems.
-
-
-
-
-
-
- A range of x-axis.
-
-
-
-
-
-
-
-
-
-
-
-
- Pan/tilt coordinate space selector. The following options are defined:
-
-
-
-
-
-
-
-
-
- Pan and tilt position. The x component corresponds to pan and the y component to tilt.
-
-
-
-
-
- A zoom position.
-
-
-
-
-
-
-
-
-
-
- Pan and tilt speed. The x component corresponds to pan and the y component to tilt. If omitted in a request, the current (if any) PanTilt movement should not be affected.
-
-
-
-
-
- A zoom speed. If omitted in a request, the current (if any) Zoom movement should not be affected.
-
-
-
-
-
-
-
-
-
-
-
- Specifies the absolute position of the PTZ unit together with the Space references. The default absolute spaces of the corresponding PTZ configuration MUST be referenced within the Position element.
-
-
-
-
-
-
- Indicates if the Pan/Tilt/Zoom device unit is currently moving, idle or in an unknown state.
-
-
-
-
-
-
- States a current PTZ error.
-
-
-
-
-
-
- Specifies the UTC time when this status was generated.
-
-
-
-
-
-
-
-
-
-
-
-
-
- A list of preset position name.
-
-
-
-
-
-
- A list of preset position.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Readable name of the preset tour.
-
-
-
-
- Read only parameters to indicate the status of the preset tour.
-
-
-
-
- Auto Start flag of the preset tour. True allows the preset tour to be activated always.
-
-
-
-
- Parameters to specify the detail behavior of the preset tour.
-
-
-
-
- A list of detail of touring spots including preset positions.
-
-
-
-
-
-
- Unique identifier of this preset tour.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Detail definition of preset position of the tour spot.
-
-
-
-
- Optional parameter to specify Pan/Tilt and Zoom speed on moving toward this tour spot.
-
-
-
-
- Optional parameter to specify time duration of staying on this tour sport.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Option to specify the preset position with Preset Token defined in advance.
-
-
-
-
- Option to specify the preset position with the home position of this PTZ Node. "False" to this parameter shall be treated as an invalid argument.
-
-
-
-
- Option to specify the preset position with vector of PTZ node directly.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates state of this preset tour by Idle/Touring/Paused.
-
-
-
-
- Indicates a tour spot currently staying.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional parameter to specify how many times the preset tour is recurred.
-
-
-
-
- Optional parameter to specify how long time duration the preset tour is recurred.
-
-
-
-
- Optional parameter to choose which direction the preset tour goes. Forward shall be chosen in case it is omitted.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not the AutoStart is supported.
-
-
-
-
- Supported options for Preset Tour Starting Condition.
-
-
-
-
- Supported options for Preset Tour Spot.
-
-
-
-
-
-
-
-
-
-
-
- Supported options for detail definition of preset position of the tour spot.
-
-
-
-
- Supported range of stay time for a tour spot.
-
-
-
-
-
-
-
-
-
-
-
- A list of available Preset Tokens for tour spots.
-
-
-
-
- An option to indicate Home postion for tour spots.
-
-
-
-
- Supported range of Pan and Tilt for tour spots.
-
-
-
-
- Supported range of Zoom for a tour spot.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported range of Recurring Time.
-
-
-
-
- Supported range of Recurring Duration.
-
-
-
-
- Supported options for Direction of Preset Tour.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Status of focus position.
-
-
-
-
-
-
- Status of focus MoveStatus.
-
-
-
-
-
-
- Error status of focus.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to set autofocus near limit (unit: meter).
-
-
-
-
- Parameter to set autofocus far limit (unit: meter).
-If set to 0.0, infinity will be used.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enabled/disabled BLC mode (on/off).
-
-
-
-
- Image brightness (unit unspecified).
-
-
-
-
- Color saturation of the image (unit unspecified).
-
-
-
-
- Contrast of the image (unit unspecified).
-
-
-
-
- Exposure mode of the device.
-
-
-
-
- Focus configuration.
-
-
-
-
- Infrared Cutoff Filter settings.
-
-
-
-
- Sharpness of the Video image.
-
-
-
-
- WDR settings.
-
-
-
-
- White balance settings.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Exposure Mode
-
-
Auto – Enabled the exposure algorithm on the NVT.
-
Manual – Disabled exposure algorithm on the NVT.
-
-
-
-
-
-
-
- The exposure priority mode (low noise/framerate).
-
-
-
-
-
-
- Rectangular exposure mask.
-
-
-
-
-
-
- Minimum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- The fixed exposure time used by the image sensor (μs).
-
-
-
-
-
-
- The fixed gain used by the image sensor (dB).
-
-
-
-
-
-
- The fixed attenuation of input light affected by the iris (dB). 0dB maps to a fully opened iris.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- White dynamic range (on/off)
-
-
-
-
-
-
- Optional level parameter (unitless)
-
-
-
-
-
-
-
-
- Enumeration describing the available backlight compenstation modes.
-
-
-
-
- Backlight compensation is disabled.
-
-
-
-
- Backlight compensation is enabled.
-
-
-
-
-
-
-
-
-
- Backlight compensation mode (on/off).
-
-
-
-
- Optional level parameter (unit unspecified).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters for the absolute focus control.
-
-
-
-
-
-
- Parameters for the relative focus control.
-
-
-
-
-
-
- Parameter for the continuous focus control.
-
-
-
-
-
-
-
-
-
-
-
- Position parameter for the absolute focus control.
-
-
-
-
-
-
- Speed parameter for the absolute focus control.
-
-
-
-
-
-
-
-
-
-
-
- Distance parameter for the relative focus control.
-
-
-
-
-
-
- Speed parameter for the relative focus control.
-
-
-
-
-
-
-
-
-
-
-
- Speed parameter for the Continuous focus control.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the position.
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the distance.
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Auto whitebalancing mode (auto/manual).
-
-
-
-
- Rgain (unitless).
-
-
-
-
- Bgain (unitless).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Status of focus.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Status of focus position.
-
-
-
-
-
-
- Status of focus MoveStatus.
-
-
-
-
-
-
- Error status of focus.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Type describing the ImagingSettings of a VideoSource. The supported options and ranges can be obtained via the GetOptions command.
-
-
-
-
- Enabled/disabled BLC mode (on/off).
-
-
-
-
- Image brightness (unit unspecified).
-
-
-
-
- Color saturation of the image (unit unspecified).
-
-
-
-
- Contrast of the image (unit unspecified).
-
-
-
-
- Exposure mode of the device.
-
-
-
-
- Focus configuration.
-
-
-
-
- Infrared Cutoff Filter settings.
-
-
-
-
- Sharpness of the Video image.
-
-
-
-
- WDR settings.
-
-
-
-
- White balance settings.
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure Image Stabilization feature.
-
-
-
-
-
-
-
-
-
-
- An optional parameter applied to only auto mode to adjust timing of toggling Ir cut filter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable Image Stabilization feature.
-
-
-
-
- Optional level parameter (unit unspecified)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Specifies which boundaries to automatically toggle Ir cut filter following parameters are applied to. Its options shall be chosen from tt:IrCutFilterAutoBoundaryType.
-
-
-
-
- Adjusts boundary exposure level for toggling Ir cut filter to on/off specified with unitless normalized value from +1.0 to -1.0. Zero is default and -1.0 is the darkest adjustment (Unitless).
-
-
-
-
- Delay time of toggling Ir cut filter to on/off after crossing of the boundary exposure levels.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Type describing whether WDR mode is enabled or disabled (on/off).
-
-
-
-
- Wide dynamic range mode (on/off).
-
-
-
-
- Optional level parameter (unit unspecified).
-
-
-
-
-
-
-
- Type describing whether BLC mode is enabled or disabled (on/off).
-
-
-
-
- Backlight compensation mode (on/off).
-
-
-
-
- Optional level parameter (unit unspecified).
-
-
-
-
-
-
-
- Type describing the exposure settings.
-
-
-
-
-
- Exposure Mode
-
-
Auto – Enabled the exposure algorithm on the device.
-
Manual – Disabled exposure algorithm on the device.
-
-
-
-
-
-
-
- The exposure priority mode (low noise/framerate).
-
-
-
-
-
-
- Rectangular exposure mask.
-
-
-
-
-
-
- Minimum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- The fixed exposure time used by the image sensor (μs).
-
-
-
-
-
-
- The fixed gain used by the image sensor (dB).
-
-
-
-
-
-
- The fixed attenuation of input light affected by the iris (dB). 0dB maps to a fully opened iris.
-
-
-
-
-
-
-
-
-
-
-
- Valid range of Backlight Compensation.
-
-
-
-
-
-
- Valid range of Brightness.
-
-
-
-
-
-
- Valid range of Color Saturation.
-
-
-
-
-
-
- Valid range of Contrast.
-
-
-
-
-
-
- Valid range of Exposure.
-
-
-
-
-
-
- Valid range of Focus.
-
-
-
-
-
-
- Valid range of IrCutFilterModes.
-
-
-
-
-
-
- Valid range of Sharpness.
-
-
-
-
-
-
- Valid range of WideDynamicRange.
-
-
-
-
-
-
- Valid range of WhiteBalance.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Options of parameters for Image Stabilization feature.
-
-
-
-
-
-
-
-
-
-
- Options of parameters for adjustment of Ir cut filter auto mode.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options of Image Stabilization mode parameter.
-
-
-
-
- Valid range of the Image Stabilization.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options of boundary types for adjustment of Ir cut filter auto mode. The opptions shall be chosen from tt:IrCutFilterAutoBoundaryType.
-
-
-
-
- Indicates whether or not boundary offset for toggling Ir cut filter is supported.
-
-
-
-
- Supported range of delay time for toggling Ir cut filter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'ON' or 'OFF'
-
-
-
-
-
-
- Level range of BacklightCompensation.
-
-
-
-
-
-
-
-
-
-
-
- Exposure Mode
-
-
Auto – Enabled the exposure algorithm on the device.
-
Manual – Disabled exposure algorithm on the device.
-
-
-
-
-
-
-
- The exposure priority mode (low noise/framerate).
-
-
-
-
-
-
- Valid range of the Minimum ExposureTime.
-
-
-
-
-
-
- Valid range of the Maximum ExposureTime.
-
-
-
-
-
-
- Valid range of the Minimum Gain.
-
-
-
-
-
-
- Valid range of the Maximum Gain.
-
-
-
-
-
-
- Valid range of the Minimum Iris.
-
-
-
-
-
-
- Valid range of the Maximum Iris.
-
-
-
-
-
-
- Valid range of the ExposureTime.
-
-
-
-
-
-
- Valid range of the Gain.
-
-
-
-
-
-
- Valid range of the Iris.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges for the absolute control.
-
-
-
-
-
-
- Valid ranges for the relative control.
-
-
-
-
-
-
- Valid ranges for the continuous control.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the distance.
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
- 'AUTO' or 'MANUAL'
-
-
-
-
-
-
- Rgain (unitless).
-
-
-
-
-
-
- Bgain (unitless).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Mode of auto fucus.
-
-
AUTO
-
MANUAL
-
-
-
-
-
-
-
- Parameter to set autofocus near limit (unit: meter).
-
-
-
-
- Parameter to set autofocus far limit (unit: meter).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Mode of WhiteBalance.
-
-
-
-
-
-
-
- Valid range of DefaultSpeed.
-
-
-
-
-
-
- Valid range of NearLimit.
-
-
-
-
-
-
- Valid range of FarLimit.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token value pairs that triggered this message. Typically only one item is present.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of parameters according to the corresponding ItemListDescription.
- Each item in the list shall have a unique name.
-
-
-
-
-
- Value name pair as defined by the corresponding description.
-
-
-
-
- Item name.
-
-
-
-
- Item value. The type is defined in the corresponding description.
-
-
-
-
-
-
- Complex value structure.
-
-
-
-
-
- XML tree contiaing the element value as defined in the corresponding description.
-
-
-
-
-
- Item name.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Set of tokens producing this message. The list may only contain SimpleItemDescription items.
- The set of tokens identify the component within the WS-Endpoint, which is responsible for the producing the message.
- For analytics events the token set shall include the VideoSourceConfigurationToken, the VideoAnalyticsConfigurationToken
- and the name of the analytics module or rule.
-
-
-
-
-
- Describes optional message payload parameters that may be used as key. E.g. object IDs of tracked objects are conveyed as key.
-
-
-
-
- Describes the payload of the message.
-
-
-
-
-
-
- Must be set to true when the described Message relates to a property. An alternative term of "property" is a "state" in contrast to a pure event, which contains relevant information for only a single point in time. Default is false.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Describes a list of items. Each item in the list shall have a unique name.
- The list is designed as linear structure without optional or unbounded elements.
- Use ElementItems only when complex structures are inevitable.
-
-
-
-
-
- Description of a simple item. The type must be of cathegory simpleType (xs:string, xs:integer, xs:float, ...).
-
-
-
-
- Item name. Must be unique within a list.
-
-
-
-
-
-
-
-
- Description of a complex type. The Type must reference a defined type.
-
-
-
-
-
- Item name. Must be unique within a list.
-
-
-
-
- The type of the item. The Type must reference a defined type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Object Class Type
-
-
-
-
- A likelihood/probability that the corresponding object belongs to this class. The sum of the likelihoods shall NOT exceed 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Number of columns of the cell grid (x dimension)
-
-
-
-
- Number of rows of the cell grid (y dimension)
-
-
-
-
- A “1” denotes a cell where motion is detected and a “0” an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of configuration parameters as defined in the correspding description.
-
-
-
-
-
- Name of the configuration.
-
-
-
-
- Type of the configuration represented by a unique QName. The Type characterizes a ConfigDescription defining the Parameters.
-
-
-
-
-
-
-
-
-
- List describing the configuration parameters. The names of the parameters must be unique. If possible SimpleItems
- should be used to transport the information to ease parsing of dynamically defined messages by a client
- application.
-
-
-
-
-
-
- The analytics modules and rule engine produce Events, which must be listed within the Analytics Module Description. In order to do so
- the structure of the Message is defined and consists of three groups: Source, Key, and Data. It is recommended to use SimpleItemDescriptions wherever applicable.
- The name of all Items must be unique within all Items contained in any group of this Message.
- Depending on the component multiple parameters or none may be needed to identify the component uniquely.
-
-
-
-
-
-
-
-
-
- The ParentTopic labels the message (e.g. "nn:RuleEngine/LineCrossing"). The real message can extend the ParentTopic
- by for example the name of the instaniated rule (e.g. "nn:RuleEngine/LineCrossing/corssMyFirstLine").
- Even without knowing the complete topic name, the subscriber will be able to distiguish the
- messages produced by different rule instances of the same type via the Source fields of the message.
- There the name of the rule instance, which produced the message, must be listed.
-
-
-
-
-
-
-
-
-
-
-
-
- XML Type of the Configuration (e.g. "tt::LineDetector").
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Lists the location of all schemas that are referenced in the rules.
-
-
-
-
- List of rules supported by the Video Analytics configuration..
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- It optionally contains a list of URLs that provide the location of schema files.
- These schema files describe the types and elements used in the analytics module descriptions.
- If the analytics module descriptions reference types or elements of the ONVIF schema file,
- the ONVIF schema file MUST be explicitly listed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains Polygon configuration for rule parameters
-
-
-
-
-
-
-
-
-
-
-
- Contains array of Polyline
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains PolylineArray configuration data
-
-
-
-
-
-
-
-
-
-
-
- Motion Expression data structure contains motion expression which is based on Scene Descriptor schema with XPATH syntax. The Type argument could allow introduction of different dialects
-
-
-
-
-
-
-
-
-
-
-
-
- Contains Rule MotionExpression configuration
-
-
-
-
-
-
-
-
-
-
-
- Mapping of the cell grid to the Video frame. The cell grid is starting from the upper left corner and x dimension is going from left to right and the y dimension from up to down.
-
-
-
-
-
-
- Number of columns of the cell grid (x dimension)
-
-
-
-
- Number of rows of the cell grid (y dimension)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Configuration of the streaming and coding settings of a Video window.
-
-
-
-
- Optional name of the pane configuration.
-
-
-
-
- If the device has audio outputs, this element contains a pointer to the audio output that is associated with the pane. A client
-can retrieve the available audio outputs of a device using the GetAudioOutputs command of the DeviceIO service.
-
-
-
-
- If the device has audio sources, this element contains a pointer to the audio source that is associated with this pane.
-The audio connection from a decoder device to the NVT is established using the backchannel mechanism. A client can retrieve the available audio sources of a device using the GetAudioSources command of the
-DeviceIO service.
-
-
-
-
- The configuration of the audio encoder including codec, bitrate
-and sample rate.
-
-
-
-
- A pointer to a Receiver that has the necessary information to receive
- data from a Transmitter. This Receiver can be connected and the network video decoder displays the received data on the specified outputs. A client can retrieve the available Receivers using the
- GetReceivers command of the Receiver Service.
-
-
-
-
- A unique identifier in the display device.
-
-
-
-
-
-
-
-
-
- A pane layout describes one Video window of a display. It links a pane configuration to a region of the screen.
-
-
-
-
- Reference to the configuration of the streaming and coding parameters.
-
-
-
-
- Describes the location and size of the area on the monitor. The area coordinate values are espressed in normalized units [-1.0, 1.0].
-
-
-
-
-
-
-
-
-
- A layout describes a set of Video windows that are displayed simultaniously on a display.
-
-
-
-
- List of panes assembling the display layout.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type contains the Audio and Video coding capabilities of a display service.
-
-
-
-
- If the device supports audio encoding this section describes the supported codecs and their configuration.
-
-
-
-
- If the device supports audio decoding this section describes the supported codecs and their settings.
-
-
-
-
- This section describes the supported video codesc and their configuration.
-
-
-
-
-
-
-
-
-
- The options supported for a display layout.
-
-
-
-
- Lists the possible Pane Layouts of the Video Output
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Description of a pane layout describing a complete display layout.
-
-
-
-
- List of areas assembling a layout. Coordinate values are in the range [-1.0, 1.0].
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Description of a receiver, including its token and configuration.
-
-
-
-
-
- Unique identifier of the receiver.
-
-
-
-
- Describes the configuration of the receiver.
-
-
-
-
-
-
-
-
-
-
- Describes the configuration of a receiver.
-
-
-
-
-
- The following connection modes are defined:
-
-
-
-
- Details of the URI to which the receiver should connect.
-
-
-
-
- Stream connection parameters.
-
-
-
-
-
-
-
-
-
-
- Specifies a receiver connection mode.
-
-
-
-
-
- The receiver connects on demand, as required by consumers of the media streams.
-
-
-
-
- The receiver attempts to maintain a persistent connection to the configured endpoint.
-
-
-
-
- The receiver does not attempt to connect.
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
- Specifies the current connection state of the receiver.
-
-
-
-
-
- The receiver is not connected.
-
-
-
-
- The receiver is attempting to connect.
-
-
-
-
- The receiver is connected.
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
- Contains information about a receiver's current state.
-
-
-
-
-
- The connection state of the receiver may have one of the following states:
-
-
-
-
- Indicates whether or not the receiver was created automatically.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The earliest point in time where there is recorded data on the device.
-
-
-
-
- The most recent point in time where there is recorded data on the device.
-
-
-
-
- The device contains this many recordings.
-
-
-
-
-
-
-
-
-
- A structure for defining a limited scope when searching in recorded data.
-
-
-
-
- A list of sources that are included in the scope. If this list is included, only data from one of these sources shall be searched.
-
-
-
-
- A list of recordings that are included in the scope. If this list is included, only data from one of these recordings shall be searched.
-
-
-
-
- An xpath expression used to specify what recordings to search. Only those recordings with an RecordingInformation structure that matches the filter shall be searched.
-
-
-
-
- Extension point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The lower boundary of the PTZ volume to look for.
-
-
-
-
- The upper boundary of the PTZ volume to look for.
-
-
-
-
- If true, search for when entering the specified PTZ volume.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A RecordingInformation structure for each found recording matching the search.
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A FindEventResult structure for each found event matching the search.
-
-
-
-
-
-
-
-
-
- The recording where this event was found. Empty string if no recording is associated with this event.
-
-
-
-
- A reference to the track where this event was found. Empty string if no track is associated with this event.
-
-
-
-
- The time when the event occured.
-
-
-
-
-
- The description of the event.
-
-
-
-
- If true, indicates that the event is a virtual event generated for this particular search session to give the state of a property at the start time of the search.
-
-
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A FindPTZPositionResult structure for each found PTZ position matching the search.
-
-
-
-
-
-
-
-
-
- A reference to the recording containing the PTZ position.
-
-
-
-
- A reference to the metadata track containing the PTZ position.
-
-
-
-
- The time when the PTZ position was valid.
-
-
-
-
- The PTZ position.
-
-
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A FindMetadataResult structure for each found set of Metadata matching the search.
-
-
-
-
-
-
-
-
-
- A reference to the recording containing the metadata.
-
-
-
-
- A reference to the metadata track containing the matching metadata.
-
-
-
-
- The point in time when the matching metadata occurs in the metadata track.
-
-
-
-
-
-
-
-
-
-
-
- The search is queued and not yet started.
-
-
-
-
- The search is underway and not yet completed.
-
-
-
-
- The search has been completed and no new results will be found.
-
-
-
-
- The state of the search is unknown. (This is not a valid response from GetSearchState.)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Information about the source of the recording. This gives a description of where the data in the recording comes from. Since a single
- recording is intended to record related material, there is just one source. It is indicates the physical location or the
- major data source for the recording. Currently the recordingconfiguration cannot describe each individual data source.
-
-
-
-
-
-
-
-
- Basic information about the track. Note that a track may represent a single contiguous time span or consist of multiple slices.
-
-
-
-
-
-
-
-
-
-
-
- A set of informative desciptions of a data source. The Search searvice allows a client to filter on recordings based on information in this structure.
-
-
-
-
-
-
- Identifier for the source chosen by the client that creates the structure.
- This identifier is opaque to the device. Clients may use any type of URI for this field. A device shall support at least 128 characters.
-
-
-
-
- Informative user readable name of the source, e.g. "Camera23". A device shall support at least 20 characters.
-
-
-
-
- Informative description of the physical location of the source, e.g. the coordinates on a map.
-
-
-
-
- Informative description of the source.
-
-
-
-
- URI provided by the service supplying data to be recorded. A device shall support at least 128 characters.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
-
-
- Type of the track: "Video", "Audio" or "Metadata".
- The track shall only be able to hold data of that type.
-
-
-
-
- Informative description of the contents of the track.
-
-
-
-
- The start date and time of the oldest recorded data in the track.
-
-
-
-
- The stop date and time of the newest recorded data in the track.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Placeholder for future extension.
-
-
-
-
-
-
-
- A set of media attributes valid for a recording at a point in time or for a time interval.
-
-
-
-
- A reference to the recording that has these attributes.
-
-
-
-
- A set of attributes for each track.
-
-
-
-
- The attributes are valid from this point in time in the recording.
-
-
-
-
- The attributes are valid until this point in time in the recording. Can be equal to 'From' to indicate that the attributes are only known to be valid for this particular point in time.
-
-
-
-
-
-
-
-
-
-
-
- The basic information about the track. Note that a track may represent a single contiguous time span or consist of multiple slices.
-
-
-
-
- If the track is a video track, exactly one of this structure shall be present and contain the video attributes.
-
-
-
-
- If the track is an audio track, exactly one of this structure shall be present and contain the audio attributes.
-
-
-
-
- If the track is an metadata track, exactly one of this structure shall be present and contain the metadata attributes.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Average bitrate in kbps.
-
-
-
-
- The width of the video in pixels.
-
-
-
-
- The height of the video in pixels.
-
-
-
-
- Used video codec, either Jpeg, H.264 or Mpeg4
-
-
-
-
- Average framerate in frames per second.
-
-
-
-
-
-
-
-
-
-
-
- The bitrate in kbps.
-
-
-
-
- Audio codec used for encoding the audio (either G.711, G.726 or AAC)
-
-
-
-
- The sample rate in kHz.
-
-
-
-
-
-
-
-
-
-
-
- Indicates that there can be PTZ data in the metadata track in the specified time interval.
-
-
-
-
- Indicates that there can be analytics data in the metadata track in the specified time interval.
-
-
-
-
- Indicates that there can be notifications in the metadata track in the specified time interval.
-
-
-
-
-
-
- List of all PTZ spaces active for recording. Note that events are only recorded on position changes and the actual point of recording may not necessarily contain an event of the specified type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Information about the source of the recording.
-
-
-
-
- Informative description of the source.
-
-
-
-
- Sspecifies the maximum time that data in any track within the
- recording shall be stored. The device shall delete any data older than the maximum retention
- time. Such data shall not be accessible anymore. If the MaximumRetentionPeriod is set to 0,
- the device shall not limit the retention time of stored data, except by resource constraints.
- Whatever the value of MaximumRetentionTime, the device may automatically delete
- recordings to free up storage space for new recordings.
-
-
-
-
-
-
-
-
-
-
-
- Type of the track. It shall be equal to the strings “Video”,
- “Audio” or “Metadata”. The track shall only be able to hold data of that type.
-
-
-
-
- Informative description of the track.
-
-
-
-
-
-
-
-
-
-
-
- Token of the recording.
-
-
-
-
- Configuration of the recording.
-
-
-
-
- List of tracks.
-
-
-
-
-
-
-
-
-
-
-
- Configuration of a track.
-
-
-
-
-
-
-
-
-
-
- Token of the track.
-
-
-
-
- Configuration of the track.
-
-
-
-
-
-
-
-
-
-
-
- Identifies the recording to which this job shall store the received data.
-
-
-
-
- The mode of the job. If it is idle, nothing shall happen. If it is active, the device shall try
- to obtain data from the receivers. A client shall use GetRecordingJobState to determine if data transfer is really taking place.
- The only valid values for Mode shall be “Idle” and “Active”.
-
-
-
-
- This shall be a non-negative number. If there are multiple recording jobs that store data to
- the same track, the device will only store the data for the recording job with the highest
- priority. The priority is specified per recording job, but the device shall determine the priority
- of each track individually. If there are two recording jobs with the same priority, the device
- shall record the data corresponding to the recording job that was activated the latest.
-
-
-
-
- Source of the recording.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This field shall be a reference to the source of the data. The type of the source
- is determined by the attribute Type in the SourceToken structure. If Type is
- http://www.onvif.org/ver10/schema/Receiver, the token is a ReceiverReference. In this case
- the device shall receive the data over the network. If Type is
- http://www.onvif.org/ver10/schema/Profile, the token identifies a media profile, instructing the
- device to obtain data from a profile that exists on the local device.
-
-
-
-
- If this field is TRUE, and if the SourceToken is omitted, the device
- shall create a receiver object (through the receiver service) and assign the
- ReceiverReference to the SourceToken field. When retrieving the RecordingJobConfiguration
- from the device, the AutoCreateReceiver field shall never be present.
-
-
-
-
- List of tracks associated with the recording.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the received RTSP stream contains multiple tracks of the same type, the
- SourceTag differentiates between those Tracks. This field can be ignored in case of recording a local source.
-
-
-
-
- The destination is the tracktoken of the track to which the device shall store the
- received data.
-
-
-
-
-
-
-
-
-
-
-
- Identification of the recording that the recording job records to.
-
-
-
-
- Holds the aggregated state over the whole RecordingJobInformation structure.
-
-
-
-
- Identifies the data source of the recording job.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Identifies the data source of the recording job.
-
-
-
-
- Holds the aggregated state over all substructures of RecordingJobStateSource.
-
-
-
-
- List of track items.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Identifies the track of the data source that provides the data.
-
-
-
-
- Indicates the destination track.
-
-
-
-
- Optionally holds an implementation defined string value that describes the error.
- The string should be in the English language.
-
-
-
-
- Provides the job state of the track. The valid
- values of state shall be “Idle”, “Active” and “Error”. If state equals “Error”, the Error field may be filled in with an implementation defined value.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Configuration parameters for the replay service.
-
-
-
-
-
- The RTSP session timeout.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the analytics engine (AnalyticsEngine) being controlled.
-
-
-
-
- Token of the analytics engine configuration (VideoAnalyticsConfiguration) in effect.
-
-
-
-
- Tokens of the input (AnalyticsEngineInput) configuration applied.
-
-
-
-
- Tokens of the receiver providing media input data. The order of ReceiverToken shall exactly match the order of InputToken.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
-
- Token of the control object whose status is requested.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Action Engine Event Payload data structure contains the information about the ONVIF command invocations. Since this event could be generated by other or proprietary actions, the command invocation specific fields are defined as optional and additional extension mechanism is provided for future or additional action definitions.
-
-
-
-
- Request Message
-
-
-
-
- Response Message
-
-
-
-
- Fault Message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AudioClassType acceptable values are;
- gun_shot, scream, glass_breaking, tire_screech
-
-
-
-
-
-
-
-
-
- Indicates audio class label
-
-
-
-
- A likelihood/probability that the corresponding audio event belongs to this class. The sum of the likelihoods shall NOT exceed 1
-
-
-
-
-
-
-
-
-
-
-
- Array of audio class label and class probability
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- For OSD position type, following are the pre-defined:
UpperLeft
-
UpperRight
-
LowerLeft
-
LowerRight
-
Custom
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The value range of "Transparent" could be defined by vendors only should follow this rule: the minimum value means non-transparent and the maximum value maens fully transparent.
-
-
-
-
-
-
-
-
-
-
-
-
-
- The following OSD Text Type are defined:
-
Plain - The Plain type means the OSD is shown as a text string which defined in the "PlainText" item.
-
Date - The Date type means the OSD is shown as a date, format of which should be present in the "DateFormat" item.
-
Time - The Time type means the OSD is shown as a time, format of which should be present in the "TimeFormat" item.
-
DateAndTime - The DateAndTime type means the OSD is shown as date and time, format of which should be present in the "DateFormat" and the "TimeFormat" item.
-
-
-
-
-
-
-
- List of supported OSD date formats. This element shall be present when the value of Type field has Date or DateAndTime. The following DateFormat are defined:
-
M/d/yyyy - e.g. 3/6/2013
-
MM/dd/yyyy - e.g. 03/06/2013
-
dd/MM/yyyy - e.g. 06/03/2013
-
yyyy/MM/dd - e.g. 2013/03/06
-
yyyy-MM-dd - e.g. 2013-06-03
-
dddd, MMMM dd, yyyy - e.g. Wednesday, March 06, 2013
-
MMMM dd, yyyy - e.g. March 06, 2013
-
dd MMMM, yyyy - e.g. 06 March, 2013
-
-
-
-
-
-
-
- List of supported OSD time formats. This element shall be present when the value of Type field has Time or DateAndTime. The following TimeFormat are defined:
-
h:mm:ss tt - e.g. 2:14:21 PM
-
hh:mm:ss tt - e.g. 02:14:21 PM
-
H:mm:ss - e.g. 14:14:21
-
HH:mm:ss - e.g. 14:14:21
-
-
-
-
-
-
- Font size of the text in pt.
-
-
-
-
- Font color of the text.
-
-
-
-
- Background color of the text.
-
-
-
-
- The content of text to be displayed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The URI of the image which to be displayed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Describe the option of the color supported. Either list each color or define the range of color value. The following values are acceptable for Colourspace attribute.
-
-
-
-
-
-
- List the supported color.
-
-
-
-
- Define the rang of color supported.
-
-
-
-
-
-
-
-
-
- Describe the option of the color and its transparency.
-
-
-
-
- Optional list of supported colors.
-
-
-
-
- Range of the transparent level. Larger means more tranparent.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported OSD text type. When a device indicates the supported number relating to Text type in MaximumNumberOfOSDs, the type shall be presented.
-
-
-
-
- Range of the font size value.
-
-
-
-
- List of supported date format.
-
-
-
-
- List of supported time format.
-
-
-
-
- List of supported font color.
-
-
-
-
- List of supported background color.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of avaiable uris of image.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the video source configuration.
-
-
-
-
- Type of OSD.
-
-
-
-
- Position configuration of OSD.
-
-
-
-
- Text configuration of OSD. It shall be present when the value of Type field is Text.
-
-
-
-
- Image configuration of OSD. It shall be present when the value of Type field is Image
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The maximum number of OSD configurations supported for the specificate video source configuration. If a device limits the number of instances by OSDType, it should indicate the supported number via the related attribute.
-
-
-
-
- List supported type of OSD configuration. When a device indicates the supported number for each types in MaximumNumberOfOSDs, related type shall be presented. A device shall return Option element relating to listed type.
-
-
-
-
- List available OSD position type. Following are the pre-defined:
UpperLeft
-
UpperRight
-
LowerLeft
-
LowerRight
-
Custom
-
-
-
-
-
- Option of the OSD text configuration. This element shall be returned if the device is signaling the support for Text.
-
-
-
-
- Option of the OSD image configuration. This element shall be returned if the device is signaling the support for Image.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/onvif.xsd b/onvif/wsdl/onvif.xsd
deleted file mode 100644
index 252204e2f..000000000
--- a/onvif/wsdl/onvif.xsd
+++ /dev/null
@@ -1,8559 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- Base class for physical entities like inputs and outputs.
-
-
-
- Unique identifier referencing the physical entity.
-
-
-
-
-
-
- Unique identifier for a physical or logical resource.
- Tokens should be assigned such that they are unique within a device. Tokens must be at least unique within its class.
- Length up to 64 characters.
-
-
-
-
-
-
-
-
- User readable name. Length up to 64 characters.
-
-
-
-
-
-
-
-
- Rectangle defined by lower left corner position and size. Units are pixel.
-
-
-
-
-
-
-
-
-
- Range of a rectangle. The rectangle itself is defined by lower left corner position and size. Units are pixel.
-
-
-
-
- Range of X-axis.
-
-
-
-
- Range of Y-axis.
-
-
-
-
- Range of width.
-
-
-
-
- Range of height.
-
-
-
-
-
-
-
- Range of values greater equal Min value and less equal Max value.
-
-
-
-
-
-
-
-
-
- Range of values greater equal Min value and less equal Max value.
-
-
-
-
-
-
-
-
-
- Range of duration greater equal Min duration and less equal Max duration.
-
-
-
-
-
-
-
-
-
- List of values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical video input.
-
-
-
-
-
-
- Frame rate in frames per second.
-
-
-
-
- Horizontal and vertical resolution
-
-
-
-
- Optional configuration of the image sensor.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional configuration of the image sensor. To be used if imaging service 2.00 is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical audio input.
-
-
-
-
-
-
- number of available audio channels. (1: mono, 2: stereo)
-
-
-
-
-
-
-
-
-
-
-
-
- A media profile consists of a set of media configurations. Media profiles are used by a client
- to configure properties of a media stream from an NVT.
- An NVT shall provide at least one media profile at boot. An NVT should provide “ready to use”
- profiles for the most common media configurations that the device offers.
- A profile consists of a set of interconnected configuration entities. Configurations are provided
- by the NVT and can be either static or created dynamically by the NVT. For example, the
- dynamic configurations can be created by the NVT depending on current available encoding
- resources.
-
-
-
-
-
- User readable name of the profile.
-
-
-
-
- Optional configuration of the Video input.
-
-
-
-
- Optional configuration of the Audio input.
-
-
-
-
- Optional configuration of the Video encoder.
-
-
-
-
- Optional configuration of the Audio encoder.
-
-
-
-
- Optional configuration of the video analytics module and rule engine.
-
-
-
-
- Optional configuration of the pan tilt zoom unit.
-
-
-
-
- Optional configuration of the metadata stream.
-
-
-
-
- Extensions defined in ONVIF 2.0
-
-
-
-
-
- Unique identifier of the profile.
-
-
-
-
- A value of true signals that the profile cannot be deleted. Default is false.
-
-
-
-
-
-
-
-
-
-
- Optional configuration of the Audio output.
-
-
-
-
- Optional configuration of the Audio decoder.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Base type defining the common properties of a configuration.
-
-
-
-
- User readable name. Length up to 64 characters.
-
-
-
-
- Number of internal references currently using this configuration. This parameter is read-only and cannot be changed by a set request. For example the value increases if the configuration is added to a media profile or attached to a PaneConfiguration.
-
-
-
-
-
- Token that uniquely refernces this configuration. Length up to 64 characters.
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the physical input.
-
-
-
-
- Rectangle specifying the Video capturing area. The capturing area shall not be larger than the whole Video source area.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure rotation of captured image.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable Rotation feature.
-
-
-
-
- Optional parameter to configure how much degree of clockwise rotation of image for On mode. Omitting this parameter for On mode means 180 degree rotation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported range for the capturing area.
-
-
-
-
- List of physical inputs.
-
-
-
-
-
-
-
-
-
-
-
-
- Options of parameters for Rotation feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options of Rotate mode parameter.
-
-
-
-
- List of supported degree value for rotation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Used video codec, either Jpeg, H.264 or Mpeg4
-
-
-
-
- Configured video resolution
-
-
-
-
- Relative value for the video quantizers and the quality of the video. A high value within supported quality range means higher quality
-
-
-
-
- Optional element to configure rate control related parameters.
-
-
-
-
- Optional element to configure Mpeg4 related parameters.
-
-
-
-
- Optional element to configure H.264 related parameters.
-
-
-
-
- Defines the multicast settings that could be used for video streaming.
-
-
-
-
- The rtsp session timeout for the related video stream
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Number of the columns of the Video image.
-
-
-
-
- Number of the lines of the Video image.
-
-
-
-
-
-
-
-
-
- Maximum output framerate in fps. If an EncodingInterval is provided the resulting encoded framerate will be reduced by the given factor.
-
-
-
-
- Interval at which images are encoded and transmitted. (A value of 1 means that every frame is encoded, a value of 2 means that every 2nd frame is encoded ...)
-
-
-
-
- the maximum output bitrate in kbps
-
-
-
-
-
-
-
-
-
- Determines the interval in which the I-Frames will be coded. An entry of 1 indicates I-Frames are continuously generated. An entry of 2 indicates that every 2nd image is an I-Frame, and 3 only every 3rd frame, etc. The frames in between are coded as P or B Frames.
-
-
-
-
- the Mpeg4 profile, either simple profile (SP) or advanced simple profile (ASP)
-
-
-
-
-
-
-
-
-
- Group of Video frames length. Determines typically the interval in which the I-Frames will be coded. An entry of 1 indicates I-Frames are continuously generated. An entry of 2 indicates that every 2nd image is an I-Frame, and 3 only every 3rd frame, etc. The frames in between are coded as P or B Frames.
-
-
-
-
- the H.264 profile, either baseline, main, extended or high
-
-
-
-
-
-
-
-
-
- Range of the quality values. A high value means higher quality.
-
-
-
-
- Optional JPEG encoder settings ranges (See also Extension element).
-
-
-
-
- Optional MPEG-4 encoder settings ranges (See also Extension element).
-
-
-
-
- Optional H.264 encoder settings ranges (See also Extension element).
-
-
-
-
-
-
-
-
-
-
-
-
- Optional JPEG encoder settings ranges.
-
-
-
-
- Optional MPEG-4 encoder settings ranges.
-
-
-
-
- Optional H.264 encoder settings ranges.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported image sizes.
-
-
-
-
- Supported frame rate in fps (frames per second).
-
-
-
-
- Supported encoding interval range. The encoding interval corresponds to the number of frames devided by the encoded frames. An encoding interval value of "1" means that all frames are encoded.
-
-
-
-
-
-
-
-
-
-
-
- Supported range of encoded bitrate in kbps.
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported image sizes.
-
-
-
-
- Supported group of Video frames length. This value typically corresponds to the I-Frame distance.
-
-
-
-
- Supported frame rate in fps (frames per second).
-
-
-
-
- Supported encoding interval range. The encoding interval corresponds to the number of frames devided by the encoded frames. An encoding interval value of "1" means that all frames are encoded.
-
-
-
-
- List of supported MPEG-4 profiles.
-
-
-
-
-
-
-
-
-
-
-
- Supported range of encoded bitrate in kbps.
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported image sizes.
-
-
-
-
- Supported group of Video frames length. This value typically corresponds to the I-Frame distance.
-
-
-
-
- Supported frame rate in fps (frames per second).
-
-
-
-
- Supported encoding interval range. The encoding interval corresponds to the number of frames devided by the encoded frames. An encoding interval value of "1" means that all frames are encoded.
-
-
-
-
- List of supported H.264 profiles.
-
-
-
-
-
-
-
-
-
-
-
- Supported range of encoded bitrate in kbps.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the Audio Source the configuration applies to
-
-
-
-
-
-
-
-
-
-
-
-
-
- Tokens of the audio source the configuration can be used for.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Audio codec used for encoding the audio input (either G.711, G.726 or AAC)
-
-
-
-
- The output bitrate in kbps.
-
-
-
-
- The output sample rate in kHz.
-
-
-
-
- Defines the multicast settings that could be used for video streaming.
-
-
-
-
- The rtsp session timeout for the related audio stream
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- list of supported AudioEncoderConfigurations
-
-
-
-
-
-
-
-
-
-
- The enoding used for audio data (either G.711, G.726 or AAC)
-
-
-
-
- List of supported bitrates in kbps for the specified Encoding
-
-
-
-
- List of supported Sample Rates in kHz for the specified Encoding
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- optional element to configure which PTZ related data is to include in the metadata stream
-
-
-
-
- Optional element to configure the streaming of events. A client might be interested in receiving all,
- none or some of the events produced by the device:
-
To get all events: Include the Events element but do not include a filter.
-
To get no events: Do not include the Events element.
-
To get only some events: Include the Events element and include a filter in the element.
-
-
-
-
-
-
- Defines whether the streamed metadata will include metadata from the analytics engines (video, cell motion, audio etc.)
-
-
-
-
- Defines the multicast settings that could be used for video streaming.
-
-
-
-
- The rtsp session timeout for the related audio stream
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True if the metadata stream shall contain the PTZ status (IDLE, MOVING or UNKNOWN)
-
-
-
-
- True if the metadata stream shall contain the PTZ position
-
-
-
-
-
-
-
-
- Subcription handling in the same way as base notification subscription.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True if the device is able to stream pan or tilt status information.
-
-
-
-
- True if the device is able to stream zoom status inforamtion.
-
-
-
-
-
- True if the device is able to stream the pan or tilt position.
-
-
-
-
- True if the device is able to stream zoom position information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical video outputs.
-
-
-
-
-
-
-
- Resolution of the display in Pixel.
-
-
-
-
- Refresh rate of the display in Hertz.
-
-
-
-
- Aspect ratio of the display as physical extent of width divided by height.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the Video Output the configuration applies to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the device is able to decode Jpeg streams this element describes the supported codecs and configurations
-
-
-
-
- If the device is able to decode H.264 streams this element describes the supported codecs and configurations
-
-
-
-
- If the device is able to decode Mpeg4 streams this element describes the supported codecs and configurations
-
-
-
-
-
-
-
-
-
-
-
- List of supported H.264 Video Resolutions
-
-
-
-
- List of supported H264 Profiles (either baseline, main, extended or high)
-
-
-
-
- Supported H.264 bitrate range in kbps
-
-
-
-
- Supported H.264 framerate range in fps
-
-
-
-
-
-
-
-
-
-
-
- List of supported Jpeg Video Resolutions
-
-
-
-
- Supported Jpeg bitrate range in kbps
-
-
-
-
- Supported Jpeg framerate range in fps
-
-
-
-
-
-
-
-
-
-
-
- List of supported Mpeg4 Video Resolutions
-
-
-
-
- List of supported Mpeg4 Profiles (either SP or ASP)
-
-
-
-
- Supported Mpeg4 bitrate range in kbps
-
-
-
-
- Supported Mpeg4 framerate range in fps
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Representation of a physical audio outputs.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the phsycial Audio output.
-
-
-
-
-
- An audio channel MAY support different types of audio transmission. While for full duplex
- operation no special handling is required, in half duplex operation the transmission direction
- needs to be switched.
- The optional SendPrimacy parameter inside the AudioOutputConfiguration indicates which
- direction is currently active. An NVC can switch between different modes by setting the
- AudioOutputConfiguration.
- The following modes for the Send-Primacy are defined:
-
www.onvif.org/ver20/HalfDuplex/Server
- The server is allowed to send audio data to the client. The client shall not send
- audio data via the backchannel to the NVT in this mode.
-
www.onvif.org/ver20/HalfDuplex/Client
- The client is allowed to send audio data via the backchannel to the server. The
- NVT shall not send audio data to the client in this mode.
-
www.onvif.org/ver20/HalfDuplex/Auto
- It is up to the device how to deal with sending and receiving audio data.
-
- Acoustic echo cancellation is out of ONVIF scope.
-
-
-
-
- Volume setting of the output. The applicable range is defined via the option AudioOutputOptions.OutputLevelRange.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Tokens of the physical Audio outputs (typically one).
-
-
-
-
-
- An audio channel MAY support different types of audio transmission. While for full duplex
- operation no special handling is required, in half duplex operation the transmission direction
- needs to be switched.
- The optional SendPrimacy parameter inside the AudioOutputConfiguration indicates which
- direction is currently active. An NVC can switch between different modes by setting the
- AudioOutputConfiguration.
- The following modes for the Send-Primacy are defined:
-
www.onvif.org/ver20/HalfDuplex/Server
- The server is allowed to send audio data to the client. The client shall not send
- audio data via the backchannel to the NVT in this mode.
-
www.onvif.org/ver20/HalfDuplex/Client
- The client is allowed to send audio data via the backchannel to the server. The
- NVT shall not send audio data to the client in this mode.
-
www.onvif.org/ver20/HalfDuplex/Auto
- It is up to the device how to deal with sending and receiving audio data.
-
- Acoustic echo cancellation is out of ONVIF scope.
-
-
-
-
- Minimum and maximum level range supported for this Output.
-
-
-
-
-
-
-
-
-
-
-
- The Audio Decoder Configuration does not contain any that parameter to configure the
-decoding .A decoder shall decode every data it receives (according to its capabilities).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the device is able to decode AAC encoded audio this section describes the supported configurations
-
-
-
-
- If the device is able to decode G711 encoded audio this section describes the supported configurations
-
-
-
-
- If the device is able to decode G726 encoded audio this section describes the supported configurations
-
-
-
-
-
-
-
-
-
-
-
- List of supported bitrates in kbps
-
-
-
-
- List of supported sample rates in kHz
-
-
-
-
-
-
-
-
-
-
-
- List of supported bitrates in kbps
-
-
-
-
- List of supported sample rates in kHz
-
-
-
-
-
-
-
-
-
-
-
- List of supported bitrates in kbps
-
-
-
-
- List of supported sample rates in kHz
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The multicast address (if this address is set to 0 no multicast streaming is enaled)
-
-
-
-
- The RTP mutlicast destination port. A device may support RTCP. In this case the port value shall be even to allow the corresponding RTCP stream to be mapped to the next higher (odd) destination port number as defined in the RTSP specification.
-
-
-
-
- In case of IPv6 the TTL value is assumed as the hop limit. Note that for IPV6 and administratively scoped IPv4 multicast the primary use for hop limit / TTL is to prevent packets from (endlessly) circulating and not limiting scope. In these cases the address contains the scope.
-
-
-
-
- Read only property signalling that streaming is persistant. Use the methods StartMulticastStreaming and StopMulticastStreaming to switch its state.
-
-
-
-
-
-
-
-
-
-
-
- Defines if a multicast or unicast stream is requested
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Defines the network protocol for streaming, either UDP=RTP/UDP, RTSP=RTP/RTSP/TCP or HTTP=RTP/RTSP/HTTP/TCP
-
-
-
-
- Optional element to describe further tunnel options. This element is normally not needed
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Stable Uri to be used for requesting the media stream
-
-
-
-
- Indicates if the Uri is only valid until the connection is established. The value shall be set to "false".
-
-
-
-
- Indicates if the Uri is invalid after a reboot of the device. The value shall be set to "false".
-
-
-
-
- Duration how long the Uri is valid. This parameter shall be set to PT0S to indicate that this stream URI is indefinitely valid even if the profile changes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if the scope is fixed or configurable.
-
-
-
-
- Scope item URI.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not an interface is enabled.
-
-
-
-
- Network interface information
-
-
-
-
- Link configuration.
-
-
-
-
- IPv4 network interface configuration.
-
-
-
-
- IPv6 network interface configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Extension point prepared for future 802.3 configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Configured link settings.
-
-
-
-
- Current active link settings.
-
-
-
-
- Integer indicating interface type, for example: 6 is ethernet.
-
-
-
-
-
-
-
-
-
- Auto negotiation on/off.
-
-
-
-
- Speed.
-
-
-
-
- Duplex type, Half or Full.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- For valid numbers, please refer to http://www.iana.org/assignments/ianaiftype-mib.
-
-
-
-
-
-
-
-
-
- Network interface name, for example eth0.
-
-
-
-
- Network interface MAC address.
-
-
-
-
- Maximum transmission unit.
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv6 is enabled.
-
-
-
-
- IPv6 configuration.
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv4 is enabled.
-
-
-
-
- IPv4 configuration.
-
-
-
-
-
-
-
-
-
- List of manually added IPv4 addresses.
-
-
-
-
- Link local address.
-
-
-
-
- IPv4 address configured by using DHCP.
-
-
-
-
- Indicates whether or not DHCP is used.
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether router advertisment is used.
-
-
-
-
- DHCP configuration.
-
-
-
-
- List of manually entered IPv6 addresses.
-
-
-
-
- List of link local IPv6 addresses.
-
-
-
-
- List of IPv6 addresses configured by using DHCP.
-
-
-
-
- List of IPv6 addresses configured by using router advertisment.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Network protocol type string.
-
-
-
-
- Indicates if the protocol is enabled or not.
-
-
-
-
- The port that is used by the protocol.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Network host type: IPv4, IPv6 or DNS.
-
-
-
-
- IPv4 address.
-
-
-
-
- IPv6 address.
-
-
-
-
- DNS name.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if the address is an IPv4 or IPv6 address.
-
-
-
-
- IPv4 address.
-
-
-
-
- IPv6 address
-
-
-
-
-
-
-
-
-
- IPv4 address
-
-
-
-
- Prefix/submask length
-
-
-
-
-
-
-
-
-
-
-
-
-
- IPv6 address
-
-
-
-
- Prefix/submask length
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether the hostname is obtained from DHCP or not.
-
-
-
-
- Indicates the hostname.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not DNS information is retrieved from DHCP.
-
-
-
-
- Search domain.
-
-
-
-
- List of DNS addresses received from DHCP.
-
-
-
-
- List of manually entered DNS addresses.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates if NTP information is to be retrieved by using DHCP.
-
-
-
-
- List of NTP addresses retrieved by using DHCP.
-
-
-
-
- List of manually entered NTP addresses.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Dynamic DNS type.
-
-
-
-
- DNS name.
-
-
-
-
- Time to live.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not an interface is enabled.
-
-
-
-
- Link configuration.
-
-
-
-
- Maximum transmission unit.
-
-
-
-
- IPv4 network interface configuration.
-
-
-
-
- IPv6 network interface configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv6 is enabled.
-
-
-
-
- Indicates whether router advertisment is used.
-
-
-
-
- List of manually added IPv6 addresses.
-
-
-
-
- DHCP configuration.
-
-
-
-
-
-
-
-
-
- Indicates whether or not IPv4 is enabled.
-
-
-
-
- List of manually added IPv4 addresses.
-
-
-
-
- Indicates whether or not DHCP is used.
-
-
-
-
-
-
-
-
-
- IPv4 address string.
-
-
-
-
- IPv6 address string.
-
-
-
-
-
-
-
-
-
- Unique identifier of network interface.
-
-
-
-
- Indicates whether the zero-configuration is enabled or not.
-
-
-
-
- The zero-configuration IPv4 address(es)
-
-
-
-
-
-
-
-
-
-
-
-
- Optional array holding the configuration for the second and possibly further interfaces.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- According to IEEE802.11-2007 H.4.1 the RSNA PSK consists of 256 bits, or 64 octets when represented in hex
- Either Key or Passphrase shall be given, if both are supplied Key shall be used by the device and Passphrase ignored.
-
-
-
-
-
-
- According to IEEE802.11-2007 H.4.1 a pass-phrase is a sequence of between 8 and 63 ASCII-encoded characters and
- each character in the pass-phrase must have an encoding in the range of 32 to 126 (decimal),inclusive.
- If only Passpharse is supplied the Key shall be derived using the algorithm described in IEEE802.11-2007 section H.4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- See IEEE802.11 7.3.2.25.2 for details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Analytics capabilities
-
-
-
-
- Device capabilities
-
-
-
-
- Event capabilities
-
-
-
-
- Imaging capabilities
-
-
-
-
- Media capabilities
-
-
-
-
- PTZ capabilities
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Analytics service URI.
-
-
-
-
- Indicates whether or not rules are supported.
-
-
-
-
- Indicates whether or not modules are supported.
-
-
-
-
-
-
-
-
-
-
-
- Device service URI.
-
-
-
-
- Network capabilities.
-
-
-
-
- System capabilities.
-
-
-
-
- I/O capabilities.
-
-
-
-
- Security capabilities.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Event service URI.
-
-
-
-
- Indicates whether or not WS Subscription policy is supported.
-
-
-
-
- Indicates whether or not WS Pull Point is supported.
-
-
-
-
- Indicates whether or not WS Pausable Subscription Manager Interface is supported.
-
-
-
-
-
-
-
-
-
-
-
- Number of input connectors.
-
-
-
-
- Number of relay outputs.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Media service URI.
-
-
-
-
- Streaming capabilities.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not RTP multicast is supported.
-
-
-
-
- Indicates whether or not RTP over TCP is supported.
-
-
-
-
- Indicates whether or not RTP/RTSP/TCP is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Maximum number of profiles.
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not IP filtering is supported.
-
-
-
-
- Indicates whether or not zeroconf is supported.
-
-
-
-
- Indicates whether or not IPv6 is supported.
-
-
-
-
- Indicates whether or not is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not TLS 1.1 is supported.
-
-
-
-
- Indicates whether or not TLS 1.2 is supported.
-
-
-
-
- Indicates whether or not onboard key generation is supported.
-
-
-
-
- Indicates whether or not access policy configuration is supported.
-
-
-
-
- Indicates whether or not WS-Security X.509 token is supported.
-
-
-
-
- Indicates whether or not WS-Security SAML token is supported.
-
-
-
-
- Indicates whether or not WS-Security Kerberos token is supported.
-
-
-
-
- Indicates whether or not WS-Security REL token is supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- EAP Methods supported by the device. The int values refer to the IANA EAP Registry.
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not WS Discovery resolve requests are supported.
-
-
-
-
- Indicates whether or not WS-Discovery Bye is supported.
-
-
-
-
- Indicates whether or not remote discovery is supported.
-
-
-
-
- Indicates whether or not system backup is supported.
-
-
-
-
- Indicates whether or not system logging is supported.
-
-
-
-
- Indicates whether or not firmware upgrade is supported.
-
-
-
-
- Indicates supported ONVIF version(s).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Major version number.
-
-
-
-
- Two digit minor version number (e.g. X.0.1 maps to "01" and X.2.1 maps to "21" where X stands for Major version number).
-
-
-
-
-
-
-
-
-
- Imaging service URI.
-
-
-
-
-
-
-
-
-
-
- PTZ service URI.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indication that the SetLayout command supports only predefined layouts.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The address of the replay service.
-
-
-
-
-
-
-
-
-
-
-
- The address of the receiver service.
-
-
-
-
- Indicates whether the device can receive RTP multicast streams.
-
-
-
-
- Indicates whether the device can receive RTP/TCP streams
-
-
-
-
- Indicates whether the device can receive RTP/RTSP/TCP streams.
-
-
-
-
- The maximum number of receivers supported by the device.
-
-
-
-
- The maximum allowed length for RTSP URIs.
-
-
-
-
-
-
-
-
-
-
-
-
- Obsolete property.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enumeration describing the available system log modes.
-
-
-
-
- Indicates that a system log is requested.
-
-
-
-
- Indicates that a access log is requested.
-
-
-
-
-
-
-
-
-
- The log information as attachment data.
-
-
-
-
- The log information as character data.
-
-
-
-
-
-
-
-
-
- The support information as attachment data.
-
-
-
-
- The support information as character data.
-
-
-
-
-
-
-
-
-
- base64 encoded binary data.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enumeration describing the available factory default modes.
-
-
-
-
- Indicates that a hard factory default is requested.
-
-
-
-
- Indicates that a soft factory default is requested.
-
-
-
-
-
-
-
-
-
- Indicates that the date and time are set manually.
-
-
-
-
- Indicates that the date and time are set through NTP
-
-
-
-
-
-
-
- General date time inforamtion returned by the GetSystemDateTime method.
-
-
-
-
- Indicates if the time is set manully or through NTP.
-
-
-
-
- Informative indicator whether daylight savings is currently on/off.
-
-
-
-
- Timezone information in Posix format.
-
-
-
-
- Current system date and time in UTC format. This field is mandatory since version 2.0.
-
-
-
-
- Date and time in local format.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Range is 1 to 12.
-
-
-
-
- Range is 1 to 31.
-
-
-
-
-
-
-
-
-
- Range is 0 to 23.
-
-
-
-
- Range is 0 to 59.
-
-
-
-
- Range is 0 to 61 (typically 59).
-
-
-
-
-
-
-
-
- The TZ format is specified by POSIX, please refer to POSIX 1003.1 section 8.3
- Example: Europe, Paris TZ=CET-1CEST,M3.5.0/2,M10.5.0/3
- CET = designation for standard time when daylight saving is not in force
- -1 = offset in hours = negative so 1 hour east of Greenwich meridian
- CEST = designation when daylight saving is in force ("Central European Summer Time")
- , = no offset number between code and comma, so default to one hour ahead for daylight saving
- M3.5.0 = when daylight saving starts = the last Sunday in March (the "5th" week means the last in the month)
- /2, = the local time when the switch occurs = 2 a.m. in this case
- M10.5.0 = when daylight saving ends = the last Sunday in October.
- /3, = the local time when the switch occurs = 3 a.m. in this case
-
-
-
-
-
- Posix timezone string.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Username string.
-
-
-
-
- Password string.
-
-
-
-
- User level string.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Certificate id.
-
-
-
-
- base64 encoded DER representation of certificate.
-
-
-
-
-
-
-
-
-
- Certificate id.
-
-
-
-
- Indicates whether or not a certificate is used in a HTTPS configuration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Validity Range is from "NotBefore" to "NotAfter"; the corresponding DateTimeRange is from "From" to "Until"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- EAP Method type as defined in IANA EAP Registry.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Confgiuration information for TLS Method.
-
-
-
-
- Password for those EAP Methods that require a password. The password shall never be returned on a get method.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'Bistable' or 'Monostable'
-
-
Bistable – After setting the state, the relay remains in this state.
-
Monostable – After setting the state, the relay returns to its idle state after the specified time.
-
-
-
-
-
-
- Time after which the relay returns to its idle state if it is in monostable mode. If the Mode field is set to bistable mode the value of the parameter can be ignored.
-
-
-
-
-
- 'open' or 'closed'
-
-
'open' means that the relay is open when the relay state is set to 'inactive' through the trigger command and closed when the state is set to 'active' through the same command.
-
'closed' means that the relay is closed when the relay state is set to 'inactive' through the trigger command and open when the state is set to 'active' through the same command.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A unique identifier that is used to reference PTZ Nodes.
-
-
-
-
-
-
- A list of Coordinate Systems available for the PTZ Node. For each Coordinate System, the PTZ Node MUST specify its allowed range.
-
-
-
-
-
-
- All preset operations MUST be available for this PTZ Node if one preset is supported.
-
-
-
-
-
-
- A boolean operator specifying the availability of a home position. If set to true, the Home Position Operations MUST be available for this PTZ Node.
-
-
-
-
-
-
- A list of supported Auxiliary commands. If the list is not empty, the Auxiliary Operations MUST be available for this PTZ Node.
-
-
-
-
-
-
-
-
- Indication whether the HomePosition of a Node is fixed or it can be changed via the SetHomePosition command.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Detail of supported Preset Tour feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates number of preset tours that can be created. Required preset tour operations shall be available for this PTZ Node if one or more preset tour is supported.
-
-
-
-
- Indicates which preset tour operations are available for this PTZ Node.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A mandatory reference to the PTZ Node that the PTZ Configuration belongs to.
-
-
-
-
-
-
- If the PTZ Node supports absolute Pan/Tilt movements, it shall specify one Absolute Pan/Tilt Position Space as default.
-
-
-
-
-
-
- If the PTZ Node supports absolute zoom movements, it shall specify one Absolute Zoom Position Space as default.
-
-
-
-
-
-
- If the PTZ Node supports relative Pan/Tilt movements, it shall specify one RelativePan/Tilt Translation Space as default.
-
-
-
-
-
-
- If the PTZ Node supports relative zoom movements, it shall specify one Relative Zoom Translation Space as default.
-
-
-
-
-
-
- If the PTZ Node supports continuous Pan/Tilt movements, it shall specify one Continuous Pan/Tilt Velocity Space as default.
-
-
-
-
-
-
- If the PTZ Node supports continuous zoom movements, it shall specify one Continuous Zoom Velocity Space as default.
-
-
-
-
-
-
- If the PTZ Node supports absolute or relative PTZ movements, it shall specify corresponding default Pan/Tilt and Zoom speeds.
-
-
-
-
-
-
- If the PTZ Node supports continuous movements, it shall specify a default timeout, after which the movement stops.
-
-
-
-
-
-
- The Pan/Tilt limits element should be present for a PTZ Node that supports an absolute Pan/Tilt. If the element is present it signals the support for configurable Pan/Tilt limits. If limits are enabled, the Pan/Tilt movements shall always stay within the specified range. The Pan/Tilt limits are disabled by setting the limits to –INF or +INF.
-
-
-
-
-
-
- The Zoom limits element should be present for a PTZ Node that supports absolute zoom. If the element is present it signals the supports for configurable Zoom limits. If limits are enabled the zoom movements shall always stay within the specified range. The Zoom limits are disabled by settings the limits to -INF and +INF.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure PT Control Direction related features.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure related parameters for E-Flip.
-
-
-
-
- Optional element to configure related parameters for reversing of PT Control Direction.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable E-Flip feature.
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable Reverse feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A list of supported coordinate systems including their range limitations.
-
-
-
-
-
-
- A timeout Range within which Timeouts are accepted by the PTZ Node.
-
-
-
-
-
-
- Supported options for PT Direction Control.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options for EFlip feature.
-
-
-
-
- Supported options for Reverse feature.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Options of EFlip mode parameter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Options of Reverse mode parameter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A range of pan tilt limits.
-
-
-
-
-
-
-
-
-
-
-
- A range of zoom limit
-
-
-
-
-
-
-
-
-
-
-
- The Generic Pan/Tilt Position space is provided by every PTZ node that supports absolute Pan/Tilt, since it does not relate to a specific physical range.
- Instead, the range should be defined as the full range of the PTZ unit normalized to the range -1 to 1 resulting in the following space description.
-
-
-
-
-
-
- The Generic Zoom Position Space is provided by every PTZ node that supports absolute Zoom, since it does not relate to a specific physical range.
- Instead, the range should be defined as the full range of the Zoom normalized to the range 0 (wide) to 1 (tele).
- There is no assumption about how the generic zoom range is mapped to magnification, FOV or other physical zoom dimension.
-
-
-
-
-
-
- The Generic Pan/Tilt translation space is provided by every PTZ node that supports relative Pan/Tilt, since it does not relate to a specific physical range.
- Instead, the range should be defined as the full positive and negative translation range of the PTZ unit normalized to the range -1 to 1,
- where positive translation would mean clockwise rotation or movement in right/up direction resulting in the following space description.
-
-
-
-
-
-
- The Generic Zoom Translation Space is provided by every PTZ node that supports relative Zoom, since it does not relate to a specific physical range.
- Instead, the corresponding absolute range should be defined as the full positive and negative translation range of the Zoom normalized to the range -1 to1,
- where a positive translation maps to a movement in TELE direction. The translation is signed to indicate direction (negative is to wide, positive is to tele).
- There is no assumption about how the generic zoom range is mapped to magnification, FOV or other physical zoom dimension. This results in the following space description.
-
-
-
-
-
-
- The generic Pan/Tilt velocity space shall be provided by every PTZ node, since it does not relate to a specific physical range.
- Instead, the range should be defined as a range of the PTZ unit’s speed normalized to the range -1 to 1, where a positive velocity would map to clockwise
- rotation or movement in the right/up direction. A signed speed can be independently specified for the pan and tilt component resulting in the following space description.
-
-
-
-
-
-
- The generic zoom velocity space specifies a zoom factor velocity without knowing the underlying physical model. The range should be normalized from -1 to 1,
- where a positive velocity would map to TELE direction. A generic zoom velocity space description resembles the following.
-
-
-
-
-
-
- The speed space specifies the speed for a Pan/Tilt movement when moving to an absolute position or to a relative translation.
- In contrast to the velocity spaces, speed spaces do not contain any directional information. The speed of a combined Pan/Tilt
- movement is represented by a single non-negative scalar value.
-
-
-
-
-
-
- The speed space specifies the speed for a Zoom movement when moving to an absolute position or to a relative translation.
- In contrast to the velocity spaces, speed spaces do not contain any directional information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A URI of coordinate systems.
-
-
-
-
-
-
- A range of x-axis.
-
-
-
-
-
-
- A range of y-axis.
-
-
-
-
-
-
-
-
-
-
-
- A URI of coordinate systems.
-
-
-
-
-
-
- A range of x-axis.
-
-
-
-
-
-
-
-
-
-
-
-
- Pan/tilt coordinate space selector. The following options are defined:
-
-
-
-
-
-
-
-
-
- Pan and tilt position. The x component corresponds to pan and the y component to tilt.
-
-
-
-
-
- A zoom position.
-
-
-
-
-
-
-
-
-
-
- Pan and tilt speed. The x component corresponds to pan and the y component to tilt. If omitted in a request, the current (if any) PanTilt movement should not be affected.
-
-
-
-
-
- A zoom speed. If omitted in a request, the current (if any) Zoom movement should not be affected.
-
-
-
-
-
-
-
-
-
-
-
- Specifies the absolute position of the PTZ unit together with the Space references. The default absolute spaces of the corresponding PTZ configuration MUST be referenced within the Position element.
-
-
-
-
-
-
- Indicates if the Pan/Tilt/Zoom device unit is currently moving, idle or in an unknown state.
-
-
-
-
-
-
- States a current PTZ error.
-
-
-
-
-
-
- Specifies the UTC time when this status was generated.
-
-
-
-
-
-
-
-
-
-
-
-
-
- A list of preset position name.
-
-
-
-
-
-
- A list of preset position.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Readable name of the preset tour.
-
-
-
-
- Read only parameters to indicate the status of the preset tour.
-
-
-
-
- Auto Start flag of the preset tour. True allows the preset tour to be activated always.
-
-
-
-
- Parameters to specify the detail behavior of the preset tour.
-
-
-
-
- A list of detail of touring spots including preset positions.
-
-
-
-
-
-
- Unique identifier of this preset tour.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Detail definition of preset position of the tour spot.
-
-
-
-
- Optional parameter to specify Pan/Tilt and Zoom speed on moving toward this tour spot.
-
-
-
-
- Optional parameter to specify time duration of staying on this tour sport.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Option to specify the preset position with Preset Token defined in advance.
-
-
-
-
- Option to specify the preset position with the home position of this PTZ Node. "False" to this parameter shall be treated as an invalid argument.
-
-
-
-
- Option to specify the preset position with vector of PTZ node directly.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates state of this preset tour by Idle/Touring/Paused.
-
-
-
-
- Indicates a tour spot currently staying.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Optional parameter to specify how many times the preset tour is recurred.
-
-
-
-
- Optional parameter to specify how long time duration the preset tour is recurred.
-
-
-
-
- Optional parameter to choose which direction the preset tour goes. Forward shall be chosen in case it is omitted.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not the AutoStart is supported.
-
-
-
-
- Supported options for Preset Tour Starting Condition.
-
-
-
-
- Supported options for Preset Tour Spot.
-
-
-
-
-
-
-
-
-
-
-
- Supported options for detail definition of preset position of the tour spot.
-
-
-
-
- Supported range of stay time for a tour spot.
-
-
-
-
-
-
-
-
-
-
-
- A list of available Preset Tokens for tour spots.
-
-
-
-
- An option to indicate Home postion for tour spots.
-
-
-
-
- Supported range of Pan and Tilt for tour spots.
-
-
-
-
- Supported range of Zoom for a tour spot.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported range of Recurring Time.
-
-
-
-
- Supported range of Recurring Duration.
-
-
-
-
- Supported options for Direction of Preset Tour.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Status of focus position.
-
-
-
-
-
-
- Status of focus MoveStatus.
-
-
-
-
-
-
- Error status of focus.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to set autofocus near limit (unit: meter).
-
-
-
-
- Parameter to set autofocus far limit (unit: meter).
-If set to 0.0, infinity will be used.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enabled/disabled BLC mode (on/off).
-
-
-
-
- Image brightness (unit unspecified).
-
-
-
-
- Color saturation of the image (unit unspecified).
-
-
-
-
- Contrast of the image (unit unspecified).
-
-
-
-
- Exposure mode of the device.
-
-
-
-
- Focus configuration.
-
-
-
-
- Infrared Cutoff Filter settings.
-
-
-
-
- Sharpness of the Video image.
-
-
-
-
- WDR settings.
-
-
-
-
- White balance settings.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Exposure Mode
-
-
Auto – Enabled the exposure algorithm on the NVT.
-
Manual – Disabled exposure algorithm on the NVT.
-
-
-
-
-
-
-
- The exposure priority mode (low noise/framerate).
-
-
-
-
-
-
- Rectangular exposure mask.
-
-
-
-
-
-
- Minimum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- The fixed exposure time used by the image sensor (μs).
-
-
-
-
-
-
- The fixed gain used by the image sensor (dB).
-
-
-
-
-
-
- The fixed attenuation of input light affected by the iris (dB). 0dB maps to a fully opened iris.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- White dynamic range (on/off)
-
-
-
-
-
-
- Optional level parameter (unitless)
-
-
-
-
-
-
-
-
- Enumeration describing the available backlight compenstation modes.
-
-
-
-
- Backlight compensation is disabled.
-
-
-
-
- Backlight compensation is enabled.
-
-
-
-
-
-
-
-
-
- Backlight compensation mode (on/off).
-
-
-
-
- Optional level parameter (unit unspecified).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters for the absolute focus control.
-
-
-
-
-
-
- Parameters for the relative focus control.
-
-
-
-
-
-
- Parameter for the continuous focus control.
-
-
-
-
-
-
-
-
-
-
-
- Position parameter for the absolute focus control.
-
-
-
-
-
-
- Speed parameter for the absolute focus control.
-
-
-
-
-
-
-
-
-
-
-
- Distance parameter for the relative focus control.
-
-
-
-
-
-
- Speed parameter for the relative focus control.
-
-
-
-
-
-
-
-
-
-
-
- Speed parameter for the Continuous focus control.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the position.
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the distance.
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Auto whitebalancing mode (auto/manual).
-
-
-
-
- Rgain (unitless).
-
-
-
-
- Bgain (unitless).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Status of focus.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Status of focus position.
-
-
-
-
-
-
- Status of focus MoveStatus.
-
-
-
-
-
-
- Error status of focus.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Type describing the ImagingSettings of a VideoSource. The supported options and ranges can be obtained via the GetOptions command.
-
-
-
-
- Enabled/disabled BLC mode (on/off).
-
-
-
-
- Image brightness (unit unspecified).
-
-
-
-
- Color saturation of the image (unit unspecified).
-
-
-
-
- Contrast of the image (unit unspecified).
-
-
-
-
- Exposure mode of the device.
-
-
-
-
- Focus configuration.
-
-
-
-
- Infrared Cutoff Filter settings.
-
-
-
-
- Sharpness of the Video image.
-
-
-
-
- WDR settings.
-
-
-
-
- White balance settings.
-
-
-
-
-
-
-
-
-
-
-
-
- Optional element to configure Image Stabilization feature.
-
-
-
-
-
-
-
-
-
-
- An optional parameter applied to only auto mode to adjust timing of toggling Ir cut filter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameter to enable/disable Image Stabilization feature.
-
-
-
-
- Optional level parameter (unit unspecified)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Specifies which boundaries to automatically toggle Ir cut filter following parameters are applied to. Its options shall be chosen from tt:IrCutFilterAutoBoundaryType.
-
-
-
-
- Adjusts boundary exposure level for toggling Ir cut filter to on/off specified with unitless normalized value from +1.0 to -1.0. Zero is default and -1.0 is the darkest adjustment (Unitless).
-
-
-
-
- Delay time of toggling Ir cut filter to on/off after crossing of the boundary exposure levels.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Type describing whether WDR mode is enabled or disabled (on/off).
-
-
-
-
- Wide dynamic range mode (on/off).
-
-
-
-
- Optional level parameter (unit unspecified).
-
-
-
-
-
-
-
- Type describing whether BLC mode is enabled or disabled (on/off).
-
-
-
-
- Backlight compensation mode (on/off).
-
-
-
-
- Optional level parameter (unit unspecified).
-
-
-
-
-
-
-
- Type describing the exposure settings.
-
-
-
-
-
- Exposure Mode
-
-
Auto – Enabled the exposure algorithm on the device.
-
Manual – Disabled exposure algorithm on the device.
-
-
-
-
-
-
-
- The exposure priority mode (low noise/framerate).
-
-
-
-
-
-
- Rectangular exposure mask.
-
-
-
-
-
-
- Minimum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of exposure time range allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the sensor gain range that is allowed to be used by the algorithm.
-
-
-
-
-
-
- Minimum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- Maximum value of the iris range allowed to be used by the algorithm.
-
-
-
-
-
-
- The fixed exposure time used by the image sensor (μs).
-
-
-
-
-
-
- The fixed gain used by the image sensor (dB).
-
-
-
-
-
-
- The fixed attenuation of input light affected by the iris (dB). 0dB maps to a fully opened iris.
-
-
-
-
-
-
-
-
-
-
-
- Valid range of Backlight Compensation.
-
-
-
-
-
-
- Valid range of Brightness.
-
-
-
-
-
-
- Valid range of Color Saturation.
-
-
-
-
-
-
- Valid range of Contrast.
-
-
-
-
-
-
- Valid range of Exposure.
-
-
-
-
-
-
- Valid range of Focus.
-
-
-
-
-
-
- Valid range of IrCutFilterModes.
-
-
-
-
-
-
- Valid range of Sharpness.
-
-
-
-
-
-
- Valid range of WideDynamicRange.
-
-
-
-
-
-
- Valid range of WhiteBalance.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Options of parameters for Image Stabilization feature.
-
-
-
-
-
-
-
-
-
-
- Options of parameters for adjustment of Ir cut filter auto mode.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options of Image Stabilization mode parameter.
-
-
-
-
- Valid range of the Image Stabilization.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Supported options of boundary types for adjustment of Ir cut filter auto mode. The opptions shall be chosen from tt:IrCutFilterAutoBoundaryType.
-
-
-
-
- Indicates whether or not boundary offset for toggling Ir cut filter is supported.
-
-
-
-
- Supported range of delay time for toggling Ir cut filter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'ON' or 'OFF'
-
-
-
-
-
-
- Level range of BacklightCompensation.
-
-
-
-
-
-
-
-
-
-
-
- Exposure Mode
-
-
Auto – Enabled the exposure algorithm on the device.
-
Manual – Disabled exposure algorithm on the device.
-
-
-
-
-
-
-
- The exposure priority mode (low noise/framerate).
-
-
-
-
-
-
- Valid range of the Minimum ExposureTime.
-
-
-
-
-
-
- Valid range of the Maximum ExposureTime.
-
-
-
-
-
-
- Valid range of the Minimum Gain.
-
-
-
-
-
-
- Valid range of the Maximum Gain.
-
-
-
-
-
-
- Valid range of the Minimum Iris.
-
-
-
-
-
-
- Valid range of the Maximum Iris.
-
-
-
-
-
-
- Valid range of the ExposureTime.
-
-
-
-
-
-
- Valid range of the Gain.
-
-
-
-
-
-
- Valid range of the Iris.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges for the absolute control.
-
-
-
-
-
-
- Valid ranges for the relative control.
-
-
-
-
-
-
- Valid ranges for the continuous control.
-
-
-
-
-
-
-
-
-
-
-
- Valid ranges of the distance.
-
-
-
-
-
-
- Valid ranges of the speed.
-
-
-
-
-
-
-
-
-
-
-
- 'AUTO' or 'MANUAL'
-
-
-
-
-
-
- Rgain (unitless).
-
-
-
-
-
-
- Bgain (unitless).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Mode of auto fucus.
-
-
AUTO
-
MANUAL
-
-
-
-
-
-
-
- Parameter to set autofocus near limit (unit: meter).
-
-
-
-
- Parameter to set autofocus far limit (unit: meter).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Mode of WhiteBalance.
-
-
-
-
-
-
-
- Valid range of DefaultSpeed.
-
-
-
-
-
-
- Valid range of NearLimit.
-
-
-
-
-
-
- Valid range of FarLimit.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token value pairs that triggered this message. Typically only one item is present.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of parameters according to the corresponding ItemListDescription.
- Each item in the list shall have a unique name.
-
-
-
-
-
- Value name pair as defined by the corresponding description.
-
-
-
-
- Item name.
-
-
-
-
- Item value. The type is defined in the corresponding description.
-
-
-
-
-
-
- Complex value structure.
-
-
-
-
-
- XML tree contiaing the element value as defined in the corresponding description.
-
-
-
-
-
- Item name.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Set of tokens producing this message. The list may only contain SimpleItemDescription items.
- The set of tokens identify the component within the WS-Endpoint, which is responsible for the producing the message.
- For analytics events the token set shall include the VideoSourceConfigurationToken, the VideoAnalyticsConfigurationToken
- and the name of the analytics module or rule.
-
-
-
-
-
- Describes optional message payload parameters that may be used as key. E.g. object IDs of tracked objects are conveyed as key.
-
-
-
-
- Describes the payload of the message.
-
-
-
-
-
-
- Must be set to true when the described Message relates to a property. An alternative term of "property" is a "state" in contrast to a pure event, which contains relevant information for only a single point in time. Default is false.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Describes a list of items. Each item in the list shall have a unique name.
- The list is designed as linear structure without optional or unbounded elements.
- Use ElementItems only when complex structures are inevitable.
-
-
-
-
-
- Description of a simple item. The type must be of cathegory simpleType (xs:string, xs:integer, xs:float, ...).
-
-
-
-
- Item name. Must be unique within a list.
-
-
-
-
-
-
-
-
- Description of a complex type. The Type must reference a defined type.
-
-
-
-
-
- Item name. Must be unique within a list.
-
-
-
-
- The type of the item. The Type must reference a defined type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Object Class Type
-
-
-
-
- A likelihood/probability that the corresponding object belongs to this class. The sum of the likelihoods shall NOT exceed 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Number of columns of the cell grid (x dimension)
-
-
-
-
- Number of rows of the cell grid (y dimension)
-
-
-
-
- A “1” denotes a cell where motion is detected and a “0” an empty cell. The first cell is in the upper left corner. Then the cell order goes first from left to right and then from up to down. If the number of cells is not a multiple of 8 the last byte is filled with zeros. The information is run length encoded according to Packbit coding in ISO 12369 (TIFF, Revision 6.0).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of configuration parameters as defined in the correspding description.
-
-
-
-
-
- Name of the configuration.
-
-
-
-
- Type of the configuration represented by a unique QName. The Type characterizes a ConfigDescription defining the Parameters.
-
-
-
-
-
-
-
-
-
- List describing the configuration parameters. The names of the parameters must be unique. If possible SimpleItems
- should be used to transport the information to ease parsing of dynamically defined messages by a client
- application.
-
-
-
-
-
-
- The analytics modules and rule engine produce Events, which must be listed within the Analytics Module Description. In order to do so
- the structure of the Message is defined and consists of three groups: Source, Key, and Data. It is recommended to use SimpleItemDescriptions wherever applicable.
- The name of all Items must be unique within all Items contained in any group of this Message.
- Depending on the component multiple parameters or none may be needed to identify the component uniquely.
-
-
-
-
-
-
-
-
-
- The ParentTopic labels the message (e.g. "nn:RuleEngine/LineCrossing"). The real message can extend the ParentTopic
- by for example the name of the instaniated rule (e.g. "nn:RuleEngine/LineCrossing/corssMyFirstLine").
- Even without knowing the complete topic name, the subscriber will be able to distiguish the
- messages produced by different rule instances of the same type via the Source fields of the message.
- There the name of the rule instance, which produced the message, must be listed.
-
-
-
-
-
-
-
-
-
-
-
-
- XML Type of the Configuration (e.g. "tt::LineDetector").
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Lists the location of all schemas that are referenced in the rules.
-
-
-
-
- List of rules supported by the Video Analytics configuration..
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- It optionally contains a list of URLs that provide the location of schema files.
- These schema files describe the types and elements used in the analytics module descriptions.
- If the analytics module descriptions reference types or elements of the ONVIF schema file,
- the ONVIF schema file MUST be explicitly listed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains Polygon configuration for rule parameters
-
-
-
-
-
-
-
-
-
-
-
- Contains array of Polyline
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains PolylineArray configuration data
-
-
-
-
-
-
-
-
-
-
-
- Motion Expression data structure contains motion expression which is based on Scene Descriptor schema with XPATH syntax. The Type argument could allow introduction of different dialects
-
-
-
-
-
-
-
-
-
-
-
-
- Contains Rule MotionExpression configuration
-
-
-
-
-
-
-
-
-
-
-
- Mapping of the cell grid to the Video frame. The cell grid is starting from the upper left corner and x dimension is going from left to right and the y dimension from up to down.
-
-
-
-
-
-
- Number of columns of the cell grid (x dimension)
-
-
-
-
- Number of rows of the cell grid (y dimension)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Configuration of the streaming and coding settings of a Video window.
-
-
-
-
- Optional name of the pane configuration.
-
-
-
-
- If the device has audio outputs, this element contains a pointer to the audio output that is associated with the pane. A client
-can retrieve the available audio outputs of a device using the GetAudioOutputs command of the DeviceIO service.
-
-
-
-
- If the device has audio sources, this element contains a pointer to the audio source that is associated with this pane.
-The audio connection from a decoder device to the NVT is established using the backchannel mechanism. A client can retrieve the available audio sources of a device using the GetAudioSources command of the
-DeviceIO service.
-
-
-
-
- The configuration of the audio encoder including codec, bitrate
-and sample rate.
-
-
-
-
- A pointer to a Receiver that has the necessary information to receive
- data from a Transmitter. This Receiver can be connected and the network video decoder displays the received data on the specified outputs. A client can retrieve the available Receivers using the
- GetReceivers command of the Receiver Service.
-
-
-
-
- A unique identifier in the display device.
-
-
-
-
-
-
-
-
-
- A pane layout describes one Video window of a display. It links a pane configuration to a region of the screen.
-
-
-
-
- Reference to the configuration of the streaming and coding parameters.
-
-
-
-
- Describes the location and size of the area on the monitor. The area coordinate values are espressed in normalized units [-1.0, 1.0].
-
-
-
-
-
-
-
-
-
- A layout describes a set of Video windows that are displayed simultaniously on a display.
-
-
-
-
- List of panes assembling the display layout.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type contains the Audio and Video coding capabilities of a display service.
-
-
-
-
- If the device supports audio encoding this section describes the supported codecs and their configuration.
-
-
-
-
- If the device supports audio decoding this section describes the supported codecs and their settings.
-
-
-
-
- This section describes the supported video codesc and their configuration.
-
-
-
-
-
-
-
-
-
- The options supported for a display layout.
-
-
-
-
- Lists the possible Pane Layouts of the Video Output
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Description of a pane layout describing a complete display layout.
-
-
-
-
- List of areas assembling a layout. Coordinate values are in the range [-1.0, 1.0].
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Description of a receiver, including its token and configuration.
-
-
-
-
-
- Unique identifier of the receiver.
-
-
-
-
- Describes the configuration of the receiver.
-
-
-
-
-
-
-
-
-
-
- Describes the configuration of a receiver.
-
-
-
-
-
- The following connection modes are defined:
-
-
-
-
- Details of the URI to which the receiver should connect.
-
-
-
-
- Stream connection parameters.
-
-
-
-
-
-
-
-
-
-
- Specifies a receiver connection mode.
-
-
-
-
-
- The receiver connects on demand, as required by consumers of the media streams.
-
-
-
-
- The receiver attempts to maintain a persistent connection to the configured endpoint.
-
-
-
-
- The receiver does not attempt to connect.
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
- Specifies the current connection state of the receiver.
-
-
-
-
-
- The receiver is not connected.
-
-
-
-
- The receiver is attempting to connect.
-
-
-
-
- The receiver is connected.
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
- Contains information about a receiver's current state.
-
-
-
-
-
- The connection state of the receiver may have one of the following states:
-
-
-
-
- Indicates whether or not the receiver was created automatically.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The earliest point in time where there is recorded data on the device.
-
-
-
-
- The most recent point in time where there is recorded data on the device.
-
-
-
-
- The device contains this many recordings.
-
-
-
-
-
-
-
-
-
- A structure for defining a limited scope when searching in recorded data.
-
-
-
-
- A list of sources that are included in the scope. If this list is included, only data from one of these sources shall be searched.
-
-
-
-
- A list of recordings that are included in the scope. If this list is included, only data from one of these recordings shall be searched.
-
-
-
-
- An xpath expression used to specify what recordings to search. Only those recordings with an RecordingInformation structure that matches the filter shall be searched.
-
-
-
-
- Extension point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The lower boundary of the PTZ volume to look for.
-
-
-
-
- The upper boundary of the PTZ volume to look for.
-
-
-
-
- If true, search for when entering the specified PTZ volume.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A RecordingInformation structure for each found recording matching the search.
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A FindEventResult structure for each found event matching the search.
-
-
-
-
-
-
-
-
-
- The recording where this event was found. Empty string if no recording is associated with this event.
-
-
-
-
- A reference to the track where this event was found. Empty string if no track is associated with this event.
-
-
-
-
- The time when the event occured.
-
-
-
-
- The description of the event.
-
-
-
-
- If true, indicates that the event is a virtual event generated for this particular search session to give the state of a property at the start time of the search.
-
-
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A FindPTZPositionResult structure for each found PTZ position matching the search.
-
-
-
-
-
-
-
-
-
- A reference to the recording containing the PTZ position.
-
-
-
-
- A reference to the metadata track containing the PTZ position.
-
-
-
-
- The time when the PTZ position was valid.
-
-
-
-
- The PTZ position.
-
-
-
-
-
-
-
-
-
-
-
- The state of the search when the result is returned. Indicates if there can be more results, or if the search is completed.
-
-
-
-
- A FindMetadataResult structure for each found set of Metadata matching the search.
-
-
-
-
-
-
-
-
-
- A reference to the recording containing the metadata.
-
-
-
-
- A reference to the metadata track containing the matching metadata.
-
-
-
-
- The point in time when the matching metadata occurs in the metadata track.
-
-
-
-
-
-
-
-
-
-
-
- The search is queued and not yet started.
-
-
-
-
- The search is underway and not yet completed.
-
-
-
-
- The search has been completed and no new results will be found.
-
-
-
-
- The state of the search is unknown. (This is not a valid response from GetSearchState.)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Information about the source of the recording. This gives a description of where the data in the recording comes from. Since a single
- recording is intended to record related material, there is just one source. It is indicates the physical location or the
- major data source for the recording. Currently the recordingconfiguration cannot describe each individual data source.
-
-
-
-
-
-
-
-
- Basic information about the track. Note that a track may represent a single contiguous time span or consist of multiple slices.
-
-
-
-
-
-
-
-
-
-
-
- A set of informative desciptions of a data source. The Search searvice allows a client to filter on recordings based on information in this structure.
-
-
-
-
-
-
- Identifier for the source chosen by the client that creates the structure.
- This identifier is opaque to the device. Clients may use any type of URI for this field. A device shall support at least 128 characters.
-
-
-
-
- Informative user readable name of the source, e.g. "Camera23". A device shall support at least 20 characters.
-
-
-
-
- Informative description of the physical location of the source, e.g. the coordinates on a map.
-
-
-
-
- Informative description of the source.
-
-
-
-
- URI provided by the service supplying data to be recorded. A device shall support at least 128 characters.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
-
-
- Type of the track: "Video", "Audio" or "Metadata".
- The track shall only be able to hold data of that type.
-
-
-
-
- Informative description of the contents of the track.
-
-
-
-
- The start date and time of the oldest recorded data in the track.
-
-
-
-
- The stop date and time of the newest recorded data in the track.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Placeholder for future extension.
-
-
-
-
-
-
-
- A set of media attributes valid for a recording at a point in time or for a time interval.
-
-
-
-
- A reference to the recording that has these attributes.
-
-
-
-
- A set of attributes for each track.
-
-
-
-
- The attributes are valid from this point in time in the recording.
-
-
-
-
- The attributes are valid until this point in time in the recording. Can be equal to 'From' to indicate that the attributes are only known to be valid for this particular point in time.
-
-
-
-
-
-
-
-
-
-
-
- The basic information about the track. Note that a track may represent a single contiguous time span or consist of multiple slices.
-
-
-
-
- If the track is a video track, exactly one of this structure shall be present and contain the video attributes.
-
-
-
-
- If the track is an audio track, exactly one of this structure shall be present and contain the audio attributes.
-
-
-
-
- If the track is an metadata track, exactly one of this structure shall be present and contain the metadata attributes.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Average bitrate in kbps.
-
-
-
-
- The width of the video in pixels.
-
-
-
-
- The height of the video in pixels.
-
-
-
-
- Used video codec, either Jpeg, H.264 or Mpeg4
-
-
-
-
- Average framerate in frames per second.
-
-
-
-
-
-
-
-
-
-
-
- The bitrate in kbps.
-
-
-
-
- Audio codec used for encoding the audio (either G.711, G.726 or AAC)
-
-
-
-
- The sample rate in kHz.
-
-
-
-
-
-
-
-
-
-
-
- Indicates that there can be PTZ data in the metadata track in the specified time interval.
-
-
-
-
- Indicates that there can be analytics data in the metadata track in the specified time interval.
-
-
-
-
- Indicates that there can be notifications in the metadata track in the specified time interval.
-
-
-
-
-
-
- List of all PTZ spaces active for recording. Note that events are only recorded on position changes and the actual point of recording may not necessarily contain an event of the specified type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Information about the source of the recording.
-
-
-
-
- Informative description of the source.
-
-
-
-
- Sspecifies the maximum time that data in any track within the
- recording shall be stored. The device shall delete any data older than the maximum retention
- time. Such data shall not be accessible anymore. If the MaximumRetentionPeriod is set to 0,
- the device shall not limit the retention time of stored data, except by resource constraints.
- Whatever the value of MaximumRetentionTime, the device may automatically delete
- recordings to free up storage space for new recordings.
-
-
-
-
-
-
-
-
-
-
-
- Type of the track. It shall be equal to the strings “Video”,
- “Audio” or “Metadata”. The track shall only be able to hold data of that type.
-
-
-
-
- Informative description of the track.
-
-
-
-
-
-
-
-
-
-
-
- Token of the recording.
-
-
-
-
- Configuration of the recording.
-
-
-
-
- List of tracks.
-
-
-
-
-
-
-
-
-
-
-
- Configuration of a track.
-
-
-
-
-
-
-
-
-
-
- Token of the track.
-
-
-
-
- Configuration of the track.
-
-
-
-
-
-
-
-
-
-
-
- Identifies the recording to which this job shall store the received data.
-
-
-
-
- The mode of the job. If it is idle, nothing shall happen. If it is active, the device shall try
- to obtain data from the receivers. A client shall use GetRecordingJobState to determine if data transfer is really taking place.
- The only valid values for Mode shall be “Idle” and “Active”.
-
-
-
-
- This shall be a non-negative number. If there are multiple recording jobs that store data to
- the same track, the device will only store the data for the recording job with the highest
- priority. The priority is specified per recording job, but the device shall determine the priority
- of each track individually. If there are two recording jobs with the same priority, the device
- shall record the data corresponding to the recording job that was activated the latest.
-
-
-
-
- Source of the recording.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This field shall be a reference to the source of the data. The type of the source
- is determined by the attribute Type in the SourceToken structure. If Type is
- http://www.onvif.org/ver10/schema/Receiver, the token is a ReceiverReference. In this case
- the device shall receive the data over the network. If Type is
- http://www.onvif.org/ver10/schema/Profile, the token identifies a media profile, instructing the
- device to obtain data from a profile that exists on the local device.
-
-
-
-
- If this field is TRUE, and if the SourceToken is omitted, the device
- shall create a receiver object (through the receiver service) and assign the
- ReceiverReference to the SourceToken field. When retrieving the RecordingJobConfiguration
- from the device, the AutoCreateReceiver field shall never be present.
-
-
-
-
- List of tracks associated with the recording.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the received RTSP stream contains multiple tracks of the same type, the
- SourceTag differentiates between those Tracks. This field can be ignored in case of recording a local source.
-
-
-
-
- The destination is the tracktoken of the track to which the device shall store the
- received data.
-
-
-
-
-
-
-
-
-
-
-
- Identification of the recording that the recording job records to.
-
-
-
-
- Holds the aggregated state over the whole RecordingJobInformation structure.
-
-
-
-
- Identifies the data source of the recording job.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Identifies the data source of the recording job.
-
-
-
-
- Holds the aggregated state over all substructures of RecordingJobStateSource.
-
-
-
-
- List of track items.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Identifies the track of the data source that provides the data.
-
-
-
-
- Indicates the destination track.
-
-
-
-
- Optionally holds an implementation defined string value that describes the error.
- The string should be in the English language.
-
-
-
-
- Provides the job state of the track. The valid
- values of state shall be “Idle”, “Active” and “Error”. If state equals “Error”, the Error field may be filled in with an implementation defined value.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Configuration parameters for the replay service.
-
-
-
-
-
- The RTSP session timeout.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the analytics engine (AnalyticsEngine) being controlled.
-
-
-
-
- Token of the analytics engine configuration (VideoAnalyticsConfiguration) in effect.
-
-
-
-
- Tokens of the input (AnalyticsEngineInput) configuration applied.
-
-
-
-
- Tokens of the receiver providing media input data. The order of ReceiverToken shall exactly match the order of InputToken.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This case should never happen.
-
-
-
-
-
-
-
-
-
- Token of the control object whose status is requested.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Action Engine Event Payload data structure contains the information about the ONVIF command invocations. Since this event could be generated by other or proprietary actions, the command invocation specific fields are defined as optional and additional extension mechanism is provided for future or additional action definitions.
-
-
-
-
- Request Message
-
-
-
-
- Response Message
-
-
-
-
- Fault Message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AudioClassType acceptable values are;
- gun_shot, scream, glass_breaking, tire_screech
-
-
-
-
-
-
-
-
-
- Indicates audio class label
-
-
-
-
- A likelihood/probability that the corresponding audio event belongs to this class. The sum of the likelihoods shall NOT exceed 1
-
-
-
-
-
-
-
-
-
-
-
- Array of audio class label and class probability
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- For OSD position type, following are the pre-defined:
UpperLeft
-
UpperRight
-
LowerLeft
-
LowerRight
-
Custom
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The value range of "Transparent" could be defined by vendors only should follow this rule: the minimum value means non-transparent and the maximum value maens fully transparent.
-
-
-
-
-
-
-
-
-
-
-
-
-
- The following OSD Text Type are defined:
-
Plain - The Plain type means the OSD is shown as a text string which defined in the "PlainText" item.
-
Date - The Date type means the OSD is shown as a date, format of which should be present in the "DateFormat" item.
-
Time - The Time type means the OSD is shown as a time, format of which should be present in the "TimeFormat" item.
-
DateAndTime - The DateAndTime type means the OSD is shown as date and time, format of which should be present in the "DateFormat" and the "TimeFormat" item.
-
-
-
-
-
-
-
- List of supported OSD date formats. This element shall be present when the value of Type field has Date or DateAndTime. The following DateFormat are defined:
-
M/d/yyyy - e.g. 3/6/2013
-
MM/dd/yyyy - e.g. 03/06/2013
-
dd/MM/yyyy - e.g. 06/03/2013
-
yyyy/MM/dd - e.g. 2013/03/06
-
yyyy-MM-dd - e.g. 2013-06-03
-
dddd, MMMM dd, yyyy - e.g. Wednesday, March 06, 2013
-
MMMM dd, yyyy - e.g. March 06, 2013
-
dd MMMM, yyyy - e.g. 06 March, 2013
-
-
-
-
-
-
-
- List of supported OSD time formats. This element shall be present when the value of Type field has Time or DateAndTime. The following TimeFormat are defined:
-
h:mm:ss tt - e.g. 2:14:21 PM
-
hh:mm:ss tt - e.g. 02:14:21 PM
-
H:mm:ss - e.g. 14:14:21
-
HH:mm:ss - e.g. 14:14:21
-
-
-
-
-
-
- Font size of the text in pt.
-
-
-
-
- Font color of the text.
-
-
-
-
- Background color of the text.
-
-
-
-
- The content of text to be displayed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The URI of the image which to be displayed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Describe the option of the color supported. Either list each color or define the range of color value. The following values are acceptable for Colourspace attribute.
-
-
-
-
-
-
- List the supported color.
-
-
-
-
- Define the rang of color supported.
-
-
-
-
-
-
-
-
-
- Describe the option of the color and its transparency.
-
-
-
-
- Optional list of supported colors.
-
-
-
-
- Range of the transparent level. Larger means more tranparent.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of supported OSD text type. When a device indicates the supported number relating to Text type in MaximumNumberOfOSDs, the type shall be presented.
-
-
-
-
- Range of the font size value.
-
-
-
-
- List of supported date format.
-
-
-
-
- List of supported time format.
-
-
-
-
- List of supported font color.
-
-
-
-
- List of supported background color.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- List of avaiable uris of image.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Reference to the video source configuration.
-
-
-
-
- Type of OSD.
-
-
-
-
- Position configuration of OSD.
-
-
-
-
- Text configuration of OSD. It shall be present when the value of Type field is Text.
-
-
-
-
- Image configuration of OSD. It shall be present when the value of Type field is Image
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The maximum number of OSD configurations supported for the specificate video source configuration. If a device limits the number of instances by OSDType, it should indicate the supported number via the related attribute.
-
-
-
-
- List supported type of OSD configuration. When a device indicates the supported number for each types in MaximumNumberOfOSDs, related type shall be presented. A device shall return Option element relating to listed type.
-
-
-
-
- List available OSD position type. Following are the pre-defined:
UpperLeft
-
UpperRight
-
LowerLeft
-
LowerRight
-
Custom
-
-
-
-
-
- Option of the OSD text configuration. This element shall be returned if the device is signaling the support for Text.
-
-
-
-
- Option of the OSD image configuration. This element shall be returned if the device is signaling the support for Image.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/ptz.wsdl b/onvif/wsdl/ptz.wsdl
deleted file mode 100644
index e977619be..000000000
--- a/onvif/wsdl/ptz.wsdl
+++ /dev/null
@@ -1,1300 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The capabilities for the PTZ service is returned in the Capabilities element.
-
-
-
-
-
-
-
-
-
-
-
-
- Indicates whether or not EFlip is supported.
-
-
-
-
- Indicates whether or not reversing of PT control direction is supported.
-
-
-
-
- Indicates support for the GetCompatibleConfigurations command.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A list of the existing PTZ Nodes on the device.
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested PTZNode.
-
-
-
-
-
-
-
-
-
-
-
- A requested PTZNode.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A list of all existing PTZConfigurations on the device.
-
-
-
-
-
-
-
-
-
-
-
-
- Token of the requested PTZConfiguration.
-
-
-
-
-
-
-
-
-
-
-
- A requested PTZConfiguration.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Flag that makes configuration persistent. Example: User wants the configuration to exist after reboot.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token of an existing configuration that the options are intended for.
-
-
-
-
-
-
-
-
-
-
-
- The requested PTZ configuration options.
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the operation should take place.
-
-
-
-
-
- The Auxiliary request data.
-
-
-
-
-
-
-
-
-
-
-
- The response contains the auxiliary response.
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the operation should take place.
-
-
-
-
-
-
-
-
-
-
-
- A list of presets which are available for the requested MediaProfile.
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the operation should take place.
-
-
-
-
-
- A requested preset name.
-
-
-
-
-
- A requested preset token.
-
-
-
-
-
-
-
-
-
-
-
- A token to the Preset which has been set.
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the operation should take place.
-
-
-
-
-
- A requested preset token.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the operation should take place.
-
-
-
-
-
- A requested preset token.
-
-
-
-
-
- A requested speed.The speed parameter can only be specified when Speed Spaces are available for the PTZ Node.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the PTZStatus should be requested.
-
-
-
-
-
-
-
-
-
-
-
- The PTZStatus for the requested MediaProfile.
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the operation should take place.
-
-
-
-
-
- A requested speed.The speed parameter can only be specified when Speed Spaces are available for the PTZ Node.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile where the home position should be set.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile.
-
-
-
-
-
- A Velocity vector specifying the velocity of pan, tilt and zoom.
-
-
-
-
-
- An optional Timeout parameter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile.
-
-
-
-
-
- A positional Translation relative to the current position
-
-
-
-
-
- An optional Speed parameter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile.
-
-
-
-
-
- A Position vector specifying the absolute target position.
-
-
-
-
-
- An optional Speed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A reference to the MediaProfile that indicate what should be stopped.
-
-
-
-
-
- Set true when we want to stop ongoing pan and tilt movements.If PanTilt arguments are not present, this command stops these movements.
-
-
-
-
-
- Set true when we want to stop ongoing zoom movement.If Zoom arguments are not present, this command stops ongoing zoom movement.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contains the token of an existing media profile the configurations shall be compatible with.
-
-
-
-
-
-
-
-
-
-
- A list of all existing PTZConfigurations on the NVT that is suitable to be added to the addressed media profile.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Returns the capabilities of the PTZ service. The result is returned in a typed answer.
-
-
-
-
-
- Get the descriptions of the available PTZ Nodes.
-
- A PTZ-capable device may have multiple PTZ Nodes. The PTZ Nodes may represent
- mechanical PTZ drivers, uploaded PTZ drivers or digital PTZ drivers. PTZ Nodes are the
- lowest level entities in the PTZ control API and reflect the supported PTZ capabilities. The
- PTZ Node is referenced either by its name or by its reference token.
-
-
-
-
-
- Get a specific PTZ Node identified by a reference
- token or a name.
-
-
-
-
-
- Get a specific PTZonfiguration from the device, identified by its reference token or name.
-
- The default Position/Translation/Velocity Spaces are introduced to allow NVCs sending move
- requests without the need to specify a certain coordinate system. The default Speeds are
- introduced to control the speed of move requests (absolute, relative, preset), where no
- explicit speed has been set.
- The allowed pan and tilt range for Pan/Tilt Limits is defined by a two-dimensional space range
- that is mapped to a specific Absolute Pan/Tilt Position Space. At least one Pan/Tilt Position
- Space is required by the PTZNode to support Pan/Tilt limits. The limits apply to all supported
- absolute, relative and continuous Pan/Tilt movements. The limits shall be checked within the
- coordinate system for which the limits have been specified. That means that even if
- movements are specified in a different coordinate system, the requested movements shall be
- transformed to the coordinate system of the limits where the limits can be checked. When a
- relative or continuous movements is specified, which would leave the specified limits, the PTZ
- unit has to move along the specified limits. The Zoom Limits have to be interpreted
- accordingly.
-
-
-
-
-
-
- Get all the existing PTZConfigurations from the device.
-
- The default Position/Translation/Velocity Spaces are introduced to allow NVCs sending move
- requests without the need to specify a certain coordinate system. The default Speeds are
- introduced to control the speed of move requests (absolute, relative, preset), where no
- explicit speed has been set.
- The allowed pan and tilt range for Pan/Tilt Limits is defined by a two-dimensional space range
- that is mapped to a specific Absolute Pan/Tilt Position Space. At least one Pan/Tilt Position
- Space is required by the PTZNode to support Pan/Tilt limits. The limits apply to all supported
- absolute, relative and continuous Pan/Tilt movements. The limits shall be checked within the
- coordinate system for which the limits have been specified. That means that even if
- movements are specified in a different coordinate system, the requested movements shall be
- transformed to the coordinate system of the limits where the limits can be checked. When a
- relative or continuous movements is specified, which would leave the specified limits, the PTZ
- unit has to move along the specified limits. The Zoom Limits have to be interpreted
- accordingly.
-
-
-
-
-
-
- Set/update a existing PTZConfiguration on the device.
-
-
-
-
-
-
- List supported coordinate systems including their range limitations. Therefore, the options
- MAY differ depending on whether the PTZ Configuration is assigned to a Profile containing a
- Video Source Configuration. In that case, the options may additionally contain coordinate
- systems referring to the image coordinate system described by the Video Source
- Configuration. If the PTZ Node supports continuous movements, it shall return a Timeout Range within
- which Timeouts are accepted by the PTZ Node.
-
-
-
-
-
-
- Operation to send auxiliary commands to the PTZ device
- mapped by the PTZNode in the selected profile. The
- operation is supported
- if the AuxiliarySupported element of the PTZNode is true
-
-
-
-
-
-
- Operation to request all PTZ presets for the PTZNode
- in the selected profile. The operation is supported if there is support
- for at least on PTZ preset by the PTZNode.
-
-
-
-
-
- The SetPreset command saves the current device position parameters so that the device can
- move to the saved preset position through the GotoPreset operation.
- In order to create a new preset, the SetPresetRequest contains no PresetToken. If creation is
- successful, the Response contains the PresetToken which uniquely identifies the Preset. An
- existing Preset can be overwritten by specifying the PresetToken of the corresponding Preset.
- In both cases (overwriting or creation) an optional PresetName can be specified. The
- operation fails if the PTZ device is moving during the SetPreset operation.
- The device MAY internally save additional states such as imaging properties in the PTZ
- Preset which then should be recalled in the GotoPreset operation.
-
-
-
-
-
- Operation to remove a PTZ preset for the Node in
- the
- selected profile. The operation is supported if the
- PresetPosition
- capability exists for teh Node in the
- selected profile.
-
-
-
-
-
-
- Operation to go to a saved preset position for the
- PTZNode in the selected profile. The operation is supported if there is
- support for at least on PTZ preset by the PTZNode.
-
-
-
-
-
- Operation to move the PTZ device to it's "home" position. The operation is supported if the HomeSupported element in the PTZNode is true.
-
-
-
-
- Operation to save current position as the home position.
- The SetHomePosition command returns with a failure if the “home” position is fixed and
- cannot be overwritten. If the SetHomePosition is successful, it is possible to recall the
- Home Position with the GotoHomePosition command.
-
-
-
-
- Operation for continuous Pan/Tilt and Zoom movements. The operation is supported if the PTZNode supports at least one continuous Pan/Tilt or Zoom space. If the space argument is omitted, the default space set by the PTZConfiguration will be used.
-
-
-
-
- Operation for Relative Pan/Tilt and Zoom Move. The operation is supported if the PTZNode supports at least one relative Pan/Tilt or Zoom space.
- The speed argument is optional. If an x/y speed value is given it is up to the device to either use
- the x value as absolute resoluting speed vector or to map x and y to the component speed.
- If the speed argument is omitted, the default speed set by the PTZConfiguration will be used.
-
-
-
-
-
-
- Operation to request PTZ status for the Node in the
- selected profile.
-
-
-
-
- Operation to move pan,tilt or zoom to a absolute destination.
- The speed argument is optional. If an x/y speed value is given it is up to the device to either use
- the x value as absolute resoluting speed vector or to map x and y to the component speed.
- If the speed argument is omitted, the default speed set by the PTZConfiguration will be used.
-
-
-
-
-
- Operation to stop ongoing pan, tilt and zoom movements of absolute relative and continuous type.
-If no stop argument for pan, tilt or zoom is set, the device will stop all ongoing pan, tilt and zoom movements.
-
-
-
-
- Operation to request PTZ preset tours in the selected media profiles.
-
-
-
-
- Operation to request a specific PTZ preset tour in the selected media profile.
-
-
-
-
- Operation to request available options to configure PTZ preset tour.
-
-
-
-
- Operation to create a preset tour for the selected media profile.
-
-
-
-
- Operation to modify a preset tour for the selected media profile.
-
-
-
-
- Operation to perform specific operation on the preset tour in selected media profile.
-
-
-
-
- Operation to delete a specific preset tour from the media profile.
-
-
-
-
- Operation to get all available PTZConfigurations that can be added to the referenced media profile.
- A device providing more than one PTZConfiguration or more than one VideoSourceConfiguration or which has any other resource
- interdependency between PTZConfiguration entities and other resources listable in a media profile should implement this operation.
- PTZConfiguration entities returned by this operation shall not fail on adding them to the referenced media profile.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/soap-envelop.xsd b/onvif/wsdl/soap-envelop.xsd
deleted file mode 100644
index b1a20e08e..000000000
--- a/onvif/wsdl/soap-envelop.xsd
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Prose in the spec does not specify that attributes are allowed on the Body element
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Fault reporting structure
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/t-1.xsd b/onvif/wsdl/t-1.xsd
deleted file mode 100644
index ae42cfbc7..000000000
--- a/onvif/wsdl/t-1.xsd
+++ /dev/null
@@ -1,188 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- TopicPathExpression ::= TopicPath ( '|' TopicPath )*
- TopicPath ::= RootTopic ChildTopicExpression*
- RootTopic ::= NamespacePrefix? ('//')? (NCName | '*')
- NamespacePrefix ::= NCName ':'
- ChildTopicExpression ::= '/' '/'? (QName | NCName | '*'| '.')
-
-
-
-
-
-
-
-
-
-
-
-
- The pattern allows strings matching the following EBNF:
- ConcreteTopicPath ::= RootTopic ChildTopic*
- RootTopic ::= QName
- ChildTopic ::= '/' (QName | NCName)
-
-
-
-
-
-
-
-
-
-
-
-
- The pattern allows strings matching the following EBNF:
- RootTopic ::= QName
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/wsdd-discovery-1.1-schema-os.xsd b/onvif/wsdl/wsdd-discovery-1.1-schema-os.xsd
deleted file mode 100644
index 3307efc1d..000000000
--- a/onvif/wsdl/wsdd-discovery-1.1-schema-os.xsd
+++ /dev/null
@@ -1,230 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/wsdd-discovery-1.1-wsdl-os.wsdl b/onvif/wsdl/wsdd-discovery-1.1-wsdl-os.wsdl
deleted file mode 100644
index 36936b2a1..000000000
--- a/onvif/wsdl/wsdd-discovery-1.1-wsdl-os.wsdl
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/wsdiscovery-udp.wsdl b/onvif/wsdl/wsdiscovery-udp.wsdl
deleted file mode 100644
index 54b9fc92d..000000000
--- a/onvif/wsdl/wsdiscovery-udp.wsdl
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/wsdl.xsd b/onvif/wsdl/wsdl.xsd
deleted file mode 100644
index a81ab5691..000000000
--- a/onvif/wsdl/wsdl.xsd
+++ /dev/null
@@ -1,314 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type is extended by component types to allow them to be documented
-
-
-
-
-
-
-
-
-
-
-
-
- This type is extended by component types to allow attributes from other namespaces to be added.
-
-
-
-
-
-
-
-
-
-
-
-
- This type is extended by component types to allow elements from other namespaces to be added.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Any top level optional element allowed to appear more then once - any child of definitions element except wsdl:types. Any extensibility element is allowed in any place.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/wsdl11soap12.xsd b/onvif/wsdl/wsdl11soap12.xsd
deleted file mode 100644
index a5e7a0b94..000000000
--- a/onvif/wsdl/wsdl11soap12.xsd
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/onvif/wsdl/xmlmime.xsd b/onvif/wsdl/xmlmime.xsd
deleted file mode 100644
index 766a07bd9..000000000
--- a/onvif/wsdl/xmlmime.xsd
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/onvif/wsdl/xop-include.xsd b/onvif/wsdl/xop-include.xsd
deleted file mode 100644
index edb43a086..000000000
--- a/onvif/wsdl/xop-include.xsd
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index e9dd6ddd3..37f93fd12 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -16,6 +16,7 @@ configure_file(zmvideo.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" @ONLY)
configure_file(zmwatch.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" @ONLY)
configure_file(zmcamtool.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmcamtool.pl" @ONLY)
configure_file(zmsystemctl.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmsystemctl.pl" @ONLY)
+configure_file(zmtelemetry.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmtelemetry.pl" @ONLY)
if(NOT ZM_NO_X10)
configure_file(zmx10.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmx10.pl" @ONLY)
endif(NOT ZM_NO_X10)
@@ -31,7 +32,7 @@ FOREACH(PERLSCRIPT ${perlscripts})
ENDFOREACH(PERLSCRIPT ${perlscripts})
# Install the perl scripts
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmaudit.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmupdate.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcamtool.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmsystemctl.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmaudit.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmupdate.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcamtool.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmsystemctl.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtelemetry.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
if(NOT ZM_NO_X10)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmx10.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif(NOT ZM_NO_X10)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
index 9a065f8cf..d75a77e45 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
+++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
@@ -1985,7 +1985,7 @@ our @options =
You can use filters to instruct ZoneMinder to upload events to
a remote server. This option indicates the password that
ZoneMinder should use to log in for transfer. If you are using
- certicate based logins for SFTP servers you can leave this
+ certificate based logins for SFTP servers you can leave this
option blank.
"),
requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ],
@@ -2077,6 +2077,21 @@ our @options =
type => $types{integer},
category => "upload",
},
+ {
+ name => "ZM_UPLOAD_STRICT",
+ default => "no",
+ description => "Require strict host key checking for SFTP uploads",
+ help => qqq("
+ You can require SFTP uploads to verify the host key of the remote server
+ for protection against man-in-the-middle attacks. You will need to add the
+ server's key to the known_hosts file. On most systems, this will be
+ ~/.ssh/known_hosts, where ~ is the home directory of the web server running
+ ZoneMinder.
+ "),
+ requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ],
+ type => $types{boolean},
+ category => "upload",
+ },
{
name => "ZM_UPLOAD_FTP_PASSIVE",
default => "yes",
@@ -2731,6 +2746,44 @@ body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% s
type => $types{boolean},
category => "system",
},
+ {
+ name => "ZM_TELEMETRY_DATA",
+ default => "yes",
+ description => "Send usage information to ZoneMinder",
+ help => qqq("
+ Enable collection of usage information of the local system and send
+ it to the ZoneMinder development team. This data will be used to
+ determine things like who and where our customers are, how big their
+ systems are, the underlying hardware and operating system, etc.
+ This is being done for the sole purpoase of creating a better
+ product for our target audience. This script is intended to be
+ completely transparent to the end user, and can be disabled from
+ the web console under Options.
+ "),
+ type => $types{boolean},
+ category => "system",
+ },
+ {
+ name => "ZM_TELEMETRY_UUID",
+ default => "",
+ description => "Unique identifier for ZoneMinder telemetry",
+ help => qqq("
+ This variable is auto-generated once by the system and is used to
+ uniquely identify it among all other ZoneMinder systems in
+ existence.
+ "),
+ type => $types{string},
+ category => "dynamic",
+ },
+ {
+ name => "ZM_TELEMETRY_LAST_UPLOAD",
+ default => "",
+ description => "When the last ZoneMinder telemetry upload ocurred",
+ help => "",
+ type => $types{integer},
+ readonly => 1,
+ category => "dynamic",
+ },
{
name => "ZM_UPDATE_CHECK_PROXY",
default => "",
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm
index 4a7bab230..739ff1175 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm
@@ -155,7 +155,7 @@ sub reset
#my $cmd = "setOSDSetting%26isEnableTimeStamp%3D0%26isEnableDevName%3D1%26dispPos%3D0%26isEnabledOSDMask%3D0";
Info ("Sending reboot $cmd");
$self->sendCmd( $cmd );
- # Setup For Stream=0 Resolution=720p Bandwith=4M FPS=30 KeyFrameInterval/GOP=100 VBR=ON
+ # Setup For Stream=0 Resolution=720p Bandwidth=4M FPS=30 KeyFrameInterval/GOP=100 VBR=ON
#$cmd = "setVideoStreamParam%26streamType%3D0%26resolution%3D0%26bitRate%3D4194304%26frameRate%3D30%26GOP%3D100%26isVBR%3D1";
#$self->sendCmd( $cmd );
# Setup For Infrared AUTO
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCC7210W.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCC7210W.pm
new file mode 100755
index 000000000..cd21316d3
--- /dev/null
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCC7210W.pm
@@ -0,0 +1,377 @@
+# ==========================================================================
+#
+# ZoneMinder IPCC-7210W IP Control Protocol Module, $Date: 2015-11-18$, $Revision: 0001$
+# Modified for use with IPCC-7210W on Nov 2015
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the implementation of the
+# IPCC-7210W IP camera control protocol
+#
+package ZoneMinder::Control::IPCC-7210W;
+
+use 5.006;
+use strict;
+use warnings;
+
+require ZoneMinder::Base;
+require ZoneMinder::Control;
+
+our @ISA = qw(ZoneMinder::Control);
+
+# ==========================================================================
+#
+# IPCC-7210W IP Control Protocol
+#
+# ==========================================================================
+
+use ZoneMinder::Logger qw(:all);
+use ZoneMinder::Config qw(:all);
+
+use Time::HiRes qw( usleep );
+
+sub new
+{
+ my $class = shift;
+ my $id = shift;
+ my $self = ZoneMinder::Control->new( $id );
+ bless( $self, $class );
+ srand( time() );
+ return $self;
+}
+
+our $AUTOLOAD;
+
+sub AUTOLOAD
+{
+ my $self = shift;
+ my $class = ref($self) || croak( "$self not object" );
+ my $name = $AUTOLOAD;
+ $name =~ s/.*://;
+ if ( exists($self->{$name}) )
+ {
+ return( $self->{$name} );
+ }
+ Fatal( "Can't access $name member of object of class $class" );
+}
+
+sub open
+{
+ my $self = shift;
+
+ $self->loadMonitor();
+
+ use LWP::UserAgent;
+ $self->{ua} = LWP::UserAgent->new;
+ $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
+
+ $self->{state} = 'open';
+}
+
+sub close
+{
+ my $self = shift;
+ $self->{state} = 'closed';
+}
+
+sub printMsg
+{
+ my $self = shift;
+ my $msg = shift;
+ my $msg_len = length($msg);
+
+ Debug( $msg."[".$msg_len."]" );
+}
+
+sub sendCmd
+{
+ my $self = shift;
+ my $cmd = shift;
+
+ my $result = undef;
+
+ printMsg( $cmd, "Tx" );
+
+ #print( "http://$address/$cmd\n" );
+ my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd".$self->{Monitor}->{ControlDevice} );
+ Info( "http://".$self->{Monitor}->{ControlAddress}."/$cmd".$self->{Monitor}->{ControlDevice} );
+ my $res = $self->{ua}->request($req);
+
+ if ( $res->is_success )
+ {
+ $result = !undef;
+ }
+ else
+ {
+ Error( "Error check failed: '".$res->status_line()."'" );
+ }
+
+ return( $result );
+}
+
+
+sub cameraReset
+{
+ my $self = shift;
+ Debug( "Camera Reset" );
+ my $cmd = "reboot.cgi?";
+ $self->sendCmd( $cmd );
+}
+
+
+#Up Arrow
+sub moveConUp
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Up" );
+ my $cmd = "decoder_control.cgi?command=0&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Down Arrow
+sub moveConDown
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Down" );
+ my $cmd = "decoder_control.cgi?command=2&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Left Arrow
+sub moveConLeft
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Left" );
+ my $cmd = "decoder_control.cgi?command=4&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Right Arrow
+sub moveConRight
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Right" );
+ my $cmd = "decoder_control.cgi?command=6&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Up Right Arrow
+sub moveConUpRight
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Up Right" );
+ my $cmd = "decoder_control.cgi?command=91&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Down Right Arrow
+sub moveConDownRight
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Down Right" );
+ my $cmd = "decoder_control.cgi?command=93&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Up Left Arrow
+sub moveConUpLeft
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Up Left" );
+ my $cmd = "decoder_control.cgi?command=90&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Down Left Arrow
+sub moveConDownLeft
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Down Left" );
+ my $cmd = "decoder_control.cgi?command=92&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Stop
+sub moveStop
+{
+ my $self = shift;
+ Debug( "Move Stop" );
+ my $cmd = "decoder_control.cgi?command=1&onestep=1&";
+ $self->sendCmd( $cmd );
+}
+
+#Move Camera to Home Position
+sub presetHome
+{
+ my $self = shift;
+ Debug( "Home Preset" );
+ my $cmd = "decoder_control.cgi?command=25&onestep=0&";
+ $self->sendCmd( $cmd );
+}
+
+# zoom out
+sub zoomRelTele
+{
+ my $self = shift;
+ Debug( "Zoom Tele" );
+ my $cmd = "camera_control.cgi?param=17&value=1&";
+ $self->sendCmd( $cmd );
+}
+
+#zoom in
+sub zoomRelWide
+{
+ my $self = shift;
+ Debug( "Zoom Wide" );
+ my $cmd = "camera_control.cgi?param=18&value=1&";
+ $self->sendCmd( $cmd );
+}
+
+
+#Set preset
+sub presetSet
+{
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam( $params, 'preset' );
+ my $presetCmd = 30 + (($preset-1)*2);
+ Debug( "Set Preset $preset with cmd $presetCmd" );
+ my $cmd = "decoder_control.cgi?command=$presetCmd&onestep=0&sit=$presetCmd&";
+ $self->sendCmd( $cmd );
+}
+
+#Goto preset
+sub presetGoto
+{
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam( $params, 'preset' );
+ my $presetCmd = 31 + (($preset-1)*2);
+ Debug( "Goto Preset $preset with cmd $presetCmd" );
+ my $cmd = "decoder_control.cgi?command=$presetCmd&onestep=0&sit=$presetCmd&";
+ $self->sendCmd( $cmd );
+}
+
+#Turn IR on
+sub wake
+{
+ my $self = shift;
+ Debug( "Wake - IR on" );
+ my $cmd = "camera_control.cgi?param=14&value=1&";
+ $self->sendCmd( $cmd );
+}
+
+#Turn IR off
+sub sleep
+{
+ my $self = shift;
+ Debug( "Sleep - IR off" );
+ my $cmd = "camera_control.cgi?param=14&value=0&";
+ $self->sendCmd( $cmd );
+}
+1;
+__END__
+
+
+
+# Below is stub documentation for your module. You'd better edit it!
+
+=head1 NAME
+
+ZoneMinder::IPCC-7210W - Perl extension for IPCC-7210W PTZ control
+
+=head1 SYNOPSIS
+
+ use ZoneMinder::Control::IPCC
+
+=head1 DESCRIPTION
+
+This script provides Pan/Tilt/Zoom control for IPCC-7210W camera.
+
+=head1 SEE ALSO
+
+ZoneMinder::Control::Wanscam
+
+=head1 AUTHOR
+
+
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2001-2008
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.3 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Netcat.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Netcat.pm
new file mode 100644
index 000000000..0e273b5b7
--- /dev/null
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Netcat.pm
@@ -0,0 +1,483 @@
+# ==========================================================================
+#
+# ZoneMinder Netcat IP Control Protocol Module, $Date: 2009-11-25 09:20:00 +0000 (Wed, 04 Nov 2009) $, $Revision: 0001 $
+# Copyright (C) 2001-2008 Philip Coombes
+# Converted for use with Netcat IP Camera by Andrew Bauer (knnniggett@users.sourceforge.net)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the first implementation of the Netcat IP camera control
+# protocol
+#
+package ZoneMinder::Control::Netcat;
+
+use 5.006;
+use strict;
+use warnings;
+
+require ZoneMinder::Base;
+require ZoneMinder::Control;
+
+our @ISA = qw(ZoneMinder::Control);
+
+our %CamParams = ();
+
+# ==========================================================================
+#
+# Netcat IP Control Protocol
+# This script sends ONVIF compliant commands and may work with other cameras
+#
+# The Netcat camera gladly accepts any command with or without authentication,
+# which prevented me from developing Onvif authentication in this control script.
+#
+# Basic preset functions are supported, but more advanced features, which make
+# use of abnormally high preset numbers (ir lamp control, tours, pan speed, etc)
+# may or may not work.
+#
+#
+# Possible future improvements (for anyone to improve upon):
+# - Onvif authentication
+# - Build the SOAP commands at runtime rather than use templates
+# - Implement previously mentioned advanced features
+#
+# Implementing the first two will require additional Perl modules, and adding
+# more dependencies to ZoneMinder is always a concern.
+#
+# On ControlAddress use the format :
+# ADDRESS:PORT
+# eg : 10.1.2.1:8899
+# 10.0.100.1:8899
+#
+# Use port 8899 for the Netcat camera
+#
+# Make sure and place a value in the Auto Stop Timeout field.
+# Recommend starting with a value of 1 second, and adjust accordingly.
+#
+# ==========================================================================
+
+use ZoneMinder::Logger qw(:all);
+use ZoneMinder::Config qw(:all);
+
+use Time::HiRes qw( usleep );
+
+sub new
+{
+
+ my $class = shift;
+ my $id = shift;
+ my $self = ZoneMinder::Control->new( $id );
+ my $logindetails = "";
+ bless( $self, $class );
+ srand( time() );
+ return $self;
+}
+
+our $AUTOLOAD;
+
+sub AUTOLOAD
+{
+ my $self = shift;
+ my $class = ref( ) || croak( "$self not object" );
+ my $name = $AUTOLOAD;
+ $name =~ s/.*://;
+ if ( exists($self->{$name}) )
+ {
+ return( $self->{$name} );
+ }
+ Fatal( "Can't access $name member of object of class $class" );
+ }
+
+sub open
+{
+ my $self = shift;
+
+ $self->loadMonitor();
+
+ use LWP::UserAgent;
+ $self->{ua} = LWP::UserAgent->new;
+ $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
+
+ $self->{state} = 'open';
+}
+
+sub close
+{
+ my $self = shift;
+ $self->{state} = 'closed';
+}
+
+sub printMsg
+{
+ my $self = shift;
+ my $msg = shift;
+ my $msg_len = length($msg);
+
+ Debug( $msg."[".$msg_len."]" );
+}
+
+sub sendCmd
+{
+ my $self = shift;
+ my $cmd = shift;
+ my $msg = shift;
+ my $content_type = shift;
+ my $result = undef;
+
+ printMsg( $cmd, "Tx" );
+
+ my $server_endpoint = "http://".$self->{Monitor}->{ControlAddress}."/$cmd";
+ my $req = HTTP::Request->new( POST => $server_endpoint );
+ $req->header('content-type' => $content_type);
+ $req->header('Host' => $self->{Monitor}->{ControlAddress});
+ $req->header('content-length' => length($msg));
+ $req->header('accept-encoding' => 'gzip, deflate');
+ $req->header('connection' => 'Close');
+ $req->content($msg);
+
+ my $res = $self->{ua}->request($req);
+
+ if ( $res->is_success ) {
+ $result = !undef;
+ } else {
+ Error( "After sending PTZ command, camera returned the following error:'".$res->status_line()."'" );
+ }
+ return( $result );
+}
+
+sub getCamParams
+{
+ my $self = shift;
+ my $msg = '000';
+ my $server_endpoint = "http://".$self->{Monitor}->{ControlAddress}."/onvif/imaging";
+ my $req = HTTP::Request->new( POST => $server_endpoint );
+ $req->header('content-type' => 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/GetImagingSettings"');
+ $req->header('Host' => $self->{Monitor}->{ControlAddress});
+ $req->header('content-length' => length($msg));
+ $req->header('accept-encoding' => 'gzip, deflate');
+ $req->header('connection' => 'Close');
+ $req->content($msg);
+
+ my $res = $self->{ua}->request($req);
+
+ if ( $res->is_success ) {
+ # We should really use an xml or soap library to parse the xml tags
+ my $content = $res->decoded_content;
+
+ if ($content =~ /.*(.+)<\/tt:Brightness>.*/) {
+ $CamParams{$1} = $2;
+ }
+ if ($content =~ /.*(.+)<\/tt:Contrast>.*/) {
+ $CamParams{$1} = $2;
+ }
+ }
+ else
+ {
+ Error( "Unable to retrieve camera image settings:'".$res->status_line()."'" );
+ }
+}
+
+#autoStop
+#This makes use of the ZoneMinder Auto Stop Timeout on the Control Tab
+sub autoStop
+{
+ my $self = shift;
+ my $autostop = shift;
+
+ if( $autostop ) {
+ Debug( "Auto Stop" );
+ my $cmd = 'onvif/PTZ';
+ my $msg = '000truefalse';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ usleep( $autostop );
+ $self->sendCmd( $cmd, $msg, $content_type );
+ }
+}
+
+# Reset the Camera
+sub reset
+{
+ Debug( "Camera Reset" );
+ my $self = shift;
+ my $cmd = "";
+ my $msg = '';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/device/wsdl/SystemReboot"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+}
+
+#Up Arrow
+sub moveConUp
+{
+ Debug( "Move Up" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Down Arrow
+sub moveConDown
+{
+ Debug( "Move Down" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Left Arrow
+sub moveConLeft
+{
+ Debug( "Move Left" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Right Arrow
+sub moveConRight
+{
+ Debug( "Move Right" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Zoom In
+sub zoomConTele
+{
+ Debug( "Zoom Tele" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Zoom Out
+sub zoomConWide
+{
+ Debug( "Zoom Wide" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Diagonally Up Right Arrow
+#This camera does not have builtin diagonal commands so we emulate them
+sub moveConUpRight
+{
+ Debug( "Move Diagonally Up Right" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Diagonally Down Right Arrow
+#This camera does not have builtin diagonal commands so we emulate them
+sub moveConDownRight
+{
+ Debug( "Move Diagonally Down Right" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Diagonally Up Left Arrow
+#This camera does not have builtin diagonal commands so we emulate them
+sub moveConUpLeft
+{
+ Debug( "Move Diagonally Up Left" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Diagonally Down Left Arrow
+#This camera does not have builtin diagonal commands so we emulate them
+sub moveConDownLeft
+{
+ Debug( "Move Diagonally Down Left" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+ $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
+}
+
+#Stop
+sub moveStop
+{
+ Debug( "Move Stop" );
+ my $self = shift;
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000truefalse';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+}
+
+#Set Camera Preset
+sub presetSet
+{
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam( $params, 'preset' );
+ Debug( "Set Preset $preset" );
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000'.$preset.'';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/SetPreset"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+}
+
+#Recall Camera Preset
+sub presetGoto
+{
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam( $params, 'preset' );
+ Debug( "Goto Preset $preset" );
+ my $cmd = 'onvif/PTZ';
+ my $msg ='000'.$preset.'';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/GotoPreset"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+}
+
+#Horizontal Patrol
+#To be determined if this camera supports this feature
+sub horizontalPatrol
+{
+ Debug( "Horizontal Patrol" );
+ my $self = shift;
+ my $cmd = '';
+ my $msg ='';
+ my $content_type = '';
+# $self->sendCmd( $cmd, $msg, $content_type );
+ Error( "PTZ Command not implemented in control script." );
+}
+
+#Horizontal Patrol Stop
+#To be determined if this camera supports this feature
+sub horizontalPatrolStop
+{
+ Debug( "Horizontal Patrol Stop" );
+ my $self = shift;
+ my $cmd = '';
+ my $msg ='';
+ my $content_type = '';
+# $self->sendCmd( $cmd, $msg, $content_type );
+ Error( "PTZ Command not implemented in control script." );
+}
+
+# Increase Brightness
+sub irisAbsOpen
+{
+ Debug( "Iris $CamParams{'Brightness'}" );
+ my $self = shift;
+ my $params = shift;
+ $self->getCamParams() unless($CamParams{'Brightness'});
+ my $step = $self->getParam( $params, 'step' );
+ my $max = 100;
+
+ $CamParams{'Brightness'} += $step;
+ $CamParams{'Brightness'} = $max if ($CamParams{'Brightness'} > $max);
+
+ my $cmd = 'onvif/imaging';
+ my $msg ='000'.$CamParams{'Brightness'}.'true';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+}
+
+# Decrease Brightness
+sub irisAbsClose
+{
+ Debug( "Iris $CamParams{'Brightness'}" );
+ my $self = shift;
+ my $params = shift;
+ $self->getCamParams() unless($CamParams{'brightness'});
+ my $step = $self->getParam( $params, 'step' );
+ my $min = 0;
+
+ $CamParams{'Brightness'} -= $step;
+ $CamParams{'Brightness'} = $min if ($CamParams{'Brightness'} < $min);
+
+ my $cmd = 'onvif/imaging';
+ my $msg ='000'.$CamParams{'Brightness'}.'true';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
+ $self->sendCmd( $cmd, $msg, $content_type );
+}
+
+# Increase Contrast
+sub whiteAbsIn
+{
+ Debug( "Iris $CamParams{'Contrast'}" );
+ my $self = shift;
+ my $params = shift;
+ $self->getCamParams() unless($CamParams{'Contrast'});
+ my $step = $self->getParam( $params, 'step' );
+ my $max = 100;
+
+ $CamParams{'Contrast'} += $step;
+ $CamParams{'Contrast'} = $max if ($CamParams{'Contrast'} > $max);
+
+ my $cmd = 'onvif/imaging';
+ my $msg ='000'.$CamParams{'Contrast'}.'true';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
+}
+
+# Decrease Contrast
+sub whiteAbsOut
+{
+ Debug( "Iris $CamParams{'Contrast'}" );
+ my $self = shift;
+ my $params = shift;
+ $self->getCamParams() unless($CamParams{'Contrast'});
+ my $step = $self->getParam( $params, 'step' );
+ my $min = 0;
+
+ $CamParams{'Contrast'} -= $step;
+ $CamParams{'Contrast'} = $min if ($CamParams{'Contrast'} < $min);
+
+ my $cmd = 'onvif/imaging';
+ my $msg ='000'.$CamParams{'Contrast'}.'true';
+ my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
+}
+
+1;
+
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm
index c8fafe023..794393644 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm
@@ -133,8 +133,10 @@ sub sendCmd
my $result = undef;
+ # Pelco P protocol checksum is created by XOR'ing the first seven bytes in the message
+ # including the first byte, the STX sync packet
my $checksum = 0x00;
- for ( my $i = 1; $i < int(@$cmd); $i++ )
+ for ( my $i = 0; $i < int(@$cmd); $i++ )
{
$checksum ^= $cmd->[$i];
}
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Vivotek_ePTZ.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Vivotek_ePTZ.pm
new file mode 100644
index 000000000..3649b35bc
--- /dev/null
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Vivotek_ePTZ.pm
@@ -0,0 +1,227 @@
+# ==========================================================================
+#
+# ZoneMinder Vivotek ePTZ Control Protocol Module
+# Copyright (C) 2015 Robin Daermann
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the implementation of the Vivotek ePTZ camera control
+# protocol
+#
+package ZoneMinder::Control::Vivotek_ePTZ;
+
+use 5.006;
+use strict;
+use warnings;
+
+require ZoneMinder::Base;
+require ZoneMinder::Control;
+
+our @ISA = qw(ZoneMinder::Control);
+
+# ==========================================================================
+#
+# Vivotek ePTZ Control Protocol
+#
+# ==========================================================================
+
+use ZoneMinder::Logger qw(:all);
+use ZoneMinder::Config qw(:all);
+
+use Time::HiRes qw( usleep );
+
+sub new
+{
+ my $class = shift;
+ my $id = shift;
+ my $self = ZoneMinder::Control->new( $id );
+ Debug( "Camera New" );
+ bless( $self, $class );
+ srand( time() );
+ return $self;
+}
+
+our $AUTOLOAD;
+
+sub AUTOLOAD
+{
+ my $self = shift;
+ my $class = ref($self) || croak( "$self not object" );
+ my $name = $AUTOLOAD;
+ Debug( "Camera AUTOLOAD" );
+ $name =~ s/.*://;
+ if ( exists($self->{$name}) )
+ {
+ return( $self->{$name} );
+ }
+ Fatal( "Can't access $name member of object of class $class" );
+}
+
+sub open
+{
+ my $self = shift;
+
+ $self->loadMonitor();
+ Debug( "Camera open" );
+ use LWP::UserAgent;
+ $self->{ua} = LWP::UserAgent->new;
+ $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
+
+ $self->{state} = 'open';
+}
+
+sub close
+{
+ my $self = shift;
+ $self->{state} = 'closed';
+}
+
+sub printMsg
+{
+ my $msg = shift;
+ my $msg_len = length($msg);
+
+ Debug( $msg."[".$msg_len."]" );
+}
+
+sub sendCmd
+{
+ my ($self, $cmd, $speedcmd) = @_;
+
+ my $result = undef;
+
+ printMsg( $speedcmd, "Tx" );
+ printMsg( $cmd, "Tx" );
+
+ my $req = HTTP::Request->new( GET => "http://" . $self->{Monitor}->{ControlAddress} . "/cgi-bin/camctrl/eCamCtrl.cgi?stream=0&$speedcmd&$cmd" );
+ my $res = $self->{ua}->request($req);
+
+ if ( $res->is_success )
+ {
+ $result = !undef;
+ }
+ else
+ {
+ Error( "Request failed: '" . $res->status_line() . "' (URI: '" . $req->as_string() . "')" );
+ }
+
+ return( $result );
+}
+
+sub moveConUp
+{
+ my ($self, $params) = @_;
+ my $speed = 'speedtilt=' . ($params->{tiltspeed} - 6);
+ Debug( "Move Up" );
+ $self->sendCmd( 'move=up', $speed );
+}
+
+sub moveConDown
+{
+ my ($self, $params) = @_;
+ my $speed = 'speedtilt=' . ($params->{tiltspeed} - 6);
+ Debug( "Move Down" );
+ $self->sendCmd( 'move=down', $speed );
+}
+
+sub moveConLeft
+{
+ my ($self, $params) = @_;
+ my $speed = 'speedpan=-' . $params->{panspeed};
+ Debug( "Move Left" );
+ $self->sendCmd( 'move=left', $speed );
+}
+
+sub moveConRight
+{
+ my ($self, $params) = @_;
+ my $speed = 'speedpan=' . ($params->{panspeed} - 6);
+ Debug( "Move Right" );
+ $self->sendCmd( 'move=right', $speed );
+}
+
+sub moveStop
+{
+ my $self = shift;
+ Debug( "Move Stop" );
+ # not implemented
+}
+
+sub zoomConTele
+{
+ my ($self, $params) = @_;
+ my $speed = 'speedzoom=' . ($params->{speed} - 6);
+ Debug( "Zoom In" );
+ $self->sendCmd( 'zoom=tele', $speed );
+}
+
+sub zoomConWide
+{
+ my ($self, $params) = @_;
+ my $speed = 'speedzoom=' . ($params->{speed} - 6);
+ Debug( "Zoom Out" );
+ $self->sendCmd( 'zoom=wide', $speed );
+}
+
+sub reset
+{
+ my $self = shift;
+ Debug( "Camera Reset" );
+ $self->sendCmd( 'move=home' );
+}
+
+1;
+__END__
+
+=head1 NAME
+
+ZoneMinder::Control::Vivotek_ePTZ - ZoneMinder Perl extension for Vivotek ePTZ
+camera control protocol
+
+=head1 SYNOPSIS
+
+ use ZoneMinder::Control::Vivotek_ePTZ;
+
+=head1 DESCRIPTION
+
+This module implements the ePTZ protocol used in various Vivotek IP cameras,
+developed with a Vivotek IB8369 model.
+
+Currently, only simple pan, tilt and zoom function is implemented. Presets will
+follow later.
+
+=head2 EXPORT
+
+None.
+
+=head1 SEE ALSO
+
+I would say, see ZoneMinder::Control documentation. But it is a stub.
+
+=head1 AUTHOR
+
+Robin Daermann Er.daermann@ids-services.deE
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2015 by Robin Daermann
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.3 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/WanscamHW0025.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/WanscamHW0025.pm
new file mode 100755
index 000000000..3dd9c2cc5
--- /dev/null
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/WanscamHW0025.pm
@@ -0,0 +1,399 @@
+# ==========================================================================
+#
+# ZoneMinder Wanscam HW0025 IP Control Protocol Module, $Date: 2009-11-25 09:20:00 +0000 (Wed, 04 Nov 2009) $, $Revision: 0001 $
+# Copyright (C) 2001-2015 Florian Neumair
+# Modified for use with Foscam FI8918W IP Camera by Dave Harris
+# Modified Feb 2011 by Howard Durdle (http://durdl.es/x) to:
+# fix horizontal panning, add presets and IR on/off
+# use Control Device field to pass username and password
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+#
+# This module contains the implementation of the Wanscam HW0025 IP camera control
+# protocol
+#
+# Known working Devices:
+# * Wanscam HW0025
+# * IPCC-7210W
+#
+package ZoneMinder::Control::WanscamHW0025;
+
+use 5.006;
+use strict;
+use warnings;
+
+require ZoneMinder::Base;
+require ZoneMinder::Control;
+
+our @ISA = qw(ZoneMinder::Control);
+
+# ==========================================================================
+#
+# Wanscam HW0025 IP Control Protocol
+#
+# ==========================================================================
+
+use ZoneMinder::Logger qw(:all);
+use ZoneMinder::Config qw(:all);
+
+use Time::HiRes qw( usleep );
+
+sub new
+{
+ my $class = shift;
+ my $id = shift;
+ my $self = ZoneMinder::Control->new( $id );
+ bless( $self, $class );
+ srand( time() );
+ return $self;
+}
+
+our $AUTOLOAD;
+
+sub AUTOLOAD
+{
+ my $self = shift;
+ my $class = ref($self) || croak( "$self not object" );
+ my $name = $AUTOLOAD;
+ $name =~ s/.*://;
+ if ( exists($self->{$name}) )
+ {
+ return( $self->{$name} );
+ }
+ Fatal( "Can't access $name member of object of class $class" );
+}
+
+sub open
+{
+ my $self = shift;
+
+ $self->loadMonitor();
+
+ use LWP::UserAgent;
+ $self->{ua} = LWP::UserAgent->new;
+ $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
+
+ $self->{state} = 'open';
+}
+
+sub close
+{
+ my $self = shift;
+ $self->{state} = 'closed';
+}
+
+sub printMsg
+{
+ my $self = shift;
+ my $msg = shift;
+ my $msg_len = length($msg);
+
+ Debug( $msg."[".$msg_len."]" );
+}
+
+sub sendCmd
+{
+ my $self = shift;
+ my $cmd = shift;
+
+ my $result = undef;
+
+ printMsg( $cmd, "Tx" );
+
+ #print( "http://$address/$cmd\n" );
+ my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd".$self->{Monitor}->{ControlDevice} );
+ Info( "http://".$self->{Monitor}->{ControlAddress}."/$cmd".$self->{Monitor}->{ControlDevice} );
+ my $res = $self->{ua}->request($req);
+
+ if ( $res->is_success )
+ {
+ $result = !undef;
+ }
+ else
+ {
+ Error( "Error check failed: '".$res->status_line()."'" );
+ }
+
+ return( $result );
+}
+
+
+sub cameraReset
+{
+ my $self = shift;
+ Debug( "Camera Reset" );
+ my $cmd = "reboot.cgi?";
+ $self->sendCmd( $cmd );
+}
+
+#Up Arrow
+sub moveConUp
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Up" );
+ my $cmd = "decoder_control.cgi?command=0&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Down Arrow
+sub moveConDown
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Down" );
+ my $cmd = "decoder_control.cgi?command=2&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Left Arrow
+sub moveConLeft
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Left" );
+ my $cmd = "decoder_control.cgi?command=4&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Right Arrow
+sub moveConRight
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Right" );
+ my $cmd = "decoder_control.cgi?command=6&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Up Right Arrow
+sub moveConUpRight
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Up Right" );
+ my $cmd = "decoder_control.cgi?command=91&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Down Right Arrow
+sub moveConDownRight
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Down Right" );
+ my $cmd = "decoder_control.cgi?command=93&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Up Left Arrow
+sub moveConUpLeft
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Up Left" );
+ my $cmd = "decoder_control.cgi?command=90&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Diagonally Down Left Arrow
+sub moveConDownLeft
+{
+ my $self = shift;
+ my $params = shift;
+ Debug( "Move Diagonally Down Left" );
+ my $cmd = "decoder_control.cgi?command=92&onestep=1&";
+ $self->sendCmd( $cmd );
+ my $autostop = $self->getParam( $params, 'autostop', 0 );
+ if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
+ {
+ usleep( $self->{Monitor}->{AutoStopTimeout} );
+ $self->moveStop( $params );
+ }
+}
+
+#Stop
+sub moveStop
+{
+ my $self = shift;
+ Debug( "Move Stop" );
+ my $cmd = "decoder_control.cgi?command=1&onestep=1&";
+ $self->sendCmd( $cmd );
+}
+
+#Move Camera to Home Position
+sub presetHome
+{
+ my $self = shift;
+ Debug( "Home Preset" );
+ my $cmd = "decoder_control.cgi?command=25&onestep=0&";
+ $self->sendCmd( $cmd );
+}
+
+# zoom out
+sub zoomRelTele
+{
+ my $self = shift;
+ Debug( "Zoom Tele" );
+ my $cmd = "camera_control.cgi?param=17&value=1&";
+ $self->sendCmd( $cmd );
+}
+
+#zoom in
+sub zoomRelWide
+{
+ my $self = shift;
+ Debug( "Zoom Wide" );
+ my $cmd = "camera_control.cgi?param=18&value=1&";
+ $self->sendCmd( $cmd );
+}
+
+
+#Set preset
+sub presetSet
+{
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam( $params, 'preset' );
+ my $presetCmd = 30 + (($preset-1)*2);
+ Debug( "Set Preset $preset with cmd $presetCmd" );
+ my $cmd = "decoder_control.cgi?command=$presetCmd&onestep=0&sit=$presetCmd&";
+ $self->sendCmd( $cmd );
+}
+
+#Goto preset
+sub presetGoto
+{
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam( $params, 'preset' );
+ my $presetCmd = 31 + (($preset-1)*2);
+ Debug( "Goto Preset $preset with cmd $presetCmd" );
+ my $cmd = "decoder_control.cgi?command=$presetCmd&onestep=0&sit=$presetCmd&";
+ $self->sendCmd( $cmd );
+}
+
+#Turn IR on
+sub wake
+{
+ my $self = shift;
+ Debug( "Wake - IR on" );
+ my $cmd = "camera_control.cgi?param=14&value=1&";
+ $self->sendCmd( $cmd );
+}
+
+#Turn IR off
+sub sleep
+{
+ my $self = shift;
+ Debug( "Sleep - IR off" );
+ my $cmd = "camera_control.cgi?param=14&value=0&";
+ $self->sendCmd( $cmd );
+}
+1;
+__END__
+# Below is stub documentation for your module. You'd better edit it!
+
+=head1 NAME
+
+ZoneMinder::Database - Perl extension for blah blah blah
+
+=head1 SYNOPSIS
+
+ use ZoneMinder::Control::Wanscam
+ blah blah blah
+
+=head1 DESCRIPTION
+
+Stub documentation for ZoneMinder, created by h2xs. It looks like the
+author of the extension was negligent enough to leave the stub
+unedited.
+
+Blah blah blah.
+=head2 EXPORT
+
+None by default.
+
+
+
+=head1 SEE ALSO
+
+Mention other useful documentation such as the documentation of
+related modules or operating system documentation (such as man pages
+in UNIX), or any relevant external documentation such as RFCs or
+standards.
+
+If you have a mailing list set up for your module, mention it here.
+
+If you have a web site set up for your module, mention it here.
+
+=head1 AUTHOR
+
+Philip Coombes,
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2001-2008 Philip Coombes
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.3 or,
+at your option, any later version of Perl 5 you may have available.
+
+
+=cut
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm
index 6c4254a7e..0a4bdea8a 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm
@@ -62,7 +62,10 @@ sub open
local *sfh;
#sysopen( *sfh, $conn->{path}, O_NONBLOCK|O_RDONLY ) or croak( "Can't sysopen: $!" );
#open( *sfh, "<".$conn->{path} ) or croak( "Can't open: $!" );
- open( *sfh, "+<", $self->{path} ) or croak( "Can't open: $!" );
+ if ( ! open( *sfh, "+<", $self->{path} ) ) {
+ Error( "Can't open file at $$self{path}: $!" );
+ croak( "Can't open file at $$self{path}: $!" );
+ }
$self->{state} = 'open';
$self->{handle} = *sfh;
}
@@ -73,7 +76,7 @@ __END__
=head1 NAME
-ZoneMinder::Database - Perl extension for blah blah blah
+ZoneMinder::Trigger::Channel::File - ZOneMinder object for a file based trigger channel
=head1 SYNOPSIS
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm
index 6c5f21961..0f977f3da 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm
@@ -61,12 +61,21 @@ sub open
{
my $self = shift;
local *sfh;
- my $saddr = sockaddr_in( $self->{port}, INADDR_ANY );
- socket( *sfh, PF_INET, SOCK_STREAM, getprotobyname('tcp') )
- or croak( "Can't open socket: $!" );
+ if ( ! socket( *sfh, PF_INET, SOCK_STREAM, getprotobyname('tcp') ) ) {
+ Error( "Can't open socket: $!" );
+ croak( "Can't open socket: $!" );
+ }
setsockopt( *sfh, SOL_SOCKET, SO_REUSEADDR, 1 );
- bind( *sfh, $saddr ) or croak( "Can't bind: $!" );
- listen( *sfh, SOMAXCONN ) or croak( "Can't listen: $!" );
+
+ my $saddr = sockaddr_in( $self->{port}, INADDR_ANY );
+ if ( ! bind( *sfh, $saddr ) ) {
+ Error( "Can't bind to port $$self{port}: $!" );
+ croak( "Can't bind to port $$self{port}: $!" );
+ }
+ if ( ! listen( *sfh, SOMAXCONN ) ) {
+ Error( "Can't listen: $!" );
+ croak( "Can't listen: $!" );
+ }
$self->{state} = 'open';
$self->{handle} = *sfh;
}
@@ -95,7 +104,7 @@ __END__
=head1 NAME
-ZoneMinder::Database - Perl extension for blah blah blah
+ZoneMinder::Trigger::Channel::Inet
=head1 SYNOPSIS
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm
index 71d6e89fc..ea74c957e 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm
@@ -63,9 +63,18 @@ sub open
local *sfh;
unlink( $self->{path} );
my $saddr = sockaddr_un( $self->{path} );
- socket( *sfh, PF_UNIX, SOCK_STREAM, 0 ) or croak( "Can't open socket: $!" );
- bind( *sfh, $saddr ) or croak( "Can't bind: $!" );
- listen( *sfh, SOMAXCONN ) or croak( "Can't listen: $!" );
+ if ( ! socket( *sfh, PF_UNIX, SOCK_STREAM, 0 ) ) {
+ Error( "Can't open unix socket at $$self{path}: $!" );
+ croak( "Can't open unix socket at $$self{path}: $!" );
+ }
+ if ( ! bind( *sfh, $saddr ) ) {
+ Error( "Can't bind unix socket at $$self{path}: $!" );
+ croak( "Can't bind unix socket at $$self{path}: $!" );
+ }
+ if ( ! listen( *sfh, SOMAXCONN ) ) {
+ Error( "Can't listen: $!" );
+ croak( "Can't listen: $!" );
+ }
$self->{handle} = *sfh;
}
@@ -93,12 +102,11 @@ __END__
=head1 NAME
-ZoneMinder::Database - Perl extension for blah blah blah
+ZoneMinder::Trigger::Channel::Unix - Object for Unix socket channel
=head1 SYNOPSIS
- use ZoneMinder::Database;
- blah blah blah
+See zmtrigger.pl
=head1 DESCRIPTION
diff --git a/scripts/zmcamtool.pl.in b/scripts/zmcamtool.pl.in
index eaa32edef..8d6a6321c 100644
--- a/scripts/zmcamtool.pl.in
+++ b/scripts/zmcamtool.pl.in
@@ -419,9 +419,9 @@ sub toPreset
foreach (@data) {
s/\b(?:\d{1,3}\.){3}\d{1,3}\b//; # ip address
s/:(6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)$/:/; # tcpip port
- s/\/\/.*:.*@/\/\/:@/; # user & pwd preceeding an ip address
- s/(&|\?)(user|username)=\w\w*(&|\?)/$1$2=$3/i; # username embeded in url
- s/(&|\?)(pwd|password)=\w\w*(&|\?)/$1$2=$3/i; # password embeded in url
+ s/\/\/.*:.*@/\/\/:@/; # user & pwd preceding an ip address
+ s/(&|\?)(user|username)=\w\w*(&|\?)/$1$2=$3/i; # username embedded in url
+ s/(&|\?)(pwd|password)=\w\w*(&|\?)/$1$2=$3/i; # password embedded in url
s/\w\w*:\w\w*/:/; # user & pwd in their own field
s/\/dev\/video\d\d*/\/dev\/video>/; # local video devices
}
diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in
index 5e2fb47c7..b120e2846 100644
--- a/scripts/zmdc.pl.in
+++ b/scripts/zmdc.pl.in
@@ -87,7 +87,8 @@ my @daemons = (
'zmx10.pl',
'zmwatch.pl',
'zmupdate.pl',
- 'zmtrack.pl'
+ 'zmtrack.pl',
+ 'zmtelemetry.pl',
);
my $command = shift @ARGV;
@@ -250,13 +251,15 @@ sub run
{
print( $PID $$ );
close( $PID );
+ } else {
+ Error( "Can't open pid file at " . ZM_PID );
}
killAll( 1 );
socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
- unlink( main::SOCK_FILE );
- bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" );
+ unlink( main::SOCK_FILE ) or Error( "Unable to unlink " . main::SOCK_FILE );
+ bind( SERVER, $saddr ) or Fatal( "Can't bind to " . main::SOCK_FILE . ": $!" );
listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" );
$SIG{CHLD} = \&reaper;
diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in
index d98d31809..1db114d9d 100755
--- a/scripts/zmfilter.pl.in
+++ b/scripts/zmfilter.pl.in
@@ -935,7 +935,8 @@ sub uploadArchFile
if $Config{ZM_UPLOAD_PORT};
$sftpOptions{timeout} = $Config{ZM_UPLOAD_TIMEOUT}
if $Config{ZM_UPLOAD_TIMEOUT};
- $sftpOptions{more} = [ '-o'=>'StrictHostKeyChecking=no' ];
+ $sftpOptions{more} = [ '-o'=>'StrictHostKeyChecking=no' ]
+ if ! $Config{ZM_UPLOAD_STRICT};
$Net::SFTP::Foreign::debug = -1
if $Config{ZM_UPLOAD_DEBUG};
my $sftp = Net::SFTP::Foreign->new( $Config{ZM_UPLOAD_HOST}, %sftpOptions );
diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in
index 183f8084c..53e29a8da 100644
--- a/scripts/zmpkg.pl.in
+++ b/scripts/zmpkg.pl.in
@@ -285,6 +285,10 @@ if ( $command =~ /^(?:start|restart)$/ )
{
runCommand( "zmdc.pl start zmupdate.pl -c" );
}
+ if ( $Config{ZM_TELEMETRY_DATA} )
+ {
+ runCommand( "zmdc.pl start zmtelemetry.pl" );
+ }
}
else
{
diff --git a/scripts/zmtelemetry.pl.in b/scripts/zmtelemetry.pl.in
new file mode 100644
index 000000000..a5c2e00a3
--- /dev/null
+++ b/scripts/zmtelemetry.pl.in
@@ -0,0 +1,343 @@
+#!/usr/bin/perl -w
+#
+# ==========================================================================
+#
+# ZoneMinder Update Script, $Date$, $Revision$
+# Copyright (C) 2001-2008 Philip Coombes
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+
+=head1 NAME
+
+zmtelemetry.pl - Send usage information to the ZoneMinder development team
+
+=head1 SYNOPSIS
+
+ zmtelemetry.pl
+
+=head1 DESCRIPTION
+
+This script collects usage information of the local system and sends it to the
+ZoneMinder development team. This data will be used to determine things like
+who and where our customers are, how big their systems are, the underlying
+hardware and operating system, etc. This is being done for the sole purpoase of
+creating a better product for our target audience. This script is intended to
+be completely transparent to the end user, and can be disabled from the web
+console under Options.
+
+=head1 OPTIONS
+
+none currently
+
+=cut
+use strict;
+use bytes;
+
+@EXTRA_PERL_LIB@
+use ZoneMinder;
+use DBI;
+use Getopt::Long;
+use autouse 'Pod::Usage'=>qw(pod2usage);
+use LWP::UserAgent;
+use Sys::MemInfo qw(totalmem);
+use Sys::CPU qw(cpu_count);
+use POSIX qw(strftime uname);
+
+$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
+$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
+delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
+
+use constant CHECK_INTERVAL => (14*24*60*60); # Interval between version checks
+
+# Setting these as contants for now.
+# Alternatively, we can put these in the dB and then retrieve using the Config hash.
+use constant ZM_TELEMETRY_SERVER_ENDPOINT => 'https://zmanon:2b2d0b4skps@telemetry.zoneminder.com/zmtelemetry/testing5';
+
+if ( $Config{ZM_TELEMETRY_DATA} )
+{
+ print( "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
+
+ my $lastCheck = $Config{ZM_TELEMETRY_LAST_CHECK};
+
+ while( 1 ) {
+ my $now = time();
+ if ( ($now-$lastCheck) > CHECK_INTERVAL ) {
+ Info( "Colleting data to send to ZoneMinder Telemetry server." );
+ my $dbh = zmDbConnect();
+ # Build the telemetry hash
+ # We should keep *BSD systems in mind when calling system commands
+ my %telemetry;
+ $telemetry{uuid} = getUUID($dbh);
+ $telemetry{ip} = getIP();
+ $telemetry{timestamp} = strftime( "%Y-%m-%dT%H:%M:%S%z", localtime() );
+ $telemetry{monitor_count} = countQuery($dbh,"Monitors");
+ $telemetry{event_count} = countQuery($dbh,"Events");
+ $telemetry{architecture} = runSysCmd("uname -p");
+ ($telemetry{kernel}, $telemetry{distro}, $telemetry{version}) = getDistro();
+ $telemetry{zm_version} = ZoneMinder::Base::ZM_VERSION;
+ $telemetry{system_memory} = totalmem();
+ $telemetry{processor_count} = cpu_count();
+ $telemetry{monitors} = getMonitorRef($dbh);
+
+ Info( "Sending data to ZoneMinder Telemetry server." );
+
+ my $result = jsonEncode( \%telemetry );
+
+ if ( sendData($result) ) {
+ $lastCheck = $now;
+
+ my $sql = "update Config set Value = ? where Name = 'ZM_TELEMETRY_LAST_UPLOAD'";
+ my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
+ my $res = $sth->execute( "$lastCheck" ) or die( "Can't execute: ".$sth->errstr() );
+ $sth->finish();
+ }
+ }
+ sleep( 3600 );
+ }
+ print( "Update agent exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
+}
+
+###############
+# SUBROUTINES #
+###############
+
+# Find, verify, then run the supplied system command
+sub runSysCmd {
+ my $msg = shift;
+ my @arguments = split(/ /,$msg);
+ chomp($arguments[0]);
+ my $path = qx( which $arguments[0] );
+
+ my $status = $? >> 8;
+ my $result = "";
+ if ( !$path || $status ) {
+ Warning( "Cannot find the $arguments[0] executable." );
+ } else {
+ chomp($path);
+ $arguments[0] = $path;
+ my $cmd = join(" ",@arguments);
+ $result = qx( $cmd );
+ chomp($result);
+ }
+
+return $result;
+}
+
+# Upload message data to ZoneMinder telemetry server
+sub sendData {
+ my $msg = shift;
+
+ my $ua = LWP::UserAgent->new;
+ my $server_endpoint = ZM_TELEMETRY_SERVER_ENDPOINT;
+
+ if ( $Config{ZM_UPDATE_CHECK_PROXY} ) {
+ $ua->proxy( "https", $Config{ZM_UPDATE_CHECK_PROXY} );
+ }
+
+ Debug("Posting telemetry data to: $server_endpoint");
+
+ # set custom HTTP request header fields
+ my $req = HTTP::Request->new(POST => $server_endpoint);
+ $req->header('content-type' => 'application/x-www-form-urlencoded');
+ $req->header('content-length' => length($msg));
+ $req->header('connection' => 'Close');
+
+ $req->content($msg);
+
+ my $resp = $ua->request($req);
+ my $resp_msg = $resp->decoded_content;
+ my $resp_code = $resp->code;
+ if ($resp->is_success) {
+ Info("Telemetry data uploaded successfully.");
+ Debug("Telemetry server upload success response message: $resp_msg");
+ } else {
+ Warning("Telemetry server returned HTTP POST error code: $resp_code");
+ Debug("Telemetry server upload failure response message: $resp_msg");
+ }
+return $resp->is_success;
+}
+
+# Retrieves the UUID from the database. Creates a new UUID if one does not exist.
+sub getUUID {
+ my $dbh = shift;
+ my $uuid= "";
+
+ # Verify the current UUID is valid and not nil
+ if (( $Config{ZM_TELEMETRY_UUID} =~ /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i ) && ( $Config{ZM_TELEMETRY_UUID} ne "00000000-0000-0000-0000-000000000000" )) {
+ $uuid = $Config{ZM_TELEMETRY_UUID};
+ } else {
+ my $sql = "SELECT uuid()";
+ my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
+ my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
+ $uuid = $Config{ZM_TELEMETRY_UUID} = $sth->fetchrow_array();
+ $sth->finish();
+
+ $sql = "UPDATE Config set Value = ? WHERE Name = 'ZM_TELEMETRY_UUID'";
+ $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
+ $res = $sth->execute( "$uuid" ) or die( "Can't execute: ".$sth->errstr() );
+ $sth->finish();
+ }
+ Debug("Using UUID of: $uuid");
+
+return $uuid;
+}
+
+# Retrieves the local server's external IP address
+sub getIP {
+ my $ipaddr = "0.0.0.0";
+ my $ua = LWP::UserAgent->new;
+ my $server_endpoint = "https://wiki.zoneminder.com/ip.php";
+
+ my $req = HTTP::Request->new(GET => $server_endpoint);
+ my $resp = $ua->request($req);
+
+ if ($resp->is_success) {
+ $ipaddr = $resp->decoded_content;
+ }
+
+ Debug("Found external ip address of: $ipaddr");
+
+return $ipaddr;
+}
+
+# As the name implies, just your average mysql count query
+sub countQuery {
+ my $dbh = shift;
+ my $table = shift;
+
+ my $sql = "SELECT count(*) FROM $table";
+ my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
+ my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
+ my $count = $sth->fetchrow_array();
+ $sth->finish();
+
+return $count
+}
+
+# Returns a reference to an array of hashes containing data from all monitors
+sub getMonitorRef {
+ my $dbh = shift;
+
+ my $sql = "SELECT Id,Name,Type,Function,Width,Height,Colours,MaxFPS,AlarmMaxFPS FROM Monitors";
+ my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
+ my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
+ my $arrayref = $sth->fetchall_arrayref({});
+
+return $arrayref;
+}
+
+sub getDistro {
+ my $kernel = "";
+ my $distro = "";
+ my $version = "";
+ my @uname = uname();
+
+ if ( $uname[0] =~ /Linux/ ) {
+ Debug("Linux distro detected.");
+ ($kernel, $distro, $version) = linuxDistro();
+ } elsif ( $uname[0] =~ /.*BSD/ ) {
+ Debug("BSD distro detected.");
+ $kernel = $uname[3];
+ $distro = $uname[0];
+ $version = $uname[2];
+ } elsif ( $uname[0] =~ /Darwin/ ) {
+ Debug("Mac OS distro detected.");
+ $kernel = $uname[3];
+ $distro = runSysCmd("sw_vers -productName");
+ $version = runSysCmd("sw_vers -productVersion");
+ } elsif ( $uname[0] =~ /SunOS|Solaris/ ) {
+ Debug("Sun Solaris detected.");
+ $kernel = $uname[3];
+ $distro = $uname[1];
+ $version = $uname[2];
+ } else {
+ Warning("ZoneMinder was unable to determine the host system. Please report.");
+ $kernel = "Unknown";
+ $distro = "Unknown";
+ $version = "Unknown";
+ }
+
+return ($kernel, $distro, $version);
+}
+
+sub linuxDistro {
+ my @uname = uname();
+ my $kernel = $uname[2];
+ my $distro = "Unknown Linux Distro";
+ my $version = "Unknown Linux Version";
+ my $found = 0;
+
+ # os-release is the standard for many new distros based on systemd
+ if ( -f "/etc/os-release" ) {
+ open(my $RELFILE,"<","/etc/os-release") or die( "Can't Open file: $!\n" );
+ while (<$RELFILE>) {
+ if ( /^NAME=(")?(.*)(?(1)\1|).*$/ ) {
+ $distro = $2;
+ $found = 1;
+ }
+ if ( /^VERSION_ID=(")?(.*)(?(1)\1|).*$/ ) {
+ $version = $2;
+ $found = 1;
+ }
+ }
+ close $RELFILE;
+ # exists on many distros but does not always contain useful information, such as redhat
+ } elsif ( -f "/etc/lsb-release" ) {
+ open(my $RELFILE,"<","/etc/lsb-release") or die( "Can't Open file: $!\n" );
+ while (<$RELFILE>) {
+ if ( /^DISTRIB_DESCRIPTION=(")?(.*)(?(1)\1|).*$/ ) {
+ $distro = $2;
+ $found = 1;
+ }
+ if ( /^DISTRIB_RELEASE=(")?(.*)(?(1)\1|).*$/ ) {
+ $version = $2;
+ $found = 1;
+ }
+ }
+ close $RELFILE;
+ }
+
+ # If all else fails, search through a list of known release files until we find one
+ if ( !$found ) {
+ my @releasefile = ("/etc/SuSE-release", "/etc/redhat-release", "/etc/redhat_version",
+ "/etc/fedora-release", "/etc/slackware-release", "/etc/slackware-version",
+ "/etc/debian_release", "/etc/debian_version", "/etc/mandrake-release",
+ "/etc/yellowdog-release", "/etc/gentoo-release");
+ foreach (@releasefile) {
+ if ( -f $_ ) {
+ open(my $RELFILE,"<",$_) or die( "Can't Open file: $!\n" );
+ while (<$RELFILE>) {
+ if ( /(.*).* (\d+\.?\d*) .*/ ) {
+ $distro = $1;
+ $version = $2;
+ $found = 1;
+ }
+ }
+ close $RELFILE;
+ last;
+ }
+ }
+ }
+
+ if ( !$found ) {
+ Warning("ZoneMinder was unable to determine Linux distro. Please report.");
+ }
+
+return ($kernel, $distro, $version);
+}
+
+
diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in
index 55166a492..222e42f79 100644
--- a/scripts/zmtrigger.pl.in
+++ b/scripts/zmtrigger.pl.in
@@ -135,14 +135,14 @@ use ZoneMinder::Trigger::Connection;
my @connections;
push( @connections,
ZoneMinder::Trigger::Connection->new(
- name=>"Chan1",
+ name=>"Chan1 TCP on port 6802",
channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ),
mode=>"rw"
)
);
push( @connections,
ZoneMinder::Trigger::Connection->new(
- name=>"Chan2",
+ name=>"Chan2 Unix Socket at " . $Config{ZM_PATH_SOCKS}.'/zmtrigger.sock',
channel=>ZoneMinder::Trigger::Channel::Unix->new(
path=>$Config{ZM_PATH_SOCKS}.'/zmtrigger.sock'
),
diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in
index 969c72cb6..3143b2d50 100644
--- a/scripts/zmupdate.pl.in
+++ b/scripts/zmupdate.pl.in
@@ -23,7 +23,7 @@
=head1 NAME
-zmupdate.pl - check and upgrade Zoneminer database
+zmupdate.pl - check and upgrade ZoneMinder database
=head1 SYNOPSIS
diff --git a/src/zm_bigfont.h b/src/zm_bigfont.h
index a65e7c04a..b653a7f4f 100644
--- a/src/zm_bigfont.h
+++ b/src/zm_bigfont.h
@@ -2,6 +2,7 @@
/* */
/* Font file generated by schrorg */
/* based on the font file generated by rthelen */
+/* using utils/mk_bigfont.pl */
/* */
/***********************************************************/
diff --git a/src/zm_config.cpp b/src/zm_config.cpp
index 8d293906c..5a7454a7b 100644
--- a/src/zm_config.cpp
+++ b/src/zm_config.cpp
@@ -136,9 +136,9 @@ void zmLoadConfig()
}
if ( ! staticConfig.SERVER_ID ) {
- Info( "No Server ID or Name specified in config. Not using Multi-Server Mode." );
+ Debug( 1, "No Server ID or Name specified in config. Not using Multi-Server Mode." );
} else {
- Info( "Server is %d: using Multi-Server Mode.", staticConfig.SERVER_ID );
+ Debug( 1, "Server is %d: using Multi-Server Mode.", staticConfig.SERVER_ID );
}
}
diff --git a/src/zm_event.cpp b/src/zm_event.cpp
index 2d405ded6..55691395e 100755
--- a/src/zm_event.cpp
+++ b/src/zm_event.cpp
@@ -1244,7 +1244,7 @@ void EventStream::processCommand( const CmdMsg *msg )
DataMsg status_msg;
status_msg.msg_type = MSG_DATA_EVENT;
- memcpy( &status_msg.msg_data, &status_data, sizeof(status_msg.msg_data) );
+ memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) );
if ( sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) ) < 0 )
{
//if ( errno != EAGAIN )
diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp
index 39924f77d..2d596746f 100755
--- a/src/zm_monitor.cpp
+++ b/src/zm_monitor.cpp
@@ -4073,7 +4073,7 @@ void MonitorStream::processCommand( const CmdMsg *msg )
DataMsg status_msg;
status_msg.msg_type = MSG_DATA_WATCH;
- memcpy( &status_msg.msg_data, &status_data, sizeof(status_msg.msg_data) );
+ memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) );
int nbytes = 0;
if ( (nbytes = sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) )) < 0 )
{
diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp
index 440c24e05..006f80faf 100644
--- a/src/zm_remote_camera_http.cpp
+++ b/src/zm_remote_camera_http.cpp
@@ -199,7 +199,7 @@ int RemoteCameraHttp::ReadData( Buffer &buffer, int bytes_expected )
return( -1 );
}
- // There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unneccessarily.
+ // There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily.
if ( total_bytes_to_read > ZM_NETWORK_BUFSIZ ) {
total_bytes_to_read = ZM_NETWORK_BUFSIZ;
Debug(3, "Just getting 32K" );
diff --git a/src/zmf.cpp b/src/zmf.cpp
index 07149c4cc..7abe7a897 100644
--- a/src/zmf.cpp
+++ b/src/zmf.cpp
@@ -274,7 +274,7 @@ int main( int argc, char *argv[] )
Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
- // Read for pipe and loop until bytes expected have been read or an error occures
+ // Read for pipe and loop until bytes expected have been read or an error occurs
int bytes_read = 0;
do
{
diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh
index 2ce506421..6fff59967 100755
--- a/utils/do_debian_package.sh
+++ b/utils/do_debian_package.sh
@@ -52,12 +52,22 @@ else
ln -sf distros/ubuntu1504_cmake debian
fi;
+# Auto-install all ZoneMinder's depedencies using the Debian control file
+sudo apt-get install devscripts equivs
+sudo mk-build-deps -ir ./debian/control
+
+if [ -z `hostname -d` ] ; then
+ AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`.local>"
+else
+ AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`>"
+fi
+
cat < debian/changelog
zoneminder ($VERSION-$DISTRO-$SNAPSHOT) $DISTRO; urgency=medium
*
- -- Isaac Connor $DATE
+ -- $AUTHOR $DATE
EOF
#rm -rf .git
diff --git a/utils/docker/apache-vhost b/utils/docker/apache-vhost
index 622e4b5e4..5f59c01b2 100644
--- a/utils/docker/apache-vhost
+++ b/utils/docker/apache-vhost
@@ -6,8 +6,7 @@
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
- Order allow,deny
- Allow from all
+ require all granted
diff --git a/utils/docker/phpdate.ini b/utils/docker/phpdate.ini
new file mode 100644
index 000000000..d35b47361
--- /dev/null
+++ b/utils/docker/phpdate.ini
@@ -0,0 +1,5 @@
+[Date]
+; Defines the default timezone used by the date functions
+; http://php.net/date.timezone
+date.timezone = GMT
+
diff --git a/utils/docker/start.sh b/utils/docker/start.sh
index 76ad3dcbb..0772f7b9b 100644
--- a/utils/docker/start.sh
+++ b/utils/docker/start.sh
@@ -1,5 +1,11 @@
#!/bin/bash
+# Prepare proper amount of shared memory
+# For H.264 cameras it may be necessary to increase the amout of shared memory
+# to 2048 megabytes.
+umount /dev/shm
+mount -t tmpfs -o rw,nosuid,nodev,noexec,relatime,size=512M tmpfs /dev/shm
+
# Start MySQL
/usr/bin/mysqld_safe &
@@ -25,7 +31,13 @@ done
mysql -u root < db/zm_create.sql
# Add the ZoneMinder DB user
-mysql -u root -e "grant insert,select,update,delete,lock tables,alter on zm.* to 'zm'@'localhost' identified by 'zm'"
+mysql -u root -e "grant insert,select,update,delete,lock tables,alter on zm.* to 'zmuser'@'localhost' identified by 'zmpass';"
+
+# Activate CGI
+a2enmod cgi
+
+# Activate modrewrite
+a2enmod rewrite
# Restart apache
service apache2 restart
diff --git a/utils/mk_bigfont.pl b/utils/mk_bigfont.pl
new file mode 100755
index 000000000..ff2b1c30c
--- /dev/null
+++ b/utils/mk_bigfont.pl
@@ -0,0 +1,67 @@
+#!/usr/bin/env perl
+#
+# ==========================================================================
+#
+# ZoneMinder Big Font Generate Script
+# Copyright (C) 2015 Robin Därmann
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ==========================================================================
+
+# Basically, this script reads src/zm_font.h and duplicates every bit of every
+# character found in that file. It then duplicates every generated line, so
+# that every character effectively gets double sized.
+# Output goes to STDOUT so it would be useful to redirect it to a file, i.e. to
+# src/zm_bigfont.c
+
+use strict;
+use warnings;
+
+my $in_head = 1;
+
+open F, '<', '../src/zm_font.h';
+
+print <) {
+ $in_head-- if $line =~ /^$/ and $in_head;
+ next while $in_head;
+ unless ($line =~ /^\s+(0x..), \/\* (........)/) {
+ $line =~ s/static unsigned char fontdata/static unsigned int bigfontdata/;
+ print $line;
+ next;
+ }
+ my $code = $1;
+ my $bincode = $2;
+ $bincode = "$1$1$2$2$3$3$4$4$5$5$6$6$7$7$8$8" if $bincode =~ /(.)(.)(.)(.)(.)(.)(.)(.)$/;
+ $bincode =~ s/ /1/g;
+ my $intcode = unpack("N", pack("B32", substr("0" x 32 . $bincode, -32)));
+ my $hexcode = sprintf("%#x", $intcode);
+ $hexcode =~ s/^0$/0x0/;
+ $bincode =~ s/1/ /g;
+ print sprintf("\t%10s, /* %s */\n", $hexcode, $bincode);
+ print sprintf("\t%10s, /* %s */\n", $hexcode, $bincode);
+}
+
+close F;
diff --git a/web/api/lib/Cake/Cache/Cache.php b/web/api/lib/Cake/Cache/Cache.php
index a75f0acfd..a7a01d0a1 100644
--- a/web/api/lib/Cake/Cache/Cache.php
+++ b/web/api/lib/Cake/Cache/Cache.php
@@ -26,12 +26,12 @@ App::uses('CacheEngine', 'Cache');
* You can configure Cache engines in your application's `bootstrap.php` file. A sample configuration would
* be
*
- * {{{
+ * ```
* Cache::config('shared', array(
* 'engine' => 'Apc',
* 'prefix' => 'my_app_'
* ));
- * }}}
+ * ```
*
* This would configure an APC cache engine to the 'shared' alias. You could then read and write
* to that cache alias by using it for the `$config` parameter in the various Cache methods. In
@@ -113,11 +113,11 @@ class Cache {
* - `user` Used by Xcache. Username for XCache
* - `password` Used by Xcache/Redis. Password for XCache/Redis
*
- * @see app/Config/core.php for configuration settings
* @param string $name Name of the configuration
* @param array $settings Optional associative array of settings passed to the engine
* @return array array(engine, settings) on success, false on failure
* @throws CacheException
+ * @see app/Config/core.php for configuration settings
*/
public static function config($name = null, $settings = array()) {
if (is_array($name)) {
@@ -125,33 +125,33 @@ class Cache {
}
$current = array();
- if (isset(self::$_config[$name])) {
- $current = self::$_config[$name];
+ if (isset(static::$_config[$name])) {
+ $current = static::$_config[$name];
}
if (!empty($settings)) {
- self::$_config[$name] = $settings + $current;
+ static::$_config[$name] = $settings + $current;
}
- if (empty(self::$_config[$name]['engine'])) {
+ if (empty(static::$_config[$name]['engine'])) {
return false;
}
- if (!empty(self::$_config[$name]['groups'])) {
- foreach (self::$_config[$name]['groups'] as $group) {
- self::$_groups[$group][] = $name;
- sort(self::$_groups[$group]);
- self::$_groups[$group] = array_unique(self::$_groups[$group]);
+ if (!empty(static::$_config[$name]['groups'])) {
+ foreach (static::$_config[$name]['groups'] as $group) {
+ static::$_groups[$group][] = $name;
+ sort(static::$_groups[$group]);
+ static::$_groups[$group] = array_unique(static::$_groups[$group]);
}
}
- $engine = self::$_config[$name]['engine'];
+ $engine = static::$_config[$name]['engine'];
- if (!isset(self::$_engines[$name])) {
- self::_buildEngine($name);
- $settings = self::$_config[$name] = self::settings($name);
- } elseif ($settings = self::set(self::$_config[$name], null, $name)) {
- self::$_config[$name] = $settings;
+ if (!isset(static::$_engines[$name])) {
+ static::_buildEngine($name);
+ $settings = static::$_config[$name] = static::settings($name);
+ } elseif ($settings = static::set(static::$_config[$name], null, $name)) {
+ static::$_config[$name] = $settings;
}
return compact('engine', 'settings');
}
@@ -160,11 +160,11 @@ class Cache {
* Finds and builds the instance of the required engine class.
*
* @param string $name Name of the config array that needs an engine instance built
- * @return boolean
+ * @return bool
* @throws CacheException
*/
protected static function _buildEngine($name) {
- $config = self::$_config[$name];
+ $config = static::$_config[$name];
list($plugin, $class) = pluginSplit($config['engine'], true);
$cacheClass = $class . 'Engine';
@@ -176,12 +176,17 @@ class Cache {
if (!is_subclass_of($cacheClass, 'CacheEngine')) {
throw new CacheException(__d('cake_dev', 'Cache engines must use %s as a base class.', 'CacheEngine'));
}
- self::$_engines[$name] = new $cacheClass();
- if (!self::$_engines[$name]->init($config)) {
- throw new CacheException(__d('cake_dev', 'Cache engine %s is not properly configured.', $name));
+ static::$_engines[$name] = new $cacheClass();
+ if (!static::$_engines[$name]->init($config)) {
+ $msg = __d(
+ 'cake_dev',
+ 'Cache engine "%s" is not properly configured. Ensure required extensions are installed, and credentials/permissions are correct',
+ $name
+ );
+ throw new CacheException($msg);
}
- if (self::$_engines[$name]->settings['probability'] && time() % self::$_engines[$name]->settings['probability'] === 0) {
- self::$_engines[$name]->gc();
+ if (static::$_engines[$name]->settings['probability'] && time() % static::$_engines[$name]->settings['probability'] === 0) {
+ static::$_engines[$name]->gc();
}
return true;
}
@@ -192,22 +197,22 @@ class Cache {
* @return array Array of configured Cache config names.
*/
public static function configured() {
- return array_keys(self::$_config);
+ return array_keys(static::$_config);
}
/**
* Drops a cache engine. Deletes the cache configuration information
- * If the deleted configuration is the last configuration using an certain engine,
+ * If the deleted configuration is the last configuration using a certain engine,
* the Engine instance is also unset.
*
* @param string $name A currently configured cache config you wish to remove.
- * @return boolean success of the removal, returns false when the config does not exist.
+ * @return bool success of the removal, returns false when the config does not exist.
*/
public static function drop($name) {
- if (!isset(self::$_config[$name])) {
+ if (!isset(static::$_config[$name])) {
return false;
}
- unset(self::$_config[$name], self::$_engines[$name]);
+ unset(static::$_config[$name], static::$_engines[$name]);
return true;
}
@@ -238,29 +243,29 @@ class Cache {
if (is_array($settings) && $value !== null) {
$config = $value;
}
- if (!isset(self::$_config[$config]) || !isset(self::$_engines[$config])) {
+ if (!isset(static::$_config[$config]) || !isset(static::$_engines[$config])) {
return false;
}
if (!empty($settings)) {
- self::$_reset = true;
+ static::$_reset = true;
}
- if (self::$_reset === true) {
+ if (static::$_reset === true) {
if (empty($settings)) {
- self::$_reset = false;
- $settings = self::$_config[$config];
+ static::$_reset = false;
+ $settings = static::$_config[$config];
} else {
if (is_string($settings) && $value !== null) {
$settings = array($settings => $value);
}
- $settings += self::$_config[$config];
+ $settings += static::$_config[$config];
if (isset($settings['duration']) && !is_numeric($settings['duration'])) {
$settings['duration'] = strtotime($settings['duration']) - time();
}
}
- self::$_engines[$config]->settings = $settings;
+ static::$_engines[$config]->settings = $settings;
}
- return self::settings($config);
+ return static::settings($config);
}
/**
@@ -269,11 +274,11 @@ class Cache {
* Permanently remove all expired and deleted data
*
* @param string $config [optional] The config name you wish to have garbage collected. Defaults to 'default'
- * @param integer $expires [optional] An expires timestamp. Defaults to NULL
- * @return void
+ * @param int $expires [optional] An expires timestamp. Defaults to NULL
+ * @return bool
*/
public static function gc($config = 'default', $expires = null) {
- self::$_engines[$config]->gc($expires);
+ return static::$_engines[$config]->gc($expires);
}
/**
@@ -292,32 +297,32 @@ class Cache {
* @param string $key Identifier for the data
* @param mixed $value Data to be cached - anything except a resource
* @param string $config Optional string configuration name to write to. Defaults to 'default'
- * @return boolean True if the data was successfully cached, false on failure
+ * @return bool True if the data was successfully cached, false on failure
*/
public static function write($key, $value, $config = 'default') {
- $settings = self::settings($config);
+ $settings = static::settings($config);
if (empty($settings)) {
return false;
}
- if (!self::isInitialized($config)) {
+ if (!static::isInitialized($config)) {
return false;
}
- $key = self::$_engines[$config]->key($key);
+ $key = static::$_engines[$config]->key($key);
if (!$key || is_resource($value)) {
return false;
}
- $success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
- self::set(null, $config);
+ $success = static::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
+ static::set(null, $config);
if ($success === false && $value !== '') {
trigger_error(
__d('cake_dev',
"%s cache was unable to write '%s' to %s cache",
$config,
$key,
- self::$_engines[$config]->settings['engine']
+ static::$_engines[$config]->settings['engine']
),
E_USER_WARNING
);
@@ -343,46 +348,46 @@ class Cache {
* @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
*/
public static function read($key, $config = 'default') {
- $settings = self::settings($config);
+ $settings = static::settings($config);
if (empty($settings)) {
return false;
}
- if (!self::isInitialized($config)) {
+ if (!static::isInitialized($config)) {
return false;
}
- $key = self::$_engines[$config]->key($key);
+ $key = static::$_engines[$config]->key($key);
if (!$key) {
return false;
}
- return self::$_engines[$config]->read($settings['prefix'] . $key);
+ return static::$_engines[$config]->read($settings['prefix'] . $key);
}
/**
* Increment a number under the key and return incremented value.
*
* @param string $key Identifier for the data
- * @param integer $offset How much to add
+ * @param int $offset How much to add
* @param string $config Optional string configuration name. Defaults to 'default'
* @return mixed new value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it.
*/
public static function increment($key, $offset = 1, $config = 'default') {
- $settings = self::settings($config);
+ $settings = static::settings($config);
if (empty($settings)) {
return false;
}
- if (!self::isInitialized($config)) {
+ if (!static::isInitialized($config)) {
return false;
}
- $key = self::$_engines[$config]->key($key);
+ $key = static::$_engines[$config]->key($key);
if (!$key || !is_int($offset) || $offset < 0) {
return false;
}
- $success = self::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
- self::set(null, $config);
+ $success = static::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
+ static::set(null, $config);
return $success;
}
@@ -390,27 +395,27 @@ class Cache {
* Decrement a number under the key and return decremented value.
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @param string $config Optional string configuration name. Defaults to 'default'
* @return mixed new value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it
*/
public static function decrement($key, $offset = 1, $config = 'default') {
- $settings = self::settings($config);
+ $settings = static::settings($config);
if (empty($settings)) {
return false;
}
- if (!self::isInitialized($config)) {
+ if (!static::isInitialized($config)) {
return false;
}
- $key = self::$_engines[$config]->key($key);
+ $key = static::$_engines[$config]->key($key);
if (!$key || !is_int($offset) || $offset < 0) {
return false;
}
- $success = self::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
- self::set(null, $config);
+ $success = static::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
+ static::set(null, $config);
return $success;
}
@@ -429,40 +434,40 @@ class Cache {
*
* @param string $key Identifier for the data
* @param string $config name of the configuration to use. Defaults to 'default'
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public static function delete($key, $config = 'default') {
- $settings = self::settings($config);
+ $settings = static::settings($config);
if (empty($settings)) {
return false;
}
- if (!self::isInitialized($config)) {
+ if (!static::isInitialized($config)) {
return false;
}
- $key = self::$_engines[$config]->key($key);
+ $key = static::$_engines[$config]->key($key);
if (!$key) {
return false;
}
- $success = self::$_engines[$config]->delete($settings['prefix'] . $key);
- self::set(null, $config);
+ $success = static::$_engines[$config]->delete($settings['prefix'] . $key);
+ static::set(null, $config);
return $success;
}
/**
* Delete all keys from the cache.
*
- * @param boolean $check if true will check expiration, otherwise delete all
+ * @param bool $check if true will check expiration, otherwise delete all
* @param string $config name of the configuration to use. Defaults to 'default'
- * @return boolean True if the cache was successfully cleared, false otherwise
+ * @return bool True if the cache was successfully cleared, false otherwise
*/
public static function clear($check = false, $config = 'default') {
- if (!self::isInitialized($config)) {
+ if (!static::isInitialized($config)) {
return false;
}
- $success = self::$_engines[$config]->clear($check);
- self::set(null, $config);
+ $success = static::$_engines[$config]->clear($check);
+ static::set(null, $config);
return $success;
}
@@ -471,14 +476,14 @@ class Cache {
*
* @param string $group name of the group to be cleared
* @param string $config name of the configuration to use. Defaults to 'default'
- * @return boolean True if the cache group was successfully cleared, false otherwise
+ * @return bool True if the cache group was successfully cleared, false otherwise
*/
public static function clearGroup($group, $config = 'default') {
- if (!self::isInitialized($config)) {
+ if (!static::isInitialized($config)) {
return false;
}
- $success = self::$_engines[$config]->clearGroup($group);
- self::set(null, $config);
+ $success = static::$_engines[$config]->clearGroup($group);
+ static::set(null, $config);
return $success;
}
@@ -486,13 +491,13 @@ class Cache {
* Check if Cache has initialized a working config for the given name.
*
* @param string $config name of the configuration to use. Defaults to 'default'
- * @return boolean Whether or not the config name has been initialized.
+ * @return bool Whether or not the config name has been initialized.
*/
public static function isInitialized($config = 'default') {
if (Configure::read('Cache.disable')) {
return false;
}
- return isset(self::$_engines[$config]);
+ return isset(static::$_engines[$config]);
}
/**
@@ -503,8 +508,8 @@ class Cache {
* @see Cache::config()
*/
public static function settings($name = 'default') {
- if (!empty(self::$_engines[$name])) {
- return self::$_engines[$name]->settings();
+ if (!empty(static::$_engines[$name])) {
+ return static::$_engines[$name]->settings();
}
return array();
}
@@ -512,7 +517,7 @@ class Cache {
/**
* Retrieve group names to config mapping.
*
- * {{{
+ * ```
* Cache::config('daily', array(
* 'duration' => '1 day', 'groups' => array('posts')
* ));
@@ -520,7 +525,7 @@ class Cache {
* 'duration' => '1 week', 'groups' => array('posts', 'archive')
* ));
* $configs = Cache::groupConfigs('posts');
- * }}}
+ * ```
*
* $config will equal to `array('posts' => array('daily', 'weekly'))`
*
@@ -530,10 +535,10 @@ class Cache {
*/
public static function groupConfigs($group = null) {
if ($group === null) {
- return self::$_groups;
+ return static::$_groups;
}
- if (isset(self::$_groups[$group])) {
- return array($group => self::$_groups[$group]);
+ if (isset(static::$_groups[$group])) {
+ return array($group => static::$_groups[$group]);
}
throw new CacheException(__d('cake_dev', 'Invalid cache group %s', $group));
}
@@ -549,27 +554,66 @@ class Cache {
*
* Using a Closure to provide data, assume $this is a Model:
*
- * {{{
+ * ```
* $model = $this;
* $results = Cache::remember('all_articles', function() use ($model) {
* return $model->find('all');
* });
- * }}}
+ * ```
*
* @param string $key The cache key to read/store data at.
* @param callable $callable The callable that provides data in the case when
* the cache key is empty. Can be any callable type supported by your PHP.
* @param string $config The cache configuration to use for this operation.
* Defaults to default.
+ * @return mixed The results of the callable or unserialized results.
*/
public static function remember($key, $callable, $config = 'default') {
- $existing = self::read($key, $config);
+ $existing = static::read($key, $config);
if ($existing !== false) {
return $existing;
}
$results = call_user_func($callable);
- self::write($key, $results, $config);
+ static::write($key, $results, $config);
return $results;
}
+/**
+ * Write data for key into a cache engine if it doesn't exist already.
+ *
+ * ### Usage:
+ *
+ * Writing to the active cache config:
+ *
+ * `Cache::add('cached_data', $data);`
+ *
+ * Writing to a specific cache config:
+ *
+ * `Cache::add('cached_data', $data, 'long_term');`
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached - anything except a resource.
+ * @param string $config Optional string configuration name to write to. Defaults to 'default'.
+ * @return bool True if the data was successfully cached, false on failure.
+ * Or if the key existed already.
+ */
+ public static function add($key, $value, $config = 'default') {
+ $settings = self::settings($config);
+
+ if (empty($settings)) {
+ return false;
+ }
+ if (!self::isInitialized($config)) {
+ return false;
+ }
+ $key = self::$_engines[$config]->key($key);
+
+ if (!$key || is_resource($value)) {
+ return false;
+ }
+
+ $success = self::$_engines[$config]->add($settings['prefix'] . $key, $value, $settings['duration']);
+ self::set(null, $config);
+ return $success;
+ }
}
diff --git a/web/api/lib/Cake/Cache/CacheEngine.php b/web/api/lib/Cake/Cache/CacheEngine.php
index 5d19bdeaf..6bad9f7ad 100644
--- a/web/api/lib/Cake/Cache/CacheEngine.php
+++ b/web/api/lib/Cake/Cache/CacheEngine.php
@@ -42,7 +42,7 @@ abstract class CacheEngine {
* Called automatically by the cache frontend
*
* @param array $settings Associative array of parameters for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
$settings += $this->settings + array(
@@ -67,7 +67,7 @@ abstract class CacheEngine {
*
* Permanently remove all expired and deleted data
*
- * @param integer $expires [optional] An expires timestamp, invalidating all data before.
+ * @param int $expires [optional] An expires timestamp, invalidating all data before.
* @return void
*/
public function gc($expires = null) {
@@ -78,11 +78,22 @@ abstract class CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
- * @param integer $duration How long to cache for.
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache for.
+ * @return bool True if the data was successfully cached, false on failure
*/
abstract public function write($key, $value, $duration);
+/**
+ * Write value for a key into cache if it doesn't already exist
+ *
+ * @param string $key Identifier for the data
+ * @param mixed $value Data to be cached
+ * @param int $duration How long to cache for.
+ * @return bool True if the data was successfully cached, false on failure
+ */
+ public function add($key, $value, $duration) {
+ }
+
/**
* Read a key from the cache
*
@@ -95,7 +106,7 @@ abstract class CacheEngine {
* Increment a number under the key and return incremented value
*
* @param string $key Identifier for the data
- * @param integer $offset How much to add
+ * @param int $offset How much to add
* @return New incremented value, false otherwise
*/
abstract public function increment($key, $offset = 1);
@@ -104,7 +115,7 @@ abstract class CacheEngine {
* Decrement a number under the key and return decremented value
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @return New incremented value, false otherwise
*/
abstract public function decrement($key, $offset = 1);
@@ -113,15 +124,15 @@ abstract class CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
abstract public function delete($key);
/**
* Delete all keys from the cache
*
- * @param boolean $check if true will check expiration, otherwise delete all
- * @return boolean True if the cache was successfully cleared, false otherwise
+ * @param bool $check if true will check expiration, otherwise delete all
+ * @return bool True if the cache was successfully cleared, false otherwise
*/
abstract public function clear($check);
@@ -130,8 +141,8 @@ abstract class CacheEngine {
* to decide whether actually delete the keys or just simulate it to achieve
* the same result.
*
- * @param string $groups name of the group to be cleared
- * @return boolean
+ * @param string $group name of the group to be cleared
+ * @return bool
*/
public function clearGroup($group) {
return false;
@@ -176,5 +187,4 @@ abstract class CacheEngine {
$key = preg_replace('/[\s]+/', '_', strtolower(trim(str_replace(array(DS, '/', '.'), '_', strval($key)))));
return $prefix . $key;
}
-
}
diff --git a/web/api/lib/Cake/Cache/Engine/ApcEngine.php b/web/api/lib/Cake/Cache/Engine/ApcEngine.php
index 8fd0ff1ad..da31651e3 100644
--- a/web/api/lib/Cake/Cache/Engine/ApcEngine.php
+++ b/web/api/lib/Cake/Cache/Engine/ApcEngine.php
@@ -38,7 +38,7 @@ class ApcEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
* @see CacheEngine::__defaults
*/
public function init($settings = array()) {
@@ -55,8 +55,8 @@ class ApcEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
- * @param integer $duration How long to cache the data, in seconds
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache the data, in seconds
+ * @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
$expires = 0;
@@ -75,7 +75,7 @@ class ApcEngine extends CacheEngine {
*/
public function read($key) {
$time = time();
- $cachetime = intval(apc_fetch($key . '_expires'));
+ $cachetime = (int)apc_fetch($key . '_expires');
if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
return false;
}
@@ -86,7 +86,7 @@ class ApcEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to increment
+ * @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
@@ -97,7 +97,7 @@ class ApcEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
@@ -108,7 +108,7 @@ class ApcEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return apc_delete($key);
@@ -117,18 +117,25 @@ class ApcEngine extends CacheEngine {
/**
* Delete all keys from the cache. This will clear every cache config using APC.
*
- * @param boolean $check If true, nothing will be cleared, as entries are removed
+ * @param bool $check If true, nothing will be cleared, as entries are removed
* from APC as they expired. This flag is really only used by FileEngine.
- * @return boolean True Returns true.
+ * @return bool True Returns true.
*/
public function clear($check) {
if ($check) {
return true;
}
- $info = apc_cache_info('user');
- $cacheKeys = $info['cache_list'];
- unset($info);
- foreach ($cacheKeys as $key) {
+ if (class_exists('APCIterator', false)) {
+ $iterator = new APCIterator(
+ 'user',
+ '/^' . preg_quote($this->settings['prefix'], '/') . '/',
+ APC_ITER_NONE
+ );
+ apc_delete($iterator);
+ return true;
+ }
+ $cache = apc_cache_info('user');
+ foreach ($cache['cache_list'] as $key) {
if (strpos($key['info'], $this->settings['prefix']) === 0) {
apc_delete($key['info']);
}
@@ -173,11 +180,30 @@ class ApcEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
- * @return boolean success
+ * @param string $group The group to clear.
+ * @return bool success
*/
public function clearGroup($group) {
apc_inc($this->settings['prefix'] . $group, 1, $success);
return $success;
}
+/**
+ * Write data for key into cache if it doesn't exist already.
+ * If it already exists, it fails and returns false.
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached.
+ * @param int $duration How long to cache the data, in seconds.
+ * @return bool True if the data was successfully cached, false on failure.
+ * @link http://php.net/manual/en/function.apc-add.php
+ */
+ public function add($key, $value, $duration) {
+ $expires = 0;
+ if ($duration) {
+ $expires = time() + $duration;
+ }
+ apc_add($key . '_expires', $expires, $duration);
+ return apc_add($key, $value, $duration);
+ }
}
diff --git a/web/api/lib/Cake/Cache/Engine/FileEngine.php b/web/api/lib/Cake/Cache/Engine/FileEngine.php
index b93d6c1a8..d650e60ee 100644
--- a/web/api/lib/Cake/Cache/Engine/FileEngine.php
+++ b/web/api/lib/Cake/Cache/Engine/FileEngine.php
@@ -53,7 +53,7 @@ class FileEngine extends CacheEngine {
/**
* True unless FileEngine::__active(); fails
*
- * @var boolean
+ * @var bool
*/
protected $_init = true;
@@ -64,7 +64,7 @@ class FileEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
$settings += array(
@@ -93,8 +93,8 @@ class FileEngine extends CacheEngine {
/**
* Garbage collection. Permanently remove all expired and deleted data
*
- * @param integer $expires [optional] An expires timestamp, invalidating all data before.
- * @return boolean True if garbage collection was successful, false on failure
+ * @param int $expires [optional] An expires timestamp, invalidating all data before.
+ * @return bool True if garbage collection was successful, false on failure
*/
public function gc($expires = null) {
return $this->clear(true);
@@ -105,11 +105,11 @@ class FileEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $data Data to be cached
- * @param integer $duration How long to cache the data, in seconds
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache the data, in seconds
+ * @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $data, $duration) {
- if ($data === '' || !$this->_init) {
+ if (!$this->_init) {
return false;
}
@@ -165,7 +165,7 @@ class FileEngine extends CacheEngine {
$this->_File->rewind();
$time = time();
- $cachetime = intval($this->_File->current());
+ $cachetime = (int)$this->_File->current();
if ($cachetime !== false && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
if ($this->settings['lock']) {
@@ -200,7 +200,7 @@ class FileEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
if ($this->_setKey($key) === false || !$this->_init) {
@@ -217,8 +217,8 @@ class FileEngine extends CacheEngine {
/**
* Delete all values from the cache
*
- * @param boolean $check Optional - only delete expired cache items
- * @return boolean True if the cache was successfully cleared, false otherwise
+ * @param bool $check Optional - only delete expired cache items
+ * @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if (!$this->_init) {
@@ -255,8 +255,8 @@ class FileEngine extends CacheEngine {
* Used to clear a directory of matching files.
*
* @param string $path The path to search.
- * @param integer $now The current timestamp
- * @param integer $threshold Any file not modified after this value will be deleted.
+ * @param int $now The current timestamp
+ * @param int $threshold Any file not modified after this value will be deleted.
* @return void
*/
protected function _clearDirectory($path, $now, $threshold) {
@@ -271,11 +271,12 @@ class FileEngine extends CacheEngine {
if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) {
continue;
}
- $filePath = $path . $entry;
- if (!file_exists($filePath) || is_dir($filePath)) {
+
+ try {
+ $file = new SplFileObject($path . $entry, 'r');
+ } catch (Exception $e) {
continue;
}
- $file = new SplFileObject($path . $entry, 'r');
if ($threshold) {
$mtime = $file->getMTime();
@@ -303,8 +304,8 @@ class FileEngine extends CacheEngine {
/**
* Not implemented
*
- * @param string $key
- * @param integer $offset
+ * @param string $key The key to decrement
+ * @param int $offset The number to offset
* @return void
* @throws CacheException
*/
@@ -315,8 +316,8 @@ class FileEngine extends CacheEngine {
/**
* Not implemented
*
- * @param string $key
- * @param integer $offset
+ * @param string $key The key to decrement
+ * @param int $offset The number to offset
* @return void
* @throws CacheException
*/
@@ -329,8 +330,8 @@ class FileEngine extends CacheEngine {
* for the cache file the key is referring to.
*
* @param string $key The key
- * @param boolean $createKey Whether the key should be created if it doesn't exists, or not
- * @return boolean true if the cache key could be set, false otherwise
+ * @param bool $createKey Whether the key should be created if it doesn't exists, or not
+ * @return bool true if the cache key could be set, false otherwise
*/
protected function _setKey($key, $createKey = false) {
$groups = null;
@@ -369,7 +370,7 @@ class FileEngine extends CacheEngine {
/**
* Determine is cache directory is writable
*
- * @return boolean
+ * @return bool
*/
protected function _active() {
$dir = new SplFileInfo($this->settings['path']);
@@ -405,7 +406,8 @@ class FileEngine extends CacheEngine {
/**
* Recursively deletes all files under any directory named as $group
*
- * @return boolean success
+ * @param string $group The group to clear.
+ * @return bool success
*/
public function clearGroup($group) {
$this->_File = null;
@@ -427,4 +429,21 @@ class FileEngine extends CacheEngine {
}
return true;
}
+
+/**
+ * Write data for key into cache if it doesn't exist already.
+ * If it already exists, it fails and returns false.
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached.
+ * @param int $duration How long to cache the data, in seconds.
+ * @return bool True if the data was successfully cached, false on failure.
+ */
+ public function add($key, $value, $duration) {
+ $cachedValue = $this->read($key);
+ if ($cachedValue === false) {
+ return $this->write($key, $value, $duration);
+ }
+ return false;
+ }
}
diff --git a/web/api/lib/Cake/Cache/Engine/MemcacheEngine.php b/web/api/lib/Cake/Cache/Engine/MemcacheEngine.php
index facaedf0e..eba2ec451 100644
--- a/web/api/lib/Cake/Cache/Engine/MemcacheEngine.php
+++ b/web/api/lib/Cake/Cache/Engine/MemcacheEngine.php
@@ -22,7 +22,7 @@
* more information.
*
* @package Cake.Cache.Engine
- * @deprecated You should use the Memcached adapter instead.
+ * @deprecated 3.0.0 You should use the Memcached adapter instead.
*/
class MemcacheEngine extends CacheEngine {
@@ -59,7 +59,7 @@ class MemcacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (!class_exists('Memcache')) {
@@ -104,7 +104,7 @@ class MemcacheEngine extends CacheEngine {
* @return array Array containing host, port
*/
protected function _parseServerString($server) {
- if ($server[0] === 'u') {
+ if (strpos($server, 'unix://') === 0) {
return array($server, 0);
}
if (substr($server, 0, 1) === '[') {
@@ -131,8 +131,8 @@ class MemcacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
- * @param integer $duration How long to cache the data, in seconds
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache the data, in seconds
+ * @return bool True if the data was successfully cached, false on failure
* @see http://php.net/manual/en/memcache.set.php
*/
public function write($key, $value, $duration) {
@@ -156,7 +156,7 @@ class MemcacheEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to increment
+ * @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
@@ -173,7 +173,7 @@ class MemcacheEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
@@ -190,7 +190,7 @@ class MemcacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Memcache->delete($key);
@@ -199,8 +199,9 @@ class MemcacheEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
- * @param boolean $check
- * @return boolean True if the cache was successfully cleared, false otherwise
+ * @param bool $check If true no deletes will occur and instead CakePHP will rely
+ * on key TTL values.
+ * @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if ($check) {
@@ -231,8 +232,8 @@ class MemcacheEngine extends CacheEngine {
* Connects to a server in connection pool
*
* @param string $host host ip address or name
- * @param integer $port Server port
- * @return boolean True if memcache server was connected
+ * @param int $port Server port
+ * @return bool True if memcache server was connected
*/
public function connect($host, $port = 11211) {
if ($this->_Memcache->getServerStatus($host, $port) === 0) {
@@ -282,9 +283,30 @@ class MemcacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
- * @return boolean success
+ * @param string $group The group to clear.
+ * @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Memcache->increment($this->settings['prefix'] . $group);
}
+
+/**
+ * Write data for key into cache if it doesn't exist already. When using memcached as your cache engine
+ * remember that the Memcached PECL extension does not support cache expiry times greater
+ * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
+ * If it already exists, it fails and returns false.
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached.
+ * @param int $duration How long to cache the data, in seconds.
+ * @return bool True if the data was successfully cached, false on failure.
+ * @link http://php.net/manual/en/memcache.add.php
+ */
+ public function add($key, $value, $duration) {
+ if ($duration > 30 * DAY) {
+ $duration = 0;
+ }
+
+ return $this->_Memcache->add($key, $value, $this->settings['compress'], $duration);
+ }
}
diff --git a/web/api/lib/Cake/Cache/Engine/MemcachedEngine.php b/web/api/lib/Cake/Cache/Engine/MemcachedEngine.php
old mode 100755
new mode 100644
index 9c50186fe..cc101a2bf
--- a/web/api/lib/Cake/Cache/Engine/MemcachedEngine.php
+++ b/web/api/lib/Cake/Cache/Engine/MemcachedEngine.php
@@ -45,6 +45,8 @@ class MemcachedEngine extends CacheEngine {
* - serialize = string, default => php. The serializer engine used to serialize data.
* Available engines are php, igbinary and json. Beside php, the memcached extension
* must be compiled with the appropriate serializer support.
+ * - options - Additional options for the memcached client. Should be an array of option => value.
+ * Use the Memcached::OPT_* constants as keys.
*
* @var array
*/
@@ -70,7 +72,7 @@ class MemcachedEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
* @throws CacheException when you try use authentication without Memcached compiled with SASL support
*/
public function init($settings = array()) {
@@ -92,7 +94,8 @@ class MemcachedEngine extends CacheEngine {
'persistent' => false,
'login' => null,
'password' => null,
- 'serialize' => 'php'
+ 'serialize' => 'php',
+ 'options' => array()
);
parent::init($settings);
@@ -104,7 +107,11 @@ class MemcachedEngine extends CacheEngine {
return true;
}
- $this->_Memcached = new Memcached($this->settings['persistent'] ? (string)$this->settings['persistent'] : null);
+ if (!$this->settings['persistent']) {
+ $this->_Memcached = new Memcached();
+ } else {
+ $this->_Memcached = new Memcached((string)$this->settings['persistent']);
+ }
$this->_setOptions();
if (count($this->_Memcached->getServerList())) {
@@ -126,8 +133,14 @@ class MemcachedEngine extends CacheEngine {
__d('cake_dev', 'Memcached extension is not build with SASL support')
);
}
+ $this->_Memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
$this->_Memcached->setSaslAuthData($this->settings['login'], $this->settings['password']);
}
+ if (is_array($this->settings['options'])) {
+ foreach ($this->settings['options'] as $opt => $value) {
+ $this->_Memcached->setOption($opt, $value);
+ }
+ }
return true;
}
@@ -136,6 +149,7 @@ class MemcachedEngine extends CacheEngine {
* Settings the memcached instance
*
* @throws CacheException when the Memcached extension is not built with the desired serializer engine
+ * @return void
*/
protected function _setOptions() {
$this->_Memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
@@ -171,8 +185,9 @@ class MemcachedEngine extends CacheEngine {
* @return array Array containing host, port
*/
protected function _parseServerString($server) {
- if ($server[0] === 'u') {
- return array($server, 0);
+ $socketTransport = 'unix://';
+ if (strpos($server, $socketTransport) === 0) {
+ return array(substr($server, strlen($socketTransport)), 0);
}
if (substr($server, 0, 1) === '[') {
$position = strpos($server, ']:');
@@ -193,13 +208,13 @@ class MemcachedEngine extends CacheEngine {
/**
* Write data for key into cache. When using memcached as your cache engine
- * remember that the Memcached pecl extension does not support cache expiry times greater
+ * remember that the Memcached PECL extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
- * @param integer $duration How long to cache the data, in seconds
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache the data, in seconds
+ * @return bool True if the data was successfully cached, false on failure
* @see http://php.net/manual/en/memcache.set.php
*/
public function write($key, $value, $duration) {
@@ -224,7 +239,7 @@ class MemcachedEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to increment
+ * @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
@@ -236,7 +251,7 @@ class MemcachedEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
@@ -248,7 +263,7 @@ class MemcachedEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Memcached->delete($key);
@@ -257,8 +272,10 @@ class MemcachedEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
- * @param boolean $check
- * @return boolean True if the cache was successfully cleared, false otherwise
+ * @param bool $check If true no deletes will occur and instead CakePHP will rely
+ * on key TTL values.
+ * @return bool True if the cache was successfully cleared, false otherwise. Will
+ * also return false if you are using a binary protocol.
*/
public function clear($check) {
if ($check) {
@@ -266,6 +283,9 @@ class MemcachedEngine extends CacheEngine {
}
$keys = $this->_Memcached->getAllKeys();
+ if ($keys === false) {
+ return false;
+ }
foreach ($keys as $key) {
if (strpos($key, $this->settings['prefix']) === 0) {
@@ -314,9 +334,30 @@ class MemcachedEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
- * @return boolean success
+ * @param string $group The group to clear.
+ * @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Memcached->increment($this->settings['prefix'] . $group);
}
+
+/**
+ * Write data for key into cache if it doesn't exist already. When using memcached as your cache engine
+ * remember that the Memcached pecl extension does not support cache expiry times greater
+ * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
+ * If it already exists, it fails and returns false.
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached.
+ * @param int $duration How long to cache the data, in seconds.
+ * @return bool True if the data was successfully cached, false on failure.
+ * @link http://php.net/manual/en/memcached.add.php
+ */
+ public function add($key, $value, $duration) {
+ if ($duration > 30 * DAY) {
+ $duration = 0;
+ }
+
+ return $this->_Memcached->add($key, $value, $duration);
+ }
}
diff --git a/web/api/lib/Cake/Cache/Engine/RedisEngine.php b/web/api/lib/Cake/Cache/Engine/RedisEngine.php
index 09415c95d..8dd98fb99 100644
--- a/web/api/lib/Cake/Cache/Engine/RedisEngine.php
+++ b/web/api/lib/Cake/Cache/Engine/RedisEngine.php
@@ -38,6 +38,7 @@ class RedisEngine extends CacheEngine {
* - port = integer port number to the Redis server (default: 6379)
* - timeout = float timeout in seconds (default: 0)
* - persistent = boolean Connects to the Redis server with a persistent connection (default: true)
+ * - unix_socket = path to the unix socket file (default: false)
*
* @var array
*/
@@ -50,7 +51,7 @@ class RedisEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (!class_exists('Redis')) {
@@ -58,13 +59,14 @@ class RedisEngine extends CacheEngine {
}
parent::init(array_merge(array(
'engine' => 'Redis',
- 'prefix' => null,
+ 'prefix' => Inflector::slug(APP_DIR) . '_',
'server' => '127.0.0.1',
'database' => 0,
'port' => 6379,
'password' => false,
'timeout' => 0,
- 'persistent' => true
+ 'persistent' => true,
+ 'unix_socket' => false
), $settings)
);
@@ -74,28 +76,29 @@ class RedisEngine extends CacheEngine {
/**
* Connects to a Redis server
*
- * @return boolean True if Redis server was connected
+ * @return bool True if Redis server was connected
*/
protected function _connect() {
- $return = false;
try {
$this->_Redis = new Redis();
- if (empty($this->settings['persistent'])) {
+ if (!empty($this->settings['unix_socket'])) {
+ $return = $this->_Redis->connect($this->settings['unix_socket']);
+ } elseif (empty($this->settings['persistent'])) {
$return = $this->_Redis->connect($this->settings['server'], $this->settings['port'], $this->settings['timeout']);
} else {
$persistentId = $this->settings['port'] . $this->settings['timeout'] . $this->settings['database'];
$return = $this->_Redis->pconnect($this->settings['server'], $this->settings['port'], $this->settings['timeout'], $persistentId);
}
} catch (RedisException $e) {
+ $return = false;
+ }
+ if (!$return) {
return false;
}
- if ($return && $this->settings['password']) {
- $return = $this->_Redis->auth($this->settings['password']);
+ if ($this->settings['password'] && !$this->_Redis->auth($this->settings['password'])) {
+ return false;
}
- if ($return) {
- $return = $this->_Redis->select($this->settings['database']);
- }
- return $return;
+ return $this->_Redis->select($this->settings['database']);
}
/**
@@ -103,13 +106,18 @@ class RedisEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
- * @param integer $duration How long to cache the data, in seconds
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache the data, in seconds
+ * @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
if (!is_int($value)) {
$value = serialize($value);
}
+
+ if (!$this->_Redis->isConnected()) {
+ $this->_connect();
+ }
+
if ($duration === 0) {
return $this->_Redis->set($key, $value);
}
@@ -138,7 +146,7 @@ class RedisEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to increment
+ * @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
@@ -150,7 +158,7 @@ class RedisEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
@@ -162,7 +170,7 @@ class RedisEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Redis->delete($key) > 0;
@@ -171,8 +179,9 @@ class RedisEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
- * @param boolean $check
- * @return boolean True if the cache was successfully cleared, false otherwise
+ * @param bool $check Whether or not expiration keys should be checked. If
+ * true, no keys will be removed as cache will rely on redis TTL's.
+ * @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if ($check) {
@@ -208,7 +217,8 @@ class RedisEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
- * @return boolean success
+ * @param string $group The group name to clear.
+ * @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Redis->incr($this->settings['prefix'] . $group);
@@ -222,4 +232,27 @@ class RedisEngine extends CacheEngine {
$this->_Redis->close();
}
}
+
+/**
+ * Write data for key into cache if it doesn't exist already.
+ * If it already exists, it fails and returns false.
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached.
+ * @param int $duration How long to cache the data, in seconds.
+ * @return bool True if the data was successfully cached, false on failure.
+ * @link https://github.com/phpredis/phpredis#setnx
+ */
+ public function add($key, $value, $duration) {
+ if (!is_int($value)) {
+ $value = serialize($value);
+ }
+
+ $result = $this->_Redis->setnx($key, $value);
+ // setnx() doesn't have an expiry option, so overwrite the key with one
+ if ($result) {
+ return $this->_Redis->setex($key, $duration, $value);
+ }
+ return false;
+ }
}
diff --git a/web/api/lib/Cake/Cache/Engine/WincacheEngine.php b/web/api/lib/Cake/Cache/Engine/WincacheEngine.php
index bfba803d2..e5c9d7bd7 100644
--- a/web/api/lib/Cake/Cache/Engine/WincacheEngine.php
+++ b/web/api/lib/Cake/Cache/Engine/WincacheEngine.php
@@ -40,7 +40,7 @@ class WincacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
* @see CacheEngine::__defaults
*/
public function init($settings = array()) {
@@ -57,8 +57,8 @@ class WincacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
- * @param integer $duration How long to cache the data, in seconds
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache the data, in seconds
+ * @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
$expires = time() + $duration;
@@ -80,7 +80,7 @@ class WincacheEngine extends CacheEngine {
*/
public function read($key) {
$time = time();
- $cachetime = intval(wincache_ucache_get($key . '_expires'));
+ $cachetime = (int)wincache_ucache_get($key . '_expires');
if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) {
return false;
}
@@ -91,7 +91,7 @@ class WincacheEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to increment
+ * @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
@@ -102,7 +102,7 @@ class WincacheEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
@@ -113,7 +113,7 @@ class WincacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return wincache_ucache_delete($key);
@@ -123,9 +123,9 @@ class WincacheEngine extends CacheEngine {
* Delete all keys from the cache. This will clear every
* item in the cache matching the cache config prefix.
*
- * @param boolean $check If true, nothing will be cleared, as entries will
+ * @param bool $check If true, nothing will be cleared, as entries will
* naturally expire in wincache..
- * @return boolean True Returns true.
+ * @return bool True Returns true.
*/
public function clear($check) {
if ($check) {
@@ -179,7 +179,8 @@ class WincacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
- * @return boolean success
+ * @param string $group The group to clear.
+ * @return bool success
*/
public function clearGroup($group) {
$success = null;
@@ -187,4 +188,20 @@ class WincacheEngine extends CacheEngine {
return $success;
}
+/**
+ * Write data for key into cache if it doesn't exist already.
+ * If it already exists, it fails and returns false.
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached.
+ * @param int $duration How long to cache the data, in seconds.
+ * @return bool True if the data was successfully cached, false on failure.
+ */
+ public function add($key, $value, $duration) {
+ $cachedValue = $this->read($key);
+ if ($cachedValue === false) {
+ return $this->write($key, $value, $duration);
+ }
+ return false;
+ }
}
diff --git a/web/api/lib/Cake/Cache/Engine/XcacheEngine.php b/web/api/lib/Cake/Cache/Engine/XcacheEngine.php
index 12e19c786..c46a7b9c5 100644
--- a/web/api/lib/Cake/Cache/Engine/XcacheEngine.php
+++ b/web/api/lib/Cake/Cache/Engine/XcacheEngine.php
@@ -41,10 +41,10 @@ class XcacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
- * @return boolean True if the engine has been successfully initialized, false if not
+ * @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
- if (php_sapi_name() !== 'cli') {
+ if (PHP_SAPI !== 'cli') {
parent::init(array_merge(array(
'engine' => 'Xcache',
'prefix' => Inflector::slug(APP_DIR) . '_',
@@ -62,8 +62,8 @@ class XcacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
- * @param integer $duration How long to cache the data, in seconds
- * @return boolean True if the data was successfully cached, false on failure
+ * @param int $duration How long to cache the data, in seconds
+ * @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
$expires = time() + $duration;
@@ -80,7 +80,7 @@ class XcacheEngine extends CacheEngine {
public function read($key) {
if (xcache_isset($key)) {
$time = time();
- $cachetime = intval(xcache_get($key . '_expires'));
+ $cachetime = (int)xcache_get($key . '_expires');
if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) {
return false;
}
@@ -94,7 +94,7 @@ class XcacheEngine extends CacheEngine {
* If the cache key is not an integer it will be treated as 0
*
* @param string $key Identifier for the data
- * @param integer $offset How much to increment
+ * @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
@@ -106,7 +106,7 @@ class XcacheEngine extends CacheEngine {
* If the cache key is not an integer it will be treated as 0
*
* @param string $key Identifier for the data
- * @param integer $offset How much to subtract
+ * @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
@@ -117,7 +117,7 @@ class XcacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
- * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
+ * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return xcache_unset($key);
@@ -126,8 +126,9 @@ class XcacheEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
- * @param boolean $check
- * @return boolean True if the cache was successfully cleared, false otherwise
+ * @param bool $check If true no deletes will occur and instead CakePHP will rely
+ * on key TTL values.
+ * @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
$this->_auth();
@@ -163,7 +164,8 @@ class XcacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
- * @return boolean success
+ * @param string $group The group to clear.
+ * @return bool success
*/
public function clearGroup($group) {
return (bool)xcache_inc($this->settings['prefix'] . $group, 1);
@@ -176,7 +178,7 @@ class XcacheEngine extends CacheEngine {
* This has to be done because xcache_clear_cache() needs to pass Basic Http Auth
* (see xcache.admin configuration settings)
*
- * @param boolean $reverse Revert changes
+ * @param bool $reverse Revert changes
* @return void
*/
protected function _auth($reverse = false) {
@@ -205,4 +207,21 @@ class XcacheEngine extends CacheEngine {
}
}
}
+
+/**
+ * Write data for key into cache if it doesn't exist already.
+ * If it already exists, it fails and returns false.
+ *
+ * @param string $key Identifier for the data.
+ * @param mixed $value Data to be cached.
+ * @param int $duration How long to cache the data, in seconds.
+ * @return bool True if the data was successfully cached, false on failure.
+ */
+ public function add($key, $value, $duration) {
+ $cachedValue = $this->read($key);
+ if ($cachedValue === false) {
+ return $this->write($key, $value, $duration);
+ }
+ return false;
+ }
}
diff --git a/web/api/lib/Cake/Config/routes.php b/web/api/lib/Cake/Config/routes.php
index e27ba3a40..7bcc0c06b 100644
--- a/web/api/lib/Cake/Config/routes.php
+++ b/web/api/lib/Cake/Config/routes.php
@@ -48,8 +48,8 @@ if ($plugins = CakePlugin::loaded()) {
$plugins[$key] = Inflector::underscore($value);
}
$pluginPattern = implode('|', $plugins);
- $match = array('plugin' => $pluginPattern);
- $shortParams = array('routeClass' => 'PluginShortRoute', 'plugin' => $pluginPattern);
+ $match = array('plugin' => $pluginPattern, 'defaultRoute' => true);
+ $shortParams = array('routeClass' => 'PluginShortRoute', 'plugin' => $pluginPattern, 'defaultRoute' => true);
foreach ($prefixes as $prefix) {
$params = array('prefix' => $prefix, $prefix => true);
@@ -66,11 +66,11 @@ if ($plugins = CakePlugin::loaded()) {
foreach ($prefixes as $prefix) {
$params = array('prefix' => $prefix, $prefix => true);
$indexParams = $params + array('action' => 'index');
- Router::connect("/{$prefix}/:controller", $indexParams);
- Router::connect("/{$prefix}/:controller/:action/*", $params);
+ Router::connect("/{$prefix}/:controller", $indexParams, array('defaultRoute' => true));
+ Router::connect("/{$prefix}/:controller/:action/*", $params, array('defaultRoute' => true));
}
-Router::connect('/:controller', array('action' => 'index'));
-Router::connect('/:controller/:action/*');
+Router::connect('/:controller', array('action' => 'index'), array('defaultRoute' => true));
+Router::connect('/:controller/:action/*', array(), array('defaultRoute' => true));
$namedConfig = Router::namedConfig();
if ($namedConfig['rules'] === false) {
@@ -79,3 +79,4 @@ if ($namedConfig['rules'] === false) {
unset($namedConfig, $params, $indexParams, $prefix, $prefixes, $shortParams, $match,
$pluginPattern, $plugins, $key, $value);
+
diff --git a/web/api/lib/Cake/Configure/ConfigReaderInterface.php b/web/api/lib/Cake/Configure/ConfigReaderInterface.php
index e36f05697..ddea4e2d3 100644
--- a/web/api/lib/Cake/Configure/ConfigReaderInterface.php
+++ b/web/api/lib/Cake/Configure/ConfigReaderInterface.php
@@ -26,7 +26,7 @@ interface ConfigReaderInterface {
* These sources can either be static resources like files, or dynamic ones like
* a database, or other datasource.
*
- * @param string $key
+ * @param string $key Key to read.
* @return array An array of data to merge into the runtime configuration
*/
public function read($key);
@@ -36,7 +36,7 @@ interface ConfigReaderInterface {
*
* @param string $key The identifier to write to.
* @param array $data The data to dump.
- * @return boolean True on success or false on failure.
+ * @return bool True on success or false on failure.
*/
public function dump($key, $data);
diff --git a/web/api/lib/Cake/Configure/IniReader.php b/web/api/lib/Cake/Configure/IniReader.php
index 886ab1779..ad3b88145 100644
--- a/web/api/lib/Cake/Configure/IniReader.php
+++ b/web/api/lib/Cake/Configure/IniReader.php
@@ -17,6 +17,7 @@
*/
App::uses('Hash', 'Utility');
+App::uses('CakePlugin', 'Core');
/**
* Ini file configuration engine.
@@ -33,10 +34,10 @@ App::uses('Hash', 'Utility');
* You can nest properties as deeply as needed using `.`'s. In addition to using `.` you
* can use standard ini section notation to create nested structures:
*
- * {{{
+ * ```
* [section]
* key = value
- * }}}
+ * ```
*
* Once loaded into Configure, the above would be accessed using:
*
@@ -101,7 +102,7 @@ class IniReader implements ConfigReaderInterface {
}
$file = $this->_getFilePath($key);
- if (!is_file($file)) {
+ if (!is_file(realpath($file))) {
throw new ConfigureException(__d('cake_dev', 'Could not load configuration file: %s', $file));
}
@@ -152,7 +153,7 @@ class IniReader implements ConfigReaderInterface {
* @param string $key The identifier to write to. If the key has a . it will be treated
* as a plugin prefix.
* @param array $data The data to convert to ini file.
- * @return integer Bytes saved.
+ * @return int Bytes saved.
*/
public function dump($key, $data) {
$result = array();
@@ -181,7 +182,7 @@ class IniReader implements ConfigReaderInterface {
/**
* Converts a value into the ini equivalent
*
- * @param mixed $value to export.
+ * @param mixed $val Value to export.
* @return string String value for ini file.
*/
protected function _value($val) {
@@ -218,7 +219,7 @@ class IniReader implements ConfigReaderInterface {
}
if ($plugin) {
- $file = App::pluginPath($plugin) . 'Config' . DS . $key;
+ $file = CakePlugin::path($plugin) . 'Config' . DS . $key;
} else {
$file = $this->_path . $key;
}
diff --git a/web/api/lib/Cake/Configure/PhpReader.php b/web/api/lib/Cake/Configure/PhpReader.php
index 175168a39..d15a41b83 100644
--- a/web/api/lib/Cake/Configure/PhpReader.php
+++ b/web/api/lib/Cake/Configure/PhpReader.php
@@ -15,6 +15,8 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
+App::uses('CakePlugin', 'Core');
+
/**
* PHP Reader allows Configure to load configuration values from
* files containing simple PHP arrays.
@@ -49,7 +51,7 @@ class PhpReader implements ConfigReaderInterface {
* Read a config file and return its contents.
*
* Files with `.` in the name will be treated as values in plugins. Instead of reading from
- * the initialized path, plugin keys will be located using App::pluginPath().
+ * the initialized path, plugin keys will be located using CakePlugin::path().
*
* @param string $key The identifier to read from. If the key has a . it will be treated
* as a plugin prefix.
@@ -63,7 +65,7 @@ class PhpReader implements ConfigReaderInterface {
}
$file = $this->_getFilePath($key);
- if (!is_file($file)) {
+ if (!is_file(realpath($file))) {
throw new ConfigureException(__d('cake_dev', 'Could not load configuration file: %s', $file));
}
@@ -81,7 +83,7 @@ class PhpReader implements ConfigReaderInterface {
* @param string $key The identifier to write to. If the key has a . it will be treated
* as a plugin prefix.
* @param array $data Data to dump.
- * @return integer Bytes saved.
+ * @return int Bytes saved.
*/
public function dump($key, $data) {
$contents = '_path . $key;
}
diff --git a/web/api/lib/Cake/Console/Command/AclShell.php b/web/api/lib/Cake/Console/Command/AclShell.php
index ac5b3cdfe..15536ebb6 100644
--- a/web/api/lib/Cake/Console/Command/AclShell.php
+++ b/web/api/lib/Cake/Console/Command/AclShell.php
@@ -220,7 +220,7 @@ class AclShell extends AppShell {
*
* @param string $class Class name that is being used.
* @param array $node Array of node information.
- * @param integer $indent indent level.
+ * @param int $indent indent level.
* @return void
*/
protected function _outputNode($class, $node, $indent) {
@@ -519,7 +519,7 @@ class AclShell extends AppShell {
/**
* Checks that given node exists
*
- * @return boolean Success
+ * @return bool Success
*/
public function nodeExists() {
if (!isset($this->args[0]) || !isset($this->args[1])) {
@@ -558,8 +558,8 @@ class AclShell extends AppShell {
* or an array of properties to use in AcoNode::node()
*
* @param string $class Class type you want (Aro/Aco)
- * @param string|array $identifier A mixed identifier for finding the node.
- * @return integer Integer of NodeId. Will trigger an error if nothing is found.
+ * @param string|array|null $identifier A mixed identifier for finding the node, otherwise null.
+ * @return int Integer of NodeId. Will trigger an error if nothing is found.
*/
protected function _getNodeId($class, $identifier) {
$node = $this->Acl->{$class}->node($identifier);
@@ -568,7 +568,7 @@ class AclShell extends AppShell {
$identifier = var_export($identifier, true);
}
$this->error(__d('cake_console', 'Could not find node using reference "%s"', $identifier));
- return;
+ return null;
}
return Hash::get($node, "0.{$class}.id");
}
@@ -579,8 +579,8 @@ class AclShell extends AppShell {
* @return array aro, aco, action
*/
protected function _getParams() {
- $aro = is_numeric($this->args[0]) ? intval($this->args[0]) : $this->args[0];
- $aco = is_numeric($this->args[1]) ? intval($this->args[1]) : $this->args[1];
+ $aro = is_numeric($this->args[0]) ? (int)$this->args[0] : $this->args[0];
+ $aco = is_numeric($this->args[1]) ? (int)$this->args[1] : $this->args[1];
$aroName = $aro;
$acoName = $aco;
diff --git a/web/api/lib/Cake/Console/Command/CommandListShell.php b/web/api/lib/Cake/Console/Command/CommandListShell.php
index 755166f41..ca6620a5b 100644
--- a/web/api/lib/Cake/Console/Command/CommandListShell.php
+++ b/web/api/lib/Cake/Console/Command/CommandListShell.php
@@ -77,7 +77,7 @@ class CommandListShell extends AppShell {
/**
* Output text.
*
- * @param array $shellList
+ * @param array $shellList The shell list.
* @return void
*/
protected function _asText($shellList) {
@@ -95,7 +95,7 @@ class CommandListShell extends AppShell {
/**
* Output as XML
*
- * @param array $shellList
+ * @param array $shellList The shell list.
* @return void
*/
protected function _asXml($shellList) {
diff --git a/web/api/lib/Cake/Console/Command/CompletionShell.php b/web/api/lib/Cake/Console/Command/CompletionShell.php
index b57c84145..57e86f949 100644
--- a/web/api/lib/Cake/Console/Command/CompletionShell.php
+++ b/web/api/lib/Cake/Console/Command/CompletionShell.php
@@ -144,7 +144,7 @@ class CompletionShell extends AppShell {
/**
* Emit results as a string, space delimited
*
- * @param array $options
+ * @param array $options The options to output
* @return void
*/
protected function _output($options = array()) {
diff --git a/web/api/lib/Cake/Console/Command/ConsoleShell.php b/web/api/lib/Cake/Console/Command/ConsoleShell.php
index 917015a9f..ac270e19b 100644
--- a/web/api/lib/Cake/Console/Command/ConsoleShell.php
+++ b/web/api/lib/Cake/Console/Command/ConsoleShell.php
@@ -19,7 +19,7 @@ App::uses('AppShell', 'Console/Command');
* Provides a very basic 'interactive' console for CakePHP apps.
*
* @package Cake.Console.Command
- * @deprecated Deprecated since version 2.4, will be removed in 3.0
+ * @deprecated 3.0.0 Deprecated since version 2.4, will be removed in 3.0
*/
class ConsoleShell extends AppShell {
@@ -193,7 +193,7 @@ class ConsoleShell extends AppShell {
/**
* Override main() to handle action
*
- * @param string $command
+ * @param string $command The command to run.
* @return void
*/
public function main($command = null) {
@@ -218,7 +218,7 @@ class ConsoleShell extends AppShell {
/**
* Determine the method to process the current command
*
- * @param string $command
+ * @param string $command The command to run.
* @return string or false
*/
protected function _method($command) {
@@ -256,7 +256,7 @@ class ConsoleShell extends AppShell {
/**
* Bind an association
*
- * @param mixed $command
+ * @param mixed $command The command to run.
* @return void
*/
protected function _bind($command) {
@@ -283,7 +283,7 @@ class ConsoleShell extends AppShell {
/**
* Unbind an association
*
- * @param mixed $command
+ * @param mixed $command The command to run.
* @return void
*/
protected function _unbind($command) {
@@ -303,7 +303,7 @@ class ConsoleShell extends AppShell {
$validCurrentAssociation = false;
foreach ($currentAssociations as $model => $currentAssociation) {
- if ($model == $modelB && $association == $currentAssociation) {
+ if ($model === $modelB && $association === $currentAssociation) {
$validCurrentAssociation = true;
}
}
@@ -320,7 +320,7 @@ class ConsoleShell extends AppShell {
/**
* Perform a find
*
- * @param mixed $command
+ * @param mixed $command The command to run.
* @return void
*/
protected function _find($command) {
@@ -382,7 +382,7 @@ class ConsoleShell extends AppShell {
/**
* Save a record
*
- * @param mixed $command
+ * @param mixed $command The command to run.
* @return void
*/
protected function _save($command) {
@@ -406,7 +406,7 @@ class ConsoleShell extends AppShell {
/**
* Show the columns for a model
*
- * @param mixed $command
+ * @param mixed $command The command to run.
* @return void
*/
protected function _columns($command) {
@@ -455,7 +455,7 @@ class ConsoleShell extends AppShell {
/**
* Parse an array URL and show the equivalent URL as a string
*
- * @param mixed $command
+ * @param mixed $command The command to run.
* @return void
*/
protected function _routeToString($command) {
@@ -471,7 +471,7 @@ class ConsoleShell extends AppShell {
/**
* Parse a string URL and show as an array
*
- * @param mixed $command
+ * @param mixed $command The command to run.
* @return void
*/
protected function _routeToArray($command) {
@@ -483,8 +483,8 @@ class ConsoleShell extends AppShell {
/**
* Tells if the specified model is included in the list of available models
*
- * @param string $modelToCheck
- * @return boolean true if is an available model, false otherwise
+ * @param string $modelToCheck The model to check.
+ * @return bool true if is an available model, false otherwise
*/
protected function _isValidModel($modelToCheck) {
return in_array($modelToCheck, $this->models);
@@ -494,7 +494,7 @@ class ConsoleShell extends AppShell {
* Reloads the routes configuration from app/Config/routes.php, and compiles
* all routes found
*
- * @return boolean True if config reload was a success, otherwise false
+ * @return bool True if config reload was a success, otherwise false
*/
protected function _loadRoutes() {
Router::reload();
diff --git a/web/api/lib/Cake/Console/Command/SchemaShell.php b/web/api/lib/Cake/Console/Command/SchemaShell.php
index 6df8a32ea..a2ddfcc0a 100644
--- a/web/api/lib/Cake/Console/Command/SchemaShell.php
+++ b/web/api/lib/Cake/Console/Command/SchemaShell.php
@@ -39,7 +39,7 @@ class SchemaShell extends AppShell {
/**
* is this a dry run?
*
- * @var boolean
+ * @var bool
*/
protected $_dry = null;
@@ -66,13 +66,10 @@ class SchemaShell extends AppShell {
list($this->params['plugin'], $splitName) = pluginSplit($name);
$name = $this->params['name'] = $splitName;
}
-
- $defaultFile = 'schema.php';
- if (empty($this->params['file'])) {
- $this->params['file'] = $defaultFile;
- }
- if ($name && $this->params['file'] === $defaultFile) {
+ if ($name && empty($this->params['file'])) {
$this->params['file'] = Inflector::underscore($name);
+ } elseif (empty($this->params['file'])) {
+ $this->params['file'] = 'schema.php';
}
if (strpos($this->params['file'], '.php') === false) {
$this->params['file'] .= '.php';
@@ -92,7 +89,7 @@ class SchemaShell extends AppShell {
$name = $plugin;
}
}
- $name = Inflector::classify($name);
+ $name = Inflector::camelize($name);
$this->Schema = new CakeSchema(compact('name', 'path', 'file', 'connection', 'plugin'));
}
@@ -125,7 +122,7 @@ class SchemaShell extends AppShell {
if ($this->params['force']) {
$options['models'] = false;
} elseif (!empty($this->params['models'])) {
- $options['models'] = String::tokenize($this->params['models']);
+ $options['models'] = CakeText::tokenize($this->params['models']);
}
$snapshot = false;
@@ -154,14 +151,14 @@ class SchemaShell extends AppShell {
Configure::write('Cache.disable', $cacheDisable);
if (!empty($this->params['exclude']) && !empty($content)) {
- $excluded = String::tokenize($this->params['exclude']);
+ $excluded = CakeText::tokenize($this->params['exclude']);
foreach ($excluded as $table) {
unset($content['tables'][$table]);
}
}
if ($snapshot === true) {
- $fileName = rtrim($this->params['file'], '.php');
+ $fileName = basename($this->params['file'], '.php');
$Folder = new Folder($this->Schema->path);
$result = $Folder->read();
@@ -288,17 +285,17 @@ class SchemaShell extends AppShell {
'connection' => $this->params['connection'],
);
if (!empty($this->params['snapshot'])) {
- $fileName = rtrim($this->Schema->file, '.php');
+ $fileName = basename($this->Schema->file, '.php');
$options['file'] = $fileName . '_' . $this->params['snapshot'] . '.php';
}
$Schema = $this->Schema->load($options);
if (!$Schema) {
- $this->err(__d('cake_console', 'The chosen schema could not be loaded. Attempted to load:'));
- $this->err(__d('cake_console', 'File: %s', $this->Schema->path . DS . $this->Schema->file));
- $this->err(__d('cake_console', 'Name: %s', $this->Schema->name));
- return $this->_stop();
+ $this->err(__d('cake_console', 'Error: The chosen schema could not be loaded. Attempted to load:'));
+ $this->err(__d('cake_console', '- file: %s', $this->Schema->path . DS . $this->Schema->file));
+ $this->err(__d('cake_console', '- name: %s', $this->Schema->name));
+ return $this->_stop(2);
}
$table = null;
if (isset($this->args[1])) {
@@ -311,8 +308,8 @@ class SchemaShell extends AppShell {
* Create database from Schema object
* Should be called via the run method
*
- * @param CakeSchema $Schema
- * @param string $table
+ * @param CakeSchema $Schema The schema instance to create.
+ * @param string $table The table name.
* @return void
*/
protected function _create(CakeSchema $Schema, $table = null) {
@@ -337,8 +334,7 @@ class SchemaShell extends AppShell {
$this->out("\n" . __d('cake_console', 'The following table(s) will be dropped.'));
$this->out(array_keys($drop));
- if (
- !empty($this->params['yes']) ||
+ if (!empty($this->params['yes']) ||
$this->in(__d('cake_console', 'Are you sure you want to drop the table(s)?'), array('y', 'n'), 'n') === 'y'
) {
$this->out(__d('cake_console', 'Dropping table(s).'));
@@ -348,8 +344,7 @@ class SchemaShell extends AppShell {
$this->out("\n" . __d('cake_console', 'The following table(s) will be created.'));
$this->out(array_keys($create));
- if (
- !empty($this->params['yes']) ||
+ if (!empty($this->params['yes']) ||
$this->in(__d('cake_console', 'Are you sure you want to create the table(s)?'), array('y', 'n'), 'y') === 'y'
) {
$this->out(__d('cake_console', 'Creating table(s).'));
@@ -362,8 +357,8 @@ class SchemaShell extends AppShell {
* Update database with Schema object
* Should be called via the run method
*
- * @param CakeSchema $Schema
- * @param string $table
+ * @param CakeSchema &$Schema The schema instance
+ * @param string $table The table name.
* @return void
*/
protected function _update(&$Schema, $table = null) {
@@ -402,13 +397,15 @@ class SchemaShell extends AppShell {
$this->out("\n" . __d('cake_console', 'The following statements will run.'));
$this->out(array_map('trim', $contents));
- if (
- !empty($this->params['yes']) ||
+ if (!empty($this->params['yes']) ||
$this->in(__d('cake_console', 'Are you sure you want to alter the tables?'), array('y', 'n'), 'n') === 'y'
) {
$this->out();
$this->out(__d('cake_console', 'Updating Database...'));
$this->_run($contents, 'update', $Schema);
+
+ Configure::write('Cache.disable', false);
+ Cache::clear(false, '_cake_model_');
}
$this->out(__d('cake_console', 'End update.'));
@@ -417,9 +414,9 @@ class SchemaShell extends AppShell {
/**
* Runs sql from _create() or _update()
*
- * @param array $contents
- * @param string $event
- * @param CakeSchema $Schema
+ * @param array $contents The contents to execute.
+ * @param string $event The event to fire
+ * @param CakeSchema $Schema The schema instance.
* @return void
*/
protected function _run($contents, $event, CakeSchema $Schema) {
@@ -483,7 +480,6 @@ class SchemaShell extends AppShell {
);
$file = array(
'help' => __d('cake_console', 'File name to read and write.'),
- 'default' => 'schema.php'
);
$name = array(
'help' => __d('cake_console',
diff --git a/web/api/lib/Cake/Console/Command/ServerShell.php b/web/api/lib/Cake/Console/Command/ServerShell.php
index ae46f6ef8..8c7d5e5e3 100644
--- a/web/api/lib/Cake/Console/Command/ServerShell.php
+++ b/web/api/lib/Cake/Console/Command/ServerShell.php
@@ -34,7 +34,7 @@ class ServerShell extends AppShell {
/**
* Default ListenPort
*
- * @var integer
+ * @var int
*/
const DEFAULT_PORT = 80;
@@ -65,8 +65,8 @@ class ServerShell extends AppShell {
* @return void
*/
public function initialize() {
- $this->_host = self::DEFAULT_HOST;
- $this->_port = self::DEFAULT_PORT;
+ $this->_host = static::DEFAULT_HOST;
+ $this->_port = static::DEFAULT_PORT;
$this->_documentRoot = WWW_ROOT;
}
@@ -91,8 +91,8 @@ class ServerShell extends AppShell {
$this->_documentRoot = $this->params['document_root'];
}
- // for windows
- if (substr($this->_documentRoot, -1, 1) == DIRECTORY_SEPARATOR) {
+ // for Windows
+ if (substr($this->_documentRoot, -1, 1) === DIRECTORY_SEPARATOR) {
$this->_documentRoot = substr($this->_documentRoot, 0, strlen($this->_documentRoot) - 1);
}
if (preg_match("/^([a-z]:)[\\\]+(.+)$/i", $this->_documentRoot, $m)) {
@@ -135,7 +135,7 @@ class ServerShell extends AppShell {
escapeshellarg($this->_documentRoot . '/index.php')
);
- $port = ($this->_port == self::DEFAULT_PORT) ? '' : ':' . $this->_port;
+ $port = ($this->_port == static::DEFAULT_PORT) ? '' : ':' . $this->_port;
$this->out(__d('cake_console', 'built-in server is running in http://%s%s/', $this->_host, $port));
system($command);
}
diff --git a/web/api/lib/Cake/Console/Command/Task/BakeTask.php b/web/api/lib/Cake/Console/Command/Task/BakeTask.php
index 6b534f365..8298e112a 100644
--- a/web/api/lib/Cake/Console/Command/Task/BakeTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/BakeTask.php
@@ -41,7 +41,7 @@ class BakeTask extends AppShell {
/**
* Flag for interactive mode
*
- * @var boolean
+ * @var bool
*/
public $interactive = false;
diff --git a/web/api/lib/Cake/Console/Command/Task/CommandTask.php b/web/api/lib/Cake/Console/Command/Task/CommandTask.php
index 9c90fc6be..fca006a72 100644
--- a/web/api/lib/Cake/Console/Command/Task/CommandTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/CommandTask.php
@@ -53,9 +53,9 @@ class CommandTask extends AppShell {
/**
* Scan the provided paths for shells, and append them into $shellList
*
- * @param string $type
- * @param array $shells
- * @param array $shellList
+ * @param string $type The type of object.
+ * @param array $shells The shell name.
+ * @param array &$shellList List of shells.
* @return void
*/
protected function _appendShells($type, $shells, &$shellList) {
@@ -90,7 +90,7 @@ class CommandTask extends AppShell {
/**
* Return a list of subcommands for a given command
*
- * @param string $commandName
+ * @param string $commandName The command you want subcommands from.
* @return array
*/
public function subCommands($commandName) {
@@ -127,7 +127,7 @@ class CommandTask extends AppShell {
/**
* Get Shell instance for the given command
*
- * @param mixed $commandName
+ * @param mixed $commandName The command you want.
* @return mixed
*/
public function getShell($commandName) {
@@ -157,7 +157,7 @@ class CommandTask extends AppShell {
/**
* Get Shell instance for the given command
*
- * @param mixed $commandName
+ * @param mixed $commandName The command to get options for.
* @return array
*/
public function options($commandName) {
diff --git a/web/api/lib/Cake/Console/Command/Task/ControllerTask.php b/web/api/lib/Cake/Console/Command/Task/ControllerTask.php
index 5a4553466..fc2d91343 100644
--- a/web/api/lib/Cake/Console/Command/Task/ControllerTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/ControllerTask.php
@@ -188,6 +188,7 @@ class ControllerTask extends BakeTask {
if (strtolower($wannaUseSession) === 'y') {
array_push($components, 'Session');
}
+ array_unique($components);
}
} else {
list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods();
@@ -224,10 +225,10 @@ class ControllerTask extends BakeTask {
/**
* Confirm a to be baked controller with the user
*
- * @param string $controllerName
- * @param string $useDynamicScaffold
- * @param array $helpers
- * @param array $components
+ * @param string $controllerName The name of the controller.
+ * @param string $useDynamicScaffold Whether or not to use dynamic scaffolds.
+ * @param array $helpers The list of helpers to include.
+ * @param array $components The list of components to include.
* @return void
*/
public function confirmController($controllerName, $useDynamicScaffold, $helpers, $components) {
@@ -247,10 +248,10 @@ class ControllerTask extends BakeTask {
);
foreach ($properties as $var => $title) {
- if (count($$var)) {
+ if (count(${$var})) {
$output = '';
- $length = count($$var);
- foreach ($$var as $i => $propElement) {
+ $length = count(${$var});
+ foreach (${$var} as $i => $propElement) {
if ($i != $length - 1) {
$output .= ucfirst($propElement) . ', ';
} else {
@@ -285,7 +286,7 @@ class ControllerTask extends BakeTask {
*
* @param string $controllerName Controller name
* @param string $admin Admin route to use
- * @param boolean $wannaUseSession Set to true to use sessions, false otherwise
+ * @param bool $wannaUseSession Set to true to use sessions, false otherwise
* @return string Baked actions
*/
public function bakeActions($controllerName, $admin = null, $wannaUseSession = true) {
@@ -383,9 +384,9 @@ class ControllerTask extends BakeTask {
* @return array Components the user wants to use.
*/
public function doComponents() {
- $components = array('Paginator');
+ $components = array('Paginator', 'Flash');
return array_merge($components, $this->_doPropertyChoices(
- __d('cake_console', "Would you like this controller to use other components\nbesides PaginatorComponent?"),
+ __d('cake_console', "Would you like this controller to use other components\nbesides PaginatorComponent and FlashComponent?"),
__d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'")
));
}
@@ -451,14 +452,14 @@ class ControllerTask extends BakeTask {
return $this->_stop();
}
- if (!$enteredController || intval($enteredController) > count($controllers)) {
+ if (!$enteredController || (int)$enteredController > count($controllers)) {
$this->err(__d('cake_console', "The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again."));
$enteredController = '';
}
}
- if (intval($enteredController) > 0 && intval($enteredController) <= count($controllers)) {
- $controllerName = $controllers[intval($enteredController) - 1];
+ if ((int)$enteredController > 0 && (int)$enteredController <= count($controllers)) {
+ $controllerName = $controllers[(int)$enteredController - 1];
} else {
$controllerName = Inflector::camelize($enteredController);
}
diff --git a/web/api/lib/Cake/Console/Command/Task/DbConfigTask.php b/web/api/lib/Cake/Console/Command/Task/DbConfigTask.php
index 75c0c13b6..ee1aa6c99 100644
--- a/web/api/lib/Cake/Console/Command/Task/DbConfigTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/DbConfigTask.php
@@ -199,8 +199,8 @@ class DbConfigTask extends AppShell {
/**
* Output verification message and bake if it looks good
*
- * @param array $config
- * @return boolean True if user says it looks good, false otherwise
+ * @param array $config The config data.
+ * @return bool True if user says it looks good, false otherwise
*/
protected function _verify($config) {
$config += $this->_defaultConfig;
@@ -247,7 +247,7 @@ class DbConfigTask extends AppShell {
* Assembles and writes database.php
*
* @param array $configs Configuration settings to use
- * @return boolean Success
+ * @return bool Success
*/
public function bake($configs) {
if (!is_dir($this->path)) {
@@ -296,7 +296,7 @@ class DbConfigTask extends AppShell {
foreach ($oldConfigs as $key => $oldConfig) {
foreach ($configs as $config) {
- if ($oldConfig['name'] == $config['name']) {
+ if ($oldConfig['name'] === $config['name']) {
unset($oldConfigs[$key]);
}
}
diff --git a/web/api/lib/Cake/Console/Command/Task/ExtractTask.php b/web/api/lib/Cake/Console/Command/Task/ExtractTask.php
index d60bc0e5c..740528f70 100644
--- a/web/api/lib/Cake/Console/Command/Task/ExtractTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/ExtractTask.php
@@ -44,7 +44,7 @@ class ExtractTask extends AppShell {
/**
* Merge all domain and category strings into the default.pot file
*
- * @var boolean
+ * @var bool
*/
protected $_merge = false;
@@ -70,7 +70,7 @@ class ExtractTask extends AppShell {
protected $_tokens = array();
/**
- * Extracted strings indexed by category and domain.
+ * Extracted strings indexed by category, domain, msgid and context.
*
* @var array
*/
@@ -93,21 +93,21 @@ class ExtractTask extends AppShell {
/**
* Holds whether this call should extract model validation messages
*
- * @var boolean
+ * @var bool
*/
protected $_extractValidation = true;
/**
* Holds the validation string domain to use for validation messages when extracting
*
- * @var boolean
+ * @var bool
*/
protected $_validationDomain = 'default';
/**
* Holds whether this call should extract the CakePHP Lib messages
*
- * @var boolean
+ * @var bool
*/
protected $_extractCore = false;
@@ -127,7 +127,7 @@ class ExtractTask extends AppShell {
);
$response = $this->in($message, null, $defaultPath);
if (strtoupper($response) === 'Q') {
- $this->out(__d('cake_console', 'Extract Aborted'));
+ $this->err(__d('cake_console', 'Extract Aborted'));
return $this->_stop();
} elseif (strtoupper($response) === 'D' && count($this->_paths)) {
$this->out();
@@ -151,7 +151,7 @@ class ExtractTask extends AppShell {
*/
public function execute() {
if (!empty($this->params['exclude'])) {
- $this->_exclude = explode(',', $this->params['exclude']);
+ $this->_exclude = explode(',', str_replace('/', DS, $this->params['exclude']));
}
if (isset($this->params['files']) && !is_array($this->params['files'])) {
$this->_files = explode(',', $this->params['files']);
@@ -204,7 +204,7 @@ class ExtractTask extends AppShell {
while (true) {
$response = $this->in($message, null, rtrim($this->_paths[0], DS) . DS . 'Locale');
if (strtoupper($response) === 'Q') {
- $this->out(__d('cake_console', 'Extract Aborted'));
+ $this->err(__d('cake_console', 'Extract Aborted'));
return $this->_stop();
} elseif ($this->_isPathUsable($response)) {
$this->_output = $response . DS;
@@ -242,29 +242,33 @@ class ExtractTask extends AppShell {
*
* Takes care of duplicate translations
*
- * @param string $category
- * @param string $domain
- * @param string $msgid
- * @param array $details
+ * @param string $category The category
+ * @param string $domain The domain
+ * @param string $msgid The message string
+ * @param array $details The file and line references
* @return void
*/
protected function _addTranslation($category, $domain, $msgid, $details = array()) {
- if (empty($this->_translations[$category][$domain][$msgid])) {
- $this->_translations[$category][$domain][$msgid] = array(
- 'msgid_plural' => false
+ $context = '';
+ if (isset($details['msgctxt'])) {
+ $context = $details['msgctxt'];
+ }
+
+ if (empty($this->_translations[$category][$domain][$msgid][$context])) {
+ $this->_translations[$category][$domain][$msgid][$context] = array(
+ 'msgid_plural' => false,
);
}
if (isset($details['msgid_plural'])) {
- $this->_translations[$category][$domain][$msgid]['msgid_plural'] = $details['msgid_plural'];
+ $this->_translations[$category][$domain][$msgid][$context]['msgid_plural'] = $details['msgid_plural'];
}
-
if (isset($details['file'])) {
$line = 0;
if (isset($details['line'])) {
$line = $details['line'];
}
- $this->_translations[$category][$domain][$msgid]['references'][$details['file']][] = $line;
+ $this->_translations[$category][$domain][$msgid][$context]['references'][$details['file']][] = $line;
}
}
@@ -312,6 +316,10 @@ class ExtractTask extends AppShell {
))->addOption('merge', array(
'help' => __d('cake_console', 'Merge all domain and category strings into the default.po file.'),
'choices' => array('yes', 'no')
+ ))->addOption('no-location', array(
+ 'boolean' => true,
+ 'default' => false,
+ 'help' => __d('cake_console', 'Do not write lines with locations'),
))->addOption('output', array(
'help' => __d('cake_console', 'Full path to output directory.')
))->addOption('files', array(
@@ -355,14 +363,14 @@ class ExtractTask extends AppShell {
protected function _extractTokens() {
foreach ($this->_files as $file) {
$this->_file = $file;
- $this->out(__d('cake_console', 'Processing %s...', $file));
+ $this->out(__d('cake_console', 'Processing %s...', $file), 1, Shell::VERBOSE);
$code = file_get_contents($file);
$allTokens = token_get_all($code);
$this->_tokens = array();
foreach ($allTokens as $token) {
- if (!is_array($token) || ($token[0] != T_WHITESPACE && $token[0] != T_INLINE_HTML)) {
+ if (!is_array($token) || ($token[0] !== T_WHITESPACE && $token[0] !== T_INLINE_HTML)) {
$this->_tokens[] = $token;
}
}
@@ -374,6 +382,15 @@ class ExtractTask extends AppShell {
$this->_parse('__dc', array('domain', 'singular', 'category'));
$this->_parse('__dn', array('domain', 'singular', 'plural'));
$this->_parse('__dcn', array('domain', 'singular', 'plural', 'count', 'category'));
+
+ $this->_parse('__x', array('context', 'singular'));
+ $this->_parse('__xn', array('context', 'singular', 'plural'));
+ $this->_parse('__dx', array('domain', 'context', 'singular'));
+ $this->_parse('__dxc', array('domain', 'context', 'singular', 'category'));
+ $this->_parse('__dxn', array('domain', 'context', 'singular', 'plural'));
+ $this->_parse('__dxcn', array('domain', 'context', 'singular', 'plural', 'count', 'category'));
+ $this->_parse('__xc', array('context', 'singular', 'category'));
+
}
}
@@ -398,7 +415,7 @@ class ExtractTask extends AppShell {
}
list($type, $string, $line) = $countToken;
- if (($type == T_STRING) && ($string == $functionName) && ($firstParenthesis === '(')) {
+ if (($type == T_STRING) && ($string === $functionName) && ($firstParenthesis === '(')) {
$position = $count;
$depth = 0;
@@ -414,11 +431,12 @@ class ExtractTask extends AppShell {
$mapCount = count($map);
$strings = $this->_getStrings($position, $mapCount);
- if ($mapCount == count($strings)) {
+ if ($mapCount === count($strings)) {
extract(array_combine($map, $strings));
$category = isset($category) ? $category : 6;
- $category = intval($category);
+ $category = (int)$category;
$categoryName = $categories[$category];
+
$domain = isset($domain) ? $domain : 'default';
$details = array(
'file' => $this->_file,
@@ -427,8 +445,14 @@ class ExtractTask extends AppShell {
if (isset($plural)) {
$details['msgid_plural'] = $plural;
}
- $this->_addTranslation($categoryName, $domain, $singular, $details);
- } else {
+ if (isset($context)) {
+ $details['msgctxt'] = $context;
+ }
+ // Skip LC_TIME files as we use a special file format for them.
+ if ($categoryName !== 'LC_TIME') {
+ $this->_addTranslation($categoryName, $domain, $singular, $details);
+ }
+ } elseif (!is_array($this->_tokens[$count - 1]) || $this->_tokens[$count - 1][0] != T_FUNCTION) {
$this->_markerError($this->_file, $line, $functionName, $count);
}
}
@@ -547,32 +571,46 @@ class ExtractTask extends AppShell {
protected function _buildFiles() {
$paths = $this->_paths;
$paths[] = realpath(APP) . DS;
+
+ usort($paths, function ($a, $b) {
+ return strlen($b) - strlen($a);
+ });
+
foreach ($this->_translations as $category => $domains) {
foreach ($domains as $domain => $translations) {
- foreach ($translations as $msgid => $details) {
- $plural = $details['msgid_plural'];
- $files = $details['references'];
- $occurrences = array();
- foreach ($files as $file => $lines) {
- $lines = array_unique($lines);
- $occurrences[] = $file . ':' . implode(';', $lines);
- }
- $occurrences = implode("\n#: ", $occurrences);
- $header = '#: ' . str_replace(DS, '/', str_replace($paths, '', $occurrences)) . "\n";
+ foreach ($translations as $msgid => $contexts) {
+ foreach ($contexts as $context => $details) {
+ $plural = $details['msgid_plural'];
+ $header = '';
+ if (empty($this->params['no-location'])) {
+ $files = $details['references'];
+ $occurrences = array();
+ foreach ($files as $file => $lines) {
+ $lines = array_unique($lines);
+ $occurrences[] = $file . ':' . implode(';', $lines);
+ }
+ $occurrences = implode("\n#: ", $occurrences);
+ $header = '#: ' . str_replace(DS, '/', str_replace($paths, '', $occurrences)) . "\n";
+ }
- if ($plural === false) {
- $sentence = "msgid \"{$msgid}\"\n";
- $sentence .= "msgstr \"\"\n\n";
- } else {
- $sentence = "msgid \"{$msgid}\"\n";
- $sentence .= "msgid_plural \"{$plural}\"\n";
- $sentence .= "msgstr[0] \"\"\n";
- $sentence .= "msgstr[1] \"\"\n\n";
- }
+ $sentence = '';
+ if ($context) {
+ $sentence .= "msgctxt \"{$context}\"\n";
+ }
+ if ($plural === false) {
+ $sentence .= "msgid \"{$msgid}\"\n";
+ $sentence .= "msgstr \"\"\n\n";
+ } else {
+ $sentence .= "msgid \"{$msgid}\"\n";
+ $sentence .= "msgid_plural \"{$plural}\"\n";
+ $sentence .= "msgstr[0] \"\"\n";
+ $sentence .= "msgstr[1] \"\"\n\n";
+ }
- $this->_store($category, $domain, $header, $sentence);
- if (($category !== 'LC_MESSAGES' || $domain !== 'default') && $this->_merge) {
- $this->_store('LC_MESSAGES', 'default', $header, $sentence);
+ $this->_store($category, $domain, $header, $sentence);
+ if (($category !== 'LC_MESSAGES' || $domain !== 'default') && $this->_merge) {
+ $this->_store('LC_MESSAGES', 'default', $header, $sentence);
+ }
}
}
}
@@ -582,10 +620,10 @@ class ExtractTask extends AppShell {
/**
* Prepare a file to be stored
*
- * @param string $category
- * @param string $domain
- * @param string $header
- * @param string $sentence
+ * @param string $category The category
+ * @param string $domain The domain
+ * @param string $header The header content.
+ * @param string $sentence The sentence to store.
* @return void
*/
protected function _store($category, $domain, $header, $sentence) {
@@ -664,7 +702,6 @@ class ExtractTask extends AppShell {
$output .= "msgid \"\"\n";
$output .= "msgstr \"\"\n";
$output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
- $output .= "\"POT-Creation-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
$output .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
$output .= "\"Last-Translator: NAME \\n\"\n";
$output .= "\"Language-Team: LANGUAGE \\n\"\n";
@@ -678,8 +715,8 @@ class ExtractTask extends AppShell {
/**
* Get the strings from the position forward
*
- * @param integer $position Actual position on tokens array
- * @param integer $target Number of strings to extract
+ * @param int &$position Actual position on tokens array
+ * @param int $target Number of strings to extract
* @return array Strings extracted
*/
protected function _getStrings(&$position, $target) {
@@ -728,22 +765,22 @@ class ExtractTask extends AppShell {
* Indicate an invalid marker on a processed file
*
* @param string $file File where invalid marker resides
- * @param integer $line Line number
+ * @param int $line Line number
* @param string $marker Marker found
- * @param integer $count Count
+ * @param int $count Count
* @return void
*/
protected function _markerError($file, $line, $marker, $count) {
- $this->out(__d('cake_console', "Invalid marker content in %s:%s\n* %s(", $file, $line, $marker));
+ $this->err(__d('cake_console', "Invalid marker content in %s:%s\n* %s(", $file, $line, $marker));
$count += 2;
$tokenCount = count($this->_tokens);
$parenthesis = 1;
while ((($tokenCount - $count) > 0) && $parenthesis) {
if (is_array($this->_tokens[$count])) {
- $this->out($this->_tokens[$count][1], false);
+ $this->err($this->_tokens[$count][1], false);
} else {
- $this->out($this->_tokens[$count], false);
+ $this->err($this->_tokens[$count], false);
if ($this->_tokens[$count] === '(') {
$parenthesis++;
}
@@ -754,7 +791,7 @@ class ExtractTask extends AppShell {
}
$count++;
}
- $this->out("\n", true);
+ $this->err("\n", true);
}
/**
@@ -774,26 +811,24 @@ class ExtractTask extends AppShell {
}
$pattern = '/' . implode('|', $exclude) . '/';
}
- foreach ($this->_paths as $path) {
- $Folder = new Folder($path);
+ foreach ($this->_paths as $i => $path) {
+ $this->_paths[$i] = realpath($path) . DS;
+ $Folder = new Folder($this->_paths[$i]);
$files = $Folder->findRecursive('.*\.(php|ctp|thtml|inc|tpl)', true);
if (!empty($pattern)) {
- foreach ($files as $i => $file) {
- if (preg_match($pattern, $file)) {
- unset($files[$i]);
- }
- }
+ $files = preg_grep($pattern, $files, PREG_GREP_INVERT);
$files = array_values($files);
}
$this->_files = array_merge($this->_files, $files);
}
+ $this->_files = array_unique($this->_files);
}
/**
* Returns whether this execution is meant to extract string only from directories in folder represented by the
* APP constant, i.e. this task is extracting strings from same application.
*
- * @return boolean
+ * @return bool
*/
protected function _isExtractingApp() {
return $this->_paths === array(APP);
@@ -803,7 +838,7 @@ class ExtractTask extends AppShell {
* Checks whether or not a given path is usable for writing.
*
* @param string $path Path to folder
- * @return boolean true if it exists and is writable, false otherwise
+ * @return bool true if it exists and is writable, false otherwise
*/
protected function _isPathUsable($path) {
return is_dir($path) && is_writable($path);
diff --git a/web/api/lib/Cake/Console/Command/Task/FixtureTask.php b/web/api/lib/Cake/Console/Command/Task/FixtureTask.php
index 0be6d36dd..1f578d083 100644
--- a/web/api/lib/Cake/Console/Command/Task/FixtureTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/FixtureTask.php
@@ -74,7 +74,7 @@ class FixtureTask extends BakeTask {
))->addOption('count', array(
'help' => __d('cake_console', 'When using generated data, the number of records to include in the fixture(s).'),
'short' => 'n',
- 'default' => 10
+ 'default' => 1
))->addOption('connection', array(
'help' => __d('cake_console', 'Which database configuration to use for baking.'),
'short' => 'c',
@@ -210,7 +210,7 @@ class FixtureTask extends BakeTask {
* @param string $model Name of model to bake.
* @param string $useTable Name of table to use.
* @param array $importOptions Options for public $import
- * @return string Baked fixture content
+ * @return string|null Baked fixture content, otherwise null.
*/
public function bake($model, $useTable = false, $importOptions = array()) {
App::uses('CakeSchema', 'Model');
@@ -242,8 +242,8 @@ class FixtureTask extends BakeTask {
$this->_Schema = new CakeSchema();
$data = $this->_Schema->read(array('models' => false, 'connection' => $this->connection));
if (!isset($data['tables'][$useTable])) {
- $this->error('Could not find your selected table ' . $useTable);
- return false;
+ $this->err("Warning: Could not find the '${useTable}' table for ${model}.");
+ return null;
}
$tableInfo = $data['tables'][$useTable];
@@ -316,7 +316,7 @@ class FixtureTask extends BakeTask {
* Generate String representation of Records
*
* @param array $tableInfo Table schema array
- * @param integer $recordCount
+ * @param int $recordCount The number of records to generate.
* @return array Array of records to use in the fixture.
*/
protected function _generateRecords($tableInfo, $recordCount = 1) {
@@ -340,7 +340,7 @@ class FixtureTask extends BakeTask {
isset($fieldInfo['length']) && $fieldInfo['length'] == 36
);
if ($isPrimaryUuid) {
- $insert = String::uuid();
+ $insert = CakeText::uuid();
} else {
$insert = "Lorem ipsum dolor sit amet";
if (!empty($fieldInfo['length'])) {
@@ -381,7 +381,7 @@ class FixtureTask extends BakeTask {
}
/**
- * Convert a $records array into a a string.
+ * Convert a $records array into a string.
*
* @param array $records Array of records to be converted to string
* @return string A string value of the $records array.
@@ -414,19 +414,26 @@ class FixtureTask extends BakeTask {
* @return array Array of records.
*/
protected function _getRecordsFromTable($modelName, $useTable = null) {
+ $modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection));
if ($this->interactive) {
$condition = null;
$prompt = __d('cake_console', "Please provide a SQL fragment to use as conditions\nExample: WHERE 1=1");
while (!$condition) {
$condition = $this->in($prompt, null, 'WHERE 1=1');
}
+
+ $recordsFound = $modelObject->find('count', array(
+ 'conditions' => $condition,
+ 'recursive' => -1,
+ ));
+
$prompt = __d('cake_console', "How many records do you want to import?");
- $recordCount = $this->in($prompt, null, 10);
+ $recordCount = $this->in($prompt, null, ($recordsFound < 10 ) ? $recordsFound : 10);
} else {
$condition = 'WHERE 1=1';
$recordCount = (isset($this->params['count']) ? $this->params['count'] : 10);
}
- $modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection));
+
$records = $modelObject->find('all', array(
'conditions' => $condition,
'recursive' => -1,
diff --git a/web/api/lib/Cake/Console/Command/Task/ModelTask.php b/web/api/lib/Cake/Console/Command/Task/ModelTask.php
index 128674b5b..2dc03a5c3 100644
--- a/web/api/lib/Cake/Console/Command/Task/ModelTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/ModelTask.php
@@ -161,8 +161,8 @@ class ModelTask extends BakeTask {
*
* @param array $options Array of options to use for the selections. indexes must start at 0
* @param string $prompt Prompt to use for options list.
- * @param integer $default The default option for the given prompt.
- * @return integer Result of user choice.
+ * @param int $default The default option for the given prompt.
+ * @return int Result of user choice.
*/
public function inOptions($options, $prompt = null, $default = null) {
$valid = false;
@@ -176,7 +176,7 @@ class ModelTask extends BakeTask {
$prompt = __d('cake_console', 'Make a selection from the choices above');
}
$choice = $this->in($prompt, null, $default);
- if (intval($choice) > 0 && intval($choice) <= $max) {
+ if ((int)$choice > 0 && (int)$choice <= $max) {
$valid = true;
}
}
@@ -186,7 +186,7 @@ class ModelTask extends BakeTask {
/**
* Handles interactive baking
*
- * @return boolean
+ * @return bool
*/
protected function _interactive() {
$this->hr();
@@ -342,7 +342,7 @@ class ModelTask extends BakeTask {
* Handles Generation and user interaction for creating validation.
*
* @param Model $model Model to have validations generated for.
- * @return array $validate Array of user selected validations.
+ * @return array validate Array of user selected validations.
*/
public function doValidation($model) {
if (!$model instanceof Model) {
@@ -383,6 +383,8 @@ class ModelTask extends BakeTask {
if (class_exists('Validation')) {
$options = get_class_methods('Validation');
}
+ $deprecatedOptions = array('notEmpty', 'between', 'ssn');
+ $options = array_diff($options, $deprecatedOptions);
sort($options);
$default = 1;
foreach ($options as $option) {
@@ -401,7 +403,7 @@ class ModelTask extends BakeTask {
*
* @param string $fieldName Name of field to be validated.
* @param array $metaData metadata for field
- * @param string $primaryKey
+ * @param string $primaryKey The primary key field.
* @return array Array of validation for the field.
*/
public function fieldValidation($fieldName, $metaData, $primaryKey = 'id') {
@@ -443,9 +445,9 @@ class ModelTask extends BakeTask {
} elseif ($metaData['type'] === 'string' && $metaData['length'] == 36) {
$guess = $methods['uuid'];
} elseif ($metaData['type'] === 'string') {
- $guess = $methods['notEmpty'];
+ $guess = $methods['notBlank'];
} elseif ($metaData['type'] === 'text') {
- $guess = $methods['notEmpty'];
+ $guess = $methods['notBlank'];
} elseif ($metaData['type'] === 'integer') {
$guess = $methods['numeric'];
} elseif ($metaData['type'] === 'float') {
@@ -460,6 +462,8 @@ class ModelTask extends BakeTask {
$guess = $methods['datetime'];
} elseif ($metaData['type'] === 'inet') {
$guess = $methods['ip'];
+ } elseif ($metaData['type'] === 'decimal') {
+ $guess = $methods['decimal'];
}
}
@@ -510,7 +514,7 @@ class ModelTask extends BakeTask {
/**
* Handles associations
*
- * @param Model $model
+ * @param Model $model The model object
* @return array Associations
*/
public function doAssociations($model) {
@@ -562,7 +566,7 @@ class ModelTask extends BakeTask {
/**
* Handles behaviors
*
- * @param Model $model
+ * @param Model $model The model object.
* @return array Behaviors
*/
public function doActsAs($model) {
@@ -632,13 +636,13 @@ class ModelTask extends BakeTask {
}
foreach ($tempFieldNames as $fieldName) {
$assoc = false;
- if ($fieldName != $model->primaryKey && $fieldName == $foreignKey) {
+ if ($fieldName !== $model->primaryKey && $fieldName === $foreignKey) {
$assoc = array(
'alias' => $tempOtherModel->name,
'className' => $tempOtherModel->name,
'foreignKey' => $fieldName
);
- } elseif ($otherTable == $model->table && $fieldName === 'parent_id') {
+ } elseif ($otherTable === $model->table && $fieldName === 'parent_id') {
$assoc = array(
'alias' => 'Child' . $model->name,
'className' => $model->name,
@@ -728,7 +732,7 @@ class ModelTask extends BakeTask {
while (strtolower($wannaDoMoreAssoc) === 'y') {
$assocs = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
$this->out(__d('cake_console', 'What is the association type?'));
- $assocType = intval($this->inOptions($assocs, __d('cake_console', 'Enter a number')));
+ $assocType = (int)$this->inOptions($assocs, __d('cake_console', 'Enter a number'));
$this->out(__d('cake_console', "For the following options be very careful to match your setup exactly.\n" .
"Any spelling mistakes will cause errors."));
@@ -765,7 +769,7 @@ class ModelTask extends BakeTask {
if (!empty($showKeys)) {
$this->out(__d('cake_console', 'A helpful List of possible keys'));
$foreignKey = $this->inOptions($showKeys, __d('cake_console', 'What is the foreignKey?'));
- $foreignKey = $showKeys[intval($foreignKey)];
+ $foreignKey = $showKeys[(int)$foreignKey];
}
if (!isset($foreignKey)) {
$foreignKey = $this->in(__d('cake_console', 'What is the foreignKey? Specify your own.'), null, $suggestedForeignKey);
@@ -812,7 +816,7 @@ class ModelTask extends BakeTask {
* Assembles and writes a Model file.
*
* @param string|object $name Model name or object
- * @param array|boolean $data if array and $name is not an object assume bake data, otherwise boolean.
+ * @param array|bool $data if array and $name is not an object assume bake data, otherwise boolean.
* @return string
*/
public function bake($name, $data = array()) {
@@ -926,7 +930,7 @@ class ModelTask extends BakeTask {
$tableIsGood = $this->in(__d('cake_console', 'Do you want to use this table?'), array('y', 'n'), 'y');
}
if (strtolower($tableIsGood) === 'n') {
- $useTable = $this->in(__d('cake_console', 'What is the name of the table?'));
+ $useTable = $this->in(__d('cake_console', 'What is the name of the table (without prefix)?'));
}
}
return $useTable;
@@ -985,14 +989,14 @@ class ModelTask extends BakeTask {
return $this->_stop();
}
- if (!$enteredModel || intval($enteredModel) > count($this->_modelNames)) {
+ if (!$enteredModel || (int)$enteredModel > count($this->_modelNames)) {
$this->err(__d('cake_console', "The model name you supplied was empty,\n" .
"or the number you selected was not an option. Please try again."));
$enteredModel = '';
}
}
- if (intval($enteredModel) > 0 && intval($enteredModel) <= count($this->_modelNames)) {
- return $this->_modelNames[intval($enteredModel) - 1];
+ if ((int)$enteredModel > 0 && (int)$enteredModel <= count($this->_modelNames)) {
+ return $this->_modelNames[(int)$enteredModel - 1];
}
return $enteredModel;
diff --git a/web/api/lib/Cake/Console/Command/Task/PluginTask.php b/web/api/lib/Cake/Console/Command/Task/PluginTask.php
index e37e437c3..7cd507942 100644
--- a/web/api/lib/Cake/Console/Command/Task/PluginTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/PluginTask.php
@@ -1,7 +1,5 @@
path . $plugin);
$directories = array(
'Config' . DS . 'Schema',
- 'Model' . DS . 'Behavior',
- 'Model' . DS . 'Datasource',
'Console' . DS . 'Command' . DS . 'Task',
+ 'Console' . DS . 'Templates',
'Controller' . DS . 'Component',
'Lib',
- 'View' . DS . 'Helper',
+ 'Locale' . DS . 'eng' . DS . 'LC_MESSAGES',
+ 'Model' . DS . 'Behavior',
+ 'Model' . DS . 'Datasource',
'Test' . DS . 'Case' . DS . 'Controller' . DS . 'Component',
- 'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper',
+ 'Test' . DS . 'Case' . DS . 'Lib',
'Test' . DS . 'Case' . DS . 'Model' . DS . 'Behavior',
+ 'Test' . DS . 'Case' . DS . 'Model' . DS . 'Datasource',
+ 'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper',
'Test' . DS . 'Fixture',
- 'Vendor',
- 'webroot'
+ 'View' . DS . 'Elements',
+ 'View' . DS . 'Helper',
+ 'View' . DS . 'Layouts',
+ 'webroot' . DS . 'css',
+ 'webroot' . DS . 'js',
+ 'webroot' . DS . 'img',
);
foreach ($directories as $directory) {
@@ -184,7 +189,7 @@ class PluginTask extends AppShell {
/**
* find and change $this->path to the user selection
*
- * @param array $pathOptions
+ * @param array $pathOptions The list of paths to look in.
* @return void
*/
public function findPath($pathOptions) {
@@ -203,7 +208,7 @@ class PluginTask extends AppShell {
}
$prompt = __d('cake_console', 'Choose a plugin path from the paths above.');
$choice = $this->in($prompt, null, 1);
- if (intval($choice) > 0 && intval($choice) <= $max) {
+ if ((int)$choice > 0 && (int)$choice <= $max) {
$valid = true;
}
}
diff --git a/web/api/lib/Cake/Console/Command/Task/ProjectTask.php b/web/api/lib/Cake/Console/Command/Task/ProjectTask.php
index c3225a99f..df1ab19db 100644
--- a/web/api/lib/Cake/Console/Command/Task/ProjectTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/ProjectTask.php
@@ -18,7 +18,7 @@
App::uses('AppShell', 'Console/Command');
App::uses('File', 'Utility');
App::uses('Folder', 'Utility');
-App::uses('String', 'Utility');
+App::uses('CakeText', 'Utility');
App::uses('Security', 'Utility');
/**
@@ -142,7 +142,7 @@ class ProjectTask extends AppShell {
/**
* Checks PHP's include_path for CakePHP.
*
- * @return boolean Indicates whether or not CakePHP exists on include_path
+ * @return bool Indicates whether or not CakePHP exists on include_path
*/
public function cakeOnIncludePath() {
$paths = explode(PATH_SEPARATOR, ini_get('include_path'));
@@ -212,7 +212,7 @@ class ProjectTask extends AppShell {
}
foreach ($Folder->messages() as $message) {
- $this->out(String::wrap(' * ' . $message), 1, Shell::VERBOSE);
+ $this->out(CakeText::wrap(' * ' . $message), 1, Shell::VERBOSE);
}
return true;
@@ -231,14 +231,14 @@ class ProjectTask extends AppShell {
* and points app/console/cake.php to the right place
*
* @param string $path Project path.
- * @return boolean success
+ * @return bool success
*/
public function consolePath($path) {
$File = new File($path . 'Console' . DS . 'cake.php');
$contents = $File->read();
if (preg_match('/(__CAKE_PATH__)/', $contents, $match)) {
- $root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " \$ds . '" : "'";
- $replacement = $root . str_replace(DS, "' . \$ds . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'";
+ $root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'";
+ $replacement = $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'";
$result = str_replace($match[0], $replacement, $contents);
if ($File->write($result)) {
return true;
@@ -252,7 +252,7 @@ class ProjectTask extends AppShell {
* Generates and writes 'Security.salt'
*
* @param string $path Project path
- * @return boolean Success
+ * @return bool Success
*/
public function securitySalt($path) {
$File = new File($path . 'Config' . DS . 'core.php');
@@ -272,7 +272,7 @@ class ProjectTask extends AppShell {
* Generates and writes 'Security.cipherSeed'
*
* @param string $path Project path
- * @return boolean Success
+ * @return bool Success
*/
public function securityCipherSeed($path) {
$File = new File($path . 'Config' . DS . 'core.php');
@@ -293,7 +293,7 @@ class ProjectTask extends AppShell {
* Writes cache prefix using app's name
*
* @param string $dir Path to project
- * @return boolean Success
+ * @return bool Success
*/
public function cachePrefix($dir) {
$app = basename($dir);
@@ -310,8 +310,8 @@ class ProjectTask extends AppShell {
* Generates and writes CAKE_CORE_INCLUDE_PATH
*
* @param string $path Project path
- * @param boolean $hardCode Whether or not define calls should be hardcoded.
- * @return boolean Success
+ * @param bool $hardCode Whether or not define calls should be hardcoded.
+ * @return bool Success
*/
public function corePath($path, $hardCode = true) {
if (dirname($path) !== CAKE_CORE_INCLUDE_PATH) {
@@ -331,8 +331,8 @@ class ProjectTask extends AppShell {
* Replaces the __CAKE_PATH__ placeholder in the template files.
*
* @param string $filename The filename to operate on.
- * @param boolean $hardCode Whether or not the define should be uncommented.
- * @return boolean Success
+ * @param bool $hardCode Whether or not the define should be uncommented.
+ * @return bool Success
*/
protected function _replaceCorePath($filename, $hardCode) {
$contents = file_get_contents($filename);
@@ -340,6 +340,11 @@ class ProjectTask extends AppShell {
$root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'";
$corePath = $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'";
+ $composer = ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib';
+ if (file_exists($composer)) {
+ $corePath = " ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib'";
+ }
+
$result = str_replace('__CAKE_PATH__', $corePath, $contents, $count);
if ($hardCode) {
$result = str_replace('//define(\'CAKE_CORE', 'define(\'CAKE_CORE', $result);
@@ -354,7 +359,7 @@ class ProjectTask extends AppShell {
* Enables Configure::read('Routing.prefixes') in /app/Config/core.php
*
* @param string $name Name to use as admin routing
- * @return boolean Success
+ * @return bool Success
*/
public function cakeAdmin($name) {
$path = (empty($this->configPath)) ? APP . 'Config' . DS : $this->configPath;
diff --git a/web/api/lib/Cake/Console/Command/Task/TestTask.php b/web/api/lib/Cake/Console/Command/Task/TestTask.php
index f85d57cd0..a147951c2 100644
--- a/web/api/lib/Cake/Console/Command/Task/TestTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/TestTask.php
@@ -102,8 +102,8 @@ class TestTask extends BakeTask {
/**
* Handles interactive baking
*
- * @param string $type
- * @return string|boolean
+ * @param string $type The type of object to bake a test for.
+ * @return string|bool
*/
protected function _interactive($type = null) {
$this->interactive = true;
@@ -129,7 +129,7 @@ class TestTask extends BakeTask {
*
* @param string $type Type of object to bake test case for ie. Model, Controller
* @param string $className the 'cake name' for the class ie. Posts for the PostsController
- * @return string|boolean
+ * @return string|bool
*/
public function bake($type, $className) {
$plugin = null;
@@ -242,7 +242,7 @@ class TestTask extends BakeTask {
* Currently only model, and controller are supported
*
* @param string $type The Type of object you are generating tests for eg. controller
- * @return boolean
+ * @return bool
*/
public function typeCanDetectFixtures($type) {
$type = strtolower($type);
@@ -254,7 +254,7 @@ class TestTask extends BakeTask {
*
* @param string $package The package of object you are generating tests for eg. controller
* @param string $class the Classname of the class the test is being generated for.
- * @return boolean
+ * @return bool
*/
public function isLoadableClass($package, $class) {
App::uses($class, $package);
@@ -302,7 +302,7 @@ class TestTask extends BakeTask {
$position = strpos($class, $type);
- if ($position !== false && strlen($class) - $position == strlen($type)) {
+ if ($position !== false && (strlen($class) - $position) === strlen($type)) {
return $class;
}
return $class . $type;
@@ -466,7 +466,7 @@ class TestTask extends BakeTask {
* Controllers require a mock class.
*
* @param string $type The type of object tests are being generated for eg. controller.
- * @return boolean
+ * @return bool
*/
public function hasMockClass($type) {
$type = strtolower($type);
diff --git a/web/api/lib/Cake/Console/Command/Task/ViewTask.php b/web/api/lib/Cake/Console/Command/Task/ViewTask.php
index 8fc387aba..06ecf0013 100644
--- a/web/api/lib/Cake/Console/Command/Task/ViewTask.php
+++ b/web/api/lib/Cake/Console/Command/Task/ViewTask.php
@@ -89,7 +89,7 @@ class ViewTask extends BakeTask {
$this->_interactive();
}
if (empty($this->args[0])) {
- return;
+ return null;
}
if (!isset($this->connection)) {
$this->connection = 'default';
@@ -151,7 +151,7 @@ class ViewTask extends BakeTask {
unset($methods[$i]);
}
}
- if ($method[0] === '_' || $method == strtolower($this->controllerName . 'Controller')) {
+ if ($method[0] === '_' || $method === strtolower($this->controllerName . 'Controller')) {
unset($methods[$i]);
}
}
@@ -206,7 +206,7 @@ class ViewTask extends BakeTask {
$this->Controller->connection = $this->connection;
$this->controllerName = $this->Controller->getName();
- $prompt = __d('cake_console', "Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite %s views if it exist.", $this->controllerName);
+ $prompt = __d('cake_console', "Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite %s views if they exist.", $this->controllerName);
$interactive = $this->in($prompt, array('y', 'n'), 'n');
if (strtolower($interactive) === 'n') {
@@ -248,7 +248,7 @@ class ViewTask extends BakeTask {
* 'singularHumanName', 'pluralHumanName', 'fields', 'foreignKeys',
* 'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'
*
- * @return array Returns an variables to be made available to a view template
+ * @return array Returns a variables to be made available to a view template
*/
protected function _loadController() {
if (!$this->controllerName) {
@@ -298,7 +298,7 @@ class ViewTask extends BakeTask {
* Bake a view file for each of the supplied actions
*
* @param array $actions Array of actions to make files for.
- * @param array $vars
+ * @param array $vars The template variables.
* @return void
*/
public function bakeActions($actions, $vars) {
@@ -342,7 +342,7 @@ class ViewTask extends BakeTask {
*
* @param string $action Action to bake
* @param string $content Content to write
- * @return boolean Success
+ * @return bool Success
*/
public function bake($action, $content = '') {
if ($content === true) {
@@ -454,8 +454,8 @@ class ViewTask extends BakeTask {
/**
* Returns associations for controllers models.
*
- * @param Model $model
- * @return array $associations
+ * @param Model $model The Model instance.
+ * @return array associations
*/
protected function _associations(Model $model) {
$keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
diff --git a/web/api/lib/Cake/Console/Command/TestShell.php b/web/api/lib/Cake/Console/Command/TestShell.php
index bd7e9d277..4dfacfdfc 100644
--- a/web/api/lib/Cake/Console/Command/TestShell.php
+++ b/web/api/lib/Cake/Console/Command/TestShell.php
@@ -179,11 +179,11 @@ class TestShell extends Shell {
/**
* Parse the CLI options into an array CakeTestDispatcher can use.
*
- * @return array Array of params for CakeTestDispatcher
+ * @return array|null Array of params for CakeTestDispatcher or null.
*/
protected function _parseArgs() {
if (empty($this->args)) {
- return;
+ return null;
}
$params = array(
'core' => false,
@@ -222,6 +222,7 @@ class TestShell extends Shell {
$options = array();
$params = $this->params;
unset($params['help']);
+ unset($params['quiet']);
if (!empty($params['no-colors'])) {
unset($params['no-colors'], $params['colors']);
@@ -334,9 +335,9 @@ class TestShell extends Shell {
/**
* Find the test case for the passed file. The file could itself be a test.
*
- * @param string $file
- * @param string $category
- * @param boolean $throwOnMissingFile
+ * @param string $file The file to map.
+ * @param string $category The test file category.
+ * @param bool $throwOnMissingFile Whether or not to throw an exception.
* @return array array(type, case)
* @throws Exception
*/
@@ -411,7 +412,7 @@ class TestShell extends Shell {
/**
* For the given file, what category of test is it? returns app, core or the name of the plugin
*
- * @param string $file
+ * @param string $file The file to map.
* @return string
*/
protected function _mapFileToCategory($file) {
diff --git a/web/api/lib/Cake/Console/Command/UpgradeShell.php b/web/api/lib/Cake/Console/Command/UpgradeShell.php
index 27d7561fe..12b3fbc9d 100644
--- a/web/api/lib/Cake/Console/Command/UpgradeShell.php
+++ b/web/api/lib/Cake/Console/Command/UpgradeShell.php
@@ -18,6 +18,7 @@
App::uses('AppShell', 'Console/Command');
App::uses('Folder', 'Utility');
+App::uses('CakePlugin', 'Core');
/**
* A shell class to help developers upgrade applications to CakePHP 2.0
@@ -102,7 +103,7 @@ class UpgradeShell extends AppShell {
public function tests() {
$this->_paths = array(APP . 'tests' . DS);
if (!empty($this->params['plugin'])) {
- $this->_paths = array(App::pluginPath($this->params['plugin']) . 'tests' . DS);
+ $this->_paths = array(CakePlugin::path($this->params['plugin']) . 'tests' . DS);
}
$patterns = array(
array(
@@ -128,7 +129,7 @@ class UpgradeShell extends AppShell {
$cwd = getcwd();
if (!empty($this->params['plugin'])) {
- chdir(App::pluginPath($this->params['plugin']));
+ chdir(CakePlugin::path($this->params['plugin']));
}
if (is_dir('plugins')) {
@@ -215,7 +216,7 @@ class UpgradeShell extends AppShell {
$this->_paths = array_diff(App::path('views'), App::core('views'));
if (!empty($this->params['plugin'])) {
- $this->_paths = array(App::pluginPath($this->params['plugin']) . 'views' . DS);
+ $this->_paths = array(CakePlugin::path($this->params['plugin']) . 'views' . DS);
}
$patterns = array();
@@ -229,7 +230,7 @@ class UpgradeShell extends AppShell {
CakePlugin::load($plugin);
$pluginHelpers = array_merge(
$pluginHelpers,
- App::objects('helper', App::pluginPath($plugin) . DS . 'views' . DS . 'helpers' . DS, false)
+ App::objects('helper', CakePlugin::path($plugin) . DS . 'views' . DS . 'helpers' . DS, false)
);
}
$helpers = array_merge($pluginHelpers, $helpers);
@@ -260,7 +261,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
- $this->_paths = array(App::pluginPath($this->params['plugin']));
+ $this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
@@ -299,7 +300,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
- $this->_paths = array(App::pluginPath($this->params['plugin']));
+ $this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
array(
@@ -354,7 +355,7 @@ class UpgradeShell extends AppShell {
$this->_paths = array_merge($views, $controllers, $components);
if (!empty($this->params['plugin'])) {
- $pluginPath = App::pluginPath($this->params['plugin']);
+ $pluginPath = CakePlugin::path($this->params['plugin']);
$this->_paths = array(
$pluginPath . 'controllers' . DS,
$pluginPath . 'controllers' . DS . 'components' . DS,
@@ -411,7 +412,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
- $this->_paths = array(App::pluginPath($this->params['plugin']));
+ $this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
array(
@@ -433,7 +434,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
- $this->_paths = array(App::pluginPath($this->params['plugin']));
+ $this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
array(
@@ -554,6 +555,7 @@ class UpgradeShell extends AppShell {
/**
* Replace cakeError with built-in exceptions.
* NOTE: this ignores calls where you've passed your own secondary parameters to cakeError().
+ *
* @return void
*/
public function exceptions() {
@@ -563,7 +565,7 @@ class UpgradeShell extends AppShell {
$this->_paths = array_merge($controllers, $components);
if (!empty($this->params['plugin'])) {
- $pluginPath = App::pluginPath($this->params['plugin']);
+ $pluginPath = CakePlugin::path($this->params['plugin']);
$this->_paths = array(
$pluginPath . 'controllers' . DS,
$pluginPath . 'controllers' . DS . 'components' . DS,
@@ -609,7 +611,7 @@ class UpgradeShell extends AppShell {
$new = 'View' . DS . Inflector::camelize($old);
$old = 'View' . DS . $old;
- if ($new == $old) {
+ if ($new === $old) {
continue;
}
@@ -661,7 +663,7 @@ class UpgradeShell extends AppShell {
* Find all php files in the folder (honoring recursive) and determine where CakePHP expects the file to be
* If the file is not exactly where CakePHP expects it - move it.
*
- * @param string $path
+ * @param string $path The path to move files in.
* @param array $options array(recursive, checkFolder)
* @return void
*/
@@ -763,7 +765,7 @@ class UpgradeShell extends AppShell {
/**
* Searches the paths and finds files based on extension.
*
- * @param string $extensions
+ * @param string $extensions The extensions to include. Defaults to none.
* @return void
*/
protected function _findFiles($extensions = '') {
@@ -839,8 +841,9 @@ class UpgradeShell extends AppShell {
);
$parser->description(
- __d('cake_console', "A shell to help automate upgrading from CakePHP 1.3 to 2.0. \n" .
- "Be sure to have a backup of your application before running these commands."
+ __d('cake_console', "A tool to help automate upgrading an application or plugin " .
+ "from CakePHP 1.3 to 2.0. Be sure to have a backup of your application before " .
+ "running these commands."
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Run all upgrade commands.'),
'parser' => $subcommandParser
diff --git a/web/api/lib/Cake/Console/ConsoleErrorHandler.php b/web/api/lib/Cake/Console/ConsoleErrorHandler.php
index aa5c464f9..7cbb2df15 100644
--- a/web/api/lib/Cake/Console/ConsoleErrorHandler.php
+++ b/web/api/lib/Cake/Console/ConsoleErrorHandler.php
@@ -40,35 +40,37 @@ class ConsoleErrorHandler {
* @return ConsoleOutput
*/
public static function getStderr() {
- if (empty(self::$stderr)) {
- self::$stderr = new ConsoleOutput('php://stderr');
+ if (empty(static::$stderr)) {
+ static::$stderr = new ConsoleOutput('php://stderr');
}
- return self::$stderr;
+ return static::$stderr;
}
/**
- * Handle a exception in the console environment. Prints a message to stderr.
+ * Handle an exception in the console environment. Prints a message to stderr.
*
- * @param Exception $exception The exception to handle
+ * @param Exception|ParserError $exception The exception to handle
* @return void
*/
- public function handleException(Exception $exception) {
- $stderr = self::getStderr();
+ public function handleException($exception) {
+ $stderr = static::getStderr();
$stderr->write(__d('cake_console', "Error: %s\n%s",
$exception->getMessage(),
$exception->getTraceAsString()
));
- return $this->_stop($exception->getCode() ? $exception->getCode() : 1);
+ $code = $exception->getCode();
+ $code = ($code && is_int($code)) ? $code : 1;
+ return $this->_stop($code);
}
/**
* Handle errors in the console environment. Writes errors to stderr,
* and logs messages if Configure::read('debug') is 0.
*
- * @param integer $code Error code
+ * @param int $code Error code
* @param string $description Description of the error.
* @param string $file The file the error occurred in.
- * @param integer $line The line the error occurred on.
+ * @param int $line The line the error occurred on.
* @param array $context The backtrace of the error.
* @return void
*/
@@ -76,7 +78,7 @@ class ConsoleErrorHandler {
if (error_reporting() === 0) {
return;
}
- $stderr = self::getStderr();
+ $stderr = static::getStderr();
list($name, $log) = ErrorHandler::mapErrorCode($code);
$message = __d('cake_console', '%s in [%s, line %s]', $description, $file, $line);
$stderr->write(__d('cake_console', "%s Error: %s\n", $name, $message));
@@ -93,7 +95,7 @@ class ConsoleErrorHandler {
/**
* Wrapper for exit(), used for testing.
*
- * @param integer $code The exit code.
+ * @param int $code The exit code.
* @return void
*/
protected function _stop($code = 0) {
diff --git a/web/api/lib/Cake/Console/ConsoleInput.php b/web/api/lib/Cake/Console/ConsoleInput.php
index e8af58bb0..551635b82 100644
--- a/web/api/lib/Cake/Console/ConsoleInput.php
+++ b/web/api/lib/Cake/Console/ConsoleInput.php
@@ -37,7 +37,7 @@ class ConsoleInput {
* 2. Handle we are attached to must be stdin.
* Allows rich editing with arrow keys and history when inputting a string.
*
- * @var boolean
+ * @var bool
*/
protected $_canReadline;
@@ -47,7 +47,7 @@ class ConsoleInput {
* @param string $handle The location of the stream to use as input.
*/
public function __construct($handle = 'php://stdin') {
- $this->_canReadline = extension_loaded('readline') && $handle == 'php://stdin' ? true : false;
+ $this->_canReadline = extension_loaded('readline') && $handle === 'php://stdin' ? true : false;
$this->_input = fopen($handle, 'r');
}
@@ -70,8 +70,8 @@ class ConsoleInput {
/**
* Checks if data is available on the stream
*
- * @param integer $timeout An optional time to wait for data
- * @return boolean True for data available, false otherwise
+ * @param int $timeout An optional time to wait for data
+ * @return bool True for data available, false otherwise
*/
public function dataAvailable($timeout = 0) {
$readFds = array($this->_input);
diff --git a/web/api/lib/Cake/Console/ConsoleInputArgument.php b/web/api/lib/Cake/Console/ConsoleInputArgument.php
index 7380893bf..08dbc21e9 100644
--- a/web/api/lib/Cake/Console/ConsoleInputArgument.php
+++ b/web/api/lib/Cake/Console/ConsoleInputArgument.php
@@ -41,7 +41,7 @@ class ConsoleInputArgument {
/**
* Is this option required?
*
- * @var boolean
+ * @var bool
*/
protected $_required;
@@ -57,7 +57,7 @@ class ConsoleInputArgument {
*
* @param string|array $name The long name of the option, or an array with all the properties.
* @param string $help The help text for this option
- * @param boolean $required Whether this argument is required. Missing required args will trigger exceptions
+ * @param bool $required Whether this argument is required. Missing required args will trigger exceptions
* @param array $choices Valid choices for this option.
*/
public function __construct($name, $help = '', $required = false, $choices = array()) {
@@ -85,7 +85,7 @@ class ConsoleInputArgument {
/**
* Generate the help for this argument.
*
- * @param integer $width The width to make the name of the option.
+ * @param int $width The width to make the name of the option.
* @return string
*/
public function help($width = 0) {
@@ -123,7 +123,7 @@ class ConsoleInputArgument {
/**
* Check if this argument is a required argument
*
- * @return boolean
+ * @return bool
*/
public function isRequired() {
return (bool)$this->_required;
@@ -132,8 +132,8 @@ class ConsoleInputArgument {
/**
* Check that $value is a valid choice for this argument.
*
- * @param string $value
- * @return boolean
+ * @param string $value The choice to validate.
+ * @return bool
* @throws ConsoleException
*/
public function validChoice($value) {
diff --git a/web/api/lib/Cake/Console/ConsoleInputOption.php b/web/api/lib/Cake/Console/ConsoleInputOption.php
index 4d68c9f9e..3a4b7a1c9 100644
--- a/web/api/lib/Cake/Console/ConsoleInputOption.php
+++ b/web/api/lib/Cake/Console/ConsoleInputOption.php
@@ -48,7 +48,7 @@ class ConsoleInputOption {
/**
* Is the option a boolean option. Boolean options do not consume a parameter.
*
- * @var boolean
+ * @var bool
*/
protected $_boolean;
@@ -72,7 +72,7 @@ class ConsoleInputOption {
* @param string|array $name The long name of the option, or an array with all the properties.
* @param string $short The short alias for this option
* @param string $help The help text for this option
- * @param boolean $boolean Whether this option is a boolean option. Boolean options don't consume extra tokens
+ * @param bool $boolean Whether this option is a boolean option. Boolean options don't consume extra tokens
* @param string $default The default value for this option.
* @param array $choices Valid choices for this option.
* @throws ConsoleException
@@ -118,7 +118,7 @@ class ConsoleInputOption {
/**
* Generate the help for this this option.
*
- * @param integer $width The width to make the name of the option.
+ * @param int $width The width to make the name of the option.
* @return string
*/
public function help($width = 0) {
@@ -168,7 +168,7 @@ class ConsoleInputOption {
/**
* Check if this option is a boolean option
*
- * @return boolean
+ * @return bool
*/
public function isBoolean() {
return (bool)$this->_boolean;
@@ -177,8 +177,8 @@ class ConsoleInputOption {
/**
* Check that a value is a valid choice for this option.
*
- * @param string $value
- * @return boolean
+ * @param string $value The choice to validate.
+ * @return bool
* @throws ConsoleException
*/
public function validChoice($value) {
diff --git a/web/api/lib/Cake/Console/ConsoleInputSubcommand.php b/web/api/lib/Cake/Console/ConsoleInputSubcommand.php
index 2ddcb955b..65c10db06 100644
--- a/web/api/lib/Cake/Console/ConsoleInputSubcommand.php
+++ b/web/api/lib/Cake/Console/ConsoleInputSubcommand.php
@@ -81,7 +81,7 @@ class ConsoleInputSubcommand {
/**
* Generate the help for this this subcommand.
*
- * @param integer $width The width to make the name of the subcommand.
+ * @param int $width The width to make the name of the subcommand.
* @return string
*/
public function help($width = 0) {
diff --git a/web/api/lib/Cake/Console/ConsoleOptionParser.php b/web/api/lib/Cake/Console/ConsoleOptionParser.php
index 589c27949..f54c5460d 100644
--- a/web/api/lib/Cake/Console/ConsoleOptionParser.php
+++ b/web/api/lib/Cake/Console/ConsoleOptionParser.php
@@ -136,7 +136,7 @@ class ConsoleOptionParser {
* Construct an OptionParser so you can define its behavior
*
* @param string $command The command name this parser is for. The command name is used for generating help.
- * @param boolean $defaultOptions Whether you want the verbose and quiet options set. Setting
+ * @param bool $defaultOptions Whether you want the verbose and quiet options set. Setting
* this to false will prevent the addition of `--verbose` & `--quiet` options.
*/
public function __construct($command = null, $defaultOptions = true) {
@@ -165,7 +165,7 @@ class ConsoleOptionParser {
* Static factory method for creating new OptionParsers so you can chain methods off of them.
*
* @param string $command The command name this parser is for. The command name is used for generating help.
- * @param boolean $defaultOptions Whether you want the verbose and quiet options set.
+ * @param bool $defaultOptions Whether you want the verbose and quiet options set.
* @return ConsoleOptionParser
*/
public static function create($command, $defaultOptions = true) {
@@ -175,7 +175,7 @@ class ConsoleOptionParser {
/**
* Build a parser from an array. Uses an array like
*
- * {{{
+ * ```
* $spec = array(
* 'description' => 'text',
* 'epilog' => 'text',
@@ -189,7 +189,7 @@ class ConsoleOptionParser {
* // list of subcommands to add.
* )
* );
- * }}}
+ * ```
*
* @param array $spec The spec to build the OptionParser with.
* @return ConsoleOptionParser
@@ -218,7 +218,7 @@ class ConsoleOptionParser {
* Get or set the command name for shell/task.
*
* @param string $text The text to set, or null if you want to read
- * @return mixed If reading, the value of the command. If setting $this will be returned
+ * @return string|self If reading, the value of the command. If setting $this will be returned.
*/
public function command($text = null) {
if ($text !== null) {
@@ -233,7 +233,7 @@ class ConsoleOptionParser {
*
* @param string|array $text The text to set, or null if you want to read. If an array the
* text will be imploded with "\n"
- * @return mixed If reading, the value of the description. If setting $this will be returned
+ * @return string|self If reading, the value of the description. If setting $this will be returned.
*/
public function description($text = null) {
if ($text !== null) {
@@ -251,7 +251,7 @@ class ConsoleOptionParser {
* the options and arguments listing when help is generated.
*
* @param string|array $text Text when setting or null when reading. If an array the text will be imploded with "\n"
- * @return mixed If reading, the value of the epilog. If setting $this will be returned.
+ * @return string|self If reading, the value of the epilog. If setting $this will be returned.
*/
public function epilog($text = null) {
if ($text !== null) {
@@ -284,7 +284,7 @@ class ConsoleOptionParser {
* @param ConsoleInputOption|string $name The long name you want to the value to be parsed out as when options are parsed.
* Will also accept an instance of ConsoleInputOption
* @param array $options An array of parameters that define the behavior of the option
- * @return ConsoleOptionParser $this.
+ * @return self
*/
public function addOption($name, $options = array()) {
if (is_object($name) && $name instanceof ConsoleInputOption) {
@@ -324,7 +324,7 @@ class ConsoleOptionParser {
*
* @param ConsoleInputArgument|string $name The name of the argument. Will also accept an instance of ConsoleInputArgument
* @param array $params Parameters for the argument, see above.
- * @return ConsoleOptionParser $this.
+ * @return self
*/
public function addArgument($name, $params = array()) {
if (is_object($name) && $name instanceof ConsoleInputArgument) {
@@ -354,7 +354,7 @@ class ConsoleOptionParser {
*
* @param array $args Array of arguments to add.
* @see ConsoleOptionParser::addArgument()
- * @return ConsoleOptionParser $this
+ * @return self
*/
public function addArguments(array $args) {
foreach ($args as $name => $params) {
@@ -369,7 +369,7 @@ class ConsoleOptionParser {
*
* @param array $options Array of options to add.
* @see ConsoleOptionParser::addOption()
- * @return ConsoleOptionParser $this
+ * @return self
*/
public function addOptions(array $options) {
foreach ($options as $name => $params) {
@@ -391,7 +391,7 @@ class ConsoleOptionParser {
*
* @param ConsoleInputSubcommand|string $name Name of the subcommand. Will also accept an instance of ConsoleInputSubcommand
* @param array $options Array of params, see above.
- * @return ConsoleOptionParser $this.
+ * @return self
*/
public function addSubcommand($name, $options = array()) {
if (is_object($name) && $name instanceof ConsoleInputSubcommand) {
@@ -410,11 +410,22 @@ class ConsoleOptionParser {
return $this;
}
+/**
+ * Remove a subcommand from the option parser.
+ *
+ * @param string $name The subcommand name to remove.
+ * @return self
+ */
+ public function removeSubcommand($name) {
+ unset($this->_subcommands[$name]);
+ return $this;
+ }
+
/**
* Add multiple subcommands at once.
*
* @param array $commands Array of subcommands.
- * @return ConsoleOptionParser $this
+ * @return self
*/
public function addSubcommands(array $commands) {
foreach ($commands as $name => $params) {
@@ -458,7 +469,7 @@ class ConsoleOptionParser {
* @param array $argv Array of args (argv) to parse.
* @param string $command The subcommand to use. If this parameter is a subcommand, that has a parser,
* That parser will be used to parse $argv instead.
- * @return Array array($params, $args)
+ * @return array array($params, $args)
* @throws ConsoleException When an invalid parameter is encountered.
*/
public function parse($argv, $command = null) {
@@ -506,12 +517,11 @@ class ConsoleOptionParser {
* @param string $subcommand If present and a valid subcommand that has a linked parser.
* That subcommands help will be shown instead.
* @param string $format Define the output format, can be text or xml
- * @param integer $width The width to format user content to. Defaults to 72
+ * @param int $width The width to format user content to. Defaults to 72
* @return string Generated help.
*/
public function help($subcommand = null, $format = 'text', $width = 72) {
- if (
- isset($this->_subcommands[$subcommand]) &&
+ if (isset($this->_subcommands[$subcommand]) &&
$this->_subcommands[$subcommand]->parser() instanceof self
) {
$subparser = $this->_subcommands[$subcommand]->parser();
@@ -597,13 +607,14 @@ class ConsoleOptionParser {
$params[$name] = $value;
return $params;
}
+ return array();
}
/**
* Check to see if $name has an option (short/long) defined for it.
*
* @param string $name The name of the option.
- * @return boolean
+ * @return bool
*/
protected function _optionExists($name) {
if (substr($name, 0, 2) === '--') {
diff --git a/web/api/lib/Cake/Console/ConsoleOutput.php b/web/api/lib/Cake/Console/ConsoleOutput.php
index fa021b565..ec6fb3941 100644
--- a/web/api/lib/Cake/Console/ConsoleOutput.php
+++ b/web/api/lib/Cake/Console/ConsoleOutput.php
@@ -47,21 +47,21 @@ class ConsoleOutput {
/**
* Raw output constant - no modification of output text.
*
- * @var integer
+ * @var int
*/
const RAW = 0;
/**
* Plain output - tags will be stripped.
*
- * @var integer
+ * @var int
*/
const PLAIN = 1;
/**
* Color output - Convert known tags in to ANSI color escape codes.
*
- * @var integer
+ * @var int
*/
const COLOR = 2;
@@ -79,10 +79,18 @@ class ConsoleOutput {
*/
protected $_output;
+/**
+ * The number of bytes last written to the output stream
+ * used when overwriting the previous message.
+ *
+ * @var int
+ */
+ protected $_lastWritten = 0;
+
/**
* The current output type. Manipulated with ConsoleOutput::outputAs();
*
- * @var integer
+ * @var int
*/
protected $_outputAs = self::COLOR;
@@ -153,16 +161,19 @@ class ConsoleOutput {
/**
* Construct the output object.
*
- * Checks for a pretty console environment. Ansicon allows pretty consoles
- * on windows, and is supported.
+ * Checks for a pretty console environment. Ansicon and ConEmu allows
+ * pretty consoles on Windows, and is supported.
*
* @param string $stream The identifier of the stream to write output to.
*/
public function __construct($stream = 'php://stdout') {
$this->_output = fopen($stream, 'w');
- if (DS === '\\' && !(bool)env('ANSICON')) {
- $this->_outputAs = self::PLAIN;
+ if ((DS === '\\' && !(bool)env('ANSICON') && env('ConEmuANSI') !== 'ON') ||
+ $stream === 'php://output' ||
+ (function_exists('posix_isatty') && !posix_isatty($this->_output))
+ ) {
+ $this->_outputAs = static::PLAIN;
}
}
@@ -170,15 +181,44 @@ class ConsoleOutput {
* Outputs a single or multiple messages to stdout. If no parameters
* are passed, outputs just a newline.
*
- * @param string|array $message A string or a an array of strings to output
- * @param integer $newlines Number of newlines to append
- * @return integer Returns the number of bytes returned from writing to stdout.
+ * @param string|array $message A string or an array of strings to output
+ * @param int $newlines Number of newlines to append
+ * @return int Returns the number of bytes returned from writing to stdout.
*/
public function write($message, $newlines = 1) {
if (is_array($message)) {
- $message = implode(self::LF, $message);
+ $message = implode(static::LF, $message);
+ }
+ return $this->_write($this->styleText($message . str_repeat(static::LF, $newlines)));
+ }
+
+/**
+ * Overwrite some already output text.
+ *
+ * Useful for building progress bars, or when you want to replace
+ * text already output to the screen with new text.
+ *
+ * **Warning** You cannot overwrite text that contains newlines.
+ *
+ * @param array|string $message The message to output.
+ * @param int $newlines Number of newlines to append.
+ * @param int|null $size The number of bytes to overwrite. Defaults to the
+ * length of the last message output.
+ * @return void
+ */
+ public function overwrite($message, $newlines = 1, $size = null) {
+ $size = $size ?: $this->_lastWritten;
+ // Output backspaces.
+ $this->write(str_repeat("\x08", $size), 0);
+ $newBytes = $this->write($message, 0);
+ // Fill any remaining bytes with spaces.
+ $fill = $size - $newBytes;
+ if ($fill > 0) {
+ $this->write(str_repeat(' ', $fill), 0);
+ }
+ if ($newlines) {
+ $this->write("", $newlines);
}
- return $this->_write($this->styleText($message . str_repeat(self::LF, $newlines)));
}
/**
@@ -188,11 +228,11 @@ class ConsoleOutput {
* @return string String with color codes added.
*/
public function styleText($text) {
- if ($this->_outputAs == self::RAW) {
+ if ($this->_outputAs == static::RAW) {
return $text;
}
- if ($this->_outputAs == self::PLAIN) {
- $tags = implode('|', array_keys(self::$_styles));
+ if ($this->_outputAs == static::PLAIN) {
+ $tags = implode('|', array_keys(static::$_styles));
return preg_replace('#?(?:' . $tags . ')>#', '', $text);
}
return preg_replace_callback(
@@ -203,7 +243,7 @@ class ConsoleOutput {
/**
* Replace tags with color codes.
*
- * @param array $matches.
+ * @param array $matches An array of matches to replace.
* @return string
*/
protected function _replaceTags($matches) {
@@ -213,16 +253,16 @@ class ConsoleOutput {
}
$styleInfo = array();
- if (!empty($style['text']) && isset(self::$_foregroundColors[$style['text']])) {
- $styleInfo[] = self::$_foregroundColors[$style['text']];
+ if (!empty($style['text']) && isset(static::$_foregroundColors[$style['text']])) {
+ $styleInfo[] = static::$_foregroundColors[$style['text']];
}
- if (!empty($style['background']) && isset(self::$_backgroundColors[$style['background']])) {
- $styleInfo[] = self::$_backgroundColors[$style['background']];
+ if (!empty($style['background']) && isset(static::$_backgroundColors[$style['background']])) {
+ $styleInfo[] = static::$_backgroundColors[$style['background']];
}
unset($style['text'], $style['background']);
foreach ($style as $option => $value) {
if ($value) {
- $styleInfo[] = self::$_options[$option];
+ $styleInfo[] = static::$_options[$option];
}
}
return "\033[" . implode($styleInfo, ';') . 'm' . $matches['text'] . "\033[0m";
@@ -232,10 +272,11 @@ class ConsoleOutput {
* Writes a message to the output stream.
*
* @param string $message Message to write.
- * @return boolean success
+ * @return bool success
*/
protected function _write($message) {
- return fwrite($this->_output, $message);
+ $this->_lastWritten = fwrite($this->_output, $message);
+ return $this->_lastWritten;
}
/**
@@ -265,23 +306,23 @@ class ConsoleOutput {
*/
public function styles($style = null, $definition = null) {
if ($style === null && $definition === null) {
- return self::$_styles;
+ return static::$_styles;
}
if (is_string($style) && $definition === null) {
- return isset(self::$_styles[$style]) ? self::$_styles[$style] : null;
+ return isset(static::$_styles[$style]) ? static::$_styles[$style] : null;
}
if ($definition === false) {
- unset(self::$_styles[$style]);
+ unset(static::$_styles[$style]);
return true;
}
- self::$_styles[$style] = $definition;
+ static::$_styles[$style] = $definition;
return true;
}
/**
* Get/Set the output type to use. The output type how formatting tags are treated.
*
- * @param integer $type The output type to use. Should be one of the class constants.
+ * @param int $type The output type to use. Should be one of the class constants.
* @return mixed Either null or the value if getting.
*/
public function outputAs($type = null) {
@@ -295,7 +336,9 @@ class ConsoleOutput {
* Clean up and close handles
*/
public function __destruct() {
- fclose($this->_output);
+ if (is_resource($this->_output)) {
+ fclose($this->_output);
+ }
}
}
diff --git a/web/api/lib/Cake/Console/HelpFormatter.php b/web/api/lib/Cake/Console/HelpFormatter.php
index c3b40c354..3a8fac98f 100644
--- a/web/api/lib/Cake/Console/HelpFormatter.php
+++ b/web/api/lib/Cake/Console/HelpFormatter.php
@@ -14,7 +14,7 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
-App::uses('String', 'Utility');
+App::uses('CakeText', 'Utility');
/**
* HelpFormatter formats help for console shells. Can format to either
@@ -33,19 +33,19 @@ class HelpFormatter {
/**
* The maximum number of arguments shown when generating usage.
*
- * @var integer
+ * @var int
*/
protected $_maxArgs = 6;
/**
* The maximum number of options shown when generating usage.
*
- * @var integer
+ * @var int
*/
protected $_maxOptions = 6;
/**
- * Build the help formatter for a an OptionParser
+ * Build the help formatter for an OptionParser
*
* @param ConsoleOptionParser $parser The option parser help is being generated for.
*/
@@ -56,7 +56,7 @@ class HelpFormatter {
/**
* Get the help as formatted text suitable for output on the command line.
*
- * @param integer $width The width of the help output.
+ * @param int $width The width of the help output.
* @return string
*/
public function text($width = 72) {
@@ -64,7 +64,7 @@ class HelpFormatter {
$out = array();
$description = $parser->description();
if (!empty($description)) {
- $out[] = String::wrap($description, $width);
+ $out[] = CakeText::wrap($description, $width);
$out[] = '';
}
$out[] = __d('cake_console', 'Usage:');
@@ -76,7 +76,7 @@ class HelpFormatter {
$out[] = '';
$max = $this->_getMaxLength($subcommands) + 2;
foreach ($subcommands as $command) {
- $out[] = String::wrap($command->help($max), array(
+ $out[] = CakeText::wrap($command->help($max), array(
'width' => $width,
'indent' => str_repeat(' ', $max),
'indentAt' => 1
@@ -93,7 +93,7 @@ class HelpFormatter {
$out[] = __d('cake_console', 'Options:');
$out[] = '';
foreach ($options as $option) {
- $out[] = String::wrap($option->help($max), array(
+ $out[] = CakeText::wrap($option->help($max), array(
'width' => $width,
'indent' => str_repeat(' ', $max),
'indentAt' => 1
@@ -108,7 +108,7 @@ class HelpFormatter {
$out[] = __d('cake_console', 'Arguments:');
$out[] = '';
foreach ($arguments as $argument) {
- $out[] = String::wrap($argument->help($max), array(
+ $out[] = CakeText::wrap($argument->help($max), array(
'width' => $width,
'indent' => str_repeat(' ', $max),
'indentAt' => 1
@@ -118,7 +118,7 @@ class HelpFormatter {
}
$epilog = $parser->epilog();
if (!empty($epilog)) {
- $out[] = String::wrap($epilog, $width);
+ $out[] = CakeText::wrap($epilog, $width);
$out[] = '';
}
return implode("\n", $out);
@@ -159,8 +159,8 @@ class HelpFormatter {
/**
* Iterate over a collection and find the longest named thing.
*
- * @param array $collection
- * @return integer
+ * @param array $collection The collection to find a max length of.
+ * @return int
*/
protected function _getMaxLength($collection) {
$max = 0;
@@ -173,7 +173,7 @@ class HelpFormatter {
/**
* Get the help as an xml string.
*
- * @param boolean $string Return the SimpleXml object or a string. Defaults to true.
+ * @param bool $string Return the SimpleXml object or a string. Defaults to true.
* @return string|SimpleXmlElement See $string
*/
public function xml($string = true) {
diff --git a/web/api/lib/Cake/Console/Helper/BaseShellHelper.php b/web/api/lib/Cake/Console/Helper/BaseShellHelper.php
new file mode 100644
index 000000000..f06a17aac
--- /dev/null
+++ b/web/api/lib/Cake/Console/Helper/BaseShellHelper.php
@@ -0,0 +1,82 @@
+_consoleOutput = $consoleOutput;
+ $this->config($config);
+ }
+
+/**
+ * Initialize config & store config values
+ *
+ * @param null $config Config values to set
+ * @return array|void
+ */
+ public function config($config = null) {
+ if ($config === null) {
+ return $this->_config;
+ }
+ if (!$this->_configInitialized) {
+ $this->_config = array_merge($this->_defaultConfig, $config);
+ $this->_configInitialized = true;
+ } else {
+ $this->_config = array_merge($this->_config, $config);
+ }
+ }
+
+/**
+ * This method should output content using `$this->_consoleOutput`.
+ *
+ * @param array $args The arguments for the helper.
+ * @return void
+ */
+ abstract public function output($args);
+}
\ No newline at end of file
diff --git a/web/api/lib/Cake/Console/Helper/ProgressShellHelper.php b/web/api/lib/Cake/Console/Helper/ProgressShellHelper.php
new file mode 100644
index 000000000..03b216963
--- /dev/null
+++ b/web/api/lib/Cake/Console/Helper/ProgressShellHelper.php
@@ -0,0 +1,122 @@
+ null);
+ if (isset($args[0])) {
+ $args['callback'] = $args[0];
+ }
+ if (!$args['callback'] || !is_callable($args['callback'])) {
+ throw new RuntimeException('Callback option must be a callable.');
+ }
+ $this->init($args);
+ $callback = $args['callback'];
+ while ($this->_progress < $this->_total) {
+ $callback($this);
+ $this->draw();
+ }
+ $this->_consoleOutput->write('');
+ }
+
+/**
+ * Initialize the progress bar for use.
+ *
+ * - `total` The total number of items in the progress bar. Defaults
+ * to 100.
+ * - `width` The width of the progress bar. Defaults to 80.
+ *
+ * @param array $args The initialization data.
+ * @return void
+ */
+ public function init(array $args = array()) {
+ $args += array('total' => 100, 'width' => 80);
+ $this->_progress = 0;
+ $this->_width = $args['width'];
+ $this->_total = $args['total'];
+ }
+
+/**
+ * Increment the progress bar.
+ *
+ * @param int $num The amount of progress to advance by.
+ * @return void
+ */
+ public function increment($num = 1) {
+ $this->_progress = min(max(0, $this->_progress + $num), $this->_total);
+ }
+
+/**
+ * Render the progress bar based on the current state.
+ *
+ * @return void
+ */
+ public function draw() {
+ $numberLen = strlen(' 100%');
+ $complete = round($this->_progress / $this->_total, 2);
+ $barLen = ($this->_width - $numberLen) * ($this->_progress / $this->_total);
+ $bar = '';
+ if ($barLen > 1) {
+ $bar = str_repeat('=', $barLen - 1) . '>';
+ }
+ $pad = ceil($this->_width - $numberLen - $barLen);
+ if ($pad > 0) {
+ $bar .= str_repeat(' ', $pad);
+ }
+ $percent = ($complete * 100) . '%';
+ $bar .= str_pad($percent, $numberLen, ' ', STR_PAD_LEFT);
+ $this->_consoleOutput->overwrite($bar, 0);
+ }
+}
\ No newline at end of file
diff --git a/web/api/lib/Cake/Console/Helper/TableShellHelper.php b/web/api/lib/Cake/Console/Helper/TableShellHelper.php
new file mode 100644
index 000000000..7cf6c799a
--- /dev/null
+++ b/web/api/lib/Cake/Console/Helper/TableShellHelper.php
@@ -0,0 +1,124 @@
+ true,
+ 'rowSeparator' => false,
+ 'headerStyle' => 'info',
+ );
+
+/**
+ * Calculate the column widths
+ *
+ * @param array $rows The rows on which the columns width will be calculated on.
+ * @return array
+ */
+ protected function _calculateWidths($rows) {
+ $widths = array();
+ foreach ($rows as $line) {
+ for ($i = 0, $len = count($line); $i < $len; $i++) {
+ $columnLength = mb_strlen($line[$i]);
+ if ($columnLength > (isset($widths[$i]) ? $widths[$i] : 0)) {
+ $widths[$i] = $columnLength;
+ }
+ }
+ }
+ return $widths;
+ }
+
+/**
+ * Output a row separator.
+ *
+ * @param array $widths The widths of each column to output.
+ * @return void
+ */
+ protected function _rowSeparator($widths) {
+ $out = '';
+ foreach ($widths as $column) {
+ $out .= '+' . str_repeat('-', $column + 2);
+ }
+ $out .= '+';
+ $this->_consoleOutput->write($out);
+ }
+
+/**
+ * Output a row.
+ *
+ * @param array $row The row to output.
+ * @param array $widths The widths of each column to output.
+ * @param array $options Options to be passed.
+ * @return void
+ */
+ protected function _render($row, $widths, $options = array()) {
+ $out = '';
+ foreach ($row as $i => $column) {
+ $pad = $widths[$i] - mb_strlen($column);
+ if (!empty($options['style'])) {
+ $column = $this->_addStyle($column, $options['style']);
+ }
+ $out .= '| ' . $column . str_repeat(' ', $pad) . ' ';
+ }
+ $out .= '|';
+ $this->_consoleOutput->write($out);
+ }
+
+/**
+ * Output a table.
+ *
+ * @param array $rows The data to render out.
+ * @return void
+ */
+ public function output($rows) {
+ $config = $this->config();
+ $widths = $this->_calculateWidths($rows);
+ $this->_rowSeparator($widths);
+ if ($config['headers'] === true) {
+ $this->_render(array_shift($rows), $widths, array('style' => $config['headerStyle']));
+ $this->_rowSeparator($widths);
+ }
+ foreach ($rows as $line) {
+ $this->_render($line, $widths);
+ if ($config['rowSeparator'] === true) {
+ $this->_rowSeparator($widths);
+ }
+ }
+ if ($config['rowSeparator'] !== true) {
+ $this->_rowSeparator($widths);
+ }
+ }
+
+/**
+ * Add style tags
+ *
+ * @param string $text The text to be surrounded
+ * @param string $style The style to be applied
+ * @return string
+ */
+ protected function _addStyle($text, $style) {
+ return '<' . $style . '>' . $text . '' . $style . '>';
+ }
+}
\ No newline at end of file
diff --git a/web/api/lib/Cake/Console/Shell.php b/web/api/lib/Cake/Console/Shell.php
index b6a6cbcf2..c446b9cd3 100644
--- a/web/api/lib/Cake/Console/Shell.php
+++ b/web/api/lib/Cake/Console/Shell.php
@@ -22,7 +22,6 @@ App::uses('ConsoleInputSubcommand', 'Console');
App::uses('ConsoleOptionParser', 'Console');
App::uses('ClassRegistry', 'Utility');
App::uses('File', 'Utility');
-App::uses('ClassRegistry', 'Utility');
/**
* Base class for command-line utilities for automating programmer chores.
@@ -31,24 +30,31 @@ App::uses('ClassRegistry', 'Utility');
*/
class Shell extends Object {
+/**
+ * Default error code
+ *
+ * @var int
+ */
+ const CODE_ERROR = 1;
+
/**
* Output constant making verbose shells.
*
- * @var integer
+ * @var int
*/
const VERBOSE = 2;
/**
* Output constant for making normal shells.
*
- * @var integer
+ * @var int
*/
const NORMAL = 1;
/**
* Output constants for making quiet shells.
*
- * @var integer
+ * @var int
*/
const QUIET = 0;
@@ -62,7 +68,7 @@ class Shell extends Object {
/**
* If true, the script will ask for permission to perform actions.
*
- * @var boolean
+ * @var bool
*/
public $interactive = true;
@@ -167,6 +173,21 @@ class Shell extends Object {
*/
public $stdin;
+/**
+ * The number of bytes last written to the output stream
+ * used when overwriting the previous message.
+ *
+ * @var int
+ */
+ protected $_lastWritten = 0;
+
+/**
+ * Contains helpers which have been previously instantiated
+ *
+ * @var array
+ */
+ protected $_helpers = array();
+
/**
* Constructs this Shell instance.
*
@@ -239,7 +260,7 @@ class Shell extends Object {
/**
* If $uses is an array load each of the models in the array
*
- * @return boolean
+ * @return bool
*/
protected function _loadModels() {
if (is_array($this->uses)) {
@@ -254,7 +275,7 @@ class Shell extends Object {
/**
* Lazy loads models using the loadModel() method if declared in $uses
*
- * @param string $name
+ * @param string $name The name of the model to look for.
* @return void
*/
public function __isset($name) {
@@ -303,7 +324,7 @@ class Shell extends Object {
/**
* Loads tasks defined in public $tasks
*
- * @return boolean
+ * @return bool
*/
public function loadTasks() {
if ($this->tasks === true || empty($this->tasks) || empty($this->Tasks)) {
@@ -318,7 +339,7 @@ class Shell extends Object {
* Check to see if this shell has a task with the provided name.
*
* @param string $task The task name to check.
- * @return boolean Success
+ * @return bool Success
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hasTask
*/
public function hasTask($task) {
@@ -329,7 +350,7 @@ class Shell extends Object {
* Check to see if this shell has a callable method by the given name.
*
* @param string $name The method name to check.
- * @return boolean
+ * @return bool
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hasMethod
*/
public function hasMethod($name) {
@@ -446,7 +467,7 @@ class Shell extends Object {
/**
* Display the help in the correct format
*
- * @param string $command
+ * @param string $command The command to get help for.
* @return void
*/
protected function _displayHelp($command) {
@@ -477,7 +498,7 @@ class Shell extends Object {
/**
* Overload get for lazy building of tasks
*
- * @param string $name
+ * @param string $name The property name to access.
* @return Shell Object of Task
*/
public function __get($name) {
@@ -492,6 +513,19 @@ class Shell extends Object {
return $this->{$name};
}
+/**
+ * Safely access the values in $this->params.
+ *
+ * @param string $name The name of the parameter to get.
+ * @return string|bool|null Value. Will return null if it doesn't exist.
+ */
+ public function param($name) {
+ if (!isset($this->params[$name])) {
+ return null;
+ }
+ return $this->params[$name];
+ }
+
/**
* Prompts the user for input, and returns it.
*
@@ -553,7 +587,8 @@ class Shell extends Object {
$result = $this->stdin->read();
if ($result === false) {
- return $this->_stop(1);
+ $this->_stop(self::CODE_ERROR);
+ return self::CODE_ERROR;
}
$result = trim($result);
@@ -574,13 +609,13 @@ class Shell extends Object {
* - `indent` Indent the text with the string provided. Defaults to null.
*
* @param string $text Text the text to format.
- * @param string|integer|array $options Array of options to use, or an integer to wrap the text to.
+ * @param string|int|array $options Array of options to use, or an integer to wrap the text to.
* @return string Wrapped / indented text
- * @see String::wrap()
+ * @see CakeText::wrap()
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::wrapText
*/
public function wrapText($text, $options = array()) {
- return String::wrap($text, $options);
+ return CakeText::wrap($text, $options);
}
/**
@@ -594,10 +629,10 @@ class Shell extends Object {
* present in most shells. Using Shell::QUIET for a message means it will always display.
* While using Shell::VERBOSE means it will only display when verbose output is toggled.
*
- * @param string|array $message A string or a an array of strings to output
- * @param integer $newlines Number of newlines to append
- * @param integer $level The message's output level, see above.
- * @return integer|boolean Returns the number of bytes returned from writing to stdout.
+ * @param string|array $message A string or an array of strings to output
+ * @param int $newlines Number of newlines to append
+ * @param int $level The message's output level, see above.
+ * @return int|bool Returns the number of bytes returned from writing to stdout.
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::out
*/
public function out($message = null, $newlines = 1, $level = Shell::NORMAL) {
@@ -609,17 +644,49 @@ class Shell extends Object {
$currentLevel = Shell::QUIET;
}
if ($level <= $currentLevel) {
- return $this->stdout->write($message, $newlines);
+ $this->_lastWritten = $this->stdout->write($message, $newlines);
+ return $this->_lastWritten;
}
return true;
}
+/**
+ * Overwrite some already output text.
+ *
+ * Useful for building progress bars, or when you want to replace
+ * text already output to the screen with new text.
+ *
+ * **Warning** You cannot overwrite text that contains newlines.
+ *
+ * @param array|string $message The message to output.
+ * @param int $newlines Number of newlines to append.
+ * @param int $size The number of bytes to overwrite. Defaults to the length of the last message output.
+ * @return int|bool Returns the number of bytes returned from writing to stdout.
+ */
+ public function overwrite($message, $newlines = 1, $size = null) {
+ $size = $size ? $size : $this->_lastWritten;
+
+ // Output backspaces.
+ $this->out(str_repeat("\x08", $size), 0);
+
+ $newBytes = $this->out($message, 0);
+
+ // Fill any remaining bytes with spaces.
+ $fill = $size - $newBytes;
+ if ($fill > 0) {
+ $this->out(str_repeat(' ', $fill), 0);
+ }
+ if ($newlines) {
+ $this->out($this->nl($newlines), 0);
+ }
+ }
+
/**
* Outputs a single or multiple error messages to stderr. If no parameters
* are passed outputs just a newline.
*
- * @param string|array $message A string or a an array of strings to output
- * @param integer $newlines Number of newlines to append
+ * @param string|array $message A string or an array of strings to output
+ * @param int $newlines Number of newlines to append
* @return void
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::err
*/
@@ -630,7 +697,7 @@ class Shell extends Object {
/**
* Returns a single or multiple linefeeds sequences.
*
- * @param integer $multiplier Number of times the linefeed sequence should be repeated
+ * @param int $multiplier Number of times the linefeed sequence should be repeated
* @return string
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::nl
*/
@@ -641,8 +708,8 @@ class Shell extends Object {
/**
* Outputs a series of minus characters to the standard output, acts as a visual separator.
*
- * @param integer $newlines Number of newlines to pre- and append
- * @param integer $width Width of the line, defaults to 63
+ * @param int $newlines Number of newlines to pre- and append
+ * @param int $width Width of the line, defaults to 63
* @return void
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hr
*/
@@ -667,7 +734,8 @@ class Shell extends Object {
if (!empty($message)) {
$this->err($message);
}
- return $this->_stop(1);
+ $this->_stop(self::CODE_ERROR);
+ return self::CODE_ERROR;
}
/**
@@ -691,7 +759,7 @@ class Shell extends Object {
*
* @param string $path Where to put the file.
* @param string $contents Content to put in the file.
- * @return boolean Success
+ * @return bool Success
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::createFile
*/
public function createFile($path, $contents) {
@@ -705,7 +773,8 @@ class Shell extends Object {
if (strtolower($key) === 'q') {
$this->out(__d('cake_console', 'Quitting.'), 2);
- return $this->_stop();
+ $this->_stop();
+ return true;
} elseif (strtolower($key) !== 'y') {
$this->out(__d('cake_console', 'Skip `%s`', $path), 2);
return false;
@@ -726,10 +795,32 @@ class Shell extends Object {
return false;
}
+/**
+ * Load given shell helper class
+ *
+ * @param string $name Name of the helper class. Supports plugin syntax.
+ * @return BaseShellHelper Instance of helper class
+ * @throws RuntimeException If invalid class name is provided
+ */
+ public function helper($name) {
+ if (isset($this->_helpers[$name])) {
+ return $this->_helpers[$name];
+ }
+ list($plugin, $helperClassName) = pluginSplit($name, true);
+ $helperClassName = Inflector::camelize($name) . "ShellHelper";
+ App::uses($helperClassName, $plugin . "Console/Helper");
+ if (!class_exists($helperClassName)) {
+ throw new RuntimeException("Class " . $helperClassName . " not found");
+ }
+ $helper = new $helperClassName($this->stdout);
+ $this->_helpers[$name] = $helper;
+ return $helper;
+ }
+
/**
* Action to create a Unit Test
*
- * @return boolean Success
+ * @return bool Success
*/
protected function _checkUnitTest() {
if (class_exists('PHPUnit_Framework_TestCase')) {
@@ -819,8 +910,8 @@ class Shell extends Object {
/**
* creates the singular name for use in views.
*
- * @param string $name
- * @return string $name
+ * @param string $name The plural underscored value.
+ * @return string name
*/
protected function _singularName($name) {
return Inflector::variable(Inflector::singularize($name));
@@ -860,7 +951,7 @@ class Shell extends Object {
* Find the correct path for a plugin. Scans $pluginPaths for the plugin you want.
*
* @param string $pluginName Name of the plugin you want ie. DebugKit
- * @return string $path path to the correct plugin.
+ * @return string path path to the correct plugin.
*/
protected function _pluginPath($pluginName) {
if (CakePlugin::loaded($pluginName)) {
@@ -874,7 +965,7 @@ class Shell extends Object {
* If you don't wish to see in your stdout or stderr everything that is logged
* through CakeLog, call this function with first param as false
*
- * @param boolean $enable whether to enable CakeLog output or not
+ * @param bool $enable whether to enable CakeLog output or not
* @return void
*/
protected function _useLogger($enable = true) {
diff --git a/web/api/lib/Cake/Console/ShellDispatcher.php b/web/api/lib/Cake/Console/ShellDispatcher.php
index b284fcbe9..d53851127 100644
--- a/web/api/lib/Cake/Console/ShellDispatcher.php
+++ b/web/api/lib/Cake/Console/ShellDispatcher.php
@@ -43,7 +43,7 @@ class ShellDispatcher {
* a status code of either 0 or 1 according to the result of the dispatch.
*
* @param array $args the argv from PHP
- * @param boolean $bootstrap Should the environment be bootstrapped.
+ * @param bool $bootstrap Should the environment be bootstrapped.
*/
public function __construct($args = array(), $bootstrap = true) {
set_time_limit(0);
@@ -79,9 +79,11 @@ class ShellDispatcher {
}
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
- define('DS', DIRECTORY_SEPARATOR);
define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(__FILE__))));
define('CAKEPHP_SHELL', true);
+ if (!defined('DS')) {
+ define('DS', DIRECTORY_SEPARATOR);
+ }
if (!defined('CORE_PATH')) {
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
@@ -114,7 +116,7 @@ class ShellDispatcher {
/**
* Initializes the environment and loads the CakePHP core.
*
- * @return boolean Success.
+ * @return bool Success.
*/
protected function _bootstrap() {
if (!defined('ROOT')) {
@@ -175,12 +177,15 @@ class ShellDispatcher {
}
set_exception_handler($exception['consoleHandler']);
set_error_handler($error['consoleHandler'], Configure::read('Error.level'));
+
+ App::uses('Debugger', 'Utility');
+ Debugger::getInstance()->output('txt');
}
/**
* Dispatches a CLI request
*
- * @return boolean
+ * @return bool
* @throws MissingShellMethodException
*/
public function dispatch() {
@@ -244,6 +249,11 @@ class ShellDispatcher {
App::uses('AppShell', 'Console/Command');
App::uses($class, $plugin . 'Console/Command');
+ if (!class_exists($class)) {
+ $plugin = Inflector::camelize($shell) . '.';
+ App::uses($class, $plugin . 'Console/Command');
+ }
+
if (!class_exists($class)) {
throw new MissingShellException(array(
'class' => $class
@@ -317,12 +327,13 @@ class ShellDispatcher {
/**
* Parses out the paths from from the argv
*
- * @param array $args
+ * @param array $args The argv to parse.
* @return void
*/
protected function _parsePaths($args) {
$parsed = array();
$keys = array('-working', '--working', '-app', '--app', '-root', '--root');
+ $args = (array)$args;
foreach ($keys as $key) {
while (($index = array_search($key, $args)) !== false) {
$keyname = str_replace('-', '', $key);
@@ -357,7 +368,7 @@ class ShellDispatcher {
/**
* Stop execution of the current script
*
- * @param integer|string $status see http://php.net/exit for values
+ * @param int|string $status see http://php.net/exit for values
* @return void
*/
protected function _stop($status = 0) {
diff --git a/web/api/lib/Cake/Console/TaskCollection.php b/web/api/lib/Cake/Console/TaskCollection.php
index ff1ddee67..3fafddd13 100644
--- a/web/api/lib/Cake/Console/TaskCollection.php
+++ b/web/api/lib/Cake/Console/TaskCollection.php
@@ -43,7 +43,7 @@ class TaskCollection extends ObjectCollection {
/**
* Constructor
*
- * @param Shell $Shell
+ * @param Shell $Shell The shell this task collection is attached to.
*/
public function __construct(Shell $Shell) {
$this->_Shell = $Shell;
@@ -53,13 +53,13 @@ class TaskCollection extends ObjectCollection {
* Loads/constructs a task. Will return the instance in the registry if it already exists.
*
* You can alias your task as an existing task by setting the 'className' key, i.e.,
- * {{{
+ * ```
* public $tasks = array(
* 'DbConfig' => array(
* 'className' => 'Bakeplus.DbConfigure'
* );
* );
- * }}}
+ * ```
* All calls to the `DbConfig` task would use `DbConfigure` found in the `Bakeplus` plugin instead.
*
* @param string $task Task name to load
diff --git a/web/api/lib/Cake/Console/Templates/default/actions/controller_actions.ctp b/web/api/lib/Cake/Console/Templates/default/actions/controller_actions.ctp
index b6b89a993..dfc309215 100644
--- a/web/api/lib/Cake/Console/Templates/default/actions/controller_actions.ctp
+++ b/web/api/lib/Cake/Console/Templates/default/actions/controller_actions.ctp
@@ -53,10 +53,10 @@
$this->->create();
if ($this->->save($this->request->data)) {
- $this->Session->setFlash(__('The has been saved.'));
+ $this->Flash->success(__('The has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
- $this->Session->setFlash(__('The could not be saved. Please, try again.'));
+ $this->Flash->error(__('The could not be saved. Please, try again.'));
return $this->flash(__('The has been saved.'), array('action' => 'index'));
@@ -94,10 +94,10 @@
if ($this->request->is(array('post', 'put'))) {
if ($this->->save($this->request->data)) {
- $this->Session->setFlash(__('The has been saved.'));
+ $this->Flash->success(__('The has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
- $this->Session->setFlash(__('The could not be saved. Please, try again.'));
+ $this->Flash->error(__('The could not be saved. Please, try again.'));
return $this->flash(__('The has been saved.'), array('action' => 'index'));
@@ -138,9 +138,9 @@
$this->request->allowMethod('post', 'delete');
if ($this->->delete()) {
- $this->Session->setFlash(__('The has been deleted.'));
+ $this->Flash->success(__('The has been deleted.'));
} else {
- $this->Session->setFlash(__('The could not be deleted. Please, try again.'));
+ $this->Flash->error(__('The could not be deleted. Please, try again.'));
}
return $this->redirect(array('action' => 'index'));
diff --git a/web/api/lib/Cake/Console/Templates/default/classes/controller.ctp b/web/api/lib/Cake/Console/Templates/default/classes/controller.ctp
index e290a8675..6beb4b401 100644
--- a/web/api/lib/Cake/Console/Templates/default/classes/controller.ctp
+++ b/web/api/lib/Cake/Console/Templates/default/classes/controller.ctp
@@ -23,10 +23,10 @@ echo "App::uses('{$plugin}AppController', '{$pluginPath}Controller');\n";
?>
/**
* Controller
- *
Controller extends App
echo ");\n\n";
endif;
- echo trim($actions);
+ if (!empty($actions)) {
+ echo trim($actions) . "\n";
+ }
endif; ?>
}
diff --git a/web/api/lib/Cake/Console/Templates/default/classes/fixture.ctp b/web/api/lib/Cake/Console/Templates/default/classes/fixture.ctp
index 0fb23e24f..7ac2c3987 100644
--- a/web/api/lib/Cake/Console/Templates/default/classes/fixture.ctp
+++ b/web/api/lib/Cake/Console/Templates/default/classes/fixture.ctp
@@ -21,8 +21,7 @@
echo "
/**
- * Fixture
- *
+ * Fixture
*/
class Fixture extends CakeTestFixture {
diff --git a/web/api/lib/Cake/Console/Templates/default/classes/model.ctp b/web/api/lib/Cake/Console/Templates/default/classes/model.ctp
index 0014e004e..6c3e64763 100644
--- a/web/api/lib/Cake/Console/Templates/default/classes/model.ctp
+++ b/web/api/lib/Cake/Console/Templates/default/classes/model.ctp
@@ -106,7 +106,7 @@ foreach ($associations as $assoc):
if (!empty($assoc)):
?>
- //The Associations below have been created with all possible keys, those that are not needed can be removed
+ // The Associations below have been created with all possible keys, those that are not needed can be removed
', '');
/**
* Test Case
- *
*/
class Test extends ControllerTestCase {
diff --git a/web/api/lib/Cake/Console/Templates/default/views/form.ctp b/web/api/lib/Cake/Console/Templates/default/views/form.ctp
index fa9c58315..4a21aabe3 100644
--- a/web/api/lib/Cake/Console/Templates/default/views/form.ctp
+++ b/web/api/lib/Cake/Console/Templates/default/views/form.ctp
@@ -1,7 +1,5 @@
Form->input('{$field}');\n";
@@ -46,7 +44,7 @@
-
Form->postLink(__('Delete'), array('action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')), null, __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}'))); ?>"; ?>
+
Form->postLink(__('Delete'), array('action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')), array('confirm' => __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}')))); ?>"; ?>
\n";
echo "\t\t\tHtml->link(__('View'), array('action' => 'view', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
echo "\t\t\tHtml->link(__('Edit'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
- echo "\t\t\tForm->postLink(__('Delete'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array(), __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
+ echo "\t\t\tForm->postLink(__('Delete'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}']))); ?>\n";
echo "\t\t
\n";
echo "\t
\n";
echo "\n";
?>
+
Paginator->counter(array(
- 'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
+ 'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
));
?>"; ?>
diff --git a/web/api/lib/Cake/View/ThemeView.php b/web/api/lib/Cake/View/ThemeView.php
index 8b36429fe..8e201a4f1 100644
--- a/web/api/lib/Cake/View/ThemeView.php
+++ b/web/api/lib/Cake/View/ThemeView.php
@@ -24,7 +24,7 @@ App::uses('View', 'View');
* Stub class for 2.1 Compatibility
*
* @package Cake.View
- * @deprecated Deprecated since 2.1, use View class instead
+ * @deprecated 3.0.0 Deprecated since 2.1, use View class instead
*/
class ThemeView extends View {
diff --git a/web/api/lib/Cake/View/View.php b/web/api/lib/Cake/View/View.php
index 6ccefbe72..f68db4e22 100644
--- a/web/api/lib/Cake/View/View.php
+++ b/web/api/lib/Cake/View/View.php
@@ -80,7 +80,7 @@ class View extends Object {
/**
* Name of the controller.
*
- * @var string Name of controller
+ * @var string
*/
public $name = null;
@@ -94,14 +94,14 @@ class View extends Object {
/**
* An array of names of built-in helpers to include.
*
- * @var mixed A single name as a string or a list of names as an array.
+ * @var mixed
*/
public $helpers = array();
/**
* Path to View.
*
- * @var string Path to View
+ * @var string
*/
public $viewPath = null;
@@ -129,7 +129,7 @@ class View extends Object {
/**
* Path to Layout.
*
- * @var string Path to Layout
+ * @var string
*/
public $layoutPath = null;
@@ -137,7 +137,7 @@ class View extends Object {
* Turns on or off CakePHP's conventional mode of applying layout files. On by default.
* Setting to off means that layouts will not be automatically applied to rendered views.
*
- * @var boolean
+ * @var bool
*/
public $autoLayout = true;
@@ -181,7 +181,7 @@ class View extends Object {
/**
* True when the view has been rendered.
*
- * @var boolean
+ * @var bool
*/
public $hasRendered = false;
@@ -251,6 +251,13 @@ class View extends Object {
*/
protected $_paths = array();
+/**
+ * Holds an array of plugin paths.
+ *
+ * @var array
+ */
+ protected $_pathsForPlugin = array();
+
/**
* The names of views and their parents used with View::extend();
*
@@ -293,7 +300,7 @@ class View extends Object {
/**
* Whether the event manager was already configured for this object
*
- * @var boolean
+ * @var bool
*/
protected $_eventManagerConfigured = false;
@@ -381,13 +388,12 @@ class View extends Object {
* If an array, the following keys can be used:
* - `config` - Used to store the cached element in a custom cache configuration.
* - `key` - Used to define the key used in the Cache::write(). It will be prefixed with `element_`
- * - `plugin` - Load an element from a specific plugin. This option is deprecated, see below.
+ * - `plugin` - (deprecated!) Load an element from a specific plugin. This option is deprecated, and
+ * will be removed in CakePHP 3.0. Use `Plugin.element_name` instead.
* - `callbacks` - Set to true to fire beforeRender and afterRender helper callbacks for this element.
* Defaults to false.
* - `ignoreMissing` - Used to allow missing elements. Set to true to not trigger notices.
* @return string Rendered Element
- * @deprecated The `$options['plugin']` is deprecated and will be removed in CakePHP 3.0. Use
- * `Plugin.element_name` instead.
*/
public function element($name, $data = array(), $options = array()) {
$file = $plugin = null;
@@ -426,7 +432,7 @@ class View extends Object {
* @param string $name Name of template file in the /app/View/Elements/ folder,
* or `MyPlugin.template` to check the template element from MyPlugin. If the element
* is not found in the plugin, the normal view path cascade will be searched.
- * @return boolean Success
+ * @return bool Success
*/
public function elementExists($name) {
return (bool)$this->_getElementFilename($name);
@@ -452,15 +458,17 @@ class View extends Object {
* @param string $view Name of view file to use
* @param string $layout Layout to use.
* @return string|null Rendered content or null if content already rendered and returned earlier.
+ * @triggers View.beforeRender $this, array($viewFileName)
+ * @triggers View.afterRender $this, array($viewFileName)
* @throws CakeException If there is an error in the view.
*/
public function render($view = null, $layout = null) {
if ($this->hasRendered) {
- return;
+ return null;
}
if ($view !== false && $viewFileName = $this->_getViewFileName($view)) {
- $this->_currentType = self::TYPE_VIEW;
+ $this->_currentType = static::TYPE_VIEW;
$this->getEventManager()->dispatch(new CakeEvent('View.beforeRender', $this, array($viewFileName)));
$this->Blocks->set('content', $this->_render($viewFileName));
$this->getEventManager()->dispatch(new CakeEvent('View.afterRender', $this, array($viewFileName)));
@@ -498,6 +506,8 @@ class View extends Object {
* @param string $content Content to render in a view, wrapped by the surrounding layout.
* @param string $layout Layout name
* @return mixed Rendered output, or false on error
+ * @triggers View.beforeLayout $this, array($layoutFileName)
+ * @triggers View.afterLayout $this, array($layoutFileName)
* @throws CakeException if there is an error in the view.
*/
public function renderLayout($content, $layout = null) {
@@ -532,7 +542,7 @@ class View extends Object {
$this->viewVars['title_for_layout'] = $title;
$this->Blocks->set('title', $title);
- $this->_currentType = self::TYPE_LAYOUT;
+ $this->_currentType = static::TYPE_LAYOUT;
$this->Blocks->set('content', $this->_render($layoutFileName));
$this->getEventManager()->dispatch(new CakeEvent('View.afterLayout', $this, array($layoutFileName)));
@@ -545,7 +555,7 @@ class View extends Object {
*
* @param string $filename the cache file to include
* @param string $timeStart the page render start time
- * @return boolean Success of rendering the cached file.
+ * @return bool Success of rendering the cached file.
*/
public function renderCache($filename, $timeStart) {
$response = $this->response;
@@ -584,15 +594,14 @@ class View extends Object {
*
* @param string $var The view var you want the contents of.
* @return mixed The content of the named var if its set, otherwise null.
- * @deprecated Will be removed in 3.0. Use View::get() instead.
+ * @deprecated 3.0.0 Will be removed in 3.0. Use View::get() instead.
*/
public function getVar($var) {
return $this->get($var);
}
/**
- * Returns the contents of the given View variable or a block.
- * Blocks are checked before view variables.
+ * Returns the contents of the given View variable.
*
* @param string $var The view var you want the contents of.
* @param mixed $default The default/fallback content of $var.
@@ -682,13 +691,23 @@ class View extends Object {
*
* @param string $name Name of the block
* @param string $default Default text
- * @return string $default The block content or $default if the block does not exist.
+ * @return string default The block content or $default if the block does not exist.
* @see ViewBlock::get()
*/
public function fetch($name, $default = '') {
return $this->Blocks->get($name, $default);
}
+/**
+ * Check if a block exists
+ *
+ * @param string $name Name of the block
+ * @return bool
+ */
+ public function exists($name) {
+ return $this->Blocks->exists($name);
+ }
+
/**
* End a capturing block. The compliment to View::start()
*
@@ -709,11 +728,11 @@ class View extends Object {
* @throws LogicException when you extend an element which doesn't exist
*/
public function extend($name) {
- if ($name[0] === '/' || $this->_currentType === self::TYPE_VIEW) {
+ if ($name[0] === '/' || $this->_currentType === static::TYPE_VIEW) {
$parent = $this->_getViewFileName($name);
} else {
switch ($this->_currentType) {
- case self::TYPE_ELEMENT:
+ case static::TYPE_ELEMENT:
$parent = $this->_getElementFileName($name);
if (!$parent) {
list($plugin, $name) = $this->pluginSplit($name);
@@ -726,7 +745,7 @@ class View extends Object {
));
}
break;
- case self::TYPE_LAYOUT:
+ case static::TYPE_LAYOUT:
$parent = $this->_getLayoutFileName($name);
break;
default:
@@ -751,7 +770,7 @@ class View extends Object {
* update/replace a script element.
* @param string $content The content of the script being added, optional.
* @return void
- * @deprecated Will be removed in 3.0. Superseded by blocks functionality.
+ * @deprecated 3.0.0 Will be removed in 3.0. Superseded by blocks functionality.
* @see View::start()
*/
public function addScript($name, $content = null) {
@@ -808,7 +827,14 @@ class View extends Object {
}
$this->viewVars = $data + $this->viewVars;
}
-
+/**
+ * Retrieve the current view type
+ *
+ * @return string
+ */
+ public function getCurrentType() {
+ return $this->_currentType;
+ }
/**
* Magic accessor for helpers. Provides access to attributes that were deprecated.
*
@@ -856,7 +882,7 @@ class View extends Object {
* Magic isset check for deprecated attributes.
*
* @param string $name Name of the attribute to check.
- * @return boolean
+ * @return bool
*/
public function __isset($name) {
if (isset($this->{$name})) {
@@ -889,6 +915,8 @@ class View extends Object {
* @param string $viewFile Filename of the view
* @param array $data Data to include in rendered view. If empty the current View::$viewVars will be used.
* @return string Rendered output
+ * @triggers View.beforeRenderFile $this, array($viewFile)
+ * @triggers View.afterRenderFile $this, array($viewFile, $content)
* @throws CakeException when a block is left open.
*/
protected function _render($viewFile, $data = array()) {
@@ -930,7 +958,7 @@ class View extends Object {
/**
* Sandbox method to evaluate a template / view script in.
*
- * @param string $viewFn Filename of the view
+ * @param string $viewFile Filename of the view
* @param array $dataForView Data to include in rendered view.
* If empty the current View::$viewVars will be used.
* @return string Rendered output
@@ -984,9 +1012,6 @@ class View extends Object {
$name = $this->viewPath . DS . $subDir . Inflector::underscore($name);
} elseif (strpos($name, DS) !== false) {
if ($name[0] === DS || $name[1] === ':') {
- if (is_file($name)) {
- return $name;
- }
$name = trim($name, DS);
} elseif ($name[0] === '.') {
$name = substr($name, 3);
@@ -1003,18 +1028,7 @@ class View extends Object {
}
}
}
- $defaultPath = $paths[0];
-
- if ($this->plugin) {
- $pluginPaths = App::path('plugins');
- foreach ($paths as $path) {
- if (strpos($path, $pluginPaths[0]) === 0) {
- $defaultPath = $path;
- break;
- }
- }
- }
- throw new MissingViewException(array('file' => $defaultPath . $name . $this->ext));
+ throw new MissingViewException(array('file' => $name . $this->ext));
}
/**
@@ -1023,7 +1037,7 @@ class View extends Object {
* It checks if the plugin is loaded, else filename will stay unchanged for filenames containing dot
*
* @param string $name The name you want to plugin split.
- * @param boolean $fallback If true uses the plugin set in the current CakeRequest when parsed plugin is not loaded
+ * @param bool $fallback If true uses the plugin set in the current CakeRequest when parsed plugin is not loaded
* @return array Array with 2 indexes. 0 => plugin name, 1 => filename
*/
public function pluginSplit($name, $fallback = true) {
@@ -1067,7 +1081,7 @@ class View extends Object {
}
}
}
- throw new MissingLayoutException(array('file' => $paths[0] . $file . $this->ext));
+ throw new MissingLayoutException(array('file' => $file . $this->ext));
}
/**
@@ -1108,12 +1122,17 @@ class View extends Object {
* Return all possible paths to find view files in order
*
* @param string $plugin Optional plugin name to scan for view files.
- * @param boolean $cached Set to false to force a refresh of view paths. Default true.
+ * @param bool $cached Set to false to force a refresh of view paths. Default true.
* @return array paths
*/
protected function _paths($plugin = null, $cached = true) {
- if ($plugin === null && $cached === true && !empty($this->_paths)) {
- return $this->_paths;
+ if ($cached === true) {
+ if ($plugin === null && !empty($this->_paths)) {
+ return $this->_paths;
+ }
+ if ($plugin !== null && isset($this->_pathsForPlugin[$plugin])) {
+ return $this->_pathsForPlugin[$plugin];
+ }
}
$paths = array();
$viewPaths = App::path('View');
@@ -1145,7 +1164,7 @@ class View extends Object {
}
$paths = array_merge($paths, $corePaths);
if ($plugin !== null) {
- return $paths;
+ return $this->_pathsForPlugin[$plugin] = $paths;
}
return $this->_paths = $paths;
}
@@ -1190,24 +1209,27 @@ class View extends Object {
* @param array $data Data to render
* @param array $options Element options
* @return string
+ * @triggers View.beforeRender $this, array($file)
+ * @triggers View.afterRender $this, array($file, $element)
*/
protected function _renderElement($file, $data, $options) {
+ $current = $this->_current;
+ $restore = $this->_currentType;
+ $this->_currentType = static::TYPE_ELEMENT;
+
if ($options['callbacks']) {
$this->getEventManager()->dispatch(new CakeEvent('View.beforeRender', $this, array($file)));
}
- $current = $this->_current;
- $restore = $this->_currentType;
-
- $this->_currentType = self::TYPE_ELEMENT;
$element = $this->_render($file, array_merge($this->viewVars, $data));
- $this->_currentType = $restore;
- $this->_current = $current;
-
if ($options['callbacks']) {
$this->getEventManager()->dispatch(new CakeEvent('View.afterRender', $this, array($file, $element)));
}
+
+ $this->_currentType = $restore;
+ $this->_current = $current;
+
if (isset($options['cache'])) {
Cache::write($this->elementCacheSettings['key'], $element, $this->elementCacheSettings['config']);
}
diff --git a/web/api/lib/Cake/View/ViewBlock.php b/web/api/lib/Cake/View/ViewBlock.php
index 28667c8c3..2d4908a28 100644
--- a/web/api/lib/Cake/View/ViewBlock.php
+++ b/web/api/lib/Cake/View/ViewBlock.php
@@ -1,7 +1,5 @@
_active)) {
- throw new CakeException(__("A view block with the name '%s' is already/still open.", $name));
+ throw new CakeException(__d('cake', "A view block with the name '%s' is already/still open.", $name));
}
$this->_active[] = $name;
ob_start();
@@ -166,7 +164,7 @@ class ViewBlock {
* @param string $name Name of the block
* @param string $value The content for the block.
* @return void
- * @deprecated As of 2.3 use ViewBlock::concat() instead.
+ * @deprecated 3.0.0 As of 2.3 use ViewBlock::concat() instead.
*/
public function append($name, $value = null) {
$this->concat($name, $value);
@@ -198,6 +196,16 @@ class ViewBlock {
return $this->_blocks[$name];
}
+/**
+ * Check if a block exists
+ *
+ * @param string $name Name of the block
+ * @return bool
+ */
+ public function exists($name) {
+ return isset($this->_blocks[$name]);
+ }
+
/**
* Get the names of all the existing blocks.
*
diff --git a/web/api/lib/Cake/View/XmlView.php b/web/api/lib/Cake/View/XmlView.php
index 1bf5419ed..7d7610836 100644
--- a/web/api/lib/Cake/View/XmlView.php
+++ b/web/api/lib/Cake/View/XmlView.php
@@ -36,10 +36,10 @@ App::uses('Hash', 'Utility');
* You can also define `'_serialize'` as an array. This will create an additional
* top level element named `` containing all the named view variables:
*
- * {{{
+ * ```
* $this->set(compact('posts', 'users', 'stuff'));
* $this->set('_serialize', array('posts', 'users'));
- * }}}
+ * ```
*
* The above would generate a XML object that looks like:
*
@@ -63,7 +63,7 @@ class XmlView extends View {
/**
* Constructor
*
- * @param Controller $controller
+ * @param Controller $controller Controller instance.
*/
public function __construct(Controller $controller = null) {
parent::__construct($controller);
@@ -109,6 +109,10 @@ class XmlView extends View {
/**
* Serialize view vars.
*
+ * ### Special parameters
+ * `_xmlOptions` You can set an array of custom options for Xml::fromArray() this way, e.g.
+ * 'format' as 'attributes' instead of 'tags'.
+ *
* @param array $serialize The viewVars that need to be serialized.
* @return string The serialized data
*/
@@ -131,10 +135,16 @@ class XmlView extends View {
}
$options = array();
+ if (isset($this->viewVars['_xmlOptions'])) {
+ $options = $this->viewVars['_xmlOptions'];
+ }
if (Configure::read('debug')) {
$options['pretty'] = true;
}
+ if (isset($options['return']) && strtolower($options['return']) === 'domdocument') {
+ return Xml::fromArray($data, $options)->saveXML();
+ }
return Xml::fromArray($data, $options)->asXML();
}
diff --git a/web/api/lib/Cake/basics.php b/web/api/lib/Cake/basics.php
index 60deced1c..e1edb6ea1 100644
--- a/web/api/lib/Cake/basics.php
+++ b/web/api/lib/Cake/basics.php
@@ -38,7 +38,7 @@ if (!function_exists('config')) {
*
* `config('config1', 'config2');`
*
- * @return boolean Success
+ * @return bool Success
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#config
*/
function config() {
@@ -64,24 +64,27 @@ if (!function_exists('debug')) {
* Only runs if debug level is greater than zero.
*
* @param mixed $var Variable to show debug information for.
- * @param boolean $showHtml If set to true, the method prints the debug data in a browser-friendly way.
- * @param boolean $showFrom If set to true, the method prints from where the function was called.
+ * @param bool $showHtml If set to true, the method prints the debug data in a browser-friendly way.
+ * @param bool $showFrom If set to true, the method prints from where the function was called.
* @return void
* @link http://book.cakephp.org/2.0/en/development/debugging.html#basic-debugging
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#debug
*/
function debug($var, $showHtml = null, $showFrom = true) {
- if (Configure::read('debug') > 0) {
- App::uses('Debugger', 'Utility');
- $file = '';
- $line = '';
- $lineInfo = '';
- if ($showFrom) {
- $trace = Debugger::trace(array('start' => 1, 'depth' => 2, 'format' => 'array'));
- $file = str_replace(array(CAKE_CORE_INCLUDE_PATH, ROOT), '', $trace[0]['file']);
- $line = $trace[0]['line'];
- }
- $html = << 1, 'depth' => 2, 'format' => 'array'));
+ $file = str_replace(array(CAKE_CORE_INCLUDE_PATH, ROOT), '', $trace[0]['file']);
+ $line = $trace[0]['line'];
+ }
+ $html = <<
%s
@@ -89,33 +92,61 @@ if (!function_exists('debug')) {
HTML;
- $text = <<%s (line %s)', $file, $line);
- }
- }
- printf($template, $lineInfo, $var);
}
+ if ($showHtml === null && $template !== $text) {
+ $showHtml = true;
+ }
+ $var = Debugger::exportVar($var, 25);
+ if ($showHtml) {
+ $template = $html;
+ $var = h($var);
+ if ($showFrom) {
+ $lineInfo = sprintf('%s (line %s)', $file, $line);
+ }
+ }
+ printf($template, $lineInfo, $var);
+ }
+
+}
+
+if (!function_exists('stackTrace')) {
+
+/**
+ * Outputs a stack trace based on the supplied options.
+ *
+ * ### Options
+ *
+ * - `depth` - The number of stack frames to return. Defaults to 999
+ * - `args` - Should arguments for functions be shown? If true, the arguments for each method call
+ * will be displayed.
+ * - `start` - The stack frame to start generating a trace from. Defaults to 1
+ *
+ * @param array $options Format for outputting stack trace
+ * @return mixed Formatted stack trace
+ * @see Debugger::trace()
+ */
+ function stackTrace(array $options = array()) {
+ if (!Configure::read('debug')) {
+ return;
+ }
+ App::uses('Debugger', 'Utility');
+
+ $options += array('start' => 0);
+ $options['start']++;
+ echo Debugger::trace($options);
}
}
@@ -125,11 +156,11 @@ if (!function_exists('sortByKey')) {
/**
* Sorts given $array by key $sortBy.
*
- * @param array $array Array to sort
+ * @param array &$array Array to sort
* @param string $sortBy Sort by this key
* @param string $order Sort order asc/desc (ascending or descending).
- * @param integer $type Type of sorting to perform
- * @return mixed Sorted array
+ * @param int $type Type of sorting to perform
+ * @return array|null Sorted array, or null if not an array.
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#sortByKey
*/
function sortByKey(&$array, $sortBy, $order = 'asc', $type = SORT_NUMERIC) {
@@ -163,13 +194,15 @@ if (!function_exists('h')) {
* @param string|array|object $text Text to wrap through htmlspecialchars. Also works with arrays, and objects.
* Arrays will be mapped and have all their elements escaped. Objects will be string cast if they
* implement a `__toString` method. Otherwise the class name will be used.
- * @param boolean $double Encode existing html entities
+ * @param bool $double Encode existing html entities
* @param string $charset Character set to use when escaping. Defaults to config value in 'App.encoding' or 'UTF-8'
* @return string Wrapped text
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#h
*/
function h($text, $double = true, $charset = null) {
- if (is_array($text)) {
+ if (is_string($text)) {
+ //optimize for strings
+ } elseif (is_array($text)) {
$texts = array();
foreach ($text as $k => $t) {
$texts[$k] = h($t, $double, $charset);
@@ -209,7 +242,7 @@ if (!function_exists('pluginSplit')) {
* Commonly used like `list($plugin, $name) = pluginSplit($name);`
*
* @param string $name The name you want to plugin split.
- * @param boolean $dotAppend Set to true if you want the plugin to have a '.' appended to it.
+ * @param bool $dotAppend Set to true if you want the plugin to have a '.' appended to it.
* @param string $plugin Optional default plugin to use if no plugin is found. Defaults to null.
* @return array Array with 2 indexes. 0 => plugin name, 1 => class name
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#pluginSplit
@@ -235,14 +268,14 @@ if (!function_exists('pr')) {
* In terminals this will act the same as using print_r() directly, when not run on cli
* print_r() will wrap
tags around the output of given array. Similar to debug().
*
- * @see debug()
* @param mixed $var Variable to print out
* @return void
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#pr
+ * @see debug()
*/
function pr($var) {
if (Configure::read('debug') > 0) {
- $template = php_sapi_name() !== 'cli' ? '
' : "\n%s\n";
printf($template, print_r($var, true));
}
}
@@ -254,10 +287,8 @@ if (!function_exists('am')) {
/**
* Merge a group of arrays
*
- * @param array First array
- * @param array Second array
- * @param array Third array
- * @param array Etc...
+ * Accepts variable arguments. Each argument will be converted into an array and then merged.
+ *
* @return array All array parameters merged into one
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#am
*/
@@ -284,7 +315,7 @@ if (!function_exists('env')) {
* environment information.
*
* @param string $key Environment variable name.
- * @return string Environment variable setting.
+ * @return string|bool|null Environment variable setting.
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#env
*/
function env($key) {
@@ -389,7 +420,7 @@ if (!function_exists('cache')) {
* @param mixed $expires A valid strtotime string when the data expires.
* @param string $target The target of the cached data; either 'cache' or 'public'.
* @return mixed The contents of the temporary file.
- * @deprecated Will be removed in 3.0. Please use Cache::write() instead.
+ * @deprecated 3.0.0 Will be removed in 3.0. Please use Cache::write() instead.
*/
function cache($path, $data = null, $expires = '+1 day', $target = 'cache') {
if (Configure::read('Cache.disable')) {
@@ -549,19 +580,13 @@ if (!function_exists('__')) {
*/
function __($singular, $args = null) {
if (!$singular) {
- return;
+ return null;
}
App::uses('I18n', 'I18n');
$translated = I18n::translate($singular);
- if ($args === null) {
- return $translated;
- } elseif (!is_array($args)) {
- $args = array_slice(func_get_args(), 1);
- }
-
- $translated = preg_replace('/(? '',
+ JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
+ JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
+ JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
+ JSON_ERROR_SYNTAX => 'Syntax error',
+ JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
+ );
+ $error = json_last_error();
+ return array_key_exists($error, $errors) ? $errors[$error] : "Unknown error ({$error})";
+ }
+
+}
diff --git a/web/api/lib/Cake/bootstrap.php b/web/api/lib/Cake/bootstrap.php
index e1bd899eb..b17c9f68f 100644
--- a/web/api/lib/Cake/bootstrap.php
+++ b/web/api/lib/Cake/bootstrap.php
@@ -148,6 +148,8 @@ App::uses('Cache', 'Cache');
App::uses('Object', 'Core');
App::uses('Multibyte', 'I18n');
+App::$bootstrapping = true;
+
/**
* Full URL prefix
*/
@@ -170,19 +172,6 @@ Configure::write('App.imageBaseUrl', IMAGES_URL);
Configure::write('App.cssBaseUrl', CSS_URL);
Configure::write('App.jsBaseUrl', JS_URL);
-App::$bootstrapping = true;
-
-Configure::bootstrap(isset($boot) ? $boot : true);
-
-if (function_exists('mb_internal_encoding')) {
- $encoding = Configure::read('App.encoding');
- if (!empty($encoding)) {
- mb_internal_encoding($encoding);
- }
- if (!empty($encoding) && function_exists('mb_regex_encoding')) {
- mb_regex_encoding($encoding);
- }
-}
if (!function_exists('mb_stripos')) {
@@ -191,9 +180,9 @@ if (!function_exists('mb_stripos')) {
*
* @param string $haystack The string from which to get the position of the first occurrence of $needle.
* @param string $needle The string to find in $haystack.
- * @param integer $offset The position in $haystack to start searching.
+ * @param int $offset The position in $haystack to start searching.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string, or false
+ * @return int|bool The numeric position of the first occurrence of $needle in the $haystack string, or false
* if $needle is not found.
*/
function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) {
@@ -209,12 +198,12 @@ if (!function_exists('mb_stristr')) {
*
* @param string $haystack The string from which to get the first occurrence of $needle.
* @param string $needle The string to find in $haystack.
- * @param boolean $part Determines which portion of $haystack this function returns.
+ * @param bool $part Determines which portion of $haystack this function returns.
* If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
* If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
* Default value is false.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return string|boolean The portion of $haystack, or false if $needle is not found.
+ * @return string|bool The portion of $haystack, or false if $needle is not found.
*/
function mb_stristr($haystack, $needle, $part = false, $encoding = null) {
return Multibyte::stristr($haystack, $needle, $part);
@@ -229,7 +218,7 @@ if (!function_exists('mb_strlen')) {
*
* @param string $string The string being checked for length.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return integer The number of characters in string $string having character encoding encoding.
+ * @return int The number of characters in string $string having character encoding encoding.
* A multi-byte character is counted as 1.
*/
function mb_strlen($string, $encoding = null) {
@@ -245,9 +234,9 @@ if (!function_exists('mb_strpos')) {
*
* @param string $haystack The string being checked.
* @param string $needle The position counted from the beginning of haystack.
- * @param integer $offset The search offset. If it is not specified, 0 is used.
+ * @param int $offset The search offset. If it is not specified, 0 is used.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string.
+ * @return int|bool The numeric position of the first occurrence of $needle in the $haystack string.
* If $needle is not found, it returns false.
*/
function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) {
@@ -263,12 +252,12 @@ if (!function_exists('mb_strrchr')) {
*
* @param string $haystack The string from which to get the last occurrence of $needle.
* @param string $needle The string to find in $haystack.
- * @param boolean $part Determines which portion of $haystack this function returns.
+ * @param bool $part Determines which portion of $haystack this function returns.
* If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
* If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
* Default value is false.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return string|boolean The portion of $haystack. or false if $needle is not found.
+ * @return string|bool The portion of $haystack. or false if $needle is not found.
*/
function mb_strrchr($haystack, $needle, $part = false, $encoding = null) {
return Multibyte::strrchr($haystack, $needle, $part);
@@ -283,12 +272,12 @@ if (!function_exists('mb_strrichr')) {
*
* @param string $haystack The string from which to get the last occurrence of $needle.
* @param string $needle The string to find in $haystack.
- * @param boolean $part Determines which portion of $haystack this function returns.
+ * @param bool $part Determines which portion of $haystack this function returns.
* If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
* If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
* Default value is false.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return string|boolean The portion of $haystack. or false if $needle is not found.
+ * @return string|bool The portion of $haystack. or false if $needle is not found.
*/
function mb_strrichr($haystack, $needle, $part = false, $encoding = null) {
return Multibyte::strrichr($haystack, $needle, $part);
@@ -303,9 +292,9 @@ if (!function_exists('mb_strripos')) {
*
* @param string $haystack The string from which to get the position of the last occurrence of $needle.
* @param string $needle The string to find in $haystack.
- * @param integer $offset The position in $haystack to start searching.
+ * @param int $offset The position in $haystack to start searching.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string,
+ * @return int|bool The numeric position of the last occurrence of $needle in the $haystack string,
* or false if $needle is not found.
*/
function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) {
@@ -321,10 +310,10 @@ if (!function_exists('mb_strrpos')) {
*
* @param string $haystack The string being checked, for the last occurrence of $needle.
* @param string $needle The string to find in $haystack.
- * @param integer $offset May be specified to begin searching an arbitrary number of characters into the string.
+ * @param int $offset May be specified to begin searching an arbitrary number of characters into the string.
* Negative values will stop searching at an arbitrary point prior to the end of the string.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string.
+ * @return int|bool The numeric position of the last occurrence of $needle in the $haystack string.
* If $needle is not found, it returns false.
*/
function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) {
@@ -340,12 +329,12 @@ if (!function_exists('mb_strstr')) {
*
* @param string $haystack The string from which to get the first occurrence of $needle.
* @param string $needle The string to find in $haystack
- * @param boolean $part Determines which portion of $haystack this function returns.
+ * @param bool $part Determines which portion of $haystack this function returns.
* If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
* If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
* Default value is FALSE.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return string|boolean The portion of $haystack, or true if $needle is not found.
+ * @return string|bool The portion of $haystack, or true if $needle is not found.
*/
function mb_strstr($haystack, $needle, $part = false, $encoding = null) {
return Multibyte::strstr($haystack, $needle, $part);
@@ -391,7 +380,7 @@ if (!function_exists('mb_substr_count')) {
* @param string $haystack The string being checked.
* @param string $needle The string being found.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
- * @return integer The number of times the $needle substring occurs in the $haystack string.
+ * @return int The number of times the $needle substring occurs in the $haystack string.
*/
function mb_substr_count($haystack, $needle, $encoding = null) {
return Multibyte::substrCount($haystack, $needle);
@@ -405,8 +394,8 @@ if (!function_exists('mb_substr')) {
* Get part of string
*
* @param string $string The string being checked.
- * @param integer $start The first position used in $string.
- * @param integer $length The maximum length of the returned string.
+ * @param int $start The first position used in $string.
+ * @param int $length The maximum length of the returned string.
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
* @return string The portion of $string specified by the $string and $length parameters.
*/
@@ -424,13 +413,13 @@ if (!function_exists('mb_encode_mimeheader')) {
* @param string $str The string being encoded
* @param string $charset specifies the name of the character set in which str is represented in.
* The default value is determined by the current NLS setting (mbstring.language).
- * @param string $transfer_encoding specifies the scheme of MIME encoding.
+ * @param string $transferEncoding specifies the scheme of MIME encoding.
* It should be either "B" (Base64) or "Q" (Quoted-Printable). Falls back to "B" if not given.
* @param string $linefeed specifies the EOL (end-of-line) marker with which
* mb_encode_mimeheader() performs line-folding
* (a » RFC term, the act of breaking a line longer than a certain length into multiple lines.
* The length is currently hard-coded to 74 characters). Falls back to "\r\n" (CRLF) if not given.
- * @param integer $indent [definition unknown and appears to have no affect]
+ * @param int $indent [definition unknown and appears to have no affect]
* @return string A converted version of the string represented in ASCII.
*/
function mb_encode_mimeheader($str, $charset = 'UTF-8', $transferEncoding = 'B', $linefeed = "\r\n", $indent = 1) {
@@ -438,3 +427,15 @@ if (!function_exists('mb_encode_mimeheader')) {
}
}
+
+Configure::bootstrap(isset($boot) ? $boot : true);
+
+if (function_exists('mb_internal_encoding')) {
+ $encoding = Configure::read('App.encoding');
+ if (!empty($encoding)) {
+ mb_internal_encoding($encoding);
+ }
+ if (!empty($encoding) && function_exists('mb_regex_encoding')) {
+ mb_regex_encoding($encoding);
+ }
+}
diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php
index 8aa7f4dc9..6b983018e 100644
--- a/web/includes/Monitor.php
+++ b/web/includes/Monitor.php
@@ -80,5 +80,17 @@ class Monitor {
return( $streamSrc );
} // end function etStreamSrc
+ public function Width() {
+ if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) {
+ return $this->{'Height'};
+ }
+ return $this->{'Width'};
+ }
+ public function Height() {
+ if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) {
+ return $this->{'Width'};
+ }
+ return $this->{'Height'};
+ }
}
?>
diff --git a/web/includes/config.php.in b/web/includes/config.php.in
index 466e195f2..2ca819210 100644
--- a/web/includes/config.php.in
+++ b/web/includes/config.php.in
@@ -173,14 +173,14 @@ if ( ! defined('ZM_SERVER_ID') ) {
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME));
if ( ! $server_id ) {
- Error("ZM_SERVER_NAME set to " . ZM_SERVER_NAME . " in config, but not found in Servers table.");
+ Error("Invalid Multi-Server configration detected. ZM_SERVER_NAME set to " . ZM_SERVER_NAME . " in zm.conf, but no corresponding entry found in Servers table.");
} else {
define( 'ZM_SERVER_ID', $server_id );
}
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_HOST));
if ( ! $server_id ) {
- Error("ZM_SERVER_HOST set to " . ZM_SERVER_HOST . " in config, but not found in Servers table.");
+ Error("Invalid Multi-Server configration detected. ZM_SERVER_HOST set to " . ZM_SERVER_HOST . " in zm.conf, but no corresponding entry found in Servers table.");
} else {
define( 'ZM_SERVER_ID', $server_id );
}
diff --git a/web/includes/functions.php b/web/includes/functions.php
index 2b879689d..89ca33e40 100644
--- a/web/includes/functions.php
+++ b/web/includes/functions.php
@@ -795,7 +795,7 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false )
{
if ( !isset($values[$key]) || ($values[$key] != $value) )
{
- $changes[$key] = "$key = ".dbEscape($value);
+ $changes[$key] = "$key = ".dbEscape(trim($value));
}
break;
}
diff --git a/web/lang/ru_ru.php b/web/lang/ru_ru.php
index 64f7a8ec7..e12c857d2 100644
--- a/web/lang/ru_ru.php
+++ b/web/lang/ru_ru.php
@@ -1,3 +1,4 @@
+
'24 ',
- '32BitColour' => '32 ', // Added - 2011-06-15
- '8BitGrey' => '256 ',
+ '24BitColour' => '24 битный цвет',
+ '32BitColour' => '32 битный цвет', // Added - 2011-06-15
+ '8BitGrey' => '256 оттенков серого',
'Action' => 'Action',
- 'Actual' => '',
+ 'Actual' => 'Действительный',
'AddNewControl' => 'Add New Control',
- 'AddNewMonitor' => ' ',
- 'AddNewUser' => ' ',
- 'AddNewZone' => ' ',
- 'Alarm' => '',
- 'AlarmBrFrames' => ' ',
- 'AlarmFrame' => ' ',
+ 'AddNewMonitor' => 'Добавить монитор',
+ 'AddNewUser' => 'Добавить пользователя',
+ 'AddNewZone' => 'Добавить зону',
+ 'Alarm' => 'Тревога',
+ 'AlarmBrFrames' => 'Кадры тревоги',
+ 'AlarmFrame' => 'Кадр тревоги',
'AlarmFrameCount' => 'Alarm Frame Count',
- 'AlarmLimits' => '. .',
+ 'AlarmLimits' => 'Гран. зоны трев.',
'AlarmMaximumFPS' => 'Alarm Maximum FPS',
- 'AlarmPx' => ' .',
+ 'AlarmPx' => 'Пкс трев.',
'AlarmRGBUnset' => 'You must set an alarm RGB colour',
'AlarmRefImageBlendPct'=> 'Alarm Reference Image Blend %ge', // Added - 2015-04-18
- 'Alert' => '',
- 'All' => '',
+ 'Alert' => 'Настороже',
+ 'All' => 'Все',
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
- 'Apply' => '',
- 'ApplyingStateChange' => ' ',
- 'ArchArchived' => ' ',
- 'ArchUnarchived' => ' ',
- 'Archive' => '',
+ 'Apply' => 'Применить',
+ 'ApplyingStateChange' => 'Состояние сервиса изменяется',
+ 'ArchArchived' => 'Только в архиве',
+ 'ArchUnarchived' => 'Только не в архиве',
+ 'Archive' => 'Архив',
'Archived' => 'Archived',
'Area' => 'Area',
'AreaUnits' => 'Area (px/%)',
- 'AttrAlarmFrames' => '- ',
- 'AttrArchiveStatus' => ' ',
- 'AttrAvgScore' => '. ',
+ 'AttrAlarmFrames' => 'Кол-во кадров тревоги',
+ 'AttrArchiveStatus' => 'Статус архивации',
+ 'AttrAvgScore' => 'Сред. оценка',
'AttrCause' => 'Cause',
- 'AttrDate' => '',
- 'AttrDateTime' => '/',
+ 'AttrDate' => 'Дата',
+ 'AttrDateTime' => 'Дата/Время',
'AttrDiskBlocks' => 'Disk Blocks',
'AttrDiskPercent' => 'Disk Percent',
- 'AttrDuration' => '',
- 'AttrFrames' => '- ',
+ 'AttrDuration' => 'Длительность',
+ 'AttrFrames' => 'Кол-во кадров',
'AttrId' => 'Id',
- 'AttrMaxScore' => '. ',
- 'AttrMonitorId' => 'Id ',
- 'AttrMonitorName' => ' ',
+ 'AttrMaxScore' => 'Макс. оценка',
+ 'AttrMonitorId' => 'Id Монитора',
+ 'AttrMonitorName' => 'Название Монитора',
'AttrName' => 'Name',
'AttrNotes' => 'Notes',
'AttrSystemLoad' => 'System Load',
- 'AttrTime' => '',
- 'AttrTotalScore' => '. ',
- 'AttrWeekday' => ' ',
+ 'AttrTime' => 'Время',
+ 'AttrTotalScore' => 'Сумм. оценка',
+ 'AttrWeekday' => 'День недели',
'Auto' => 'Auto',
'AutoStopTimeout' => 'Auto Stop Timeout',
'Available' => 'Available', // Added - 2009-03-31
- 'AvgBrScore' => '. ',
+ 'AvgBrScore' => 'Сред. оценка',
'Background' => 'Background',
'BackgroundFilter' => 'Run filter in background',
'BadAlarmFrameCount' => 'Alarm frame count must be an integer of one or more',
@@ -157,14 +158,14 @@ $SLANG = array(
'BadWarmupCount' => 'Warmup frames must be an integer of zero or more',
'BadWebColour' => 'Web colour must be a valid web colour string',
'BadWidth' => 'Width must be set to a valid value',
- 'Bandwidth' => '',
+ 'Bandwidth' => 'канал',
'BandwidthHead' => 'Bandwidth', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
- 'BlobPx' => ' ',
- 'BlobSizes' => ' ',
- 'Blobs' => '- ',
- 'Brightness' => '',
+ 'BlobPx' => 'Пкс объекта',
+ 'BlobSizes' => 'Размер объектов',
+ 'Blobs' => 'Кол-во объектов',
+ 'Brightness' => 'Яркость',
'Buffer' => 'Buffer', // Added - 2015-04-18
- 'Buffers' => '',
+ 'Buffers' => 'Буферы',
'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18
'CanAutoFocus' => 'Can Auto Focus',
'CanAutoGain' => 'Can Auto Gain',
@@ -204,35 +205,35 @@ $SLANG = array(
'CanZoomAbs' => 'Can Zoom Absolute',
'CanZoomCon' => 'Can Zoom Continuous',
'CanZoomRel' => 'Can Zoom Relative',
- 'Cancel' => '',
- 'CancelForcedAlarm' => ' ',
- 'CaptureHeight' => ' Y',
+ 'Cancel' => 'Отменить',
+ 'CancelForcedAlarm' => 'Отменить форсированную тревогу',
+ 'CaptureHeight' => 'Размер по Y',
'CaptureMethod' => 'Capture Method', // Added - 2009-02-08
- 'CapturePalette' => ' ',
+ 'CapturePalette' => 'Режим захвата',
'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18
- 'CaptureWidth' => ' X',
+ 'CaptureWidth' => 'Размер по X',
'Cause' => 'Cause',
- 'CheckMethod' => ' ',
+ 'CheckMethod' => 'Метод проверки тревоги',
'ChooseDetectedCamera' => 'Choose Detected Camera', // Added - 2009-03-31
- 'ChooseFilter' => ' ',
+ 'ChooseFilter' => 'Выбрать фильтр',
'ChooseLogFormat' => 'Choose a log format', // Added - 2011-06-17
'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17
'ChoosePreset' => 'Choose Preset',
'Clear' => 'Clear', // Added - 2011-06-16
- 'Close' => '',
- 'Colour' => '',
+ 'Close' => 'Закрыть',
+ 'Colour' => 'Цвет',
'Command' => 'Command',
'Component' => 'Component', // Added - 2011-06-16
'Config' => 'Config',
- 'ConfiguredFor' => ' ',
+ 'ConfiguredFor' => 'Настроен на',
'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?',
- 'ConfirmPassword' => ' ',
- 'ConjAnd' => '',
- 'ConjOr' => '',
- 'Console' => '',
- 'ContactAdmin' => ' .',
+ 'ConfirmPassword' => 'Подтвердите пароль',
+ 'ConjAnd' => 'и',
+ 'ConjOr' => 'или',
+ 'Console' => 'Сервер',
+ 'ContactAdmin' => 'Пожалуйста обратитесь к вашему администратору.',
'Continue' => 'Continue',
- 'Contrast' => '',
+ 'Contrast' => 'Контраст',
'Control' => 'Control',
'ControlAddress' => 'Control Address',
'ControlCap' => 'Control Capability',
@@ -242,29 +243,29 @@ $SLANG = array(
'Controllable' => 'Controllable',
'Current' => 'Current', // Added - 2015-04-18
'Cycle' => 'Cycle',
- 'CycleWatch' => ' ',
+ 'CycleWatch' => 'Циклический просмотр',
'DateTime' => 'Date/Time', // Added - 2011-06-16
- 'Day' => '',
+ 'Day' => 'День',
'Debug' => 'Debug',
'DefaultRate' => 'Default Rate',
'DefaultScale' => 'Default Scale',
'DefaultView' => 'Default View',
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18
- 'Delete' => '',
- 'DeleteAndNext' => ' & .',
- 'DeleteAndPrev' => ' & .',
- 'DeleteSavedFilter' => ' ',
- 'Description' => '',
+ 'Delete' => 'Удалить',
+ 'DeleteAndNext' => 'Удалить & след.',
+ 'DeleteAndPrev' => 'Удалить & пред.',
+ 'DeleteSavedFilter' => 'Удалить сохраненный фильтр',
+ 'Description' => 'Описание',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18
'Device' => 'Device', // Added - 2009-02-08
- 'DeviceChannel' => '',
- 'DeviceFormat' => '',
- 'DeviceNumber' => ' ',
+ 'DeviceChannel' => 'Канал',
+ 'DeviceFormat' => 'Формат',
+ 'DeviceNumber' => 'Номер устройства',
'DevicePath' => 'Device Path',
'Devices' => 'Devices',
- 'Dimensions' => '',
+ 'Dimensions' => 'Размеры',
'DisableAlarms' => 'Disable Alarms',
'Disk' => 'Disk',
'Display' => 'Display', // Added - 2011-01-30
@@ -281,23 +282,23 @@ $SLANG = array(
'DonateYes' => 'Yes, I\'d like to donate now',
'Download' => 'Download',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
- 'Duration' => '',
- 'Edit' => '',
+ 'Duration' => 'Длительность',
+ 'Edit' => 'Редактирование',
'Email' => 'Email',
'EnableAlarms' => 'Enable Alarms',
- 'Enabled' => '',
- 'EnterNewFilterName' => ' ',
- 'Error' => '',
- 'ErrorBrackets' => ': ',
- 'ErrorValidValue' => ': ',
- 'Etc' => ' ..',
- 'Event' => '',
- 'EventFilter' => ' ',
+ 'Enabled' => 'разрешен',
+ 'EnterNewFilterName' => 'Введите новое название фильтра',
+ 'Error' => 'Ошибка',
+ 'ErrorBrackets' => 'Ошибка: количество открывающих и закрывающих скобок должно быть одинаковым',
+ 'ErrorValidValue' => 'Ошибка: проверьте что все термы имеют действительное значение',
+ 'Etc' => 'и т.д.',
+ 'Event' => 'Событие',
+ 'EventFilter' => 'Фильтр событий',
'EventId' => 'Event Id',
'EventName' => 'Event Name',
'EventPrefix' => 'Event Prefix',
- 'Events' => '',
- 'Exclude' => '',
+ 'Events' => 'События',
+ 'Exclude' => 'Исключить',
'Execute' => 'Execute',
'Export' => 'Export',
'ExportDetails' => 'Export Event Details',
@@ -313,8 +314,8 @@ $SLANG = array(
'ExportSucceeded' => 'Export Succeeded', // Added - 2009-02-08
'ExportVideoFiles' => 'Export Video Files (if present)',
'Exporting' => 'Exporting',
- 'FPS' => '/c',
- 'FPSReportInterval' => ' ',
+ 'FPS' => 'к/c',
+ 'FPSReportInterval' => 'Период обновления индикации скорости',
'FTP' => 'FTP',
'Far' => 'Far',
'FastForward' => 'Fast Forward',
@@ -328,12 +329,12 @@ $SLANG = array(
'FilterExecuteEvents' => 'Execute command on all matches',
'FilterLog' => 'Filter log', // Added - 2015-04-18
'FilterMessageEvents' => 'Message details of all matches',
- 'FilterPx' => ' ',
+ 'FilterPx' => 'Пкс фильтра',
'FilterUnset' => 'You must specify a filter width and height',
'FilterUploadEvents' => 'Upload all matches',
'FilterVideoEvents' => 'Create video for all matches',
'Filters' => 'Filters',
- 'First' => '',
+ 'First' => 'Первый',
'FlippedHori' => 'Flipped Horizontally',
'FlippedVert' => 'Flipped Vertically',
'FnMocord' => 'Mocord', // Added 2013.08.16.
@@ -343,21 +344,21 @@ $SLANG = array(
'FnNone' => 'None', // Added 2013.08.16.
'FnRecord' => 'Record', // Added 2013.08.16.
'Focus' => 'Focus',
- 'ForceAlarm' => ' ',
+ 'ForceAlarm' => 'Включить тревогу',
'Format' => 'Format',
- 'Frame' => '',
- 'FrameId' => 'Id ',
- 'FrameRate' => '',
- 'FrameSkip' => ' ',
- 'Frames' => '',
- 'Func' => '.',
- 'Function' => '',
+ 'Frame' => 'Кадр',
+ 'FrameId' => 'Id кадра',
+ 'FrameRate' => 'Скорость',
+ 'FrameSkip' => 'Пропускать кадры',
+ 'Frames' => 'кадры',
+ 'Func' => 'Функ.',
+ 'Function' => 'Функция',
'Gain' => 'Gain',
'General' => 'General',
- 'GenerateVideo' => ' ',
- 'GeneratingVideo' => ' ',
- 'GoToZoneMinder' => ' ZoneMinder.com',
- 'Grey' => '/',
+ 'GenerateVideo' => 'Генерировать видео',
+ 'GeneratingVideo' => 'Генерируется видео',
+ 'GoToZoneMinder' => 'Перейти на ZoneMinder.com',
+ 'Grey' => 'ч/б',
'Group' => 'Group',
'Groups' => 'Groups',
'HasFocusSpeed' => 'Has Focus Speed',
@@ -371,25 +372,25 @@ $SLANG = array(
'HasTurboTilt' => 'Has Turbo Tilt',
'HasWhiteSpeed' => 'Has White Bal. Speed',
'HasZoomSpeed' => 'Has Zoom Speed',
- 'High' => '',
- 'HighBW' => ' ',
+ 'High' => 'широкий',
+ 'HighBW' => 'Широкий канал',
'Home' => 'Home',
- 'Hour' => '',
- 'Hue' => '',
+ 'Hour' => 'Час',
+ 'Hue' => 'Оттенок',
'Id' => 'Id',
'Idle' => 'Idle',
- 'Ignore' => '',
- 'Image' => '',
- 'ImageBufferSize' => ' ',
+ 'Ignore' => 'Игнорировать',
+ 'Image' => 'Изображение',
+ 'ImageBufferSize' => 'Размер буфера изображения',
'Images' => 'Images',
'In' => 'In',
- 'Include' => '',
- 'Inverted' => '',
+ 'Include' => 'Включить',
+ 'Inverted' => 'Инвертировать',
'Iris' => 'Iris',
'KeyString' => 'Key String',
'Label' => 'Label',
- 'Language' => '',
- 'Last' => '',
+ 'Language' => 'Язык',
+ 'Last' => 'Последний',
'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16
'Libvlc' => 'Libvlc',
@@ -399,23 +400,23 @@ $SLANG = array(
'LinkedMonitors' => 'Linked Monitors',
'List' => 'List',
'Load' => 'Load',
- 'Local' => '',
+ 'Local' => 'Локальный',
'Log' => 'Log', // Added - 2011-06-16
- 'LoggedInAs' => '',
+ 'LoggedInAs' => 'Пользователь',
'Logging' => 'Logging', // Added - 2011-06-16
- 'LoggingIn' => ' ',
- 'Login' => '',
- 'Logout' => '',
+ 'LoggingIn' => 'Вход в систему',
+ 'Login' => 'Войти',
+ 'Logout' => 'Выйти',
'Logs' => 'Logs', // Added - 2011-06-17
- 'Low' => '',
- 'LowBW' => ' ',
+ 'Low' => 'узкий',
+ 'LowBW' => 'Узкий канал',
'Main' => 'Main',
'Man' => 'Man',
'Manual' => 'Manual',
- 'Mark' => '',
- 'Max' => '.',
+ 'Mark' => 'Метка',
+ 'Max' => 'Макс.',
'MaxBandwidth' => 'Max Bandwidth',
- 'MaxBrScore' => '. ',
+ 'MaxBrScore' => 'Макс. оценка',
'MaxFocusRange' => 'Max Focus Range',
'MaxFocusSpeed' => 'Max Focus Speed',
'MaxFocusStep' => 'Max Focus Step',
@@ -437,16 +438,16 @@ $SLANG = array(
'MaxZoomRange' => 'Max Zoom Range',
'MaxZoomSpeed' => 'Max Zoom Speed',
'MaxZoomStep' => 'Max Zoom Step',
- 'MaximumFPS' => ' (/)',
- 'Medium' => '',
- 'MediumBW' => ' ',
+ 'MaximumFPS' => 'Ограничение скорости записи (к/с)',
+ 'Medium' => 'средний',
+ 'MediumBW' => 'Обычный канал',
'Message' => 'Message', // Added - 2011-06-16
'MinAlarmAreaLtMax' => 'Minimum alarm area should be less than maximum',
'MinAlarmAreaUnset' => 'You must specify the minimum alarm pixel count',
- 'MinBlobAreaLtMax' => ' ',
+ 'MinBlobAreaLtMax' => 'Минимальная площадь объекта должна быть меньше чем максимальная площадь объекта',
'MinBlobAreaUnset' => 'You must specify the minimum blob pixel count',
'MinBlobLtMinFilter' => 'Minimum blob area should be less than or equal to minimum filter area',
- 'MinBlobsLtMax' => ' ',
+ 'MinBlobsLtMax' => 'Минимальное число объектов должно быть меньше чем максимальное число объектов',
'MinBlobsUnset' => 'You must specify the minimum blob count',
'MinFilterAreaLtMax' => 'Minimum filter area should be less than maximum',
'MinFilterAreaUnset' => 'You must specify the minimum filter pixel count',
@@ -463,7 +464,7 @@ $SLANG = array(
'MinPanRange' => 'Min Pan Range',
'MinPanSpeed' => 'Min Pan Speed',
'MinPanStep' => 'Min Pan Step',
- 'MinPixelThresLtMax' => ' - - ',
+ 'MinPixelThresLtMax' => 'Нижний порог кол-ва пикселей должен быть ниже верхнего порога кол-ва пикселей',
'MinPixelThresUnset' => 'You must specify a minimum pixel threshold',
'MinTiltRange' => 'Min Tilt Range',
'MinTiltSpeed' => 'Min Tilt Speed',
@@ -474,17 +475,17 @@ $SLANG = array(
'MinZoomRange' => 'Min Zoom Range',
'MinZoomSpeed' => 'Min Zoom Speed',
'MinZoomStep' => 'Min Zoom Step',
- 'Misc' => '',
+ 'Misc' => 'Разное',
'Mode' => 'Mode', // Added - 2015-04-18
- 'Monitor' => '',
- 'MonitorIds' => 'Id ',
+ 'Monitor' => 'Монитор',
+ 'MonitorIds' => 'Id Мониторов',
'MonitorPreset' => 'Monitor Preset',
'MonitorPresetIntro' => 'Select an appropriate preset from the list below.
Please note that this may overwrite any values you already have configured for this monitor.
',
'MonitorProbe' => 'Monitor Probe', // Added - 2009-03-31
'MonitorProbeIntro' => 'The list below shows detected analog and network cameras and whether they are already being used or available for selection.
Select the desired entry from the list below.
Please note that not all cameras may be detected and that choosing a camera here may overwrite any values you already have configured for the current monitor.
', // Added - 2009-03-31
- 'Monitors' => '',
+ 'Monitors' => 'Мониторы',
'Montage' => 'Montage',
- 'Month' => '',
+ 'Month' => 'Месяц',
'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip',
'Move' => 'Move',
@@ -493,30 +494,30 @@ $SLANG = array(
'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15.
'Mtg4widgrd' => '4-wide grid', // Added 2013.08.15.
'MtgDefault' => 'Default', // Added 2013.08.15.
- 'MustBeGe' => ' ',
- 'MustBeLe' => ' ',
- 'MustConfirmPassword' => ' ',
- 'MustSupplyPassword' => ' ',
- 'MustSupplyUsername' => ' ',
- 'Name' => '',
+ 'MustBeGe' => 'должно быть больше или равно',
+ 'MustBeLe' => 'должно быть меньше или равно',
+ 'MustConfirmPassword' => 'Вы должны подтвердить пароль',
+ 'MustSupplyPassword' => 'Вы должны ввести пароль',
+ 'MustSupplyUsername' => 'Вы должны ввести имя пользователя',
+ 'Name' => 'Имя',
'Near' => 'Near',
- 'Network' => '',
- 'New' => '.',
+ 'Network' => 'Сеть',
+ 'New' => 'Нов.',
'NewGroup' => 'New Group',
'NewLabel' => 'New Label',
- 'NewPassword' => ' ',
- 'NewState' => ' ',
- 'NewUser' => ' ',
- 'Next' => '.',
- 'No' => '',
+ 'NewPassword' => 'Новый пароль',
+ 'NewState' => 'Новое состояние',
+ 'NewUser' => 'Новый пользователь',
+ 'Next' => 'След.',
+ 'No' => 'Нет',
'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31
- 'NoFramesRecorded' => ' ',
+ 'NoFramesRecorded' => 'Это событие не содежит кадров',
'NoGroup' => 'No Group',
- 'NoSavedFilters' => ' ',
- 'NoStatisticsRecorded' => ' / ',
- 'None' => '',
- 'NoneAvailable' => ' ',
- 'Normal' => '',
+ 'NoSavedFilters' => 'нет сохраненных фильтров',
+ 'NoStatisticsRecorded' => 'Статистика по этому событию/кадру не записана',
+ 'None' => 'отсутствует',
+ 'NoneAvailable' => 'не доступны',
+ 'Normal' => 'Нормальная',
'Notes' => 'Notes',
'NumPresets' => 'Num Presets',
'Off' => 'Off',
@@ -524,106 +525,106 @@ $SLANG = array(
'OnvifCredentialsIntro'=> 'Please supply user name and password for the selected camera. If no user has been created for the camera then the user given here will be created with the given password.
', // Added - 2015-04-18
'OnvifProbe' => 'ONVIF', // Added - 2015-04-18
'OnvifProbeIntro' => 'The list below shows detected ONVIF cameras and whether they are already being used or available for selection.
Select the desired entry from the list below.
Please note that not all cameras may be detected and that choosing a camera here may overwrite any values you already have configured for the current monitor.
Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.
', // Added - 2015-04-18
'Progress' => 'Progress', // Added - 2015-04-18
'Protocol' => 'Protocol',
- 'Rate' => '',
- 'Real' => '',
+ 'Rate' => 'Скорость',
+ 'Real' => 'Реальная',
'Record' => 'Record',
- 'RefImageBlendPct' => ' , %',
- 'Refresh' => '',
- 'Remote' => '',
- 'RemoteHostName' => ' ',
- 'RemoteHostPath' => ' ',
- 'RemoteHostPort' => ' ',
+ 'RefImageBlendPct' => 'Прозрачность опорного кадра, %',
+ 'Refresh' => 'Обновить',
+ 'Remote' => 'Удаленный',
+ 'RemoteHostName' => 'Имя удаленного хоста',
+ 'RemoteHostPath' => 'Путь на удаленном хосте',
+ 'RemoteHostPort' => 'удаленный порт',
'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08
- 'RemoteImageColours' => ' ',
+ 'RemoteImageColours' => 'Цветность на удаленном хосте',
'RemoteMethod' => 'Remote Method', // Added - 2009-02-08
'RemoteProtocol' => 'Remote Protocol', // Added - 2009-02-08
- 'Rename' => '',
+ 'Rename' => 'Переименовать',
'Replay' => 'Replay',
'ReplayAll' => 'All Events',
'ReplayGapless' => 'Gapless Events',
'ReplaySingle' => 'Single Event',
'Reset' => 'Reset',
- 'ResetEventCounts' => ' ',
- 'Restart' => '',
- 'Restarting' => '',
- 'RestrictedCameraIds' => 'Id ',
+ 'ResetEventCounts' => 'Обнулить счетчик событий',
+ 'Restart' => 'Перезапустить',
+ 'Restarting' => 'Перезапускается',
+ 'RestrictedCameraIds' => 'Id запрещенных камер',
'RestrictedMonitors' => 'Restricted Monitors',
'ReturnDelay' => 'Return Delay',
'ReturnLocation' => 'Return Location',
'Rewind' => 'Rewind',
- 'RotateLeft' => ' ',
- 'RotateRight' => ' ',
+ 'RotateLeft' => 'Повернуть влево',
+ 'RotateRight' => 'Повернуть вправо',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
- 'RunMode' => ' ',
- 'RunState' => '',
- 'Running' => '',
- 'Save' => '',
- 'SaveAs' => ' ',
- 'SaveFilter' => ' ',
- 'Scale' => '',
- 'Score' => '',
- 'Secs' => '.',
- 'Sectionlength' => ' ( )',
+ 'RunMode' => 'Режим работы',
+ 'RunState' => 'Состояние',
+ 'Running' => 'Выполняется',
+ 'Save' => 'Сохранить',
+ 'SaveAs' => 'Сохранить как',
+ 'SaveFilter' => 'Сохранить фильтр',
+ 'Scale' => 'Масштаб',
+ 'Score' => 'Оценка',
+ 'Secs' => 'Сек.',
+ 'Sectionlength' => 'Длина секции (в кадрах)',
'Select' => 'Select',
'SelectFormat' => 'Select Format', // Added - 2011-06-17
'SelectLog' => 'Select Log', // Added - 2011-06-17
'SelectMonitors' => 'Select Monitors',
'SelfIntersecting' => 'Polygon edges must not intersect',
'Set' => 'Set',
- 'SetNewBandwidth' => ' ',
+ 'SetNewBandwidth' => 'Установка новой ширина канала',
'SetPreset' => 'Set Preset',
- 'Settings' => '',
- 'ShowFilterWindow' => ' ',
+ 'Settings' => 'Настройки',
+ 'ShowFilterWindow' => 'Показать окно фильтра',
'ShowTimeline' => 'Show Timeline',
'SignalCheckColour' => 'Signal Check Colour',
'Size' => 'Size',
@@ -632,19 +633,19 @@ $SLANG = array(
'SortAsc' => 'Asc',
'SortBy' => 'Sort by',
'SortDesc' => 'Desc',
- 'Source' => '',
+ 'Source' => 'Источник',
'SourceColours' => 'Source Colours', // Added - 2009-02-08
'SourcePath' => 'Source Path', // Added - 2009-02-08
- 'SourceType' => ' ',
+ 'SourceType' => 'Тип источника',
'Speed' => 'Speed',
'SpeedHigh' => 'High Speed',
'SpeedLow' => 'Low Speed',
'SpeedMedium' => 'Medium Speed',
'SpeedTurbo' => 'Turbo Speed',
- 'Start' => '',
- 'State' => '',
- 'Stats' => '',
- 'Status' => '',
+ 'Start' => 'Запустить',
+ 'State' => 'Состояние',
+ 'Stats' => 'Статистика',
+ 'Status' => 'Статус',
'Step' => 'Step',
'StepBack' => 'Step Back',
'StepForward' => 'Step Forward',
@@ -652,84 +653,84 @@ $SLANG = array(
'StepMedium' => 'Medium Step',
'StepNone' => 'No Step',
'StepSmall' => 'Small Step',
- 'Stills' => '-',
- 'Stop' => '',
- 'Stopped' => '',
- 'Stream' => '',
+ 'Stills' => 'Стоп-кадры',
+ 'Stop' => 'Остановить',
+ 'Stopped' => 'Остановлен',
+ 'Stream' => 'Поток',
'StreamReplayBuffer' => 'Stream Replay Image Buffer',
'Submit' => 'Submit',
- 'System' => '',
+ 'System' => 'Система',
'SystemLog' => 'System Log', // Added - 2011-06-16
'TargetColorspace' => 'Target colorspace', // Added - 2015-04-18
'Tele' => 'Tele',
'Thumbnail' => 'Thumbnail',
'Tilt' => 'Tilt',
- 'Time' => '',
- 'TimeDelta' => ' ',
- 'TimeStamp' => ' ',
+ 'Time' => 'Время',
+ 'TimeDelta' => 'Относительное время',
+ 'TimeStamp' => 'Метка времени',
'Timeline' => 'Timeline',
'TimelineTip1' => 'Pass your mouse over the graph to view a snapshot image and event details.', // Added 2013.08.15.
'TimelineTip2' => 'Click on the coloured sections of the graph, or the image, to view the event.', // Added 2013.08.15.
'TimelineTip3' => 'Click on the background to zoom in to a smaller time period based around your click.', // Added 2013.08.15.
'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // Added 2013.08.15.
- 'Timestamp' => ' ',
- 'TimestampLabelFormat' => ' ',
- 'TimestampLabelX' => 'X- ',
- 'TimestampLabelY' => 'Y- ',
+ 'Timestamp' => 'Метка времени',
+ 'TimestampLabelFormat' => 'Формат метки',
+ 'TimestampLabelX' => 'X-координата метки',
+ 'TimestampLabelY' => 'Y-координата метки',
'Today' => 'Today',
- 'Tools' => '',
+ 'Tools' => 'Инструменты',
'Total' => 'Total', // Added - 2011-06-16
- 'TotalBrScore' => '. ',
+ 'TotalBrScore' => 'Сумм. оценка',
'TrackDelay' => 'Track Delay',
'TrackMotion' => 'Track Motion',
- 'Triggers' => '',
+ 'Triggers' => 'Триггеры',
'TurboPanSpeed' => 'Turbo Pan Speed',
'TurboTiltSpeed' => 'Turbo Tilt Speed',
- 'Type' => '',
- 'Unarchive' => '. ',
+ 'Type' => 'Тип',
+ 'Unarchive' => 'Уд. из архива',
'Undefined' => 'Undefined', // Added - 2009-02-08
- 'Units' => '. ',
+ 'Units' => 'Ед. измерения',
'Unknown' => 'Unknown',
'Update' => 'Update',
- 'UpdateAvailable' => ' ZoneMinder',
- 'UpdateNotNecessary' => ' ',
+ 'UpdateAvailable' => 'Доступно обновление ZoneMinder',
+ 'UpdateNotNecessary' => 'Обновление не требуется',
'Updated' => 'Updated', // Added - 2011-06-16
'Upload' => 'Upload', // Added - 2011-08-23
- 'UseFilter' => ' ',
- 'UseFilterExprsPost' => ' ', // This is used at the end of the phrase 'use N filter expressions'
- 'UseFilterExprsPre' => '. ', // This is used at the beginning of the phrase 'use N filter expressions'
+ 'UseFilter' => 'Использовать фильтр',
+ 'UseFilterExprsPost' => ' выражений для фильтра', // This is used at the end of the phrase 'use N filter expressions'
+ 'UseFilterExprsPre' => 'Испол. ', // This is used at the beginning of the phrase 'use N filter expressions'
'UsedPlugins' => 'Used Plugins',
- 'User' => '',
- 'Username' => ' ',
- 'Users' => '',
+ 'User' => 'Пользователь',
+ 'Username' => 'Имя пользователя',
+ 'Users' => 'Пользователи',
'V4L' => 'V4L', // Added - 2015-04-18
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
- 'Value' => '',
- 'Version' => '',
- 'VersionIgnore' => ' ',
- 'VersionRemindDay' => ' ',
- 'VersionRemindHour' => ' ',
- 'VersionRemindNever' => ' ',
- 'VersionRemindWeek' => ' ',
- 'Video' => '',
+ 'Value' => 'Значение',
+ 'Version' => 'Версия',
+ 'VersionIgnore' => 'Игнорировать эту версию',
+ 'VersionRemindDay' => 'Напомнить через день',
+ 'VersionRemindHour' => 'Напомнить через час',
+ 'VersionRemindNever' => 'Не говорить о новых версиях',
+ 'VersionRemindWeek' => 'Напомнить через неделю',
+ 'Video' => 'Видео',
'VideoFormat' => 'Video Format',
- 'VideoGenFailed' => ' !',
+ 'VideoGenFailed' => 'Ошибка генерации видео!',
'VideoGenFiles' => 'Existing Video Files',
'VideoGenNoFiles' => 'No Video Files Found',
- 'VideoGenParms' => ' ',
+ 'VideoGenParms' => 'Параметры генерации видео',
'VideoGenSucceeded' => 'Video Generation Succeeded!',
- 'VideoSize' => ' ',
- 'View' => '',
- 'ViewAll' => '. ',
+ 'VideoSize' => 'Размер изображения',
+ 'View' => 'Просмотр',
+ 'ViewAll' => 'Просм. все',
'ViewEvent' => 'View Event',
- 'ViewPaged' => '. ',
+ 'ViewPaged' => 'Просм. постранично',
'Wake' => 'Wake',
- 'WarmupFrames' => ' ',
+ 'WarmupFrames' => 'Кадры разогрева',
'Watch' => 'Watch',
- 'Web' => '',
+ 'Web' => 'Интерфейс',
'WebColour' => 'Web Colour',
- 'Week' => '',
+ 'Week' => 'Неделя',
'White' => 'White',
'WhiteBalance' => 'White Balance',
'Wide' => 'Wide',
@@ -739,10 +740,10 @@ $SLANG = array(
'X10InputAlarmString' => 'X10 Input Alarm String',
'X10OutputAlarmString' => 'X10 Output Alarm String',
'Y' => 'Y',
- 'Yes' => '',
- 'YouNoPerms' => ' .',
- 'Zone' => '',
- 'ZoneAlarmColour' => ' (Red/Green/Blue)',
+ 'Yes' => 'Да',
+ 'YouNoPerms' => 'У вас не достаточно прав для доступа к этому ресурсу.',
+ 'Zone' => 'Зона',
+ 'ZoneAlarmColour' => 'Цвет тревоги (Red/Green/Blue)',
'ZoneArea' => 'Zone Area',
'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count',
'ZoneFilterSize' => 'Filter Width/Height (pixels)',
@@ -753,7 +754,7 @@ $SLANG = array(
'ZoneMinMaxPixelThres' => 'Min/Max Pixel Threshold (0-255)',
'ZoneMinderLog' => 'ZoneMinder Log', // Added - 2011-06-17
'ZoneOverloadFrames' => 'Overload Frame Ignore Count',
- 'Zones' => '',
+ 'Zones' => 'Зоны',
'Zoom' => 'Zoom',
'ZoomIn' => 'Zoom In',
'ZoomOut' => 'Zoom Out',
@@ -761,13 +762,13 @@ $SLANG = array(
// Complex replacements with formatting and/or placements, must be passed through sprintf
$CLANG = array(
- 'CurrentLogin' => ' : \'%1$s\'',
+ 'CurrentLogin' => 'Текущий пользователь: \'%1$s\'',
'EventCount' => '%1$s %2$s', // For example '37 Events' (from Vlang below)
- 'LastEvents' => ' %1$s %2$s', // For example 'Last 37 Events' (from Vlang below)
- 'LatestRelease' => ' : v%1$s, : v%2$s.',
+ 'LastEvents' => 'Последние %1$s %2$s', // For example 'Last 37 Events' (from Vlang below)
+ 'LatestRelease' => 'Последняя версия: v%1$s, у Вас установлена: v%2$s.',
'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below)
- 'MonitorFunction' => ' %1$s',
- 'RunningRecentVer' => ' ZoneMinder, v%s.',
+ 'MonitorFunction' => 'Функция монитора %1$s',
+ 'RunningRecentVer' => 'У вас установлена новейшая версия ZoneMinder, v%s.',
'VersionMismatch' => 'Version mismatch, system is version %1$s, database is %2$s.', // Added - 2011-05-25
);
@@ -807,8 +808,8 @@ $CLANG = array(
// Variable arrays expressing plurality, see the zmVlang description above
$VLANG = array(
- 'Event' => array( 1=>'', 2=>'', 3=>'' ),
- 'Monitor' => array( 1=>'', 2=>'', 3=>'' ),
+ 'Event' => array( 1=>'Событий', 2=>'Событие', 3=>'События' ),
+ 'Monitor' => array( 1=>'Мониторов', 2=>'Монитор', 3=>'Монитора' ),
);
// You will need to choose or write a function that can correlate the plurality string arrays
diff --git a/web/skins/classic/css/classic/export.css b/web/skins/classic/css/classic/export.css
index b9b542d5b..757b49057 100644
--- a/web/skins/classic/css/classic/export.css
+++ b/web/skins/classic/css/classic/export.css
@@ -1,7 +1,7 @@
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size:10px;
- font-weight: normal
+ font-weight: normal;
color: #333333;
}
diff --git a/web/skins/classic/css/dark/export.css b/web/skins/classic/css/dark/export.css
index b9b542d5b..757b49057 100644
--- a/web/skins/classic/css/dark/export.css
+++ b/web/skins/classic/css/dark/export.css
@@ -1,7 +1,7 @@
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size:10px;
- font-weight: normal
+ font-weight: normal;
color: #333333;
}
diff --git a/web/skins/classic/css/flat/export.css b/web/skins/classic/css/flat/export.css
index b9b542d5b..757b49057 100644
--- a/web/skins/classic/css/flat/export.css
+++ b/web/skins/classic/css/flat/export.css
@@ -1,7 +1,7 @@
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size:10px;
- font-weight: normal
+ font-weight: normal;
color: #333333;
}
diff --git a/web/skins/classic/css/flat/skin.css b/web/skins/classic/css/flat/skin.css
index 3a7ee575e..528eb6e4b 100644
--- a/web/skins/classic/css/flat/skin.css
+++ b/web/skins/classic/css/flat/skin.css
@@ -23,7 +23,7 @@
body {
font-family: "Open Sans", Verdana, Arial, Helvetica, sans-serif;
- font-size: 16px;
+ font-size: 13px;
color: #333333;
font-weight: 300;
text-align: center;
diff --git a/web/skins/classic/js/jquery-1.11.3.js b/web/skins/classic/js/jquery-1.11.3.js
new file mode 100644
index 000000000..6feb11086
--- /dev/null
+++ b/web/skins/classic/js/jquery-1.11.3.js
@@ -0,0 +1,10351 @@
+/*!
+ * jQuery JavaScript Library v1.11.3
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-04-28T16:19Z
+ */
+
+(function( global, factory ) {
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+ // For CommonJS and CommonJS-like environments where a proper window is present,
+ // execute the factory and get jQuery
+ // For environments that do not inherently posses a window with a document
+ // (such as Node.js), expose a jQuery-making factory as module.exports
+ // This accentuates the need for the creation of a real window
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//
+
+var deletedIds = [];
+
+var slice = deletedIds.slice;
+
+var concat = deletedIds.concat;
+
+var push = deletedIds.push;
+
+var indexOf = deletedIds.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+ version = "1.11.3",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android<4.1, IE<9
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num != null ?
+
+ // Return just the one element from the set
+ ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+ // Return all the elements in a clean array
+ slice.call( this );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: deletedIds.sort,
+ splice: deletedIds.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var src, copyIsArray, copy, name, options, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ /* jshint eqeqeq: false */
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ // parseFloat NaNs numeric-cast false positives (null|true|false|"")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ // adding 1 corrects loss of precision from parseFloat (#15100)
+ return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ isPlainObject: function( obj ) {
+ var key;
+
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Support: IE<9
+ // Handle iteration over inherited properties before own properties.
+ if ( support.ownLast ) {
+ for ( key in obj ) {
+ return hasOwn.call( obj, key );
+ }
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && jQuery.trim( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android<4.1, IE<9
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( indexOf ) {
+ return indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ while ( j < len ) {
+ first[ i++ ] = second[ j++ ];
+ }
+
+ // Support: IE<9
+ // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+ if ( len !== len ) {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var args, proxy, tmp;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: function() {
+ return +( new Date() );
+ },
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.0-pre
+ * http://sizzlejs.com/
+ *
+ * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-12-16
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // General-purpose constants
+ MAX_NEGATIVE = 1 << 31,
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf as it's faster than native
+ // http://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + characterEncoding + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+ rescape = /'|\\/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ };
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+ nodeType = context.nodeType;
+
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ if ( !seed && documentIsHTML ) {
+
+ // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document (jQuery #6963)
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getElementsByClassName ) {
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+ nid = old = expando;
+ newContext = context;
+ newSelector = nodeType !== 1 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return !!fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( div.parentNode ) {
+ div.parentNode.removeChild( div );
+ }
+ // release memory in IE
+ div = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = attrs.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ ( ~b.sourceIndex || MAX_NEGATIVE ) -
+ ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare, parent,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+ parent = doc.defaultView;
+
+ // Support: IE>8
+ // If iframe document is assigned to "document" variable and if iframe has been reloaded,
+ // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+ // IE6-8 do not support the defaultView property so parent will be undefined
+ if ( parent && parent !== parent.top ) {
+ // IE11 does not have attachEvent, so all must suffer
+ if ( parent.addEventListener ) {
+ parent.addEventListener( "unload", unloadHandler, false );
+ } else if ( parent.attachEvent ) {
+ parent.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* Support tests
+ ---------------------------------------------------------------------- */
+ documentIsHTML = !isXML( doc );
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( div ) {
+ div.className = "i";
+ return !div.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( div ) {
+ docElem.appendChild( div ).id = expando;
+ return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [ m ] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
+
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See http://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ docElem.appendChild( div ).innerHTML = "" +
+ "";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
+ if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibing-combinator selector` fails
+ if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( div ) {
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = doc.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ div.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( div.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch (e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (oldCache = outerCache[ dir ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ outerCache[ dir ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is no seed and only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+ // Should return 1, but returns 4 (following)
+ return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+ div.innerHTML = "";
+ return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+ div.innerHTML = "";
+ div.firstChild.setAttribute( "value", "" );
+ return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+ return div.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ /* jshint -W018 */
+ return !!qualifier.call( elem, i, elem ) !== not;
+ });
+
+ }
+
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ });
+
+ }
+
+ if ( typeof qualifier === "string" ) {
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+ });
+}
+
+jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 && elem.nodeType === 1 ?
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ }));
+};
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i,
+ ret = [],
+ self = this,
+ len = self.length;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = this.selector ? this.selector + " " + selector : selector;
+ return ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], false) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], true) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ init = jQuery.fn.init = function( selector, context ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return typeof rootjQuery.ready !== "undefined" ?
+ rootjQuery.ready( selector ) :
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.extend({
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+jQuery.fn.extend({
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && (pos ?
+ pos.index(cur) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector(cur, selectors)) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.unique(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ if ( this.length > 1 ) {
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ ret = jQuery.unique( ret );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+ }
+
+ return this.pushStack( ret );
+ };
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ firingLength = 0;
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( list && ( !fired || stack ) ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+
+
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+
+ } else if ( !(--remaining) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+};
+
+jQuery.extend({
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.triggerHandler ) {
+ jQuery( document ).triggerHandler( "ready" );
+ jQuery( document ).off( "ready" );
+ }
+ }
+});
+
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+
+ } else {
+ document.detachEvent( "onreadystatechange", completed );
+ window.detachEvent( "onload", completed );
+ }
+}
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+ detach();
+ jQuery.ready();
+ }
+}
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", completed );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", completed );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // detach all dom ready events
+ detach();
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+};
+
+
+var strundefined = typeof undefined;
+
+
+
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+ break;
+}
+support.ownLast = i !== "0";
+
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
+
+// Execute ASAP in case we need to set body.style.zoom
+jQuery(function() {
+ // Minified: var a,b,c,d
+ var val, div, body, container;
+
+ body = document.getElementsByTagName( "body" )[ 0 ];
+ if ( !body || !body.style ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ // Setup
+ div = document.createElement( "div" );
+ container = document.createElement( "div" );
+ container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+ body.appendChild( container ).appendChild( div );
+
+ if ( typeof div.style.zoom !== strundefined ) {
+ // Support: IE<8
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
+
+ support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
+ if ( val ) {
+ // Prevent IE 6 from affecting layout for positioned elements #11048
+ // Prevent IE from shrinking the body in IE 7 mode #12869
+ // Support: IE<8
+ body.style.zoom = 1;
+ }
+ }
+
+ body.removeChild( container );
+});
+
+
+
+
+(function() {
+ var div = document.createElement( "div" );
+
+ // Execute the test only if not already executed in another module.
+ if (support.deleteExpando == null) {
+ // Support: IE<9
+ support.deleteExpando = true;
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+ }
+
+ // Null elements to avoid leaks in IE.
+ div = null;
+})();
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+ var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+ nodeType = +elem.nodeType || 1;
+
+ // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+ return nodeType !== 1 && nodeType !== 9 ?
+ false :
+
+ // Nodes accept data unless otherwise specified; rejection can be conditional
+ !noData || noData !== true && elem.getAttribute("classid") === noData;
+};
+
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var ret, thisCache,
+ internalKey = jQuery.expando,
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ // Avoid exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( typeof name === "string" ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i,
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ } else {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+ }
+
+ i = name.length;
+ while ( i-- ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ /* jshint eqeqeq: false */
+ } else if ( support.deleteExpando || cache != cache.window ) {
+ /* jshint eqeqeq: true */
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+}
+
+jQuery.extend({
+ cache: {},
+
+ // The following elements (space-suffixed to avoid Object.prototype collisions)
+ // throw uncatchable exceptions if you attempt to set expando properties
+ noData: {
+ "applet ": true,
+ "embed ": true,
+ // ...but Flash objects (which have this classid) *can* handle expandos
+ "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return internalData( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ return internalRemoveData( elem, name );
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return internalData( elem, name, data, true );
+ },
+
+ _removeData: function( elem, name ) {
+ return internalRemoveData( elem, name, true );
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[0],
+ attrs = elem && elem.attributes;
+
+ // Special expections of .data basically thwart jQuery.access,
+ // so implement the relevant behavior ourselves
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE11+
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice(5) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ return arguments.length > 1 ?
+
+ // Sets one value
+ this.each(function() {
+ jQuery.data( this, key, value );
+ }) :
+
+ // Gets one value
+ // Try to fetch any internally stored data first
+ elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery._removeData( elem, type + "queue" );
+ jQuery._removeData( elem, key );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while ( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+ };
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+};
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+ // Minified: var a,b,c
+ var input = document.createElement( "input" ),
+ div = document.createElement( "div" ),
+ fragment = document.createDocumentFragment();
+
+ // Setup
+ div.innerHTML = "
a";
+
+ // IE strips leading whitespace when .innerHTML is used
+ support.leadingWhitespace = div.firstChild.nodeType === 3;
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ support.tbody = !div.getElementsByTagName( "tbody" ).length;
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ support.html5Clone =
+ document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>";
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ input.type = "checkbox";
+ input.checked = true;
+ fragment.appendChild( input );
+ support.appendChecked = input.checked;
+
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ // Support: IE6-IE11+
+ div.innerHTML = "";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ fragment.appendChild( div );
+ div.innerHTML = "";
+
+ // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+ // old WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<9
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+ support.noCloneEvent = true;
+ if ( div.attachEvent ) {
+ div.attachEvent( "onclick", function() {
+ support.noCloneEvent = false;
+ });
+
+ div.cloneNode( true ).click();
+ }
+
+ // Execute the test only if not already executed in another module.
+ if (support.deleteExpando == null) {
+ // Support: IE<9
+ support.deleteExpando = true;
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+ }
+})();
+
+
+(function() {
+ var i, eventName,
+ div = document.createElement( "div" );
+
+ // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
+ for ( i in { submit: true, change: true, focusin: true }) {
+ eventName = "on" + i;
+
+ if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+ div.setAttribute( eventName, "t" );
+ support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+ }
+ }
+
+ // Null elements to avoid leaks in IE.
+ div = null;
+})();
+
+
+var rformElems = /^(?:input|select|textarea)$/i,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+ var tmp, events, t, handleObjIn,
+ special, eventHandle, handleObj,
+ handlers, type, namespaces, origType,
+ elemData = jQuery._data( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+ var j, handleObj, tmp,
+ origCount, t, events,
+ special, handlers, type,
+ namespaces, origType,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery._removeData( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ var handle, ontype, cur,
+ bubbleType, special, tmp, i,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+ jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ try {
+ elem[ type ]();
+ } catch ( e ) {
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+ }
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, ret, handleObj, matched, j,
+ handlerQueue = [],
+ args = slice.call( arguments ),
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var sel, handleObj, matches, i,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG