diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e3944002..471066ac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Change Log +## [v1.29.0](https://github.com/ZoneMinder/ZoneMinder/tree/v1.29.0) (2016-02-03) +[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.29.0-rc2...v1.29.0) + +**Merged pull requests:** + +- 1253 zms quit cmd [\#1254](https://github.com/ZoneMinder/ZoneMinder/pull/1254) ([pliablepixels](https://github.com/pliablepixels)) +- Add Debug/Info lines reporting multi-server status [\#1252](https://github.com/ZoneMinder/ZoneMinder/pull/1252) ([connortechnology](https://github.com/connortechnology)) +- Do debian package mods [\#1244](https://github.com/ZoneMinder/ZoneMinder/pull/1244) ([pliablepixels](https://github.com/pliablepixels)) +- zmtrigger - process off+time delay condition [\#1240](https://github.com/ZoneMinder/ZoneMinder/pull/1240) ([knnniggett](https://github.com/knnniggett)) +- Multi server [\#1233](https://github.com/ZoneMinder/ZoneMinder/pull/1233) ([connortechnology](https://github.com/connortechnology)) +- remove Google open Sans external import [\#1232](https://github.com/ZoneMinder/ZoneMinder/pull/1232) ([connortechnology](https://github.com/connortechnology)) +- PTZ - Added autostop to Down command on FI8918W [\#1189](https://github.com/ZoneMinder/ZoneMinder/pull/1189) ([marcolino7](https://github.com/marcolino7)) + +## [v1.29.0-rc2](https://github.com/ZoneMinder/ZoneMinder/tree/v1.29.0-rc2) (2016-01-05) +[Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.29.0-rc1...v1.29.0-rc2) + +**Merged pull requests:** + +- Multi server [\#1223](https://github.com/ZoneMinder/ZoneMinder/pull/1223) ([connortechnology](https://github.com/connortechnology)) +- Multi server [\#1222](https://github.com/ZoneMinder/ZoneMinder/pull/1222) ([connortechnology](https://github.com/connortechnology)) +- Multi server [\#1217](https://github.com/ZoneMinder/ZoneMinder/pull/1217) ([connortechnology](https://github.com/connortechnology)) +- Multi server [\#1215](https://github.com/ZoneMinder/ZoneMinder/pull/1215) ([connortechnology](https://github.com/connortechnology)) +- Change log updates [\#1172](https://github.com/ZoneMinder/ZoneMinder/pull/1172) ([SteveGilvarry](https://github.com/SteveGilvarry)) + ## [v1.29.0-rc1](https://github.com/ZoneMinder/ZoneMinder/tree/v1.29.0-rc1) (2016-01-01) [Full Changelog](https://github.com/ZoneMinder/ZoneMinder/compare/v1.28.1...v1.29.0-rc1) @@ -328,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 fe1ea60b5..d219ac491 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # cmake_minimum_required (VERSION 2.6) project (zoneminder) -set(zoneminder_VERSION "1.29.1") +set(zoneminder_VERSION "1.30.2") # make API version a minor of ZM version set(zoneminder_API_VERSION "${zoneminder_VERSION}.1") 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 4aa63b1a6..fcd96bfd6 100644 --- a/README.md +++ b/README.md @@ -227,7 +227,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/configure.ac b/configure.ac index aca8b929e..d17ce6e9b 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ # For instructions on building with cmake, please see INSTALL # AC_PREREQ(2.59) -AC_INIT(zm,1.29.1,[http://www.zoneminder.com/forums/ - Please check FAQ first],zoneminder,http://www.zoneminder.com/downloads.html) +AC_INIT(zm,1.30.2,[http://www.zoneminder.com/forums/ - Please check FAQ first],zoneminder,http://www.zoneminder.com/downloads.html) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR(src/zm.h) AC_CONFIG_HEADERS(config.h) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index a60bc9c5c..0a56d37ac 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -227,6 +227,7 @@ CREATE TABLE `Filters` ( `AutoExecuteCmd` tinytext, `AutoDelete` tinyint(3) unsigned NOT NULL default '0', `Background` tinyint(1) unsigned NOT NULL default '0', + `Concurrent` tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (`Name`) ) ENGINE=@ZM_MYSQL_ENGINE@; @@ -414,6 +415,7 @@ INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1'); DROP TABLE IF EXISTS `Servers`; CREATE TABLE `Servers` ( `Id` int(10) unsigned NOT NULL auto_increment, + `Hostname` TEXT, `Name` varchar(64) NOT NULL default '', `State_Id` int(10) unsigned, PRIMARY KEY (`Id`) @@ -603,8 +605,9 @@ 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); -- -- 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.30.1.sql b/db/zm_update-1.30.1.sql new file mode 100644 index 000000000..298668e08 --- /dev/null +++ b/db/zm_update-1.30.1.sql @@ -0,0 +1,110 @@ +-- +-- This updates a 1.28.108 database to 1.28.109 +-- + +-- +-- Add Controls definition for Vivotek ePTZ +-- +INSERT INTO Controls +SELECT * FROM (SELECT NULL as Id, + 'Vivotek ePTZ' as Name, + 'Remote' as Type, + 'Vivotek_ePTZ' as Protocol, + 0 as CanWake, + 0 as CanSleep, + 1 as CanReset, + 1 as CanZoom, + 0 as CanAutoZoom, + 0 as CanZoomAbs, + 0 as CanZoomRel, + 1 as CanZoomCon, + 0 as MinZoomRange, + 0 as MaxZoomRange, + 0 as MinZoomStep, + 0 as MaxZoomStep, + 1 as HasZoomSpeed, + 0 as MinZoomSpeed, + 5 as MaxZoomSpeed, + 0 as CanFocus, + 0 as CanAutoFocus, + 0 as CanFocusAbs, + 0 as CanFocusRel, + 0 as CanFocusCon, + 0 as MinFocusRange, + 0 as MaxFocusRange, + 0 as MinFocusStep, + 0 as MaxFocusStep, + 0 as HasFocusSpeed, + 0 as MinFocusSpeed, + 0 as MaxFocusSpeed, + 0 as CanIris, + 0 as CanAutoIris, + 0 as CanIrisAbs, + 0 as CanIrisRel, + 0 as CanIrisCon, + 0 as MinIrisRange, + 0 as MaxIrisRange, + 0 as MinIrisStep, + 0 as MaxIrisStep, + 0 as HasIrisSpeed, + 0 as MinIrisSpeed, + 0 as MaxIrisSpeed, + 0 as CanGain, + 0 as CanAutoGain, + 0 as CanGainAbs, + 0 as CanGainRel, + 0 as CanGainCon, + 0 as MinGainRange, + 0 as MaxGainRange, + 0 as MinGainStep, + 0 as MaxGainStep, + 0 as HasGainSpeed, + 0 as MinGainSpeed, + 0 as MaxGainSpeed, + 0 as CanWhite, + 0 as CanAutoWhite, + 0 as CanWhiteAbs, + 0 as CanWhiteRel, + 0 as CanWhiteCon, + 0 as MinWhiteRange, + 0 as MaxWhiteRange, + 0 as MinWhiteStep, + 0 as MaxWhiteStep, + 0 as HasWhiteSpeed, + 0 as MinWhiteSpeed, + 0 as MaxWhiteSpeed, + 0 as HasPresets, + 0 as NumPresets, + 0 as HasHomePreset, + 0 as CanSetPresets, + 1 as CanMove, + 0 as CanMoveDiag, + 0 as CanMoveMap, + 0 as CanMoveAbs, + 0 as CanMoveRel, + 1 as CanMoveCon, + 1 as CanPan, + 0 as MinPanRange, + 0 as MaxPanRange, + 0 as MinPanStep, + 0 as MaxPanStep, + 1 as HasPanSpeed, + 0 as MinPanSpeed, + 5 as MaxPanSpeed, + 0 as HasTurboPan, + 0 as TurboPanSpeed, + 1 as CanTilt, + 0 as MinTiltRange, + 0 as MaxTiltRange, + 0 as MinTiltStep, + 0 as MaxTiltStep, + 1 as HasTiltSpeed, + 0 as MinTiltSpeed, + 5 as MaxTiltSpeed, + 0 as HasTurboTilt, + 0 as TurboTiltSpeed, + 0 as CanAutoScan, + 0 as NumScanPaths) AS tmp +WHERE NOT EXISTS ( + SELECT Name FROM Controls WHERE name = 'Vivotek ePTZ' +) LIMIT 1; diff --git a/db/zm_update-1.30.2.sql b/db/zm_update-1.30.2.sql new file mode 100644 index 000000000..7f5e6c0a8 --- /dev/null +++ b/db/zm_update-1.30.2.sql @@ -0,0 +1,21 @@ +-- +-- This updates a 1.30.1 database to 1.30.2 +-- + +-- +-- Update Filters table to have a Concurrent Column +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Filters' + AND table_schema = DATABASE() + AND column_name = 'Concurrent' + ) > 0, +"SELECT 'Column Concurrent already exists in Filters'", +"ALTER TABLE Filters ADD COLUMN `Concurrent` tinyint(1) unsigned NOT NULL default '0' AFTER Background" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/distros/fedora/CMakeLists.txt b/distros/fedora/CMakeLists.txt index f49d451f1..ba1b743ba 100644 --- a/distros/fedora/CMakeLists.txt +++ b/distros/fedora/CMakeLists.txt @@ -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 85088d868..0f88a9a16 100644 --- a/distros/fedora/README.Fedora +++ b/distros/fedora/README.Fedora @@ -44,12 +44,10 @@ New installs set during the previous step, you will need to create the ZoneMinder database and configure a database account for ZoneMinder to use: - mysql -u root -p < /usr/share/zoneminder/db/zm_create.sql - mysql -u root -p - mysql> grant all - on zm.* to 'zmuser'@localhost identified by 'zmpass'; - mysql> exit; - mysqladmin -u root -p reload + mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql + mysql -uroot -p -e "grant all on zm.* to \ + 'zmuser'@localhost identified by 'zmpass';" + mysqladmin -uroot -p reload The database account credentials, zmuser/zmpass, are arbitrary. Set them to anything that suits your envinroment. @@ -125,9 +123,7 @@ Upgrades have increased. Verify the zmuser database account has been granted all permission to the ZoneMinder database: - mysql -u root -p - mysql> show grants for zmuser@localhost; - mysql> exit; + mysql -uroot -p -e "show grants for zmuser@localhost;" See step 2 of the Installation section to add missing permissions. diff --git a/distros/fedora/zoneminder.f22.spec b/distros/fedora/zoneminder.f22.spec index 2396a868b..9beef6319 100644 --- a/distros/fedora/zoneminder.f22.spec +++ b/distros/fedora/zoneminder.f22.spec @@ -65,7 +65,7 @@ too much degradation of performance. %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_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 @@ -138,7 +138,7 @@ fi %files %defattr(-,root,root,-) -%doc AUTHORS COPYING README.md distros/fedora/README.Fedora distros/fedora/jscalendar-doc +%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 diff --git a/distros/fedora/zoneminder.f23.spec b/distros/fedora/zoneminder.f23.spec index da19c80ee..14b653117 100644 --- a/distros/fedora/zoneminder.f23.spec +++ b/distros/fedora/zoneminder.f23.spec @@ -65,7 +65,7 @@ too much degradation of performance. %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_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 @@ -138,7 +138,7 @@ fi %files %defattr(-,root,root,-) -%doc AUTHORS COPYING README.md distros/fedora/README.Fedora distros/fedora/jscalendar-doc +%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 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..849ef1073 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -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 e6e53bbc6..f0e627c90 100644 --- a/distros/redhat/README.CentOS +++ b/distros/redhat/README.CentOS @@ -30,12 +30,9 @@ New installs will need to create the ZoneMinder database and configure a database account for ZoneMinder to use: - mysql -uroot -p - mysql> create database zm; - mysql> grant all - on zm.* to 'zmuser'@localhost identified by 'zmpass'; - mysql> exit; mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql + mysql -uroot -p -e "grant all on zm.* to \ + 'zmuser'@localhost identified by 'zmpass';" mysqladmin -uroot -p reload The database account credentials, zmuser/zmpass, are arbitrary. Set them to @@ -117,9 +114,7 @@ New installs have increased. Verify the zmuser database account has been granted all permission to the ZoneMinder database: - mysql -u root -p - mysql> show grants for zmuser@localhost; - mysql> exit; + mysql -uroot -p -e "show grants for zmuser@localhost;" See step 2 of the Installation section to add missing permissions. diff --git a/distros/redhat/README.Centos7 b/distros/redhat/README.Centos7 index 451f4290b..f4566b01c 100644 --- a/distros/redhat/README.Centos7 +++ b/distros/redhat/README.Centos7 @@ -32,12 +32,10 @@ New installs will need to create the ZoneMinder database and configure a database account for ZoneMinder to use: - mysql -u root -p < /usr/share/zoneminder/db/zm_create.sql - mysql -u root -p - mysql> grant all - on zm.* to 'zmuser'@localhost identified by 'zmpass'; - mysql> exit; - mysqladmin -u root -p reload + mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql + mysql -uroot -p -e "grant all on zm.* to \ + 'zmuser'@localhost identified by 'zmpass';" + mysqladmin -uroot -p reload The database account credentials, zmuser/zmpass, are arbitrary. Set them to anything that suits your envinroment. @@ -112,9 +110,7 @@ Upgrades have increased. Verify the zmuser database account has been granted all permission to the ZoneMinder database: - mysql -u root -p - mysql> show grants for zmuser@localhost; - mysql> exit; + mysql -uroot -p -e "show grants for zmuser@localhost;" See step 2 of the Installation section to add missing permissions. diff --git a/distros/redhat/zoneminder.el6.spec b/distros/redhat/zoneminder.el6.spec index 97623addf..82406d431 100644 --- a/distros/redhat/zoneminder.el6.spec +++ b/distros/redhat/zoneminder.el6.spec @@ -130,7 +130,7 @@ rm -rf %{_docdir}/%{name}-%{version} %files %defattr(-,root,root,-) -%doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.CentOS distros/redhat/jscalendar-doc +%doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.CentOS distros/redhat/README.https distros/redhat/jscalendar-doc %doc distros/redhat/local_zoneminder.te %config %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm.conf %config(noreplace) %attr(644,root,root) %{_sysconfdir}/httpd/conf.d/zoneminder.conf diff --git a/distros/redhat/zoneminder.el7.spec b/distros/redhat/zoneminder.el7.spec index 60406b477..c350553b3 100644 --- a/distros/redhat/zoneminder.el7.spec +++ b/distros/redhat/zoneminder.el7.spec @@ -137,7 +137,7 @@ fi %files %defattr(-,root,root,-) -%doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.Centos7 distros/redhat/jscalendar-doc +%doc AUTHORS BUGS ChangeLog COPYING LICENSE NEWS README.md distros/redhat/README.Centos7 distros/redhat/README.https distros/redhat/jscalendar-doc %doc distros/redhat/local_zoneminder.te %config %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf %config(noreplace) %attr(644,root,root) /etc/httpd/conf.d/zoneminder.conf 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/ubuntu1410/changelog b/distros/ubuntu1410/changelog index a4b5302e7..8b68863fd 100644 --- a/distros/ubuntu1410/changelog +++ b/distros/ubuntu1410/changelog @@ -1,3 +1,21 @@ +zoneminder (1.29.111-trusty-2016020101) trusty; urgency=medium + + * Fix video download and use of Storage Areas + + -- Isaac Connor Mon, 01 Feb 2016 13:42:06 -0500 + +zoneminder (1.29.111-trusty-2016011401) trusty; urgency=medium + + * fix timeline view for storageareas + + -- Isaac Connor Thu, 14 Jan 2016 14:03:41 -0500 + +zoneminder (1.29.111-trusty-2016010801) trusty; urgency=medium + + * Add better debug and skip when event links are not just digits. Merge multi-server stuff from master. + + -- Isaac Connor Fri, 08 Jan 2016 10:37:16 -0500 + zoneminder (1.29.111-trusty-2016010401) trusty; urgency=medium * include fix to rotate image dimensions when applying a rotation diff --git a/distros/ubuntu1410/control b/distros/ubuntu1410/control index ba5b28653..4f979f8c2 100644 --- a/distros/ubuntu1410/control +++ b/distros/ubuntu1410/control @@ -86,7 +86,7 @@ Section: web Architecture: any Depends: zoneminder-core (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}, debconf, apache2, libapache2-mod-php5 | libapache2-mod-fcgid, - php5, php5-mysql | php5-mysqlnd + php5, php5-mysql | php5-mysqlnd, php5-gd Description: Essential files for ZoneMinder's web user interface ZoneMinder is a video camera security and surveillance solution. . 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/distros/ubuntu1504_cmake/control b/distros/ubuntu1504_cmake/control index 4ae391763..b61e7583a 100644 --- a/distros/ubuntu1504_cmake/control +++ b/distros/ubuntu1504_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 @@ -105,7 +105,7 @@ Package: zoneminder-doc Section: doc Architecture: all Multi-Arch: foreign -Depends: ${misc:Depends}, ${sphinxdoc:Depends} +Depends: ${misc:Depends}, ${sphinxdoc:Depends}, python-sphinx-rtd-theme | python3-sphinx-rtd-theme Suggests: www-browser Description: ZoneMinder documentation ZoneMinder is intended for use in single or multi-camera video security diff --git a/distros/ubuntu1504_cmake/zoneminder.logrotate b/distros/ubuntu1504_cmake/zoneminder.logrotate index ac7ce0795..18fc6b0a0 100644 --- a/distros/ubuntu1504_cmake/zoneminder.logrotate +++ b/distros/ubuntu1504_cmake/zoneminder.logrotate @@ -1,10 +1,10 @@ -/var/log/zm/*log { +/var/log/zm/*.log { missingok notifempty sharedscripts postrotate /usr/bin/zmpkg.pl logrot >>/dev/null 2>&1 || : endscript - weekly - rotate 3 + daily + rotate 7 } diff --git a/docs/conf.py b/docs/conf.py index 817ceebcc..9bda5df7b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -87,8 +87,6 @@ exclude_patterns = ['_build'] # output. They are ignored by default. #show_authors = False -import sphinx_rtd_theme - # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' @@ -115,7 +113,6 @@ html_theme = 'default' # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". 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/multiserver.rst b/docs/installationguide/multiserver.rst index aa6139551..e9ebefac2 100644 --- a/docs/installationguide/multiserver.rst +++ b/docs/installationguide/multiserver.rst @@ -21,7 +21,7 @@ New installs 1. Follow the normal instructions for your distro for installing ZoneMinder onto all the ZoneMinder servers in the normal fashion. Only a single database will be needed either as standalone, or on one of the ZoneMinder Servers. -2. On each ZoneMinder server, edit zm.conf. Find the ZM_DB_HOST variable and set it to the name or ip address of your Database Server. +2. On each ZoneMinder server, edit zm.conf. Find the ZM_DB_HOST variable and set it to the name or ip address of your Database Server. Find the ZM_SERVER_HOST and enter a name for this ZoneMinder server. Use a name easily recognizable by you. This name is not used by ZoneMinder for dns or any other form of network conectivity. 3. Copy the file /usr/share/zoneminder/db/zm_create.sql from one of the ZoneMinder Servers to the machine targeted as the Database Server. @@ -34,9 +34,7 @@ New installs :: mysql -u root -p < zm_create.sql - mysql -u root -p - mysql> grant all on zm.* to 'zmuser'@'%' identified by 'zmpass'; - mysql> exit; + mysql -uroot -p -e "grant all on zm.* to 'zmuser'@localhost identified by 'zmpass';" mysqladmin -u root -p reload The database account credentials, zmuser/zmpass, are arbitrary. Set them to anything that suits your environment. @@ -52,6 +50,6 @@ Additionally, you must also edit /usr/share/zoneminder/www/api/app/Config/databa NOTE: The location of this folder varies by distro. This folder is often found under "/var/lib/zoneminder/events" for RedHat based distros and "/var/cache/zoneminder/events" for Debain based distros. This folder is NOT a Symbolic Link! -10. Open your browser and point it to the web console on any of the ZoneMinder Servers (they will all be the same). Open Options, click the Servers tab,and populate this screen with all of your ZoneMinder Servers. +10. Open your browser and point it to the web console on any of the ZoneMinder Servers (they will all be the same). Open Options, click the Servers tab,and populate this screen with all of your ZoneMinder Servers. Each server has a field for its name and its hostname. The name is what you used for ZM_SERVER_HOST in step 2. The hostname is the network name or ip address ZoneMinder should use. 11. When creating a new Monitor, remember to select the server the camera will be assigned to from the Server drop down box. 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..f9181a95f 100644 --- a/docs/userguide/gettingstarted.rst +++ b/docs/userguide/gettingstarted.rst @@ -65,7 +65,7 @@ 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). * **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/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index c3bc792aa..0c5a82a30 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -104,6 +104,7 @@ BEGIN #$dbh->disconnect(); if ( ! exists $Config{ZM_SERVER_ID} ) { + $Config{ZM_SERVER_ID} = undef; $sth = $dbh->prepare_cached( 'SELECT * FROM Servers WHERE Name=?' ); if ( $Config{ZM_SERVER_NAME} ) { $res = $sth->execute( $Config{ZM_SERVER_NAME} ); @@ -114,7 +115,6 @@ BEGIN my $result = $sth->fetchrow_hashref(); $Config{ZM_SERVER_ID} = $$result{Id}; } - $Config{ZM_SERVER_ID} = undef; } } diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 9a065f8cf..703d47c30 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", diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm index 835f2943b..c9997526d 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm @@ -173,6 +173,7 @@ sub moveConDown Debug( "Move Down" ); my $cmd = "decoder_control.cgi?command=2"; $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); } #Left Arrow 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/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/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 32177bf07..807edce79 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -98,29 +98,28 @@ sub getEventPath { my $event = shift; + my $Storage = $event->Storage(); + my $event_path = ""; if ( $Config{ZM_USE_DEEP_STORAGE} ) { - $event_path = $Config{ZM_DIR_EVENTS} - .'/'.$event->{MonitorId} - .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $event_path = join('/', + $Storage->Path(), + $event->{MonitorId}, + strftime( "%y/%m/%d/%H/%M/%S", localtime($event->{Time}) - ) - ; + ), + ); } else { - $event_path = $Config{ZM_DIR_EVENTS} - .'/'.$event->{MonitorId} - .'/'.$event->{Id} - ; + $event_path = join('/', + $Storage->Path(), + $event->{MonitorId}, + $event->{Id}, + ); } - if ( index($Config{ZM_DIR_EVENTS},'/') != 0 ){ - $event_path = $Config{ZM_PATH_WEB} - .'/'.$event_path - ; - } return( $event_path ); } diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm index b8190d2a9..cef91df51 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm @@ -127,6 +127,7 @@ sub Execute { while( my $event = $sth->fetchrow_hashref() ) { push @results, $event; } + Debug($sql . ' returned ' . @results . ' events.' ); $sth->finish(); Debug("Loaded " . @results . " events for filter $_[0]{Name} using query ($sql)"); return @results; @@ -360,7 +361,6 @@ sub Sql { { $sql .= " limit 0,".$filter_expr->{limit}; } - Debug( "SQL:$sql\n" ); $self->{Sql} = $sql; } # end if has Sql return $self->{Sql}; diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index df3073796..285e6d270 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -212,6 +212,10 @@ MAIN: while( $loop ) { my $count = 0; foreach my $event_link ( @event_links ) { + if ( $event_link =~ /[^\d\.]/ ) { + Warning("Non-event link found $event_link in $day_dir, skipping"); + next; + } Debug( "Checking link $event_link" ); ( my $event = $event_link ) =~ s/^.*\.//; my $event_path = readlink( $event_link ); 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/zmfilter.pl.in b/scripts/zmfilter.pl.in index 5c605fd73..f3a8a8c83 100755 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -27,7 +27,7 @@ zmfilter.pl - ZoneMinder tool to filter events =head1 SYNOPSIS - zmfilter.pl [-f ,--filter=] | -v, --version + zmfilter.pl [-f ,--filter=] [--filter_id=] | -v, --version =head1 DESCRIPTION @@ -37,7 +37,9 @@ matching events. =head1 OPTIONS + -f{filter name}, --filter={filter name} - The name of a specific filter to run + --filter_id={filter id} - The id of a specific filter to run -v, --version - Print ZoneMinder version =cut @@ -60,8 +62,6 @@ use constant START_DELAY => 5; # How long to wait before starting @EXTRA_PERL_LIB@ use ZoneMinder; -require ZoneMinder::Event; -require ZoneMinder::Filter; use DBI; use POSIX; use Time::HiRes qw/gettimeofday/; @@ -70,6 +70,24 @@ use Getopt::Long; use autouse 'Pod::Usage'=>qw(pod2usage); use autouse 'Data::Dumper'=>qw(Dumper); +my $filter_name = ""; +my $filter_id; +my $version = 0; + +GetOptions( + 'filter=s' =>\$filter_name, + 'filter_id=s' =>\$filter_id, + 'version' =>\$version +) or pod2usage(-exitstatus => -1); + +if ( $version ) { + print ZoneMinder::Base::ZM_VERSION . "\n"; + exit(0); +} + +require ZoneMinder::Event; +require ZoneMinder::Filter; + use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|) ? $Config{ZM_DIR_EVENTS} : ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS}) @@ -135,20 +153,6 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL}; my $event_id = 0; -my $filter_parm = ""; -my $version = 0; - -# - -GetOptions( - 'filter=s' =>\$filter_parm, - 'version' =>\$version -) or pod2usage(-exitstatus => -1); - -if ( $version ) { - print ZoneMinder::Base::ZM_VERSION . "\n"; - exit(0); -} if ( ! EVENT_PATH ) { Error( "No event path defined. Config was $Config{ZM_DIR_EVENTS}\n" ); @@ -159,39 +163,42 @@ chdir( EVENT_PATH ); my $dbh = zmDbConnect(); -if ( $filter_parm ) -{ - Info( "Scanning for events using filter '$filter_parm'\n" ); -} -else -{ +if ( $filter_name ) { + Info( "Scanning for events using filter '$filter_name'\n" ); +} elsif ( $filter_id ) { + Info( "Scanning for events using filter id '$filter_id'\n" ); +} else { Info( "Scanning for events\n" ); } -if ( !$filter_parm ) -{ +if ( ! ( $filter_name or $filter_id ) ) { sleep( START_DELAY ); } my $filters; my $last_action = 0; -while( 1 ) -{ +while( 1 ) { my $now = time; - if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) - { + if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) { Debug( "Reloading filters\n" ); $last_action = $now; - $filters = getFilters( $filter_parm ); + $filters = getFilters( { Name=>$filter_name, Id=>$filter_id } ); } - foreach my $filter ( @$filters ) - { - checkFilter( $filter ); + foreach my $filter ( @$filters ) { + if ( $$filter{Concurrent} and ! ( $filter_id or $filter_name ) ) { + my ( $proc ) = $0 =~ /(\S+)/; + my ( $id ) = $$filter{Id} =~ /(\d+)/; + Debug("Running concurrent filter process $proc --filter_id $$filter{Id} => $id for $$filter{Name}"); + + system( qq`$proc --filter "$$filter{Name}" &` ); + } else { + checkFilter( $filter ); + } } - last if ( $filter_parm ); + last if ( $filter_name or $filter_id ); Debug( "Sleeping for $delay seconds\n" ); sleep( $delay ); @@ -199,16 +206,18 @@ while( 1 ) sub getFilters { - my $filter_name = shift; + my $sql_filters = @_ ? shift : {}; + my @sql_values; my @filters; my $sql = "SELECT * FROM Filters WHERE"; - if ( $filter_name ) - { + if ( $$sql_filters{Name} ) { $sql .= " Name = ? and"; - } - else - { + push @sql_values, $$sql_filters{Name}; + } elsif ( $$sql_filters{Id} ) { + $sql .= " Id = ? and"; + push @sql_values, $$sql_filters{Id}; + } else { $sql .= " Background = 1 and"; } $sql .= "( AutoArchive = 1 @@ -221,17 +230,8 @@ sub getFilters ) ORDER BY Name"; my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res; - if ( $filter_name ) - { - $res = $sth->execute( $filter_name ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - } - else - { - $res = $sth->execute() - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - } + my $res = $sth->execute( @sql_values ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) { my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter ); @@ -245,7 +245,12 @@ sub getFilters push( @filters, $filter ); } $sth->finish(); - Debug( "Got " . @filters . " filters" ); + if ( ! @filters ) { + Error("No filter found for $sql with values(@sql_values)"); + } else { + Debug( "Got " . @filters . " filters" ); + } + return( \@filters ); } @@ -530,7 +535,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/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 2d0afb13c..55166a492 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -504,22 +504,11 @@ sub handleMessage Info( "Set monitor to $state\n" ); if ( $delay ) { - my $action_time = time()+$delay; my $action_text = $id."|".( ($state eq "enable") ? "disable" : "enable" - ) - ; - my $action_array = $actions{$action_time}; - if ( !$action_array ) - { - $action_array = $actions{$action_time} = []; - } - push( @$action_array, { connection=>$connection, - message=>$action_text - } - ); - Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); + ); + handleDelay($delay, $connection, $action_text); } } elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) @@ -534,43 +523,33 @@ sub handleMessage zmTriggerEventOn( $monitor, $score, $cause, $text ); zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); Info( "Trigger '$trigger' '$cause'\n" ); + if ( $delay ) + { + my $action_text = $id."|cancel"; + handleDelay($delay, $connection, $action_text); + } } elsif ( $trigger eq "off" ) { - my $last_event = zmGetLastEvent( $monitor ); - zmTriggerEventOff( $monitor ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger'\n" ); - # Wait til it's finished - while( zmInAlarm( $monitor ) - && ($last_event == zmGetLastEvent( $monitor )) - ) + if ( $delay ) { - # Tenth of a second - usleep( 100000 ); - } + my $action_text = $id."|off|0|".$cause."|".$text; + handleDelay($delay, $connection, $action_text); + } else { + my $last_event = zmGetLastEvent( $monitor ); + zmTriggerEventOff( $monitor ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Trigger '$trigger'\n" ); + # Wait til it's finished + while( zmInAlarm( $monitor ) + && ($last_event == zmGetLastEvent( $monitor )) + ) + { + # Tenth of a second + usleep( 100000 ); + } zmTriggerEventCancel( $monitor ); - } - else - { - Info( "Trigger '$trigger'\n" ); - zmTriggerEventCancel( $monitor ); - } - if ( $delay ) - { - my $action_time = time()+$delay; - #my $action_text = $id."|cancel|0|".$cause."|".$text; - my $action_text = $id."|cancel"; - my $action_array = $actions{$action_time}; - if ( !$action_array ) - { - $action_array = $actions{$action_time} = []; } - push( @$action_array, { connection=>$connection, - message=>$action_text - } - ); - Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); } } elsif( $action eq "cancel" ) @@ -590,5 +569,23 @@ sub handleMessage } } # end sub handleMessage +sub handleDelay +{ + my $delay = shift; + my $connection = shift; + my $action_text = shift; + + my $action_time = time()+$delay; + my $action_array = $actions{$action_time}; + if ( !$action_array ) + { + $action_array = $actions{$action_time} = []; + } + push( @$action_array, { connection=>$connection, + message=>$action_text + } + ); + Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); +} 1; __END__ 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_config.cpp b/src/zm_config.cpp index 5521b5a14..8d293906c 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -115,6 +115,7 @@ void zmLoadConfig() if ( ! staticConfig.SERVER_ID ) { if ( ! staticConfig.SERVER_NAME.empty() ) { + Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() ); std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() ); if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { staticConfig.SERVER_ID = atoi(dbrow[0]); @@ -124,6 +125,7 @@ void zmLoadConfig() } // end if has SERVER_NAME } else if ( staticConfig.SERVER_NAME.empty() ) { + Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID ); std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID ); if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { @@ -133,6 +135,11 @@ void zmLoadConfig() } } + if ( ! staticConfig.SERVER_ID ) { + Info( "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 ); + } } StaticConfig staticConfig; diff --git a/src/zm_event.cpp b/src/zm_event.cpp index bcbc3989a..8a4d54f3c 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -1095,6 +1095,11 @@ void EventStream::processCommand( const CmdMsg *msg ) Debug( 1, "Got QUERY command, sending STATUS" ); break; } + case CMD_QUIT : + { + Info ("User initiated exit - CMD_QUIT"); + break; + } default : { // Do nothing, for now @@ -1132,6 +1137,9 @@ void EventStream::processCommand( const CmdMsg *msg ) exit( -1 ); } } + // quit after sending a status, if this was a quit request + if ((MsgCommand)msg->msg_data[0]==CMD_QUIT) + exit(0); updateFrameRate( (double)event_data->frame_count/event_data->duration ); } diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 7f8e9e2d9..6f3d7ca5d 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2062,9 +2062,9 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose sql += "'"; } if ( staticConfig.SERVER_ID ) { -Debug( 1, "Server ID %d", staticConfig.SERVER_ID ); sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); } + Debug( 1, "Loading Local Monitors with %s", sql.c_str() ); MYSQL_RES *result = zmDbFetch( sql.c_str() ); if ( !result ) { @@ -2246,6 +2246,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c sql += stringtf(" AND Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); } + Debug( 1, "Loading Remote Monitors with %s", sql.c_str() ); MYSQL_RES *result = zmDbFetch( sql.c_str() ); if ( !result ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); @@ -2426,6 +2427,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu if ( staticConfig.SERVER_ID ) { sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); } + Debug( 1, "Loading File Monitors with %s", sql.c_str() ); MYSQL_RES *result = zmDbFetch( sql.c_str() ); if ( !result ) { @@ -2570,6 +2572,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose if ( staticConfig.SERVER_ID ) { sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); } + Debug( 1, "Loading FFMPEG Monitors with %s", sql.c_str() ); MYSQL_RES *result = zmDbFetch( sql.c_str() ); if ( ! result ) { Error( "Cannot load FfmpegMonitors" ); @@ -3937,6 +3940,11 @@ void MonitorStream::processCommand( const CmdMsg *msg ) Debug( 1, "Got SCALE command, to %d", scale ); break; } + case CMD_QUIT : + { + Info ("User initiated exit - CMD_QUIT"); + break; + } case CMD_QUERY : { Debug( 1, "Got QUERY command, sending STATUS" ); @@ -4002,6 +4010,10 @@ void MonitorStream::processCommand( const CmdMsg *msg ) } } + // quit after sending a status, if this was a quit request + if ((MsgCommand)msg->msg_data[0]==CMD_QUIT) + exit(0); + updateFrameRate( monitor->GetFPS() ); } 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/zm_stream.h b/src/zm_stream.h index 9936688a8..4f6442725 100644 --- a/src/zm_stream.h +++ b/src/zm_stream.h @@ -57,7 +57,7 @@ protected: } DataMsg; typedef enum { MSG_CMD=1, MSG_DATA_WATCH, MSG_DATA_EVENT } MsgType; - typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUERY=99 } MsgCommand; + typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUIT, CMD_QUERY=99 } MsgCommand; protected: Monitor *monitor; diff --git a/src/zmf.cpp b/src/zmf.cpp index 6873488ad..52fa06cf1 100644 --- a/src/zmf.cpp +++ b/src/zmf.cpp @@ -275,7 +275,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 b7a97a0a6..2b4e88f54 100755 --- a/utils/do_debian_package.sh +++ b/utils/do_debian_package.sh @@ -1,18 +1,45 @@ #!/bin/bash + +if [ "$1" == "clean" ]; then + +read -p "Do you really want to delete existing packages? [y/N]" +[[ $REPLY == [yY] ]] && { rm -fr zoneminder*.build zoneminder*.changes zoneminder*.deb; echo "Existing package files deleted"; } || { echo "Packages have NOT been deleted"; } +exit; + +fi + + DATE=`date -R` DISTRO=$1 SNAPSHOT=$2 +if [ "$SNAPSHOT" == "stable" ]; then +SNAPSHOT=""; +fi; + + TYPE=$3 if [ "$TYPE" == "" ]; then TYPE="source"; fi; +BRANCH=$4 + if [ ! -d 'zoneminder_release' ]; then -git clone https://github.com/ZoneMinder/ZoneMinder.git zoneminder_release + git clone https://github.com/ZoneMinder/ZoneMinder.git zoneminder_release +fi; +if [ "$BRANCH" != "" ]; then + cd zoneminder_release + if [ "$BRANCH" == "stable" ]; then + BRANCH=$(git describe --tags $(git rev-list --tags --max-count=1)); + echo "Latest stable branch is $BRANCH"; + + fi + git checkout $BRANCH + cd ../ fi; VERSION=`cat zoneminder_release/version` if [ $VERSION == "" ]; then -exit 1; + exit 1; fi; echo "Doing $TYPE release zoneminder_$VERSION-$DISTRO-$SNAPSHOT"; mv zoneminder_release zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig @@ -20,28 +47,45 @@ cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig git submodule init git submodule update --init --recursive if [ $DISTRO == "trusty" ]; then -cp -r distros/ubuntu1204_cmake debian +ln -sf distros/ubuntu1204_cmake debian else -cp -r distros/ubuntu1504_cmake debian +ln -sf distros/ubuntu1504_cmake debian fi; +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 -rm .gitignore -cd ../ -tar zcf zoneminder_$VERSION-$DISTRO.orig.tar.gz zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig -cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig +#rm -rf .git +#rm .gitignore +#cd ../ +#tar zcf zoneminder_$VERSION-$DISTRO.orig.tar.gz zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig +#cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig if [ $TYPE == "binary" ]; then -debuild -k52C7377E + debuild else -debuild -S -sa -k52C7377E + if [ $TYPE == "local" ]; then + debuild -i -us -uc -b + else + debuild -S -sa + fi; fi; + cd ../ -rm -fr zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig + +read -p "Do you want to keep the checked out version of Zoneminder (incase you want to modify it later) [y/N]" +[[ $REPLY == [yY] ]] && { mv zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig zoneminder_release; echo "The checked out copy is preserved in zoneminder_release"; } || { rm -fr zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig; echo "The checked out copy has been deleted"; } +echo "Done!" + + + 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/version b/version index 83cf0d951..d1eaa3ba0 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.29.1 +1.30.2 diff --git a/web/includes/Event.php b/web/includes/Event.php new file mode 100644 index 000000000..cd4f831d8 --- /dev/null +++ b/web/includes/Event.php @@ -0,0 +1,72 @@ + $v) { + $this->{$k} = $v; + } + } else { + Error("No row for Event " . $IdOrRow ); + } + } // end function __construct + public function Storage() { + return new Storage( $this->{'StorageId'} ); + } + public function __call( $fn, array $args){ + if(isset($this->{$fn})){ + return $this->{$fn}; + #array_unshift($args, $this); + #call_user_func_array( $this->{$fn}, $args); + } + } + + public function Path() { + $Storage = $this->Storage(); + return $Storage->Path().'/'.$this->Relative_Path(); + } + public function Relative_Path() { + $event_path = ""; + + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = + $this->{'MonitorId'} + .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $this->{'Time'} + ) + ; + } + else + { + $event_path = + $this->{'MonitorId'} + .'/'.$this->{'Id'} + ; + } + + return( $event_path ); + + } + +} + + +?> diff --git a/web/includes/Makefile.am b/web/includes/Makefile.am index 32abb2cdd..3ef2528b7 100644 --- a/web/includes/Makefile.am +++ b/web/includes/Makefile.am @@ -6,6 +6,7 @@ web_DATA = \ config.php dist_web_DATA = \ + Event.php \ Monitor.php \ Server.php \ Storage.php \ diff --git a/web/includes/Storage.php b/web/includes/Storage.php index 7928fe041..1820b977d 100644 --- a/web/includes/Storage.php +++ b/web/includes/Storage.php @@ -36,5 +36,14 @@ class Storage { #call_user_func_array( $this->{$fn}, $args); } } + public static function find_all() { + $storage_areas = array(); + $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name'); + $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' ); + foreach ( $results as $row => $obj ) { + $storage_areas[] = $obj; + } + return $storage_areas; + } } ?> diff --git a/web/includes/actions.php b/web/includes/actions.php index bd07da509..75d8b95fd 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -181,6 +181,8 @@ if ( !empty($action) ) $sql .= ", AutoDelete = ".dbEscape($_REQUEST['autoDelete']); if ( !empty($_REQUEST['background']) ) $sql .= ", Background = ".dbEscape($_REQUEST['background']); + if ( !empty($_REQUEST['concurrent']) ) + $sql .= ", Concurrent = ".dbEscape($_REQUEST['concurrent']); dbQuery( $sql ); $refreshParent = true; } diff --git a/web/includes/functions.php b/web/includes/functions.php index 30b183385..14a8d778e 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -792,7 +792,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/en_gb.php b/web/lang/en_gb.php index 82c089c11..705505002 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -87,6 +87,7 @@ $SLANG = array( 'Actual' => 'Actual', 'AddNewControl' => 'Add New Control', 'AddNewMonitor' => 'Add New Monitor', + 'AddNewServer' => 'Add New Server', 'AddNewUser' => 'Add New User', 'AddNewZone' => 'Add New Zone', 'Alarm' => 'Alarm', @@ -232,6 +233,7 @@ $SLANG = array( 'Close' => 'Close', 'Colour' => 'Colour', 'Command' => 'Command', + 'ConcurrentFilter' => 'Run filter concurrently', 'Config' => 'Config', 'ConfiguredFor' => 'Configured for', 'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?', @@ -385,6 +387,7 @@ $SLANG = array( 'HighBW' => 'High B/W', 'High' => 'High', 'Home' => 'Home', + 'Hostname' => 'Hostname', 'Hour' => 'Hour', 'Hue' => 'Hue', 'Id' => 'Id', 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.

', // Added - 2015-04-18 - 'OpEq' => 'ÒÁ×ÎÏ', - 'OpGt' => 'ÂÏÌØÛÅ', - 'OpGtEq' => 'ÂÏÌØÛÅ ÌÉÂÏ ÒÁ×ÎÏ', - 'OpIn' => '× ÓÐÉÓËÅ', - 'OpLt' => 'ÍÅÎØÛÅ', - 'OpLtEq' => 'ÍÅÎØÛÅ ÉÌÉ ÒÁ×ÎÏ', - 'OpMatches' => 'ÓÏ×ÐÁÄÁÅÔ', - 'OpNe' => 'ÎÅ ÒÁ×ÎÏ', - 'OpNotIn' => 'ÎÅ × ÓÐÉÓËÅ', - 'OpNotMatches' => 'ÎÅ ÓÏ×ÐÁÄÁÅÔ', + 'OpEq' => 'равно', + 'OpGt' => 'больше', + 'OpGtEq' => 'больше либо равно', + 'OpIn' => 'в ÑпиÑке', + 'OpLt' => 'меньше', + 'OpLtEq' => 'меньше или равно', + 'OpMatches' => 'Ñовпадает', + 'OpNe' => 'не равно', + 'OpNotIn' => 'не в ÑпиÑке', + 'OpNotMatches' => 'не Ñовпадает', 'Open' => 'Open', 'OptionHelp' => 'OptionHelp', - 'OptionRestartWarning' => 'üÔÉ ÉÚÍÅÎÅÎÉÑ ÐÏÄÅÊÓÔ×ÕÀÔ ÔÏÌØËÏ ÐÏÓÌÅ ÐÅÒÅÚÁÐÕÓËÁ ÐÒÏÇÒÁÍÍÙ.', - 'Options' => 'ïÐÃÉÉ', - 'OrEnterNewName' => 'ÉÌÉ ××ÅÄÉÔÅ ÎÏ×ÏÅ ÉÍÑ', + 'OptionRestartWarning' => 'Эти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´ÐµÐ¹Ñтвуют только поÑле перезапуÑка программы.', + 'Options' => 'Опции', + 'OrEnterNewName' => 'или введите новое имÑ', 'Order' => 'Order', - 'Orientation' => 'ïÒÉÅÎÔÁÃÉÑ', + 'Orientation' => 'ОриентациÑ', 'Out' => 'Out', - 'OverwriteExisting' => 'ðÅÒÅÚÁÐÉÓÁÔØ ÓÕÝÅÓÔ×ÕÀÝÅÅ', - 'Paged' => 'ðÏ ÓÔÒÁÎÉÃÁÍ', + 'OverwriteExisting' => 'ПерезапиÑать ÑущеÑтвующее', + 'Paged' => 'По Ñтраницам', 'Pan' => 'Pan', 'PanLeft' => 'Pan Left', 'PanRight' => 'Pan Right', 'PanTilt' => 'Pan/Tilt', - 'Parameter' => 'ðÁÒÁÍÅÒ', - 'Password' => 'ðÁÒÏÌØ', - 'PasswordsDifferent' => 'ðÁÒÏÌÉ ÎÅ ÓÏ×ÐÁÄÁÀÔ', - 'Paths' => 'ðÕÔÉ', + 'Parameter' => 'Парамер', + 'Password' => 'Пароль', + 'PasswordsDifferent' => 'Пароли не Ñовпадают', + 'Paths' => 'Пути', 'Pause' => 'Pause', 'Phone' => 'Phone', - 'PhoneBW' => 'ôÅÌÅÆÏÎÎÁÑ ÌÉÎÉÑ', + 'PhoneBW' => 'Ð¢ÐµÐ»ÐµÑ„Ð¾Ð½Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ', 'Pid' => 'PID', // Added - 2011-06-16 'PixelDiff' => 'Pixel Diff', - 'Pixels' => '× ÐÉËÓÅÌÑÈ', + 'Pixels' => 'в пикÑелÑÑ…', 'Play' => 'Play', 'PlayAll' => 'Play All', - 'PleaseWait' => 'ðÏÖÁÌÕÊÓÔÁ ÐÏÄÏÖÄÉÔÅ', + 'PleaseWait' => 'ПожалуйÑта подождите', 'Plugins' => 'Plugins', 'Point' => 'Point', - 'PostEventImageBuffer' => 'âÕÆÅÒ ÐÏÓÌÅ ÓÏÂÙÔÉÑ', - 'PreEventImageBuffer' => 'âÕÆÅÒ ÄÏ ÓÏÂÙÔÉÑ', + 'PostEventImageBuffer' => 'Буфер поÑле ÑобытиÑ', + 'PreEventImageBuffer' => 'Буфер до ÑобытиÑ', 'PreserveAspect' => 'Preserve Aspect Ratio', 'Preset' => 'Preset', 'Presets' => 'Presets', - 'Prev' => 'ðÒÅÄ.', + 'Prev' => 'Пред.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

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 6a871c416..528eb6e4b 100644 --- a/web/skins/classic/css/flat/skin.css +++ b/web/skins/classic/css/flat/skin.css @@ -21,11 +21,9 @@ * Primary look and feel styles */ -@import url("https://fonts.googleapis.com/css?family=Open+Sans:200,200italic,300,300italic,400,400italic,600,600italic,700"); - 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/dark.js b/web/skins/classic/js/dark.js index 76a83b298..b3e63245a 100644 --- a/web/skins/classic/js/dark.js +++ b/web/skins/classic/js/dark.js @@ -47,7 +47,7 @@ var popupSizes = { 'image': { 'addWidth': 48, 'addHeight': 80 }, 'log': { 'width': 1080, 'height': 720 }, 'login': { 'width': 720, 'height': 480 }, - 'logout': { 'width': 260, 'height': 100 }, + 'logout': { 'width': 260, 'height': 150 }, 'monitor': { 'width': 600, 'height': 780 }, 'monitorpreset':{ 'width': 440, 'height': 200 }, 'monitorprobe': { 'width': 500, 'height': 240 }, diff --git a/web/skins/classic/js/flat.js b/web/skins/classic/js/flat.js index 0ed7c55b0..aa0233783 100644 --- a/web/skins/classic/js/flat.js +++ b/web/skins/classic/js/flat.js @@ -47,7 +47,7 @@ var popupSizes = { 'image': { 'addWidth': 48, 'addHeight': 80 }, 'log': { 'width': 1080, 'height': 720 }, 'login': { 'width': 720, 'height': 480 }, - 'logout': { 'width': 260, 'height': 100 }, + 'logout': { 'width': 260, 'height': 150 }, 'monitor': { 'width': 600, 'height': 780 }, 'monitorpreset':{ 'width': 440, 'height': 200 }, 'monitorprobe': { 'width': 500, 'height': 240 }, diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 8f30070e0..53479787f 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -20,6 +20,9 @@ require_once('includes/Server.php'); $servers = Server::find_all(); +require_once('includes/Storage.php'); +$storage_areas = Storage::find_all(); +$show_storage_areas = count($storage_areas) > 1 and canEdit( 'System' ) ? 1 : 0; $eventCounts = array( array( @@ -212,7 +215,11 @@ if ( canView( 'Stream' ) && $cycleCount > 1 ) { $cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0; ?> -
 / 
+
+  /  +  /  + +
- 1 ) { ?> + + + + - + @@ -287,7 +301,7 @@ for ( $i = 0; $i < count($eventCounts); $i++ ) foreach( $displayMonitors as $monitor ) { ?> - + '.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'', canEdit( 'Monitors' ) ) ?> - 1 ) { ?> + Name(); @@ -336,6 +350,12 @@ echo $Server->Name();   + + Name(); +?> + checked="checked"/>

+

+ checked="checked"/> +

disabled="disabled"/>
diff --git a/web/skins/classic/views/js/timeline.js b/web/skins/classic/views/js/timeline.js index 89d2ecd34..1e01706e3 100644 --- a/web/skins/classic/views/js/timeline.js +++ b/web/skins/classic/views/js/timeline.js @@ -112,7 +112,7 @@ function previewEvent( eventId, frameId ) function loadEventImage( imagePath, eid, fid, width, height ) { var imageSrc = $('imageSrc'); - imageSrc.setProperty( 'src', imagePrefix+imagePath ); + imageSrc.setProperty( 'src', imagePrefix + '&eid='+eid+'&fid='+fid ); imageSrc.removeEvent( 'click' ); imageSrc.addEvent( 'click', showEvent.pass( [ eid, fid, width, height ] ) ); var eventData = $('eventData'); diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 31ffd9232..4568e974a 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -804,7 +804,7 @@ switch ( $tab ) elseif ( $newMonitor['Type'] == "Remote" ) { ?> - + -  () checked="checked"/> + > () checked="checked"/> diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index fc86ad64b..e2e5e7b9d 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -113,7 +113,7 @@ foreach ( $monitors as $monitor ) if ( !isset( $scale ) ) $scale = reScale( SCALE_BASE, $monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ); ?> -
+
0 "; + +// This program only calls itself with the time range involved -- it does all monitors (the user can see, in the called group) all the time + +if ( !empty($user['MonitorIds']) ) +{ + $monFilterSql = ' AND M.Id IN ('.$user['MonitorIds'].')'; + + $eventsSql .= $monFilterSql; + $monitorsSQL .= $monFilterSql; + $frameSql .= $monFilterSql; +} + +// Parse input parameters -- note for future, validate/clean up better in case we don't get called from self. +// Live overrides all the min/max stuff but it is still processed + +// The default (nothing at all specified) is for 1 hour so we do not read the whole database + + +if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) +{ + $maxTime=strftime("%c",time()); + $minTime=strftime("%c",time() - 3600); +} +if ( isset($_REQUEST['minTime']) ) + $minTime = validHtmlStr($_REQUEST['minTime']); + +if ( isset($_REQUEST['maxTime']) ) + $maxTime = validHtmlStr($_REQUEST['maxTime']); + +// AS a special case a "all" is passed in as an exterme interval - if so , clear them here and let the database query find them + +if ( (strtotime($maxTime) - strtotime($minTime))/(365*24*3600) > 30 ) // test years +{ + $minTime=null; + $maxTime=null; +} + +$fitMode=1; +if (isset($_REQUEST['fit']) && $_REQUEST['fit']=='0' ) + $fitMode=0; + +if ( isset($_REQUEST['scale']) ) + $defaultScale=validHtmlStr($_REQUEST['scale']); +else + $defaultScale=1; + +$speeds=[0, 0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2, 3, 5, 10, 20, 50]; + +if (isset($_REQUEST['speed']) ) + $defaultSpeed=validHtmlStr($_REQUEST['speed']); +else + $defaultSpeed=1; + +$speedIndex=5; // default to 1x +for ($i=0; $i + + +
+ +
+ + step=0.10 width=20% onchange='setScale(this.value)' oninput='showScale(this.value)'/> + x +
+
+ + value= step=1 wdth=20% onchange='setSpeed(this.value)' oninput='showSpeed(this.value)'/> + fps +
+
+ + + + + + + + + +
+
+ + + + +
+\n"; +foreach ($monitors as $m) +{ + { + echo "No Canvas Support!!\n"; + } +} +echo "
\n"; +echo "

evaluating fps

\n"; +echo " + +
+ + diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index fa48c9b2e..249abeeaa 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -222,6 +222,7 @@ elseif ( $tab == "users" ) + @@ -229,6 +230,7 @@ elseif ( $tab == "users" ) + disabled="disabled"/> diff --git a/web/skins/classic/views/server.php b/web/skins/classic/views/server.php index fd22bf367..83df0501e 100644 --- a/web/skins/classic/views/server.php +++ b/web/skins/classic/views/server.php @@ -52,11 +52,11 @@ xhtmlHeaders(__FILE__, translate('Server')." - ".$newServer['Name'] ); - + - + diff --git a/web/skins/classic/views/video.php b/web/skins/classic/views/video.php index 34537f0b2..52257fbc7 100644 --- a/web/skins/classic/views/video.php +++ b/web/skins/classic/views/video.php @@ -24,6 +24,8 @@ if ( !canView( 'Events' ) ) return; } +require_once('includes/Event.php'); + $eid = validInt($_REQUEST['eid']); $sql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultRate,M.DefaultScale FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?'; @@ -45,7 +47,8 @@ if ( isset( $_REQUEST['scale'] ) ) else $scale = reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); -$eventPath = ZM_DIR_EVENTS.'/'.getEventPath( $event ); +$Event = new Event( $event['Id'] ); +$eventPath = $Event->Path(); $videoFormats = array(); $ffmpegFormats = preg_split( '/\s+/', ZM_FFMPEG_FORMATS ); diff --git a/web/views/image.php b/web/views/image.php index de8205f76..322b4c100 100644 --- a/web/views/image.php +++ b/web/views/image.php @@ -38,6 +38,9 @@ if ( !canView( 'Events' ) ) return; } +require_once('includes/Storage.php'); +require_once('includes/Event.php'); + header( 'Content-type: image/jpeg' ); // Compatibility for PHP 5.4 @@ -55,13 +58,23 @@ if (!function_exists('imagescale')) } } +$Storage = NULL; $errorText = false; if ( empty($_REQUEST['path']) ) { - $errorText = "No image path"; + if ( ! empty($_REQUEST['fid']) ) { + if ( ! empty($_REQUEST['eid'] ) ) { + $Event = new Event( $_REQUEST['eid'] ); + $Storage = $Event->Storage(); + $path = $Event->Relative_Path().'/'.sprintf("%'.0".ZM_EVENT_IMAGE_DIGITS.'d',$_REQUEST['fid']).'-capture.jpg'; + } + } else { + $errorText = "No image path"; + } } else { + $Storage = new Storage(); $path = $_REQUEST['path']; if ( !empty($user['MonitorIds']) ) { @@ -111,10 +124,12 @@ if ( $errorText ) Error( $errorText ); else if( ($scale==0 || $scale==100) && $width==0 && $height==0 ) - readfile( ZM_DIR_EVENTS.'/'.$path ); + if ( ! readfile( $Storage->Path().'/'.$path ) ) { + Error("No bytes read from ". $Storage->Path() . '/'.$path ); + } else { - $i = imagecreatefromjpeg ( ZM_DIR_EVENTS.'/'.$path ); + $i = imagecreatefromjpeg ( $Storage->Path().'/'.$path ); $oldWidth=imagesx($i); $oldHeight=imagesy($i); if($width==0 && $height==0) // scale has to be set to get here with both zero