Merge branch 'storageareas' into zma_to_thread

This commit is contained in:
Isaac Connor 2018-08-11 10:08:30 -04:00
commit 979b31ffc3
161 changed files with 22476 additions and 20807 deletions

View File

@ -1,6 +1,6 @@
You should only file an issue if you found a bug. Feature and enhancement requests, general discussions and support questions should occur in one of the following areas: You should only file an issue if you found a bug. Feature and enhancement requests, general discussions and support questions should occur in one of the following areas:
- The ZoneMinder IRC channel - irc.freenode.net #zoneminder - The [ZoneMinder-Chat Slack channel](https://zoneminder-chat.herokuapp.com/)
- The [ZoneMinder Forum](https://forums.zoneminder.com/) - The [ZoneMinder Forum](https://forums.zoneminder.com/)
**Do not post feature or enhancement requests, general discussions or support questions here.** **Do not post feature or enhancement requests, general discussions or support questions here.**

26
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,26 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- "Under Review"
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -804,6 +804,24 @@ if(WITH_SYSTEMD)
endif(NOT POLKIT_FOUND) endif(NOT POLKIT_FOUND)
endif(WITH_SYSTEMD) endif(WITH_SYSTEMD)
# Find the path to an arp compatible executable
if(ZM_PATH_ARP STREQUAL "")
find_program(ARP_EXECUTABLE arp)
if(ARP_EXECUTABLE)
set(ZM_PATH_ARP "${ARP_EXECUTABLE}")
mark_as_advanced(ARP_EXECUTABLE)
else(ARP_EXECUTABLE)
find_program(ARP_EXECUTABLE ip)
if(ARP_EXECUTABLE)
set(ZM_PATH_ARP "${ARP_EXECUTABLE} neigh")
mark_as_advanced(ARP_EXECUTABLE)
endif(ARP_EXECUTABLE)
endif(ARP_EXECUTABLE)
if(ARP_EXECUTABLE-NOTFOUND)
message(WARNING "Unable to find a compatible arp binary. Monitor probe will not function." )
endif(ARP_EXECUTABLE-NOTFOUND)
endif(ZM_PATH_ARP STREQUAL "")
# Some variables that zm expects # Some variables that zm expects
set(ZM_PID "${ZM_RUNDIR}/zm.pid") set(ZM_PID "${ZM_RUNDIR}/zm.pid")
set(ZM_CONFIG "${ZM_CONFIG_DIR}/zm.conf") set(ZM_CONFIG "${ZM_CONFIG_DIR}/zm.conf")

View File

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

View File

@ -518,6 +518,7 @@ CREATE TABLE `Monitors` (
`ArchivedEvents` int(10) default NULL, `ArchivedEvents` int(10) default NULL,
`ArchivedEventDiskSpace` bigint default NULL, `ArchivedEventDiskSpace` bigint default NULL,
`ZoneCount` TINYINT NOT NULL DEFAULT 0, `ZoneCount` TINYINT NOT NULL DEFAULT 0,
`Refresh` int(10) unsigned default NULL,
PRIMARY KEY (`Id`) PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@; ) ENGINE=@ZM_MYSQL_ENGINE@;
@ -560,7 +561,7 @@ CREATE TABLE `Servers` (
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`State_Id` int(10) unsigned, `State_Id` int(10) unsigned,
`Status` enum('Unknown','NotRunning','Running') NOT NULL default 'Unknown', `Status` enum('Unknown','NotRunning','Running') NOT NULL default 'Unknown',
`Load` DECIMAL(5,1), `CpuLoad` DECIMAL(5,1) default NULL,
`TotalMem` bigint unsigned default null, `TotalMem` bigint unsigned default null,
`FreeMem` bigint unsigned default null, `FreeMem` bigint unsigned default null,
`TotalSwap` bigint unsigned default null, `TotalSwap` bigint unsigned default null,
@ -778,7 +779,8 @@ INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-423','Ffmpeg','Reolink',0,0,1,1
INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-411','Ffmpeg','Reolink',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-411','Ffmpeg','Reolink',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-420','Ffmpeg','Reolink',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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-420','Ffmpeg','Reolink',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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'D-LINK DCS-3415','Remote','DCS3415',0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'D-LINK DCS-3415','Remote','DCS3415',0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'IOS Camera','Ffmpeg','IPCAMIOS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Dericam P2','Ffmpeg','DericamP2',0,1,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,10,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,45,0,0,1,0,0,0,0,1,1,45,0,0,0,0);
-- --
-- Add some monitor preset values -- Add some monitor preset values
-- --

View File

@ -1,20 +0,0 @@
DROP TABLE IF EXISTS `Monitor_Status`;
CREATE TABLE `Monitor_Status` (
`MonitorId` int(10) unsigned NOT NULL,
`Status` enum('Unknown','NotRunning','Running','Connected','Signal') NOT NULL default 'Unknown',
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,2) NOT NULL default 0,
PRIMARY KEY (`MonitorId`)
) ENGINE=MEMORY;
SET SESSION sql_mode='NO_AUTO_VALUE_ON_ZERO';
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM Storage WHERE Name = 'Default' AND Id=0 AND Path='/var/cache/zoneminder/events'
) > 0,
"SELECT 'Default Storage Area already exists.'",
"INSERT INTO Storage (Id,Name,Path,Scheme,ServerId) VALUES (0,'Default','/var/cache/zoneminder/events','Medium',NULL)"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -12,7 +12,7 @@ PREPARE stmt FROM @s;
EXECUTE stmt; EXECUTE stmt;
ALTER TABLE `Monitors` MODIFY `OutputCodec` int(10) UNSIGNED NOT NULL default 0; ALTER TABLE `Monitors` MODIFY `OutputCodec` INT UNSIGNED default 0;
SET @s = (SELECT IF( SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()

View File

@ -16,7 +16,7 @@ SET @s = (SELECT IF(
AND column_name = 'Refresh' AND column_name = 'Refresh'
) > 0, ) > 0,
"SELECT 'Column Refresh exists in Monitors'", "SELECT 'Column Refresh exists in Monitors'",
"ALTER TABLE Monitors ADD `Refresh` int(10) unsigned default NULL" "ALTER TABLE Monitors ADD `Refresh` int(10) unsigned default NULL AFTER `ZoneCount`"
)); ));
PREPARE stmt FROM @s; PREPARE stmt FROM @s;

23
db/zm_update-1.31.45.sql Normal file
View File

@ -0,0 +1,23 @@
--
-- This updates a 1.31.44 database to 1.31.45
--
-- Add WebSite enum to Monitor.Type
-- Add Refresh column to Monitors table
-- This is the same as the update to 1.31.43, but due to Refresh not being added to zm_create.sql.in we need to have it
-- again in order to fix people who did a fresh install from 1.31.43 or 1.31.44.
--
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Monitors'
AND table_schema = DATABASE()
AND column_name = 'Refresh'
) > 0,
"SELECT 'Column Refresh exists in Monitors'",
"ALTER TABLE Monitors ADD `Refresh` int(10) unsigned default NULL AFTER `ZoneCount`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -13,6 +13,7 @@ Build-Depends: debhelper (>= 9), cmake
, libv4l-dev (>= 0.8.3) , libv4l-dev (>= 0.8.3)
, libbz2-dev , libbz2-dev
, ffmpeg | libav-tools , ffmpeg | libav-tools
, net-tools
, libnetpbm10-dev , libnetpbm10-dev
, libvlccore-dev, libvlc-dev , libvlccore-dev, libvlc-dev
, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev , libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev

View File

@ -8,16 +8,6 @@ SET(zmgid_final www)
SET(webroot /srv/www/htdocs) SET(webroot /srv/www/htdocs)
SET(zm_webdir ${webroot}/zoneminder) SET(zm_webdir ${webroot}/zoneminder)
# Download jscalendar & move files into position
file(DOWNLOAD http://downloads.sourceforge.net/jscalendar/jscalendar-1.0.zip ${CMAKE_CURRENT_SOURCE_DIR}/jscalendar-1.0.zip STATUS download_jsc)
if(download_jsc EQUAL 0)
message(STATUS "Jscalander successfully downloaded. Installing...")
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/jscalendar.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ERROR_VARIABLE unzip_jsc)
message(STATUS "Status of jscalender script was: ${unzip_jsc}")
else(download_jsc EQUAL 0)
message(STATUS "Unable to download optional jscalander. Skipping...")
endif(download_jsc EQUAL 0)
# Create several empty folders # Create several empty folders
file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp) file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp)
@ -45,7 +35,3 @@ install(FILES zoneminder.tmpfiles DESTINATION /etc/tmpfiles.d RENAME zoneminder.
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) 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)
install(FILES zoneminder.service DESTINATION /usr/lib/systemd/system PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.service DESTINATION /usr/lib/systemd/system PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
# Install jscalendar
if(unzip_jsc STREQUAL "")
install(DIRECTORY jscalendar-1.0/ DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/tools/jscalendar)
endif(unzip_jsc STREQUAL "")

View File

@ -1,7 +0,0 @@
#!/bin/bash
unzip -o jscalendar-1.0.zip
mkdir -v jscalendar-doc
cd jscalendar-1.0
mv -v *html *php doc/* README ../jscalendar-doc
rmdir -v doc

View File

@ -16,7 +16,6 @@ Version: 1.27.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons
# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
# Mootools is under the MIT license: http://mootools.net/ # Mootools is under the MIT license: http://mootools.net/
License: GPLv2+ and LGPLv2+ and MIT License: GPLv2+ and LGPLv2+ and MIT
URL: http://www.zoneminder.com/ URL: http://www.zoneminder.com/
@ -141,7 +140,7 @@ fi
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc AUTHORS COPYING README.md distros/opensuse/README.OpenSuse distros/opensuse/jscalendar-doc %doc AUTHORS COPYING README.md distros/opensuse/README.OpenSuse
%docdir /opt/zoneminder/share/man %docdir /opt/zoneminder/share/man
%config %attr(640,root,%{zmgid_final}) /etc/zm.conf %config %attr(640,root,%{zmgid_final}) /etc/zm.conf
%config(noreplace) %attr(644,root,root) /etc/apache2/conf.d/zoneminder.conf %config(noreplace) %attr(644,root,root) /etc/apache2/conf.d/zoneminder.conf

View File

@ -27,18 +27,6 @@ else(ZM_WEB_USER STREQUAL "nginx")
configure_file(systemd/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY) configure_file(systemd/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY)
endif(ZM_WEB_USER STREQUAL "nginx") endif(ZM_WEB_USER STREQUAL "nginx")
# Unpack jscalendar & move files into position
message(STATUS "Unpacking and Installing jscalendar...")
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/misc/jscalendar.sh
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
ERROR_VARIABLE unzip_jsc
)
if("${unzip_jsc}" STREQUAL "")
message(STATUS "jscalendar successfully installed.")
else("${unzip_jsc}" STREQUAL "")
message(FATAL_ERROR "\nAn error occurred while jscalendar was being processed:\n${unzip_jsc}")
endif("${unzip_jsc}" STREQUAL "")
# Create several empty folders # Create several empty folders
file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp) file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp)
@ -58,7 +46,6 @@ install(CODE "execute_process(COMMAND ln -sf ../../java/cambozola.jar \"\$ENV{DE
# Install auxiliary files # Install auxiliary files
install(FILES misc/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) install(FILES misc/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)
install(DIRECTORY jscalendar-1.0/ DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/tools/jscalendar)
# Install zoneminder service files # Install zoneminder service files
install(FILES zoneminder.logrotate DESTINATION /etc/logrotate.d RENAME zoneminder 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)

View File

@ -1,7 +0,0 @@
#!/bin/bash
unzip -o misc/jscalendar-1.0.zip
mkdir -v jscalendar-doc
cd jscalendar-1.0
mv -v *html *php doc/* README ../jscalendar-doc
rmdir -v doc

View File

@ -3,6 +3,11 @@ What's New
1. See the ZoneMinder release notes for a list of new features: 1. See the ZoneMinder release notes for a list of new features:
https://github.com/ZoneMinder/zoneminder/releases https://github.com/ZoneMinder/zoneminder/releases
2. The contents of the ZoneMinder Apache config file have changed. In
addition, this ZoneMinder package now requires you to manually symlink the
ZoneMinder Apache config file. See new install step 6 and upgrade step 3
below for details.
New installs New installs
============ ============

View File

@ -4,6 +4,11 @@ What's New
1. See the ZoneMinder release notes for a list of new features: 1. See the ZoneMinder release notes for a list of new features:
https://github.com/ZoneMinder/zoneminder/releases https://github.com/ZoneMinder/zoneminder/releases
2. The contents of the ZoneMinder Apache config file have changed. In
addition, this ZoneMinder package now requires you to manually symlink the
ZoneMinder Apache config file. See new install step 6 and upgrade step 3
below for details.
New installs New installs
============ ============
@ -80,7 +85,7 @@ New installs
When in doubt, proceed with the default: When in doubt, proceed with the default:
sudo ln -s /etc/zm/www/zoneminder.conf /etc/httpd/conf.d/ sudo ln -s /etc/zm/www/zoneminder.conf /etc/httpd/conf.d/
sudo dnf install mod_ssl sudo yum install mod_ssl
7. Now start the web server: 7. Now start the web server:

View File

@ -1,5 +1,5 @@
D @ZM_TMPDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_TMPDIR@ 0755 @WEB_USER@ @WEB_GROUP@
D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@
D @ZM_CACHEDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_CACHEDIR@ 0755 @WEB_USER@ @WEB_GROUP@
D @ZM_DIR_EVENTS@ 0755 @WEB_USER@ @WEB_GROUP@ d @ZM_DIR_EVENTS@ 0755 @WEB_USER@ @WEB_GROUP@
D @ZM_DIR_IMAGES@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_DIR_IMAGES@ 0755 @WEB_USER@ @WEB_GROUP@

View File

@ -26,11 +26,10 @@
%global _hardened_build 1 %global _hardened_build 1
Name: zoneminder Name: zoneminder
Version: 1.31.43 Version: 1.31.45
Release: 1%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons
# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
# Mootools is inder the MIT license: http://mootools.net/ # Mootools is inder the MIT license: http://mootools.net/
# CakePHP is under the MIT license: https://github.com/cakephp/cakephp # CakePHP is under the MIT license: https://github.com/cakephp/cakephp
# Crud is under the MIT license: https://github.com/FriendsOfCake/crud # Crud is under the MIT license: https://github.com/FriendsOfCake/crud
@ -53,6 +52,7 @@ BuildRequires: pcre-devel
BuildRequires: libjpeg-turbo-devel BuildRequires: libjpeg-turbo-devel
BuildRequires: findutils BuildRequires: findutils
BuildRequires: coreutils BuildRequires: coreutils
BuildRequires: net-tools
BuildRequires: perl BuildRequires: perl
BuildRequires: perl-generators BuildRequires: perl-generators
BuildRequires: perl(Archive::Tar) BuildRequires: perl(Archive::Tar)
@ -74,8 +74,11 @@ BuildRequires: gcc-c++
BuildRequires: vlc-devel BuildRequires: vlc-devel
BuildRequires: libcurl-devel BuildRequires: libcurl-devel
BuildRequires: libv4l-devel BuildRequires: libv4l-devel
BuildRequires: desktop-file-utils
# ZoneMinder looks for and records the location of the ffmpeg binary during build
BuildRequires: ffmpeg
BuildRequires: ffmpeg-devel BuildRequires: ffmpeg-devel
BuildRequires: desktop-file-utils
# Required for mp4 container support # Required for mp4 container support
BuildRequires: libmp4v2-devel BuildRequires: libmp4v2-devel
@ -89,6 +92,7 @@ BuildRequires: x264-devel
Requires: php-mysqli Requires: php-mysqli
Requires: php-common Requires: php-common
Requires: php-gd Requires: php-gd
%{?fedora:Requires: php-json}
Requires: php-pecl-apcu Requires: php-pecl-apcu
%{?with_apcu_bc:Requires: php-pecl-apcu-bc} %{?with_apcu_bc:Requires: php-pecl-apcu-bc}
Requires: cambozola Requires: cambozola
@ -248,7 +252,7 @@ EOF
%files %files
%license COPYING %license COPYING
%doc AUTHORS README.md distros/redhat/readme/README.%{readme_suffix} distros/redhat/readme/README.https distros/redhat/jscalendar-doc %doc AUTHORS README.md distros/redhat/readme/README.%{readme_suffix} distros/redhat/readme/README.https
# We want these two folders to have "normal" read permission # We want these two folders to have "normal" read permission
# compared to the folder contents # compared to the folder contents

View File

@ -9,7 +9,17 @@ ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
# Order matters. This Alias must come first # Order matters. This Alias must come first
Alias /zm/cache /var/cache/zoneminder/cache Alias /zm/cache /var/cache/zoneminder/cache
<Directory /var/cache/zoneminder/cache> <Directory /var/cache/zoneminder/cache>
Options -Indexes +FollowSymLinks Options -Indexes +FollowSymLinks
AllowOverride None
<IfModule mod_authz_core.c>
# Apache 2.4
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2
Order deny,allow
Allow from all
</IfModule>
</Directory> </Directory>
Alias /zm /usr/share/zoneminder/www Alias /zm /usr/share/zoneminder/www
@ -45,4 +55,3 @@ Alias /zm /usr/share/zoneminder/www
RewriteRule ^ index.php [L] RewriteRule ^ index.php [L]
RewriteBase /zm/api RewriteBase /zm/api
</Directory> </Directory>

View File

@ -9,7 +9,17 @@ ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
# Order matters. This alias must come first. # Order matters. This alias must come first.
Alias /zm/cache /var/cache/zoneminder/cache Alias /zm/cache /var/cache/zoneminder/cache
<Directory /var/cache/zoneminder/cache> <Directory /var/cache/zoneminder/cache>
Options -Indexes +FollowSymLinks Options -Indexes +FollowSymLinks
AllowOverride None
<IfModule mod_authz_core.c>
# Apache 2.4
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2
Order deny,allow
Allow from all
</IfModule>
</Directory> </Directory>
Alias /zm /usr/share/zoneminder/www Alias /zm /usr/share/zoneminder/www

View File

@ -11,6 +11,8 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
,libavformat-dev (>= 6:10~) ,libavformat-dev (>= 6:10~)
,libavutil-dev (>= 6:10~) ,libavutil-dev (>= 6:10~)
,libswscale-dev (>= 6:10~) ,libswscale-dev (>= 6:10~)
,ffmpeg | libav-tools
,net-tools
,libbz2-dev ,libbz2-dev
,libgcrypt-dev | libgcrypt11-dev ,libgcrypt-dev | libgcrypt11-dev
,libcurl4-gnutls-dev ,libcurl4-gnutls-dev

View File

@ -13,8 +13,8 @@ The API is built in CakePHP and lives under the ``/api`` directory. It
provides a RESTful service and supports CRUD (create, retrieve, update, delete) provides a RESTful service and supports CRUD (create, retrieve, update, delete)
functions for Monitors, Events, Frames, Zones and Config. functions for Monitors, Events, Frames, Zones and Config.
Security Login, Logout & API Security
^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The APIs tie into ZoneMinder's existing security model. This means if you have The APIs tie into ZoneMinder's existing security model. This means if you have
OPT_AUTH enabled, you need to log into ZoneMinder using the same browser you plan to OPT_AUTH enabled, you need to log into ZoneMinder using the same browser you plan to
use the APIs from. If you are developing an app that relies on the API, you need use the APIs from. If you are developing an app that relies on the API, you need
@ -23,11 +23,32 @@ to do a POST login from the app into ZoneMinder before you can access the API.
Then, you need to re-use the authentication information of the login (returned as cookie states) Then, you need to re-use the authentication information of the login (returned as cookie states)
with subsequent APIs for the authentication information to flow through to the APIs. with subsequent APIs for the authentication information to flow through to the APIs.
This means if you plan to use cuRL to experiment with these APIs, you first need to do This means if you plan to use cuRL to experiment with these APIs, you first need to login:
**Login process for ZoneMinder v1.32.0 and above**
:: ::
curl -d "username=XXXX&password=YYYY&action=login&view=console" -c cookies.txt http://yourzmip/zm/index.php curl -XPOST -d "user=XXXX&pass=YYYY" -c cookies.txt http://yourzmip/zm/api/login.json
Staring ZM 1.32.0, you also have a `logout` API that basically clears your session. It looks like this:
::
curl -b cookies.txt http://yourzmip/zm/api/logout.json
**Login process for older versions of ZoneMinder**
::
curl -d "username=XXXX&password=YYYY&action=login&view=console" -c cookies.txt http://yourzmip/zm/index.php
The equivalent logout process for older versions of ZoneMinder is:
::
curl -XPOST -d "username=XXXX&password=YYYY&action=logout&view=console" -b cookies.txt http://yourzmip/zm/index.php
replacing *XXXX* and *YYYY* with your username and password, respectively. replacing *XXXX* and *YYYY* with your username and password, respectively.
@ -36,25 +57,55 @@ and the command will silently fail.
What the "-c cookies.txt" does is store a cookie state reflecting that you have logged into ZM. You now need What the "-c cookies.txt" does is store a cookie state reflecting that you have logged into ZM. You now need
to apply that cookie state to all subsequent APIs. You do that by using a '-b cookies.txt' to subsequent APIs if you are to apply that cookie state to all subsequent APIs. You do that by using a '-b cookies.txt' to subsequent APIs if you are
using CuRL like so: using CuRL like so:
:: ::
curl -b cookies.txt http://yourzmip/zm/api/monitors.json curl -b cookies.txt http://yourzmip/zm/api/monitors.json
This would return a list of monitors and pass on the authentication information to the ZM API layer.
A deeper dive into the login process
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As you might have seen above, there are two ways to login, one that uses the `login.json` API and the other that logs in using the ZM portal. If you are running ZoneMinder 1.32.0 and above, it is *strongly* recommended you use the `login.json` approach. The "old" approach will still work but is not as powerful as the API based login. Here are the reasons why:
* The "old" approach basically uses the same login webpage (`index.php`) that a user would log into when viewing the ZM console. This is not really using an API and more importantly, if you have additional components like reCAPTCHA enabled, this will not work. Using the API approach is much cleaner and will work irrespective of reCAPTCHA
* The new login API returns important information that you can use to stream videos as well, right after login. Consider for example, a typical response to the login API (`/login.json`):
::
{
"credentials": "auth=f5b9cf48693fe8552503c8ABCD5",
"append_password": 0,
"version": "1.31.44",
"apiversion": "1.0"
}
In this example I have `OPT_AUTH` enabled in ZoneMinder and it returns my credential key. You can then use this key to stream images like so:
::
<img src="https://server/zm/cgi-bin/nph-zms?monitor=1&auth=<authval>" />
Where `authval` is the credentials returned to start streaming videos.
The `append_password` field will contain 1 when it is necessary for you to append your ZM password. This is the case when you set `AUTH_RELAY` in ZM options to "plain", for example. In that case, the `credentials` field may contain something like `&user=admin&pass=` and you have to add your password to that string.
.. NOTE:: It is recommended you invoke the `login` API once every 60 minutes to make sure the session stays alive. The same is true if you use the old login method too.
This would return a list of monitors and pass on the authentication information to the ZM API layer.
So remember, if you are using authentication, please add a ``-b cookies.txt`` to each of the commands below if you are using
CuRL. If you are not using CuRL and writing your own app, you need to make sure you pass on cookies to subsequent requests
in your app.
Examples (please read security notice above) Examples (please read security notice above)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You will see each URL ending in either ``.xml`` or ``.json``. This is the Please remember, if you are using authentication, please add a ``-b cookies.txt`` to each of the commands below if you are using
format of the request, and it determines the format that any data returned to CuRL. If you are not using CuRL and writing your own app, you need to make sure you pass on cookies to subsequent requests
you will be in. I like json, however you can use xml if you'd like. in your app.
(In all examples, replace 'server' with IP or hostname & port where ZoneMinder is running) (In all examples, replace 'server' with IP or hostname & port where ZoneMinder is running)

View File

@ -2711,7 +2711,7 @@ our @options = (
}, },
{ {
name => 'ZM_TELEMETRY_DATA', name => 'ZM_TELEMETRY_DATA',
default => 'yes', default => 'no',
description => 'Send usage information to ZoneMinder', description => 'Send usage information to ZoneMinder',
help => q` help => q`
Enable collection of usage information of the local system and send Enable collection of usage information of the local system and send
@ -2954,7 +2954,7 @@ our @options = (
When creating a Web Site monitor, if the target web site has When creating a Web Site monitor, if the target web site has
X-Frame-Options set to sameorigin in the header, the site will X-Frame-Options set to sameorigin in the header, the site will
not display in ZoneMinder. This is a design feature in most modern not display in ZoneMinder. This is a design feature in most modern
browsers. When this condiction has occured, ZoneMinder will write a browsers. When this condition occurs, ZoneMinder will write a
warning to the log file. To get around this, one can install a browser warning to the log file. To get around this, one can install a browser
plugin or extension to ignore X-Frame headers, and then the page will plugin or extension to ignore X-Frame headers, and then the page will
display properly. Once the plugin or extenstion has ben installed, display properly. Once the plugin or extenstion has ben installed,
@ -2963,6 +2963,37 @@ our @options = (
type => $types{boolean}, type => $types{boolean},
category => 'web', category => 'web',
}, },
{
name => 'ZM_WEB_FILTER_SOURCE',
default => 'Hostname',
description => 'How to filter information in the source column.',
help => q`
This option only affects monitors with a source type of Ffmpeg,
Libvlc, or WebSite. This setting controls what information is
displayed in the Source column on the console. Selecting 'None'
will not filter anything. The entire source string will be
displayed, which may contain sensitive information. Selecting
'NoCredentials' will strip out usernames and passwords from the
string. If there are any port numbers in the string and they are
common (80, 554, etc) then those will be removed as well.
Selecting 'Hostname' will filter out all information except for
the hostname or ip address. When in doubt, stay with the default
'Hostname'. This feature uses the php function 'url_parts' to
identify the various pieces of the url. If the url in question
is unusual or not standard in some way, then filtering may not
produce the desired results.
`,
type => {
db_type =>'string',
hint =>'None|Hostname|NoCredentials',
pattern =>qr|^([NH])|i,
format =>q( ($1 =~ /^Non/)
? 'None'
: ($1 =~ /^H/ ? 'Hostname' : 'NoCredentials' )
)
},
category => 'web',
},
{ {
name => 'ZM_WEB_H_REFRESH_MAIN', name => 'ZM_WEB_H_REFRESH_MAIN',
default => '60', default => '60',

View File

@ -0,0 +1,475 @@
# ==========================================================================
#
# ZoneMinder Dericam P2 Control Protocol Module
# Copyright (C) Roman Dissertori
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================
#
# This module contains the implementation of the Dericam P2 device control protocol
#
package ZoneMinder::Control::DericamP2;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our %CamParams = ();
# ==========================================================================
#
# Dericam P2 Control Protocol
#
# On ControlAddress use the format :
# USERNAME:PASSWORD@ADDRESS:PORT
# eg : admin:@10.1.2.1:80
# zoneminder:zonepass@10.0.100.1:40000
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
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 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" );
my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" );
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 getCamParams
{
my $self = shift;
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=getimageattr";
my $req = $self->sendCmd( $cmd );
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
# Parse results setting values in %FCParams
my $content = $res->decoded_content;
while ($content =~ s/var\s+([^=]+)=([^;]+);//ms) {
$CamParams{$1} = $2;
}
}
else
{
Error( "Error check failed:'".$res->status_line()."'" );
}
}
#autoStop
#This makes use of the ZoneMinder Auto Stop Timeout on the Control Tab
sub autoStop
{
my $self = shift;
my $stop_command = shift;
my $autostop = shift;
if( $stop_command && $autostop)
{
Debug( "Auto Stop" );
usleep( $autostop );
my $cmd = "decoder_control.cgi?command=".$stop_command;
$self->sendCmd( $cmd );
}
}
# Reset the Camera
sub reset
{
my $self = shift;
Debug( "Camera Reset" );
# Move to default position
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-act=home";
$self->sendCmd( $cmd );
# Reset all other values to default
$cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-image_type=1&-default=on";
$self->sendCmd( $cmd );
}
# Reboot Camera (on Sleep button)
sub sleep
{
my $self = shift;
Debug( "Camera Reboot" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-act=sysreboot";
$self->sendCmd( $cmd );
}
# Stop the Camera
sub moveStop
{
my $self = shift;
Debug( "Camera Stop" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-act=stop";
$self->sendCmd( $cmd );
}
#Up Arrow
sub moveConUp
{
my $self = shift;
my $stop_command = "1";
Debug( "Move Up" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=up&-speed=45";
$self->sendCmd( $cmd );
#$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#Down Arrow
sub moveConDown
{
my $self = shift;
my $stop_command = "3";
Debug( "Move Down" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=down&-speed=45";
$self->sendCmd( $cmd );
#$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#Left Arrow
sub moveConLeft
{
my $self = shift;
my $stop_command = "5";
Debug( "Move Left" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=left&-speed=45";
$self->sendCmd( $cmd );
#$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#Right Arrow
sub moveConRight
{
my $self = shift;
my $stop_command = "7";
Debug( "Move Right" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=right&-speed=45";
$self->sendCmd( $cmd );
#$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#Zoom In
sub zoomConTele
{
my $self = shift;
Debug( "Zoom Tele" );
my $cmd = "decoder_control.cgi?command=18";
$self->sendCmd( $cmd );
}
#Zoom Out
sub zoomConWide
{
my $self = shift;
Debug( "Zoom Wide" );
my $cmd = "decoder_control.cgi?command=16";
$self->sendCmd( $cmd );
}
#Diagonally Up Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpRight
{
my $self = shift;
Debug( "Move Diagonally Up Right" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=upright&-speed=45";
$self->sendCmd( $cmd );
}
#Diagonally Down Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownRight
{
my $self = shift;
Debug( "Move Diagonally Down Right" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=downright&-speed=45";
$self->sendCmd( $cmd );
}
#Diagonally Up Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpLeft
{
my $self = shift;
Debug( "Move Diagonally Up Left" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=upleft&-speed=45";
$self->sendCmd( $cmd );
}
#Diagonally Down Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownLeft
{
my $self = shift;
Debug( "Move Diagonally Down Left" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=downnleft&-speed=45";
$self->sendCmd( $cmd );
}
#Set Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 30,32,34,36,38,40,42,44 for presets 1-8 respectively
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset $preset" );
if (( $preset >= 1 ) && ( $preset <= 8 )) {
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=preset&-act=set&-number=".(($preset*2) + 28);
$self->sendCmd( $cmd );
}
}
#Recall Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 31,33,35,37,39,41,43,45 for presets 1-8 respectively
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
if (( $preset >= 1 ) && ( $preset <= 8 )) {
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=preset&-act=goto&-number=".(($preset*2) + 29);
$self->sendCmd( $cmd );
}
if ( $preset == 9 ) {
$self->horizontalPatrol();
}
if ( $preset == 10 ) {
$self->verticalPatrol();
}
}
#Horizontal Patrol
sub horizontalPatrol
{
my $self = shift;
Debug( "Horizontal Patrol" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=hscan";
$self->sendCmd( $cmd );
}
#Vertical Patrol
sub verticalPatrol
{
my $self = shift;
Debug( "Vertical Patrol" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=vscan";
$self->sendCmd( $cmd );
}
# Increase Brightness
sub irisAbsOpen
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'brightness'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'brightness'} += $step;
$CamParams{'brightness'} = 100 if ($CamParams{'brightness'} > 100);
Debug( "Increase Brightness" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-brightness=".$CamParams{'brightness'};
$self->sendCmd( $cmd );
}
# Decrease Brightness
sub irisAbsClose
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'brightness'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'brightness'} -= $step;
$CamParams{'brightness'} = 0 if ($CamParams{'brightness'} < 0);
Debug( "Decrease Brightness" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-brightness=".$CamParams{'brightness'};
$self->sendCmd( $cmd );
}
# Increase Contrast
sub whiteAbsIn
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'contrast'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'contrast'} += $step;
$CamParams{'contrast'} = 100 if ($CamParams{'contrast'} > 100);
Debug( "Increase Contrast" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-contrast=".$CamParams{'contrast'};
$self->sendCmd( $cmd );
}
# Decrease Contrast
sub whiteAbsOut
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'contrast'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'contrast'} -= $step;
$CamParams{'contrast'} = 0 if ($CamParams{'contrast'} < 0);
Debug( "Decrease Contrast" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-contrast=".$CamParams{'contrast'};
$self->sendCmd( $cmd );
}
#TODO Saturation cgi-bin/hi3510/param.cgi?cmd=setimageattr&-saturation=44 [0-255]
sub satIncrease
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'saturation'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'saturation'} += $step;
$CamParams{'saturation'} = 255 if ($CamParams{'saturation'} > 255);
Debug( "Increase Saturation" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-saturation=".$CamParams{'saturation'};
$self->sendCmd( $cmd );
}
sub satDecrease
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'saturation'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'saturation'} -= $step;
$CamParams{'saturation'} = 0 if ($CamParams{'saturation'} < 0);
Debug( "Decrease Saturation" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-saturation=".$CamParams{'saturation'};
$self->sendCmd( $cmd );
}
#TODO Sharpness cgi-bin/hi3510/param.cgi?cmd=setimageattr&-sharpness=37 [0-100]
sub sharpIncrease
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'sharpness'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'sharpness'} += $step;
$CamParams{'sharpness'} = 100 if ($CamParams{'sharpness'} > 100);
Debug( "Increase Sharpness" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-sharpness=".$CamParams{'sharpness'};
$self->sendCmd( $cmd );
}
sub sharpDecrease
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'sharpness'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'sharpness'} -= $step;
$CamParams{'sharpness'} = 0 if ($CamParams{'sharpness'} < 0);
Debug( "Decrease Sharpness" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-sharpness=".$CamParams{'sharpness'};
$self->sendCmd( $cmd );
}
#TODO Hue cgi-bin/hi3510/param.cgi?cmd=setimageattr&-hue=37 [0-100]
sub hueIncrease
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'hue'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'hue'} += $step;
$CamParams{'hue'} = 100 if ($CamParams{'hue'} > 100);
Debug( "Increase Hue" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-hue=".$CamParams{'hue'};
$self->sendCmd( $cmd );
}
sub hueDecrease
{
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'hue'});
my $step = $self->getParam( $params, 'step' );
$CamParams{'hue'} -= $step;
$CamParams{'hue'} = 0 if ($CamParams{'hue'} < 0);
Debug( "Decrease Hue" );
my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-hue=".$CamParams{'hue'};
$self->sendCmd( $cmd );
}
1;

View File

@ -0,0 +1,326 @@
# ==========================================================================
#
# ZoneMinder iPhone Control Protocol Module, $Date: 2018-07-15 00:20:00 +0000 $, $Revision: 0003 $
# Copyright (C) 2001-2008 Philip Coombes
#
# Modified for iPhone ipcamera for IOS BY PETER ZARGLIS n 2018-06-09 13:45:00
# 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 iPhone ipcamera for IOS
# control protocol.
#
# ==========================================================================
package ZoneMinder::Control::IPCAMIOS;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# iPhone ipcamera for IOS Protocol
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
my $loopfactor=100000;
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
my $logindetails = "";
bless( $self, $class );
srand( time() );
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($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" );
$self->{state} = 'open';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $result = undef;
my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" );
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = $res->decoded_content;
}
else
{
Error( "Error check failed: '".$res->status_line()."'" );
}
return( $result );
}
sub getDisplayAttr
{
my $self = shift;
my $param = shift;
my $cmdget = "parameters?";
my $resp = $self->sendCmd( $cmdget );
my @fields = split(',',$resp);
my $response=$fields[$param];
my @buffer=split(':',$response);
my $response2=$buffer[1];
return ($response2);
}
sub sleep
{
}
# Flip image vertically -> Horz -> off
sub moveConUp
{
my $self = shift;
my $params = shift;
Debug( "Flip Image" );
my $dvalue=$self->getDisplayAttr(3);
if ( $dvalue == 2 )
{
$dvalue=0;
my $cmd = "parameters?flip=$dvalue";
$self->sendCmd( $cmd );
}
else
{
$dvalue=$dvalue+1;
my $cmd = "parameters?flip=$dvalue";
$self->sendCmd( $cmd );
}
}
# Change camera (front facing or back)
sub moveConDown
{
my $self = shift;
my $params = shift;
Debug( "Change Camera" );
my $dvalue=$self->getDisplayAttr(7);
if ( $dvalue == 0 )
{
my $cmd = "parameters?camera=1";
$self->sendCmd( $cmd );
}
else
{
my $cmd = "parameters?camera=0";
$self->sendCmd( $cmd );
}
}
# Picture Orientation Clockwise
sub moveConRight
{
my $self = shift;
my $params = shift;
Debug( "Orientation" );
my $dvalue=$self->getDisplayAttr(10);
if ( $dvalue == 1 )
{
$dvalue=4;
my $cmd = "parameters?rotation=$dvalue";
$self->sendCmd( $cmd );
}
else
{
$dvalue=$dvalue-1;
my $cmd = "parameters?rotation=$dvalue";
$self->sendCmd( $cmd );
}
}
# Picture Orientation Anti-Clockwise
sub moveConLeft
{
my $self = shift;
my $params = shift;
Debug( "Orientation" );
my $dvalue=$self->getDisplayAttr(10);
if ( $dvalue == 4 )
{
$dvalue=1;
my $cmd = "parameters?rotation=$dvalue";
$self->sendCmd( $cmd );
}
else
{
$dvalue=$dvalue+1;
my $cmd = "parameters?rotation=$dvalue";
$self->sendCmd( $cmd );
}
}
# presetHome is used to turn off Torch, unlock Focus, unlock Exposure, unlock white-balance, rotation, image flipping
# Just basically reset all the little variables and set it to medium quality
# Rotation = 0 means it will autoselect using built in detection
sub presetHome
{
my $self = shift;
Debug( "Home Preset" );
my $cmd = "parameters?torch=0&focus=0&wb=0&exposure=0&rotation=0&flip=0&quality=0.5";
$self->sendCmd( $cmd );
}
sub focusAbsNear
# Focus Un/Lock
{
my $self = shift;
my $params = shift;
Debug( "Focus Un/Lock" );
my $dvalue=$self->getDisplayAttr(2);
if ( $dvalue == 0 )
{
my $cmd = "parameters?focus=1";
$self->sendCmd( $cmd );
}
else
{
my $cmd = "parameters?focus=0";
$self->sendCmd( $cmd );
}
}
sub focusAbsFar
# Exposure Un/Lock
{
my $self = shift;
my $params = shift;
Debug( "Exposure Un/Lock" );
my $dvalue=$self->getDisplayAttr(11);
if ( $dvalue == 0 )
{
my $cmd = "parameters?exposure=1";
$self->sendCmd( $cmd );
}
else
{
my $cmd = "parameters?exposure=0";
$self->sendCmd( $cmd );
}
}
# Increase stream Quality (from 0 to 10)
sub irisAbsOpen
{
my $self = shift;
my $params = shift;
Debug( "Quality" );
my $dvalue=$self->getDisplayAttr(8);
if ( $dvalue < 1 )
{
$dvalue=$dvalue+0.1;
my $cmd = "parameters?quality=$dvalue";
$self->sendCmd( $cmd );
}
}
# Decrease stream Quality (from 10 to 0)
sub irisAbsClose
{
my $self = shift;
my $params = shift;
Debug( "Quality" );
my $dvalue=$self->getDisplayAttr(8);
if ( $dvalue > 0 )
{
$dvalue=$dvalue-0.1;
my $cmd = "parameters?quality=$dvalue";
$self->sendCmd( $cmd );
}
}
# White Balance Un/Lock
sub whiteAbsIn
{
my $self = shift;
my $params = shift;
Debug( "White Balance" );
my $dvalue=$self->getDisplayAttr(9);
if ( $dvalue == 0 )
{
my $cmd = "parameters?wb=1";
$self->sendCmd( $cmd );
}
else
{
my $cmd = "parameters?wb=0";
$self->sendCmd( $cmd );
}
}
# Torch control on/off
sub whiteAbsOut
{
my $self = shift;
my $params = shift;
Debug( "Torch" );
my $dvalue=$self->getDisplayAttr(5);
if ( $dvalue == 0 )
{
my $cmd = "parameters?torch=1";
$self->sendCmd( $cmd );
}
else
{
my $cmd = "parameters?torch=0";
$self->sendCmd( $cmd );
}
}
1;

View File

@ -108,7 +108,7 @@ sub zmDbConnect {
, $Config{ZM_DB_PASS} , $Config{ZM_DB_PASS}
); );
}; };
if ( !$dbh or $@ ) { if ( !$dbh or $@ ) {
Error("Error reconnecting to db: errstr:$DBI::errstr error val:$@"); Error("Error reconnecting to db: errstr:$DBI::errstr error val:$@");
} else { } else {
$dbh->{AutoCommit} = 1; $dbh->{AutoCommit} = 1;

View File

@ -347,14 +347,14 @@ sub delete {
my $event = $_[0]; my $event = $_[0];
if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartTime} ) ) { if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartTime} ) ) {
my ( $caller, undef, $line ) = caller; my ( $caller, undef, $line ) = caller;
Warning( "Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime} from $caller:$line\n" ); Warning("Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime} from $caller:$line\n");
return; return;
} }
if ( ! -e $event->Storage()->Path() ) { if ( ! -e $event->Storage()->Path() ) {
Warning("Not deleting event because storage path doesn't exist"); Warning("Not deleting event because storage path doesn't exist");
return; return;
} }
Info( "Deleting event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime}\n" ); Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime}\n");
$ZoneMinder::Database::dbh->ping(); $ZoneMinder::Database::dbh->ping();
$ZoneMinder::Database::dbh->begin_work(); $ZoneMinder::Database::dbh->begin_work();
@ -362,9 +362,9 @@ sub delete {
{ {
my $sql = 'DELETE FROM Frames WHERE EventId=?'; my $sql = 'DELETE FROM Frames WHERE EventId=?';
my $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql ) my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
or Error( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() ); or Error( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
my $res = $sth->execute( $event->{Id} ) my $res = $sth->execute($event->{Id})
or Error( "Can't execute '$sql': ".$sth->errstr() ); or Error( "Can't execute '$sql': ".$sth->errstr() );
$sth->finish(); $sth->finish();
if ( $ZoneMinder::Database::dbh->errstr() ) { if ( $ZoneMinder::Database::dbh->errstr() ) {
@ -373,10 +373,10 @@ sub delete {
} }
$sql = 'DELETE FROM Stats WHERE EventId=?'; $sql = 'DELETE FROM Stats WHERE EventId=?';
$sth = $ZoneMinder::Database::dbh->prepare_cached( $sql ) $sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
or Error( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() ); or Error("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr());
$res = $sth->execute( $event->{Id} ) $res = $sth->execute($event->{Id})
or Error( "Can't execute '$sql': ".$sth->errstr() ); or Error("Can't execute '$sql': ".$sth->errstr());
$sth->finish(); $sth->finish();
if ( $ZoneMinder::Database::dbh->errstr() ) { if ( $ZoneMinder::Database::dbh->errstr() ) {
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
@ -387,10 +387,10 @@ sub delete {
# Do it individually to avoid locking up the table for new events # Do it individually to avoid locking up the table for new events
{ {
my $sql = 'DELETE FROM Events WHERE Id=?'; my $sql = 'DELETE FROM Events WHERE Id=?';
my $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql ) my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
or Error( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() ); or Error("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr());
my $res = $sth->execute( $event->{Id} ) my $res = $sth->execute($event->{Id})
or Error( "Can't execute '$sql': ".$sth->errstr() ); or Error("Can't execute '$sql': ".$sth->errstr());
$sth->finish(); $sth->finish();
} }
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
@ -602,7 +602,7 @@ Debug("Files to move @files");
die "Unable to add key for $filename"; die "Unable to add key for $filename";
} }
my $duration = time - $starttime; my $duration = time - $starttime;
Debug("PUT to S3 " . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . Number::Bytes::Human::format_bytes($size/$duration) . "/sec"); Debug("PUT to S3 " . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . Number::Bytes::Human::format_bytes($duration?$size/$duration:$size) . '/sec');
} # end foreach file. } # end foreach file.
$moved = 1; $moved = 1;

View File

@ -307,7 +307,7 @@ sub Sql {
if ( $self->{AutoMessage} ) { if ( $self->{AutoMessage} ) {
# Include all events, including events that are still ongoing # Include all events, including events that are still ongoing
# and have no EndTime yet # and have no EndTime yet
$sql .= ' AND ( '.$self->{Sql}.' )'; $sql .= ' WHERE ( '.$self->{Sql}.' )';
} else { } else {
# Only include closed events (events with valid EndTime) # Only include closed events (events with valid EndTime)
$sql .= ' WHERE (E.EndTime IS NOT NULL) AND ( '.$self->{Sql}.' )'; $sql .= ' WHERE (E.EndTime IS NOT NULL) AND ( '.$self->{Sql}.' )';

View File

@ -557,8 +557,8 @@ our $hasJSONAny = 0;
sub _testJSON { sub _testJSON {
return if ( $testedJSON ); return if ( $testedJSON );
my $result = eval { my $result = eval {
require JSON::Any; require JSON::MaybeXS;
JSON::Any->import(); JSON::MaybeXS->import();
}; };
$testedJSON = 1; $testedJSON = 1;
$hasJSONAny = 1 if ( $result ); $hasJSONAny = 1 if ( $result );
@ -581,7 +581,7 @@ sub jsonEncode {
_testJSON(); _testJSON();
if ( $hasJSONAny ) { if ( $hasJSONAny ) {
my $string = eval { JSON::Any->objToJson( $value ) }; my $string = eval { JSON::MaybeXS->encode_json( $value ) };
Fatal( "Unable to encode object to JSON: $@" ) unless( $string ); Fatal( "Unable to encode object to JSON: $@" ) unless( $string );
return( $string ); return( $string );
} }
@ -616,7 +616,7 @@ sub jsonDecode {
_testJSON(); _testJSON();
if ( $hasJSONAny ) { if ( $hasJSONAny ) {
my $object = eval { JSON::Any->jsonToObj( $value ) }; my $object = eval { JSON::MaybeXS->decode_json( $value ) };
Fatal( "Unable to decode JSON string '$value': $@" ) unless( $object ); Fatal( "Unable to decode JSON string '$value': $@" ) unless( $object );
return( $object ); return( $object );
} }

View File

@ -198,6 +198,7 @@ sub initialise( @ ) {
my $this = shift; my $this = shift;
my %options = @_; my %options = @_;
$this->{hasTerm} = -t STDERR;
$this->{id} = $options{id} if defined($options{id}); $this->{id} = $options{id} if defined($options{id});
$this->{logPath} = $options{logPath} if defined($options{logPath}); $this->{logPath} = $options{logPath} if defined($options{logPath});
@ -245,7 +246,8 @@ sub initialise( @ ) {
$tempSyslogLevel = $level if defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG')); $tempSyslogLevel = $level if defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG'));
if ( $Config{ZM_LOG_DEBUG} ) { if ( $Config{ZM_LOG_DEBUG} ) {
foreach my $target ( split( /\|/, $Config{ZM_LOG_DEBUG_TARGET} ) ) { # Splitting on an empty string doesn't return an empty string, it returns an empty array
foreach my $target ( $Config{ZM_LOG_DEBUG_TARGET} ? split(/\|/, $Config{ZM_LOG_DEBUG_TARGET}) : '' ) {
if ( $target eq $this->{id} if ( $target eq $this->{id}
|| $target eq '_'.$this->{id} || $target eq '_'.$this->{id}
|| $target eq $this->{idRoot} || $target eq $this->{idRoot}
@ -278,6 +280,9 @@ sub initialise( @ ) {
$this->{initialised} = !undef; $this->{initialised} = !undef;
# this function can get called on a previously initialized log Object, so clean any sth's
$this->{sth} = undef;
Debug( 'LogOpts: level='.$codes{$this->{level}} Debug( 'LogOpts: level='.$codes{$this->{level}}
.'/'.$codes{$this->{effectiveLevel}} .'/'.$codes{$this->{effectiveLevel}}
.', screen='.$codes{$this->{termLevel}} .', screen='.$codes{$this->{termLevel}}
@ -319,6 +324,8 @@ sub reinitialise {
my $screenLevel = $this->termLevel(); my $screenLevel = $this->termLevel();
$this->termLevel(NOLOG); $this->termLevel(NOLOG);
$this->termLevel($screenLevel) if $screenLevel > NOLOG; $this->termLevel($screenLevel) if $screenLevel > NOLOG;
$this->{sth} = undef;
} }
# Prevents undefined logging levels # Prevents undefined logging levels
@ -392,6 +399,12 @@ sub level {
# ICON: I am remarking this out because I don't see the point of having an effective level, if we are just going to set it to level. # ICON: I am remarking this out because I don't see the point of having an effective level, if we are just going to set it to level.
#$this->{effectiveLevel} = $this->{level} if ( $this->{level} > $this->{effectiveLevel} ); #$this->{effectiveLevel} = $this->{level} if ( $this->{level} > $this->{effectiveLevel} );
# ICON: The point is that LOG_DEBUG can be set either in db or in env var and will get passed in here.
# So this will turn on debug, even if not output has Debug level turned on. I think it should be the other way around
# ICON: Let's try this line instead. effectiveLevel is 1 DEBUG from above, but LOG_DEBUG is off, then $this->level will be 0, and
# so effectiveLevel will become 0
$this->{effectiveLevel} = $this->{level} if ( $this->{level} < $this->{effectiveLevel} );
} }
return $this->{level}; return $this->{level};
} }
@ -474,7 +487,7 @@ sub openSyslog {
sub closeSyslog { sub closeSyslog {
my $this = shift; my $this = shift;
#closelog(); closelog();
} }
sub logFile { sub logFile {
@ -517,54 +530,59 @@ sub logPrint {
if ( $level <= $this->{effectiveLevel} ) { if ( $level <= $this->{effectiveLevel} ) {
$string =~ s/[\r\n]+$//g; $string =~ s/[\r\n]+$//g;
if ( $level <= $this->{syslogLevel} ) {
my $code = $codes{$level}; syslog($priorities{$level}, $codes{$level}.' [%s]', $string);
}
my ($seconds, $microseconds) = gettimeofday(); my ($seconds, $microseconds) = gettimeofday();
my $message = sprintf( if ( $level <= $this->{fileLevel} or $level <= $this->{termLevel} ) {
'%s.%06d %s[%d].%s [%s]' my $message = sprintf(
, strftime('%x %H:%M:%S', localtime($seconds)) '%s.%06d %s[%d].%s [%s]'
, $microseconds , strftime('%x %H:%M:%S', localtime($seconds))
, $this->{id} , $microseconds
, $$ , $this->{id}
, $code , $$
, $string , $codes{$level}
); , $string
if ( $this->{trace} ) { );
$message = Carp::shortmess($message); if ( $this->{trace} ) {
} else { $message = Carp::shortmess($message);
$message = $message."\n"; } else {
$message = $message."\n";
}
print($LOGFILE $message) if $level <= $this->{fileLevel};
print(STDERR $message) if $level <= $this->{termLevel};
} }
if ( $level <= $this->{syslogLevel} ) {
syslog($priorities{$level}, $code.' [%s]', $string);
}
print($LOGFILE $message) if $level <= $this->{fileLevel};
print(STDERR $message) if $level <= $this->{termLevel};
if ( $level <= $this->{databaseLevel} ) { if ( $level <= $this->{databaseLevel} ) {
if ( ( $this->{dbh} and $this->{dbh}->ping() ) or ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) { if ( ! ( $this->{dbh} and $this->{dbh}->ping() ) ) {
$this->{sth} = undef;
my $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NULL )'; if ( ! ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) {
$this->{sth} = $this->{dbh}->prepare_cached($sql); #print(STDERR "Can't log to database: ");
if ( !$this->{sth} ) {
$this->{databaseLevel} = NOLOG; $this->{databaseLevel} = NOLOG;
Error("Can't prepare log entry '$sql': ".$this->{dbh}->errstr()); return;
} else {
my $res = $this->{sth}->execute($seconds+($microseconds/1000000.0)
, $this->{id}
, $$
, $level
, $code
, $string
, $this->{fileName}
);
if ( !$res ) {
$this->{databaseLevel} = NOLOG;
Error("Can't execute log entry '$sql': ".$this->{dbh}->errstr());
}
} }
} else { }
print(STDERR "Can't log to database: ");
my $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NULL )';
$this->{sth} = $this->{dbh}->prepare_cached($sql) if ! $this->{sth};
if ( !$this->{sth} ) {
$this->{databaseLevel} = NOLOG;
Error("Can't prepare log entry '$sql': ".$this->{dbh}->errstr());
return;
}
my $res = $this->{sth}->execute($seconds+($microseconds/1000000.0)
, $this->{id}
, $$
, $level
, $codes{$level}
, $string
, $this->{fileName}
);
if ( !$res ) {
$this->{databaseLevel} = NOLOG;
Error("Can't execute log entry '$sql': ".$this->{dbh}->errstr());
} }
} # end if doing db logging } # end if doing db logging
} # end if level < effectivelevel } # end if level < effectivelevel

View File

@ -252,36 +252,37 @@ MAIN: while( $loop ) {
foreach my $day_dir ( @day_dirs ) { foreach my $day_dir ( @day_dirs ) {
Debug( "Checking day dir $day_dir" ); Debug( "Checking day dir $day_dir" );
( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint ( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint
if ( ! chdir( $day_dir ) ) { if ( !chdir($day_dir) ) {
Error( "Can't chdir to '$$Storage{Path}/$day_dir': $!" ); Error("Can't chdir to '$$Storage{Path}/$day_dir': $!");
next; next;
} }
if ( ! opendir( DIR, '.' ) ) { if ( ! opendir(DIR, '.') ) {
Error( "Can't open directory '$$Storage{Path}/$day_dir': $!" ); Error("Can't open directory '$$Storage{Path}/$day_dir': $!");
next; next;
} }
my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR ); my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR );
closedir( DIR ); Debug("Have " . @event_links . ' event links');
closedir(DIR);
my $count = 0; my $count = 0;
foreach my $event_link ( @event_links ) { foreach my $event_link ( @event_links ) {
if ( $event_link =~ /[^\d\.]/ ) { if ( $event_link =~ /[^\d\.]/ ) {
Warning("Non-event link found $event_link in $day_dir, skipping"); Warning("Non-event link found $event_link in $day_dir, skipping");
next; next;
} }
Debug( "Checking link $event_link" ); Debug("Checking link $event_link");
( my $event = $event_link ) =~ s/^.*\.//; ( my $event = $event_link ) =~ s/^.*\.//;
#Event path is hour/minute/sec #Event path is hour/minute/sec
my $event_path = readlink( $event_link ); my $event_path = readlink($event_link);
if ( !($event_path and -e $event_path) ) { if ( !($event_path and -e $event_path) ) {
aud_print( "Event link $day_dir/$event_link does not point to valid target" ); aud_print("Event link $day_dir/$event_link does not point to valid target");
if ( confirm() ) { if ( confirm() ) {
( $event_link ) = ( $event_link =~ /^(.*)$/ ); # De-taint ( $event_link ) = ( $event_link =~ /^(.*)$/ ); # De-taint
unlink( $event_link ); unlink($event_link);
$cleaned = 1; $cleaned = 1;
} }
} else { } else {
Debug( "Checking link $event_link points to $event_path " ); Debug("Checking link $event_link points to $event_path ");
my $Event = $fs_events->{$event} = new ZoneMinder::Event(); my $Event = $fs_events->{$event} = new ZoneMinder::Event();
$$Event{Id} = $event; $$Event{Id} = $event;
$$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path); $$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path);
@ -292,6 +293,42 @@ MAIN: while( $loop ) {
$Event->DiskSpace( undef ); $Event->DiskSpace( undef );
} # event path exists } # event path exists
} # end foreach event_link } # end foreach event_link
# Now check for events that have lost their link
my @time_dirs = glob('[0-9][0-9]/[0-9][0-9]/[0-9][0-9]');
foreach my $event_dir ( @time_dirs ) {
Debug("Checking time dir $event_dir");
( $event_dir ) = ( $event_dir =~ /^(.*)$/ ); # De-taint
my $event_id = undef;
my @mp4_files = glob("$event_dir/[0-9]+\-video.mp4");
foreach my $mp4_file ( @mp4_files ) {
my ( $id ) = $mp4_file =~ /^([0-9]+)\-video\.mp4$/;
if ( $id ) {
$event_id = $id;
last;
}
}
if ( $event_id ) {
my $Event = $fs_events->{$event_id} = new ZoneMinder::Event();
$$Event{Id} = $event_id;
$$Event{Path} = join('/', $Storage->Path(), $day_dir, $event_dir);
$$Event{RelativePath} = join('/', $day_dir, $event_dir);
$$Event{Scheme} = 'Deep';
$Event->MonitorId( $monitor_dir );
$Event->StorageId( $Storage->Id() );
$Event->DiskSpace( undef );
} else {
aud_print("Deleting event directories with no event id information at $day_dir/$event_dir");
if ( confirm() ) {
my $command = "rm -rf $event_dir";
executeShellCommand( $command );
$cleaned = 1;
}
} # end if able to find id
} # end foreach event_dir without link
chdir( $Storage->Path() ); chdir( $Storage->Path() );
} # end foreach day dir } # end foreach day dir
} }
@ -701,17 +738,18 @@ FROM Frames WHERE EventId=?';
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^(.*)s$/ ) { if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^(.*)s$/ ) {
$Config{ZM_LOG_DATABASE_LIMIT} = $1; $Config{ZM_LOG_DATABASE_LIMIT} = $1;
} }
my $deleteLogByTimeSql = my $deleted_rows;
'DELETE low_priority FROM Logs do {
WHERE TimeKey < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.')'; my $deleteLogByTimeSql =
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql ) 'DELETE FROM Logs
or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() ); WHERE TimeKey < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 10';
$res = $deleteLogByTimeSth->execute() my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
or Fatal( "Can't execute: ".$deleteLogByTimeSth->errstr() ); or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() );
if ( $deleteLogByTimeSth->rows() ){ $res = $deleteLogByTimeSth->execute()
aud_print( 'Deleted '.$deleteLogByTimeSth->rows() or Fatal( "Can't execute: ".$deleteLogByTimeSth->errstr() );
." log table entries by time\n" ); $deleted_rows = $deleteLogByTimeSth->rows();
} aud_print( "Deleted $deleted_rows log table entries by time\n" );
} while ( $deleted_rows );
} }
} # end if ZM_LOG_DATABASE_LIMIT } # end if ZM_LOG_DATABASE_LIMIT
$loop = $continuous; $loop = $continuous;

View File

@ -119,13 +119,13 @@ if ( $command eq 'version' ) {
} }
my $needs_daemon = $command !~ /(?:startup|shutdown|status|check|logrot|version)/; my $needs_daemon = $command !~ /(?:startup|shutdown|status|check|logrot|version)/;
my $daemon = shift @ARGV; my $daemon = shift @ARGV;
if ( $needs_daemon && ! $daemon ) { if ( $needs_daemon && !$daemon ) {
print(STDERR "No daemon given\n"); print(STDERR "No daemon given\n");
pod2usage(-exitstatus => -1); pod2usage(-exitstatus => -1);
} }
my @args; my @args;
my $daemon_patt = '('.join( '|', @daemons ).')'; my $daemon_patt = '('.join('|', @daemons).')';
if ( $needs_daemon ) { if ( $needs_daemon ) {
if ( $daemon =~ /^${daemon_patt}$/ ) { if ( $daemon =~ /^${daemon_patt}$/ ) {
$daemon = $1; $daemon = $1;
@ -139,7 +139,7 @@ foreach my $arg ( @ARGV ) {
# Detaint arguments, if they look ok # Detaint arguments, if they look ok
#if ( $arg =~ /^(-{0,2}[\w]+)/ ) #if ( $arg =~ /^(-{0,2}[\w]+)/ )
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) { if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
push( @args, $1 ); push @args, $1;
} else { } else {
print(STDERR "Bogus argument '$arg' found"); print(STDERR "Bogus argument '$arg' found");
exit(-1); exit(-1);
@ -172,7 +172,7 @@ if ( !$server_up ) {
exit(); exit();
} elsif ( $command ne 'startup' ) { } elsif ( $command ne 'startup' ) {
print("Unable to connect to server using socket at " . SOCK_FILE . "\n"); print("Unable to connect to server using socket at " . SOCK_FILE . "\n");
exit( -1 ); exit(-1);
} }
# The server isn't there # The server isn't there
@ -210,7 +210,7 @@ if ( ($command eq 'check') && !$daemon ) {
# The server is there, connect to it # The server is there, connect to it
CLIENT->autoflush(); CLIENT->autoflush();
my $message = join(';', $command, ( $daemon ? $daemon : () ), @args ); my $message = join(';', $command, ( $daemon ? $daemon : () ), @args);
print(CLIENT $message); print(CLIENT $message);
shutdown(CLIENT, 1); shutdown(CLIENT, 1);
while( my $line = <CLIENT> ) { while( my $line = <CLIENT> ) {
@ -242,16 +242,31 @@ use constant KILL_DELAY => 60; # seconds to wait between sending TERM and sendin
our %cmd_hash; our %cmd_hash;
our %pid_hash; our %pid_hash;
our %terminating_processes; our %terminating_processes;
our %pids_to_reap;
our $zm_terminate = 0; our $zm_terminate = 0;
sub run { sub run {
# Call this first otherwise stdout/stderror redirects to the pidfile = bad
if ( open(my $PID, '>', ZM_PID) ) {
print($PID $$);
close($PID);
} else {
# Log not initialized at this point so use die instead
die "Can't open pid file at ".ZM_PID."\n";
}
my $fd = 0; my $fd = 0;
# THis also closes dbh and CLIENT and SERVER
while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) { while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
POSIX::close($fd++); POSIX::close($fd++);
} }
setpgrp(); setpgrp();
# dbh got closed with the rest of the fd's above, so need to reconnect.
my $dbh = zmDbConnect(1);
logInit(); logInit();
dPrint(ZoneMinder::Logger::INFO, 'Server starting at ' dPrint(ZoneMinder::Logger::INFO, 'Server starting at '
@ -259,24 +274,16 @@ sub run {
."\n" ."\n"
); );
if ( open(my $PID, '>', ZM_PID) ) {
print($PID $$);
close($PID);
} else {
Error("Can't open pid file at " . ZM_PID);
}
# Tell any existing processes to die, wait 1 second between TERM and KILL # Tell any existing processes to die, wait 1 second between TERM and KILL
killAll(1); killAll(1);
dPrint(ZoneMinder::Logger::INFO, 'Socket should be open at ' .main::SOCK_FILE); dPrint(ZoneMinder::Logger::INFO, 'Socket should be open at ' .main::SOCK_FILE);
my $dbh = zmDbConnect(1);
socket(SERVER, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!"); socket(SERVER, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
unlink(main::SOCK_FILE) or Error('Unable to unlink ' . main::SOCK_FILE .". Error message was: $!") if -e main::SOCK_FILE; unlink(main::SOCK_FILE) or Error('Unable to unlink ' . main::SOCK_FILE .". Error message was: $!") if -e main::SOCK_FILE;
bind(SERVER, $saddr) or Fatal("Can't bind to " . main::SOCK_FILE . ": $!"); bind(SERVER, $saddr) or Fatal("Can't bind to " . main::SOCK_FILE . ": $!");
listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!"); listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
$SIG{CHLD} = \&reaper; $SIG{CHLD} = \&chld_sig_handler;
$SIG{INT} = \&shutdown_sig_handler; $SIG{INT} = \&shutdown_sig_handler;
$SIG{TERM} = \&shutdown_sig_handler; $SIG{TERM} = \&shutdown_sig_handler;
$SIG{ABRT} = \&shutdown_sig_handler; $SIG{ABRT} = \&shutdown_sig_handler;
@ -287,35 +294,28 @@ sub run {
my $win = $rin; my $win = $rin;
my $ein = $win; my $ein = $win;
my $timeout = 1; my $timeout = 1;
my $Server = undef;
my $secs_count = 0; my $secs_count = 0;
if ( $Config{ZM_SERVER_ID} ) {
require ZoneMinder::Server;
$Server = new ZoneMinder::Server($Config{ZM_SERVER_ID});
dPrint(ZoneMinder::Logger::INFO, 'Loading Server record have ' . $$Server{Name});
}
while( !$zm_terminate ) { while( !$zm_terminate ) {
if ( $Config{ZM_SERVER_ID} ) { if ( $Config{ZM_SERVER_ID} ) {
if ( ! ( $secs_count % 60 ) ) { if ( ! ( $secs_count % 60 ) ) {
Debug("Connecting");
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) { while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
Warning("Not connected to db ($dbh)".($dbh?" ping(".$dbh->ping().")":''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting'); Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting');
$dbh = zmDbConnect(); $dbh = zmDbConnect();
} }
last if $zm_terminate;
my @cpuload = CpuLoad(); my @cpuload = CpuLoad();
Debug("UPdating Server record @cpuload"); Debug("Updating Server record @cpuload");
if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,CpuLoad=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef, if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,CpuLoad=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef,
'Running', $cpuload[0], &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) { 'Running', $cpuload[0], &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr()); Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID} :".$dbh->errstr());
} }
} }
$secs_count += 1; $secs_count += 1;
} }
my $nfound = select(my $rout = $rin, undef, undef, $timeout); my $nfound = select(my $rout = $rin, undef, undef, $timeout);
Debug("Aftere select $nfound");
if ( $nfound > 0 ) { if ( $nfound > 0 ) {
if ( vec($rout, fileno(SERVER), 1) ) { if ( vec($rout, fileno(SERVER), 1) ) {
my $paddr = accept(CLIENT, SERVER); my $paddr = accept(CLIENT, SERVER);
@ -337,7 +337,7 @@ Debug("Aftere select $nfound");
# Do nothing, this is all we're here for # Do nothing, this is all we're here for
dPrint(ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n"); dPrint(ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n");
} elsif ( $command eq 'shutdown' ) { } elsif ( $command eq 'shutdown' ) {
# Breka out of while loop # Break out of while loop
last; last;
} elsif ( $command eq 'check' ) { } elsif ( $command eq 'check' ) {
check($daemon, @args); check($daemon, @args);
@ -370,19 +370,17 @@ Debug("Aftere select $nfound");
#print( "Select timed out\n" ); #print( "Select timed out\n" );
} }
Debug("restartPending");
restartPending(); restartPending();
Debug("check_for_processes_to_kill"); check_for_processes_to_kill() if %terminating_processes;
check_for_processes_to_kill(); reaper() if %pids_to_reap;
} # end while } # end while
dPrint(ZoneMinder::Logger::INFO, 'Server exiting at ' dPrint(ZoneMinder::Logger::INFO, 'Server exiting at '
.strftime( '%y/%m/%d %H:%M:%S', localtime() ) .strftime('%y/%m/%d %H:%M:%S', localtime())
."\n" ."\n"
); );
if ( $Config{ZM_SERVER_ID} ) { if ( $Config{ZM_SERVER_ID} ) {
$dbh = zmDbConnect() if ! $dbh->ping(); $dbh = zmDbConnect() if ! ($dbh and $dbh->ping());
if ( ! defined $dbh->do(q{UPDATE Servers SET Status='NotRunning' WHERE Id=?}, undef, $Config{ZM_SERVER_ID}) ) { if ( ! defined $dbh->do(q{UPDATE Servers SET Status='NotRunning' WHERE Id=?}, undef, $Config{ZM_SERVER_ID}) ) {
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr()); Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr());
} }
@ -391,6 +389,7 @@ Debug("check_for_processes_to_kill");
} }
sub cPrint { sub cPrint {
# One thought here, if no client exists to read these... does it block?
if ( fileno(CLIENT) ) { if ( fileno(CLIENT) ) {
print CLIENT @_ print CLIENT @_
} }
@ -399,9 +398,7 @@ sub cPrint {
# I think the purpose of this is to echo the logs to the client process so it can then display them. # I think the purpose of this is to echo the logs to the client process so it can then display them.
sub dPrint { sub dPrint {
my $logLevel = shift; my $logLevel = shift;
if ( fileno(CLIENT) ) { cPrint(@_);
print CLIENT @_
}
if ( $logLevel == ZoneMinder::Logger::DEBUG ) { if ( $logLevel == ZoneMinder::Logger::DEBUG ) {
Debug(@_); Debug(@_);
} elsif ( $logLevel == ZoneMinder::Logger::INFO ) { } elsif ( $logLevel == ZoneMinder::Logger::INFO ) {
@ -435,12 +432,14 @@ sub start {
my $sigset = POSIX::SigSet->new; my $sigset = POSIX::SigSet->new;
my $blockset = POSIX::SigSet->new(SIGCHLD); my $blockset = POSIX::SigSet->new(SIGCHLD);
Debug("Blocking SIGCHLD");
sigprocmask(SIG_BLOCK, $blockset, $sigset) or Fatal("Can't block SIGCHLD: $!"); sigprocmask(SIG_BLOCK, $blockset, $sigset) or Fatal("Can't block SIGCHLD: $!");
Debug("forking"); # Apparently the child closing the db connection can affect the parent.
zmDbDisconnect();
if ( my $cpid = fork() ) { if ( my $cpid = fork() ) {
$dbh = zmDbConnect(1);
# This logReinit is required. Not sure why. # This logReinit is required. Not sure why.
logReinit(); #logReinit();
$process->{pid} = $cpid; $process->{pid} = $cpid;
$process->{started} = time(); $process->{started} = time();
@ -453,9 +452,10 @@ sub start {
$cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process; $cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process;
sigprocmask(SIG_SETMASK, $sigset) or Fatal("Can't restore SIGCHLD: $!"); sigprocmask(SIG_SETMASK, $sigset) or Fatal("Can't restore SIGCHLD: $!");
Debug("unblocking child");
} elsif ( defined($cpid) ) { } elsif ( defined($cpid) ) {
# Force reconnection to the db. # Child process
# Force reconnection to the db. $dbh got copied, but isn't really valid anymore.
$dbh = zmDbConnect(1); $dbh = zmDbConnect(1);
logReinit(); logReinit();
@ -472,7 +472,7 @@ sub start {
my @good_args; my @good_args;
foreach my $arg ( @args ) { foreach my $arg ( @args ) {
# Detaint arguments, if they look ok # Detaint arguments, if they look ok
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) { if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
push @good_args, $1; push @good_args, $1;
} else { } else {
@ -488,8 +488,8 @@ sub start {
POSIX::close($fd++); POSIX::close($fd++);
} }
# Child process
$SIG{CHLD} = 'DEFAULT'; $SIG{CHLD} = 'DEFAULT';
$SIG{HUP} = 'DEFAULT';
$SIG{INT} = 'DEFAULT'; $SIG{INT} = 'DEFAULT';
$SIG{TERM} = 'DEFAULT'; $SIG{TERM} = 'DEFAULT';
$SIG{ABRT} = 'DEFAULT'; $SIG{ABRT} = 'DEFAULT';
@ -516,7 +516,7 @@ sub send_stop {
.strftime('%y/%m/%d %H:%M:%S', localtime()) .strftime('%y/%m/%d %H:%M:%S', localtime())
."\n" ."\n"
); );
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n"; sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
return(); return();
} }
@ -635,15 +635,24 @@ sub shutdown_sig_handler {
$zm_terminate = 1; $zm_terminate = 1;
} }
sub reaper { sub chld_sig_handler {
my $saved_status = $!; my $saved_status = $!;
# Wait for a child to terminate # Wait for a child to terminate
while ( (my $cpid = waitpid(-1, WNOHANG)) > 0 ) { while ( (my $cpid = waitpid(-1, WNOHANG)) > 0 ) {
my $status = $?; $pids_to_reap{$cpid} = { status=>$?, stopped=>time() };
} # end while waitpid
$SIG{CHLD} = \&chld_sig_handler;
$! = $saved_status;
}
sub reaper {
foreach my $cpid ( keys %pids_to_reap ) {
my $process = $pid_hash{$cpid}; my $process = $pid_hash{$cpid};
delete $pid_hash{$cpid}; delete $pid_hash{$cpid};
my $reap_info = $pids_to_reap{$cpid};
my ( $status, $stopped ) = @$reap_info{'status','stopped'};
delete $pids_to_reap{$cpid};
if ( !$process ) { if ( !$process ) {
dPrint(ZoneMinder::Logger::INFO, "Can't find child with pid of '$cpid'\n"); dPrint(ZoneMinder::Logger::INFO, "Can't find child with pid of '$cpid'\n");
@ -652,7 +661,7 @@ sub reaper {
delete $terminating_processes{$$process{command}}; delete $terminating_processes{$$process{command}};
delete $$process{term_sent_at}; delete $$process{term_sent_at};
$process->{stopped} = time(); $process->{stopped} = $stopped;
$process->{runtime} = ($process->{stopped}-$process->{started}); $process->{runtime} = ($process->{stopped}-$process->{started});
delete $process->{pid}; delete $process->{pid};
@ -701,15 +710,12 @@ sub reaper {
$process->{delay} = $Config{ZM_MAX_RESTART_DELAY}; $process->{delay} = $Config{ZM_MAX_RESTART_DELAY};
} }
} }
Debug("Delay for $$process{command} is now $$process{delay}"); #Debug("Delay for $$process{command} is now $$process{delay}");
} else { } else {
delete $cmd_hash{$$process{command}}; delete $cmd_hash{$$process{command}};
} }
} # end while waitpid } # end foreach pid_to_reap
$SIG{CHLD} = \&reaper; } # end sub reaper
$! = $saved_status;
Debug("Leaving reaper");
}
sub restartPending { sub restartPending {
# Restart any pending processes, we list them first because cmd_hash may change in foreach # Restart any pending processes, we list them first because cmd_hash may change in foreach
@ -720,7 +726,6 @@ sub restartPending {
start($process->{daemon}, @{$process->{args}}); start($process->{daemon}, @{$process->{args}});
} }
} }
Debug("done restartPending");
} }
sub shutdownAll { sub shutdownAll {
@ -730,6 +735,8 @@ sub shutdownAll {
send_stop(1, $pid_hash{$pid}); send_stop(1, $pid_hash{$pid});
} }
while ( keys %terminating_processes ) { while ( keys %terminating_processes ) {
reaper() if %pids_to_reap;
check_for_processes_to_kill(); check_for_processes_to_kill();
if ( %terminating_processes ) { if ( %terminating_processes ) {
Debug("Still " . %terminating_processes . ' to die. sleeping'); Debug("Still " . %terminating_processes . ' to die. sleeping');
@ -808,7 +815,7 @@ sub status {
foreach my $process ( values %cmd_hash ) { foreach my $process ( values %cmd_hash ) {
if ( $process->{pending} ) { if ( $process->{pending} ) {
dPrint(ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at " dPrint(ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at "
.strftime( '%y/%m/%d %H:%M:%S', localtime($process->{pending})) .strftime('%y/%m/%d %H:%M:%S', localtime($process->{pending}))
."\n" ."\n"
); );
} }

View File

@ -70,16 +70,18 @@ use Getopt::Long;
use autouse 'Pod::Usage'=>qw(pod2usage); use autouse 'Pod::Usage'=>qw(pod2usage);
use autouse 'Data::Dumper'=>qw(Dumper); use autouse 'Data::Dumper'=>qw(Dumper);
my $daemon = 0;
my $filter_name = ''; my $filter_name = '';
my $filter_id; my $filter_id;
my $version = 0; my $version = 0;
my $zm_terminate = 0; my $zm_terminate = 0;
GetOptions( GetOptions(
'filter=s' =>\$filter_name, daemon =>\$daemon,
'filter_id=s' =>\$filter_id, 'filter=s' =>\$filter_name,
'version' =>\$version 'filter_id=s' =>\$filter_id,
) or pod2usage(-exitstatus => -1); version =>\$version
) or pod2usage(-exitstatus => -1);
if ( $version ) { if ( $version ) {
print ZoneMinder::Base::ZM_VERSION . "\n"; print ZoneMinder::Base::ZM_VERSION . "\n";
@ -96,15 +98,21 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
logInit($filter_id?(id=>'zmfilter_'.$filter_id):()); logInit($filter_id?(id=>'zmfilter_'.$filter_id):());
sub HupHandler { sub HupHandler {
Info("Received HUP, reloading"); # This idea at this time is to just exit, freeing up the memory.
# zmfilter.pl will be respawned by zmdc.
TermHandler();
return;
Info('Received HUP, reloading');
ZoneMinder::Object::init_cache();
&ZoneMinder::Logger::logHupHandler(); &ZoneMinder::Logger::logHupHandler();
} }
sub TermHandler { sub TermHandler {
Info("Received TERM, exiting"); Info('Received TERM, exiting');
$zm_terminate = 1; $zm_terminate = 1;
} }
sub Term { sub Term {
exit( 0 ); exit(0);
} }
$SIG{HUP} = \&HupHandler; $SIG{HUP} = \&HupHandler;
$SIG{TERM} = \&TermHandler; $SIG{TERM} = \&TermHandler;
@ -173,7 +181,7 @@ if ( $filter_name ) {
} }
if ( ! ( $filter_name or $filter_id ) ) { if ( ! ( $filter_name or $filter_id ) ) {
Debug("Sleeping due to start delay: " . START_DELAY . ' seconds...'); Debug('Sleeping due to start delay: ' . START_DELAY . ' seconds...');
sleep(START_DELAY); sleep(START_DELAY);
} }
@ -201,7 +209,7 @@ while( !$zm_terminate ) {
} }
} }
last if $filter_name or $filter_id or $zm_terminate; last if (!$daemon and ($filter_name or $filter_id)) or $zm_terminate;
Debug("Sleeping for $delay seconds\n"); Debug("Sleeping for $delay seconds\n");
sleep($delay); sleep($delay);
@ -265,8 +273,7 @@ sub checkFilter {
Info( Info(
join(' ', join(' ',
'Checking filter', $filter->{Name}, 'Checking filter', $filter->{Name},
join( ', ', join(', ',
($filter->{AutoDelete}?'delete':()), ($filter->{AutoDelete}?'delete':()),
($filter->{AutoArchive}?'archive':()), ($filter->{AutoArchive}?'archive':()),
($filter->{AutoVideo}?'video':()), ($filter->{AutoVideo}?'video':()),
@ -309,7 +316,7 @@ sub checkFilter {
} }
if ( $Config{ZM_OPT_MESSAGE} && $filter->{AutoMessage} ) { if ( $Config{ZM_OPT_MESSAGE} && $filter->{AutoMessage} ) {
if ( !$event->{Messaged} ) { if ( !$event->{Messaged} ) {
$delete_ok = undef if !sendMessage($filter, $event); $delete_ok = undef if !sendMessage($filter, $Event);
} }
} }
if ( $Config{ZM_OPT_UPLOAD} && $filter->{AutoUpload} ) { if ( $Config{ZM_OPT_UPLOAD} && $filter->{AutoUpload} ) {
@ -383,7 +390,7 @@ sub generateVideo {
$format = $ffmpeg_formats[0]; $format = $ffmpeg_formats[0];
} }
my $command = join( '', my $command = join('',
$Config{ZM_PATH_BIN}, $Config{ZM_PATH_BIN},
'/zmvideo.pl -e ', '/zmvideo.pl -e ',
$event->{Id}, $event->{Id},
@ -395,7 +402,7 @@ sub generateVideo {
$format, $format,
); );
my $output = qx($command); my $output = qx($command);
chomp( $output ); chomp($output);
my $status = $? >> 8; my $status = $? >> 8;
if ( $status || logDebugging() ) { if ( $status || logDebugging() ) {
Debug("Output: $output\n"); Debug("Output: $output\n");
@ -833,7 +840,7 @@ sub sendEmail {
sub sendMessage { sub sendMessage {
my $filter = shift; my $filter = shift;
my $event = shift; my $Event = shift;
if ( ! $Config{ZM_FROM_EMAIL} ) { if ( ! $Config{ZM_FROM_EMAIL} ) {
Error('No from email address defined, not sending message'); Error('No from email address defined, not sending message');
@ -846,10 +853,10 @@ sub sendMessage {
Info('Creating notification message'); Info('Creating notification message');
my $subject = substituteTags($Config{ZM_MESSAGE_SUBJECT}, $filter, $event); my $subject = substituteTags($Config{ZM_MESSAGE_SUBJECT}, $filter, $Event);
return 0 if !$subject; return 0 if !$subject;
my @attachments; my @attachments;
my $body = substituteTags($Config{ZM_MESSAGE_BODY}, $filter, $event, \@attachments); my $body = substituteTags($Config{ZM_MESSAGE_BODY}, $filter, $Event, \@attachments);
return 0 if !$body; return 0 if !$body;
Info("Sending notification message '$subject'"); Info("Sending notification message '$subject'");
@ -930,11 +937,11 @@ sub sendMessage {
my $sql = 'UPDATE Events SET Messaged = 1 WHERE Id = ?'; my $sql = 'UPDATE Events SET Messaged = 1 WHERE Id = ?';
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
or Fatal("Unable toprepare '$sql': ".$dbh->errstr()); or Fatal("Unable toprepare '$sql': ".$dbh->errstr());
my $res = $sth->execute($event->{Id}) my $res = $sth->execute($Event->{Id})
or Fatal("Unable toexecute '$sql': ".$dbh->errstr()); or Fatal("Unable toexecute '$sql': ".$dbh->errstr());
return 1; return 1;
} } # end sub sendMessage
sub executeCommand { sub executeCommand {
my $filter = shift; my $filter = shift;

View File

@ -41,9 +41,10 @@ use autouse 'Pod::Usage'=>qw(pod2usage);
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $store_state=""; # PP - will remember state name passed my $store_state=''; # PP - will remember state name passed
logInit(); logInit();
Info("Aftere LogInit");
my $command = $ARGV[0]||''; my $command = $ARGV[0]||'';
if ( $command eq 'version' ) { if ( $command eq 'version' ) {
@ -53,28 +54,27 @@ if ( $command eq 'version' ) {
my $state; my $state;
my $dbh; my $dbh = zmDbConnect();
Info("Command: $command");
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) { if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) {
if ( $command ) { if ( $command ) {
$dbh = zmDbConnect();
# Check to see if it's a valid run state # Check to see if it's a valid run state
my $sql = 'SELECT * FROM States WHERE Name=?'; my $sql = 'SELECT * FROM States WHERE Name=?';
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute( $command ) my $res = $sth->execute($command)
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
if ( $state = $sth->fetchrow_hashref() ) { if ( $state = $sth->fetchrow_hashref() ) {
$state->{Name} = $command; #$state->{Name} = $command;
$state->{Definitions} = []; $state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) ) { foreach( split(',', $state->{Definition}) ) {
my ( $id, $function, $enabled ) = split( /:/, $_ ); my ( $id, $function, $enabled ) = split(':', $_);
push( @{$state->{Definitions}}, push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled } { Id=>$id, Function=>$function, Enabled=>$enabled }
); );
} }
$store_state=$command; # PP - Remember the name that was passed to search in DB $store_state = $command; # PP - Remember the name that was passed to search in DB
$command = 'state'; $command = 'state';
} else { } else {
$command = undef; $command = undef;
} }
@ -82,64 +82,64 @@ if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ )
if ( !$command ) { if ( !$command ) {
pod2usage(-exitstatus => -1); pod2usage(-exitstatus => -1);
} }
} } # end if not one of the usual commands
$dbh = zmDbConnect() if ! $dbh;
# PP - Sane state check # PP - Sane state check
isActiveSanityCheck(); isActiveSanityCheck();
# Move to the right place # Move to the right place
chdir( $Config{ZM_PATH_WEB} ) chdir($Config{ZM_PATH_WEB})
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" ); or Fatal("Can't chdir to '$Config{ZM_PATH_WEB}': $!");
my $dbg_id = ''; my $dbg_id = '';
Info( "Command: $command\n" ); Info("Command: $command");
my $retval = 0; my $retval = 0;
if ( $command eq 'state' ) { if ( $command eq 'state' ) {
Info( "Updating DB: $state->{Name}\n" ); Info("Updating DB: $state->{Name}");
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=? ORDER BY Id ASC' : 'SELECT * FROM Monitors ORDER BY Id ASC'; my $sql = 'SELECT * FROM Monitors' . ($Config{ZM_SERVER_ID} ? ' WHERE ServerId=?' : '' ) .' ORDER BY Id ASC';
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: () ) my $res = $sth->execute($Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: ())
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
while( my $monitor = $sth->fetchrow_hashref() ) { while( my $monitor = $sth->fetchrow_hashref() ) {
foreach my $definition ( @{$state->{Definitions}} ) { foreach my $definition ( @{$state->{Definitions}} ) {
if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) { if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) {
$monitor->{NewFunction} = $definition->{Function}; $monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled}; $monitor->{NewEnabled} = $definition->{Enabled};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
) {
my $sql = 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
or Fatal( "Can't execute: ".$sth->errstr() );
} }
} }
$sth->finish(); #next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
) {
my $sql = 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?';
my $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute($monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id})
or Fatal("Can't execute: ".$sth->errstr());
} # end if change of function or enablement
} # end foreach monitor
$sth->finish();
# PP - Now mark a specific state as active # PP - Now mark a specific state as active
resetStates(); resetStates();
Info ("Marking $store_state as Enabled"); Info("Marking $store_state as Enabled");
$sql = "UPDATE States SET IsActive = '1' WHERE Name = ?"; $sql = 'UPDATE States SET IsActive = 1 WHERE Name = ?';
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute( $store_state ) $res = $sth->execute($store_state)
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
# PP - zero out other states isActive # PP - zero out other states isActive
$command = 'restart'; $command = 'restart';
} } # end if command = state
# Check if we are running systemd and if we have been called by the system # Check if we are running systemd and if we have been called by the system
if ( $command =~ /^(start|stop|restart)$/ ) { if ( $command =~ /^(start|stop|restart)$/ ) {
@ -154,6 +154,7 @@ if ( $command =~ /^(start|stop|restart)$/ ) {
if ( $command =~ /^(?:stop|restart)$/ ) { if ( $command =~ /^(?:stop|restart)$/ ) {
my $status = runCommand('zmdc.pl check'); my $status = runCommand('zmdc.pl check');
Debug("zmdc.pl check = $status");
if ( $status eq 'running' ) { if ( $status eq 'running' ) {
runCommand('zmdc.pl shutdown'); runCommand('zmdc.pl shutdown');
@ -163,20 +164,19 @@ if ( $command =~ /^(?:stop|restart)$/ ) {
} }
} }
#runCommand( "zmupdate.pl -f" );
if ( $command =~ /^(?:start|restart)$/ ) { if ( $command =~ /^(?:start|restart)$/ ) {
my $status = runCommand('zmdc.pl check'); my $status = runCommand('zmdc.pl check');
Debug("zmdc.pl check = $status");
if ( $status eq 'stopped' ) { if ( $status eq 'stopped' ) {
if ( $Config{ZM_DYN_DB_VERSION} if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION ) and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
) { ) {
Fatal( 'Version mismatch, system is version '.ZM_VERSION Fatal('Version mismatch, system is version '.ZM_VERSION
.', database is '.$Config{ZM_DYN_DB_VERSION} .', database is '.$Config{ZM_DYN_DB_VERSION}
.', please run zmupdate.pl to update.' .', please run zmupdate.pl to update.'
); );
exit( -1 ); exit(-1);
} }
# Recreate the temporary directory if it's been wiped # Recreate the temporary directory if it's been wiped
@ -196,8 +196,8 @@ if ( $command =~ /^(?:start|restart)$/ ) {
my @values; my @values;
if ( $Config{ZM_SERVER_ID} ) { if ( $Config{ZM_SERVER_ID} ) {
require ZoneMinder::Server; require ZoneMinder::Server;
Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n"); Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}");
$Server = new ZoneMinder::Server( $Config{ZM_SERVER_ID} ); $Server = new ZoneMinder::Server($Config{ZM_SERVER_ID});
$sql = 'SELECT * FROM Monitors WHERE ServerId=?'; $sql = 'SELECT * FROM Monitors WHERE ServerId=?';
@values = ( $Config{ZM_SERVER_ID} ); @values = ( $Config{ZM_SERVER_ID} );
} else { } else {
@ -206,55 +206,58 @@ if ( $command =~ /^(?:start|restart)$/ ) {
} }
{ {
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute( @values ) my $res = $sth->execute(@values)
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
while( my $monitor = $sth->fetchrow_hashref() ) { while( my $monitor = $sth->fetchrow_hashref() ) {
if ( $monitor->{Function} ne 'None' && $monitor->{Type} ne 'WebSite' ) { if ( $monitor->{Function} ne 'None' && $monitor->{Type} ne 'WebSite' ) {
if ( $monitor->{Type} eq 'Local' ) { if ( $monitor->{Type} eq 'Local' ) {
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" ); runCommand("zmdc.pl start zmc -d $monitor->{Device}");
} else { } else {
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" ); runCommand("zmdc.pl start zmc -m $monitor->{Id}");
}
if ( $Config{ZM_OPT_CONTROL} ) {
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) {
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
}
} }
} if ( $Config{ZM_OPT_CONTROL} ) {
} if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) {
} if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
$sth->finish(); runCommand("zmdc.pl start zmtrack.pl -m $monitor->{Id}");
} else {
Warning('Monitor is set to track motion, but does not have motion detection enabled.');
} # end if Has motion enabled
} # end if track motion
} # end if ZM_OPT_CONTROL
} # end if function is not none or Website
} # end foreach monitor
$sth->finish();
} }
{ {
my $sql = 'SELECT Id FROM Filters WHERE Background=1'; my $sql = 'SELECT Id FROM Filters WHERE Background=1';
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute() my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
if ( $sth->rows ) { if ( $sth->rows ) {
while( my $filter = $sth->fetchrow_hashref() ) { while( my $filter = $sth->fetchrow_hashref() ) {
# This is now started unconditionally # This is now started unconditionally
runCommand("zmdc.pl start zmfilter.pl --filter_id=$$filter{Id}"); runCommand("zmdc.pl start zmfilter.pl --filter_id=$$filter{Id} --daemon");
}
} else {
runCommand('zmdc.pl start zmfilter.pl');
} }
} else { $sth->finish();
runCommand('zmdc.pl start zmfilter.pl');
}
$sth->finish();
} }
if ( $Config{ZM_RUN_AUDIT} ) { if ( $Config{ZM_RUN_AUDIT} ) {
if ( $Server and exists $$Server{'zmaudit'} and ! $$Server{'zmaudit'} ) { if ( $Server and exists $$Server{zmaudit} and ! $$Server{zmaudit} ) {
Debug("Not running zmaudit.pl because it is turned off for this server."); Debug('Not running zmaudit.pl because it is turned off for this server.');
} else { } else {
runCommand('zmdc.pl start zmaudit.pl -c'); runCommand('zmdc.pl start zmaudit.pl -c');
} }
} }
if ( $Config{ZM_OPT_TRIGGERS} ) { if ( $Config{ZM_OPT_TRIGGERS} ) {
if ( $Server and exists $$Server{'zmtrigger'} and ! $$Server{'zmtrigger'} ) { if ( $Server and exists $$Server{zmtrigger} and ! $$Server{zmtrigger} ) {
Debug("Not running zmtrigger.pl because it is turned off for this server."); Debug('Not running zmtrigger.pl because it is turned off for this server.');
} else { } else {
runCommand('zmdc.pl start zmtrigger.pl'); runCommand('zmdc.pl start zmtrigger.pl');
} }
@ -272,25 +275,25 @@ if ( $command =~ /^(?:start|restart)$/ ) {
if ($Config{ZM_OPT_USE_EVENTNOTIFICATION} ) { if ($Config{ZM_OPT_USE_EVENTNOTIFICATION} ) {
runCommand('zmdc.pl start zmeventnotification.pl'); runCommand('zmdc.pl start zmeventnotification.pl');
} }
if ( $Server and exists $$Server{'zmstats'} and ! $$Server{'zmstats'} ) { if ( $Server and exists $$Server{zmstats} and ! $$Server{zmstats} ) {
Debug("Not running zmstats.pl because it is turned off for this server."); Debug('Not running zmstats.pl because it is turned off for this server.');
} else { } else {
runCommand('zmdc.pl start zmstats.pl'); runCommand('zmdc.pl start zmstats.pl');
} }
} else { } else {
$retval = 1; $retval = 1;
} }
} } # end if command is start or restart
if ( $command eq 'status' ) { if ( $command eq 'status' ) {
my $status = runCommand('zmdc.pl check'); my $status = runCommand('zmdc.pl check');
print( STDOUT $status."\n" ); print(STDOUT $status."\n");
} elsif ( $command eq 'logrot' ) { } elsif ( $command eq 'logrot' ) {
runCommand('zmdc.pl logrot'); runCommand('zmdc.pl logrot');
} }
exit( $retval ); exit($retval);
# PP - Make sure isActive is on and only one # PP - Make sure isActive is on and only one
sub isActiveSanityCheck { sub isActiveSanityCheck {
@ -299,11 +302,11 @@ sub isActiveSanityCheck {
$dbh = zmDbConnect() if ! $dbh; $dbh = zmDbConnect() if ! $dbh;
# PP - First, make sure default exists and there is only one # PP - First, make sure default exists and there is only one
my $sql = "SELECT Name FROM States WHERE Name='default'"; my $sql = q`SELECT Name FROM States WHERE Name='default'`;
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute() my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
if ( $sth->rows != 1 ) { if ( $sth->rows != 1 ) {
# PP - no row, or too many rows. Either case is an error # PP - no row, or too many rows. Either case is an error
@ -313,68 +316,53 @@ sub isActiveSanityCheck {
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');"; $sql = q`"INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');`;
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
} }
# PP - Now make sure no two states have IsActive=1 # PP - Now make sure no two states have IsActive=1
$sql = "SELECT Name FROM States WHERE IsActive = '1'"; $sql = 'SELECT Name FROM States WHERE IsActive = 1';
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
if ( $sth->rows != 1 ) { if ( $sth->rows != 1 ) {
Info( 'Fixing States table so only one run state is active' ); Info('Fixing States table so only one run state is active');
resetStates(); resetStates();
$sql = "UPDATE States SET IsActive='1' WHERE Name='default'"; $sql = q`UPDATE States SET IsActive=1 WHERE Name='default'`;
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
} }
} } # end sub isActiveSanityCheck
# PP - zeroes out isActive for all states # PP - zeroes out isActive for all states
sub resetStates { sub resetStates {
$dbh = zmDbConnect() if ! $dbh; $dbh = zmDbConnect() if ! $dbh;
my $sql = "UPDATE States SET IsActive='0'"; my $sql = 'UPDATE States SET IsActive=0';
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute() my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal("Can't execute: ".$sth->errstr());
} }
sub systemdRunning { sub systemdRunning {
my $result = 0;
my $output = qx(ps -o comm="" -p 1); my $output = qx(ps -o comm="" -p 1);
chomp( $output ); return scalar ( $output =~ /systemd/ );
if ( $output =~ /systemd/ ) {
$result = 1;
}
return $result;
} }
sub calledBysystem { sub calledBysystem {
my $result = 0;
my $ppid = getppid(); my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid); my $output = qx(ps -o comm="" -p $ppid);
chomp( $output ); #chomp( $output );
if ($output =~ /^(?:systemd|init)$/) { return ($output =~ /^(?:systemd|init)$/);
$result = 1;
}
return $result;
} }
sub verifyFolder { sub verifyFolder {
@ -382,24 +370,22 @@ sub verifyFolder {
# Recreate the temporary directory if it's been wiped # Recreate the temporary directory if it's been wiped
if ( !-e $folder ) { if ( !-e $folder ) {
Debug( "Recreating directory '$folder'" ); Debug("Recreating directory '$folder'");
mkdir( $folder, 0774 ) mkdir($folder, 0774)
or Fatal( "Can't create missing temporary directory '$folder': $!" ); or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> ); my ( $runName ) = getpwuid($>);
if ( $runName ne $Config{ZM_WEB_USER} ) { if ( $runName ne $Config{ZM_WEB_USER} ) {
# Not running as web user, so should be root in which case # Not running as web user, so should be root in which case
# chown the directory # chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} ) my ( $webName, $webPass, $webUid, $webGid ) = getpwnam($Config{ZM_WEB_USER})
or Fatal( "Can't get user details for web user '" or Fatal("Can't get details for web user '$Config{ZM_WEB_USER}': $!");
.$Config{ZM_WEB_USER}."': $!" chown($webUid, $webGid, $folder)
or Fatal("Can't change ownership of '$folder' to '"
.$Config{ZM_WEB_USER}.':'.$Config{ZM_WEB_GROUP}."': $!"
); );
chown( $webUid, $webGid, "$folder" ) } # end if runName ne ZM_WEB_USER
or Fatal( "Can't change ownership of directory '$folder' to '" } # end if folder doesn't exist
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!" } # end sub verifyFolder
);
}
}
}
1; 1;
__END__ __END__

View File

@ -33,6 +33,7 @@ use LWP::UserAgent;
use Sys::MemInfo qw(totalmem); use Sys::MemInfo qw(totalmem);
use Sys::CPU qw(cpu_count); use Sys::CPU qw(cpu_count);
use POSIX qw(strftime uname); use POSIX qw(strftime uname);
use JSON::MaybeXS;
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
@ -87,7 +88,7 @@ while( 1 ) {
# We should keep *BSD systems in mind when calling system commands # We should keep *BSD systems in mind when calling system commands
my %telemetry; my %telemetry;
$telemetry{uuid} = getUUID($dbh); $telemetry{uuid} = getUUID($dbh);
$telemetry{ip} = getIP(); ($telemetry{city}, $telemetry{region}, $telemetry{country}, $telemetry{latitude}, $telemetry{longitude}) = getGeo();
$telemetry{timestamp} = strftime( '%Y-%m-%dT%H:%M:%S%z', localtime() ); $telemetry{timestamp} = strftime( '%Y-%m-%dT%H:%M:%S%z', localtime() );
$telemetry{monitor_count} = countQuery($dbh,'Monitors'); $telemetry{monitor_count} = countQuery($dbh,'Monitors');
$telemetry{event_count} = countQuery($dbh,'Events'); $telemetry{event_count} = countQuery($dbh,'Events');
@ -203,22 +204,25 @@ sub getUUID {
return $uuid; return $uuid;
} }
# Retrieves the local server's external IP address # Retrieve this server's general location information from a GeoIP database
sub getIP { sub getGeo {
my $ipaddr = '0.0.0.0'; my $unknown = 'Unknown';
my $endpoint = 'https://ipinfo.io/geo';
my $ua = LWP::UserAgent->new; my $ua = LWP::UserAgent->new;
my $server_endpoint = 'https://wiki.zoneminder.com/ip.php'; my $req = HTTP::Request->new(GET => $endpoint);
my $req = HTTP::Request->new(GET => $server_endpoint);
my $resp = $ua->request($req); my $resp = $ua->request($req);
my $resp_msg = $resp->decoded_content;
my $resp_code = $resp->code;
if ($resp->is_success) { if ($resp->is_success) {
$ipaddr = $resp->decoded_content; my $content = decode_json( $resp_msg );
(my $latitude, my $longitude) = split /,/, $content->{loc};
return ($content->{city}, $content->{region}, $content->{country}, $latitude, $longitude);
} else {
Warning("Geoip data retrieval returned HTTP POST error code: $resp_code");
Debug("Geoip data retrieval failure response message: $resp_msg");
return ($unknown, $unknown, $unknown, $unknown);
} }
Debug("Found external ip address of: $ipaddr");
return $ipaddr;
} }
# As the name implies, just your average mysql count query # As the name implies, just your average mysql count query

View File

@ -173,6 +173,12 @@ my $cwd = getcwd;
my $video_name; my $video_name;
my @event_ids; my @event_ids;
# Fail if the path to a valid ffmpeg binary is not set
if ( ! -x $Config{ZM_PATH_FFMPEG} ) {
Fatal("Ffmpeg binary not found or not executable. Verify ZM_PATH_FFMPEG points to ffmpeg, avconv, or a compatible binary.");
}
if ( $event_id ) { if ( $event_id ) {
@event_ids = ( $event_id ); @event_ids = ( $event_id );

View File

@ -69,41 +69,44 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
logInit(); logInit();
logSetSignal(); logSetSignal();
Info( "Watchdog starting, pausing for ".START_DELAY." seconds\n" ); Info('Watchdog starting, pausing for '.START_DELAY.' seconds');
sleep( START_DELAY ); sleep(START_DELAY);
my $dbh = zmDbConnect(); my $dbh = zmDbConnect();
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors'; my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql ) my $sth = $dbh->prepare_cached($sql)
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
while( 1 ) { while( 1 ) {
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal('Can\'t execute: '.$sth->errstr());
while( my $monitor = $sth->fetchrow_hashref() ) { while( my $monitor = $sth->fetchrow_hashref() ) {
my $now = time();
next if $monitor->{Function} eq 'None'; next if $monitor->{Function} eq 'None';
next if $monitor->{Type} eq 'WebSite'; next if $monitor->{Type} eq 'WebSite';
my $now = time();
my $restart = 0; my $restart = 0;
if ( zmMemVerify( $monitor ) ) { if ( zmMemVerify($monitor) ) {
# Check we have got an image recently # Check we have got an image recently
my $capture_time = zmGetLastWriteTime( $monitor ); my $capture_time = zmGetLastWriteTime($monitor);
if ( !defined($capture_time) ) { if ( !defined($capture_time) ) {
# Can't read from shared data # Can't read from shared data
Debug( "LastWriteTime is not defined." ); Debug('LastWriteTime is not defined.');
zmMemInvalidate( $monitor ); zmMemInvalidate($monitor);
next; next;
} }
Debug( "LastWriteTime is = $capture_time." ); Debug("Monitor $$monitor{Id} LastWriteTime is $capture_time.");
if ( !$capture_time ) { if ( !$capture_time ) {
my $startup_time = zmGetStartupTime( $monitor ); my $startup_time = zmGetStartupTime($monitor);
if ( $now - $startup_time > $Config{ZM_WATCH_MAX_DELAY} ) { if ( $now - $startup_time > $Config{ZM_WATCH_MAX_DELAY} ) {
Info( "Restarting capture daemon for ".$monitor->{Name}.", no image since startup. Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}\n" ); Info(
"Restarting capture daemon for $$monitor{Name}, no image since startup. ".
"Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}"
);
$restart = 1; $restart = 1;
} else { } else {
# We can't get the last capture time so can't be sure it's died, it might just be starting up. # We can't get the last capture time so can't be sure it's died, it might just be starting up.
zmMemInvalidate( $monitor ); zmMemInvalidate($monitor);
next; next;
} }
} }
@ -115,44 +118,44 @@ while( 1 ) {
: $Config{ZM_WATCH_MAX_DELAY} : $Config{ZM_WATCH_MAX_DELAY}
; ;
my $image_delay = $now-$capture_time; my $image_delay = $now-$capture_time;
Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" ); Debug("Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay");
if ( $image_delay > $max_image_delay ) { if ( $image_delay > $max_image_delay ) {
Info( "Restarting capture daemon for " Info("Restarting capture daemon for "
.$monitor->{Name}.", time since last capture $image_delay seconds ($now-$capture_time)\n" .$monitor->{Name}.", time since last capture $image_delay seconds ($now-$capture_time)"
); );
$restart = 1; $restart = 1;
} }
} # end if ! restart } # end if ! restart
} else { } else {
Info( "Restarting capture daemon for ".$monitor->{Name}.", shared data not valid\n" ); Info("Restarting capture daemon for $monitor->{Name}, shared data not valid");
$restart = 1; $restart = 1;
} }
if ( $restart ) { if ( $restart ) {
# Because zma depends on zmc, and zma can hold the shm in place, preventing zmc from using the space in /dev/shm, # Because zma depends on zmc, and zma can hold the shm in place, preventing zmc from using the space in /dev/shm,
# we need to stop zma before restarting zmc. # we need to stop zma before restarting zmc.
runCommand( "zmdc.pl stop zma -m $$monitor{Id}" ) if $monitor->{Function} ne 'Monitor'; runCommand("zmdc.pl stop zma -m $$monitor{Id}") if $monitor->{Function} ne 'Monitor';
my $command; my $command;
if ( $monitor->{Type} eq 'Local' ) { if ( $monitor->{Type} eq 'Local' ) {
$command = "zmdc.pl restart zmc -d $monitor->{Device}"; $command = "zmdc.pl restart zmc -d $monitor->{Device}";
} else { } else {
$command = "zmdc.pl restart zmc -m $monitor->{Id}"; $command = "zmdc.pl restart zmc -m $monitor->{Id}";
} }
runCommand( $command ); runCommand($command);
runCommand( "zmdc.pl start zma -m $$monitor{Id}" ) if $monitor->{Function} ne 'Monitor'; runCommand("zmdc.pl start zma -m $$monitor{Id}") if $monitor->{Function} ne 'Monitor';
} elsif ( $monitor->{Function} ne 'Monitor' ) { } elsif ( $monitor->{Function} ne 'Monitor' ) {
# Now check analysis daemon # Now check analysis daemon
$restart = 0; $restart = 0;
# Check we have got an image recently # Check we have got an image recently
my $image_time = zmGetLastReadTime( $monitor ); my $image_time = zmGetLastReadTime($monitor);
if ( !defined($image_time) ) { if ( !defined($image_time) ) {
# Can't read from shared data # Can't read from shared data
$restart = 1; $restart = 1;
Error("Error reading shared data for $$monitor{Id} $$monitor{Name}\n"); Error("Error reading shared data for $$monitor{Id} $$monitor{Name}");
} elsif ( !$image_time ) { } elsif ( !$image_time ) {
# We can't get the last capture time so can't be sure it's died. # We can't get the last capture time so can't be sure it's died.
$restart = 1; $restart = 1;
Error("Last analyse time for $$monitor{Id} $$monitor{Name} was zero.\n"); Error("Last analyse time for $$monitor{Id} $$monitor{Name} was zero.");
} else { } else {
my $max_image_delay = ( $monitor->{MaxFPS} my $max_image_delay = ( $monitor->{MaxFPS}
@ -162,34 +165,34 @@ while( 1 ) {
: $Config{ZM_WATCH_MAX_DELAY} : $Config{ZM_WATCH_MAX_DELAY}
; ;
my $image_delay = $now-$image_time; my $image_delay = $now-$image_time;
Debug( "Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay\n" ); Debug("Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay");
if ( $image_delay > $max_image_delay ) { if ( $image_delay > $max_image_delay ) {
Info( "Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting," Info("Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting,"
." time since last analysis $image_delay seconds ($now-$image_time)\n" ." time since last analysis $image_delay seconds ($now-$image_time)"
); );
$restart = 1; $restart = 1;
} }
} }
if ( $restart ) { if ( $restart ) {
Info( "Restarting analysis daemon for $$monitor{Id} $$monitor{Name}\n"); Info("Restarting analysis daemon for $$monitor{Id} $$monitor{Name}\n");
my $command; my $command;
if ( $monitor->{Type} eq 'Local' ) { if ( $monitor->{Type} eq 'Local' ) {
$command = "zmdc.pl restart zmc -d $monitor->{Device}"; $command = "zmdc.pl restart zmc -d $monitor->{Device}";
} else { } else {
$command = "zmdc.pl restart zmc -m $monitor->{Id}"; $command = "zmdc.pl restart zmc -m $monitor->{Id}";
} }
runCommand( $command ); runCommand($command);
} # end if restart } # end if restart
} # end if check analysis daemon } # end if check analysis daemon
# Prevent open handles building up if we have connect to shared memory # Prevent open handles building up if we have connect to shared memory
zmMemInvalidate( $monitor ); # Close our file handle to the zmc process we are about to end zmMemInvalidate($monitor); # Close our file handle to the zmc process we are about to end
} # end foreach monitor } # end foreach monitor
sleep( $Config{ZM_WATCH_CHECK_INTERVAL} ); sleep($Config{ZM_WATCH_CHECK_INTERVAL});
} # end while (1) } # end while (1)
Info( "Watchdog exiting\n" ); Info("Watchdog exiting");
exit(); exit();
1; 1;

View File

@ -104,7 +104,10 @@ public:
bool CanCapture() const { return( capture ); } bool CanCapture() const { return( capture ); }
bool SupportsNativeVideo() const { return( (type == FFMPEG_SRC )||(type == REMOTE_SRC)); } bool SupportsNativeVideo() const {
return (type == FFMPEG_SRC);
//return (type == FFMPEG_SRC )||(type == REMOTE_SRC);
}
virtual int PrimeCapture() { return( 0 ); } virtual int PrimeCapture() { return( 0 ); }
virtual int PreCapture()=0; virtual int PreCapture()=0;

View File

@ -24,7 +24,7 @@
#include "zm_db.h" #include "zm_db.h"
MYSQL dbconn; MYSQL dbconn;
Mutex db_mutex; RecursiveMutex db_mutex;
bool zmDbConnected = false; bool zmDbConnected = false;
@ -91,15 +91,15 @@ void zmDbClose() {
} }
MYSQL_RES * zmDbFetch(const char * query) { MYSQL_RES * zmDbFetch(const char * query) {
if ( ! zmDbConnected ) { if ( !zmDbConnected ) {
Error("Not connected."); Error("Not connected.");
return NULL; return NULL;
} }
db_mutex.lock(); db_mutex.lock();
if ( mysql_query(&dbconn, query) ) { if ( mysql_query(&dbconn, query) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
db_mutex.unlock(); db_mutex.unlock();
Error("Can't run query: %s", mysql_error(&dbconn));
return NULL; return NULL;
} }
Debug(4, "Success running query: %s", query); Debug(4, "Success running query: %s", query);

View File

@ -41,7 +41,7 @@ class zmDbRow {
}; };
extern MYSQL dbconn; extern MYSQL dbconn;
extern Mutex db_mutex; extern RecursiveMutex db_mutex;
bool zmDbConnect(); bool zmDbConnect();
void zmDbClose(); void zmDbClose();

View File

@ -67,7 +67,8 @@ Event::Event(
untimedEvent = true; untimedEvent = true;
start_time = now; start_time = now;
} else if ( start_time.tv_sec > now.tv_sec ) { } else if ( start_time.tv_sec > now.tv_sec ) {
Error("StartTime in the future %u.%u > %u.%u", Error(
"StartTime in the future %u.%u > %u.%u",
start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec
); );
start_time = now; start_time = now;
@ -89,8 +90,8 @@ Event::Event(
snprintf(sql, sizeof(sql), snprintf(sql, sizeof(sql),
"INSERT INTO Events " "INSERT INTO Events "
"( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme )" "( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme )"
" VALUES " " VALUES "
"( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '', %d, '%s' )", "( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '', %d, '%s' )",
monitor->Id(), monitor->Id(),
storage->Id(), storage->Id(),
start_time.tv_sec, start_time.tv_sec,
@ -183,12 +184,13 @@ Event::Event(
} }
// Create empty id tag file // Create empty id tag file
std::string id_file = stringtf("%s/.%" PRIu64, path, id); std::string id_file = stringtf("%s/.%" PRIu64, path.c_str(), id);
if ( FILE *id_fp = fopen(id_file.c_str(), "w") ) if ( FILE *id_fp = fopen(id_file.c_str(), "w") )
fclose(id_fp); fclose(id_fp);
else else
Error("Can't fopen %s: %s", id_file.c_str(), strerror(errno)); Error("Can't fopen %s: %s", id_file.c_str(), strerror(errno));
} // deep storage or not } // deep storage or not
Debug(2,"Created event %d at %s", id, path.c_str());
last_db_frame = 0; last_db_frame = 0;
@ -288,7 +290,7 @@ bool Event::WriteFrameImage(Image *image, struct timeval timestamp, const char *
int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default
bool rc; bool rc;
Debug(3, "Writing image to %s", event_file ); Debug(3, "Writing image to %s", event_file);
if ( !config.timestamp_on_capture ) { if ( !config.timestamp_on_capture ) {
// stash the image we plan to use in another pointer regardless if timestamped. // stash the image we plan to use in another pointer regardless if timestamped.
@ -436,7 +438,7 @@ void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, str
frames++; frames++;
static char event_file[PATH_MAX]; static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames); snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path.c_str(), frames);
if ( save_jpegs & 1 ) { if ( save_jpegs & 1 ) {
Debug(1, "Writing pre-capture frame %d", frames); Debug(1, "Writing pre-capture frame %d", frames);
WriteFrameImage(images[i], *(timestamps[i]), event_file); WriteFrameImage(images[i], *(timestamps[i]), event_file);
@ -446,7 +448,7 @@ void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, str
// neccessarily be of the motion. But some events are less than 10 frames, // neccessarily be of the motion. But some events are less than 10 frames,
// so I am changing this to 1, but we should overwrite it later with a better snapshot. // so I am changing this to 1, but we should overwrite it later with a better snapshot.
if ( frames == 1 ) { if ( frames == 1 ) {
std::string snapshot_file = std::string(path) + "/snapshot.jpg"; std::string snapshot_file = path + "/snapshot.jpg";
WriteFrameImage(images[i], *(timestamps[i]), snapshot_file.c_str()); WriteFrameImage(images[i], *(timestamps[i]), snapshot_file.c_str());
} }
} }
@ -508,7 +510,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
frames++; frames++;
static char event_file[PATH_MAX]; static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames); snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path.c_str(), frames);
if ( save_jpegs & 1 ) { if ( save_jpegs & 1 ) {
Debug(1, "Writing capture frame %d to %s", frames, event_file); Debug(1, "Writing capture frame %d to %s", frames, event_file);
@ -519,9 +521,9 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
//If this is the first frame, we should add a thumbnail to the event directory //If this is the first frame, we should add a thumbnail to the event directory
// On the first frame, max_score will be zero, this effectively makes us write out a thumbnail // On the first frame, max_score will be zero, this effectively makes us write out a thumbnail
// for the first frame as well. // for the first frame as well.
if ( score > max_score ) { if ( frames == 1 || score > (int)max_score ) {
std::string snapshot_file = std::string(path) + "/snapshot.jpg"; std::string snapshot_file = path + "/snapshot.jpg";
WriteFrameImage( image, timestamp, snapshot_file.c_str() ); WriteFrameImage(image, timestamp, snapshot_file.c_str());
} }
} }
@ -587,11 +589,12 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
max_score = score; max_score = score;
if ( alarm_image ) { if ( alarm_image ) {
snprintf(event_file, sizeof(event_file), staticConfig.analyse_file_format, path, frames);
Debug(1, "Writing analysis frame %d", frames);
if ( save_jpegs & 2 ) { if ( save_jpegs & 2 ) {
WriteFrameImage(alarm_image, timestamp, event_file, true); snprintf(event_file, sizeof(event_file), staticConfig.analyse_file_format, path.c_str(), frames);
Debug(1, "Writing analysis frame %d", frames);
if ( ! WriteFrameImage(alarm_image, timestamp, event_file, true) ) {
Error("Failed to write analysis frame image");
}
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,7 @@
#include <cstdarg> #include <cstdarg>
bool Logger::smInitialised = false; bool Logger::smInitialised = false;
Logger *Logger::smInstance = 0; Logger *Logger::smInstance = NULL;
Logger::StringMap Logger::smCodes; Logger::StringMap Logger::smCodes;
Logger::IntMap Logger::smSyslogPriorities; Logger::IntMap Logger::smSyslogPriorities;
@ -59,9 +59,9 @@ static void subtractTime( struct timeval * const tp1, struct timeval * const tp2
void Logger::usrHandler( int sig ) { void Logger::usrHandler( int sig ) {
Logger *logger = fetch(); Logger *logger = fetch();
if ( sig == SIGUSR1 ) if ( sig == SIGUSR1 )
logger->level( logger->level()+1 ); logger->level(logger->level()+1);
else if ( sig == SIGUSR2 ) else if ( sig == SIGUSR2 )
logger->level( logger->level()-1 ); logger->level(logger->level()-1);
Info("Logger - Level changed to %d", logger->level()); Info("Logger - Level changed to %d", logger->level());
} }
@ -80,7 +80,7 @@ Logger::Logger() :
mFlush(false) { mFlush(false) {
if ( smInstance ) { if ( smInstance ) {
Panic( "Attempt to create second instance of Logger class" ); Panic("Attempt to create second instance of Logger class");
} }
if ( !smInitialised ) { if ( !smInitialised ) {
@ -134,11 +134,11 @@ void Logger::initialise(const std::string &id, const Options &options) {
std::string tempLogFile; std::string tempLogFile;
if ( (envPtr = getTargettedEnv("LOG_FILE")) ) if ( (envPtr = getTargettedEnv("LOG_FILE")) ) {
tempLogFile = envPtr; tempLogFile = envPtr;
else if ( options.mLogFile.size() ) } else if ( options.mLogFile.size() ) {
tempLogFile = options.mLogFile; tempLogFile = options.mLogFile;
else { } else {
if ( options.mLogPath.size() ) { if ( options.mLogPath.size() ) {
mLogPath = options.mLogPath; mLogPath = options.mLogPath;
} }
@ -170,7 +170,7 @@ void Logger::initialise(const std::string &id, const Options &options) {
tempSyslogLevel = config.log_level_syslog >= DEBUG1 ? DEBUG9 : config.log_level_syslog; tempSyslogLevel = config.log_level_syslog >= DEBUG1 ? DEBUG9 : config.log_level_syslog;
// Legacy // Legacy
if ( (envPtr = getenv( "LOG_PRINT" )) ) if ( (envPtr = getenv("LOG_PRINT")) )
tempTerminalLevel = atoi(envPtr) ? DEBUG9 : NOLOG; tempTerminalLevel = atoi(envPtr) ? DEBUG9 : NOLOG;
if ( (envPtr = getTargettedEnv("LOG_LEVEL")) ) if ( (envPtr = getTargettedEnv("LOG_LEVEL")) )
@ -219,7 +219,7 @@ void Logger::initialise(const std::string &id, const Options &options) {
mFlush = false; mFlush = false;
if ( (envPtr = getenv("LOG_FLUSH")) ) { if ( (envPtr = getenv("LOG_FLUSH")) ) {
mFlush = atoi( envPtr ); mFlush = atoi(envPtr);
} else if ( config.log_debug ) { } else if ( config.log_debug ) {
mFlush = true; mFlush = true;
} }
@ -570,12 +570,12 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
} }
} }
void logInit( const char *name, const Logger::Options &options ) { void logInit(const char *name, const Logger::Options &options) {
if ( !Logger::smInstance ) if ( !Logger::smInstance )
Logger::smInstance = new Logger(); Logger::smInstance = new Logger();
Logger::Options tempOptions = options; Logger::Options tempOptions = options;
tempOptions.mLogPath = staticConfig.PATH_LOGS; tempOptions.mLogPath = staticConfig.PATH_LOGS;
Logger::smInstance->initialise( name, tempOptions ); Logger::smInstance->initialise(name, tempOptions);
} }
void logTerm() { void logTerm() {

View File

@ -890,6 +890,18 @@ bool Monitor::connect() {
exit(-1); exit(-1);
} }
} }
if ( purpose == ANALYSIS ) {
if ( analysis_fps ) {
// Size of pre event buffer must be greater than pre_event_count
// if alarm_frame_count > 1, because in this case the buffer contains
// alarmed images that must be discarded when event is created
pre_event_buffer_count = pre_event_count + alarm_frame_count - 1;
}
timestamps = new struct timeval *[pre_event_count];
images = new Image *[pre_event_count];
last_signal = shared_data->signal;
}
Debug(3, "Success connecting"); Debug(3, "Success connecting");
return true; return true;
@ -1523,7 +1535,6 @@ bool Monitor::CheckSignal( const Image *image ) {
void Monitor::CheckAction() { void Monitor::CheckAction() {
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if ( shared_data->action ) { if ( shared_data->action ) {
// Can there be more than 1 bit set in the action? Shouldn't these be elseifs? // Can there be more than 1 bit set in the action? Shouldn't these be elseifs?
if ( shared_data->action & RELOAD ) { if ( shared_data->action & RELOAD ) {
@ -1595,8 +1606,8 @@ bool Monitor::Analyse() {
// last_write_index is the last capture // last_write_index is the last capture
// last_read_index is the last analysis // last_read_index is the last analysis
if ( ! Enabled() ) { if ( !Enabled() ) {
Warning("SHouldn't be doing Analyze when not Enabled"); Warning("Shouldn't be doing Analyze when not Enabled");
return false; return false;
} }
@ -1726,7 +1737,7 @@ bool Monitor::Analyse() {
cause += ", "; cause += ", ";
cause += LINKED_CAUSE; cause += LINKED_CAUSE;
} }
noteSet.insert( linked_monitors[i]->Name() ); noteSet.insert(linked_monitors[i]->Name());
score += 50; score += 50;
} }
} // end foreach linked_monitor } // end foreach linked_monitor
@ -2326,19 +2337,17 @@ int Monitor::Capture() {
//Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); //Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time );
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps ); //Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
Info("%s: images:%d - Capturing at %.2lf fps, capturing bandwidth %ubytes/sec", name, image_count, new_capture_fps, new_capture_bandwidth); Info("%s: images:%d - Capturing at %.2lf fps, capturing bandwidth %ubytes/sec", name, image_count, new_capture_fps, new_capture_bandwidth);
if ( new_capture_fps != capture_fps ) { capture_fps = new_capture_fps;
capture_fps = new_capture_fps; last_fps_time = now;
last_fps_time = now; static char sql[ZM_SQL_SML_BUFSIZ];
static char sql[ZM_SQL_SML_BUFSIZ]; db_mutex.lock();
db_mutex.lock(); snprintf(sql, sizeof(sql),
snprintf(sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,CaptureFPS,CaptureBandwidth) VALUES (%d, %.2lf,%u) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf, CaptureBandwidth=%u",
"INSERT INTO Monitor_Status (MonitorId,CaptureFPS,CaptureBandwidth) VALUES (%d, %.2lf,%u) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf, CaptureBandwidth=%u", id, capture_fps, new_capture_bandwidth, capture_fps, new_capture_bandwidth);
id, capture_fps, new_capture_bandwidth, capture_fps, new_capture_bandwidth); if ( mysql_query(&dbconn, sql) ) {
if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn));
Error("Can't run query: %s", mysql_error(&dbconn)); }
} db_mutex.unlock();
db_mutex.unlock();
} // end if fps has changed
} }
} // end if report fps } // end if report fps
} else { // result == 0 } else { // result == 0

View File

@ -691,7 +691,7 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
} // end if buffered playback } // end if buffered playback
frame_count++; frame_count++;
} else { } else {
Debug(5,"Waiting for capture"); Debug(4,"Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) } // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))); unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));

View File

@ -55,6 +55,10 @@ RemoteCamera::~RemoteCamera() {
freeaddrinfo(hp); freeaddrinfo(hp);
hp = NULL; hp = NULL;
} }
if ( mAuthenticator ) {
delete mAuthenticator;
mAuthenticator = NULL;
}
} }
void RemoteCamera::Initialise() { void RemoteCamera::Initialise() {

View File

@ -73,7 +73,7 @@ public:
int Capture( ZMPacket &p ); int Capture( ZMPacket &p );
int PostCapture(); int PostCapture();
AVStream* get_VideoStream(); AVStream* get_VideoStream();
int Close() { return 0; }; int Close() { Disconnect(); return 0; };
}; };
#endif // ZM_REMOTE_CAMERA_HTTP_H #endif // ZM_REMOTE_CAMERA_HTTP_H

View File

@ -367,6 +367,6 @@ int RemoteCameraRtsp::Capture( ZMPacket &zm_packet ) {
} // end int RemoteCameraRtsp::Capture(ZMPacket &packet) } // end int RemoteCameraRtsp::Capture(ZMPacket &packet)
int RemoteCameraRtsp::PostCapture() { int RemoteCameraRtsp::PostCapture() {
return( 0 ); return 0;
} }
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT

View File

@ -27,15 +27,14 @@
namespace zm { namespace zm {
Authenticator::Authenticator( const std::string &username, const std::string &password) : Authenticator::Authenticator( const std::string &username, const std::string &password) :
fCnonce( "0a4f113b" ), fCnonce("0a4f113b"),
fUsername(username), fUsername(username),
fPassword(password) fPassword(password)
{ {
#ifdef HAVE_GCRYPT_H #ifdef HAVE_GCRYPT_H
// Special initialisation for libgcrypt // Special initialisation for libgcrypt
if ( !gcry_check_version( GCRYPT_VERSION ) ) if ( !gcry_check_version(GCRYPT_VERSION) ) {
{ Fatal("Unable to initialise libgcrypt");
Fatal( "Unable to initialise libgcrypt" );
} }
gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); gcry_control( GCRYCTL_DISABLE_SECMEM, 0 );
gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 );
@ -64,36 +63,34 @@ void Authenticator::authHandleHeader(std::string headerData)
size_t digest_match_len = strlen(digest_match); size_t digest_match_len = strlen(digest_match);
// Check if basic auth // Check if basic auth
if (strncasecmp(headerData.c_str(),basic_match,strlen(basic_match)) == 0) if ( strncasecmp(headerData.c_str(),basic_match,strlen(basic_match)) == 0 ) {
{
fAuthMethod = AUTH_BASIC; fAuthMethod = AUTH_BASIC;
Debug( 2, "Set authMethod to Basic"); Debug(2, "Set authMethod to Basic");
} }
// Check if digest auth // Check if digest auth
else if (strncasecmp( headerData.c_str(),digest_match,digest_match_len ) == 0) else if (strncasecmp( headerData.c_str(),digest_match,digest_match_len ) == 0) {
{
fAuthMethod = AUTH_DIGEST; fAuthMethod = AUTH_DIGEST;
Debug( 2, "Set authMethod to Digest"); Debug( 2, "Set authMethod to Digest");
StringVector subparts = split(headerData.substr(digest_match_len, headerData.length() - digest_match_len), ","); StringVector subparts = split(headerData.substr(digest_match_len, headerData.length() - digest_match_len), ",");
// subparts are key="value" // subparts are key="value"
for ( size_t i = 0; i < subparts.size(); i++ ) for ( size_t i = 0; i < subparts.size(); i++ ) {
{ StringVector kvPair = split(trimSpaces(subparts[i]), "=");
StringVector kvPair = split( trimSpaces( subparts[i] ), "=" ); std::string key = trimSpaces(kvPair[0]);
std::string key = trimSpaces( kvPair[0] ); if ( key == "realm" ) {
if (key == "realm") { fRealm = trimSet(kvPair[1], "\"");
fRealm = trimSet( kvPair[1], "\"");
continue; continue;
} }
if (key == "nonce") { if ( key == "nonce" ) {
fNonce = trimSet( kvPair[1], "\""); fNonce = trimSet(kvPair[1], "\"");
continue; continue;
} }
if (key == "qop") { if ( key == "qop" ) {
fQop = trimSet( kvPair[1], "\""); fQop = trimSet(kvPair[1], "\"");
continue; continue;
} }
} }
Debug( 2, "Auth data completed. User: %s, realm: %s, nonce: %s, qop: %s", username().c_str(), fRealm.c_str(), fNonce.c_str(), fQop.c_str() ); Debug(2, "Auth data completed. User: %s, realm: %s, nonce: %s, qop: %s",
username().c_str(), fRealm.c_str(), fNonce.c_str(), fQop.c_str());
} }
} }
@ -103,12 +100,9 @@ std::string Authenticator::quote( const std::string &src ) {
std::string Authenticator::getAuthHeader(std::string method, std::string uri) { std::string Authenticator::getAuthHeader(std::string method, std::string uri) {
std::string result = "Authorization: "; std::string result = "Authorization: ";
if (fAuthMethod == AUTH_BASIC) if (fAuthMethod == AUTH_BASIC) {
{
result += "Basic " + base64Encode( username() + ":" + password() ); result += "Basic " + base64Encode( username() + ":" + password() );
} } else if (fAuthMethod == AUTH_DIGEST) {
else if (fAuthMethod == AUTH_DIGEST)
{
result += std::string("Digest ") + result += std::string("Digest ") +
"username=\"" + quote(username()) + "\", realm=\"" + quote(realm()) + "\", " + "username=\"" + quote(username()) + "\", realm=\"" + quote(realm()) + "\", " +
"nonce=\"" + quote(nonce()) + "\", uri=\"" + quote(uri) + "\""; "nonce=\"" + quote(nonce()) + "\", uri=\"" + quote(uri) + "\"";
@ -153,8 +147,7 @@ std::string Authenticator::computeDigestResponse(std::string &method, std::strin
gnutls_datum_t md5dataha1 = { (unsigned char*)ha1Data.c_str(), ha1Data.length() }; gnutls_datum_t md5dataha1 = { (unsigned char*)ha1Data.c_str(), ha1Data.length() };
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha1, md5buf, &md5len ); gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha1, md5buf, &md5len );
#endif #endif
for ( unsigned int j = 0; j < md5len; j++ ) for ( unsigned int j = 0; j < md5len; j++ ) {
{
sprintf(&md5HexBuf[2*j], "%02x", md5buf[j] ); sprintf(&md5HexBuf[2*j], "%02x", md5buf[j] );
} }
md5HexBuf[md5len*2]='\0'; md5HexBuf[md5len*2]='\0';
@ -169,8 +162,7 @@ std::string Authenticator::computeDigestResponse(std::string &method, std::strin
gnutls_datum_t md5dataha2 = { (unsigned char*)ha2Data.c_str(), ha2Data.length() }; gnutls_datum_t md5dataha2 = { (unsigned char*)ha2Data.c_str(), ha2Data.length() };
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha2, md5buf, &md5len ); gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha2, md5buf, &md5len );
#endif #endif
for ( unsigned int j = 0; j < md5len; j++ ) for ( unsigned int j = 0; j < md5len; j++ ) {
{
sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] );
} }
md5HexBuf[md5len*2]='\0'; md5HexBuf[md5len*2]='\0';
@ -191,22 +183,21 @@ std::string Authenticator::computeDigestResponse(std::string &method, std::strin
gnutls_datum_t md5datadigest = { (unsigned char*)digestData.c_str(), digestData.length() }; gnutls_datum_t md5datadigest = { (unsigned char*)digestData.c_str(), digestData.length() };
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5datadigest, md5buf, &md5len ); gnutls_fingerprint( GNUTLS_DIG_MD5, &md5datadigest, md5buf, &md5len );
#endif #endif
for ( unsigned int j = 0; j < md5len; j++ ) for ( unsigned int j = 0; j < md5len; j++ ) {
{
sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] );
} }
md5HexBuf[md5len*2]='\0'; md5HexBuf[md5len*2]='\0';
return md5HexBuf; return md5HexBuf;
#else // HAVE_DECL_MD5 #else // HAVE_DECL_MD5
Error( "You need to build with gnutls or openssl installed to use digest authentication" ); Error("You need to build with gnutls or openssl installed to use digest authentication");
return( 0 ); return 0;
#endif // HAVE_DECL_MD5 #endif // HAVE_DECL_MD5
} }
void Authenticator::checkAuthResponse(std::string &response) { void Authenticator::checkAuthResponse(std::string &response) {
std::string authLine; std::string authLine;
StringVector lines = split( response, "\r\n" ); StringVector lines = split(response, "\r\n");
const char* authenticate_match = "WWW-Authenticate:"; const char* authenticate_match = "WWW-Authenticate:";
size_t authenticate_match_len = strlen(authenticate_match); size_t authenticate_match_len = strlen(authenticate_match);

View File

@ -97,6 +97,15 @@ bool Mutex::locked() {
return( state == EBUSY ); return( state == EBUSY );
} }
RecursiveMutex::RecursiveMutex() {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if ( pthread_mutex_init(&mMutex, &attr) < 0 )
Error("Unable to create pthread mutex: %s", strerror(errno));
}
Condition::Condition( Mutex &mutex ) : mMutex( mutex ) { Condition::Condition( Mutex &mutex ) : mMutex( mutex ) {
if ( pthread_cond_init( &mCondition, NULL ) < 0 ) if ( pthread_cond_init( &mCondition, NULL ) < 0 )
Fatal( "Unable to create pthread condition: %s", strerror(errno) ); Fatal( "Unable to create pthread condition: %s", strerror(errno) );

View File

@ -59,27 +59,34 @@ public:
}; };
class Mutex { class Mutex {
friend class Condition; friend class Condition;
private: private:
pthread_mutex_t mMutex; pthread_mutex_t mMutex;
public: public:
Mutex(); Mutex();
~Mutex(); ~Mutex();
private: private:
pthread_mutex_t *getMutex() { pthread_mutex_t *getMutex() {
return( &mMutex ); return &mMutex;
} }
public: public:
int trylock(); int trylock();
void lock(); void lock();
void lock( int secs ); void lock( int secs );
void lock( double secs ); void lock( double secs );
void unlock(); void unlock();
bool locked(); bool locked();
};
class RecursiveMutex : public Mutex {
private:
pthread_mutex_t mMutex;
public:
RecursiveMutex();
}; };
class ScopedMutex { class ScopedMutex {

View File

@ -376,7 +376,10 @@ int X264MP4Writer::x264config() {
x264params.b_annexb = 0; x264params.b_annexb = 0;
/* TODO: Setup error handler */ /* TODO: Setup error handler */
// x264params.i_log_level = X264_LOG_DEBUG; if ( logDebugging() )
x264params.i_log_level = X264_LOG_DEBUG;
else
x264params.i_log_level = X264_LOG_NONE;
/* Process user parameters (excluding preset, tune and profile) */ /* Process user parameters (excluding preset, tune and profile) */
for ( unsigned int i = 0; i < user_params.size(); i++ ) { for ( unsigned int i = 0; i < user_params.size(); i++ ) {

View File

@ -689,6 +689,10 @@ bool VideoStore::setup_resampler() {
audio_out_ctx->sample_fmt = audio_in_ctx->sample_fmt; audio_out_ctx->sample_fmt = audio_in_ctx->sample_fmt;
audio_out_ctx->channels = audio_in_ctx->channels; audio_out_ctx->channels = audio_in_ctx->channels;
audio_out_ctx->channel_layout = audio_in_ctx->channel_layout; audio_out_ctx->channel_layout = audio_in_ctx->channel_layout;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
#else
audio_out_ctx->refcounted_frames = 1;
#endif
if ( audio_out_codec->supported_samplerates ) { if ( audio_out_codec->supported_samplerates ) {
int found = 0; int found = 0;

View File

@ -17,12 +17,15 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
#define __STDC_FORMAT_MACROS 1
#include <cinttypes>
#include "zm.h" #include "zm.h"
#include "zm_db.h" #include "zm_db.h"
#include "zm_zone.h" #include "zm_zone.h"
#include "zm_image.h" #include "zm_image.h"
#include "zm_monitor.h" #include "zm_monitor.h"
void Zone::Setup( void Zone::Setup(
Monitor *p_monitor, Monitor *p_monitor,
int p_id, int p_id,

View File

@ -83,7 +83,7 @@ int main( int argc, char *argv[] ) {
while (1) { while (1) {
int option_index = 0; int option_index = 0;
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index); int c = getopt_long(argc, argv, "m:h:v", long_options, &option_index);
if ( c == -1 ) { if ( c == -1 ) {
break; break;
} }
@ -144,7 +144,7 @@ int main( int argc, char *argv[] ) {
unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay(); unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay();
time_t last_analysis_update_time, cur_time; time_t last_analysis_update_time, cur_time;
monitor->UpdateAdaptiveSkip(); monitor->UpdateAdaptiveSkip();
last_analysis_update_time = time( 0 ); last_analysis_update_time = time(0);
while( (!zm_terminate) && monitor->ShmValid() ) { while( (!zm_terminate) && monitor->ShmValid() ) {
// Process the next image // Process the next image
@ -181,5 +181,5 @@ int main( int argc, char *argv[] ) {
Image::Deinitialise(); Image::Deinitialise();
logTerm(); logTerm();
zmDbClose(); zmDbClose();
return( 0 ); return 0;
} }

View File

@ -386,5 +386,5 @@ int main(int argc, char *argv[]) {
logTerm(); logTerm();
zmDbClose(); zmDbClose();
return result; return zm_terminate ? 0 : result;
} }

View File

@ -46,7 +46,7 @@ bool ValidateAccess( User *user, int mon_id ) {
user->Id(), user->getUsername(), mon_id ); user->Id(), user->getUsername(), mon_id );
exit( -1 ); exit( -1 );
} }
return( allowed ); return allowed;
} }
int main( int argc, const char *argv[] ) { int main( int argc, const char *argv[] ) {
@ -74,45 +74,44 @@ int main( int argc, const char *argv[] ) {
unsigned int playback_buffer = 0; unsigned int playback_buffer = 0;
bool nph = false; bool nph = false;
const char *basename = strrchr( argv[0], '/' ); const char *basename = strrchr(argv[0], '/');
if (basename) //if we found a / lets skip past it if ( basename ) //if we found a / lets skip past it
basename++; basename++;
else //argv[0] will not always contain the full path, but rather just the script name else //argv[0] will not always contain the full path, but rather just the script name
basename = argv[0]; basename = argv[0];
const char *nph_prefix = "nph-"; const char *nph_prefix = "nph-";
if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) ) { if ( basename && !strncmp(basename, nph_prefix, strlen(nph_prefix)) ) {
nph = true; nph = true;
} }
zmLoadConfig(); zmLoadConfig();
const char *query = getenv("QUERY_STRING");
const char *query = getenv( "QUERY_STRING" );
if ( query ) { if ( query ) {
Debug( 1, "Query: %s", query ); Debug(1, "Query: %s", query);
char temp_query[1024]; char temp_query[1024];
strncpy( temp_query, query, sizeof(temp_query) ); strncpy(temp_query, query, sizeof(temp_query));
char *q_ptr = temp_query; char *q_ptr = temp_query;
char *parms[16]; // Shouldn't be more than this char *parms[16]; // Shouldn't be more than this
int parm_no = 0; int parm_no = 0;
while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) ) { while( (parm_no < 16) && (parms[parm_no] = strtok(q_ptr, "&")) ) {
parm_no++; parm_no++;
q_ptr = NULL; q_ptr = NULL;
} }
for ( int p = 0; p < parm_no; p++ ) { for ( int p = 0; p < parm_no; p++ ) {
char *name = strtok( parms[p], "=" ); char *name = strtok(parms[p], "=");
char *value = strtok( NULL, "=" ); char *value = strtok(NULL, "=");
if ( !value ) if ( !value )
value = (char *)""; value = (char *)"";
if ( !strcmp( name, "source" ) ) { if ( !strcmp(name, "source") ) {
source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR; source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
} else if ( !strcmp( name, "mode" ) ) { } else if ( !strcmp(name, "mode") ) {
mode = !strcmp( value, "jpeg" )?ZMS_JPEG:ZMS_MPEG; mode = !strcmp(value, "jpeg")?ZMS_JPEG:ZMS_MPEG;
mode = !strcmp( value, "raw" )?ZMS_RAW:mode; mode = !strcmp(value, "raw")?ZMS_RAW:mode;
mode = !strcmp( value, "zip" )?ZMS_ZIP:mode; mode = !strcmp(value, "zip")?ZMS_ZIP:mode;
mode = !strcmp( value, "single" )?ZMS_SINGLE:mode; mode = !strcmp(value, "single")?ZMS_SINGLE:mode;
} else if ( !strcmp( name, "format" ) ) { } else if ( !strcmp( name, "format" ) ) {
strncpy( format, value, sizeof(format) ); strncpy( format, value, sizeof(format) );
} else if ( !strcmp( name, "monitor" ) ) { } else if ( !strcmp( name, "monitor" ) ) {
@ -182,32 +181,32 @@ int main( int argc, const char *argv[] ) {
if ( config.opt_use_auth ) { if ( config.opt_use_auth ) {
User *user = 0; User *user = 0;
if ( strcmp( config.auth_relay, "none" ) == 0 ) { if ( strcmp(config.auth_relay, "none") == 0 ) {
if ( username.length() ) { if ( username.length() ) {
user = zmLoadUser( username.c_str() ); user = zmLoadUser(username.c_str());
} }
} else { } else {
//if ( strcmp( config.auth_relay, "hashed" ) == 0 ) //if ( strcmp( config.auth_relay, "hashed" ) == 0 )
{ {
if ( *auth ) { if ( *auth ) {
user = zmLoadAuthUser( auth, config.auth_hash_ips ); user = zmLoadAuthUser(auth, config.auth_hash_ips);
} }
} }
//else if ( strcmp( config.auth_relay, "plain" ) == 0 ) //else if ( strcmp( config.auth_relay, "plain" ) == 0 )
{ {
if ( username.length() && password.length() ) { if ( username.length() && password.length() ) {
user = zmLoadUser( username.c_str(), password.c_str() ); user = zmLoadUser(username.c_str(), password.c_str());
} }
} }
} }
if ( !user ) { if ( !user ) {
Error( "Unable to authenticate user" ); Error("Unable to authenticate user");
logTerm(); logTerm();
zmDbClose(); zmDbClose();
return( -1 ); return -1;
} }
ValidateAccess( user, monitor_id ); ValidateAccess(user, monitor_id);
} } // end if config.opt_use_auth
hwcaps_detect(); hwcaps_detect();
zmSetDefaultTermHandler(); zmSetDefaultTermHandler();

View File

@ -257,11 +257,14 @@ execpackpack () {
fi fi
if [ "${TRAVIS}" == "true" ]; then if [ "${TRAVIS}" == "true" ]; then
utils/packpack/heartbeat.sh & # Travis will fail the build if the output gets too long
mypid=$! # To mitigate that, use grep to filter out some of the noise
packpack/packpack $parms > buildlog.txt 2>&1 if [ "${ARCH}" != "armhf" ]; then
kill $mypid packpack/packpack $parms | grep -Ev '^(-- Installing:|-- Up-to-date:|Skip blib|Manifying|Installing /build|cp lib|writing output...|copying images...|reading sources...|[Working])'
tail -n 3000 buildlog.txt | grep -v ONVIF else
# Travis never ceases to amaze. For the case of arm emulation, Travis fails the build due to too little output over a 10 minute period. Facepalm.
packpack/packpack $parms | grep -Ev '^(-- Installing:|Skip blib|Manifying|Installing /build|cp lib|writing output...|copying images...|reading sources...|[Working])'
fi
else else
packpack/packpack $parms packpack/packpack $parms
fi fi

View File

@ -82,7 +82,7 @@ fi
# Don't stare too closely. You will burn your eyes out. # Don't stare too closely. You will burn your eyes out.
sed -i '/.*'${variable}'.*/{ sed -i '/.*'${variable}'.*/{
$!{ N $!{ N
s/\(.*'${variable}'.*\n.*\)\"\(.*\)\"/\1\"'"${default}"'\"/ s/\(.*'${variable}'.*\n.*\)'\''\(.*\)'\''/\1'\'''"${default}"''\''/
t yes t yes
P P
D D

View File

@ -1 +1 @@
1.31.44 1.31.45

View File

@ -1,40 +1,28 @@
<?php <?php
define( "MSG_TIMEOUT", 2.0 ); define("MSG_TIMEOUT", 2.0);
define( "MSG_DATA_SIZE", 4+256 ); define("MSG_DATA_SIZE", 4+256);
if ( canEdit( 'Monitors' ) ) if ( canEdit('Monitors') ) {
{ $zmuCommand = getZmuCommand(' -m '.validInt($_REQUEST['id']));
$zmuCommand = getZmuCommand( " -m ".validInt($_REQUEST['id']) );
switch ( validJsStr($_REQUEST['command']) ) switch ( validJsStr($_REQUEST['command']) ) {
{ case 'disableAlarms' :
case "disableAlarms" : $zmuCommand .= ' -n';
{
$zmuCommand .= " -n";
break; break;
} case 'enableAlarms' :
case "enableAlarms" : $zmuCommand .= ' -c';
{
$zmuCommand .= " -c";
break; break;
} case 'forceAlarm' :
case "forceAlarm" : $zmuCommand .= ' -a';
{
$zmuCommand .= " -a";
break; break;
} case 'cancelForcedAlarm' :
case "cancelForcedAlarm" : $zmuCommand .= ' -c';
{
$zmuCommand .= " -c";
break; break;
}
default : default :
{ ajaxError("Unexpected command '".validJsStr($_REQUEST['command'])."'");
ajaxError( "Unexpected command '".validJsStr($_REQUEST['command'])."'" );
}
} }
ajaxResponse( exec( escapeshellcmd( $zmuCommand ) ) ); ajaxResponse(exec(escapeshellcmd($zmuCommand)));
} else { } else {
ajaxError( 'Insufficient permissions' ); ajaxError('Insufficient permissions');
} }
?> ?>

View File

@ -1,28 +1,28 @@
<?php <?php
if ( empty($_REQUEST['id']) && empty($_REQUEST['eids']) ) { if ( empty($_REQUEST['id']) && empty($_REQUEST['eids']) ) {
ajaxError( 'No event id(s) supplied' ); ajaxError('No event id(s) supplied');
} }
if ( canView( 'Events' ) ) { if ( canView('Events') ) {
switch ( $_REQUEST['action'] ) { switch ( $_REQUEST['action'] ) {
case 'video' : case 'video' :
{ {
if ( empty($_REQUEST['videoFormat']) ) { if ( empty($_REQUEST['videoFormat']) ) {
ajaxError( 'Video Generation Failure, no format given' ); ajaxError('Video Generation Failure, no format given');
} elseif ( empty($_REQUEST['rate']) ) { } elseif ( empty($_REQUEST['rate']) ) {
ajaxError( 'Video Generation Failure, no rate given' ); ajaxError('Video Generation Failure, no rate given');
} elseif ( empty($_REQUEST['scale']) ) { } elseif ( empty($_REQUEST['scale']) ) {
ajaxError( 'Video Generation Failure, no scale given' ); ajaxError('Video Generation Failure, no scale given');
} else { } else {
$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 = ?'.monitorLimitSql(); $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 = ?'.monitorLimitSql();
if ( !($event = dbFetchOne( $sql, NULL, array( $_REQUEST['id'] ) )) ) if ( !($event = dbFetchOne($sql, NULL, array( $_REQUEST['id']))) ) {
ajaxError( 'Video Generation Failure, Unable to load event' ); ajaxError('Video Generation Failure, Unable to load event');
else { } else {
if ( $videoFile = createVideo( $event, $_REQUEST['videoFormat'], $_REQUEST['rate'], $_REQUEST['scale'], !empty($_REQUEST['overwrite']) ) ) if ( $videoFile = createVideo($event, $_REQUEST['videoFormat'], $_REQUEST['rate'], $_REQUEST['scale'], !empty($_REQUEST['overwrite'])) )
ajaxResponse( array( 'response'=>$videoFile ) ); ajaxResponse(array('response'=>$videoFile));
else else
ajaxError( 'Video Generation Failed' ); ajaxError('Video Generation Failed');
} }
} }
$ok = true; $ok = true;
@ -37,7 +37,7 @@ if ( canView( 'Events' ) ) {
} }
case 'export' : case 'export' :
{ {
require_once( ZM_SKIN_PATH.'/includes/export_functions.php' ); require_once(ZM_SKIN_PATH.'/includes/export_functions.php');
# We use session vars in here, so we need to restart the session because we stopped it in index.php to improve concurrency. # We use session vars in here, so we need to restart the session because we stopped it in index.php to improve concurrency.
session_start(); session_start();
@ -46,22 +46,27 @@ if ( canView( 'Events' ) ) {
$exportDetail = $_SESSION['export']['detail'] = $_REQUEST['exportDetail']; $exportDetail = $_SESSION['export']['detail'] = $_REQUEST['exportDetail'];
else else
$exportDetail = false; $exportDetail = false;
if ( !empty($_REQUEST['exportFrames']) ) if ( !empty($_REQUEST['exportFrames']) )
$exportFrames = $_SESSION['export']['frames'] = $_REQUEST['exportFrames']; $exportFrames = $_SESSION['export']['frames'] = $_REQUEST['exportFrames'];
else else
$exportFrames = false; $exportFrames = false;
if ( !empty($_REQUEST['exportImages']) ) if ( !empty($_REQUEST['exportImages']) )
$exportImages = $_SESSION['export']['images'] = $_REQUEST['exportImages']; $exportImages = $_SESSION['export']['images'] = $_REQUEST['exportImages'];
else else
$exportImages = false; $exportImages = false;
if ( !empty($_REQUEST['exportVideo']) ) if ( !empty($_REQUEST['exportVideo']) )
$exportVideo = $_SESSION['export']['video'] = $_REQUEST['exportVideo']; $exportVideo = $_SESSION['export']['video'] = $_REQUEST['exportVideo'];
else else
$exportVideo = false; $exportVideo = false;
if ( !empty($_REQUEST['exportMisc']) ) if ( !empty($_REQUEST['exportMisc']) )
$exportMisc = $_SESSION['export']['misc'] = $_REQUEST['exportMisc']; $exportMisc = $_SESSION['export']['misc'] = $_REQUEST['exportMisc'];
else else
$exportMisc = false; $exportMisc = false;
if ( !empty($_REQUEST['exportFormat']) ) if ( !empty($_REQUEST['exportFormat']) )
$exportFormat = $_SESSION['export']['format'] = $_REQUEST['exportFormat']; $exportFormat = $_SESSION['export']['format'] = $_REQUEST['exportFormat'];
else else
@ -70,67 +75,84 @@ if ( canView( 'Events' ) ) {
session_write_close(); session_write_close();
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id']; $exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
if ( $exportFile = exportEvents( $exportIds, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat ) ) if ( $exportFile = exportEvents(
ajaxResponse( array( 'exportFile'=>$exportFile ) ); $exportIds,
(isset($_REQUEST['connkey'])?$_REQUEST['connkey']:''),
$exportDetail,
$exportFrames,
$exportImages,
$exportVideo,
$exportMisc,
$exportFormat
) )
ajaxResponse(array('exportFile'=>$exportFile));
else else
ajaxError( 'Export Failed' ); ajaxError('Export Failed');
break; break;
} }
case 'download' : case 'download' :
{ {
require_once( ZM_SKIN_PATH.'/includes/export_functions.php' ); require_once(ZM_SKIN_PATH.'/includes/export_functions.php');
$exportVideo = 1; $exportVideo = 1;
$exportFormat = $_REQUEST['exportFormat']; $exportFormat = $_REQUEST['exportFormat'];
$exportStructure = 'flat'; $exportStructure = 'flat';
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id']; $exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
if ( $exportFile = exportEvents( $exportIds, false, false, false, $exportVideo, false, $exportFormat, $exportStructure ) ) if ( $exportFile = exportEvents(
ajaxResponse( array( 'exportFile'=>$exportFile ) ); $exportIds,
(isset($_REQUEST['connkey'])?$_REQUEST['connkey']:''),
false,false, false, $exportVideo, false, $exportFormat, $exportStructure ) )
ajaxResponse(array('exportFile'=>$exportFile));
else else
ajaxError( 'Export Failed' ); ajaxError('Export Failed');
break; break;
} }
} }
} } // end if canView('Events')
if ( canEdit( 'Events' ) ) { if ( canEdit('Events') ) {
switch ( $_REQUEST['action'] ) { switch ( $_REQUEST['action'] ) {
case 'rename' : case 'rename' :
{ {
if ( !empty($_REQUEST['eventName']) ) if ( !empty($_REQUEST['eventName']) )
dbQuery( 'UPDATE Events SET Name = ? WHERE Id = ?', array( $_REQUEST['eventName'], $_REQUEST['id'] ) ); dbQuery('UPDATE Events SET Name = ? WHERE Id = ?', array($_REQUEST['eventName'], $_REQUEST['id']));
else else
ajaxError( 'No new event name supplied' ); ajaxError('No new event name supplied');
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) ); ajaxResponse(array('refreshEvent'=>true, 'refreshParent'=>true));
break; break;
} }
case 'eventdetail' : case 'eventdetail' :
{ {
dbQuery( 'UPDATE Events SET Cause = ?, Notes = ? WHERE Id = ?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['id'] ) ); dbQuery(
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) ); 'UPDATE Events SET Cause = ?, Notes = ? WHERE Id = ?',
array($_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['id'])
);
ajaxResponse(array('refreshEvent'=>true, 'refreshParent'=>true));
break; break;
} }
case 'archive' : case 'archive' :
case 'unarchive' : case 'unarchive' :
{ {
$archiveVal = ($_REQUEST['action'] == 'archive')?1:0; $archiveVal = ($_REQUEST['action'] == 'archive')?1:0;
dbQuery( 'UPDATE Events SET Archived = ? WHERE Id = ?', array( $archiveVal, $_REQUEST['id']) ); dbQuery(
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>false ) ); 'UPDATE Events SET Archived = ? WHERE Id = ?',
array($archiveVal, $_REQUEST['id'])
);
ajaxResponse(array('refreshEvent'=>true, 'refreshParent'=>false));
break; break;
} }
case 'delete' : case 'delete' :
{ {
$Event = new Event( $_REQUEST['id'] ); $Event = new Event($_REQUEST['id']);
if ( ! $Event->Id() ) { if ( ! $Event->Id() ) {
ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.' ) ); ajaxResponse(array('refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.'));
} else { } else {
$Event->delete(); $Event->delete();
ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true ) ); ajaxResponse(array('refreshEvent'=>false, 'refreshParent'=>true));
} }
break; break;
} }
} }
} } // end if canEdit('Events')
ajaxError( 'Unrecognised action or insufficient permissions' );
ajaxError('Unrecognised action or insufficient permissions');
?> ?>

View File

@ -22,13 +22,9 @@ if ( sem_acquire($semaphore,1) !== false ) {
if ( file_exists( $localSocketFile ) ) { if ( file_exists( $localSocketFile ) ) {
Warning("sock file $localSocketFile already exists?! Is someone else talking to zms?"); Warning("sock file $localSocketFile already exists?! Is someone else talking to zms?");
// They could be. We can maybe have concurrent requests from a browser. // They could be. We can maybe have concurrent requests from a browser.
} else {
Logger::Debug("socket file does not exist, we should be good to connect.");
} }
if ( ! socket_bind( $socket, $localSocketFile ) ) { if ( ! socket_bind( $socket, $localSocketFile ) ) {
ajaxError( "socket_bind( $localSocketFile ) failed: ".socket_strerror(socket_last_error()) ); ajaxError("socket_bind( $localSocketFile ) failed: ".socket_strerror(socket_last_error()) );
} else {
Logger::Debug("Bound to $localSocketFile");
} }
switch ( $_REQUEST['command'] ) { switch ( $_REQUEST['command'] ) {
@ -81,7 +77,6 @@ if ( sem_acquire($semaphore,1) !== false ) {
$eSockets = NULL; $eSockets = NULL;
$timeout = MSG_TIMEOUT - ( time() - $start_time ); $timeout = MSG_TIMEOUT - ( time() - $start_time );
Logger::Debug("TImeout is: $timeout/1000 seconds. " );
$numSockets = socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 ); $numSockets = socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 );

View File

@ -27,114 +27,80 @@ App::uses('CrudControllerTrait', 'Crud.Lib');
* Add your application-wide methods in the class below, your controllers * Add your application-wide methods in the class below, your controllers
* will inherit them. * will inherit them.
* *
* @package app.Controller * @package app.Controller
* @link http://book.cakephp.org/2.0/en/controllers.html#the-app-controller * @link http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
*/ */
class AppController extends Controller { class AppController extends Controller {
use CrudControllerTrait; use CrudControllerTrait;
public $components = [ public $components = [
'Session', // We are going to use SessionHelper to check PHP session vars 'Session', // We are going to use SessionHelper to check PHP session vars
'RequestHandler', 'RequestHandler',
'Crud.Crud' => [ 'Crud.Crud' => [
'actions' => [ 'actions' => [
'index' => 'Crud.Index', 'index' => 'Crud.Index',
'add' => 'Crud.Add', 'add' => 'Crud.Add',
'edit' => 'Crud.Edit', 'edit' => 'Crud.Edit',
'view' => 'Crud.View', 'view' => 'Crud.View',
'keyvalue' => 'Crud.List', 'keyvalue' => 'Crud.List',
'category' => 'Crud.Category' 'category' => 'Crud.Category'
], ],
'listeners' => ['Api', 'ApiTransformation'] 'listeners' => ['Api', 'ApiTransformation']
#], #],
#'DebugKit.Toolbar' => [ #'DebugKit.Toolbar' => [
# 'bootstrap' => true, 'routes' => true # 'bootstrap' => true, 'routes' => true
] ]
]; ];
// Global beforeFilter function // Global beforeFilter function
//Zoneminder sets the username session variable //Zoneminder sets the username session variable
// to the logged in user. If this variable is set // to the logged in user. If this variable is set
// then you are logged in // then you are logged in
// its pretty simple to extend this to also check // its pretty simple to extend this to also check
// for role and deny API access in future // for role and deny API access in future
// Also checking to do this only if ZM_OPT_USE_AUTH is on // Also checking to do this only if ZM_OPT_USE_AUTH is on
public function beforeFilter() { public function beforeFilter() {
$this->loadModel('Config'); if ( ! ZM_OPT_USE_API ) {
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_API'));
$config = $this->Config->find('first', $options);
$zmOptApi = $config['Config']['Value'];
if ($zmOptApi !='1') {
throw new UnauthorizedException(__('API Disabled')); throw new UnauthorizedException(__('API Disabled'));
return; return;
} }
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH'));
$config = $this->Config->find('first', $options);
$zmOptAuth = $config['Config']['Value'];
if ( $zmOptAuth == '1' ) { # For use throughout the app. If not logged in, this will be null.
require_once "../../../includes/auth.php"; global $user;
$user = $this->Session->read('user');
if ( ZM_OPT_USE_AUTH ) {
require_once '../../../includes/auth.php';
$this->loadModel('User'); $mUser = $this->request->query('user') ? $this->request->query('user') : $this->request->data('user');
if ( isset($_REQUEST['user']) and isset($_REQUEST['pass']) ) { $mPassword = $this->request->query('pass') ? $this->request->query('pass') : $this->request->data('pass');
$user = $this->User->find('first', array ('conditions' => array ( $mAuth = $this->request->query('auth') ? $this->request->query('auth') : $this->request->data('auth');
'User.Username' => $_REQUEST['user'],
'User.Password' => $_REQUEST['pass'], if ( $mUser and $mPassword ) {
)) ); $user = userLogin($mUser, $mPassword);
if ( ! $user ) { if ( !$user ) {
throw new UnauthorizedException(__('User not found')); throw new UnauthorizedException(__('User not found or incorrect password'));
return;
}
} else if ( $mAuth ) {
$user = getAuthUser($mAuth);
if ( !$user ) {
throw new UnauthorizedException(__('Invalid Auth Key'));
return; return;
} else {
$this->Session->Write( 'user.Username', $user['User']['Username'] );
$this->Session->Write( 'user.Enabled', $user['User']['Enabled'] );
} }
} }
// We need to reject methods that are not authenticated
if ( isset($_REQUEST['auth']) ) { // besides login and logout
if ( strcasecmp($this->params->action, 'logout') ) {
$user = getAuthUser($_REQUEST['auth']); if ( !( $user and $user['Username'] ) ) {
if ( ! $user ) { throw new UnauthorizedException(__('Not Authenticated'));
throw new UnauthorizedException(__('User not found')); return;
} else if ( !( $user and $user['Enabled'] ) ) {
throw new UnauthorizedException(__('User is not enabled'));
return; return;
} else {
if ( ! $this->Session->Write('user.Username', $user['Username']) )
$this->log("Error writing session var user.Username");
if ( ! $this->Session->Write('user.Enabled', $user['Enabled']) )
$this->log("Error writing session var user.Enabled");
} }
} # end if REQUEST['auth'] } # end if ! login or logout
} # end if ZM_OPT_AUTH
if ( ! $this->Session->read('user.Username') ) {
throw new UnauthorizedException(__('Not Authenticated'));
return;
} else if ( ! $this->Session->read('user.Enabled') ) {
throw new UnauthorizedException(__('User is not enabled'));
return;
}
$options = array ('conditions' => array ('User.Username' => $this->Session->Read('user.Username')));
$userMonitors = $this->User->find('first', $options);
$this->Session->Write('allowedMonitors',$userMonitors['User']['MonitorIds']);
$this->Session->Write('streamPermission',$userMonitors['User']['Stream']);
$this->Session->Write('eventPermission',$userMonitors['User']['Events']);
$this->Session->Write('controlPermission',$userMonitors['User']['Control']);
$this->Session->Write('systemPermission',$userMonitors['User']['System']);
$this->Session->Write('monitorPermission',$userMonitors['User']['Monitors']);
} else {
// if auth is not on, you can do everything
//$userMonitors = $this->User->find('first', $options);
$this->Session->Write('allowedMonitors','');
$this->Session->Write('streamPermission','View');
$this->Session->Write('eventPermission','Edit');
$this->Session->Write('controlPermission','Edit');
$this->Session->Write('systemPermission','Edit');
$this->Session->Write('monitorPermission','Edit');
}
} # end function beforeFilter() } # end function beforeFilter()
} }

View File

@ -21,15 +21,18 @@ class ConfigsController extends AppController {
* *
* @return void * @return void
*/ */
public function index() { public function index() {
$this->Config->recursive = 0; global $configvals;
$configs = $this->Config->find('all'); $this->Config->recursive = 0;
$this->set(array( $configs = $this->Config->find('all');
'configs' => $configs, foreach ( $configvals as $k=>$v ) {
'_serialize' => array('configs') $configs[] = array( 'Config'=>array('Name'=>$k, 'Value'=>$v ) );
)); }
} $this->set(array(
'configs' => $configs,
'_serialize' => array('configs')
));
}
/** /**
* view method * view method
@ -53,8 +56,14 @@ class ConfigsController extends AppController {
public function viewByName($name = null) { public function viewByName($name = null) {
$config = $this->Config->findByName($name, array('fields' => 'Value')); $config = $this->Config->findByName($name, array('fields' => 'Value'));
if (!$config) { if ( !$config ) {
throw new NotFoundException(__('Invalid config')); global $configvals;
if ( $configvals[$name] ) {
$config = array( 'Config'=>array('Value'=>$configvals[$name]) );
} else {
throw new NotFoundException(__('Invalid config'));
}
} else {
} }
$this->set(array( $this->set(array(

View File

@ -1,5 +1,6 @@
<?php <?php
App::uses('AppController', 'Controller'); App::uses('AppController', 'Controller');
/** /**
* Events Controller * Events Controller
* *
@ -7,61 +8,63 @@ App::uses('AppController', 'Controller');
*/ */
class EventsController extends AppController { class EventsController extends AppController {
/** /**
* Components * Components
* *
* @var array * @var array
*/ */
public $components = array('RequestHandler', 'Scaler', 'Image', 'Paginator'); public $components = array('RequestHandler', 'Scaler', 'Image', 'Paginator');
public function beforeFilter() { public function beforeFilter() {
parent::beforeFilter(); parent::beforeFilter();
$canView = $this->Session->Read('eventPermission'); global $user;
if ($canView =='None') { $canView = (!$user) || ($user['Events'] != 'None');
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges')); throw new UnauthorizedException(__('Insufficient Privileges'));
return; return;
} }
} }
/** /**
* index method * index method
* *
* @return void * @return void
* This also creates a thumbnail for each event. * This also creates a thumbnail for each event.
*/ */
public function index() { public function index() {
$this->Event->recursive = -1; $this->Event->recursive = -1;
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
if (!empty($allowedMonitors)) { global $user;
$allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null;
if ( $allowedMonitors ) {
$mon_options = array('Event.MonitorId' => $allowedMonitors); $mon_options = array('Event.MonitorId' => $allowedMonitors);
} else { } else {
$mon_options=''; $mon_options = '';
} }
if ($this->request->params['named']) { if ( $this->request->params['named'] ) {
//$this->FilterComponent = $this->Components->load('Filter'); //$this->FilterComponent = $this->Components->load('Filter');
//$conditions = $this->FilterComponent->buildFilter($this->request->params['named']); //$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
$conditions = $this->request->params['named']; $conditions = $this->request->params['named'];
} else { } else {
$conditions = array(); $conditions = array();
} }
$settings = array( $settings = array(
// https://github.com/ZoneMinder/ZoneMinder/issues/995 // https://github.com/ZoneMinder/ZoneMinder/issues/995
// 'limit' => $limit['ZM_WEB_EVENTS_PER_PAGE'], // 'limit' => $limit['ZM_WEB_EVENTS_PER_PAGE'],
// 25 events per page which is what the above // 25 events per page which is what the above
// default is, is way too low for an API // default is, is way too low for an API
// changing this to 100 so we don't kill ZM // changing this to 100 so we don't kill ZM
// with many event APIs. In future, we can // with many event APIs. In future, we can
// make a nice ZM_API_ITEMS_PER_PAGE for all pagination // make a nice ZM_API_ITEMS_PER_PAGE for all pagination
// API // API
'limit' => '100', 'limit' => '100',
'order' => array('StartTime'), 'order' => array('StartTime'),
'paramType' => 'querystring', 'paramType' => 'querystring',
); );
if ( isset( $conditions['GroupId'] ) ) { if ( isset($conditions['GroupId']) ) {
$settings['joins'] = array( $settings['joins'] = array(
array( array(
'table' => 'Groups_Monitors', 'table' => 'Groups_Monitors',
@ -75,45 +78,46 @@ class EventsController extends AppController {
} }
$settings['conditions'] = array($conditions, $mon_options); $settings['conditions'] = array($conditions, $mon_options);
// How many events to return // How many events to return
$this->loadModel('Config'); $this->loadModel('Config');
$limit = $this->Config->find('list', array( $limit = $this->Config->find('list', array(
'conditions' => array('Name' => 'ZM_WEB_EVENTS_PER_PAGE'), 'conditions' => array('Name' => 'ZM_WEB_EVENTS_PER_PAGE'),
'fields' => array('Name', 'Value') 'fields' => array('Name', 'Value')
)); ));
$this->Paginator->settings = $settings; $this->Paginator->settings = $settings;
$events = $this->Paginator->paginate('Event'); $events = $this->Paginator->paginate('Event');
// For each event, get the frameID which has the largest score // For each event, get the frameID which has the largest score
foreach ($events as $key => $value) { foreach ( $events as $key => $value ) {
$maxScoreFrameId = $this->getMaxScoreAlarmFrameId($value['Event']['Id']); $maxScoreFrameId = $this->getMaxScoreAlarmFrameId($value['Event']['Id']);
$events[$key]['Event']['MaxScoreFrameId'] = $maxScoreFrameId; $events[$key]['Event']['MaxScoreFrameId'] = $maxScoreFrameId;
} }
$this->set(compact('events')); $this->set(compact('events'));
} } // end public function index()
/** /**
* view method * view method
* *
* @throws NotFoundException * @throws NotFoundException
* @param string $id * @param string $id
* @return void * @return void
*/ */
public function view($id = null) { public function view($id = null) {
$this->loadModel('Config'); $this->loadModel('Config');
$this->Event->recursive = 1; $this->Event->recursive = 1;
if (!$this->Event->exists($id)) { if ( !$this->Event->exists($id) ) {
throw new NotFoundException(__('Invalid event')); throw new NotFoundException(__('Invalid event'));
} }
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); global $user;
$allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null;
if (!empty($allowedMonitors)) { if ( $allowedMonitors ) {
$mon_options = array('Event.MonitorId' => $allowedMonitors); $mon_options = array('Event.MonitorId' => $allowedMonitors);
} else { } else {
$mon_options=''; $mon_options = '';
} }
$options = array('conditions' => array(array('Event.' . $this->Event->primaryKey => $id), $mon_options)); $options = array('conditions' => array(array('Event.' . $this->Event->primaryKey => $id), $mon_options));
@ -149,14 +153,16 @@ class EventsController extends AppController {
*/ */
public function add() { public function add() {
if ($this->Session->Read('eventPermission') != 'Edit') { global $user;
$canEdit = (!$user) || ($user['Events'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges')); throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
if ($this->request->is('post')) { if ( $this->request->is('post') ) {
$this->Event->create(); $this->Event->create();
if ($this->Event->save($this->request->data)) { if ( $this->Event->save($this->request->data) ) {
return $this->flash(__('The event has been saved.'), array('action' => 'index')); return $this->flash(__('The event has been saved.'), array('action' => 'index'));
} }
} }
@ -173,18 +179,20 @@ class EventsController extends AppController {
*/ */
public function edit($id = null) { public function edit($id = null) {
if ($this->Session->Read('eventPermission') != 'Edit') { global $user;
$canEdit = (!$user) || ($user['Events'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges')); throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
$this->Event->id = $id; $this->Event->id = $id;
if (!$this->Event->exists($id)) { if ( !$this->Event->exists($id) ) {
throw new NotFoundException(__('Invalid event')); throw new NotFoundException(__('Invalid event'));
} }
if ($this->Event->save($this->request->data)) { if ( $this->Event->save($this->request->data) ) {
$message = 'Saved'; $message = 'Saved';
} else { } else {
$message = 'Error'; $message = 'Error';
@ -204,16 +212,18 @@ class EventsController extends AppController {
* @return void * @return void
*/ */
public function delete($id = null) { public function delete($id = null) {
if ($this->Session->Read('eventPermission') != 'Edit') { global $user;
$canEdit = (!$user) || ($user['Events'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges')); throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
$this->Event->id = $id; $this->Event->id = $id;
if (!$this->Event->exists()) { if ( !$this->Event->exists() ) {
throw new NotFoundException(__('Invalid event')); throw new NotFoundException(__('Invalid event'));
} }
$this->request->allowMethod('post', 'delete'); $this->request->allowMethod('post', 'delete');
if ($this->Event->delete()) { if ( $this->Event->delete() ) {
//$this->loadModel('Frame'); //$this->loadModel('Frame');
//$this->Event->Frame->delete(); //$this->Event->Frame->delete();
return $this->flash(__('The event has been deleted.'), array('action' => 'index')); return $this->flash(__('The event has been deleted.'), array('action' => 'index'));
@ -228,7 +238,7 @@ class EventsController extends AppController {
foreach ($this->params['named'] as $param_name => $value) { foreach ($this->params['named'] as $param_name => $value) {
// Transform params into mysql // Transform params into mysql
if (preg_match("/interval/i", $value, $matches)) { if ( preg_match('/interval/i', $value, $matches) ) {
$condition = array("$param_name >= (date_sub(now(), $value))"); $condition = array("$param_name >= (date_sub(now(), $value))");
} else { } else {
$condition = array($param_name => $value); $condition = array($param_name => $value);
@ -254,12 +264,12 @@ class EventsController extends AppController {
$this->Event->recursive = -1; $this->Event->recursive = -1;
$results = array(); $results = array();
$moreconditions =""; $moreconditions = '';
foreach ($this->request->params['named'] as $name => $param) { foreach ($this->request->params['named'] as $name => $param) {
$moreconditions = $moreconditions . " AND ".$name.$param; $moreconditions = $moreconditions . ' AND '.$name.$param;
} }
$query = $this->Event->query("select MonitorId, COUNT(*) AS Count from Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;"); $query = $this->Event->query("SELECT MonitorId, COUNT(*) AS Count FROM Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;");
foreach ($query as $result) { foreach ($query as $result) {
$results[$result['Events']['MonitorId']] = $result[0]['Count']; $results[$result['Events']['MonitorId']] = $result[0]['Count'];
@ -275,7 +285,7 @@ class EventsController extends AppController {
public function createThumbnail($id = null) { public function createThumbnail($id = null) {
$this->Event->recursive = -1; $this->Event->recursive = -1;
if (!$this->Event->exists($id)) { if ( !$this->Event->exists($id) ) {
throw new NotFoundException(__('Invalid event')); throw new NotFoundException(__('Invalid event'));
} }
@ -285,13 +295,13 @@ class EventsController extends AppController {
// Find the max Frame for this Event. Error out otherwise. // Find the max Frame for this Event. Error out otherwise.
$this->loadModel('Frame'); $this->loadModel('Frame');
if (! $frame = $this->Frame->find('first', array( if ( !( $frame = $this->Frame->find('first', array(
'conditions' => array( 'conditions' => array(
'EventId' => $event['Event']['Id'], 'EventId' => $event['Event']['Id'],
'Score' => $event['Event']['MaxScore'] 'Score' => $event['Event']['MaxScore']
) )
))) { ))) ) {
throw new NotFoundException(__("Can not find Frame for Event " . $event['Event']['Id'])); throw new NotFoundException(__('Can not find Frame for Event ' . $event['Event']['Id']));
} }
$this->loadModel('Config'); $this->loadModel('Config');
@ -304,14 +314,15 @@ class EventsController extends AppController {
$config = $this->Config->find('list', array( $config = $this->Config->find('list', array(
'conditions' => array('OR' => array( 'conditions' => array('OR' => array(
'Name' => array('ZM_WEB_LIST_THUMB_WIDTH', 'Name' => array(
'ZM_WEB_LIST_THUMB_HEIGHT', 'ZM_WEB_LIST_THUMB_WIDTH',
'ZM_EVENT_IMAGE_DIGITS', 'ZM_WEB_LIST_THUMB_HEIGHT',
'ZM_DIR_IMAGES', 'ZM_EVENT_IMAGE_DIGITS',
$thumbs, 'ZM_DIR_IMAGES',
'ZM_DIR_EVENTS' $thumbs,
) 'ZM_DIR_EVENTS'
)), )
)),
'fields' => array('Name', 'Value') 'fields' => array('Name', 'Value')
)); ));
$config['ZM_WEB_SCALE_THUMBS'] = $config[$thumbs]; $config['ZM_WEB_SCALE_THUMBS'] = $config[$thumbs];
@ -335,12 +346,12 @@ class EventsController extends AppController {
$thumbData['Width'] = (int)$thumbWidth; $thumbData['Width'] = (int)$thumbWidth;
$thumbData['Height'] = (int)$thumbHeight; $thumbData['Height'] = (int)$thumbHeight;
return( $thumbData ); return $thumbData;
} }
public function archive($id = null) { public function archive($id = null) {
$this->Event->recursive = -1; $this->Event->recursive = -1;
if (!$this->Event->exists($id)) { if ( !$this->Event->exists($id) ) {
throw new NotFoundException(__('Invalid event')); throw new NotFoundException(__('Invalid event'));
} }
@ -365,7 +376,7 @@ class EventsController extends AppController {
public function getMaxScoreAlarmFrameId($id = null) { public function getMaxScoreAlarmFrameId($id = null) {
$this->Event->recursive = -1; $this->Event->recursive = -1;
if (!$this->Event->exists($id)) { if ( !$this->Event->exists($id) ) {
throw new NotFoundException(__('Invalid event')); throw new NotFoundException(__('Invalid event'));
} }
@ -382,7 +393,7 @@ class EventsController extends AppController {
'Score' => $event['Event']['MaxScore'] 'Score' => $event['Event']['MaxScore']
) )
))) { ))) {
throw new NotFoundException(__("Can not find Frame for Event " . $event['Event']['Id'])); throw new NotFoundException(__('Can not find Frame for Event ' . $event['Event']['Id']));
} }
return $frame['Frame']['Id']; return $frame['Frame']['Id'];
} }

View File

@ -2,133 +2,164 @@
App::uses('AppController', 'Controller'); App::uses('AppController', 'Controller');
class HostController extends AppController { class HostController extends AppController {
public $components = array('RequestHandler');
public function daemonCheck($daemon=false, $args=false) { public $components = array('RequestHandler', 'Session');
public function daemonCheck($daemon=false, $args=false) {
$string = Configure::read('ZM_PATH_BIN').'/zmdc.pl check'; $string = Configure::read('ZM_PATH_BIN').'/zmdc.pl check';
if ( $daemon ) { if ( $daemon ) {
$string .= " $daemon"; $string .= " $daemon";
if ( $args ) if ( $args )
$string .= " $args"; $string .= " $args";
} }
$result = exec($string); $result = exec($string);
$result = preg_match('/running/', $result); $result = preg_match('/running/', $result);
$this->set(array(
'result' => $result,
'_serialize' => array('result')
));
}
function getLoad() {
$load = sys_getloadavg();
$this->set(array(
'load' => $load,
'_serialize' => array('load')
));
}
function getCredentials() {
// ignore debug warnings from other functions
$this->view='Json';
$credentials = "";
$appendPassword = 0;
$this->loadModel('Config');
$isZmAuth = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')))['Config']['Value'];
if ($isZmAuth) {
$zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value'];
if ($zmAuthRelay == 'hashed') {
$zmAuthHashIps= $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value'];
$credentials = 'auth='.generateAuthHash($zmAuthHashIps);
}
elseif ($zmAuthRelay == 'plain') {
// user will need to append the store password here
$credentials = "user=".$this->Session->read('user.Username')."&pass=";
$appendPassword = 1;
}
elseif ($zmAuthRelay == 'none') {
$credentials = "user=".$this->Session->read('user.Username');
}
}
$this->set(array( $this->set(array(
'credentials'=> $credentials, 'result' => $result,
'append_password'=>$appendPassword, '_serialize' => array('result')
));
}
function getLoad() {
$load = sys_getloadavg();
$this->set(array(
'load' => $load,
'_serialize' => array('load')
));
}
function login() {
$cred = $this->_getCredentials();
$ver = $this->_getVersion();
$this->set(array(
'credentials' => $cred[0],
'append_password'=>$cred[1],
'version' => $ver[0],
'apiversion' => $ver[1],
'_serialize' => array('credentials',
'append_password',
'version',
'apiversion'
)));
} // end function login()
// clears out session
function logout() {
global $user;
$this->Session->Write('user', null);
$this->set(array(
'result' => 'ok',
'_serialize' => array('result')
));
} // end function logout()
private function _getCredentials() {
$credentials = '';
$appendPassword = 0;
$this->loadModel('Config');
$isZmAuth = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')))['Config']['Value'];
if ( $isZmAuth ) {
require_once "../../../includes/auth.php"; # in the event we directly call getCredentials.json
$this->Session->read('user'); # this is needed for command line/curl to recognize a session
$zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value'];
if ( $zmAuthRelay == 'hashed' ) {
$zmAuthHashIps= $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value'];
$credentials = 'auth='.generateAuthHash($zmAuthHashIps);
} else if ( $zmAuthRelay == 'plain' ) {
// user will need to append the store password here
$credentials = 'user='.$this->Session->read('user.Username').'&pass=';
$appendPassword = 1;
} else if ( $zmAuthRelay == 'none' ) {
$credentials = 'user='.$this->Session->read('user.Username');
}
}
return array($credentials, $appendPassword);
} // end function _getCredentials
function getCredentials() {
// ignore debug warnings from other functions
$this->view='Json';
$val = $this->_getCredentials();
$this->set(array(
'credentials'=> $val[0],
'append_password'=>$val[1],
'_serialize' => array('credentials', 'append_password') '_serialize' => array('credentials', 'append_password')
) ); ) );
} }
// If $mid is set, only return disk usage for that monitor
// If $mid is set, only return disk usage for that monitor
// Else, return an array of total disk usage, and per-monitor // Else, return an array of total disk usage, and per-monitor
// usage. // usage.
function getDiskPercent($mid = null) { function getDiskPercent($mid = null) {
$this->loadModel('Config'); $this->loadModel('Config');
$this->loadModel('Monitor'); $this->loadModel('Monitor');
// If $mid is passed, see if it is valid // If $mid is passed, see if it is valid
if ($mid) { if ($mid) {
if (!$this->Monitor->exists($mid)) { if (!$this->Monitor->exists($mid)) {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
} }
$zm_dir_events = $this->Config->find('list', array( $zm_dir_events = $this->Config->find('list', array(
'conditions' => array('Name' => 'ZM_DIR_EVENTS'), 'conditions' => array('Name' => 'ZM_DIR_EVENTS'),
'fields' => array('Name', 'Value') 'fields' => array('Name', 'Value')
)); ));
$zm_dir_events = $zm_dir_events['ZM_DIR_EVENTS' ]; $zm_dir_events = $zm_dir_events['ZM_DIR_EVENTS' ];
// Test to see if $zm_dir_events is relative or absolute // Test to see if $zm_dir_events is relative or absolute
if ('/' === "" || strrpos($zm_dir_events, '/', -strlen($zm_dir_events)) !== TRUE) { if ('/' === "" || strrpos($zm_dir_events, '/', -strlen($zm_dir_events)) !== TRUE) {
// relative - so add the full path // relative - so add the full path
$zm_dir_events = Configure::read('ZM_PATH_WEB') . '/' . $zm_dir_events; $zm_dir_events = Configure::read('ZM_PATH_WEB') . '/' . $zm_dir_events;
} }
if ($mid) { if ($mid) {
// Get disk usage for $mid // Get disk usage for $mid
$usage = shell_exec ("du -sh0 $zm_dir_events/$mid | awk '{print $1}'"); $usage = shell_exec ("du -sh0 $zm_dir_events/$mid | awk '{print $1}'");
} else { } else {
$monitors = $this->Monitor->find('all', array( $monitors = $this->Monitor->find('all', array(
'fields' => array('Id', 'Name', 'WebColour') 'fields' => array('Id', 'Name', 'WebColour')
)); ));
$usage = array(); $usage = array();
// Add each monitor's usage to array // Add each monitor's usage to array
foreach ($monitors as $key => $value) { foreach ($monitors as $key => $value) {
$id = $value['Monitor']['Id']; $id = $value['Monitor']['Id'];
$name = $value['Monitor']['Name']; $name = $value['Monitor']['Name'];
$color = $value['Monitor']['WebColour']; $color = $value['Monitor']['WebColour'];
$space = shell_exec ("du -s0 $zm_dir_events/$id | awk '{print $1}'"); $space = shell_exec ("du -s0 $zm_dir_events/$id | awk '{print $1}'");
if ($space == null) { if ($space == null) {
$space = 0; $space = 0;
} }
$space = $space/1024/1024; $space = $space/1024/1024;
$usage[$name] = array( $usage[$name] = array(
'space' => rtrim($space), 'space' => rtrim($space),
'color' => $color 'color' => $color
); );
} }
// Add total usage to array // Add total usage to array
$space = shell_exec( "df $zm_dir_events |tail -n1 | awk '{print $3 }'"); $space = shell_exec( "df $zm_dir_events |tail -n1 | awk '{print $3 }'");
$space = $space/1024/1024; $space = $space/1024/1024;
$usage['Total'] = array( $usage['Total'] = array(
'space' => rtrim($space), 'space' => rtrim($space),
'color' => '#F7464A' 'color' => '#F7464A'
); );
} }
$this->set(array( $this->set(array(
'usage' => $usage, 'usage' => $usage,
'_serialize' => array('usage') '_serialize' => array('usage')
)); ));
} }
function getTimeZone() { function getTimeZone() {
//http://php.net/manual/en/function.date-default-timezone-get.php //http://php.net/manual/en/function.date-default-timezone-get.php
@ -139,18 +170,18 @@ class HostController extends AppController {
)); ));
} }
function getVersion() { private function _getVersion() {
//throw new UnauthorizedException(__('API Disabled')); $version = Configure::read('ZM_VERSION');
$version = Configure::read('ZM_VERSION'); $apiversion = '1.0';
// not going to use the ZM_API_VERSION return array($version, $apiversion);
// requires recompilation and dependency on ZM upgrade }
//$apiversion = Configure::read('ZM_API_VERSION');
$apiversion = '1.0';
$this->set(array( function getVersion() {
'version' => $version, $val = $this->_getVersion();
'apiversion' => $apiversion, $this->set(array(
'_serialize' => array('version', 'apiversion') 'version' => $val[0],
)); 'apiversion' => $val[1],
} '_serialize' => array('version', 'apiversion')
));
}
} }

View File

@ -18,10 +18,13 @@ class MonitorsController extends AppController {
public function beforeRender() { public function beforeRender() {
$this->set($this->Monitor->enumValues()); $this->set($this->Monitor->enumValues());
} }
public function beforeFilter() { public function beforeFilter() {
parent::beforeFilter(); parent::beforeFilter();
$canView = $this->Session->Read('monitorPermission'); global $user;
if ($canView == 'None') { # We already tested for auth in appController, so we just need to test for specific permission
$canView = (!$user) || ($user['Monitors'] != 'None');
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges')); throw new UnauthorizedException(__('Insufficient Privileges'));
return; return;
} }
@ -35,7 +38,7 @@ class MonitorsController extends AppController {
public function index() { public function index() {
$this->Monitor->recursive = 0; $this->Monitor->recursive = 0;
if ($this->request->params['named']) { if ( $this->request->params['named'] ) {
$this->FilterComponent = $this->Components->load('Filter'); $this->FilterComponent = $this->Components->load('Filter');
//$conditions = $this->FilterComponent->buildFilter($this->request->params['named']); //$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
$conditions = $this->request->params['named']; $conditions = $this->request->params['named'];
@ -43,13 +46,14 @@ class MonitorsController extends AppController {
$conditions = array(); $conditions = array();
} }
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); global $user;
if (!empty($allowedMonitors)) { $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null;
if ( $allowedMonitors ) {
$conditions['Monitor.Id' ] = $allowedMonitors; $conditions['Monitor.Id' ] = $allowedMonitors;
} }
$find_array = array('conditions'=>$conditions,'contain'=>array('Group')); $find_array = array('conditions'=>$conditions,'contain'=>array('Group'));
if ( isset( $conditions['GroupId'] ) ) { if ( isset($conditions['GroupId']) ) {
$find_array['joins'] = array( $find_array['joins'] = array(
array( array(
'table' => 'Groups_Monitors', 'table' => 'Groups_Monitors',
@ -84,11 +88,12 @@ class MonitorsController extends AppController {
*/ */
public function view($id = null) { public function view($id = null) {
$this->Monitor->recursive = 0; $this->Monitor->recursive = 0;
if (!$this->Monitor->exists($id)) { if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); global $user;
if (!empty($allowedMonitors)) { $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null;
if ( $allowedMonitors ) {
$restricted = array('Monitor.' . $this->Monitor->primaryKey => $allowedMonitors); $restricted = array('Monitor.' . $this->Monitor->primaryKey => $allowedMonitors);
} else { } else {
$restricted = ''; $restricted = '';
@ -114,13 +119,15 @@ class MonitorsController extends AppController {
public function add() { public function add() {
if ( $this->request->is('post') ) { if ( $this->request->is('post') ) {
if ( $this->Session->Read('systemPermission') != 'Edit' ) { global $user;
throw new UnauthorizedException(__('Insufficient privileges')); $canAdd = (!$user) || ($user['System'] == 'Edit' );
if ( !$canAdd ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
$this->Monitor->create(); $this->Monitor->create();
if ($this->Monitor->save($this->request->data)) { if ( $this->Monitor->save($this->request->data) ) {
$this->daemonControl($this->Monitor->id, 'start'); $this->daemonControl($this->Monitor->id, 'start');
//return $this->flash(__('The monitor has been saved.'), array('action' => 'index')); //return $this->flash(__('The monitor has been saved.'), array('action' => 'index'));
$message = 'Saved'; $message = 'Saved';
@ -144,10 +151,12 @@ class MonitorsController extends AppController {
public function edit($id = null) { public function edit($id = null) {
$this->Monitor->id = $id; $this->Monitor->id = $id;
if (!$this->Monitor->exists($id)) { if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
if ($this->Session->Read('monitorPermission') != 'Edit') { global $user;
$canEdit = (!$user) || ($user['Monitors'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges')); throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
@ -163,9 +172,17 @@ class MonitorsController extends AppController {
// - restart or stop this monitor after change // - restart or stop this monitor after change
$func = $Monitor['Function']; $func = $Monitor['Function'];
// We don't pass the request data as the monitor object because it may be a subset of the full monitor array // We don't pass the request data as the monitor object because it may be a subset of the full monitor array
$this->daemonControl( $this->Monitor->id, 'stop' ); $this->daemonControl($this->Monitor->id, 'stop');
if ( ( $func != 'None' ) and ( (!defined('ZM_SERVER_ID')) or ($Monitor['ServerId']==ZM_SERVER_ID) ) ) { if (
$this->daemonControl( $this->Monitor->id, 'start' ); ( $func != 'None' )
and
(
(!defined('ZM_SERVER_ID'))
or
($Monitor['ServerId']==ZM_SERVER_ID)
)
) {
$this->daemonControl($this->Monitor->id, 'start');
} }
} else { } else {
$message = 'Error ' . print_r($this->Monitor->invalidFields(), true); $message = 'Error ' . print_r($this->Monitor->invalidFields(), true);
@ -187,10 +204,10 @@ class MonitorsController extends AppController {
*/ */
public function delete($id = null) { public function delete($id = null) {
$this->Monitor->id = $id; $this->Monitor->id = $id;
if (!$this->Monitor->exists()) { if ( !$this->Monitor->exists() ) {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
if ($this->Session->Read('systemPermission') != 'Edit') { if ( $this->Session->Read('systemPermission') != 'Edit' ) {
throw new UnauthorizedException(__('Insufficient privileges')); throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
@ -198,7 +215,7 @@ class MonitorsController extends AppController {
$this->daemonControl($this->Monitor->id, 'stop'); $this->daemonControl($this->Monitor->id, 'stop');
if ($this->Monitor->delete()) { if ( $this->Monitor->delete() ) {
return $this->flash(__('The monitor has been deleted.'), array('action' => 'index')); return $this->flash(__('The monitor has been deleted.'), array('action' => 'index'));
} else { } else {
return $this->flash(__('The monitor could not be deleted. Please, try again.'), array('action' => 'index')); return $this->flash(__('The monitor could not be deleted. Please, try again.'), array('action' => 'index'));
@ -206,7 +223,7 @@ class MonitorsController extends AppController {
} }
public function sourceTypes() { public function sourceTypes() {
$sourceTypes = $this->Monitor->query("describe Monitors Type;"); $sourceTypes = $this->Monitor->query('describe Monitors Type;');
preg_match('/^enum\((.*)\)$/', $sourceTypes[0]['COLUMNS']['Type'], $matches); preg_match('/^enum\((.*)\)$/', $sourceTypes[0]['COLUMNS']['Type'], $matches);
foreach( explode(',', $matches[1]) as $value ) { foreach( explode(',', $matches[1]) as $value ) {
@ -226,7 +243,7 @@ class MonitorsController extends AppController {
public function alarm() { public function alarm() {
$id = $this->request->params['named']['id']; $id = $this->request->params['named']['id'];
$cmd = strtolower($this->request->params['named']['command']); $cmd = strtolower($this->request->params['named']['command']);
if (!$this->Monitor->exists($id)) { if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
if ( $cmd != 'on' && $cmd != 'off' && $cmd != 'status' ) { if ( $cmd != 'on' && $cmd != 'off' && $cmd != 'status' ) {
@ -252,19 +269,18 @@ class MonitorsController extends AppController {
// form auth key based on auth credentials // form auth key based on auth credentials
$this->loadModel('Config'); $this->loadModel('Config');
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')); $options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH'));
$config = $this->Config->find('first', $options); $config = $this->Config->find('first', $options);
$zmOptAuth = $config['Config']['Value']; $zmOptAuth = $config['Config']['Value'];
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')); $options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY'));
$config = $this->Config->find('first', $options); $config = $this->Config->find('first', $options);
$zmAuthRelay = $config['Config']['Value']; $zmAuthRelay = $config['Config']['Value'];
$auth=''; $auth = '';
if ( $zmOptAuth ) { if ( $zmOptAuth ) {
if ( $zmAuthRelay == 'hashed' ) { if ( $zmAuthRelay == 'hashed' ) {
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_SECRET')); $options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_SECRET'));
$config = $this->Config->find('first', $options); $config = $this->Config->find('first', $options);
$zmAuthHashSecret = $config['Config']['Value']; $zmAuthHashSecret = $config['Config']['Value'];
$time = localtime(); $time = localtime();
@ -293,7 +309,7 @@ class MonitorsController extends AppController {
$id = $this->request->params['named']['id']; $id = $this->request->params['named']['id'];
$daemon = $this->request->params['named']['daemon']; $daemon = $this->request->params['named']['daemon'];
if (!$this->Monitor->exists($id)) { if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
@ -306,7 +322,7 @@ class MonitorsController extends AppController {
$monitor = Set::extract('/Monitor/.', $monitor); $monitor = Set::extract('/Monitor/.', $monitor);
// Pass -d for local, otherwise -m // Pass -d for local, otherwise -m
if ($monitor[0]['Type'] == 'Local') { if ( $monitor[0]['Type'] == 'Local' ) {
$args = '-d '. $monitor[0]['Device']; $args = '-d '. $monitor[0]['Device'];
} else { } else {
$args = '-m '. $monitor[0]['Id']; $args = '-m '. $monitor[0]['Id'];
@ -315,7 +331,7 @@ class MonitorsController extends AppController {
// Build the command, and execute it // Build the command, and execute it
$zm_path_bin = Configure::read('ZM_PATH_BIN'); $zm_path_bin = Configure::read('ZM_PATH_BIN');
$command = escapeshellcmd("$zm_path_bin/zmdc.pl status $daemon $args"); $command = escapeshellcmd("$zm_path_bin/zmdc.pl status $daemon $args");
$status = exec( $command ); $status = exec($command);
// If 'not' is present, the daemon is not running, so return false // If 'not' is present, the daemon is not running, so return false
// https://github.com/ZoneMinder/ZoneMinder/issues/799#issuecomment-108996075 // https://github.com/ZoneMinder/ZoneMinder/issues/799#issuecomment-108996075
@ -332,25 +348,18 @@ class MonitorsController extends AppController {
} }
public function daemonControl($id, $command, $monitor=null, $daemon=null) { public function daemonControl($id, $command, $monitor=null, $daemon=null) {
$args = '';
$daemons = array(); $daemons = array();
if (!$monitor) { if ( !$monitor ) {
// Need to see if it is local or remote // Need to see if it is local or remote
$monitor = $this->Monitor->find('first', array( $monitor = $this->Monitor->find('first', array(
'fields' => array('Type', 'Function'), 'fields' => array('Type', 'Function', 'Device'),
'conditions' => array('Id' => $id) 'conditions' => array('Id' => $id)
)); ));
$monitor = $monitor['Monitor']; $monitor = $monitor['Monitor'];
} }
if ($monitor['Type'] == 'Local') { if ( $monitor['Function'] == 'Monitor' ) {
$args = '-d ' . $monitor['Device'];
} else {
$args = '-m ' . $id;
}
if ($monitor['Function'] == 'Monitor') {
array_push($daemons, 'zmc'); array_push($daemons, 'zmc');
} else { } else {
array_push($daemons, 'zmc', 'zma'); array_push($daemons, 'zmc', 'zma');
@ -358,10 +367,16 @@ class MonitorsController extends AppController {
$zm_path_bin = Configure::read('ZM_PATH_BIN'); $zm_path_bin = Configure::read('ZM_PATH_BIN');
foreach ($daemons as $daemon) { foreach ( $daemons as $daemon ) {
$args = '';
if ( $daemon == 'zmc' and $monitor['Type'] == 'Local' ) {
$args = '-d ' . $monitor['Device'];
} else {
$args = '-m ' . $id;
}
$shellcmd = escapeshellcmd("$zm_path_bin/zmdc.pl $command $daemon $args"); $shellcmd = escapeshellcmd("$zm_path_bin/zmdc.pl $command $daemon $args");
$status = exec( $shellcmd ); $status = exec( $shellcmd );
} }
} }
} // end class MonitorsController } // end class MonitorsController

View File

@ -8,7 +8,6 @@ App::uses('AppController', 'Controller');
*/ */
class ServersController extends AppController { class ServersController extends AppController {
/** /**
* Components * Components
* *
@ -16,18 +15,16 @@ class ServersController extends AppController {
*/ */
public $components = array('Paginator', 'RequestHandler'); public $components = array('Paginator', 'RequestHandler');
public function beforeFilter() {
public function beforeFilter() { parent::beforeFilter();
parent::beforeFilter(); global $user;
$canView = $this->Session->Read('streamPermission'); $canView = (!$user) || ($user['System'] != 'None');
if ($canView =='None') { if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges')); throw new UnauthorizedException(__('Insufficient Privileges'));
return; return;
}
} }
}
/** /**
* index method * index method
* *
@ -36,7 +33,7 @@ public function beforeFilter() {
public function index() { public function index() {
$this->Server->recursive = 0; $this->Server->recursive = 0;
$options=''; $options = '';
$servers = $this->Server->find('all',$options); $servers = $this->Server->find('all',$options);
$this->set(array( $this->set(array(
'servers' => $servers, 'servers' => $servers,
@ -76,16 +73,17 @@ public function beforeFilter() {
* @return void * @return void
*/ */
public function add() { public function add() {
if ($this->request->is('post')) { if ( $this->request->is('post') ) {
if ($this->Session->Read('systemPermission') != 'Edit') global $user;
{ $canEdit = (!$user) || ($user['System'] == 'Edit');
throw new UnauthorizedException(__('Insufficient privileges')); if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
$this->Server->create(); $this->Server->create();
if ($this->Server->save($this->request->data)) { if ( $this->Server->save($this->request->data) ) {
# Might be nice to send it a start request # Might be nice to send it a start request
#$this->daemonControl($this->Server->id, 'start', $this->request->data); #$this->daemonControl($this->Server->id, 'start', $this->request->data);
return $this->flash(__('The server has been saved.'), array('action' => 'index')); return $this->flash(__('The server has been saved.'), array('action' => 'index'));
@ -103,15 +101,17 @@ public function beforeFilter() {
public function edit($id = null) { public function edit($id = null) {
$this->Server->id = $id; $this->Server->id = $id;
if (!$this->Server->exists($id)) { global $user;
throw new NotFoundException(__('Invalid server')); $canEdit = (!$user) || ($user['System'] == 'Edit');
} if ( !$canEdit ) {
if ($this->Session->Read('systemPermission') != 'Edit') throw new UnauthorizedException(__('Insufficient privileges'));
{
throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
if ($this->Server->save($this->request->data)) {
if ( !$this->Server->exists($id) ) {
throw new NotFoundException(__('Invalid server'));
}
if ( $this->Server->save($this->request->data) ) {
$message = 'Saved'; $message = 'Saved';
} else { } else {
$message = 'Error'; $message = 'Error';
@ -133,20 +133,22 @@ public function beforeFilter() {
* @return void * @return void
*/ */
public function delete($id = null) { public function delete($id = null) {
$this->Server->id = $id; global $user;
if (!$this->Server->exists()) { $canEdit = (!$user) || ($user['System'] == 'Edit');
throw new NotFoundException(__('Invalid server')); if ( !$canEdit ) {
} throw new UnauthorizedException(__('Insufficient privileges'));
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
$this->Server->id = $id;
if ( !$this->Server->exists() ) {
throw new NotFoundException(__('Invalid server'));
}
$this->request->allowMethod('post', 'delete'); $this->request->allowMethod('post', 'delete');
#$this->daemonControl($this->Server->id, 'stop'); #$this->daemonControl($this->Server->id, 'stop');
if ($this->Server->delete()) { if ( $this->Server->delete() ) {
return $this->flash(__('The server has been deleted.'), array('action' => 'index')); return $this->flash(__('The server has been deleted.'), array('action' => 'index'));
} else { } else {
return $this->flash(__('The server could not be deleted. Please, try again.'), array('action' => 'index')); return $this->flash(__('The server could not be deleted. Please, try again.'), array('action' => 'index'));

View File

@ -12,30 +12,28 @@ class StatesController extends AppController {
public $components = array('RequestHandler'); public $components = array('RequestHandler');
public function beforeFilter() { public function beforeFilter() {
parent::beforeFilter(); parent::beforeFilter();
$canView = $this->Session->Read('systemPermission'); global $user;
if ($canView =='None') $canView = (!$user) || ($user['System'] != 'None');
{ if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges')); throw new UnauthorizedException(__('Insufficient Privileges'));
return; return;
} }
} }
/** /**
* index method * index method
* *
* @return void * @return void
*/ */
public function index() { public function index() {
$this->State->recursive = 0; $this->State->recursive = 0;
$states = $this->State->find('all'); $states = $this->State->find('all');
$this->set(array( $this->set(array(
'states' => $states, 'states' => $states,
'_serialize' => array('states') '_serialize' => array('states')
)); ));
} }
/** /**
* view method * view method
@ -44,35 +42,35 @@ public function beforeFilter() {
* @param string $id * @param string $id
* @return void * @return void
*/ */
public function view($id = null) { public function view($id = null) {
if (!$this->State->exists($id)) { if ( !$this->State->exists($id) ) {
throw new NotFoundException(__('Invalid state')); throw new NotFoundException(__('Invalid state'));
} }
$options = array('conditions' => array('State.' . $this->State->primaryKey => $id)); $options = array('conditions' => array('State.' . $this->State->primaryKey => $id));
$this->set('state', $this->State->find('first', $options)); $this->set('state', $this->State->find('first', $options));
} }
/** /**
* add method * add method
* *
* @return void * @return void
*/ */
public function add() { public function add() {
if ($this->request->is('post')) {
if ($this->Session->Read('systemPermission') != 'Edit') if ($this->request->is('post')) {
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
$this->State->create(); if ($this->Session->Read('systemPermission') != 'Edit')
if ($this->State->save($this->request->data)) { {
return $this->flash(__('The state has been saved.'), array('action' => 'index')); throw new UnauthorizedException(__('Insufficient privileges'));
} return;
} }
}
$this->State->create();
if ($this->State->save($this->request->data)) {
return $this->flash(__('The state has been saved.'), array('action' => 'index'));
}
}
}
/** /**
* edit method * edit method
@ -81,26 +79,27 @@ public function beforeFilter() {
* @param string $id * @param string $id
* @return void * @return void
*/ */
public function edit($id = null) { public function edit($id = null) {
if (!$this->State->exists($id)) { if (!$this->State->exists($id)) {
throw new NotFoundException(__('Invalid state')); throw new NotFoundException(__('Invalid state'));
} }
if ($this->Session->Read('systemPermission') != 'Edit') global $user;
{ $canEdit = (!$user) || ($user['System'] == 'Edit');
throw new UnauthorizedException(__('Insufficient privileges')); if ( !$canEdit ) {
return; throw new UnauthorizedException(__('Insufficient privileges'));
} return;
}
if ($this->request->is(array('post', 'put'))) { if ( $this->request->is(array('post', 'put')) ) {
if ($this->State->save($this->request->data)) { if ( $this->State->save($this->request->data) ) {
return $this->flash(__('The state has been saved.'), array('action' => 'index')); return $this->flash(__('The state has been saved.'), array('action' => 'index'));
} }
} else { } else {
$options = array('conditions' => array('State.' . $this->State->primaryKey => $id)); $options = array('conditions' => array('State.' . $this->State->primaryKey => $id));
$this->request->data = $this->State->find('first', $options); $this->request->data = $this->State->find('first', $options);
} }
} }
/** /**
* delete method * delete method
@ -109,48 +108,50 @@ public function beforeFilter() {
* @param string $id * @param string $id
* @return void * @return void
*/ */
public function delete($id = null) { public function delete($id = null) {
$this->State->id = $id; $this->State->id = $id;
if ($this->Session->Read('systemPermission') != 'Edit') global $user;
{ $canEdit = (!$user) || ($user['System'] == 'Edit');
throw new UnauthorizedException(__('Insufficient privileges')); if ( !$canEdit ) {
return; throw new UnauthorizedException(__('Insufficient privileges'));
} return;
}
if (!$this->State->exists()) { if (!$this->State->exists()) {
throw new NotFoundException(__('Invalid state')); throw new NotFoundException(__('Invalid state'));
} }
$this->request->allowMethod('post', 'delete'); $this->request->allowMethod('post', 'delete');
if ($this->State->delete()) { if ($this->State->delete()) {
return $this->flash(__('The state has been deleted.'), array('action' => 'index')); return $this->flash(__('The state has been deleted.'), array('action' => 'index'));
} else { } else {
return $this->flash(__('The state could not be deleted. Please, try again.'), array('action' => 'index')); return $this->flash(__('The state could not be deleted. Please, try again.'), array('action' => 'index'));
} }
} }
public function change() { public function change() {
if ($this->Session->Read('systemPermission') != 'Edit') global $user;
{ $canEdit = (!$user) || ($user['System'] == 'Edit');
throw new UnauthorizedException(__('Insufficient privileges')); if ( !$canEdit ) {
return; throw new UnauthorizedException(__('Insufficient privileges'));
} return;
}
$newState = $this->request->params['pass'][0]; $newState = $this->request->params['pass'][0];
$blah = $this->packageControl($newState); $blah = $this->packageControl($newState);
$this->set(array( $this->set(array(
'blah' => $blah, 'blah' => $blah,
'_serialize' => array('blah') '_serialize' => array('blah')
)); ));
} }
public function packageControl( $command ) { public function packageControl( $command ) {
$zm_path_bin = Configure::read('ZM_PATH_BIN'); $zm_path_bin = Configure::read('ZM_PATH_BIN');
$string = $zm_path_bin.'/zmpkg.pl '.escapeshellarg( $command ); $string = $zm_path_bin.'/zmpkg.pl '.escapeshellarg( $command );
$status = exec( $string ); $status = exec( $string );
return $status; return $status;
} }
} }

View File

@ -0,0 +1,172 @@
<?php
App::uses('AppController', 'Controller');
/**
* Users Controller
*
* @property User $User
*/
class UsersController extends AppController {
/**
* Components
*
* @var array
*/
public $components = array('RequestHandler', 'Paginator');
/**
* index method
*
* @return void
* This also creates a thumbnail for each user.
*/
public function index() {
$this->User->recursive = 0;
$users = $this->Paginator->paginate('User');
$this->set(compact('users'));
}
/**
* view method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function view($id = null) {
$this->loadModel('Config');
$configs = $this->Config->find('list', array(
'fields' => array('Name', 'Value'),
'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
));
$this->User->recursive = 1;
if (!$this->User->exists($id)) {
throw new NotFoundException(__('Invalid user'));
}
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
$user = $this->User->find('first', $options);
$this->set(array(
'user' => $user,
'_serialize' => array('user')
));
}
/**
* add method
*
* @return void
*/
public function add() {
if ($this->request->is('post')) {
$this->User->create();
if ($this->User->save($this->request->data)) {
return $this->flash(__('The user has been saved.'), array('action' => 'index'));
}
$this->Session->setFlash(
__('The user could not be saved. Please, try again.')
);
}
}
/**
* edit method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function edit($id = null) {
$this->User->id = $id;
if (!$this->User->exists($id)) {
throw new NotFoundException(__('Invalid user'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->User->save($this->request->data)) {
$message = 'Saved';
} else {
$message = 'Error';
}
} else {
$this->request->data = $this->User->read(null, $id);
unset($this->request->data['User']['password']);
}
$this->set(array(
'message' => $message,
'_serialize' => array('message')
));
}
/**
* delete method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function delete($id = null) {
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException(__('Invalid user'));
}
$this->request->allowMethod('post', 'delete');
if ($this->User->delete()) {
$message = 'The user has been deleted.';
} else {
$message = 'The user could not be deleted. Please, try again.';
}
$this->set(array(
'message' => $message,
'_serialize' => array('message')
));
}
public function beforeFilter() {
parent::beforeFilter();
$this->loadModel('Config');
$configs = $this->Config->find('list', array(
'fields' => array('Name', 'Value'),
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
));
if ( $configs['ZM_OPT_USE_AUTH'] ) {
$this->Auth->allow('add','logout');
} else {
$this->Auth->allow();
}
}
public function login() {
$this->loadModel('Config');
$configs = $this->Config->find('list', array(
'fields' => array('Name', 'Value'),
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
));
if ( ! $configs['ZM_OPT_USE_AUTH'] ) {
$this->set(array(
'message' => 'Login is not required.',
'_serialize' => array('message')
));
return;
}
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
}
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
public function logout() {
return $this->redirect($this->Auth->logout());
}
}

View File

@ -8,92 +8,93 @@ App::uses('AppController', 'Controller');
*/ */
class ZonePresetsController extends AppController { class ZonePresetsController extends AppController {
/** /**
* Components * Components
* *
* @var array * @var array
*/ */
public $components = array('RequestHandler'); public $components = array('RequestHandler');
/** /**
* index method * index method
* *
* @return void * @return void
*/ */
public function index() { public function index() {
$zonePresets = $this->ZonePreset->find('all'); $zonePresets = $this->ZonePreset->find('all');
$this->set(array( $this->set(array(
'zonePresets' => $zonePresets, 'zonePresets' => $zonePresets,
'_serialize' => array('zonePresets') '_serialize' => array('zonePresets')
)); ));
} }
/** /**
* view method * view method
* *
* @throws NotFoundException * @throws NotFoundException
* @param string $id * @param string $id
* @return void * @return void
*/ */
public function view($id = null) { public function view($id = null) {
if (!$this->ZonePreset->exists($id)) { if ( !$this->ZonePreset->exists($id) ) {
throw new NotFoundException(__('Invalid zone preset')); throw new NotFoundException(__('Invalid zone preset'));
} }
$options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id)); $options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id));
$this->set('zonePreset', $this->ZonePreset->find('first', $options)); $this->set('zonePreset', $this->ZonePreset->find('first', $options));
} }
/** /**
* add method * add method
* *
* @return void * @return void
*/ */
public function add() { public function add() {
if ($this->request->is('post')) { if ( $this->request->is('post') ) {
$this->ZonePreset->create(); $this->ZonePreset->create();
if ($this->ZonePreset->save($this->request->data)) { if ( $this->ZonePreset->save($this->request->data) ) {
return $this->flash(__('The zone preset has been saved.'), array('action' => 'index')); return $this->flash(__('The zone preset has been saved.'), array('action' => 'index'));
} }
} }
} }
/** /**
* edit method * edit method
* *
* @throws NotFoundException * @throws NotFoundException
* @param string $id * @param string $id
* @return void * @return void
*/ */
public function edit($id = null) { public function edit($id = null) {
if (!$this->ZonePreset->exists($id)) { if ( !$this->ZonePreset->exists($id) ) {
throw new NotFoundException(__('Invalid zone preset')); throw new NotFoundException(__('Invalid zone preset'));
} }
if ($this->request->is(array('post', 'put'))) { if ( $this->request->is(array('post', 'put')) ) {
if ($this->ZonePreset->save($this->request->data)) { if ( $this->ZonePreset->save($this->request->data) ) {
return $this->flash(__('The zone preset has been saved.'), array('action' => 'index')); return $this->flash(__('The zone preset has been saved.'), array('action' => 'index'));
} }
} else { } else {
$options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id)); $options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id));
$this->request->data = $this->ZonePreset->find('first', $options); $this->request->data = $this->ZonePreset->find('first', $options);
} }
} }
/** /**
* delete method * delete method
* *
* @throws NotFoundException * @throws NotFoundException
* @param string $id * @param string $id
* @return void * @return void
*/ */
public function delete($id = null) { public function delete($id = null) {
$this->ZonePreset->id = $id; $this->ZonePreset->id = $id;
if (!$this->ZonePreset->exists()) { if ( !$this->ZonePreset->exists() ) {
throw new NotFoundException(__('Invalid zone preset')); throw new NotFoundException(__('Invalid zone preset'));
} }
$this->request->allowMethod('post', 'delete'); $this->request->allowMethod('post', 'delete');
if ($this->ZonePreset->delete()) { if ( $this->ZonePreset->delete() ) {
return $this->flash(__('The zone preset has been deleted.'), array('action' => 'index')); return $this->flash(__('The zone preset has been deleted.'), array('action' => 'index'));
} else { } else {
return $this->flash(__('The zone preset could not be deleted. Please, try again.'), array('action' => 'index')); return $this->flash(__('The zone preset could not be deleted. Please, try again.'), array('action' => 'index'));
} }
}} }
} // end class ZonePresetsController

View File

@ -7,148 +7,163 @@ App::uses('AppController', 'Controller');
*/ */
class ZonesController extends AppController { class ZonesController extends AppController {
/** /**
* Components * Components
* *
* @var array * @var array
*/ */
public $components = array('RequestHandler'); public $components = array('RequestHandler');
public function beforeFilter() { public function beforeFilter() {
parent::beforeFilter(); parent::beforeFilter();
$canView = $this->Session->Read('monitorPermission');
if ($canView =='None')
{
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
} global $user;
$canView = (!$user) || $user['Monitors'] != 'None';
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
}
// Find all zones which belong to a MonitorId // Find all zones which belong to a MonitorId
public function forMonitor($id = null) { public function forMonitor($id = null) {
$this->loadModel('Monitor'); $this->loadModel('Monitor');
if (!$this->Monitor->exists($id)) { if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
$this->Zone->recursive = -1; $this->Zone->recursive = -1;
$zones = $this->Zone->find('all', array( $zones = $this->Zone->find('all', array(
'conditions' => array('MonitorId' => $id) 'conditions' => array('MonitorId' => $id)
)); ));
$this->set(array( $this->set(array(
'zones' => $zones, 'zones' => $zones,
'_serialize' => array('zones') '_serialize' => array('zones')
)); ));
} }
public function index() { public function index() {
$this->Zone->recursive = -1; $this->Zone->recursive = -1;
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); global $user;
if (!empty($allowedMonitors)) $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'],NULL, PREG_SPLIT_NO_EMPTY) : null;
{ if ( $allowedMonitors ) {
$mon_options = array('Zones.MonitorId' => $allowedMonitors); $mon_options = array('Zones.MonitorId' => $allowedMonitors);
} } else {
else $mon_options = '';
{
$mon_options='';
} }
$zones = $this->Zone->find('all',$mon_options); $zones = $this->Zone->find('all',$mon_options);
$this->set(array( $this->set(array(
'zones' => $zones, 'zones' => $zones,
'_serialize' => array('zones') '_serialize' => array('zones')
)); ));
} }
/**
* add method /**
* * add method
* @return void *
*/ * @return void
public function add() { */
if ($this->request->is('post')) { public function add() {
$this->Zone->create(); if ( $this->request->is('post') ) {
if ($this->Zone->save($this->request->data)) {
return $this->flash(__('The zone has been saved.'), array('action' => 'index')); global $user;
} $canEdit = (!$user) || $user['Monitors'] == 'Edit';
} if ( !$canEdit ) {
$monitors = $this->Zone->Monitor->find('list'); throw new UnauthorizedException(__('Insufficient Privileges'));
$this->set(compact('monitors')); return;
}
$this->Zone->create();
if ( $this->Zone->save($this->request->data) ) {
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
}
}
$monitors = $this->Zone->Monitor->find('list');
$this->set(compact('monitors'));
}
/**
* edit method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function edit($id = null) {
$this->Zone->id = $id;
if ( !$this->Zone->exists($id) ) {
throw new NotFoundException(__('Invalid zone'));
}
if ( $this->request->is(array('post', 'put')) ) {
global $user;
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
if ( $this->Zone->save($this->request->data) ) {
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
}
} else {
$options = array('conditions' => array('Zone.' . $this->Zone->primaryKey => $id));
$this->request->data = $this->Zone->find('first', $options);
}
$monitors = $this->Zone->Monitor->find('list');
$this->set(compact('monitors'));
}
/**
* delete method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function delete($id = null) {
$this->Zone->id = $id;
if ( !$this->Zone->exists() ) {
throw new NotFoundException(__('Invalid zone'));
}
$this->request->allowMethod('post', 'delete');
global $user;
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
if ( $this->Zone->delete() ) {
return $this->flash(__('The zone has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The zone could not be deleted. Please, try again.'), array('action' => 'index'));
}
}
public function createZoneImage($id = null) {
$this->loadModel('Monitor');
$this->Monitor->id = $id;
if ( !$this->Monitor->exists() ) {
throw new NotFoundException(__('Invalid zone'));
} }
/** $this->loadModel('Config');
* edit method $zm_dir_images = $this->Config->find('list', array(
* 'conditions' => array('Name' => 'ZM_DIR_IMAGES'),
* @throws NotFoundException 'fields' => array('Name', 'Value')
* @param string $id ));
* @return void
*/
public function edit($id = null) {
$this->Zone->id = $id;
if (!$this->Zone->exists($id)) { $zm_dir_images = $zm_dir_images['ZM_DIR_IMAGES'];
throw new NotFoundException(__('Invalid zone')); $zm_path_web = Configure::read('ZM_PATH_WEB');
} $zm_path_bin = Configure::read('ZM_PATH_BIN');
if ($this->request->is(array('post', 'put'))) { $images_path = "$zm_path_web/$zm_dir_images";
if ($this->Zone->save($this->request->data)) {
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
}
} else {
$options = array('conditions' => array('Zone.' . $this->Zone->primaryKey => $id));
$this->request->data = $this->Zone->find('first', $options);
}
$monitors = $this->Zone->Monitor->find('list');
$this->set(compact('monitors'));
}
/** chdir($images_path);
* delete method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function delete($id = null) {
$this->Zone->id = $id;
if (!$this->Zone->exists()) {
throw new NotFoundException(__('Invalid zone'));
}
$this->request->allowMethod('post', 'delete');
if ($this->Zone->delete()) {
return $this->flash(__('The zone has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The zone could not be deleted. Please, try again.'), array('action' => 'index'));
}
}
$command = escapeshellcmd("$zm_path_bin/zmu -z -m $id");
system($command, $status);
$this->set(array(
public function createZoneImage( $id = null ) { 'status' => $status,
$this->loadModel('Monitor'); '_serialize' => array('status')
$this->Monitor->id = $id; ));
if (!$this->Monitor->exists()) { }
throw new NotFoundException(__('Invalid zone')); } // end class
}
$this->loadModel('Config');
$zm_dir_images = $this->Config->find('list', array(
'conditions' => array('Name' => 'ZM_DIR_IMAGES'),
'fields' => array('Name', 'Value')
));
$zm_dir_images = $zm_dir_images['ZM_DIR_IMAGES'];
$zm_path_web = Configure::read('ZM_PATH_WEB');
$zm_path_bin = Configure::read('ZM_PATH_BIN');
$images_path = "$zm_path_web/$zm_dir_images";
chdir($images_path);
$command = escapeshellcmd("$zm_path_bin/zmu -z -m $id");
system( $command, $status );
$this->set(array(
'status' => $status,
'_serialize' => array('status')
));
}
}

View File

@ -1,12 +1,28 @@
<?php <?php
App::uses('AppModel', 'Model'); App::uses('AppModel', 'Model');
/** /**
* User Model * User Model
* *
* @property Monitor $Monitor
* @property Frame $Frame
*/ */
class User extends AppModel { class User extends AppModel {
public $validate = array(
'Username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A username is required'
)
),
'Password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A password is required'
)
)
);
/** /**
* Use table * Use table
* *
@ -26,6 +42,48 @@ class User extends AppModel {
* *
* @var string * @var string
*/ */
public $displayField = 'Name'; public $displayField = 'Username';
//The Associations below have been created with all possible keys, those that are not needed can be removed
/**
* belongsTo associations
*
* @var array
*/
public $belongsTo = array(
/*'Monitor' => array(
'className' => 'Monitor',
'foreignKey' => 'MonitorId',
'conditions' => '',
'fields' => '',
'order' => ''
)
*/
);
/**
* hasMany associations
*
* @var array
*/
public $hasMany = array(
/*
'Frame' => array(
'className' => 'Frame',
'foreignKey' => 'UserId',
'dependent' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
*/
);
} }

View File

@ -0,0 +1,15 @@
<!-- app/View/Users/add.ctp -->
<div class="users form">
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend><?php echo __('Add User'); ?></legend>
<?php echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->input('role', array(
'options' => array('admin' => 'Admin', 'author' => 'Author')
));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>

View File

@ -0,0 +1,5 @@
<?php
$array['users'] = $users;
$array['pagination'] = $this->Paginator->params();
echo json_encode($array);
?>

View File

@ -0,0 +1 @@
echo json_encode($user);

View File

@ -0,0 +1,13 @@
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend>
<?php echo __('Please enter your username and password'); ?>
</legend>
<?php echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login')); ?>
</div>

View File

@ -0,0 +1,2 @@
$xml = Xml::fromArray(array('response' => $events));
echo $xml->asXML();

View File

@ -0,0 +1,2 @@
$xml = Xml::fromArray(array('response' => $event));
echo $xml->asXML();

View File

@ -12,6 +12,9 @@ private $defaults = array(
'CanMoveRel' => 0, 'CanMoveRel' => 0,
'CanMoveCon' => 0, 'CanMoveCon' => 0,
'CanPan' => 0, 'CanPan' => 0,
'CanReset' => 0,
'CanSleep' => 0,
'CanWake' => 0,
'MinPanRange' => NULL, 'MinPanRange' => NULL,
'MaxPanRange' => NULL, 'MaxPanRange' => NULL,
'MinPanStep' => NULL, 'MinPanStep' => NULL,
@ -103,7 +106,7 @@ private $defaults = array(
if ( $IdOrRow ) { if ( $IdOrRow ) {
$row = NULL; $row = NULL;
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Control WHERE Id=?', NULL, array( $IdOrRow ) ); $row = dbFetchOne( 'SELECT * FROM Controls WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) { if ( ! $row ) {
Error("Unable to load Control record for Id=" . $IdOrRow ); Error("Unable to load Control record for Id=" . $IdOrRow );
} }

View File

@ -246,7 +246,7 @@ class Event {
if ( is_null($new) or ( $new != '' ) ) { if ( is_null($new) or ( $new != '' ) ) {
$this->{'DiskSpace'} = $new; $this->{'DiskSpace'} = $new;
} }
if ( null === $this->{'DiskSpace'} ) { if ( (!array_key_exists('DiskSpace',$this)) or (null === $this->{'DiskSpace'}) ) {
$this->{'DiskSpace'} = folder_size($this->Path()); $this->{'DiskSpace'} = folder_size($this->Path());
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'})); dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
} }

View File

@ -20,7 +20,7 @@ public $defaults = array(
'limit' => 100, 'limit' => 100,
'Query' => array(), 'Query' => array(),
'sort_field' => ZM_WEB_EVENT_SORT_FIELD, 'sort_field' => ZM_WEB_EVENT_SORT_FIELD,
'sort_asc' => ZM_WEB_EVENT_SORT_ORDER == 'asc' ? 'asc' : 'desc', 'sort_asc' => ZM_WEB_EVENT_SORT_ORDER,
); );
public function __construct( $IdOrRow=NULL ) { public function __construct( $IdOrRow=NULL ) {

View File

@ -9,8 +9,10 @@ private $defaults = array(
'Name' => '', 'Name' => '',
'StorageId' => 0, 'StorageId' => 0,
'ServerId' => 0, 'ServerId' => 0,
'Type' => 'Ffmpeg',
'Function' => 'None', 'Function' => 'None',
'Enabled' => 1, 'Enabled' => 1,
'LinkedMonitors' => null,
'Width' => null, 'Width' => null,
'Height' => null, 'Height' => null,
'Orientation' => null, 'Orientation' => null,
@ -20,9 +22,9 @@ private $defaults = array(
'OutputContainer' => 'auto', 'OutputContainer' => 'auto',
'ZoneCount' => 0, 'ZoneCount' => 0,
'Triggers' => null, 'Triggers' => null,
'Type' => 'Ffmpeg',
'MaxFPS' => null, 'MaxFPS' => null,
'AlarmMaxFPS' => null, 'AlarmMaxFPS' => null,
'Refresh' => null,
); );
private $status_fields = array( private $status_fields = array(
'AnalysisFPS' => null, 'AnalysisFPS' => null,
@ -218,7 +220,7 @@ private $control_fields = array(
if ( ZM_OPT_USE_AUTH ) { if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) { if ( ZM_AUTH_RELAY == 'hashed' ) {
$args['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS ); $args['auth'] = generateAuthHash(ZM_AUTH_HASH_IPS);
} elseif ( ZM_AUTH_RELAY == 'plain' ) { } elseif ( ZM_AUTH_RELAY == 'plain' ) {
$args['user'] = $_SESSION['username']; $args['user'] = $_SESSION['username'];
$args['pass'] = $_SESSION['password']; $args['pass'] = $_SESSION['password'];
@ -338,13 +340,13 @@ private $control_fields = array(
} }
if ( $mode == 'stop' ) { if ( $mode == 'stop' ) {
daemonControl( 'stop', 'zmc', $zmcArgs ); daemonControl('stop', 'zmc', $zmcArgs);
} else { } else {
if ( $mode == 'restart' ) { if ( $mode == 'restart' ) {
daemonControl( 'stop', 'zmc', $zmcArgs ); daemonControl('stop', 'zmc', $zmcArgs);
} }
if ( $this->{'Function'} != 'None' ) { if ( $this->{'Function'} != 'None' ) {
daemonControl( 'start', 'zmc', $zmcArgs ); daemonControl('start', 'zmc', $zmcArgs);
} }
} }
} else if ( $this->ServerId() ) { } else if ( $this->ServerId() ) {
@ -381,6 +383,8 @@ private $control_fields = array(
} catch ( Exception $e ) { } catch ( Exception $e ) {
Error("Except $e thrown trying to restart zmc"); Error("Except $e thrown trying to restart zmc");
} }
} else {
Error("Server not assigned to Monitor in a multi-server setup. Please assign a server to the Monitor.");
} }
} // end function zmcControl } // end function zmcControl
@ -388,9 +392,9 @@ private $control_fields = array(
if ( (!defined('ZM_SERVER_ID')) or ( array_key_exists('ServerId', $this) and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) { if ( (!defined('ZM_SERVER_ID')) or ( array_key_exists('ServerId', $this) and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) { if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) {
if ( ZM_OPT_CONTROL ) { if ( ZM_OPT_CONTROL ) {
daemonControl( 'stop', 'zmtrack.pl', '-m '.$this->{'Id'} ); daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'});
} }
daemonControl( 'stop', 'zma', '-m '.$this->{'Id'} ); daemonControl('stop', 'zma', '-m '.$this->{'Id'});
} else { } else {
if ( $mode == 'restart' ) { if ( $mode == 'restart' ) {
if ( ZM_OPT_CONTROL ) { if ( ZM_OPT_CONTROL ) {
@ -407,7 +411,8 @@ private $control_fields = array(
} }
} }
} // end if we are on the recording server } // end if we are on the recording server
} } // end public function zmaControl
public function GroupIds( $new='') { public function GroupIds( $new='') {
if ( $new != '' ) { if ( $new != '' ) {
if(!is_array($new)) { if(!is_array($new)) {
@ -468,6 +473,8 @@ private $control_fields = array(
$this->{'Storage'} = isset($this->{'StorageId'}) ? $this->{'Storage'} = isset($this->{'StorageId'}) ?
Storage::find_one(array('Id'=>$this->{'StorageId'})) : Storage::find_one(array('Id'=>$this->{'StorageId'})) :
new Storage(NULL); new Storage(NULL);
if ( ! $this->{'Storage'} )
$this->{'Storage'} = new Storage(NULL);
} }
return $this->{'Storage'}; return $this->{'Storage'};
} }
@ -485,14 +492,20 @@ private $control_fields = array(
$source = preg_replace( '/^.*\//', '', $this->{'Path'} ); $source = preg_replace( '/^.*\//', '', $this->{'Path'} );
} elseif ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) { } elseif ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) {
$url_parts = parse_url( $this->{'Path'} ); $url_parts = parse_url( $this->{'Path'} );
unset($url_parts['user']); if ( ZM_WEB_FILTER_SOURCE == "Hostname" ) { # Filter out everything but the hostname
unset($url_parts['pass']); $source = $url_parts['host'];
#unset($url_parts['scheme']); } elseif ( ZM_WEB_FILTER_SOURCE == "NoCredentials" ) { # Filter out sensitive and common items
unset($url_parts['query']); unset($url_parts['user']);
#unset($url_parts['path']); unset($url_parts['pass']);
if ( isset($url_parts['port']) and ( $url_parts['port'] == '80' or $url_parts['port'] == '554' ) ) #unset($url_parts['scheme']);
unset($url_parts['port']); unset($url_parts['query']);
$source = unparse_url($url_parts); #unset($url_parts['path']);
if ( isset($url_parts['port']) and ( $url_parts['port'] == '80' or $url_parts['port'] == '554' ) )
unset($url_parts['port']);
$source = unparse_url($url_parts);
} else { # Don't filter anything
$source = $this->{'Path'};
}
} }
if ( $source == '' ) { if ( $source == '' ) {
$source = 'Monitor ' . $this->{'Id'}; $source = 'Monitor ' . $this->{'Id'};

View File

@ -1,5 +1,5 @@
<?php <?php
require_once( 'database.php' ); require_once('database.php');
class Server { class Server {
private $defaults = array( private $defaults = array(

View File

@ -140,20 +140,31 @@ class Storage {
return $usage; return $usage;
} }
public function disk_total_space() { public function disk_total_space() {
if ( ! array_key_exists('disk_total_space', $this) ) { if ( !array_key_exists('disk_total_space', $this) ) {
$this->{'disk_total_space'} = disk_total_space($this->Path()); $path = $this->Path();
if ( file_exists($path) ) {
$this->{'disk_total_space'} = disk_total_space($path);
} else {
Error("Path $path does not exist.");
$this->{'disk_total_space'} = 0;
}
} }
return $this->{'disk_total_space'}; return $this->{'disk_total_space'};
} }
public function disk_used_space() { public function disk_used_space() {
# This isn't a function like this in php, so we have to add up the space used in each event. # This isn't a function like this in php, so we have to add up the space used in each event.
if ( (! array_key_exists('disk_used_space', $this)) or (!$this->{'disk_used_space'}) ) { if ( ( !array_key_exists('disk_used_space', $this)) or !$this->{'disk_used_space'} ) {
if ( $this->{'Type'} == 's3fs' ) { if ( $this->{'Type'} == 's3fs' ) {
$this->{'disk_used_space'} = $this->disk_event_space(); $this->{'disk_used_space'} = $this->disk_event_space();
} else { } else {
$path = $this->Path(); $path = $this->Path();
$this->{'disk_used_space'} = disk_total_space($path) - disk_free_space($path); if ( file_exists($path) ) {
$this->{'disk_used_space'} = disk_total_space($path) - disk_free_space($path);
} else {
Error("Path $path does not exist.");
$this->{'disk_used_space'} = 0;
}
} }
} }
return $this->{'disk_used_space'}; return $this->{'disk_used_space'};

View File

@ -114,23 +114,23 @@ if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 're
// as it produces the same error as when you don't answer a recaptcha // as it produces the same error as when you don't answer a recaptcha
if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) { if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) {
if (!in_array('invalid-input-secret',$responseData['error-codes'])) { if (!in_array('invalid-input-secret',$responseData['error-codes'])) {
Error ('reCaptcha authentication failed'); Error('reCaptcha authentication failed');
userLogout(); userLogout();
$view='login'; $view='login';
$refreshParent = true; $refreshParent = true;
return;
} else { } else {
//Let them login but show an error //Let them login but show an error
echo '<script type="text/javascript">alert("'.translate('RecaptchaWarning').'"); </script>'; echo '<script type="text/javascript">alert("'.translate('RecaptchaWarning').'"); </script>';
Error ('Invalid recaptcha secret detected'); Error('Invalid recaptcha secret detected');
} }
} }
} // end if success==false } // end if success==false
} // end if using reCaptcha } // end if using reCaptcha
$username = validStr( $_REQUEST['username'] ); $username = validStr($_REQUEST['username']);
$password = isset($_REQUEST['password'])?validStr($_REQUEST['password']):''; $password = isset($_REQUEST['password'])?validStr($_REQUEST['password']):'';
userLogin( $username, $password ); userLogin($username, $password);
$refreshParent = true; $refreshParent = true;
$view = 'console'; $view = 'console';
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console';
@ -476,15 +476,12 @@ if ( canEdit( 'Monitors' ) ) {
); );
if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) { if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) {
Logger::Debug("Auto selecting server");
$_REQUEST['newMonitor']['ServerId'] = dbFetchOne('SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id'); $_REQUEST['newMonitor']['ServerId'] = dbFetchOne('SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id');
Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] ); Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] );
if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) { if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) {
$_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID; $_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID;
Logger::Debug("Auto selecting server to " . ZM_SERVER_ID); Logger::Debug("Auto selecting server to " . ZM_SERVER_ID);
} }
} else {
Logger::Debug("NOT Auto selecting server" . $_REQUEST['newMonitor']['ServerId']);
} }
$columns = getTableColumns('Monitors'); $columns = getTableColumns('Monitors');
@ -495,8 +492,8 @@ if ( canEdit( 'Monitors' ) ) {
# If we change anything that changes the shared mem size, zma can complain. So let's stop first. # If we change anything that changes the shared mem size, zma can complain. So let's stop first.
if ( $monitor['Type'] != 'WebSite' ) { if ( $monitor['Type'] != 'WebSite' ) {
zmaControl( $monitor, 'stop' ); zmaControl($monitor, 'stop');
zmcControl( $monitor, 'stop' ); zmcControl($monitor, 'stop');
} }
dbQuery( 'UPDATE Monitors SET '.implode( ', ', $changes ).' WHERE Id=?', array($mid) ); dbQuery( 'UPDATE Monitors SET '.implode( ', ', $changes ).' WHERE Id=?', array($mid) );
// Groups will be added below // Groups will be added below
@ -570,23 +567,26 @@ if ( canEdit( 'Monitors' ) ) {
} }
$restart = true; $restart = true;
} else {
Logger::Debug("No action due to no changes to Monitor");
} # end if count(changes) } # end if count(changes)
if (
( !isset($_POST['newMonitor']['GroupIds']) )
or
( count($_POST['newMonitor']['GroupIds']) != count($Monitor->GroupIds()) )
or
array_diff($_POST['newMonitor']['GroupIds'], $Monitor->GroupIds())
) {
if ( $Monitor->Id() )
dbQuery('DELETE FROM Groups_Monitors WHERE MonitorId=?', array($mid));
if ( isset($_POST['newMonitor']['GroupIds']) ) { if (
foreach ( $_POST['newMonitor']['GroupIds'] as $group_id ) { ( !isset($_POST['newMonitor']['GroupIds']) )
dbQuery('INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid)); or
} ( count($_POST['newMonitor']['GroupIds']) != count($Monitor->GroupIds()) )
or
array_diff($_POST['newMonitor']['GroupIds'], $Monitor->GroupIds())
) {
if ( $Monitor->Id() )
dbQuery('DELETE FROM Groups_Monitors WHERE MonitorId=?', array($mid));
if ( isset($_POST['newMonitor']['GroupIds']) ) {
foreach ( $_POST['newMonitor']['GroupIds'] as $group_id ) {
dbQuery('INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid));
} }
} // end if there has been a change of groups }
} // end if there has been a change of groups
if ( ZM_OPT_X10 ) { if ( ZM_OPT_X10 ) {
$x10Changes = getFormChanges( $x10Monitor, $_REQUEST['newX10Monitor'] ); $x10Changes = getFormChanges( $x10Monitor, $_REQUEST['newX10Monitor'] );
@ -732,7 +732,7 @@ if ( canEdit( 'System' ) ) {
$_SESSION['zmMontageLayout'] = $Layout->Id(); $_SESSION['zmMontageLayout'] = $Layout->Id();
setcookie('zmMontageLayout', $Layout->Id(), 1 ); setcookie('zmMontageLayout', $Layout->Id(), 1 );
session_write_close(); session_write_close();
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montagereview'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montage';
} // end if save } // end if save
} else if ( $_REQUEST['object'] == 'server' ) { } else if ( $_REQUEST['object'] == 'server' ) {

View File

@ -19,7 +19,7 @@
// //
function userLogin($username, $password='', $passwordHashed=false) { function userLogin($username, $password='', $passwordHashed=false) {
global $user, $cookies; global $user;
$sql = 'SELECT * FROM Users WHERE Enabled=1'; $sql = 'SELECT * FROM Users WHERE Enabled=1';
$sql_values = NULL; $sql_values = NULL;
@ -34,7 +34,12 @@ function userLogin($username, $password='', $passwordHashed=false) {
$sql .= ' AND Username=?'; $sql .= ' AND Username=?';
$sql_values = array($username); $sql_values = array($username);
} }
session_start(); $close_session = 0;
if ( !is_session_started() ) {
Logger::Debug("Starting session in userLogin");
session_start();
$close_session = 1;
}
$_SESSION['username'] = $username; $_SESSION['username'] = $username;
if ( ZM_AUTH_RELAY == 'plain' ) { if ( ZM_AUTH_RELAY == 'plain' ) {
// Need to save this in session // Need to save this in session
@ -54,7 +59,9 @@ function userLogin($username, $password='', $passwordHashed=false) {
$_SESSION['loginFailed'] = true; $_SESSION['loginFailed'] = true;
unset($user); unset($user);
} }
session_write_close(); if ( $close_session )
session_write_close();
return isset($user) ? $user: null;
} # end function userLogin } # end function userLogin
function userLogout() { function userLogout() {
@ -103,13 +110,13 @@ function getAuthUser($auth) {
return false; return false;
} // end getAuthUser($auth) } // end getAuthUser($auth)
function generateAuthHash($useRemoteAddr) { function generateAuthHash($useRemoteAddr, $force=false) {
if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) { if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) {
# regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800 # regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800
$time = time(); $time = time();
$mintime = $time - ( ZM_AUTH_HASH_TTL * 1800 ); $mintime = $time - ( ZM_AUTH_HASH_TTL * 1800 );
if ( ( !isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < $mintime ) ) { if ( $force or ( !isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < $mintime ) ) {
# Don't both regenerating Auth Hash if an hour hasn't gone by yet # Don't both regenerating Auth Hash if an hour hasn't gone by yet
$local_time = localtime(); $local_time = localtime();
$authKey = ''; $authKey = '';
@ -120,19 +127,25 @@ function generateAuthHash($useRemoteAddr) {
} }
#Logger::Debug("Generated using hour:".$local_time[2] . ' mday:' . $local_time[3] . ' month:'.$local_time[4] . ' year: ' . $local_time[5] ); #Logger::Debug("Generated using hour:".$local_time[2] . ' mday:' . $local_time[3] . ' month:'.$local_time[4] . ' year: ' . $local_time[5] );
$auth = md5($authKey); $auth = md5($authKey);
session_start(); if ( !$force ) {
$_SESSION['AuthHash'] = $auth; $close_session = 0;
$_SESSION['AuthHashGeneratedAt'] = $time; if ( !is_session_started() ) {
session_write_close(); session_start();
$close_session = 1;
}
$_SESSION['AuthHash'] = $auth;
$_SESSION['AuthHashGeneratedAt'] = $time;
session_write_close();
} else {
return $auth;
}
#Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" ); #Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" );
#} else { #} else {
#Logger::Debug("Using cached auth " . $_SESSION['AuthHash'] ." beacuse generatedat:" . $_SESSION['AuthHashGeneratedAt'] . ' < now:'. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '. $mintime); #Logger::Debug("Using cached auth " . $_SESSION['AuthHash'] ." beacuse generatedat:" . $_SESSION['AuthHashGeneratedAt'] . ' < now:'. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '. $mintime);
} # end if AuthHash is not cached } # end if AuthHash is not cached
return $_SESSION['AuthHash']; return $_SESSION['AuthHash'];
} else { } # end if using AUTH and AUTH_RELAY
$auth = ''; return '';
}
return $auth;
} }
function visibleMonitor($mid) { function visibleMonitor($mid) {
@ -153,4 +166,17 @@ function canEdit($area, $mid=false) {
return ( $user[$area] == 'Edit' && ( !$mid || visibleMonitor($mid) )); return ( $user[$area] == 'Edit' && ( !$mid || visibleMonitor($mid) ));
} }
function is_session_started() {
if ( php_sapi_name() !== 'cli' ) {
if ( version_compare(phpversion(), '5.4.0', '>=') ) {
return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
} else {
return session_id() === '' ? FALSE : TRUE;
}
} else {
Warning("php_sapi_name === 'cli'");
}
return FALSE;
}
?> ?>

View File

@ -227,7 +227,7 @@ function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
if ( canStreamIframe() ) { if ( canStreamIframe() ) {
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>'; return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
} else { } else {
return '<img id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" style="'.($width? ' width:'.$width.';' : '' ).($height ? ' height:'. $height.';' : '' ).'"/>'; return '<img id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" style="'.($width? ' width:'.$width.'px;' : '' ).($height ? ' height:'. $height.'px;' : '' ).'"/>';
} }
} }
@ -334,11 +334,11 @@ function getZmuCommand( $args ) {
if ( ZM_OPT_USE_AUTH ) { if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) { if ( ZM_AUTH_RELAY == 'hashed' ) {
$zmuCommand .= ' -A '.generateAuthHash( false ); $zmuCommand .= ' -A '.generateAuthHash(false, true);
} elseif ( ZM_AUTH_RELAY == 'plain' ) { } elseif ( ZM_AUTH_RELAY == 'plain' ) {
$zmuCommand .= ' -U ' .escapeshellarg($_SESSION['username']).' -P '.escapeshellarg($_SESSION['password']); $zmuCommand .= ' -U ' .escapeshellarg($_SESSION['username']).' -P '.escapeshellarg($_SESSION['password']);
} elseif ( ZM_AUTH_RELAY == 'none' ) { } elseif ( ZM_AUTH_RELAY == 'none' ) {
$zmuCommand .= " -U ".escapeshellarg($_SESSION['username']); $zmuCommand .= ' -U '.escapeshellarg($_SESSION['username']);
} }
} }
@ -355,7 +355,7 @@ function getEventDefaultVideoPath( $event ) {
function deletePath( $path ) { function deletePath( $path ) {
if ( is_dir( $path ) ) { if ( is_dir( $path ) ) {
system( escapeshellcmd( 'rm -rf '.$path ) ); system( escapeshellcmd( 'rm -rf '.$path ) );
} else { } else if ( file_exists($path) ) {
unlink( $path ); unlink( $path );
} }
} }
@ -432,20 +432,38 @@ function htmlSelect( $name, $contents, $values, $behaviours=false ) {
} }
} }
return "<select name=\"$name\" id=\"$name\"$behaviourText>".htmlOptions( $contents, $values ).'</select>'; return "<select name=\"$name\" id=\"$name\"$behaviourText>".htmlOptions($contents, $values).'</select>';
} }
function htmlOptions( $contents, $values ) { function htmlOptions($contents, $values) {
$html = ''; $options_html = '';
foreach ( $contents as $value=>$text ) {
if ( is_array( $text ) ) foreach ( $contents as $value=>$option ) {
$text = $text['Name']; $disabled = 0;
else if ( is_object( $text ) ) $text = '';
$text = $text->Name(); if ( is_array($option) ) {
$selected = is_array( $values ) ? in_array( $value, $values ) : !strcmp($value, $values);
$html .= "<option value=\"$value\"".($selected?" selected=\"selected\"":'').">$text</option>"; if ( isset($option['Name']) )
$text = $option['Name'];
else if ( isset($option['text']) )
$text = $option['text'];
if ( isset($option['disabled']) ) {
$disabled = $option['disabled'];
Error("Setting to disabled");
}
} else if ( is_object($option) ) {
$text = $option->Name();
} else {
$text = $option;
}
$selected = is_array($values) ? in_array($value, $values) : !strcmp($value, $values);
$options_html .= "<option value=\"$value\"".
($selected?' selected="selected"':'').
($disabled?' disabled="disabled"':'').
">$text</option>";
} }
return $html; return $options_html;
} }
function truncText( $text, $length, $deslash=1 ) { function truncText( $text, $length, $deslash=1 ) {
@ -2063,7 +2081,7 @@ function cache_bust( $file ) {
global $css; global $css;
$dirname = preg_replace( '/\//', '_', $parts['dirname'] ); $dirname = preg_replace( '/\//', '_', $parts['dirname'] );
$cacheFile = $dirname.'_'.$parts['filename'].'-'.$css.'-'.filemtime($file).'.'.$parts['extension']; $cacheFile = $dirname.'_'.$parts['filename'].'-'.$css.'-'.filemtime($file).'.'.$parts['extension'];
if ( file_exists( ZM_DIR_CACHE.'/'.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_DIR_CACHE.'/'.$cacheFile ) ) { if ( file_exists(ZM_DIR_CACHE.'/'.$cacheFile) or symlink(ZM_PATH_WEB.'/'.$file, ZM_DIR_CACHE.'/'.$cacheFile) ) {
return 'cache/'.$cacheFile; return 'cache/'.$cacheFile;
} else { } else {
Warning("Failed linking $file to $cacheFile"); Warning("Failed linking $file to $cacheFile");
@ -2137,15 +2155,15 @@ function getStreamHTML( $monitor, $options = array() ) {
if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) { if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) {
//Warning("Scale to " . $options['scale'] ); //Warning("Scale to " . $options['scale'] );
$options['width'] = reScale( $monitor->Width(), $options['scale'] ) . 'px'; $options['width'] = reScale( $monitor->Width(), $options['scale'] );
$options['height'] = reScale( $monitor->Height(), $options['scale'] ) . 'px'; $options['height'] = reScale( $monitor->Height(), $options['scale'] );
} else { } else {
# scale is empty or 100 # scale is empty or 100
# There may be a fixed width applied though, in which case we need to leave the height empty # There may be a fixed width applied though, in which case we need to leave the height empty
if ( ! ( isset($options['width']) and $options['width'] ) ) { if ( ! ( isset($options['width']) and $options['width'] ) ) {
$options['width'] = $monitor->Width() . 'px'; $options['width'] = $monitor->Width();
if ( ! ( isset($options['height']) and $options['height'] ) ) { if ( ! ( isset($options['height']) and $options['height'] ) ) {
$options['height'] = $monitor->Height() . 'px'; $options['height'] = $monitor->Height();
} }
} else if ( ! isset($options['height']) ) { } else if ( ! isset($options['height']) ) {
$options['height'] = ''; $options['height'] = '';
@ -2159,12 +2177,13 @@ function getStreamHTML( $monitor, $options = array() ) {
$options['buffer'] = $monitor->StreamReplayBuffer(); $options['buffer'] = $monitor->StreamReplayBuffer();
//Warning("width: " . $options['width'] . ' height: ' . $options['height']. ' scale: ' . $options['scale'] ); //Warning("width: " . $options['width'] . ' height: ' . $options['height']. ' scale: ' . $options['scale'] );
if ( $monitor->Type() == "WebSite" ) { if ( $monitor->Type() == 'WebSite' ) {
return getWebSiteUrl( 'liveStream'.$monitor->Id(), $monitor->Path(), return getWebSiteUrl(
( isset($options['width']) ? $options['width'] : NULL ), 'liveStream'.$monitor->Id(), $monitor->Path(),
( isset($options['height']) ? $options['height'] : NULL ), ( isset($options['width']) ? $options['width'] : NULL ),
$monitor->Name() ( isset($options['height']) ? $options['height'] : NULL ),
); $monitor->Name()
);
//FIXME, the width and height of the image need to be scaled. //FIXME, the width and height of the image need to be scaled.
} else if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) { } else if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
$streamSrc = $monitor->getStreamSrc( array( $streamSrc = $monitor->getStreamSrc( array(
@ -2177,7 +2196,7 @@ function getStreamHTML( $monitor, $options = array() ) {
return getVideoStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], ZM_MPEG_LIVE_FORMAT, $monitor->Name() ); return getVideoStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
} else if ( $options['mode'] == 'stream' and canStream() ) { } else if ( $options['mode'] == 'stream' and canStream() ) {
$options['mode'] = 'jpeg'; $options['mode'] = 'jpeg';
$streamSrc = $monitor->getStreamSrc( $options ); $streamSrc = $monitor->getStreamSrc($options);
if ( canStreamNative() ) if ( canStreamNative() )
return getImageStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name()); return getImageStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());

View File

@ -51,7 +51,12 @@ require_once( 'includes/Event.php' );
require_once( 'includes/Group.php' ); require_once( 'includes/Group.php' );
require_once( 'includes/Monitor.php' ); require_once( 'includes/Monitor.php' );
if ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ) {
if (
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
or
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'))
) {
$protocol = 'https'; $protocol = 'https';
} else { } else {
$protocol = 'http'; $protocol = 'http';
@ -200,7 +205,7 @@ isset($view) || $view = NULL;
isset($request) || $request = NULL; isset($request) || $request = NULL;
isset($action) || $action = NULL; isset($action) || $action = NULL;
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames' && $view != 'archive' ) { if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $request != 'control' && $view != 'frames' && $view != 'archive' ) {
require_once( 'includes/csrf/csrf-magic.php' ); require_once( 'includes/csrf/csrf-magic.php' );
#Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); #Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
csrf_check(); csrf_check();

View File

@ -324,6 +324,7 @@ $SLANG = array(
'Exclude' => 'Exclude', 'Exclude' => 'Exclude',
'Execute' => 'Execute', 'Execute' => 'Execute',
'ExportDetails' => 'Export Event Details', 'ExportDetails' => 'Export Event Details',
'ExportMatches' => 'Export Matches',
'Exif' => 'Embed EXIF data into image', 'Exif' => 'Embed EXIF data into image',
'Export' => 'Export', 'Export' => 'Export',
'DownloadVideo' => 'Download Video', 'DownloadVideo' => 'Download Video',
@ -662,6 +663,7 @@ $SLANG = array(
'ShowFilterWindow' => 'Show Filter Window', 'ShowFilterWindow' => 'Show Filter Window',
'ShowTimeline' => 'Show Timeline', 'ShowTimeline' => 'Show Timeline',
'SignalCheckColour' => 'Signal Check Colour', 'SignalCheckColour' => 'Signal Check Colour',
'SignalCheckPoints' => 'Signal Check Points',
'Size' => 'Size', 'Size' => 'Size',
'SkinDescription' => 'Change the skin for this session', 'SkinDescription' => 'Change the skin for this session',
'CSSDescription' => 'Change the css for this session', 'CSSDescription' => 'Change the css for this session',
@ -696,6 +698,7 @@ $SLANG = array(
'Stills' => 'Stills', 'Stills' => 'Stills',
'Stopped' => 'Stopped', 'Stopped' => 'Stopped',
'Stop' => 'Stop', 'Stop' => 'Stop',
'StorageArea' => 'Storage Area',
'StorageScheme' => 'Scheme', 'StorageScheme' => 'Scheme',
'StreamReplayBuffer' => 'Stream Replay Image Buffer', 'StreamReplayBuffer' => 'Stream Replay Image Buffer',
'Stream' => 'Stream', 'Stream' => 'Stream',

View File

@ -60,10 +60,10 @@ $SLANG = array(
'AttrDateTime' => 'Fecha/Hora', 'AttrDateTime' => 'Fecha/Hora',
'AttrDiskBlocks' => 'Disk Blocks', 'AttrDiskBlocks' => 'Disk Blocks',
'AttrDiskPercent' => 'Disk Percent', 'AttrDiskPercent' => 'Disk Percent',
'AttrDuration' => 'Duración', 'AttrDuration' => 'Duración',
'AttrFrames' => 'Cuadros', 'AttrFrames' => 'Cuadros',
'AttrId' => 'Id', 'AttrId' => 'Id',
'AttrMaxScore' => 'Puntaje Máximo', 'AttrMaxScore' => 'Puntaje Máximo',
'AttrMonitorId' => 'Monitor Id', 'AttrMonitorId' => 'Monitor Id',
'AttrMonitorName' => 'Nombre Monitor', 'AttrMonitorName' => 'Nombre Monitor',
'AttrName' => 'Name', 'AttrName' => 'Name',
@ -71,7 +71,7 @@ $SLANG = array(
'AttrSystemLoad' => 'System Load', 'AttrSystemLoad' => 'System Load',
'AttrTime' => 'Hora', 'AttrTime' => 'Hora',
'AttrTotalScore' => 'Puntaje Total', 'AttrTotalScore' => 'Puntaje Total',
'AttrWeekday' => 'Día Semana', 'AttrWeekday' => 'Día Semana',
'Auto' => 'Auto', 'Auto' => 'Auto',
'AutoStopTimeout' => 'Auto Stop Timeout', 'AutoStopTimeout' => 'Auto Stop Timeout',
'Available' => 'Available', // Added - 2009-03-31 'Available' => 'Available', // Added - 2009-03-31
@ -95,7 +95,7 @@ $SLANG = array(
'BadLabelY' => 'Label Y co-ordinate must be set to an integer of zero or more', 'BadLabelY' => 'Label Y co-ordinate must be set to an integer of zero or more',
'BadMaxFPS' => 'Maximum FPS must be a positive integer or floating point value', 'BadMaxFPS' => 'Maximum FPS must be a positive integer or floating point value',
'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more', 'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more',
'BadNameChars' => 'Los nombres pueden contener solamente caracteres alfanuméricos más el guión y la raya', 'BadNameChars' => 'Los nombres pueden contener solamente caracteres alfanuméricos más el guión y la raya',
'BadPalette' => 'Palette must be set to a valid value', // Added - 2009-03-31 'BadPalette' => 'Palette must be set to a valid value', // Added - 2009-03-31
'BadPath' => 'Path must be set to a valid value', 'BadPath' => 'Path must be set to a valid value',
'BadPort' => 'Port must be set to a valid number', 'BadPort' => 'Port must be set to a valid number',
@ -177,7 +177,7 @@ $SLANG = array(
'Config' => 'Config.', 'Config' => 'Config.',
'ConfiguredFor' => 'Configurado Para', 'ConfiguredFor' => 'Configurado Para',
'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?', 'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?',
'ConfirmPassword' => 'Confirmar Contraseña', 'ConfirmPassword' => 'Confirmar Contraseña',
'ConjAnd' => 'y', 'ConjAnd' => 'y',
'ConjOr' => 'o', 'ConjOr' => 'o',
'Console' => 'Console', 'Console' => 'Console',
@ -195,7 +195,7 @@ $SLANG = array(
'Cycle' => 'Cycle', 'Cycle' => 'Cycle',
'CycleWatch' => 'Cycle Watch', 'CycleWatch' => 'Cycle Watch',
'DateTime' => 'Date/Time', // Added - 2011-06-16 'DateTime' => 'Date/Time', // Added - 2011-06-16
'Day' => 'Día', 'Day' => 'Día',
'Debug' => 'Debug', 'Debug' => 'Debug',
'DefaultRate' => 'Default Rate', 'DefaultRate' => 'Default Rate',
'DefaultScale' => 'Default Scale', 'DefaultScale' => 'Default Scale',
@ -203,15 +203,15 @@ $SLANG = array(
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18 'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18 'Delay' => 'Delay', // Added - 2015-04-18
'Delete' => 'Borrar', 'Delete' => 'Borrar',
'DeleteAndNext' => 'Borrar &amp; Próximo', 'DeleteAndNext' => 'Borrar &amp; Próximo',
'DeleteAndPrev' => 'Borrar &amp; Anterior', 'DeleteAndPrev' => 'Borrar &amp; Anterior',
'DeleteSavedFilter' => 'Borrar Filtro Guardado', 'DeleteSavedFilter' => 'Borrar Filtro Guardado',
'Description' => 'Descripción', 'Description' => 'Descripción',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31 'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18 'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18
'Device' => 'Device', // Added - 2009-02-08 'Device' => 'Device', // Added - 2009-02-08
'DeviceChannel' => 'Canal', 'DeviceChannel' => 'Canal',
'DeviceFormat' => 'Señal', 'DeviceFormat' => 'Señal',
'DeviceNumber' => 'Fuente', 'DeviceNumber' => 'Fuente',
'DevicePath' => 'Device Path', 'DevicePath' => 'Device Path',
'Devices' => 'Devices', 'Devices' => 'Devices',
@ -232,15 +232,15 @@ $SLANG = array(
'DonateYes' => 'Yes, I\'d like to donate now', 'DonateYes' => 'Yes, I\'d like to donate now',
'Download' => 'Download', 'Download' => 'Download',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31 'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
'Duration' => 'Duración', 'Duration' => 'Duración',
'Edit' => 'Editar', 'Edit' => 'Editar',
'Email' => 'Email', 'Email' => 'Email',
'EnableAlarms' => 'Enable Alarms', 'EnableAlarms' => 'Enable Alarms',
'Enabled' => 'Habilitado', 'Enabled' => 'Habilitado',
'EnterNewFilterName' => 'Ingresar Nuevo Nombre De Filtro', 'EnterNewFilterName' => 'Ingresar Nuevo Nombre De Filtro',
'Error' => 'Error', 'Error' => 'Error',
'ErrorBrackets' => 'Error, Revisar si tiene la misma cantidad de paréntesis de apertura', 'ErrorBrackets' => 'Error, Revisar si tiene la misma cantidad de paréntesis de apertura',
'ErrorValidValue' => 'Error, Revisar si los términos tienen nombres validos', 'ErrorValidValue' => 'Error, Revisar si los términos tienen nombres validos',
'Etc' => 'etc', 'Etc' => 'etc',
'Event' => 'Evento', 'Event' => 'Evento',
'EventFilter' => 'Filtro de Evento', 'EventFilter' => 'Filtro de Evento',
@ -302,7 +302,7 @@ $SLANG = array(
'FrameSkip' => 'Saltear Cuadro', 'FrameSkip' => 'Saltear Cuadro',
'Frames' => 'Cuadros', 'Frames' => 'Cuadros',
'Func' => 'Func', 'Func' => 'Func',
'Function' => 'Función', 'Function' => 'Función',
'Gain' => 'Gain', 'Gain' => 'Gain',
'General' => 'General', 'General' => 'General',
'GenerateVideo' => 'Crear Video', 'GenerateVideo' => 'Crear Video',
@ -326,12 +326,12 @@ $SLANG = array(
'HighBW' => 'Alta&nbsp;B/W', 'HighBW' => 'Alta&nbsp;B/W',
'Home' => 'Home', 'Home' => 'Home',
'Hour' => 'Hora', 'Hour' => 'Hora',
'Hue' => 'Saturación', 'Hue' => 'Saturación',
'Id' => 'Id', 'Id' => 'Id',
'Idle' => 'Pasivo', 'Idle' => 'Pasivo',
'Ignore' => 'Ignorar', 'Ignore' => 'Ignorar',
'Image' => 'Imagen', 'Image' => 'Imagen',
'ImageBufferSize' => 'Tamaño del Buffer de Imagen', 'ImageBufferSize' => 'Tamaño del Buffer de Imagen',
'Images' => 'Images', 'Images' => 'Images',
'In' => 'In', 'In' => 'In',
'Include' => 'Incluir', 'Include' => 'Incluir',
@ -434,7 +434,7 @@ $SLANG = array(
'MonitorProbe' => 'Monitor Probe', // Added - 2009-03-31 '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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // 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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2009-03-31
'Monitors' => 'Monitores', 'Monitors' => 'Monitores',
'Montage' => 'Cámara Múltiple', 'Montage' => 'Cámara Múltiple',
'Month' => 'Mes', 'Month' => 'Mes',
'More' => 'More', // Added - 2011-06-16 'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip', 'MotionFrameSkip' => 'Motion Frame Skip',
@ -446,8 +446,8 @@ $SLANG = array(
'MtgDefault' => 'Default', // Added 2013.08.15. 'MtgDefault' => 'Default', // Added 2013.08.15.
'MustBeGe' => 'Debe ser mayor o igual que', 'MustBeGe' => 'Debe ser mayor o igual que',
'MustBeLe' => 'Debe ser menor o igual que', 'MustBeLe' => 'Debe ser menor o igual que',
'MustConfirmPassword' => 'Debe confirmar la contraseña', 'MustConfirmPassword' => 'Debe confirmar la contraseña',
'MustSupplyPassword' => 'Debe ingresar una contraseña', 'MustSupplyPassword' => 'Debe ingresar una contraseña',
'MustSupplyUsername' => 'You must supply a username', // Added - 2009-02-08 'MustSupplyUsername' => 'You must supply a username', // Added - 2009-02-08
'Name' => 'Nombre', 'Name' => 'Nombre',
'Near' => 'Near', 'Near' => 'Near',
@ -455,7 +455,7 @@ $SLANG = array(
'New' => 'Nuevo', 'New' => 'Nuevo',
'NewGroup' => 'New Group', 'NewGroup' => 'New Group',
'NewLabel' => 'New Label', 'NewLabel' => 'New Label',
'NewPassword' => 'Nueva Contraseña', 'NewPassword' => 'Nueva Contraseña',
'NewState' => 'Nuevo Estado', 'NewState' => 'Nuevo Estado',
'NewUser' => 'Nuevo Usuario', 'NewUser' => 'Nuevo Usuario',
'Next' => 'Siguiente', 'Next' => 'Siguiente',
@ -491,7 +491,7 @@ $SLANG = array(
'Options' => 'Opciones', 'Options' => 'Opciones',
'OrEnterNewName' => 'o agregue nombre', 'OrEnterNewName' => 'o agregue nombre',
'Order' => 'Order', 'Order' => 'Order',
'Orientation' => 'Orientación', 'Orientation' => 'Orientación',
'Out' => 'Out', 'Out' => 'Out',
'OverwriteExisting' => 'Sobreescribir Exitente', 'OverwriteExisting' => 'Sobreescribir Exitente',
'Paged' => 'Paged', 'Paged' => 'Paged',
@ -500,8 +500,8 @@ $SLANG = array(
'PanRight' => 'Pan Right', 'PanRight' => 'Pan Right',
'PanTilt' => 'Pan/Tilt', 'PanTilt' => 'Pan/Tilt',
'Parameter' => 'Parametro', 'Parameter' => 'Parametro',
'Password' => 'Contraseña', 'Password' => 'Contraseña',
'PasswordsDifferent' => 'Las contraseñas nueva y de confirmacion son diferentes', 'PasswordsDifferent' => 'Las contraseñas nueva y de confirmacion son diferentes',
'Paths' => 'Enlaces', 'Paths' => 'Enlaces',
'Pause' => 'Pause', 'Pause' => 'Pause',
'Phone' => 'Phone', 'Phone' => 'Phone',
@ -556,7 +556,7 @@ $SLANG = array(
'RotateRight' => 'Rotar a la izquierda', 'RotateRight' => 'Rotar a la izquierda',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25 'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunMode' => 'Metodo Ejecucion', 'RunMode' => 'Metodo Ejecucion',
'RunState' => 'Estado de Ejecución', 'RunState' => 'Estado de Ejecución',
'Running' => 'Ejecutando', 'Running' => 'Ejecutando',
'Save' => 'Guardar', 'Save' => 'Guardar',
'SaveAs' => 'Guardar Como', 'SaveAs' => 'Guardar Como',
@ -564,7 +564,7 @@ $SLANG = array(
'Scale' => 'Escala', 'Scale' => 'Escala',
'Score' => 'Res.', 'Score' => 'Res.',
'Secs' => 'Seg', 'Secs' => 'Seg',
'Sectionlength' => 'Longitud Sección', 'Sectionlength' => 'Longitud Sección',
'Select' => 'Select', 'Select' => 'Select',
'SelectFormat' => 'Select Format', // Added - 2011-06-17 'SelectFormat' => 'Select Format', // Added - 2011-06-17
'SelectLog' => 'Select Log', // Added - 2011-06-17 'SelectLog' => 'Select Log', // Added - 2011-06-17
@ -630,7 +630,7 @@ $SLANG = array(
'Today' => 'Today', 'Today' => 'Today',
'Tools' => 'Herra.', 'Tools' => 'Herra.',
'Total' => 'Total', // Added - 2011-06-16 'Total' => 'Total', // Added - 2011-06-16
'TotalBrScore' => 'Total<br/>puntuación', 'TotalBrScore' => 'Total<br/>puntuación',
'TrackDelay' => 'Track Delay', 'TrackDelay' => 'Track Delay',
'TrackMotion' => 'Track Motion', 'TrackMotion' => 'Track Motion',
'Triggers' => 'Gatillos', 'Triggers' => 'Gatillos',
@ -642,8 +642,8 @@ $SLANG = array(
'Units' => 'Unidades', 'Units' => 'Unidades',
'Unknown' => 'Desconocido', 'Unknown' => 'Desconocido',
'Update' => 'Update', 'Update' => 'Update',
'UpdateAvailable' => 'Una Actualización a ZoneMinder esta disponible', 'UpdateAvailable' => 'Una Actualización a ZoneMinder esta disponible',
'UpdateNotNecessary' => 'No se requiere Actualización', 'UpdateNotNecessary' => 'No se requiere Actualización',
'Updated' => 'Updated', // Added - 2011-06-16 'Updated' => 'Updated', // Added - 2011-06-16
'Upload' => 'Upload', // Added - 2011-08-23 'Upload' => 'Upload', // Added - 2011-08-23
'UseFilter' => 'Usar Filtro', 'UseFilter' => 'Usar Filtro',
@ -657,9 +657,9 @@ $SLANG = array(
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18 'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18 'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
'Value' => 'Valor', 'Value' => 'Valor',
'Version' => 'Versión', 'Version' => 'Versión',
'VersionIgnore' => 'Ignore esta versión', 'VersionIgnore' => 'Ignore esta versión',
'VersionRemindDay' => 'Recordar en 1 día', 'VersionRemindDay' => 'Recordar en 1 día',
'VersionRemindHour' => 'Recordar en 1 hora', 'VersionRemindHour' => 'Recordar en 1 hora',
'VersionRemindNever' => 'No avizar de nuevas versiones', 'VersionRemindNever' => 'No avizar de nuevas versiones',
'VersionRemindWeek' => 'Recordar en 1 semana', 'VersionRemindWeek' => 'Recordar en 1 semana',
@ -670,7 +670,7 @@ $SLANG = array(
'VideoGenNoFiles' => 'No Video Files Found', 'VideoGenNoFiles' => 'No Video Files Found',
'VideoGenParms' => 'Parametros Generacion Video', 'VideoGenParms' => 'Parametros Generacion Video',
'VideoGenSucceeded' => 'Video Generation Succeeded!', 'VideoGenSucceeded' => 'Video Generation Succeeded!',
'VideoSize' => 'Tamaño Video', 'VideoSize' => 'Tamaño Video',
'View' => 'Ver', 'View' => 'Ver',
'ViewAll' => 'Ver Todo', 'ViewAll' => 'Ver Todo',
'ViewEvent' => 'View Event', 'ViewEvent' => 'View Event',
@ -686,7 +686,7 @@ $SLANG = array(
'Wide' => 'Wide', 'Wide' => 'Wide',
'X' => 'X', 'X' => 'X',
'X10' => 'X10', 'X10' => 'X10',
'X10ActivationString' => 'X10 Comando Activación', 'X10ActivationString' => 'X10 Comando Activación',
'X10InputAlarmString' => 'X10 Comando Entrada Alarma', 'X10InputAlarmString' => 'X10 Comando Entrada Alarma',
'X10OutputAlarmString' => 'X10 Output Alarm String', 'X10OutputAlarmString' => 'X10 Output Alarm String',
'Y' => 'Y', 'Y' => 'Y',

View File

@ -71,62 +71,62 @@ setlocale( LC_ALL, 'he_IL' ); //All locale settings 4.3.0 and after
// Simple String Replacements // Simple String Replacements
$SLANG = array( $SLANG = array(
'24BitColour' => 'צבע 24 ביט', '24BitColour' => 'öáò 24 áéè',
'32BitColour' => 'צבע 32 ביט', // Added - 2011-06-15 '32BitColour' => 'öáò 32 áéè', // Added - 2011-06-15
'8BitGrey' => 'גווני אפור 8 ביט', '8BitGrey' => 'âååðé àôåø 8 áéè',
'Action' => 'פעולה', 'Action' => 'ôòåìä',
'Actual' => 'מקורי', 'Actual' => 'î÷åøé',
'AddNewControl' => 'הוסף קונטרול חדש', 'AddNewControl' => 'äåñó ÷åðèøåì çãù',
'AddNewMonitor' => 'הוסף מוניטור חדש', 'AddNewMonitor' => 'äåñó îåðéèåø çãù',
'AddNewUser' => 'הוסף משתמש חדש', 'AddNewUser' => 'äåñó îùúîù çãù',
'AddNewZone' => 'הוסף איזור חדש', 'AddNewZone' => 'äåñó àéæåø çãù',
'Alarm' => 'אזעקה', 'Alarm' => 'àæò÷ä',
'AlarmBrFrames' => 'אזעקת<br/>פריימים', 'AlarmBrFrames' => 'àæò÷ú<br/>ôøééîéí',
'AlarmFrame' => 'אזעקת פריימים', 'AlarmFrame' => 'àæò÷ú ôøééîéí',
'AlarmFrameCount' => 'ספירת אזעקות פריימים', 'AlarmFrameCount' => 'ñôéøú àæò÷åú ôøééîéí',
'AlarmLimits' => 'הגבלות אזעקה', 'AlarmLimits' => 'äâáìåú àæò÷ä',
'AlarmMaximumFPS' => 'Alarm Maximum FPS', 'AlarmMaximumFPS' => 'Alarm Maximum FPS',
'AlarmPx' => 'אזעקת Px', 'AlarmPx' => 'àæò÷ú Px',
'AlarmRGBUnset' => 'הינך חייב לאתחל אזעקת צבע', 'AlarmRGBUnset' => 'äéðê çééá ìàúçì àæò÷ú öáò',
'AlarmRefImageBlendPct'=> 'Alarm Reference Image Blend %ge', // Added - 2015-04-18 'AlarmRefImageBlendPct'=> 'Alarm Reference Image Blend %ge', // Added - 2015-04-18
'Alert' => 'התראה', 'Alert' => 'äúøàä',
'All' => 'הכל', 'All' => 'äëì',
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22 'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23 'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
'Apply' => 'החל', 'Apply' => 'äçì',
'ApplyingStateChange' => 'החל שינוי מצב', 'ApplyingStateChange' => 'äçì ùéðåé îöá',
'ArchArchived' => 'ארכיב בלבד', 'ArchArchived' => 'àøëéá áìáã',
'ArchUnarchived' => 'לא לארכיב בלבד', 'ArchUnarchived' => 'ìà ìàøëéá áìáã',
'Archive' => 'ארכיב', 'Archive' => 'àøëéá',
'Archived' => 'אורכב', 'Archived' => 'àåøëá',
'Area' => 'אזור', 'Area' => 'àæåø',
'AreaUnits' => 'אזור (px/%)', 'AreaUnits' => 'àæåø (px/%)',
'AttrAlarmFrames' => 'Alarm Frames', 'AttrAlarmFrames' => 'Alarm Frames',
'AttrArchiveStatus' => 'Archive Status', 'AttrArchiveStatus' => 'Archive Status',
'AttrAvgScore' => 'ניקוד ממוצע', 'AttrAvgScore' => 'ðé÷åã îîåöò',
'AttrCause' => 'סיבה', 'AttrCause' => 'ñéáä',
'AttrDate' => 'תאריך', 'AttrDate' => 'úàøéê',
'AttrDateTime' => 'תאריך/שעה', 'AttrDateTime' => 'úàøéê/ùòä',
'AttrDiskBlocks' => 'Disk Blocks', 'AttrDiskBlocks' => 'Disk Blocks',
'AttrDiskPercent' => 'Disk Percent', 'AttrDiskPercent' => 'Disk Percent',
'AttrDuration' => 'משך זמן', 'AttrDuration' => 'îùê æîï',
'AttrFrames' => 'פריימים', 'AttrFrames' => 'ôøééîéí',
'AttrId' => 'Id', 'AttrId' => 'Id',
'AttrMaxScore' => 'ניקוד מקסימלי', 'AttrMaxScore' => 'ðé÷åã î÷ñéîìé',
'AttrMonitorId' => 'Monitor Id', 'AttrMonitorId' => 'Monitor Id',
'AttrMonitorName' => 'שם מוניטור', 'AttrMonitorName' => 'ùí îåðéèåø',
'AttrName' => 'שם', 'AttrName' => 'ùí',
'AttrNotes' => 'הערות', 'AttrNotes' => 'äòøåú',
'AttrSystemLoad' => 'System Load', 'AttrSystemLoad' => 'System Load',
'AttrTime' => 'שעה', 'AttrTime' => 'ùòä',
'AttrTotalScore' => 'סך סכום', 'AttrTotalScore' => 'ñê ñëåí',
'AttrWeekday' => 'יום בשבוע', 'AttrWeekday' => 'éåí áùáåò',
'Auto' => 'אוטו', 'Auto' => 'àåèå',
'AutoStopTimeout' => 'פסק זמן עצירה אוטו', 'AutoStopTimeout' => 'ôñ÷ æîï òöéøä àåèå',
'Available' => 'Available', // Added - 2009-03-31 'Available' => 'Available', // Added - 2009-03-31
'AvgBrScore' => 'ניקוד<br/>ממוצע', 'AvgBrScore' => 'ðé÷åã<br/>îîåöò',
'Background' => 'רקע', 'Background' => 'ø÷ò',
'BackgroundFilter' => 'הרץ מסנן ברקע', 'BackgroundFilter' => 'äøõ îñðï áø÷ò',
'BadAlarmFrameCount' => 'Alarm frame count must be an integer of one or more', 'BadAlarmFrameCount' => 'Alarm frame count must be an integer of one or more',
'BadAlarmMaxFPS' => 'Alarm Maximum FPS must be a positive integer or floating point value', 'BadAlarmMaxFPS' => 'Alarm Maximum FPS must be a positive integer or floating point value',
'BadAnalysisFPS' => 'Analysis FPS must be a positive integer or floating point value', // Added - 2015-07-22 'BadAnalysisFPS' => 'Analysis FPS must be a positive integer or floating point value', // Added - 2015-07-22
@ -157,24 +157,24 @@ $SLANG = array(
'BadWarmupCount' => 'Warmup frames must be an integer of zero or more', 'BadWarmupCount' => 'Warmup frames must be an integer of zero or more',
'BadWebColour' => 'Web colour must be a valid web colour string', 'BadWebColour' => 'Web colour must be a valid web colour string',
'BadWidth' => 'Width must be set to a valid value', '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 'BandwidthHead' => 'Bandwidth', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
'BlobPx' => 'Blob Px', 'BlobPx' => 'Blob Px',
'BlobSizes' => 'Blob Sizes', 'BlobSizes' => 'Blob Sizes',
'Blobs' => 'Blobs', 'Blobs' => 'Blobs',
'Brightness' => 'בהירות', 'Brightness' => 'áäéøåú',
'Buffer' => 'Buffer', // Added - 2015-04-18 'Buffer' => 'Buffer', // Added - 2015-04-18
'Buffers' => 'Buffers', 'Buffers' => 'Buffers',
'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18 'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18
'CanAutoFocus' => 'אפשר התמקדות אוטומטי', 'CanAutoFocus' => 'àôùø äúî÷ãåú àåèåîèé',
'CanAutoGain' => 'Can Auto Gain', 'CanAutoGain' => 'Can Auto Gain',
'CanAutoIris' => 'Can Auto Iris', 'CanAutoIris' => 'Can Auto Iris',
'CanAutoWhite' => 'Can Auto White Bal.', 'CanAutoWhite' => 'Can Auto White Bal.',
'CanAutoZoom' => 'אפשר זום אוטומטי', 'CanAutoZoom' => 'àôùø æåí àåèåîèé',
'CanFocus' => 'אפשר התמקדות', 'CanFocus' => 'àôùø äúî÷ãåú',
'CanFocusAbs' => 'אפשר התמקדות אבסולוטי', 'CanFocusAbs' => 'àôùø äúî÷ãåú àáñåìåèé',
'CanFocusCon' => 'אפשר התמקדות מתמשך', 'CanFocusCon' => 'àôùø äúî÷ãåú îúîùê',
'CanFocusRel' => 'אפשר התמקדות יחסי', 'CanFocusRel' => 'àôùø äúî÷ãåú éçñé',
'CanGain' => 'Can Gain ', 'CanGain' => 'Can Gain ',
'CanGainAbs' => 'Can Gain Absolute', 'CanGainAbs' => 'Can Gain Absolute',
'CanGainCon' => 'Can Gain Continuous', 'CanGainCon' => 'Can Gain Continuous',
@ -183,136 +183,136 @@ $SLANG = array(
'CanIrisAbs' => 'Can Iris Absolute', 'CanIrisAbs' => 'Can Iris Absolute',
'CanIrisCon' => 'Can Iris Continuous', 'CanIrisCon' => 'Can Iris Continuous',
'CanIrisRel' => 'Can Iris Relative', 'CanIrisRel' => 'Can Iris Relative',
'CanMove' => 'אפשר תנועה', 'CanMove' => 'àôùø úðåòä',
'CanMoveAbs' => 'אפשר תנועה אבסולוטית', 'CanMoveAbs' => 'àôùø úðåòä àáñåìåèéú',
'CanMoveCon' => 'אפשר תזוזה מתמשכת', 'CanMoveCon' => 'àôùø úæåæä îúîùëú',
'CanMoveDiag' => 'Can Move Diagonally', 'CanMoveDiag' => 'Can Move Diagonally',
'CanMoveMap' => 'Can Move Mapped', 'CanMoveMap' => 'Can Move Mapped',
'CanMoveRel' => 'אפשר תזוזה יחסית', 'CanMoveRel' => 'àôùø úæåæä éçñéú',
'CanPan' => 'Can Pan' , 'CanPan' => 'Can Pan' ,
'CanReset' => 'אפשר אתחול', 'CanReset' => 'àôùø àúçåì',
'CanSetPresets' => 'Can Set Presets', 'CanSetPresets' => 'Can Set Presets',
'CanSleep' => 'אפשר מצב שינה', 'CanSleep' => 'àôùø îöá ùéðä',
'CanTilt' => 'אפשר זעזוע', 'CanTilt' => 'àôùø æòæåò',
'CanWake' => 'אפשר יציאה ממצב שינה', 'CanWake' => 'àôùø éöéàä îîöá ùéðä',
'CanWhite' => 'Can White Balance', 'CanWhite' => 'Can White Balance',
'CanWhiteAbs' => 'Can White Bal. Absolute', 'CanWhiteAbs' => 'Can White Bal. Absolute',
'CanWhiteBal' => 'Can White Bal.', 'CanWhiteBal' => 'Can White Bal.',
'CanWhiteCon' => 'Can White Bal. Continuous', 'CanWhiteCon' => 'Can White Bal. Continuous',
'CanWhiteRel' => 'Can White Bal. Relative', 'CanWhiteRel' => 'Can White Bal. Relative',
'CanZoom' => 'אפשר זום', 'CanZoom' => 'àôùø æåí',
'CanZoomAbs' => 'אפשר זום אבסולוטי', 'CanZoomAbs' => 'àôùø æåí àáñåìåèé',
'CanZoomCon' => 'אפשר זום מתמשך', 'CanZoomCon' => 'àôùø æåí îúîùê',
'CanZoomRel' => 'אפשר זום יחסי', 'CanZoomRel' => 'àôùø æåí éçñé',
'Cancel' => 'בטל', 'Cancel' => 'áèì',
'CancelForcedAlarm' => 'Cancel Forced Alarm', 'CancelForcedAlarm' => 'Cancel Forced Alarm',
'CaptureHeight' => 'Capture Height', 'CaptureHeight' => 'Capture Height',
'CaptureMethod' => 'Capture Method', // Added - 2009-02-08 'CaptureMethod' => 'Capture Method', // Added - 2009-02-08
'CapturePalette' => 'Capture Palette', 'CapturePalette' => 'Capture Palette',
'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18 'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18
'CaptureWidth' => 'Capture Width', 'CaptureWidth' => 'Capture Width',
'Cause' => 'סיבה', 'Cause' => 'ñéáä',
'CheckMethod' => 'Alarm Check Method', 'CheckMethod' => 'Alarm Check Method',
'ChooseDetectedCamera' => 'Choose Detected Camera', // Added - 2009-03-31 'ChooseDetectedCamera' => 'Choose Detected Camera', // Added - 2009-03-31
'ChooseFilter' => 'בחר מסנן', 'ChooseFilter' => 'áçø îñðï',
'ChooseLogFormat' => 'Choose a log format', // Added - 2011-06-17 'ChooseLogFormat' => 'Choose a log format', // Added - 2011-06-17
'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17 'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17
'ChoosePreset' => 'Choose Preset', 'ChoosePreset' => 'Choose Preset',
'Clear' => 'Clear', // Added - 2011-06-16 'Clear' => 'Clear', // Added - 2011-06-16
'Close' => 'סגור', 'Close' => 'ñâåø',
'Colour' => 'צבע', 'Colour' => 'öáò',
'Command' => 'פקודה', 'Command' => 'ô÷åãä',
'Component' => 'Component', // Added - 2011-06-16 'Component' => 'Component', // Added - 2011-06-16
'Config' => 'תצורה', 'Config' => 'úöåøä',
'ConfiguredFor' => 'תצורה עבור', 'ConfiguredFor' => 'úöåøä òáåø',
'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?', 'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?',
'ConfirmPassword' => 'אשר סיסמא', 'ConfirmPassword' => 'àùø ñéñîà',
'ConjAnd' => 'ו', 'ConjAnd' => 'å',
'ConjOr' => 'או', 'ConjOr' => 'àå',
'Console' => 'קונסול', 'Console' => '÷åðñåì',
'ContactAdmin' => 'צור קשר עם מנהל המערכת בשביל פרטים נוספים.', 'ContactAdmin' => 'öåø ÷ùø òí îðäì äîòøëú áùáéì ôøèéí ðåñôéí.',
'Continue' => 'המשך', 'Continue' => 'äîùê',
'Contrast' => 'ניגודיות', 'Contrast' => 'ðéâåãéåú',
'Control' => 'קונטרול', 'Control' => '÷åðèøåì',
'ControlAddress' => 'כתובת הקונטרול', 'ControlAddress' => 'ëúåáú ä÷åðèøåì',
'ControlCap' => 'יכולת הקונטרול', 'ControlCap' => 'éëåìú ä÷åðèøåì',
'ControlCaps' => 'יכולות הקונטרול', 'ControlCaps' => 'éëåìåú ä÷åðèøåì',
'ControlDevice' => 'התקן הקונטרול', 'ControlDevice' => 'äú÷ï ä÷åðèøåì',
'ControlType' => 'סוג הקונטרול', 'ControlType' => 'ñåâ ä÷åðèøåì',
'Controllable' => 'Controllable', 'Controllable' => 'Controllable',
'Current' => 'Current', // Added - 2015-04-18 'Current' => 'Current', // Added - 2015-04-18
'Cycle' => 'מחזורי', 'Cycle' => 'îçæåøé',
'CycleWatch' => 'צפייה מחזורית', 'CycleWatch' => 'öôééä îçæåøéú',
'DateTime' => 'Date/Time', // Added - 2011-06-16 'DateTime' => 'Date/Time', // Added - 2011-06-16
'Day' => 'יום', 'Day' => 'éåí',
'Debug' => 'Debug', 'Debug' => 'Debug',
'DefaultRate' => 'Default Rate', 'DefaultRate' => 'Default Rate',
'DefaultScale' => 'Default Scale', 'DefaultScale' => 'Default Scale',
'DefaultView' => 'Default View', 'DefaultView' => 'Default View',
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18 'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18 'Delay' => 'Delay', // Added - 2015-04-18
'Delete' => 'מחק', 'Delete' => 'îç÷',
'DeleteAndNext' => 'מחק &amp; הבא', 'DeleteAndNext' => 'îç÷ &amp; äáà',
'DeleteAndPrev' => 'מחק &amp; הקודם', 'DeleteAndPrev' => 'îç÷ &amp; ä÷åãí',
'DeleteSavedFilter' => 'מחק מסנן שמור', 'DeleteSavedFilter' => 'îç÷ îñðï ùîåø',
'Description' => 'תיאור', 'Description' => 'úéàåø',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31 'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18 'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18
'Device' => 'Device', // Added - 2009-02-08 'Device' => 'Device', // Added - 2009-02-08
'DeviceChannel' => 'ערוץ ההתקן', 'DeviceChannel' => 'òøåõ ääú÷ï',
'DeviceFormat' => 'תבנית ההתקן', 'DeviceFormat' => 'úáðéú ääú÷ï',
'DeviceNumber' => 'מספר ההתקן', 'DeviceNumber' => 'îñôø ääú÷ï',
'DevicePath' => 'נתיב ההתקן', 'DevicePath' => 'ðúéá ääú÷ï',
'Devices' => 'התקנים', 'Devices' => 'äú÷ðéí',
'Dimensions' => 'מימדים', 'Dimensions' => 'îéîãéí',
'DisableAlarms' => 'נטרל אזעקות', 'DisableAlarms' => 'ðèøì àæò÷åú',
'Disk' => 'דיסק', 'Disk' => 'ãéñ÷',
'Display' => 'Display', // Added - 2011-01-30 'Display' => 'Display', // Added - 2011-01-30
'Displaying' => 'Displaying', // Added - 2011-06-16 'Displaying' => 'Displaying', // Added - 2011-06-16
'DoNativeMotionDetection'=> 'Do Native Motion Detection', 'DoNativeMotionDetection'=> 'Do Native Motion Detection',
'Donate' => 'תרום בבקשה', 'Donate' => 'úøåí áá÷ùä',
'DonateAlready' => 'לא, תרמתי כבר', 'DonateAlready' => 'ìà, úøîúé ëáø',
'DonateEnticement' => 'You\'ve been running ZoneMinder for a while now and hopefully are finding it a useful addition to your home or workplace security. Although ZoneMinder is, and will remain, free and open source, it costs money to develop and support. If you would like to help support future development and new features then please consider donating. Donating is, of course, optional but very much appreciated and you can donate as much or as little as you like.<br><br>If you would like to donate please select the option below or go to http://www.zoneminder.com/donate.html in your browser.<br><br>Thank you for using ZoneMinder and don\'t forget to visit the forums on ZoneMinder.com for support or suggestions about how to make your ZoneMinder experience even better.', 'DonateEnticement' => 'You\'ve been running ZoneMinder for a while now and hopefully are finding it a useful addition to your home or workplace security. Although ZoneMinder is, and will remain, free and open source, it costs money to develop and support. If you would like to help support future development and new features then please consider donating. Donating is, of course, optional but very much appreciated and you can donate as much or as little as you like.<br><br>If you would like to donate please select the option below or go to http://www.zoneminder.com/donate.html in your browser.<br><br>Thank you for using ZoneMinder and don\'t forget to visit the forums on ZoneMinder.com for support or suggestions about how to make your ZoneMinder experience even better.',
'DonateRemindDay' => 'עדיין לא, הזכר לא בעוד יום אחד', 'DonateRemindDay' => 'òãééï ìà, äæëø ìà áòåã éåí àçã',
'DonateRemindHour' => 'עדיין לא, הזכר לי בעוד שעה אחת', 'DonateRemindHour' => 'òãééï ìà, äæëø ìé áòåã ùòä àçú',
'DonateRemindMonth' => 'עדיין לא, הזכר לי בעוד חודש אחד', 'DonateRemindMonth' => 'òãééï ìà, äæëø ìé áòåã çåãù àçã',
'DonateRemindNever' => 'לא, אני לא רוצה לתרום, אל תתזכר אותי', 'DonateRemindNever' => 'ìà, àðé ìà øåöä ìúøåí, àì úúæëø àåúé',
'DonateRemindWeek' => 'עדיין לא, הזכר לי בעוד שבוע אחד', 'DonateRemindWeek' => 'òãééï ìà, äæëø ìé áòåã ùáåò àçã',
'DonateYes' => 'כן, אני מעוניין לתרום עכשיו', 'DonateYes' => 'ëï, àðé îòåðééï ìúøåí òëùéå',
'Download' => 'הורד', 'Download' => 'äåøã',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31 'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
'Duration' => 'משך זמן', 'Duration' => 'îùê æîï',
'Edit' => 'ערוך', 'Edit' => 'òøåê',
'Email' => 'דוא"ל', 'Email' => 'ãåà"ì',
'EnableAlarms' => 'אפשר אזעקות', 'EnableAlarms' => 'àôùø àæò÷åú',
'Enabled' => 'אפשר', 'Enabled' => 'àôùø',
'EnterNewFilterName' => 'הזן מסנן חדש', 'EnterNewFilterName' => 'äæï îñðï çãù',
'Error' => 'שגיאה', 'Error' => 'ùâéàä',
'ErrorBrackets' => 'Error, please check you have an equal number of opening and closing brackets', 'ErrorBrackets' => 'Error, please check you have an equal number of opening and closing brackets',
'ErrorValidValue' => 'Error, please check that all terms have a valid value', 'ErrorValidValue' => 'Error, please check that all terms have a valid value',
'Etc' => 'וכו\'', 'Etc' => 'åëå\'',
'Event' => 'אירוע', 'Event' => 'àéøåò',
'EventFilter' => 'מסנן אירוע', 'EventFilter' => 'îñðï àéøåò',
'EventId' => 'זיהוי אירוע', 'EventId' => 'æéäåé àéøåò',
'EventName' => 'שם אירוע', 'EventName' => 'ùí àéøåò',
'EventPrefix' => 'Event Prefix', 'EventPrefix' => 'Event Prefix',
'Events' => 'אירועים', 'Events' => 'àéøåòéí',
'Exclude' => 'ללא', 'Exclude' => 'ììà',
'Execute' => 'בצע', 'Execute' => 'áöò',
'Export' => 'יצא', 'Export' => 'éöà',
'ExportDetails' => 'יצא פרטי אירוע', 'ExportDetails' => 'éöà ôøèé àéøåò',
'ExportFailed' => 'יצוא נכשל', 'ExportFailed' => 'éöåà ðëùì',
'ExportFormat' => 'יצא תבנית קובץ', 'ExportFormat' => 'éöà úáðéú ÷åáõ',
'ExportFormatTar' => 'Tar', 'ExportFormatTar' => 'Tar',
'ExportFormatZip' => 'Zip', 'ExportFormatZip' => 'Zip',
'ExportFrames' => 'Export Frame Details', 'ExportFrames' => 'Export Frame Details',
'ExportImageFiles' => 'יצא קבצי תמונה', 'ExportImageFiles' => 'éöà ÷áöé úîåðä',
'ExportLog' => 'Export Log', // Added - 2011-06-17 'ExportLog' => 'Export Log', // Added - 2011-06-17
'ExportMiscFiles' => 'יצא קבצים אחרים (אם ישנם)', 'ExportMiscFiles' => 'éöà ÷áöéí àçøéí (àí éùðí)',
'ExportOptions' => 'יצא אפשרויות', 'ExportOptions' => 'éöà àôùøåéåú',
'ExportSucceeded' => 'Export Succeeded', // Added - 2009-02-08 'ExportSucceeded' => 'Export Succeeded', // Added - 2009-02-08
'ExportVideoFiles' => 'Export Video Files (if present)', 'ExportVideoFiles' => 'Export Video Files (if present)',
'Exporting' => 'מייצא', 'Exporting' => 'îééöà',
'FPS' => 'fps', 'FPS' => 'fps',
'FPSReportInterval' => 'FPS Report Interval', 'FPSReportInterval' => 'FPS Report Interval',
'FTP' => 'FTP', 'FTP' => 'FTP',
@ -320,20 +320,20 @@ $SLANG = array(
'FastForward' => 'Fast Forward', 'FastForward' => 'Fast Forward',
'Feed' => 'Feed', 'Feed' => 'Feed',
'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08 'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08
'File' => 'קובץ', 'File' => '÷åáõ',
'Filter' => 'Filter', // Added - 2015-04-18 'Filter' => 'Filter', // Added - 2015-04-18
'FilterArchiveEvents' => 'ארכב תואמים', 'FilterArchiveEvents' => 'àøëá úåàîéí',
'FilterDeleteEvents' => 'מחק תואמים', 'FilterDeleteEvents' => 'îç÷ úåàîéí',
'FilterEmailEvents' => 'שלח דואר של כל התואמים', 'FilterEmailEvents' => 'ùìç ãåàø ùì ëì äúåàîéí',
'FilterExecuteEvents' => 'Execute command on all matches', 'FilterExecuteEvents' => 'Execute command on all matches',
'FilterLog' => 'Filter log', // Added - 2015-04-18 'FilterLog' => 'Filter log', // Added - 2015-04-18
'FilterMessageEvents' => 'Message details of all matches', 'FilterMessageEvents' => 'Message details of all matches',
'FilterPx' => 'Filter Px', 'FilterPx' => 'Filter Px',
'FilterUnset' => 'עליך לציין רוחב וגובה מסנן', 'FilterUnset' => 'òìéê ìöééï øåçá åâåáä îñðï',
'FilterUploadEvents' => 'עלה את כל התואמים', 'FilterUploadEvents' => 'òìä àú ëì äúåàîéí',
'FilterVideoEvents' => 'צור וידאו לכל התואמים', 'FilterVideoEvents' => 'öåø åéãàå ìëì äúåàîéí',
'Filters' => 'מסננים', 'Filters' => 'îñððéí',
'First' => 'הראשון', 'First' => 'äøàùåï',
'FlippedHori' => 'Flipped Horizontally', 'FlippedHori' => 'Flipped Horizontally',
'FlippedVert' => 'Flipped Vertically', 'FlippedVert' => 'Flipped Vertically',
'FnMocord' => 'Mocord', // Added 2013.08.16. 'FnMocord' => 'Mocord', // Added 2013.08.16.
@ -342,24 +342,24 @@ $SLANG = array(
'FnNodect' => 'Nodect', // Added 2013.08.16. 'FnNodect' => 'Nodect', // Added 2013.08.16.
'FnNone' => 'None', // Added 2013.08.16. 'FnNone' => 'None', // Added 2013.08.16.
'FnRecord' => 'Record', // Added 2013.08.16. 'FnRecord' => 'Record', // Added 2013.08.16.
'Focus' => 'התמקד', 'Focus' => 'äúî÷ã',
'ForceAlarm' => 'הכרח אזעקה', 'ForceAlarm' => 'äëøç àæò÷ä',
'Format' => 'תבנית', 'Format' => 'úáðéú',
'Frame' => 'פריים', 'Frame' => 'ôøééí',
'FrameId' => 'Frame Id', 'FrameId' => 'Frame Id',
'FrameRate' => 'Frame Rate', 'FrameRate' => 'Frame Rate',
'FrameSkip' => 'דלג פריים', 'FrameSkip' => 'ãìâ ôøééí',
'Frames' => 'פריימים', 'Frames' => 'ôøééîéí',
'Func' => 'פונק', 'Func' => 'ôåð÷',
'Function' => 'פונקציה', 'Function' => 'ôåð÷öéä',
'Gain' => 'Gain', 'Gain' => 'Gain',
'General' => 'כללי', 'General' => 'ëììé',
'GenerateVideo' => 'צור וידאו', 'GenerateVideo' => 'öåø åéãàå',
'GeneratingVideo' => 'מייצר וידאו', 'GeneratingVideo' => 'îééöø åéãàå',
'GoToZoneMinder' => 'בקר ZoneMinder.com', 'GoToZoneMinder' => 'á÷ø ZoneMinder.com',
'Grey' => 'אפור', 'Grey' => 'àôåø',
'Group' => 'קבוצה', 'Group' => '÷áåöä',
'Groups' => 'קבוצות', 'Groups' => '÷áåöåú',
'HasFocusSpeed' => 'Has Focus Speed', 'HasFocusSpeed' => 'Has Focus Speed',
'HasGainSpeed' => 'Has Gain Speed', 'HasGainSpeed' => 'Has Gain Speed',
'HasHomePreset' => 'Has Home Preset', 'HasHomePreset' => 'Has Home Preset',
@ -371,51 +371,51 @@ $SLANG = array(
'HasTurboTilt' => 'Has Turbo Tilt', 'HasTurboTilt' => 'Has Turbo Tilt',
'HasWhiteSpeed' => 'Has White Bal. Speed', 'HasWhiteSpeed' => 'Has White Bal. Speed',
'HasZoomSpeed' => 'Has Zoom Speed', 'HasZoomSpeed' => 'Has Zoom Speed',
'High' => 'גבוה', 'High' => 'âáåä',
'HighBW' => 'גבוה&nbsp;ר/פ', 'HighBW' => 'âáåä&nbsp;ø/ô',
'Home' => 'בית', 'Home' => 'áéú',
'Hour' => 'שעה', 'Hour' => 'ùòä',
'Hue' => 'Hue', 'Hue' => 'Hue',
'Id' => 'זיהוי', 'Id' => 'æéäåé',
'Idle' => 'המתנה', 'Idle' => 'äîúðä',
'Ignore' => 'התעלם', 'Ignore' => 'äúòìí',
'Image' => 'תמונה', 'Image' => 'úîåðä',
'ImageBufferSize' => 'Image Buffer Size (frames)', 'ImageBufferSize' => 'Image Buffer Size (frames)',
'Images' => 'תמונות', 'Images' => 'úîåðåú',
'In' => 'בתוך', 'In' => 'áúåê',
'Include' => 'כלול', 'Include' => 'ëìåì',
'Inverted' => 'הפוך', 'Inverted' => 'äôåê',
'Iris' => 'Iris', 'Iris' => 'Iris',
'KeyString' => 'מחרוזת תוים', 'KeyString' => 'îçøåæú úåéí',
'Label' => 'תווית', 'Label' => 'úååéú',
'Language' => 'שפה', 'Language' => 'ùôä',
'Last' => 'אחרון', 'Last' => 'àçøåï',
'Layout' => 'Layout', // Added - 2009-02-08 'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16 'Level' => 'Level', // Added - 2011-06-16
'Libvlc' => 'Libvlc', 'Libvlc' => 'Libvlc',
'LimitResultsPost' => 'תוצאות בלבד;', // This is used at the end of the phrase 'Limit to first N results only' 'LimitResultsPost' => 'úåöàåú áìáã;', // This is used at the end of the phrase 'Limit to first N results only'
'LimitResultsPre' => 'הגבל לראשון', // This is used at the beginning of the phrase 'Limit to first N results only' 'LimitResultsPre' => 'äâáì ìøàùåï', // This is used at the beginning of the phrase 'Limit to first N results only'
'Line' => 'Line', // Added - 2011-06-16 'Line' => 'Line', // Added - 2011-06-16
'LinkedMonitors' => 'מוניטורים מקושרים', 'LinkedMonitors' => 'îåðéèåøéí î÷åùøéí',
'List' => 'רשימה', 'List' => 'øùéîä',
'Load' => 'טען', 'Load' => 'èòï',
'Local' => 'מקומי', 'Local' => 'î÷åîé',
'Log' => 'Log', // Added - 2011-06-16 'Log' => 'Log', // Added - 2011-06-16
'LoggedInAs' => 'התחבר כ', 'LoggedInAs' => 'äúçáø ë',
'Logging' => 'Logging', // Added - 2011-06-16 'Logging' => 'Logging', // Added - 2011-06-16
'LoggingIn' => 'מתחבר', 'LoggingIn' => 'îúçáø',
'Login' => 'התחבר', 'Login' => 'äúçáø',
'Logout' => 'התנתק', 'Logout' => 'äúðú÷',
'Logs' => 'Logs', // Added - 2011-06-17 'Logs' => 'Logs', // Added - 2011-06-17
'Low' => 'נמוך', 'Low' => 'ðîåê',
'LowBW' => 'נמוך&nbsp;ר/פ', 'LowBW' => 'ðîåê&nbsp;ø/ô',
'Main' => 'מרכזי', 'Main' => 'îøëæé',
'Man' => 'מדריך', 'Man' => 'îãøéê',
'Manual' => 'מדריך', 'Manual' => 'îãøéê',
'Mark' => 'סמן', 'Mark' => 'ñîï',
'Max' => 'מקס', 'Max' => 'î÷ñ',
'MaxBandwidth' => 'רוחב פס מקס', 'MaxBandwidth' => 'øåçá ôñ î÷ñ',
'MaxBrScore' => 'ניקוד<br/>מקסימלי', 'MaxBrScore' => 'ðé÷åã<br/>î÷ñéîìé',
'MaxFocusRange' => 'Max Focus Range', 'MaxFocusRange' => 'Max Focus Range',
'MaxFocusSpeed' => 'Max Focus Speed', 'MaxFocusSpeed' => 'Max Focus Speed',
'MaxFocusStep' => 'Max Focus Step', 'MaxFocusStep' => 'Max Focus Step',
@ -438,7 +438,7 @@ $SLANG = array(
'MaxZoomSpeed' => 'Max Zoom Speed', 'MaxZoomSpeed' => 'Max Zoom Speed',
'MaxZoomStep' => 'Max Zoom Step', 'MaxZoomStep' => 'Max Zoom Step',
'MaximumFPS' => 'Maximum FPS', 'MaximumFPS' => 'Maximum FPS',
'Medium' => 'בינוני', 'Medium' => 'áéðåðé',
'MediumBW' => 'Medium&nbsp;B/W', 'MediumBW' => 'Medium&nbsp;B/W',
'Message' => 'Message', // Added - 2011-06-16 'Message' => 'Message', // Added - 2011-06-16
'MinAlarmAreaLtMax' => 'Minimum alarm area should be less than maximum', 'MinAlarmAreaLtMax' => 'Minimum alarm area should be less than maximum',
@ -476,18 +476,18 @@ $SLANG = array(
'MinZoomStep' => 'Min Zoom Step', 'MinZoomStep' => 'Min Zoom Step',
'Misc' => 'Misc', 'Misc' => 'Misc',
'Mode' => 'Mode', // Added - 2015-04-18 'Mode' => 'Mode', // Added - 2015-04-18
'Monitor' => 'מוניטור', 'Monitor' => 'îåðéèåø',
'MonitorIds' => 'Monitor&nbsp;Ids', 'MonitorIds' => 'Monitor&nbsp;Ids',
'MonitorPreset' => 'Monitor Preset', 'MonitorPreset' => 'Monitor Preset',
'MonitorPresetIntro' => 'Select an appropriate preset from the list below.<br><br>Please note that this may overwrite any values you already have configured for this monitor.<br><br>', 'MonitorPresetIntro' => 'Select an appropriate preset from the list below.<br><br>Please note that this may overwrite any values you already have configured for this monitor.<br><br>',
'MonitorProbe' => 'Monitor Probe', // Added - 2009-03-31 '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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // 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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2009-03-31
'Monitors' => 'מוניטורים', 'Monitors' => 'îåðéèåøéí',
'Montage' => 'Montage', 'Montage' => 'Montage',
'Month' => 'חודש', 'Month' => 'çåãù',
'More' => 'More', // Added - 2011-06-16 'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip', 'MotionFrameSkip' => 'Motion Frame Skip',
'Move' => 'הזז', 'Move' => 'äææ',
'Mtg2widgrd' => '2-wide grid', // Added 2013.08.15. 'Mtg2widgrd' => '2-wide grid', // Added 2013.08.15.
'Mtg3widgrd' => '3-wide grid', // Added 2013.08.15. 'Mtg3widgrd' => '3-wide grid', // Added 2013.08.15.
'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15. 'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15.
@ -498,48 +498,48 @@ $SLANG = array(
'MustConfirmPassword' => 'You must confirm the password', 'MustConfirmPassword' => 'You must confirm the password',
'MustSupplyPassword' => 'You must supply a password', 'MustSupplyPassword' => 'You must supply a password',
'MustSupplyUsername' => 'You must supply a username', 'MustSupplyUsername' => 'You must supply a username',
'Name' => 'שם', 'Name' => 'ùí',
'Near' => 'ליד', 'Near' => 'ìéã',
'Network' => 'רשת', 'Network' => 'øùú',
'New' => 'חדש', 'New' => 'çãù',
'NewGroup' => 'קבוצה חדשה', 'NewGroup' => '÷áåöä çãùä',
'NewLabel' => 'תווית חדשה', 'NewLabel' => 'úååéú çãùä',
'NewPassword' => 'סיסמא חדשה', 'NewPassword' => 'ñéñîà çãùä',
'NewState' => 'מצב חדש', 'NewState' => 'îöá çãù',
'NewUser' => 'משתמש חדש', 'NewUser' => 'îùúîù çãù',
'Next' => 'הבא', 'Next' => 'äáà',
'No' => 'לא', 'No' => 'ìà',
'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31 'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31
'NoFramesRecorded' => 'There are no frames recorded for this event', 'NoFramesRecorded' => 'There are no frames recorded for this event',
'NoGroup' => 'ללא קבוצה', 'NoGroup' => 'ììà ÷áåöä',
'NoSavedFilters' => 'NoSavedFilters', 'NoSavedFilters' => 'NoSavedFilters',
'NoStatisticsRecorded' => 'There are no statistics recorded for this event/frame', 'NoStatisticsRecorded' => 'There are no statistics recorded for this event/frame',
'None' => 'ריק', 'None' => 'øé÷',
'NoneAvailable' => 'בלתי זמין', 'NoneAvailable' => 'áìúé æîéï',
'Normal' => 'נורמלי', 'Normal' => 'ðåøîìé',
'Notes' => 'Notes', 'Notes' => 'Notes',
'NumPresets' => 'Num Presets', 'NumPresets' => 'Num Presets',
'Off' => 'כבוי', 'Off' => 'ëáåé',
'On' => 'דלוק', 'On' => 'ãìå÷',
'OnvifCredentialsIntro'=> 'Please supply user name and password for the selected camera.<br/>If no user has been created for the camera then the user given here will be created with the given password.<br/><br/>', // Added - 2015-04-18 'OnvifCredentialsIntro'=> 'Please supply user name and password for the selected camera.<br/>If no user has been created for the camera then the user given here will be created with the given password.<br/><br/>', // Added - 2015-04-18
'OnvifProbe' => 'ONVIF', // 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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18 'OnvifProbeIntro' => 'The list below shows detected ONVIF cameras and whether they are already being used or available for selection.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18
'OpEq' => 'שווה ל', 'OpEq' => 'ùååä ì',
'OpGt' => 'גדול מ', 'OpGt' => 'âãåì î',
'OpGtEq' => 'greater than or equal to', 'OpGtEq' => 'greater than or equal to',
'OpIn' => 'in set', 'OpIn' => 'in set',
'OpLt' => 'פחות מ', 'OpLt' => 'ôçåú î',
'OpLtEq' => 'less than or equal to', 'OpLtEq' => 'less than or equal to',
'OpMatches' => 'matches', 'OpMatches' => 'matches',
'OpNe' => 'אינו שווה', 'OpNe' => 'àéðå ùååä',
'OpNotIn' => 'not in set', 'OpNotIn' => 'not in set',
'OpNotMatches' => 'אינו תואם', 'OpNotMatches' => 'àéðå úåàí',
'Open' => 'פתח', 'Open' => 'ôúç',
'OptionHelp' => 'OptionHelp', 'OptionHelp' => 'OptionHelp',
'OptionRestartWarning' => 'These changes may not come into effect fully\nwhile the system is running. When you have\nfinished making your changes please ensure that\nyou restart ZoneMinder.', 'OptionRestartWarning' => 'These changes may not come into effect fully\nwhile the system is running. When you have\nfinished making your changes please ensure that\nyou restart ZoneMinder.',
'Options' => 'אפשרויות', 'Options' => 'àôùøåéåú',
'OrEnterNewName' => 'or enter new name', 'OrEnterNewName' => 'or enter new name',
'Order' => 'מיון', 'Order' => 'îéåï',
'Orientation' => 'Orientation', 'Orientation' => 'Orientation',
'Out' => 'Out', 'Out' => 'Out',
'OverwriteExisting' => 'Overwrite Existing', 'OverwriteExisting' => 'Overwrite Existing',
@ -548,200 +548,200 @@ $SLANG = array(
'PanLeft' => 'Pan Left', 'PanLeft' => 'Pan Left',
'PanRight' => 'Pan Right', 'PanRight' => 'Pan Right',
'PanTilt' => 'Pan/Tilt', 'PanTilt' => 'Pan/Tilt',
'Parameter' => 'פרמטר', 'Parameter' => 'ôøîèø',
'Password' => 'סיסמא', 'Password' => 'ñéñîà',
'PasswordsDifferent' => 'The new and confirm passwords are different', 'PasswordsDifferent' => 'The new and confirm passwords are different',
'Paths' => 'נתיבים', 'Paths' => 'ðúéáéí',
'Pause' => 'Pause', 'Pause' => 'Pause',
'Phone' => 'טלפון', 'Phone' => 'èìôåï',
'PhoneBW' => 'ר/פ&nbsp;טלפון', 'PhoneBW' => 'ø/ô&nbsp;èìôåï',
'Pid' => 'PID', // Added - 2011-06-16 'Pid' => 'PID', // Added - 2011-06-16
'PixelDiff' => 'Pixel Diff', 'PixelDiff' => 'Pixel Diff',
'Pixels' => 'פיקסלים', 'Pixels' => 'ôé÷ñìéí',
'Play' => 'Play', 'Play' => 'Play',
'PlayAll' => 'נגן הכל', 'PlayAll' => 'ðâï äëì',
'PleaseWait' => 'המתן בבקשה', 'PleaseWait' => 'äîúï áá÷ùä',
'Plugins' => 'Plugins', 'Plugins' => 'Plugins',
'Point' => 'נקודה', 'Point' => 'ð÷åãä',
'PostEventImageBuffer' => 'Post Event Image Count', 'PostEventImageBuffer' => 'Post Event Image Count',
'PreEventImageBuffer' => 'Pre Event Image Count', 'PreEventImageBuffer' => 'Pre Event Image Count',
'PreserveAspect' => 'Preserve Aspect Ratio', 'PreserveAspect' => 'Preserve Aspect Ratio',
'Preset' => 'Preset', 'Preset' => 'Preset',
'Presets' => 'Presets', 'Presets' => 'Presets',
'Prev' => 'הקודם', 'Prev' => 'ä÷åãí',
'Probe' => 'Probe', // Added - 2009-03-31 'Probe' => 'Probe', // Added - 2009-03-31
'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18
'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18
'Progress' => 'Progress', // Added - 2015-04-18 'Progress' => 'Progress', // Added - 2015-04-18
'Protocol' => 'Protocol', 'Protocol' => 'Protocol',
'Rate' => 'דירוג', 'Rate' => 'ãéøåâ',
'Real' => 'אמיתי', 'Real' => 'àîéúé',
'Record' => 'הקלטה', 'Record' => 'ä÷ìèä',
'RefImageBlendPct' => 'Reference Image Blend %ge', 'RefImageBlendPct' => 'Reference Image Blend %ge',
'Refresh' => 'רענון', 'Refresh' => 'øòðåï',
'Remote' => 'מרוחק', 'Remote' => 'îøåç÷',
'RemoteHostName' => 'שם מארח מרוחק', 'RemoteHostName' => 'ùí îàøç îøåç÷',
'RemoteHostPath' => 'נתיב מארח מרוחק', 'RemoteHostPath' => 'ðúéá îàøç îøåç÷',
'RemoteHostPort' => 'פורט מארח מרוחק', 'RemoteHostPort' => 'ôåøè îàøç îøåç÷',
'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08 'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08
'RemoteImageColours' => 'Remote Image Colours', 'RemoteImageColours' => 'Remote Image Colours',
'RemoteMethod' => 'Remote Method', // Added - 2009-02-08 'RemoteMethod' => 'Remote Method', // Added - 2009-02-08
'RemoteProtocol' => 'Remote Protocol', // Added - 2009-02-08 'RemoteProtocol' => 'Remote Protocol', // Added - 2009-02-08
'Rename' => 'שנה שם', 'Rename' => 'ùðä ùí',
'Replay' => 'Replay', 'Replay' => 'Replay',
'ReplayAll' => 'All Events', 'ReplayAll' => 'All Events',
'ReplayGapless' => 'Gapless Events', 'ReplayGapless' => 'Gapless Events',
'ReplaySingle' => 'Single Event', 'ReplaySingle' => 'Single Event',
'Reset' => 'אפס', 'Reset' => 'àôñ',
'ResetEventCounts' => 'Reset Event Counts', 'ResetEventCounts' => 'Reset Event Counts',
'Restart' => 'אתחל', 'Restart' => 'àúçì',
'Restarting' => 'מאתחל', 'Restarting' => 'îàúçì',
'RestrictedCameraIds' => 'Restricted Camera Ids', 'RestrictedCameraIds' => 'Restricted Camera Ids',
'RestrictedMonitors' => 'Restricted Monitors', 'RestrictedMonitors' => 'Restricted Monitors',
'ReturnDelay' => 'חזרה מהשהיה', 'ReturnDelay' => 'çæøä îäùäéä',
'ReturnLocation' => 'מיקום חזרה', 'ReturnLocation' => 'îé÷åí çæøä',
'Rewind' => 'Rewind', 'Rewind' => 'Rewind',
'RotateLeft' => 'סובב שמאלה', 'RotateLeft' => 'ñåáá ùîàìä',
'RotateRight' => 'סובב ימינה', 'RotateRight' => 'ñåáá éîéðä',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25 'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunMode' => 'צורת ריצה', 'RunMode' => 'öåøú øéöä',
'RunState' => 'מצב ריצה', 'RunState' => 'îöá øéöä',
'Running' => 'מריץ', 'Running' => 'îøéõ',
'Save' => 'שמור', 'Save' => 'ùîåø',
'SaveAs' => 'שמור בשם', 'SaveAs' => 'ùîåø áùí',
'SaveFilter' => 'שמור מסנן', 'SaveFilter' => 'ùîåø îñðï',
'Scale' => 'סקאלה', 'Scale' => 'ñ÷àìä',
'Score' => 'ניקוד', 'Score' => 'ðé÷åã',
'Secs' => 'שניות', 'Secs' => 'ùðéåú',
'Sectionlength' => 'אורך קטע', 'Sectionlength' => 'àåøê ÷èò',
'Select' => 'בחר', 'Select' => 'áçø',
'SelectFormat' => 'Select Format', // Added - 2011-06-17 'SelectFormat' => 'Select Format', // Added - 2011-06-17
'SelectLog' => 'Select Log', // Added - 2011-06-17 'SelectLog' => 'Select Log', // Added - 2011-06-17
'SelectMonitors' => 'בחר מוניטורים', 'SelectMonitors' => 'áçø îåðéèåøéí',
'SelfIntersecting' => 'Polygon edges must not intersect', 'SelfIntersecting' => 'Polygon edges must not intersect',
'Set' => 'קבע', 'Set' => '÷áò',
'SetNewBandwidth' => 'Set New Bandwidth', 'SetNewBandwidth' => 'Set New Bandwidth',
'SetPreset' => 'Set Preset', 'SetPreset' => 'Set Preset',
'Settings' => 'הגדרות', 'Settings' => 'äâãøåú',
'ShowFilterWindow' => 'Show Filter Window', 'ShowFilterWindow' => 'Show Filter Window',
'ShowTimeline' => 'Show Timeline', 'ShowTimeline' => 'Show Timeline',
'SignalCheckColour' => 'Signal Check Colour', 'SignalCheckColour' => 'Signal Check Colour',
'Size' => 'גודל', 'Size' => 'âåãì',
'SkinDescription' => 'Change the default skin for this computer', // Added - 2011-01-30 'SkinDescription' => 'Change the default skin for this computer', // Added - 2011-01-30
'Sleep' => 'שינה', 'Sleep' => 'ùéðä',
'SortAsc' => 'Asc', 'SortAsc' => 'Asc',
'SortBy' => 'Sort by', 'SortBy' => 'Sort by',
'SortDesc' => 'Desc', 'SortDesc' => 'Desc',
'Source' => 'מקור', 'Source' => 'î÷åø',
'SourceColours' => 'Source Colours', // Added - 2009-02-08 'SourceColours' => 'Source Colours', // Added - 2009-02-08
'SourcePath' => 'Source Path', // Added - 2009-02-08 'SourcePath' => 'Source Path', // Added - 2009-02-08
'SourceType' => 'סוג מקור', 'SourceType' => 'ñåâ î÷åø',
'Speed' => 'מהירות', 'Speed' => 'îäéøåú',
'SpeedHigh' => 'מהירות גבוהה', 'SpeedHigh' => 'îäéøåú âáåää',
'SpeedLow' => 'מהירות נמוכה', 'SpeedLow' => 'îäéøåú ðîåëä',
'SpeedMedium' => 'מצלמה בינונית', 'SpeedMedium' => 'îöìîä áéðåðéú',
'SpeedTurbo' => 'מהירות טורבו', 'SpeedTurbo' => 'îäéøåú èåøáå',
'Start' => 'התחל', 'Start' => 'äúçì',
'State' => 'מצב', 'State' => 'îöá',
'Stats' => 'מצבים', 'Stats' => 'îöáéí',
'Status' => 'סטטוס', 'Status' => 'ñèèåñ',
'Step' => 'צעד', 'Step' => 'öòã',
'StepBack' => 'Step Back', 'StepBack' => 'Step Back',
'StepForward' => 'Step Forward', 'StepForward' => 'Step Forward',
'StepLarge' => 'צעד גדול', 'StepLarge' => 'öòã âãåì',
'StepMedium' => 'צעד בינוני', 'StepMedium' => 'öòã áéðåðé',
'StepNone' => 'אל תצעד', 'StepNone' => 'àì úöòã',
'StepSmall' => 'צעד קטן', 'StepSmall' => 'öòã ÷èï',
'Stills' => 'סטילס', 'Stills' => 'ñèéìñ',
'Stop' => 'עצור', 'Stop' => 'òöåø',
'Stopped' => 'נעצר', 'Stopped' => 'ðòöø',
'Stream' => 'סטרים', 'Stream' => 'ñèøéí',
'StreamReplayBuffer' => 'Stream Replay Image Buffer', 'StreamReplayBuffer' => 'Stream Replay Image Buffer',
'Submit' => 'Submit', 'Submit' => 'Submit',
'System' => 'מערכת', 'System' => 'îòøëú',
'SystemLog' => 'System Log', // Added - 2011-06-16 'SystemLog' => 'System Log', // Added - 2011-06-16
'TargetColorspace' => 'Target colorspace', // Added - 2015-04-18 'TargetColorspace' => 'Target colorspace', // Added - 2015-04-18
'Tele' => 'טל', 'Tele' => 'èì',
'Thumbnail' => 'Thumbnail', 'Thumbnail' => 'Thumbnail',
'Tilt' => 'Tilt', 'Tilt' => 'Tilt',
'Time' => 'זמן', 'Time' => 'æîï',
'TimeDelta' => 'שינוי בזמן', 'TimeDelta' => 'ùéðåé áæîï',
'TimeStamp' => 'חותמת זמן', 'TimeStamp' => 'çåúîú æîï',
'Timeline' => 'קו זמן', 'Timeline' => '÷å æîï',
'TimelineTip1' => 'Pass your mouse over the graph to view a snapshot image and event details.', // Added 2013.08.15. '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. '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. '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. 'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // Added 2013.08.15.
'Timestamp' => 'חותמת זמן', 'Timestamp' => 'çåúîú æîï',
'TimestampLabelFormat' => 'Timestamp Label Format', 'TimestampLabelFormat' => 'Timestamp Label Format',
'TimestampLabelX' => 'Timestamp Label X', 'TimestampLabelX' => 'Timestamp Label X',
'TimestampLabelY' => 'Timestamp Label Y', 'TimestampLabelY' => 'Timestamp Label Y',
'Today' => 'היום', 'Today' => 'äéåí',
'Tools' => 'כלים', 'Tools' => 'ëìéí',
'Total' => 'Total', // Added - 2011-06-16 'Total' => 'Total', // Added - 2011-06-16
'TotalBrScore' => 'סך<br/>ניקוד', 'TotalBrScore' => 'ñê<br/>ðé÷åã',
'TrackDelay' => 'Track Delay', 'TrackDelay' => 'Track Delay',
'TrackMotion' => 'Track Motion', 'TrackMotion' => 'Track Motion',
'Triggers' => 'טריגרים', 'Triggers' => 'èøéâøéí',
'TurboPanSpeed' => 'Turbo Pan Speed', 'TurboPanSpeed' => 'Turbo Pan Speed',
'TurboTiltSpeed' => 'Turbo Tilt Speed', 'TurboTiltSpeed' => 'Turbo Tilt Speed',
'Type' => 'סוג', 'Type' => 'ñåâ',
'Unarchive' => 'בלתי ארכיב', 'Unarchive' => 'áìúé àøëéá',
'Undefined' => 'Undefined', // Added - 2009-02-08 'Undefined' => 'Undefined', // Added - 2009-02-08
'Units' => 'יחידות', 'Units' => 'éçéãåú',
'Unknown' => 'בלתי ידוע', 'Unknown' => 'áìúé éãåò',
'Update' => 'עדכון', 'Update' => 'òãëåï',
'UpdateAvailable' => 'עדכון לזון-מינדר אפשרי.', 'UpdateAvailable' => 'òãëåï ìæåï-îéðãø àôùøé.',
'UpdateNotNecessary' => 'עדכון אינו הכרחי.', 'UpdateNotNecessary' => 'òãëåï àéðå äëøçé.',
'Updated' => 'Updated', // Added - 2011-06-16 'Updated' => 'Updated', // Added - 2011-06-16
'Upload' => 'Upload', // Added - 2011-08-23 'Upload' => 'Upload', // Added - 2011-08-23
'UseFilter' => 'שימוש במסנן', 'UseFilter' => 'ùéîåù áîñðï',
'UseFilterExprsPost' => '&nbsp;filter&nbsp;expressions', // This is used at the end of the phrase 'use N filter expressions' 'UseFilterExprsPost' => '&nbsp;filter&nbsp;expressions', // This is used at the end of the phrase 'use N filter expressions'
'UseFilterExprsPre' => 'שימוש&nbsp;', // This is used at the beginning of the phrase 'use N filter expressions' 'UseFilterExprsPre' => 'ùéîåù&nbsp;', // This is used at the beginning of the phrase 'use N filter expressions'
'UsedPlugins' => 'Used Plugins', 'UsedPlugins' => 'Used Plugins',
'User' => 'משתמש', 'User' => 'îùúîù',
'Username' => 'שם משתמש', 'Username' => 'ùí îùúîù',
'Users' => 'משתמשים', 'Users' => 'îùúîùéí',
'V4L' => 'V4L', // Added - 2015-04-18 'V4L' => 'V4L', // Added - 2015-04-18
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18 'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18 'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
'Value' => 'ערך', 'Value' => 'òøê',
'Version' => 'גירסה', 'Version' => 'âéøñä',
'VersionIgnore' => 'התעלם מגירסה זו', 'VersionIgnore' => 'äúòìí îâéøñä æå',
'VersionRemindDay' => 'הזכר לי בעוד יום אחד', 'VersionRemindDay' => 'äæëø ìé áòåã éåí àçã',
'VersionRemindHour' => 'הזכר לי בעוד שעה אחת', 'VersionRemindHour' => 'äæëø ìé áòåã ùòä àçú',
'VersionRemindNever' => 'Don\'t remind about new versions', 'VersionRemindNever' => 'Don\'t remind about new versions',
'VersionRemindWeek' => 'Remind again in 1 week', 'VersionRemindWeek' => 'Remind again in 1 week',
'Video' => 'וידאו', 'Video' => 'åéãàå',
'VideoFormat' => 'תבנית וידאו', 'VideoFormat' => 'úáðéú åéãàå',
'VideoGenFailed' => 'Video Generation Failed!', 'VideoGenFailed' => 'Video Generation Failed!',
'VideoGenFiles' => 'Existing Video Files', 'VideoGenFiles' => 'Existing Video Files',
'VideoGenNoFiles' => 'No Video Files Found', 'VideoGenNoFiles' => 'No Video Files Found',
'VideoGenParms' => 'Video Generation Parameters', 'VideoGenParms' => 'Video Generation Parameters',
'VideoGenSucceeded' => 'Video Generation Succeeded!', 'VideoGenSucceeded' => 'Video Generation Succeeded!',
'VideoSize' => 'גודל וידאו', 'VideoSize' => 'âåãì åéãàå',
'View' => 'הצג', 'View' => 'äöâ',
'ViewAll' => 'הצג הכל', 'ViewAll' => 'äöâ äëì',
'ViewEvent' => 'הצג אירוע', 'ViewEvent' => 'äöâ àéøåò',
'ViewPaged' => 'View Paged', 'ViewPaged' => 'View Paged',
'Wake' => 'הער', 'Wake' => 'äòø',
'WarmupFrames' => 'Warmup Frames', 'WarmupFrames' => 'Warmup Frames',
'Watch' => 'צפה', 'Watch' => 'öôä',
'Web' => 'אינטרנט', 'Web' => 'àéðèøðè',
'WebColour' => 'צבע אינטרנט', 'WebColour' => 'öáò àéðèøðè',
'Week' => 'שבוע', 'Week' => 'ùáåò',
'White' => 'לבן', 'White' => 'ìáï',
'WhiteBalance' => 'White Balance', 'WhiteBalance' => 'White Balance',
'Wide' => 'רחב', 'Wide' => 'øçá',
'X' => 'X', 'X' => 'X',
'X10' => 'X10', 'X10' => 'X10',
'X10ActivationString' => 'X10 Activation String', 'X10ActivationString' => 'X10 Activation String',
'X10InputAlarmString' => 'X10 Input Alarm String', 'X10InputAlarmString' => 'X10 Input Alarm String',
'X10OutputAlarmString' => 'X10 Output Alarm String', 'X10OutputAlarmString' => 'X10 Output Alarm String',
'Y' => 'Y', 'Y' => 'Y',
'Yes' => 'כן', 'Yes' => 'ëï',
'YouNoPerms' => 'אין לך הרשאה להיכנס למקור זה.', 'YouNoPerms' => 'àéï ìê äøùàä ìäéëðñ ìî÷åø æä.',
'Zone' => 'אזור', 'Zone' => 'àæåø',
'ZoneAlarmColour' => 'Alarm Colour (Red/Green/Blue)', 'ZoneAlarmColour' => 'Alarm Colour (Red/Green/Blue)',
'ZoneArea' => 'Zone Area', 'ZoneArea' => 'Zone Area',
'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count', 'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count',
@ -753,10 +753,10 @@ $SLANG = array(
'ZoneMinMaxPixelThres' => 'Min/Max Pixel Threshold (0-255)', 'ZoneMinMaxPixelThres' => 'Min/Max Pixel Threshold (0-255)',
'ZoneMinderLog' => 'ZoneMinder Log', // Added - 2011-06-17 'ZoneMinderLog' => 'ZoneMinder Log', // Added - 2011-06-17
'ZoneOverloadFrames' => 'Overload Frame Ignore Count', 'ZoneOverloadFrames' => 'Overload Frame Ignore Count',
'Zones' => 'אזורים', 'Zones' => 'àæåøéí',
'Zoom' => 'זום', 'Zoom' => 'æåí',
'ZoomIn' => 'זום פנימה', 'ZoomIn' => 'æåí ôðéîä',
'ZoomOut' => 'זום החוצה', 'ZoomOut' => 'æåí äçåöä',
); );
// Complex replacements with formatting and/or placements, must be passed through sprintf // Complex replacements with formatting and/or placements, must be passed through sprintf

View File

@ -4,7 +4,7 @@
// //
// Feel Free to contact Me at illuminati@linuxmail.org // Feel Free to contact Me at illuminati@linuxmail.org
// //
// Tradução Para Português do Brasil do Zoneminder // Tradução Para Português do Brasil do Zoneminder
// //
// Sinta-se Livre para me contactar em illuminati@linuxmail.org // Sinta-se Livre para me contactar em illuminati@linuxmail.org
@ -18,7 +18,7 @@ $SLANG = array(
'Actual' => 'Atual', 'Actual' => 'Atual',
'AddNewControl' => 'Add New Control', 'AddNewControl' => 'Add New Control',
'AddNewMonitor' => 'Adicionar Monitor', 'AddNewMonitor' => 'Adicionar Monitor',
'AddNewUser' => 'Adicionar Usuário', 'AddNewUser' => 'Adicionar Usuário',
'AddNewZone' => 'Adicionar Zona', 'AddNewZone' => 'Adicionar Zona',
'Alarm' => 'Alarme', 'Alarm' => 'Alarme',
'AlarmBrFrames' => 'Imagens<br/>Alarmadas', 'AlarmBrFrames' => 'Imagens<br/>Alarmadas',
@ -34,7 +34,7 @@ $SLANG = array(
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22 'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23 'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
'Apply' => 'Aplicar', 'Apply' => 'Aplicar',
'ApplyingStateChange' => 'Aplicando mudança de estado', 'ApplyingStateChange' => 'Aplicando mudança de estado',
'ArchArchived' => 'Somente Arquivados', 'ArchArchived' => 'Somente Arquivados',
'ArchUnarchived' => 'Somente Nao Arquivados', 'ArchUnarchived' => 'Somente Nao Arquivados',
'Archive' => 'Arquivar', 'Archive' => 'Arquivar',
@ -49,7 +49,7 @@ $SLANG = array(
'AttrDateTime' => 'Data/Horario', 'AttrDateTime' => 'Data/Horario',
'AttrDiskBlocks' => 'Blocos de Disco', 'AttrDiskBlocks' => 'Blocos de Disco',
'AttrDiskPercent' => 'Porcentagem de Disco', 'AttrDiskPercent' => 'Porcentagem de Disco',
'AttrDuration' => 'Duração', 'AttrDuration' => 'Duração',
'AttrFrames' => 'Imagens', 'AttrFrames' => 'Imagens',
'AttrId' => 'Id', 'AttrId' => 'Id',
'AttrMaxScore' => 'Max. Score', 'AttrMaxScore' => 'Max. Score',
@ -58,7 +58,7 @@ $SLANG = array(
'AttrName' => 'Nome', 'AttrName' => 'Nome',
'AttrNotes' => 'Notes', 'AttrNotes' => 'Notes',
'AttrSystemLoad' => 'System Load', 'AttrSystemLoad' => 'System Load',
'AttrTime' => 'Horário', 'AttrTime' => 'Horário',
'AttrTotalScore' => 'Score Total', 'AttrTotalScore' => 'Score Total',
'AttrWeekday' => 'Dia/Semana', 'AttrWeekday' => 'Dia/Semana',
'Auto' => 'Auto', 'Auto' => 'Auto',
@ -84,7 +84,7 @@ $SLANG = array(
'BadLabelY' => 'Label Y co-ordinate must be set to an integer of zero or more', 'BadLabelY' => 'Label Y co-ordinate must be set to an integer of zero or more',
'BadMaxFPS' => 'Maximum FPS must be a positive integer or floating point value', 'BadMaxFPS' => 'Maximum FPS must be a positive integer or floating point value',
'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more', 'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more',
'BadNameChars' => 'Nomes devem ser caracteres alfanuméricos mais hífen e underscore', 'BadNameChars' => 'Nomes devem ser caracteres alfanuméricos mais hífen e underscore',
'BadPalette' => 'Palette must be set to a valid value', // Added - 2009-03-31 'BadPalette' => 'Palette must be set to a valid value', // Added - 2009-03-31
'BadPath' => 'Path must be set to a valid value', 'BadPath' => 'Path must be set to a valid value',
'BadPort' => 'Port must be set to a valid number', 'BadPort' => 'Port must be set to a valid number',
@ -145,7 +145,7 @@ $SLANG = array(
'CanZoomCon' => 'Can Zoom Continuous', 'CanZoomCon' => 'Can Zoom Continuous',
'CanZoomRel' => 'Can Zoom Relative', 'CanZoomRel' => 'Can Zoom Relative',
'Cancel' => 'Cancelar', 'Cancel' => 'Cancelar',
'CancelForcedAlarm' => 'Cancelar Alarme Forçado', 'CancelForcedAlarm' => 'Cancelar Alarme Forçado',
'CaptureHeight' => 'Altura da Captura', 'CaptureHeight' => 'Altura da Captura',
'CaptureMethod' => 'Capture Method', // Added - 2009-02-08 'CaptureMethod' => 'Capture Method', // Added - 2009-02-08
'CapturePalette' => 'Paleta de Captura', 'CapturePalette' => 'Paleta de Captura',
@ -192,10 +192,10 @@ $SLANG = array(
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18 'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18 'Delay' => 'Delay', // Added - 2015-04-18
'Delete' => 'Deletar', 'Delete' => 'Deletar',
'DeleteAndNext' => 'Deletar &amp; Próx', 'DeleteAndNext' => 'Deletar &amp; Próx',
'DeleteAndPrev' => 'Deletar &amp; Ant', 'DeleteAndPrev' => 'Deletar &amp; Ant',
'DeleteSavedFilter' => 'Deletar Filtros Salvos', 'DeleteSavedFilter' => 'Deletar Filtros Salvos',
'Description' => 'Descrição', 'Description' => 'Descrição',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31 'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18 'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18
'Device' => 'Device', // Added - 2009-02-08 'Device' => 'Device', // Added - 2009-02-08
@ -204,7 +204,7 @@ $SLANG = array(
'DeviceNumber' => 'Num. do Dispos.', 'DeviceNumber' => 'Num. do Dispos.',
'DevicePath' => 'Device Path', 'DevicePath' => 'Device Path',
'Devices' => 'Devices', 'Devices' => 'Devices',
'Dimensions' => 'Dimensões', 'Dimensions' => 'Dimensões',
'DisableAlarms' => 'Disable Alarms', 'DisableAlarms' => 'Disable Alarms',
'Disk' => 'Disco', 'Disk' => 'Disco',
'Display' => 'Display', // Added - 2011-01-30 'Display' => 'Display', // Added - 2011-01-30
@ -221,15 +221,15 @@ $SLANG = array(
'DonateYes' => 'Yes, I\'d like to donate now', 'DonateYes' => 'Yes, I\'d like to donate now',
'Download' => 'Download', 'Download' => 'Download',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31 'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
'Duration' => 'Duração', 'Duration' => 'Duração',
'Edit' => 'Editar', 'Edit' => 'Editar',
'Email' => 'Email', 'Email' => 'Email',
'EnableAlarms' => 'Enable Alarms', 'EnableAlarms' => 'Enable Alarms',
'Enabled' => 'Habilitado', 'Enabled' => 'Habilitado',
'EnterNewFilterName' => 'Digite nome do novo filtro', 'EnterNewFilterName' => 'Digite nome do novo filtro',
'Error' => 'Erro', 'Error' => 'Erro',
'ErrorBrackets' => 'Por favor cheque se você tem o mesmo numero de chaves abertas e fechadas', 'ErrorBrackets' => 'Por favor cheque se você tem o mesmo numero de chaves abertas e fechadas',
'ErrorValidValue' => 'Erro, por favor cheque se os campos estão corretos', 'ErrorValidValue' => 'Erro, por favor cheque se os campos estão corretos',
'Etc' => 'etc', 'Etc' => 'etc',
'Event' => 'Evento', 'Event' => 'Evento',
'EventFilter' => 'Filtro de Evento', 'EventFilter' => 'Filtro de Evento',
@ -283,7 +283,7 @@ $SLANG = array(
'FnNone' => 'None', // Added 2013.08.16. 'FnNone' => 'None', // Added 2013.08.16.
'FnRecord' => 'Record', // Added 2013.08.16. 'FnRecord' => 'Record', // Added 2013.08.16.
'Focus' => 'Focus', 'Focus' => 'Focus',
'ForceAlarm' => 'Forçar Alarme', 'ForceAlarm' => 'Forçar Alarme',
'Format' => 'Format', 'Format' => 'Format',
'Frame' => 'Imagem', 'Frame' => 'Imagem',
'FrameId' => 'Id de Imagem', 'FrameId' => 'Id de Imagem',
@ -291,7 +291,7 @@ $SLANG = array(
'FrameSkip' => 'Salto de Imagem', 'FrameSkip' => 'Salto de Imagem',
'Frames' => 'Imagens', 'Frames' => 'Imagens',
'Func' => 'Func', 'Func' => 'Func',
'Function' => 'Função', 'Function' => 'Função',
'Gain' => 'Gain', 'Gain' => 'Gain',
'General' => 'General', 'General' => 'General',
'GenerateVideo' => 'Gerar Video', 'GenerateVideo' => 'Gerar Video',
@ -315,7 +315,7 @@ $SLANG = array(
'HighBW' => 'Alta&nbsp;L/B', 'HighBW' => 'Alta&nbsp;L/B',
'Home' => 'Home', 'Home' => 'Home',
'Hour' => 'Hora', 'Hour' => 'Hora',
'Hue' => 'Saturação', 'Hue' => 'Saturação',
'Id' => 'Id', 'Id' => 'Id',
'Idle' => 'Parado', 'Idle' => 'Parado',
'Ignore' => 'Ignorar', 'Ignore' => 'Ignorar',
@ -329,7 +329,7 @@ $SLANG = array(
'KeyString' => 'Key String', 'KeyString' => 'Key String',
'Label' => 'Label', 'Label' => 'Label',
'Language' => 'Linguagem', 'Language' => 'Linguagem',
'Last' => 'Último', 'Last' => 'Último',
'Layout' => 'Layout', // Added - 2009-02-08 'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16 'Level' => 'Level', // Added - 2011-06-16
'Libvlc' => 'Libvlc', 'Libvlc' => 'Libvlc',
@ -383,7 +383,7 @@ $SLANG = array(
'Message' => 'Message', // Added - 2011-06-16 'Message' => 'Message', // Added - 2011-06-16
'MinAlarmAreaLtMax' => 'Minimum alarm area should be less than maximum', 'MinAlarmAreaLtMax' => 'Minimum alarm area should be less than maximum',
'MinAlarmAreaUnset' => 'You must specify the minimum alarm pixel count', 'MinAlarmAreaUnset' => 'You must specify the minimum alarm pixel count',
'MinBlobAreaLtMax' => 'A area minima de blob deve ser menor do que a area máxima de blob', 'MinBlobAreaLtMax' => 'A area minima de blob deve ser menor do que a area máxima de blob',
'MinBlobAreaUnset' => 'You must specify the minimum blob pixel count', 'MinBlobAreaUnset' => 'You must specify the minimum blob pixel count',
'MinBlobLtMinFilter' => 'Minimum blob area should be less than or equal to minimum filter area', 'MinBlobLtMinFilter' => 'Minimum blob area should be less than or equal to minimum filter area',
'MinBlobsLtMax' => 'O minimo de Blobs deve ser menor que o maximo de blobs', 'MinBlobsLtMax' => 'O minimo de Blobs deve ser menor que o maximo de blobs',
@ -424,7 +424,7 @@ $SLANG = array(
'MonitorProbeIntro' => 'The list below shows detected analog and network cameras and whether they are already being used or available for selection.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // 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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2009-03-31
'Monitors' => 'Monitores', 'Monitors' => 'Monitores',
'Montage' => 'Montagem', 'Montage' => 'Montagem',
'Month' => 'Mês', 'Month' => 'Mês',
'More' => 'More', // Added - 2011-06-16 'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip', 'MotionFrameSkip' => 'Motion Frame Skip',
'Move' => 'Move', 'Move' => 'Move',
@ -437,7 +437,7 @@ $SLANG = array(
'MustBeLe' => 'deve ser menor ou igual a', 'MustBeLe' => 'deve ser menor ou igual a',
'MustConfirmPassword' => 'Voce deve Confirmar a senha', 'MustConfirmPassword' => 'Voce deve Confirmar a senha',
'MustSupplyPassword' => 'Voce deve informar a senha', 'MustSupplyPassword' => 'Voce deve informar a senha',
'MustSupplyUsername' => 'Voce deve informar nome de usuário', 'MustSupplyUsername' => 'Voce deve informar nome de usuário',
'Name' => 'Nome', 'Name' => 'Nome',
'Near' => 'Near', 'Near' => 'Near',
'Network' => 'Rede', 'Network' => 'Rede',
@ -446,16 +446,16 @@ $SLANG = array(
'NewLabel' => 'New Label', 'NewLabel' => 'New Label',
'NewPassword' => 'Nova Senha', 'NewPassword' => 'Nova Senha',
'NewState' => 'Novo Estado', 'NewState' => 'Novo Estado',
'NewUser' => 'Novo Usuário', 'NewUser' => 'Novo Usuário',
'Next' => 'Próx', 'Next' => 'Próx',
'No' => 'Não', 'No' => 'Não',
'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31 'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31
'NoFramesRecorded' => 'Não há imagens gravadas neste evento', 'NoFramesRecorded' => 'Não há imagens gravadas neste evento',
'NoGroup' => 'No Group', 'NoGroup' => 'No Group',
'NoSavedFilters' => 'SemFiltrosSalvos', 'NoSavedFilters' => 'SemFiltrosSalvos',
'NoStatisticsRecorded' => 'Não há estatísticas gravadas neste evento/imagem', 'NoStatisticsRecorded' => 'Não há estatísticas gravadas neste evento/imagem',
'None' => 'Nada', 'None' => 'Nada',
'NoneAvailable' => 'Nada disponível', 'NoneAvailable' => 'Nada disponível',
'Normal' => 'Normal', 'Normal' => 'Normal',
'Notes' => 'Notes', 'Notes' => 'Notes',
'NumPresets' => 'Num Presets', 'NumPresets' => 'Num Presets',
@ -472,15 +472,15 @@ $SLANG = array(
'OpLtEq' => 'menor que ou igual a', 'OpLtEq' => 'menor que ou igual a',
'OpMatches' => 'combina', 'OpMatches' => 'combina',
'OpNe' => 'diferente de', 'OpNe' => 'diferente de',
'OpNotIn' => 'não no set', 'OpNotIn' => 'não no set',
'OpNotMatches' => 'não combina', 'OpNotMatches' => 'não combina',
'Open' => 'Open', 'Open' => 'Open',
'OptionHelp' => 'OpçãoAjuda', 'OptionHelp' => 'OpçãoAjuda',
'OptionRestartWarning' => 'Reinicie o Zoneminder para que as mudanças tenham efeito', 'OptionRestartWarning' => 'Reinicie o Zoneminder para que as mudanças tenham efeito',
'Options' => 'Opções', 'Options' => 'Opções',
'OrEnterNewName' => 'ou defina novo nome', 'OrEnterNewName' => 'ou defina novo nome',
'Order' => 'Order', 'Order' => 'Order',
'Orientation' => 'Orientação', 'Orientation' => 'Orientação',
'Out' => 'Out', 'Out' => 'Out',
'OverwriteExisting' => 'Sobrescrever Existente', 'OverwriteExisting' => 'Sobrescrever Existente',
'Paged' => 'Paginado', 'Paged' => 'Paginado',
@ -490,7 +490,7 @@ $SLANG = array(
'PanTilt' => 'Pan/Tilt', 'PanTilt' => 'Pan/Tilt',
'Parameter' => 'Parametro', 'Parameter' => 'Parametro',
'Password' => 'Senha', 'Password' => 'Senha',
'PasswordsDifferent' => 'A nova senha e a de confirmação são diferentes', 'PasswordsDifferent' => 'A nova senha e a de confirmação são diferentes',
'Paths' => 'Caminhos', 'Paths' => 'Caminhos',
'Pause' => 'Pause', 'Pause' => 'Pause',
'Phone' => 'Phone', 'Phone' => 'Phone',
@ -503,8 +503,8 @@ $SLANG = array(
'PleaseWait' => 'Por Favor Espere', 'PleaseWait' => 'Por Favor Espere',
'Plugins' => 'Plugins', 'Plugins' => 'Plugins',
'Point' => 'Point', 'Point' => 'Point',
'PostEventImageBuffer' => 'Buffer de imagem pós evento', 'PostEventImageBuffer' => 'Buffer de imagem pós evento',
'PreEventImageBuffer' => 'Buffer de imagem pré evento', 'PreEventImageBuffer' => 'Buffer de imagem pré evento',
'PreserveAspect' => 'Preserve Aspect Ratio', 'PreserveAspect' => 'Preserve Aspect Ratio',
'Preset' => 'Preset', 'Preset' => 'Preset',
'Presets' => 'Presets', 'Presets' => 'Presets',
@ -517,7 +517,7 @@ $SLANG = array(
'Rate' => 'Vel.', 'Rate' => 'Vel.',
'Real' => 'Real', 'Real' => 'Real',
'Record' => 'Gravar', 'Record' => 'Gravar',
'RefImageBlendPct' => 'Referência de imagem Blend %ge', 'RefImageBlendPct' => 'Referência de imagem Blend %ge',
'Refresh' => 'Atualizar', 'Refresh' => 'Atualizar',
'Remote' => 'Remoto', 'Remote' => 'Remoto',
'RemoteHostName' => 'Nome do host remoto', 'RemoteHostName' => 'Nome do host remoto',
@ -536,16 +536,16 @@ $SLANG = array(
'ResetEventCounts' => 'Resetar contagem de eventos', 'ResetEventCounts' => 'Resetar contagem de eventos',
'Restart' => 'Reiniciar', 'Restart' => 'Reiniciar',
'Restarting' => 'Reiniciando', 'Restarting' => 'Reiniciando',
'RestrictedCameraIds' => 'Ids de camera proibídos', 'RestrictedCameraIds' => 'Ids de camera proibídos',
'RestrictedMonitors' => 'Restricted Monitors', 'RestrictedMonitors' => 'Restricted Monitors',
'ReturnDelay' => 'Return Delay', 'ReturnDelay' => 'Return Delay',
'ReturnLocation' => 'Return Location', 'ReturnLocation' => 'Return Location',
'Rewind' => 'Rewind', 'Rewind' => 'Rewind',
'RotateLeft' => 'Rotacionar à esquerda ', 'RotateLeft' => 'Rotacionar à esquerda ',
'RotateRight' => 'Rotacionar à direita', 'RotateRight' => 'Rotacionar à direita',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25 'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunMode' => 'Modo de Execução', 'RunMode' => 'Modo de Execução',
'RunState' => 'Estado de Execução', 'RunState' => 'Estado de Execução',
'Running' => 'Rodando', 'Running' => 'Rodando',
'Save' => 'Salvar', 'Save' => 'Salvar',
'SaveAs' => 'Salvar Como', 'SaveAs' => 'Salvar Como',
@ -562,7 +562,7 @@ $SLANG = array(
'Set' => 'Set', 'Set' => 'Set',
'SetNewBandwidth' => 'Defina Nova L/B', 'SetNewBandwidth' => 'Defina Nova L/B',
'SetPreset' => 'Set Preset', 'SetPreset' => 'Set Preset',
'Settings' => 'Configurações', 'Settings' => 'Configurações',
'ShowFilterWindow' => 'MostrarJanelaDeFiltros', 'ShowFilterWindow' => 'MostrarJanelaDeFiltros',
'ShowTimeline' => 'Show Timeline', 'ShowTimeline' => 'Show Timeline',
'SignalCheckColour' => 'Signal Check Colour', 'SignalCheckColour' => 'Signal Check Colour',
@ -595,7 +595,7 @@ $SLANG = array(
'Stills' => 'Imagens', 'Stills' => 'Imagens',
'Stop' => 'Parar', 'Stop' => 'Parar',
'Stopped' => 'Parado', 'Stopped' => 'Parado',
'Stream' => 'Contínuo', 'Stream' => 'Contínuo',
'StreamReplayBuffer' => 'Stream Replay Image Buffer', 'StreamReplayBuffer' => 'Stream Replay Image Buffer',
'Submit' => 'Submit', 'Submit' => 'Submit',
'System' => 'Sistema', 'System' => 'Sistema',
@ -614,8 +614,8 @@ $SLANG = array(
'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // 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' => 'Tempo', 'Timestamp' => 'Tempo',
'TimestampLabelFormat' => 'Formato de etiqueta de tempo', 'TimestampLabelFormat' => 'Formato de etiqueta de tempo',
'TimestampLabelX' => 'posição de etiqueta X', 'TimestampLabelX' => 'posição de etiqueta X',
'TimestampLabelY' => 'posição de etiqueta Y', 'TimestampLabelY' => 'posição de etiqueta Y',
'Today' => 'Today', 'Today' => 'Today',
'Tools' => 'Ferramentas', 'Tools' => 'Ferramentas',
'Total' => 'Total', // Added - 2011-06-16 'Total' => 'Total', // Added - 2011-06-16
@ -631,35 +631,35 @@ $SLANG = array(
'Units' => 'Unidades', 'Units' => 'Unidades',
'Unknown' => 'Desconhecido', 'Unknown' => 'Desconhecido',
'Update' => 'Update', 'Update' => 'Update',
'UpdateAvailable' => 'Um update ao zoneminder está disponível.', 'UpdateAvailable' => 'Um update ao zoneminder está disponível.',
'UpdateNotNecessary' => 'Não é necessário update.', 'UpdateNotNecessary' => 'Não é necessário update.',
'Updated' => 'Updated', // Added - 2011-06-16 'Updated' => 'Updated', // Added - 2011-06-16
'Upload' => 'Upload', // Added - 2011-08-23 'Upload' => 'Upload', // Added - 2011-08-23
'UseFilter' => 'Use Filtro', 'UseFilter' => 'Use Filtro',
'UseFilterExprsPost' => '&nbsp;expressões&nbsp;de&nbsp;filtragem', // This is used at the end of the phrase 'use N filter expressions' 'UseFilterExprsPost' => '&nbsp;expressões&nbsp;de&nbsp;filtragem', // This is used at the end of the phrase 'use N filter expressions'
'UseFilterExprsPre' => 'Use&nbsp;', // This is used at the beginning of the phrase 'use N filter expressions' 'UseFilterExprsPre' => 'Use&nbsp;', // This is used at the beginning of the phrase 'use N filter expressions'
'UsedPlugins' => 'Used Plugins', 'UsedPlugins' => 'Used Plugins',
'User' => 'Usuário', 'User' => 'Usuário',
'Username' => 'Nome de Usuário', 'Username' => 'Nome de Usuário',
'Users' => 'Usuários', 'Users' => 'Usuários',
'V4L' => 'V4L', // Added - 2015-04-18 'V4L' => 'V4L', // Added - 2015-04-18
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18 'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18 'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
'Value' => 'Valor', 'Value' => 'Valor',
'Version' => 'Versão', 'Version' => 'Versão',
'VersionIgnore' => 'Ignorar esta versão', 'VersionIgnore' => 'Ignorar esta versão',
'VersionRemindDay' => 'Lembre novamente em 1 dia', 'VersionRemindDay' => 'Lembre novamente em 1 dia',
'VersionRemindHour' => 'Lembre novamente em 1 hora', 'VersionRemindHour' => 'Lembre novamente em 1 hora',
'VersionRemindNever' => 'Nao lembrar novas versões', 'VersionRemindNever' => 'Nao lembrar novas versões',
'VersionRemindWeek' => 'Lembrar novamente em 1 semana', 'VersionRemindWeek' => 'Lembrar novamente em 1 semana',
'Video' => 'Video', 'Video' => 'Video',
'VideoFormat' => 'Video Format', 'VideoFormat' => 'Video Format',
'VideoGenFailed' => 'Geração de Vídeo falhou!', 'VideoGenFailed' => 'Geração de Vídeo falhou!',
'VideoGenFiles' => 'Existing Video Files', 'VideoGenFiles' => 'Existing Video Files',
'VideoGenNoFiles' => 'No Video Files Found', 'VideoGenNoFiles' => 'No Video Files Found',
'VideoGenParms' => 'Parametros de geração de vídeo', 'VideoGenParms' => 'Parametros de geração de vídeo',
'VideoGenSucceeded' => 'Video Generation Succeeded!', 'VideoGenSucceeded' => 'Video Generation Succeeded!',
'VideoSize' => 'Tamanho do vídeo', 'VideoSize' => 'Tamanho do vídeo',
'View' => 'Ver', 'View' => 'Ver',
'ViewAll' => 'Ver Tudo', 'ViewAll' => 'Ver Tudo',
'ViewEvent' => 'View Event', 'ViewEvent' => 'View Event',
@ -675,12 +675,12 @@ $SLANG = array(
'Wide' => 'Wide', 'Wide' => 'Wide',
'X' => 'X', 'X' => 'X',
'X10' => 'X10', 'X10' => 'X10',
'X10ActivationString' => 'String de Ativação X10', 'X10ActivationString' => 'String de Ativação X10',
'X10InputAlarmString' => 'String de Entrada de alarme X10', 'X10InputAlarmString' => 'String de Entrada de alarme X10',
'X10OutputAlarmString' => 'String de Saída de Alarme X10', 'X10OutputAlarmString' => 'String de Saída de Alarme X10',
'Y' => 'Y', 'Y' => 'Y',
'Yes' => 'Sim', 'Yes' => 'Sim',
'YouNoPerms' => 'Você não tem permissões para acessar este recurso.', 'YouNoPerms' => 'Você não tem permissões para acessar este recurso.',
'Zone' => 'Zona', 'Zone' => 'Zona',
'ZoneAlarmColour' => 'Cor de Alarme (Red/Green/Blue)', 'ZoneAlarmColour' => 'Cor de Alarme (Red/Green/Blue)',
'ZoneArea' => 'Zone Area', 'ZoneArea' => 'Zone Area',
@ -701,13 +701,13 @@ $SLANG = array(
// Complex replacements with formatting and/or placements, must be passed through sprintf // Complex replacements with formatting and/or placements, must be passed through sprintf
$CLANG = array( $CLANG = array(
'CurrentLogin' => 'Login atual é \'%1$s\'', 'CurrentLogin' => 'Login atual é \'%1$s\'',
'EventCount' => '%1$s %2$s', // For example '37 Events' (from Vlang below) 'EventCount' => '%1$s %2$s', // For example '37 Events' (from Vlang below)
'LastEvents' => 'Últimos %1$s %2$s', // For example 'Last 37 Events' (from Vlang below) 'LastEvents' => 'Últimos %1$s %2$s', // For example 'Last 37 Events' (from Vlang below)
'LatestRelease' => 'A Última versão é v%1$s, você tem v%2$s.', 'LatestRelease' => 'A Última versão é v%1$s, você tem v%2$s.',
'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below) 'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below)
'MonitorFunction' => 'Monitor %1$s Funcção', 'MonitorFunction' => 'Monitor %1$s Funcção',
'RunningRecentVer' => 'Você está usando a versão mais recente do ZoneMinder, v%s.', 'RunningRecentVer' => 'Você está usando a versão mais recente do ZoneMinder, v%s.',
'VersionMismatch' => 'Version mismatch, system is version %1$s, database is %2$s.', // Added - 2011-05-25 'VersionMismatch' => 'Version mismatch, system is version %1$s, database is %2$s.', // Added - 2011-05-25
); );

View File

@ -72,92 +72,92 @@
// Simple String Replacements // Simple String Replacements
$SLANG = array( $SLANG = array(
'24BitColour' => '24 bitars färg', '24BitColour' => '24 bitars färg',
'32BitColour' => '32 bitars färg', // Added - 2011-06-15 '32BitColour' => '32 bitars färg', // Added - 2011-06-15
'8BitGrey' => '8 bit gråskala', '8BitGrey' => '8 bit gråskala',
'Action' => 'Action', 'Action' => 'Action',
'Actual' => 'Verklig', 'Actual' => 'Verklig',
'AddNewControl' => 'Ny kontroll', 'AddNewControl' => 'Ny kontroll',
'AddNewMonitor' => 'Ny bevakare', 'AddNewMonitor' => 'Ny bevakare',
'AddNewUser' => 'Ny användare', 'AddNewUser' => 'Ny användare',
'AddNewZone' => 'Ny zon', 'AddNewZone' => 'Ny zon',
'Alarm' => 'Larm', 'Alarm' => 'Larm',
'AlarmBrFrames' => 'Larm<br/>ramar', 'AlarmBrFrames' => 'Larm<br/>ramar',
'AlarmFrame' => 'Larmram', 'AlarmFrame' => 'Larmram',
'AlarmFrameCount' => 'Larmramsräknare', 'AlarmFrameCount' => 'Larmramsräknare',
'AlarmLimits' => 'Larmgränser', 'AlarmLimits' => 'Larmgränser',
'AlarmMaximumFPS' => 'Max. ramar/s för larm', 'AlarmMaximumFPS' => 'Max. ramar/s för larm',
'AlarmPx' => 'Larmpunkter', 'AlarmPx' => 'Larmpunkter',
'AlarmRGBUnset' => 'Du måste sätta en färg för RGB-larm', 'AlarmRGBUnset' => 'Du måste sätta en färg för RGB-larm',
'AlarmRefImageBlendPct'=> 'Alarm Reference Image Blend %ge', // Added - 2015-04-18 'AlarmRefImageBlendPct'=> 'Alarm Reference Image Blend %ge', // Added - 2015-04-18
'Alert' => 'Varning', 'Alert' => 'Varning',
'All' => 'Alla', 'All' => 'Alla',
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22 'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23 'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
'Apply' => 'Lägg till', 'Apply' => 'Lägg till',
'ApplyingStateChange' => 'Aktivera statusändring', 'ApplyingStateChange' => 'Aktivera statusändring',
'ArchArchived' => 'Arkivera endast', 'ArchArchived' => 'Arkivera endast',
'ArchUnarchived' => 'Endast ej arkiverade', 'ArchUnarchived' => 'Endast ej arkiverade',
'Archive' => 'Arkiv', 'Archive' => 'Arkiv',
'Archived' => 'Arkiverad', 'Archived' => 'Arkiverad',
'Area' => 'Område', 'Area' => 'Område',
'AreaUnits' => 'Område (px/%)', 'AreaUnits' => 'Område (px/%)',
'AttrAlarmFrames' => 'Larmramar', 'AttrAlarmFrames' => 'Larmramar',
'AttrArchiveStatus' => 'Arkivstatus', 'AttrArchiveStatus' => 'Arkivstatus',
'AttrAvgScore' => 'Ung. värde', 'AttrAvgScore' => 'Ung. värde',
'AttrCause' => 'Orsak', 'AttrCause' => 'Orsak',
'AttrDate' => 'Datum', 'AttrDate' => 'Datum',
'AttrDateTime' => 'Datum/Tid', 'AttrDateTime' => 'Datum/Tid',
'AttrDiskBlocks' => 'Diskblock', 'AttrDiskBlocks' => 'Diskblock',
'AttrDiskPercent' => 'Diskprocent', 'AttrDiskPercent' => 'Diskprocent',
'AttrDuration' => 'Längd', 'AttrDuration' => 'Längd',
'AttrFrames' => 'Ramar', 'AttrFrames' => 'Ramar',
'AttrId' => 'Id', 'AttrId' => 'Id',
'AttrMaxScore' => 'Max. värde', 'AttrMaxScore' => 'Max. värde',
'AttrMonitorId' => 'Bevakningsid', 'AttrMonitorId' => 'Bevakningsid',
'AttrMonitorName' => 'Bevakningsnamn', 'AttrMonitorName' => 'Bevakningsnamn',
'AttrName' => 'Namn', 'AttrName' => 'Namn',
'AttrNotes' => 'Notering', 'AttrNotes' => 'Notering',
'AttrSystemLoad' => 'Systemlast', 'AttrSystemLoad' => 'Systemlast',
'AttrTime' => 'Tid', 'AttrTime' => 'Tid',
'AttrTotalScore' => 'Totalvärde', 'AttrTotalScore' => 'Totalvärde',
'AttrWeekday' => 'Veckodag', 'AttrWeekday' => 'Veckodag',
'Auto' => 'Automatik', 'Auto' => 'Automatik',
'AutoStopTimeout' => 'Tidsutlösning för automatstop', 'AutoStopTimeout' => 'Tidsutlösning för automatstop',
'Available' => 'Available', // Added - 2009-03-31 'Available' => 'Available', // Added - 2009-03-31
'AvgBrScore' => 'Ung.<br/>träff', 'AvgBrScore' => 'Ung.<br/>träff',
'Background' => 'Bakgrund', 'Background' => 'Bakgrund',
'BackgroundFilter' => 'Kör filter i bakgrunden', 'BackgroundFilter' => 'Kör filter i bakgrunden',
'BadAlarmFrameCount' => 'Ramantalet för larm måste vara ett heltal, minsta värdet är 1', 'BadAlarmFrameCount' => 'Ramantalet för larm måste vara ett heltal, minsta värdet är 1',
'BadAlarmMaxFPS' => 'Larm för bilder/s måste vara ett positivt heltal eller ett flyttal', 'BadAlarmMaxFPS' => 'Larm för bilder/s måste vara ett positivt heltal eller ett flyttal',
'BadAnalysisFPS' => 'Analysis FPS must be a positive integer or floating point value', // Added - 2015-07-22 'BadAnalysisFPS' => 'Analysis FPS must be a positive integer or floating point value', // Added - 2015-07-22
'BadAnalysisUpdateDelay'=> 'Analysis update delay must be set to an integer of zero or more', // Added - 2015-07-23 'BadAnalysisUpdateDelay'=> 'Analysis update delay must be set to an integer of zero or more', // Added - 2015-07-23
'BadChannel' => 'Kanalen måste vara ett heltal, noll eller högre', 'BadChannel' => 'Kanalen måste vara ett heltal, noll eller högre',
'BadColours' => 'Target colour must be set to a valid value', // Added - 2011-06-15 'BadColours' => 'Target colour must be set to a valid value', // Added - 2011-06-15
'BadDevice' => 'Enheten måste sättas till ett giltigt värde', 'BadDevice' => 'Enheten måste sättas till ett giltigt värde',
'BadFPSReportInterval' => 'Buffern för ramintervallrapporten måste vara ett heltal på minst 0 eller högre', 'BadFPSReportInterval' => 'Buffern för ramintervallrapporten måste vara ett heltal på minst 0 eller högre',
'BadFormat' => 'Formatet måste vara ett heltal, noll eller högre', 'BadFormat' => 'Formatet måste vara ett heltal, noll eller högre',
'BadFrameSkip' => 'Värdet för ramöverhopp måste vara ett heltal på 0 eller högre', 'BadFrameSkip' => 'Värdet för ramöverhopp måste vara ett heltal på 0 eller högre',
'BadHeight' => 'Höjden måste sättas till ett giltigt värde', 'BadHeight' => 'Höjden måste sättas till ett giltigt värde',
'BadHost' => 'Detta fält ska innehålla en giltig ip-adress eller värdnamn, inkludera inte http://', 'BadHost' => 'Detta fält ska innehålla en giltig ip-adress eller värdnamn, inkludera inte http://',
'BadImageBufferCount' => 'Bufferstorleken för avbilden måste vara ett heltal på minst 10 eller högre', 'BadImageBufferCount' => 'Bufferstorleken för avbilden måste vara ett heltal på minst 10 eller högre',
'BadLabelX' => 'Etiketten för X koordinaten måste sättas till ett heltal, 0 eller högre', 'BadLabelX' => 'Etiketten för X koordinaten måste sättas till ett heltal, 0 eller högre',
'BadLabelY' => 'Etiketten för Y koordinaten måste sättas till ett heltal, 0 eller högre', 'BadLabelY' => 'Etiketten för Y koordinaten måste sättas till ett heltal, 0 eller högre',
'BadMaxFPS' => 'Max. ramar/s måste vara ett positivt heltal eller ett flyttal', 'BadMaxFPS' => 'Max. ramar/s måste vara ett positivt heltal eller ett flyttal',
'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more', 'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more',
'BadNameChars' => 'Namn kan endast innehålla alfanumeriska tecken, utrymmen, bindestreck och understreck', 'BadNameChars' => 'Namn kan endast innehålla alfanumeriska tecken, utrymmen, bindestreck och understreck',
'BadPalette' => 'Palette must be set to a valid value', // Added - 2009-03-31 'BadPalette' => 'Palette must be set to a valid value', // Added - 2009-03-31
'BadPath' => 'Sökvägen måste innehålla ett giltigt värde', 'BadPath' => 'Sökvägen måste innehålla ett giltigt värde',
'BadPort' => 'Porten måste innehålla ett giltigt nummer', 'BadPort' => 'Porten måste innehålla ett giltigt nummer',
'BadPostEventCount' => 'Räknaren för efterhändelsen måste vara ett heltal på 0 eller högre', 'BadPostEventCount' => 'Räknaren för efterhändelsen måste vara ett heltal på 0 eller högre',
'BadPreEventCount' => 'Räknaren för för-händelsen måste vara ett heltal på 0 eller högre, och mindre än bufferstorleken på avbilden', 'BadPreEventCount' => 'Räknaren för för-händelsen måste vara ett heltal på 0 eller högre, och mindre än bufferstorleken på avbilden',
'BadRefBlendPerc' => 'Mixprocenten för referensen måste hara ett positivt heltal', 'BadRefBlendPerc' => 'Mixprocenten för referensen måste hara ett positivt heltal',
'BadSectionLength' => 'Sektionslängden måste vara ett heltal på minst 30 eller högre', 'BadSectionLength' => 'Sektionslängden måste vara ett heltal på minst 30 eller högre',
'BadSignalCheckColour' => 'Kontrollfärgen på signalen måste vara en giltig RGB färgsträng', 'BadSignalCheckColour' => 'Kontrollfärgen på signalen måste vara en giltig RGB färgsträng',
'BadStreamReplayBuffer'=> 'Buffern för strömmande uppspelning måste vara ett heltal på 0 eller högre', 'BadStreamReplayBuffer'=> 'Buffern för strömmande uppspelning måste vara ett heltal på 0 eller högre',
'BadWarmupCount' => 'Uppvärmingsramen måste vara ett heltal på 0 eller högre', 'BadWarmupCount' => 'Uppvärmingsramen måste vara ett heltal på 0 eller högre',
'BadWebColour' => 'Webbfärgen måste vara en giltig sträng för webbfärg', 'BadWebColour' => 'Webbfärgen måste vara en giltig sträng för webbfärg',
'BadWidth' => 'Bredden måste sättas til ett giltigt värde', 'BadWidth' => 'Bredden måste sättas til ett giltigt värde',
'Bandwidth' => 'Bandbredd', 'Bandwidth' => 'Bandbredd',
'BandwidthHead' => 'Bandwidth', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing 'BandwidthHead' => 'Bandwidth', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
'BlobPx' => 'Blob Px', 'BlobPx' => 'Blob Px',
@ -168,7 +168,7 @@ $SLANG = array(
'Buffers' => 'Buffrar', 'Buffers' => 'Buffrar',
'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18 'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18
'CanAutoFocus' => 'Har autofokus', 'CanAutoFocus' => 'Har autofokus',
'CanAutoGain' => 'Har autonivå', 'CanAutoGain' => 'Har autonivå',
'CanAutoIris' => 'Har autoiris', 'CanAutoIris' => 'Har autoiris',
'CanAutoWhite' => 'Har autovitbalans.', 'CanAutoWhite' => 'Har autovitbalans.',
'CanAutoZoom' => 'Har autozoom', 'CanAutoZoom' => 'Har autozoom',
@ -176,23 +176,23 @@ $SLANG = array(
'CanFocusAbs' => 'Har absolut fokus', 'CanFocusAbs' => 'Har absolut fokus',
'CanFocusCon' => 'Har kontinuerlig fokus', 'CanFocusCon' => 'Har kontinuerlig fokus',
'CanFocusRel' => 'Har relativ fokus', 'CanFocusRel' => 'Har relativ fokus',
'CanGain' => 'Har nivå', 'CanGain' => 'Har nivå',
'CanGainAbs' => 'Har absolut nivå', 'CanGainAbs' => 'Har absolut nivå',
'CanGainCon' => 'Har kontinuerlig nivå', 'CanGainCon' => 'Har kontinuerlig nivå',
'CanGainRel' => 'Har relativ nivå', 'CanGainRel' => 'Har relativ nivå',
'CanIris' => 'Har iris', 'CanIris' => 'Har iris',
'CanIrisAbs' => 'Har absolut iris', 'CanIrisAbs' => 'Har absolut iris',
'CanIrisCon' => 'Har kontinuerlig iris', 'CanIrisCon' => 'Har kontinuerlig iris',
'CanIrisRel' => 'Har relativ iris', 'CanIrisRel' => 'Har relativ iris',
'CanMove' => 'Har förflyttning', 'CanMove' => 'Har förflyttning',
'CanMoveAbs' => 'Har absolut förflyttning', 'CanMoveAbs' => 'Har absolut förflyttning',
'CanMoveCon' => 'Har kontinuerlig förflyttning', 'CanMoveCon' => 'Har kontinuerlig förflyttning',
'CanMoveDiag' => 'Har diagonal förflyttning', 'CanMoveDiag' => 'Har diagonal förflyttning',
'CanMoveMap' => 'Har mappad förflyttning', 'CanMoveMap' => 'Har mappad förflyttning',
'CanMoveRel' => 'Har relativ förflyttning', 'CanMoveRel' => 'Har relativ förflyttning',
'CanPan' => 'Har panorering', 'CanPan' => 'Har panorering',
'CanReset' => 'Har återställning', 'CanReset' => 'Har återställning',
'CanSetPresets' => 'Har förinställningar', 'CanSetPresets' => 'Har förinställningar',
'CanSleep' => 'Kan vila', 'CanSleep' => 'Kan vila',
'CanTilt' => 'Kan tilta', 'CanTilt' => 'Kan tilta',
'CanWake' => 'Kan vakna', 'CanWake' => 'Kan vakna',
@ -205,39 +205,39 @@ $SLANG = array(
'CanZoomAbs' => 'Kan zooma absolut', 'CanZoomAbs' => 'Kan zooma absolut',
'CanZoomCon' => 'Kan zooma kontinuerligt', 'CanZoomCon' => 'Kan zooma kontinuerligt',
'CanZoomRel' => 'Kan zooma realativt', 'CanZoomRel' => 'Kan zooma realativt',
'Cancel' => 'Ångra', 'Cancel' => 'Ångra',
'CancelForcedAlarm' => 'Ångra tvingande larm', 'CancelForcedAlarm' => 'Ångra tvingande larm',
'CaptureHeight' => 'Fångsthöjd', 'CaptureHeight' => 'Fångsthöjd',
'CaptureMethod' => 'Capture Method', // Added - 2009-02-08 'CaptureMethod' => 'Capture Method', // Added - 2009-02-08
'CapturePalette' => 'Fångstpalett', 'CapturePalette' => 'Fångstpalett',
'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18 'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18
'CaptureWidth' => 'Fångstbredd', 'CaptureWidth' => 'Fångstbredd',
'Cause' => 'Orsak', 'Cause' => 'Orsak',
'CheckMethod' => 'Larmkontrollmetod', 'CheckMethod' => 'Larmkontrollmetod',
'ChooseDetectedCamera' => 'Choose Detected Camera', // Added - 2009-03-31 'ChooseDetectedCamera' => 'Choose Detected Camera', // Added - 2009-03-31
'ChooseFilter' => 'Välj filter', 'ChooseFilter' => 'Välj filter',
'ChooseLogFormat' => 'Choose a log format', // Added - 2011-06-17 'ChooseLogFormat' => 'Choose a log format', // Added - 2011-06-17
'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17 'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17
'ChoosePreset' => 'Välj standard', 'ChoosePreset' => 'Välj standard',
'Clear' => 'Clear', // Added - 2011-06-16 'Clear' => 'Clear', // Added - 2011-06-16
'Close' => 'Stäng', 'Close' => 'Stäng',
'Colour' => 'Färg', 'Colour' => 'Färg',
'Command' => 'Kommando', 'Command' => 'Kommando',
'Component' => 'Component', // Added - 2011-06-16 'Component' => 'Component', // Added - 2011-06-16
'Config' => 'Konfigurera', 'Config' => 'Konfigurera',
'ConfiguredFor' => 'Konfigurerad för', 'ConfiguredFor' => 'Konfigurerad för',
'ConfirmDeleteEvents' => 'Är du säker på att du vill ta bort dom valda händelserna?', 'ConfirmDeleteEvents' => 'Är du säker på att du vill ta bort dom valda händelserna?',
'ConfirmPassword' => 'Bekräfta lösenord', 'ConfirmPassword' => 'Bekräfta lösenord',
'ConjAnd' => 'och', 'ConjAnd' => 'och',
'ConjOr' => 'eller', 'ConjOr' => 'eller',
'Console' => 'Konsoll', 'Console' => 'Konsoll',
'ContactAdmin' => 'Kontakta din administratör för detaljer.', 'ContactAdmin' => 'Kontakta din administratör för detaljer.',
'Continue' => 'Fortsätt', 'Continue' => 'Fortsätt',
'Contrast' => 'Kontrast', 'Contrast' => 'Kontrast',
'Control' => 'Kontroll', 'Control' => 'Kontroll',
'ControlAddress' => 'Kontrolladress', 'ControlAddress' => 'Kontrolladress',
'ControlCap' => 'Kontrollförmåga', 'ControlCap' => 'Kontrollförmåga',
'ControlCaps' => 'Kontrollförmågor', 'ControlCaps' => 'Kontrollförmågor',
'ControlDevice' => 'Kontrollenhet', 'ControlDevice' => 'Kontrollenhet',
'ControlType' => 'Kontrolltyp', 'ControlType' => 'Kontrolltyp',
'Controllable' => 'Kontrollerbar', 'Controllable' => 'Kontrollerbar',
@ -253,8 +253,8 @@ $SLANG = array(
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18 'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18 'Delay' => 'Delay', // Added - 2015-04-18
'Delete' => 'Radera', 'Delete' => 'Radera',
'DeleteAndNext' => 'Radera &amp; Nästa', 'DeleteAndNext' => 'Radera &amp; Nästa',
'DeleteAndPrev' => 'Radera &amp; Föreg.', 'DeleteAndPrev' => 'Radera &amp; Föreg.',
'DeleteSavedFilter' => 'Radera sparade filter', 'DeleteSavedFilter' => 'Radera sparade filter',
'Description' => 'Beskrivning', 'Description' => 'Beskrivning',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31 'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
@ -263,7 +263,7 @@ $SLANG = array(
'DeviceChannel' => 'Enhetskanal', 'DeviceChannel' => 'Enhetskanal',
'DeviceFormat' => 'Enhetsformat', 'DeviceFormat' => 'Enhetsformat',
'DeviceNumber' => 'Enhetsnummer', 'DeviceNumber' => 'Enhetsnummer',
'DevicePath' => 'Enhetssökväg', 'DevicePath' => 'Enhetssökväg',
'Devices' => 'Enheter', 'Devices' => 'Enheter',
'Dimensions' => 'Dimensioner', 'Dimensions' => 'Dimensioner',
'DisableAlarms' => 'Avaktivera larm', 'DisableAlarms' => 'Avaktivera larm',
@ -271,39 +271,39 @@ $SLANG = array(
'Display' => 'Display', // Added - 2011-01-30 'Display' => 'Display', // Added - 2011-01-30
'Displaying' => 'Displaying', // Added - 2011-06-16 'Displaying' => 'Displaying', // Added - 2011-06-16
'DoNativeMotionDetection'=> 'Do Native Motion Detection', 'DoNativeMotionDetection'=> 'Do Native Motion Detection',
'Donate' => 'Var vänlig och donera', 'Donate' => 'Var vänlig och donera',
'DonateAlready' => 'Nej, Jag har redan donerat', 'DonateAlready' => 'Nej, Jag har redan donerat',
'DonateEnticement' => 'Du har kört ZoneMinder ett tag nu och förhoppningsvis har du sett att det fungerar bra hemma eller på ditt företag. Även om ZoneMinder är, och kommer att vara, fri programvara och öppen kallkod, så kostar det pengar att utveckla och underhålla. Om du vill hjälpa till med framtida utveckling och nya funktioner så var vanlig och bidrag med en slant. Bidragen är naturligtvis en option men mycket uppskattade och du kan bidra med precis hur mycket du vill.<br><br>Om du vill ge ett bidrag väljer du nedan eller surfar till http://www.zoneminder.com/donate.html.<br><br>Tack för att du använder ZoneMinder, glöm inte att besöka forumen på ZoneMinder.com för support och förslag om hur du får din ZoneMinder att fungera lite bättre.', 'DonateEnticement' => 'Du har kört ZoneMinder ett tag nu och förhoppningsvis har du sett att det fungerar bra hemma eller på ditt företag. Även om ZoneMinder är, och kommer att vara, fri programvara och öppen kallkod, så kostar det pengar att utveckla och underhålla. Om du vill hjälpa till med framtida utveckling och nya funktioner så var vanlig och bidrag med en slant. Bidragen är naturligtvis en option men mycket uppskattade och du kan bidra med precis hur mycket du vill.<br><br>Om du vill ge ett bidrag väljer du nedan eller surfar till http://www.zoneminder.com/donate.html.<br><br>Tack för att du använder ZoneMinder, glöm inte att besöka forumen på ZoneMinder.com för support och förslag om hur du får din ZoneMinder att fungera lite bättre.',
'DonateRemindDay' => 'Inte än, påminn om 1 dag', 'DonateRemindDay' => 'Inte än, påminn om 1 dag',
'DonateRemindHour' => 'Inte än, påminn om en 1 timme', 'DonateRemindHour' => 'Inte än, påminn om en 1 timme',
'DonateRemindMonth' => 'Inte än, påminn om 1 månad', 'DonateRemindMonth' => 'Inte än, påminn om 1 månad',
'DonateRemindNever' => 'Nej, Jag vill inte donera, påminn mig inte mer', 'DonateRemindNever' => 'Nej, Jag vill inte donera, påminn mig inte mer',
'DonateRemindWeek' => 'Inte än, påminn om 1 vecka', 'DonateRemindWeek' => 'Inte än, påminn om 1 vecka',
'DonateYes' => 'Ja, jag vill gärna donera nu', 'DonateYes' => 'Ja, jag vill gärna donera nu',
'Download' => 'Ladda ner', 'Download' => 'Ladda ner',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31 'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
'Duration' => 'Längd', 'Duration' => 'Längd',
'Edit' => 'Redigera', 'Edit' => 'Redigera',
'Email' => 'E-post', 'Email' => 'E-post',
'EnableAlarms' => 'Aktivera larm', 'EnableAlarms' => 'Aktivera larm',
'Enabled' => 'Aktiverad', 'Enabled' => 'Aktiverad',
'EnterNewFilterName' => 'Mata in nytt filternamn', 'EnterNewFilterName' => 'Mata in nytt filternamn',
'Error' => 'Fel', 'Error' => 'Fel',
'ErrorBrackets' => 'Fel, kontrollera att du har samma antal vänster som höger-hakar', 'ErrorBrackets' => 'Fel, kontrollera att du har samma antal vänster som höger-hakar',
'ErrorValidValue' => 'Fel, kontrollera att alla parametrar har giltligt värde', 'ErrorValidValue' => 'Fel, kontrollera att alla parametrar har giltligt värde',
'Etc' => 'etc', 'Etc' => 'etc',
'Event' => 'Händelse', 'Event' => 'Händelse',
'EventFilter' => 'Händelsefilter', 'EventFilter' => 'Händelsefilter',
'EventId' => 'Händelse nr', 'EventId' => 'Händelse nr',
'EventName' => 'Händelsenamn', 'EventName' => 'Händelsenamn',
'EventPrefix' => 'Händelseprefix', 'EventPrefix' => 'Händelseprefix',
'Events' => 'Händelser', 'Events' => 'Händelser',
'Exclude' => 'Exkludera', 'Exclude' => 'Exkludera',
'Execute' => 'Utför', 'Execute' => 'Utför',
'Export' => 'Exportera', 'Export' => 'Exportera',
'ExportDetails' => 'Exportera händelsedetaljer', 'ExportDetails' => 'Exportera händelsedetaljer',
'ExportFailed' => 'Exporten misslyckades', 'ExportFailed' => 'Exporten misslyckades',
'ExportFormat' => 'Filformat för exporter', 'ExportFormat' => 'Filformat för exporter',
'ExportFormatTar' => 'Tar', 'ExportFormatTar' => 'Tar',
'ExportFormatZip' => 'Zip', 'ExportFormatZip' => 'Zip',
'ExportFrames' => 'Exportera ramdetaljer', 'ExportFrames' => 'Exportera ramdetaljer',
@ -323,20 +323,20 @@ $SLANG = array(
'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08 'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08
'File' => 'Fil', 'File' => 'Fil',
'Filter' => 'Filter', // Added - 2015-04-18 'Filter' => 'Filter', // Added - 2015-04-18
'FilterArchiveEvents' => 'Arkivera alla träffar', 'FilterArchiveEvents' => 'Arkivera alla träffar',
'FilterDeleteEvents' => 'Radera alla träffar', 'FilterDeleteEvents' => 'Radera alla träffar',
'FilterEmailEvents' => 'Skicka e-post med detaljer om alla träffar', 'FilterEmailEvents' => 'Skicka e-post med detaljer om alla träffar',
'FilterExecuteEvents' => 'Utför kommando på alla träffar', 'FilterExecuteEvents' => 'Utför kommando på alla träffar',
'FilterLog' => 'Filter log', // Added - 2015-04-18 'FilterLog' => 'Filter log', // Added - 2015-04-18
'FilterMessageEvents' => 'Meddela detaljer om alla träffar', 'FilterMessageEvents' => 'Meddela detaljer om alla träffar',
'FilterPx' => 'Filter Px', 'FilterPx' => 'Filter Px',
'FilterUnset' => 'Du måste specificera filtrets bredd och höjd', 'FilterUnset' => 'Du måste specificera filtrets bredd och höjd',
'FilterUploadEvents' => 'Ladda upp alla träffar', 'FilterUploadEvents' => 'Ladda upp alla träffar',
'FilterVideoEvents' => 'Skapa video för alla träffar', 'FilterVideoEvents' => 'Skapa video för alla träffar',
'Filters' => 'Filter', 'Filters' => 'Filter',
'First' => 'Först', 'First' => 'Först',
'FlippedHori' => 'Vänd horisontellt', 'FlippedHori' => 'Vänd horisontellt',
'FlippedVert' => 'Vänd vertikalt', 'FlippedVert' => 'Vänd vertikalt',
'FnMocord' => 'Mocord', // Added 2013.08.16. 'FnMocord' => 'Mocord', // Added 2013.08.16.
'FnModect' => 'Modect', // Added 2013.08.16. 'FnModect' => 'Modect', // Added 2013.08.16.
'FnMonitor' => 'Monitor', // Added 2013.08.16. 'FnMonitor' => 'Monitor', // Added 2013.08.16.
@ -349,31 +349,31 @@ $SLANG = array(
'Frame' => 'Ram', 'Frame' => 'Ram',
'FrameId' => 'Ram id', 'FrameId' => 'Ram id',
'FrameRate' => 'Ram hastighet', 'FrameRate' => 'Ram hastighet',
'FrameSkip' => 'Hoppa över ram', 'FrameSkip' => 'Hoppa över ram',
'Frames' => 'Ramar', 'Frames' => 'Ramar',
'Func' => 'Funk', 'Func' => 'Funk',
'Function' => 'Funktion', 'Function' => 'Funktion',
'Gain' => 'Nivå', 'Gain' => 'Nivå',
'General' => 'Generell', 'General' => 'Generell',
'GenerateVideo' => 'Skapa video', 'GenerateVideo' => 'Skapa video',
'GeneratingVideo' => 'Skapar video', 'GeneratingVideo' => 'Skapar video',
'GoToZoneMinder' => 'Gå till ZoneMinder.com', 'GoToZoneMinder' => 'Gå till ZoneMinder.com',
'Grey' => 'Grå', 'Grey' => 'Grå',
'Group' => 'Grupp', 'Group' => 'Grupp',
'Groups' => 'Grupper', 'Groups' => 'Grupper',
'HasFocusSpeed' => 'Har focushastighet', 'HasFocusSpeed' => 'Har focushastighet',
'HasGainSpeed' => 'Har nivåhastighet', 'HasGainSpeed' => 'Har nivåhastighet',
'HasHomePreset' => 'Har normalinställning', 'HasHomePreset' => 'Har normalinställning',
'HasIrisSpeed' => 'Har irishastighet', 'HasIrisSpeed' => 'Har irishastighet',
'HasPanSpeed' => 'Har panoramahastighet', 'HasPanSpeed' => 'Har panoramahastighet',
'HasPresets' => 'Har förinställningar', 'HasPresets' => 'Har förinställningar',
'HasTiltSpeed' => 'Har tilthastighet', 'HasTiltSpeed' => 'Har tilthastighet',
'HasTurboPan' => 'Har turbopanorering', 'HasTurboPan' => 'Har turbopanorering',
'HasTurboTilt' => 'Har turbotilt', 'HasTurboTilt' => 'Har turbotilt',
'HasWhiteSpeed' => 'Har vitbalanshastighet', 'HasWhiteSpeed' => 'Har vitbalanshastighet',
'HasZoomSpeed' => 'Har Zoomhastighet', 'HasZoomSpeed' => 'Har Zoomhastighet',
'High' => 'Hög', 'High' => 'Hög',
'HighBW' => 'Hög bandbredd', 'HighBW' => 'Hög bandbredd',
'Home' => 'Hem', 'Home' => 'Hem',
'Hour' => 'Timme', 'Hour' => 'Timme',
'Hue' => 'Hue', 'Hue' => 'Hue',
@ -387,17 +387,17 @@ $SLANG = array(
'Include' => 'Inkludera', 'Include' => 'Inkludera',
'Inverted' => 'Inverterad', 'Inverted' => 'Inverterad',
'Iris' => 'Iris', 'Iris' => 'Iris',
'KeyString' => 'Nyckelsträng', 'KeyString' => 'Nyckelsträng',
'Label' => 'Etikett', 'Label' => 'Etikett',
'Language' => 'Språk', 'Language' => 'Språk',
'Last' => 'Sist', 'Last' => 'Sist',
'Layout' => 'Layout', // Added - 2009-02-08 'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16 'Level' => 'Level', // Added - 2011-06-16
'Libvlc' => 'Libvlc', 'Libvlc' => 'Libvlc',
'LimitResultsPost' => 'resultaten;', // This is used at the end of the phrase 'Limit to first N results only' 'LimitResultsPost' => 'resultaten;', // This is used at the end of the phrase 'Limit to first N results only'
'LimitResultsPre' => 'Begränsa till första', // This is used at the beginning of the phrase 'Limit to first N results only' 'LimitResultsPre' => 'Begränsa till första', // This is used at the beginning of the phrase 'Limit to first N results only'
'Line' => 'Line', // Added - 2011-06-16 'Line' => 'Line', // Added - 2011-06-16
'LinkedMonitors' => 'Länkade övervakare', 'LinkedMonitors' => 'Länkade övervakare',
'List' => 'Lista', 'List' => 'Lista',
'Load' => 'Belastning', 'Load' => 'Belastning',
'Local' => 'Lokal', 'Local' => 'Lokal',
@ -408,8 +408,8 @@ $SLANG = array(
'Login' => 'Logga in', 'Login' => 'Logga in',
'Logout' => 'Logga ut', 'Logout' => 'Logga ut',
'Logs' => 'Logs', // Added - 2011-06-17 'Logs' => 'Logs', // Added - 2011-06-17
'Low' => 'Låg', 'Low' => 'Låg',
'LowBW' => 'Låg bandbredd', 'LowBW' => 'Låg bandbredd',
'Main' => 'Huvudmeny', 'Main' => 'Huvudmeny',
'Man' => 'Man', 'Man' => 'Man',
'Manual' => 'Manuell', 'Manual' => 'Manuell',
@ -417,75 +417,75 @@ $SLANG = array(
'Max' => 'Max', 'Max' => 'Max',
'MaxBandwidth' => 'Max bandbredd', 'MaxBandwidth' => 'Max bandbredd',
'MaxBrScore' => 'Max.<br/>Score', 'MaxBrScore' => 'Max.<br/>Score',
'MaxFocusRange' => 'Max fokusområde', 'MaxFocusRange' => 'Max fokusområde',
'MaxFocusSpeed' => 'Max fokushastighet', 'MaxFocusSpeed' => 'Max fokushastighet',
'MaxFocusStep' => 'Max fokussteg', 'MaxFocusStep' => 'Max fokussteg',
'MaxGainRange' => 'Max nivåområde', 'MaxGainRange' => 'Max nivåområde',
'MaxGainSpeed' => 'Max nivåhastighet', 'MaxGainSpeed' => 'Max nivåhastighet',
'MaxGainStep' => 'Max nivåsteg', 'MaxGainStep' => 'Max nivåsteg',
'MaxIrisRange' => 'Max irsiområde', 'MaxIrisRange' => 'Max irsiområde',
'MaxIrisSpeed' => 'Max irishastighet', 'MaxIrisSpeed' => 'Max irishastighet',
'MaxIrisStep' => 'Max irissteg', 'MaxIrisStep' => 'Max irissteg',
'MaxPanRange' => 'Max panoramaområde', 'MaxPanRange' => 'Max panoramaområde',
'MaxPanSpeed' => 'Max panoramahastighet', 'MaxPanSpeed' => 'Max panoramahastighet',
'MaxPanStep' => 'Max panoramasteg', 'MaxPanStep' => 'Max panoramasteg',
'MaxTiltRange' => 'Max tiltområde', 'MaxTiltRange' => 'Max tiltområde',
'MaxTiltSpeed' => 'Max tilthastighet', 'MaxTiltSpeed' => 'Max tilthastighet',
'MaxTiltStep' => 'Max tiltsteg', 'MaxTiltStep' => 'Max tiltsteg',
'MaxWhiteRange' => 'Max vitbalansområde', 'MaxWhiteRange' => 'Max vitbalansområde',
'MaxWhiteSpeed' => 'Max vitbalanshastighet', 'MaxWhiteSpeed' => 'Max vitbalanshastighet',
'MaxWhiteStep' => 'Max vitbalanssteg', 'MaxWhiteStep' => 'Max vitbalanssteg',
'MaxZoomRange' => 'Max zoomområde', 'MaxZoomRange' => 'Max zoomområde',
'MaxZoomSpeed' => 'Max zoomhastighet', 'MaxZoomSpeed' => 'Max zoomhastighet',
'MaxZoomStep' => 'Max zoomsteg', 'MaxZoomStep' => 'Max zoomsteg',
'MaximumFPS' => 'Max ramar/s', 'MaximumFPS' => 'Max ramar/s',
'Medium' => 'Mellan', 'Medium' => 'Mellan',
'MediumBW' => 'Mellan bandbredd', 'MediumBW' => 'Mellan bandbredd',
'Message' => 'Message', // Added - 2011-06-16 'Message' => 'Message', // Added - 2011-06-16
'MinAlarmAreaLtMax' => 'Minsta larmarean skall vara mindre än största', 'MinAlarmAreaLtMax' => 'Minsta larmarean skall vara mindre än största',
'MinAlarmAreaUnset' => 'Du måste ange minsta antal larmbildpunkter', 'MinAlarmAreaUnset' => 'Du måste ange minsta antal larmbildpunkter',
'MinBlobAreaLtMax' => 'Minsta blobarean skall vara mindre än högsta', 'MinBlobAreaLtMax' => 'Minsta blobarean skall vara mindre än högsta',
'MinBlobAreaUnset' => 'Du måste ange minsta antalet blobpixlar', 'MinBlobAreaUnset' => 'Du måste ange minsta antalet blobpixlar',
'MinBlobLtMinFilter' => 'Minsta blobarean skall vara mindre än eller lika med minsta filterarean', 'MinBlobLtMinFilter' => 'Minsta blobarean skall vara mindre än eller lika med minsta filterarean',
'MinBlobsLtMax' => 'Minsta antalet blobbar skall vara mindre än största', 'MinBlobsLtMax' => 'Minsta antalet blobbar skall vara mindre än största',
'MinBlobsUnset' => 'Du måste ange minsta antalet blobbar', 'MinBlobsUnset' => 'Du måste ange minsta antalet blobbar',
'MinFilterAreaLtMax' => 'Minsta filterarean skall vara mindre än högsta', 'MinFilterAreaLtMax' => 'Minsta filterarean skall vara mindre än högsta',
'MinFilterAreaUnset' => 'Du måste ange minsta antal filterbildpunkter', 'MinFilterAreaUnset' => 'Du måste ange minsta antal filterbildpunkter',
'MinFilterLtMinAlarm' => 'Minsta filterarean skall vara mindre än eller lika med minsta larmarean', 'MinFilterLtMinAlarm' => 'Minsta filterarean skall vara mindre än eller lika med minsta larmarean',
'MinFocusRange' => 'Min fokusområde', 'MinFocusRange' => 'Min fokusområde',
'MinFocusSpeed' => 'Min fokushastighet', 'MinFocusSpeed' => 'Min fokushastighet',
'MinFocusStep' => 'Min fokussteg', 'MinFocusStep' => 'Min fokussteg',
'MinGainRange' => 'Min nivåområde', 'MinGainRange' => 'Min nivåområde',
'MinGainSpeed' => 'Min nivåhastighet', 'MinGainSpeed' => 'Min nivåhastighet',
'MinGainStep' => 'Min nivåsteg', 'MinGainStep' => 'Min nivåsteg',
'MinIrisRange' => 'Min irisområde', 'MinIrisRange' => 'Min irisområde',
'MinIrisSpeed' => 'Min irishastighet', 'MinIrisSpeed' => 'Min irishastighet',
'MinIrisStep' => 'Min irissteg', 'MinIrisStep' => 'Min irissteg',
'MinPanRange' => 'Min panoramaområde', 'MinPanRange' => 'Min panoramaområde',
'MinPanSpeed' => 'Min panoramahastighet', 'MinPanSpeed' => 'Min panoramahastighet',
'MinPanStep' => 'Min panoramasteg', 'MinPanStep' => 'Min panoramasteg',
'MinPixelThresLtMax' => 'Minsta tröskelvärde för bildpunkter ska vara mindre än högsta', 'MinPixelThresLtMax' => 'Minsta tröskelvärde för bildpunkter ska vara mindre än högsta',
'MinPixelThresUnset' => 'Du måste ange minsta tröskelvärde för bildpunkter', 'MinPixelThresUnset' => 'Du måste ange minsta tröskelvärde för bildpunkter',
'MinTiltRange' => 'Min tiltområde', 'MinTiltRange' => 'Min tiltområde',
'MinTiltSpeed' => 'Min tilthastighet', 'MinTiltSpeed' => 'Min tilthastighet',
'MinTiltStep' => 'Min tiltsteg', 'MinTiltStep' => 'Min tiltsteg',
'MinWhiteRange' => 'Min vitbalansområde', 'MinWhiteRange' => 'Min vitbalansområde',
'MinWhiteSpeed' => 'Min vitbalanshastighet', 'MinWhiteSpeed' => 'Min vitbalanshastighet',
'MinWhiteStep' => 'Min vitbalanssteg', 'MinWhiteStep' => 'Min vitbalanssteg',
'MinZoomRange' => 'Min zoomområde', 'MinZoomRange' => 'Min zoomområde',
'MinZoomSpeed' => 'Min zoomhastighet', 'MinZoomSpeed' => 'Min zoomhastighet',
'MinZoomStep' => 'Min zoomsteg', 'MinZoomStep' => 'Min zoomsteg',
'Misc' => 'Övrigt', 'Misc' => 'Övrigt',
'Mode' => 'Mode', // Added - 2015-04-18 'Mode' => 'Mode', // Added - 2015-04-18
'Monitor' => 'Bevakning', 'Monitor' => 'Bevakning',
'MonitorIds' => 'Bevakningsnr', 'MonitorIds' => 'Bevakningsnr',
'MonitorPreset' => 'Förinställd bevakning', 'MonitorPreset' => 'Förinställd bevakning',
'MonitorPresetIntro' => 'Välj en förinställning från listan.<br><br>Var medveten om att detta kan skriva över inställningar du redan gjort för denna bevakare.<br><br>', 'MonitorPresetIntro' => 'Välj en förinställning från listan.<br><br>Var medveten om att detta kan skriva över inställningar du redan gjort för denna bevakare.<br><br>',
'MonitorProbe' => 'Monitor Probe', // Added - 2009-03-31 '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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // 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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2009-03-31
'Monitors' => 'Bevakare', 'Monitors' => 'Bevakare',
'Montage' => 'Montera', 'Montage' => 'Montera',
'Month' => 'Månad', 'Month' => 'Månad',
'More' => 'More', // Added - 2011-06-16 'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip', 'MotionFrameSkip' => 'Motion Frame Skip',
'Move' => 'Flytta', 'Move' => 'Flytta',
@ -494,65 +494,65 @@ $SLANG = array(
'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15. 'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15.
'Mtg4widgrd' => '4-wide grid', // Added 2013.08.15. 'Mtg4widgrd' => '4-wide grid', // Added 2013.08.15.
'MtgDefault' => 'Default', // Added 2013.08.15. 'MtgDefault' => 'Default', // Added 2013.08.15.
'MustBeGe' => 'måste vara större än eller lika med', 'MustBeGe' => 'måste vara större än eller lika med',
'MustBeLe' => 'måste vara mindre än eller lika med', 'MustBeLe' => 'måste vara mindre än eller lika med',
'MustConfirmPassword' => 'Du måste bekräfta lösenordet', 'MustConfirmPassword' => 'Du måste bekräfta lösenordet',
'MustSupplyPassword' => 'Du måste ange ett lösenord', 'MustSupplyPassword' => 'Du måste ange ett lösenord',
'MustSupplyUsername' => 'Du måste ange ett användarnamn', 'MustSupplyUsername' => 'Du måste ange ett användarnamn',
'Name' => 'Namn', 'Name' => 'Namn',
'Near' => 'Nära', 'Near' => 'Nära',
'Network' => 'Nätverk', 'Network' => 'Nätverk',
'New' => 'Ny', 'New' => 'Ny',
'NewGroup' => 'Ny grupp', 'NewGroup' => 'Ny grupp',
'NewLabel' => 'Ny etikett', 'NewLabel' => 'Ny etikett',
'NewPassword' => 'Nytt lösenord', 'NewPassword' => 'Nytt lösenord',
'NewState' => 'Nytt läge', 'NewState' => 'Nytt läge',
'NewUser' => 'Ny användare', 'NewUser' => 'Ny användare',
'Next' => 'Nästa', 'Next' => 'Nästa',
'No' => 'Nej', 'No' => 'Nej',
'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31 'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31
'NoFramesRecorded' => 'Det finns inga ramar inspelade för denna händelse', 'NoFramesRecorded' => 'Det finns inga ramar inspelade för denna händelse',
'NoGroup' => 'Ingen grupp', 'NoGroup' => 'Ingen grupp',
'NoSavedFilters' => 'Inga sparade filter', 'NoSavedFilters' => 'Inga sparade filter',
'NoStatisticsRecorded' => 'Det finns ingen statistik inspelad för denna händelse/ram', 'NoStatisticsRecorded' => 'Det finns ingen statistik inspelad för denna händelse/ram',
'None' => 'Ingen', 'None' => 'Ingen',
'NoneAvailable' => 'Ingen tillgänglig', 'NoneAvailable' => 'Ingen tillgänglig',
'Normal' => 'Normal', 'Normal' => 'Normal',
'Notes' => 'Not.', 'Notes' => 'Not.',
'NumPresets' => 'Antal förinställningar', 'NumPresets' => 'Antal förinställningar',
'Off' => 'Av', 'Off' => 'Av',
'On' => 'På', 'On' => 'På',
'OnvifCredentialsIntro'=> 'Please supply user name and password for the selected camera.<br/>If no user has been created for the camera then the user given here will be created with the given password.<br/><br/>', // Added - 2015-04-18 'OnvifCredentialsIntro'=> 'Please supply user name and password for the selected camera.<br/>If no user has been created for the camera then the user given here will be created with the given password.<br/><br/>', // Added - 2015-04-18
'OnvifProbe' => 'ONVIF', // 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.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18 'OnvifProbeIntro' => 'The list below shows detected ONVIF cameras and whether they are already being used or available for selection.<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18
'OpEq' => 'lika med', 'OpEq' => 'lika med',
'OpGt' => 'större än', 'OpGt' => 'större än',
'OpGtEq' => 'större än eller lika med', 'OpGtEq' => 'större än eller lika med',
'OpIn' => 'in set', 'OpIn' => 'in set',
'OpLt' => 'mindre än', 'OpLt' => 'mindre än',
'OpLtEq' => 'mindre än eller lika med', 'OpLtEq' => 'mindre än eller lika med',
'OpMatches' => 'matchar', 'OpMatches' => 'matchar',
'OpNe' => 'inte lika med', 'OpNe' => 'inte lika med',
'OpNotIn' => 'inte i set', 'OpNotIn' => 'inte i set',
'OpNotMatches' => 'matchar inte', 'OpNotMatches' => 'matchar inte',
'Open' => 'Öppna', 'Open' => 'Öppna',
'OptionHelp' => 'Optionhjälp', 'OptionHelp' => 'Optionhjälp',
'OptionRestartWarning' => 'Dessa ändringar kommer inte att vara implementerade\nnär systemet körs. När du är klar starta om\n ZoneMinder.', 'OptionRestartWarning' => 'Dessa ändringar kommer inte att vara implementerade\nnär systemet körs. När du är klar starta om\n ZoneMinder.',
'Options' => 'Alternativ', 'Options' => 'Alternativ',
'OrEnterNewName' => 'eller skriv in nytt namn', 'OrEnterNewName' => 'eller skriv in nytt namn',
'Order' => 'Sortera', 'Order' => 'Sortera',
'Orientation' => 'Orientation', 'Orientation' => 'Orientation',
'Out' => 'Ut', 'Out' => 'Ut',
'OverwriteExisting' => 'Skriv över', 'OverwriteExisting' => 'Skriv över',
'Paged' => 'Paged', 'Paged' => 'Paged',
'Pan' => 'Panorera', 'Pan' => 'Panorera',
'PanLeft' => 'Panorera vänster', 'PanLeft' => 'Panorera vänster',
'PanRight' => 'Panorera höger', 'PanRight' => 'Panorera höger',
'PanTilt' => 'Pan/Tilt', 'PanTilt' => 'Pan/Tilt',
'Parameter' => 'Parameter', 'Parameter' => 'Parameter',
'Password' => 'Lösenord', 'Password' => 'Lösenord',
'PasswordsDifferent' => 'Lösenorden skiljer sig åt', 'PasswordsDifferent' => 'Lösenorden skiljer sig åt',
'Paths' => 'Sökvägar', 'Paths' => 'Sökvägar',
'Pause' => 'Paus', 'Pause' => 'Paus',
'Phone' => 'Mobil', 'Phone' => 'Mobil',
'PhoneBW' => 'Mobil bandbredd', 'PhoneBW' => 'Mobil bandbredd',
@ -561,15 +561,15 @@ $SLANG = array(
'Pixels' => 'bildpunkter', 'Pixels' => 'bildpunkter',
'Play' => 'Spela', 'Play' => 'Spela',
'PlayAll' => 'Visa alla', 'PlayAll' => 'Visa alla',
'PleaseWait' => 'Vänta...', 'PleaseWait' => 'Vänta...',
'Plugins' => 'Plugins', 'Plugins' => 'Plugins',
'Point' => 'Punkt', 'Point' => 'Punkt',
'PostEventImageBuffer' => 'Post Event Image Count', 'PostEventImageBuffer' => 'Post Event Image Count',
'PreEventImageBuffer' => 'Pre Event Image Count', 'PreEventImageBuffer' => 'Pre Event Image Count',
'PreserveAspect' => 'Bevara lägesförhållande', 'PreserveAspect' => 'Bevara lägesförhållande',
'Preset' => 'Förinställning', 'Preset' => 'Förinställning',
'Presets' => 'Förinställningar', 'Presets' => 'Förinställningar',
'Prev' => 'Föreg.', 'Prev' => 'Föreg.',
'Probe' => 'Probe', // Added - 2009-03-31 'Probe' => 'Probe', // Added - 2009-03-31
'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18
'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .<br/><br/>Select the desired entry from the list below.<br/><br/>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.<br/><br/>', // Added - 2015-04-18
@ -580,51 +580,51 @@ $SLANG = array(
'Record' => 'Spela in', 'Record' => 'Spela in',
'RefImageBlendPct' => 'Reference Image Blend %ge', 'RefImageBlendPct' => 'Reference Image Blend %ge',
'Refresh' => 'Uppdatera', 'Refresh' => 'Uppdatera',
'Remote' => 'Fjärr', 'Remote' => 'Fjärr',
'RemoteHostName' => 'Fjärrnamn', 'RemoteHostName' => 'Fjärrnamn',
'RemoteHostPath' => 'Fjärrsökväg', 'RemoteHostPath' => 'Fjärrsökväg',
'RemoteHostPort' => 'Fjärrport', 'RemoteHostPort' => 'Fjärrport',
'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08 'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08
'RemoteImageColours' => 'Fjärrbildfärger', 'RemoteImageColours' => 'Fjärrbildfärger',
'RemoteMethod' => 'Remote Method', // Added - 2009-02-08 'RemoteMethod' => 'Remote Method', // Added - 2009-02-08
'RemoteProtocol' => 'Remote Protocol', // Added - 2009-02-08 'RemoteProtocol' => 'Remote Protocol', // Added - 2009-02-08
'Rename' => 'Byt namn', 'Rename' => 'Byt namn',
'Replay' => 'Repris', 'Replay' => 'Repris',
'ReplayAll' => 'Alla händelser', 'ReplayAll' => 'Alla händelser',
'ReplayGapless' => 'Gapless Events', 'ReplayGapless' => 'Gapless Events',
'ReplaySingle' => 'Ensam händelse', 'ReplaySingle' => 'Ensam händelse',
'Reset' => 'Återställ', 'Reset' => 'Återställ',
'ResetEventCounts' => 'Återställ händelseräknare', 'ResetEventCounts' => 'Återställ händelseräknare',
'Restart' => 'Återstart', 'Restart' => 'Återstart',
'Restarting' => 'Återstartar', 'Restarting' => 'Återstartar',
'RestrictedCameraIds' => 'Begränsade kameranr.', 'RestrictedCameraIds' => 'Begränsade kameranr.',
'RestrictedMonitors' => 'Begränsade bevakare', 'RestrictedMonitors' => 'Begränsade bevakare',
'ReturnDelay' => 'Fördröjd retur', 'ReturnDelay' => 'Fördröjd retur',
'ReturnLocation' => 'Återvänd till position', 'ReturnLocation' => 'Återvänd till position',
'Rewind' => 'Backa', 'Rewind' => 'Backa',
'RotateLeft' => 'Rotera vänster', 'RotateLeft' => 'Rotera vänster',
'RotateRight' => 'Rotera höger', 'RotateRight' => 'Rotera höger',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25 'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunMode' => 'Körläge', 'RunMode' => 'Körläge',
'RunState' => 'Körläge', 'RunState' => 'Körläge',
'Running' => 'Körs', 'Running' => 'Körs',
'Save' => 'Spara', 'Save' => 'Spara',
'SaveAs' => 'Spara som', 'SaveAs' => 'Spara som',
'SaveFilter' => 'Spara filter', 'SaveFilter' => 'Spara filter',
'Scale' => 'Skala', 'Scale' => 'Skala',
'Score' => 'Resultat', 'Score' => 'Resultat',
'Secs' => 'Sek', 'Secs' => 'Sek',
'Sectionlength' => 'Sektionslängd', 'Sectionlength' => 'Sektionslängd',
'Select' => 'Välj', 'Select' => 'Välj',
'SelectFormat' => 'Select Format', // Added - 2011-06-17 'SelectFormat' => 'Select Format', // Added - 2011-06-17
'SelectLog' => 'Select Log', // Added - 2011-06-17 'SelectLog' => 'Select Log', // Added - 2011-06-17
'SelectMonitors' => 'Välj bevakare', 'SelectMonitors' => 'Välj bevakare',
'SelfIntersecting' => 'Polygonändarna får inte överlappa', 'SelfIntersecting' => 'Polygonändarna får inte överlappa',
'Set' => 'Ställ in', 'Set' => 'Ställ in',
'SetNewBandwidth' => 'Ställ in ny bandbredd', 'SetNewBandwidth' => 'Ställ in ny bandbredd',
'SetPreset' => 'Ställ in förinställning', 'SetPreset' => 'Ställ in förinställning',
'Settings' => 'Inställningar', 'Settings' => 'Inställningar',
'ShowFilterWindow' => 'Visa fönsterfilter', 'ShowFilterWindow' => 'Visa fönsterfilter',
'ShowTimeline' => 'Visa tidslinje', 'ShowTimeline' => 'Visa tidslinje',
'SignalCheckColour' => 'Signal Check Colour', 'SignalCheckColour' => 'Signal Check Colour',
'Size' => 'Storlek', 'Size' => 'Storlek',
@ -633,31 +633,31 @@ $SLANG = array(
'SortAsc' => 'Stigande', 'SortAsc' => 'Stigande',
'SortBy' => 'Sortera', 'SortBy' => 'Sortera',
'SortDesc' => 'Fallande', 'SortDesc' => 'Fallande',
'Source' => 'Källa', 'Source' => 'Källa',
'SourceColours' => 'Source Colours', // Added - 2009-02-08 'SourceColours' => 'Source Colours', // Added - 2009-02-08
'SourcePath' => 'Source Path', // Added - 2009-02-08 'SourcePath' => 'Source Path', // Added - 2009-02-08
'SourceType' => 'Källtyp', 'SourceType' => 'Källtyp',
'Speed' => 'Hastighet', 'Speed' => 'Hastighet',
'SpeedHigh' => 'Höghastighet', 'SpeedHigh' => 'Höghastighet',
'SpeedLow' => 'Låghastighet', 'SpeedLow' => 'Låghastighet',
'SpeedMedium' => 'Normalhastighet', 'SpeedMedium' => 'Normalhastighet',
'SpeedTurbo' => 'Turbohastighet', 'SpeedTurbo' => 'Turbohastighet',
'Start' => 'Start', 'Start' => 'Start',
'State' => 'Läge', 'State' => 'Läge',
'Stats' => 'Statistik', 'Stats' => 'Statistik',
'Status' => 'Status', 'Status' => 'Status',
'Step' => 'Steg', 'Step' => 'Steg',
'StepBack' => 'Stepga bakåt', 'StepBack' => 'Stepga bakåt',
'StepForward' => 'Stega framåt', 'StepForward' => 'Stega framåt',
'StepLarge' => 'Stora steg', 'StepLarge' => 'Stora steg',
'StepMedium' => 'Normalsteg', 'StepMedium' => 'Normalsteg',
'StepNone' => 'Inga steg', 'StepNone' => 'Inga steg',
'StepSmall' => 'Små steg', 'StepSmall' => 'Små steg',
'Stills' => 'Stillbilder', 'Stills' => 'Stillbilder',
'Stop' => 'Stopp', 'Stop' => 'Stopp',
'Stopped' => 'Stoppad', 'Stopped' => 'Stoppad',
'Stream' => 'Strömmande', 'Stream' => 'Strömmande',
'StreamReplayBuffer' => 'Buffert för strömmande uppspelning', 'StreamReplayBuffer' => 'Buffert för strömmande uppspelning',
'Submit' => 'Skicka', 'Submit' => 'Skicka',
'System' => 'System', 'System' => 'System',
'SystemLog' => 'System Log', // Added - 2011-06-16 'SystemLog' => 'System Log', // Added - 2011-06-16
@ -667,22 +667,22 @@ $SLANG = array(
'Tilt' => 'Tilt', 'Tilt' => 'Tilt',
'Time' => 'Tid', 'Time' => 'Tid',
'TimeDelta' => 'tidsdelta', 'TimeDelta' => 'tidsdelta',
'TimeStamp' => 'Tidsstämpel', 'TimeStamp' => 'Tidsstämpel',
'Timeline' => 'Tidslinje', 'Timeline' => 'Tidslinje',
'TimelineTip1' => 'Pass your mouse over the graph to view a snapshot image and event details.', // Added 2013.08.15. '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. '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. '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. 'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // Added 2013.08.15.
'Timestamp' => 'Tidsstämpel', 'Timestamp' => 'Tidsstämpel',
'TimestampLabelFormat' => 'Format på tidsstämpel', 'TimestampLabelFormat' => 'Format på tidsstämpel',
'TimestampLabelX' => 'Värde på tidsstämpel X', 'TimestampLabelX' => 'Värde på tidsstämpel X',
'TimestampLabelY' => 'Värde på tidsstämpel Y', 'TimestampLabelY' => 'Värde på tidsstämpel Y',
'Today' => 'Idag', 'Today' => 'Idag',
'Tools' => 'Verktyg', 'Tools' => 'Verktyg',
'Total' => 'Total', // Added - 2011-06-16 'Total' => 'Total', // Added - 2011-06-16
'TotalBrScore' => 'Total<br/>Score', 'TotalBrScore' => 'Total<br/>Score',
'TrackDelay' => 'Spårfördröjning', 'TrackDelay' => 'Spårfördröjning',
'TrackMotion' => 'Spåra rörelse', 'TrackMotion' => 'Spåra rörelse',
'Triggers' => 'Triggers', 'Triggers' => 'Triggers',
'TurboPanSpeed' => 'Turbo panoramahastighet', 'TurboPanSpeed' => 'Turbo panoramahastighet',
'TurboTiltSpeed' => 'Turbo tilthastighet', 'TurboTiltSpeed' => 'Turbo tilthastighet',
@ -690,63 +690,63 @@ $SLANG = array(
'Unarchive' => 'Packa upp', 'Unarchive' => 'Packa upp',
'Undefined' => 'Undefined', // Added - 2009-02-08 'Undefined' => 'Undefined', // Added - 2009-02-08
'Units' => 'Enheter', 'Units' => 'Enheter',
'Unknown' => 'Okänd', 'Unknown' => 'Okänd',
'Update' => 'Uppdatera', 'Update' => 'Uppdatera',
'UpdateAvailable' => 'En uppdatering till ZoneMinder finns tillgänglig.', 'UpdateAvailable' => 'En uppdatering till ZoneMinder finns tillgänglig.',
'UpdateNotNecessary' => 'Ingen uppdatering behövs.', 'UpdateNotNecessary' => 'Ingen uppdatering behövs.',
'Updated' => 'Updated', // Added - 2011-06-16 'Updated' => 'Updated', // Added - 2011-06-16
'Upload' => 'Upload', // Added - 2011-08-23 'Upload' => 'Upload', // Added - 2011-08-23
'UseFilter' => 'Använd filter', 'UseFilter' => 'Använd filter',
'UseFilterExprsPost' => '&nbsp;filter&nbsp;expressions', // This is used at the end of the phrase 'use N filter expressions' 'UseFilterExprsPost' => '&nbsp;filter&nbsp;expressions', // This is used at the end of the phrase 'use N filter expressions'
'UseFilterExprsPre' => 'Använd&nbsp;', // This is used at the beginning of the phrase 'use N filter expressions' 'UseFilterExprsPre' => 'Använd&nbsp;', // This is used at the beginning of the phrase 'use N filter expressions'
'UsedPlugins' => 'Used Plugins', 'UsedPlugins' => 'Used Plugins',
'User' => 'Användare', 'User' => 'Användare',
'Username' => 'Användarnamn', 'Username' => 'Användarnamn',
'Users' => 'Användare', 'Users' => 'Användare',
'V4L' => 'V4L', // Added - 2015-04-18 'V4L' => 'V4L', // Added - 2015-04-18
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18 'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18 'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
'Value' => 'Värde', 'Value' => 'Värde',
'Version' => 'Version', 'Version' => 'Version',
'VersionIgnore' => 'Ignorera denna version', 'VersionIgnore' => 'Ignorera denna version',
'VersionRemindDay' => 'Påminn om 1 dag', 'VersionRemindDay' => 'Påminn om 1 dag',
'VersionRemindHour' => 'Påminn om 1 timme', 'VersionRemindHour' => 'Påminn om 1 timme',
'VersionRemindNever' => 'Påminn inte om nya versioner', 'VersionRemindNever' => 'Påminn inte om nya versioner',
'VersionRemindWeek' => 'Påminn om en 1 vecka', 'VersionRemindWeek' => 'Påminn om en 1 vecka',
'Video' => 'Video', 'Video' => 'Video',
'VideoFormat' => 'Videoformat', 'VideoFormat' => 'Videoformat',
'VideoGenFailed' => 'Videogenereringen misslyckades!', 'VideoGenFailed' => 'Videogenereringen misslyckades!',
'VideoGenFiles' => 'Befintliga videofiler', 'VideoGenFiles' => 'Befintliga videofiler',
'VideoGenNoFiles' => 'Inga videofiler', 'VideoGenNoFiles' => 'Inga videofiler',
'VideoGenParms' => 'Inställningar för videogenerering', 'VideoGenParms' => 'Inställningar för videogenerering',
'VideoGenSucceeded' => 'Videogenereringen lyckades!', 'VideoGenSucceeded' => 'Videogenereringen lyckades!',
'VideoSize' => 'Videostorlek', 'VideoSize' => 'Videostorlek',
'View' => 'Visa', 'View' => 'Visa',
'ViewAll' => 'Visa alla', 'ViewAll' => 'Visa alla',
'ViewEvent' => 'Visa händelse', 'ViewEvent' => 'Visa händelse',
'ViewPaged' => 'Visa Paged', 'ViewPaged' => 'Visa Paged',
'Wake' => 'Vakna', 'Wake' => 'Vakna',
'WarmupFrames' => 'Värm upp ramar', 'WarmupFrames' => 'Värm upp ramar',
'Watch' => 'Se', 'Watch' => 'Se',
'Web' => 'Webb', 'Web' => 'Webb',
'WebColour' => 'Webbfärg', 'WebColour' => 'Webbfärg',
'Week' => 'Vecka', 'Week' => 'Vecka',
'White' => 'Vit', 'White' => 'Vit',
'WhiteBalance' => 'Vitbalans', 'WhiteBalance' => 'Vitbalans',
'Wide' => 'Vid', 'Wide' => 'Vid',
'X' => 'X', 'X' => 'X',
'X10' => 'X10', 'X10' => 'X10',
'X10ActivationString' => 'X10 aktiveringssträng', 'X10ActivationString' => 'X10 aktiveringssträng',
'X10InputAlarmString' => 'X10 larmingångssträng', 'X10InputAlarmString' => 'X10 larmingångssträng',
'X10OutputAlarmString' => 'X10 larmutgångssträng', 'X10OutputAlarmString' => 'X10 larmutgångssträng',
'Y' => 'J', 'Y' => 'J',
'Yes' => 'Ja', 'Yes' => 'Ja',
'YouNoPerms' => 'Du har inte tillstånd till denna resurs.', 'YouNoPerms' => 'Du har inte tillstånd till denna resurs.',
'Zone' => 'Zon', 'Zone' => 'Zon',
'ZoneAlarmColour' => 'Larmfärg (Röd/Grön/Blå)', 'ZoneAlarmColour' => 'Larmfärg (Röd/Grön/Blå)',
'ZoneArea' => 'Zonarea', 'ZoneArea' => 'Zonarea',
'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count', 'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count',
'ZoneFilterSize' => 'Filterbredd/höjd (pixlar)', 'ZoneFilterSize' => 'Filterbredd/höjd (pixlar)',
'ZoneMinMaxAlarmArea' => 'Min/Max larmarea', 'ZoneMinMaxAlarmArea' => 'Min/Max larmarea',
'ZoneMinMaxBlobArea' => 'Min/Max blobbarea', 'ZoneMinMaxBlobArea' => 'Min/Max blobbarea',
'ZoneMinMaxBlobs' => 'Min/Max blobbar', 'ZoneMinMaxBlobs' => 'Min/Max blobbar',
@ -762,13 +762,13 @@ $SLANG = array(
// Complex replacements with formatting and/or placements, must be passed through sprintf // Complex replacements with formatting and/or placements, must be passed through sprintf
$CLANG = array( $CLANG = array(
'CurrentLogin' => 'Aktuell inloggning är \'%1$s\'', 'CurrentLogin' => 'Aktuell inloggning är \'%1$s\'',
'EventCount' => '%1$s %2$s', // For example '37 Events' (from Vlang below) 'EventCount' => '%1$s %2$s', // For example '37 Events' (from Vlang below)
'LastEvents' => 'Senaste %1$s %2$s', // For example 'Last 37 Events' (from Vlang below) 'LastEvents' => 'Senaste %1$s %2$s', // For example 'Last 37 Events' (from Vlang below)
'LatestRelease' => 'Aktuell version är v%1$s, du har v%2$s.', 'LatestRelease' => 'Aktuell version är v%1$s, du har v%2$s.',
'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below) 'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below)
'MonitorFunction' => 'Bevakare %1$s funktion', 'MonitorFunction' => 'Bevakare %1$s funktion',
'RunningRecentVer' => 'Du använder den senaste versionen av ZoneMinder, v%s.', 'RunningRecentVer' => 'Du använder den senaste versionen av ZoneMinder, v%s.',
'VersionMismatch' => 'Version mismatch, system is version %1$s, database is %2$s.', // Added - 2011-05-25 'VersionMismatch' => 'Version mismatch, system is version %1$s, database is %2$s.', // Added - 2011-05-25
); );
@ -806,7 +806,7 @@ $CLANG = array(
// Variable arrays expressing plurality, see the zmVlang description above // Variable arrays expressing plurality, see the zmVlang description above
$VLANG = array( $VLANG = array(
'Event' => array( 0=>'Händelser', 1=>'Händelsen', 2=>'Händelserna' ), 'Event' => array( 0=>'Händelser', 1=>'Händelsen', 2=>'Händelserna' ),
'Monitor' => array( 0=>'Bevakare', 1=>'Bevakare', 2=>'Bevakare' ), 'Monitor' => array( 0=>'Bevakare', 1=>'Bevakare', 2=>'Bevakare' ),
); );
@ -826,7 +826,7 @@ function zmVlang( $langVarArray, $count )
return( $value ); return( $value );
} }
} }
die( 'Fel, kan inte relatera variabel språksträng' ); die( 'Fel, kan inte relatera variabel språksträng' );
} }
// This is an version that could be used in the Russian example above // This is an version that could be used in the Russian example above
@ -886,8 +886,8 @@ function zmVlang( $langVarArray, $count )
// These overrides are in the form show below where the array key represents the option name minus the initial ZM_ // These overrides are in the form show below where the array key represents the option name minus the initial ZM_
$OLANG = array( $OLANG = array(
'LANG_DEFAULT' => array( 'LANG_DEFAULT' => array(
'Prompt' => "Välj språk för ZoneMinder", 'Prompt' => "Välj språk för ZoneMinder",
'Help' => "ZoneMinder kan använda annat språk än engelska i menyer och texter. Välj här det språk du vill använda till ZoneMinder." 'Help' => "ZoneMinder kan använda annat språk än engelska i menyer och texter. Välj här det språk du vill använda till ZoneMinder."
), ),
'OPTIONS_FFMPEG' => array( 'OPTIONS_FFMPEG' => array(
'Help' => "Parameters in this field are passed on to FFmpeg. Multiple parameters can be separated by ,~~ ". 'Help' => "Parameters in this field are passed on to FFmpeg. Multiple parameters can be separated by ,~~ ".

View File

@ -0,0 +1,3 @@
input[type="text"] {
width: 100%;
}

View File

@ -38,13 +38,6 @@
text-align: center; text-align: center;
} }
#dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
margin: 0 3px;
}
#dvrControls input[disabled] { #dvrControls input[disabled] {
color: #aaaaaa; color: #aaaaaa;
} }

View File

@ -18,21 +18,19 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
function exportHeader( $title ) function exportHeader($title) {
{
?> ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang="en">
<html xmlns="http://www.w3.org/1999/xhtml"> <head>
<head> <meta charset="utf-8">
<title><?php echo $title ?></title> <title><?php echo $title ?></title>
<style type="text/css"> <style type="text/css">
<!-- <!--
<?php include( ZM_SKIN_PATH.'/css/'.ZM_SKIN_NAME.'/export.css' ); ?> <?php include(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/css/'.ZM_SKIN_NAME.'/export.css'); ?>
ul.tabs { ul.tabs {
margin: 0; margin: 0;
margin-bottom: -1px; margin-bottom: -1px;
padding: 0; padding: 0;
float: left; float: left;
list-style: none; list-style: none;
@ -70,50 +68,46 @@ html ul.tabs li.active, html ul.tabs li.active a:hover {
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;
} }
--> -->
</style> </style>
<script type="text/javascript"> <script type="text/javascript" src="<?php echo ($title == translate('Images').' Master' ? '' : '../') ?>jquery.js"></script>
<?php include(ZM_SKIN_PATH.'/js/jquery.js') ?> <!--<script type="text/javascript" src="<?php echo ($title == translate('Images').' Master' ? '' : '../') ?>video.js"></script>-->
</script> <script type="text/javascript">
<script type="text/javascript" language="javascript" charset="utf-8">
/*==========[tab code]==========*/ /*==========[tab code]==========*/
$(document).ready(function() { $(document).ready(function() {
//When page loads... //When page loads...
$(".tab_content").hide(); //Hide all content $(".tab_content").hide(); //Hide all content
$("ul.tabs li:first").addClass("active").show(); //Activate first tab $("ul.tabs li:first").addClass("active").show(); //Activate first tab
$(".tab_content:first").show(); //Show first tab content $(".tab_content:first").show(); //Show first tab content
//On Click Event //On Click Event
$("ul.tabs li").click(function() { $("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active"); //Remove any "active" class $("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab $(this).addClass("active"); //Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content $(".tab_content").hide(); //Hide all tab content
var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content
$(activeTab).fadeIn(); //Fade in the active ID content $(activeTab).fadeIn(); //Fade in the active ID content
return false; return false;
}); });
}); });
// ]]> // ]]>
</script> </script>
</head> </head>
<?php <?php
} }
function exportEventDetail( $event, $exportFrames, $exportImages ) function exportEventDetail($event, $exportFrames, $exportImages) {
{ ob_start();
ob_start(); exportHeader(translate('Event').' '.$event->Id());
exportHeader( translate('Event')." ".$event->Id() );
$otherlinks = ''; $otherlinks = '';
if( $exportFrames ) $otherlinks .= '<a href="zmEventFrames.html">'.translate('Frames').'</a>,'; if( $exportFrames ) $otherlinks .= '<a href="zmEventFrames.html">'.translate('Frames').'</a>,';
if( $exportImages ) $otherlinks .= '<a href="zmEventImages.html">'.translate('Images').'</a>,'; if( $exportImages ) $otherlinks .= '<a href="zmEventImages.html">'.translate('Images').'</a>,';
$otherlinks = substr($otherlinks,0,-1); $otherlinks = substr($otherlinks,0,-1);
?> ?>
<body> <body>
<div id="page"> <div id="page">
@ -139,22 +133,20 @@ function exportEventDetail( $event, $exportFrames, $exportImages )
</body> </body>
</html> </html>
<?php <?php
return( ob_get_clean() ); return ob_get_clean();
} }
function exportEventFrames( $event, $exportDetail, $exportImages ) function exportEventFrames($event, $exportDetail, $exportImages) {
{ $sql = 'SELECT *, unix_timestamp( TimeStamp ) AS UnixTimeStamp FROM Frames WHERE EventID = ? ORDER BY FrameId';
$sql = "SELECT *, unix_timestamp( TimeStamp ) AS UnixTimeStamp FROM Frames WHERE EventID = ? ORDER BY FrameId"; $frames = dbFetchAll($sql, NULL, array($event->Id()));
$frames = dbFetchAll( $sql, NULL, array( $event->Id() ) );
ob_start(); ob_start();
exportHeader( translate('Frames')." ".$event->Id() ); exportHeader(translate('Frames').' '.$event->Id());
$otherlinks = ''; $otherlinks = '';
if( $exportDetail ) $otherlinks .= '<a href="zmEventDetail.html">'.translate('Event').'</a>,'; if( $exportDetail ) $otherlinks .= '<a href="zmEventDetail.html">'.translate('Event').'</a>,';
if( $exportImages ) $otherlinks .= '<a href="zmEventImages.html">'.translate('Images').'</a>,'; if( $exportImages ) $otherlinks .= '<a href="zmEventImages.html">'.translate('Images').'</a>,';
$otherlinks = substr($otherlinks,0,-1); $otherlinks = substr($otherlinks,0,-1);
?> ?>
<body> <body>
<div id="page"> <div id="page">
@ -168,56 +160,49 @@ function exportEventFrames( $event, $exportDetail, $exportImages )
<th><?php echo translate('TimeDelta') ?></th> <th><?php echo translate('TimeDelta') ?></th>
<th><?php echo translate('Score') ?></th> <th><?php echo translate('Score') ?></th>
<?php <?php
if ( $exportImages ) if ( $exportImages ) {
{
?> ?>
<th><?php echo translate('Image') ?></th> <th><?php echo translate('Image') ?></th>
<?php <?php
} }
?> ?>
</tr> </tr>
<?php <?php
if ( count($frames) ) if ( count($frames) ) {
{ $eventPath = $event->Path();
$eventPath = $event->Path(); foreach ( $frames as $frame ) {
foreach ( $frames as $frame ) $imageFile = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId']);
{ $imagePath = $eventPath.'/'.$imageFile;
$imageFile = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $frame['FrameId'] ); $analImage = preg_replace('/capture/', 'analyse', $imagePath);
$imagePath = $eventPath."/".$imageFile; if ( file_exists($analImage) ) {
$analImage = preg_replace( "/capture/", "analyse", $imagePath ); $imageFile = preg_replace('/capture/', 'analyse', $imageFile);
if ( file_exists( $analImage ) ) }
{
$imageFile = preg_replace( "/capture/", "analyse", $imageFile );
}
$class = strtolower($frame['Type']); $class = strtolower($frame['Type']);
?> ?>
<tr class="<?php echo $class ?>"> <tr class="<?php echo $class ?>">
<td><?php echo $frame['FrameId'] ?></td> <td><?php echo $frame['FrameId'] ?></td>
<td><?php echo $frame['Type'] ?></td> <td><?php echo $frame['Type'] ?></td>
<td><?php echo strftime( STRF_FMT_TIME, $frame['UnixTimeStamp'] ) ?></td> <td><?php echo strftime(STRF_FMT_TIME, $frame['UnixTimeStamp']) ?></td>
<td><?php echo number_format( $frame['Delta'], 2 ) ?></td> <td><?php echo number_format($frame['Delta'], 2) ?></td>
<td><?php echo $frame['Score'] ?></td> <td><?php echo $frame['Score'] ?></td>
<?php <?php
if ( $exportImages ) if ( $exportImages ) {
{
?> ?>
<td><a href="<?php echo $imageFile ?>" target="zmExportImage"><img src="<?php echo $imageFile ?>" border="0" class="thumb" alt="Frame <?php echo $frame['FrameId'] ?>"/></a></td> <td><a href="<?php echo $imageFile ?>" target="zmExportImage"><img src="<?php echo $imageFile ?>" class="thumb" alt="Frame <?php echo $frame['FrameId'] ?>"/></a></td>
<?php <?php
} }
?> ?>
</tr> </tr>
<?php <?php
} } # end foreach frame
} } else {
else
{
?> ?>
<tr> <tr>
<td class="monoRow" colspan="<?php echo $exportImages?6:5 ?>"><?php echo translate('NoFramesRecorded') ?></td> <td class="monoRow" colspan="<?php echo $exportImages?6:5 ?>"><?php echo translate('NoFramesRecorded') ?></td>
</tr> </tr>
<?php <?php
} } # end if count($frames)
?> ?>
</table> </table>
</div> </div>
@ -225,13 +210,12 @@ function exportEventFrames( $event, $exportDetail, $exportImages )
</body> </body>
</html> </html>
<?php <?php
return( ob_get_clean() ); return ob_get_clean();
} }
function exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist ) function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
{ ob_start();
ob_start(); exportHeader(translate('Images').' '.$event->Id());
exportHeader( translate('Images')." ".$event->Id() );
$otherlinks = ''; $otherlinks = '';
if( $exportDetail ) $otherlinks .= '<a href="zmEventDetail.html">'.translate('Event').'</a>,'; if( $exportDetail ) $otherlinks .= '<a href="zmEventDetail.html">'.translate('Event').'</a>,';
@ -257,28 +241,54 @@ function exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist )
<h2><?php echo translate('Images') ?>: <?php echo validHtmlStr($event->Name()) ?><?php if(!empty($otherlinks)) { ?> (<?php echo$otherlinks?>) <?php } ?></h2> <h2><?php echo translate('Images') ?>: <?php echo validHtmlStr($event->Name()) ?><?php if(!empty($otherlinks)) { ?> (<?php echo$otherlinks?>) <?php } ?></h2>
<?php
if ( $event->DefaultVideo() ) {
// videojs zoomrotate only when direct recording
$Zoom = 1;
$Rotation = 0;
$Monitor = $event->Monitor();
if ( $Monitor->VideoWriter() == '2' ) {
# Passthrough
$Rotation = $event->Orientation();
if ( in_array($event->Orientation(),array('90','270')) )
$Zoom = $event->Height()/$event->Width();
}
?>
<div id="videoFeed">
<video id="videoobj" class="video-js vjs-default-skin" style="transform: matrix(1, 0, 0, 1, 0, 0)"
width="<?php echo $event->Width() ?>"
height="<?php echo $event->Height() ?>"
data-setup='{ "controls": true, "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "zoom": "<?php echo $Zoom ?>"}}}'>
<source src="<?php echo $event->getStreamSrc(array('mode'=>'mpeg','format'=>'h264')); ?>" type="video/mp4">
<track id="monitorCaption" kind="captions" label="English" srclang="en" src='data:plain/text;charset=utf-8,"WEBVTT\n\n 00:00:00.000 --> 00:00:01.000 ZoneMinder"' default>
Your browser does not support the video tag.
</video>
</div><!--videoFeed-->
<?php
} else { // end if DefaultVideo
?>
<ilayer id="slidensmain" width=&{slidewidth}; height=&{slideheight}; bgColor=&{slidebgcolor}; visibility=hide> <ilayer id="slidensmain" width=&{slidewidth}; height=&{slideheight}; bgColor=&{slidebgcolor}; visibility=hide>
<layer id="slidenssub" width=&{slidewidth}; left=auto top=auto></layer> <layer id="slidenssub" width="&{slidewidth};" left="auto" top="auto"></layer>
</ilayer> </ilayer>
<div id="imagevideo" align="center"></div> <div id="imagevideo" align="center"></div>
<br> <br>
<div align="center"> <div align="center">
<button onclick="stepbackward()">< Step</button><button <button type="button" onclick="stepbackward()">&lt; Step</button>
id="btnrwd" onclick="rewind()" >Rwd</button><button <button type="button" id="btnrwd" onclick="rewind()" >Rwd</button>
id="btnplay" onclick="playstop()">Stop</button><button <button type="button" id="btnplay" onclick="playstop()">Stop</button>
onclick="stepforward()">Step ></button><button <button type="button" onclick="stepforward()">Step &gt;</button>
id="btnspeedup" onclick="speedup()">speedup</button><button <button type="button" id="btnspeedup" onclick="speedup()">speedup</button>
id="btnspeeddown" onclick="speeddown()">slowdown</button> <button type="button" id="btnspeeddown" onclick="speeddown()">slowdown</button>
</div> </div>
<div align="center"><div class="horizontal_track" > <div align="center"><div class="horizontal_track" >
<div class="horizontal_slit" >&nbsp;</div> <div class="horizontal_slit" >&nbsp;</div>
<div class="horizontal_slider" id="imageslider_id" style="left: 0px;" <div class="horizontal_slider" id="imageslider_id" style="left: 0px;"
onmousedown="slide(event,'horizontal', <?php echo($event->Width()-20)?>, 1, <?php echo$listcount?>, <?php echo$listcount?>,0, 'imageslider_display_id');" >&nbsp;</div> onmousedown="slide(event,'horizontal', <?php echo($event->Width()-20)?>, 1, <?php echo$listcount?>, <?php echo$listcount?>,0, 'imageslider_display_id');">&nbsp;</div>
</div></div> </div>
<div align="center"><div class="display_holder" ><input id="imageslider_display_id" class="value_display" type="text" value="0" onfocus="blur(this);" /></div></div> </div>
<div align="center"><div class="display_holder"><input id="imageslider_display_id" class="value_display" type="text" value="0" onfocus="blur(this);"/></div></div>
<script type="text/javascript">
<script language="JavaScript1.2">
/*********************************************** /***********************************************
* Flexi Slideshow- © Dynamic Drive (www.dynamicdrive.com) * Flexi Slideshow- © Dynamic Drive (www.dynamicdrive.com)
@ -286,15 +296,15 @@ function exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist )
* Visit http://www.dynamicdrive.com/ for full source code * Visit http://www.dynamicdrive.com/ for full source code
***********************************************/ ***********************************************/
var eventWidth = <?php echo$event->Width()?>; var eventWidth = <?php echo $event->Width()?>;
var eventHeight = <?php echo$event->Height()?>; var eventHeight = <?php echo $event->Height()?>;
var variableslide=[<?php echo$slides?>]; var variableslide=[<?php echo $slides?>];
//configure the below 3 variables to set the dimension/background color of the slideshow //configure the below 3 variables to set the dimension/background color of the slideshow
var slidewidth=eventWidth+'px' //set to width of LARGEST image in your slideshow var slidewidth=eventWidth+'px'; //set to width of LARGEST image in your slideshow
var slideheight=eventHeight+'px' //set to height of LARGEST iamge in your slideshow, plus any text description var slideheight=eventHeight+'px'; //set to height of LARGEST image in your slideshow, plus any text description
var slidebgcolor='#ffffff' var slidebgcolor='#ffffff';
//configure the below variable to determine the delay between image rotations (in miliseconds) //configure the below variable to determine the delay between image rotations (in miliseconds)
var origslidedelay=100; var origslidedelay=100;
@ -306,15 +316,15 @@ var ie=document.all;
var dom=document.getElementById; var dom=document.getElementById;
for (i=0;i<variableslide.length;i++){ for (i=0;i<variableslide.length;i++){
var cacheimage=new Image() var cacheimage = new Image();
cacheimage.src=variableslide[i] cacheimage.src = variableslide[i];
} }
var currentslide=-1 var currentslide = -1;
var mytimer = null; var mytimer = null;
//if (ie||dom) document.write('<div id="slidedom" style="width:'+slidewidth+'px;height:'+slideheight+'; background-color:'+slidebgcolor+'"></div>'); //if (ie||dom) document.write('<div id="slidedom" style="width:'+slidewidth+'px;height:'+slideheight+'; background-color:'+slidebgcolor+'"></div>');
if (ie||dom) document.getElementById('imagevideo').innerHTML = '<div id="slidedom" style="width:'+slidewidth+'px;height:'+slideheight+'; background-color:'+slidebgcolor+'"><img src="" name="imageslideframe"></div>'; if (ie||dom) document.getElementById('imagevideo').innerHTML = '<div id="slidedom" style="width:'+slidewidth+';height:'+slideheight+'; background-color:'+slidebgcolor+'"><img src="" name="imageslideframe"></div>';
function rotateimages(){ function rotateimages(){
if (currentslide==variableslide.length-1) currentslide=0; if (currentslide==variableslide.length-1) currentslide=0;
@ -337,14 +347,12 @@ function changeimage() {
slideManual(currentslide+1,eventWidth-20, 1, variableslide.length); slideManual(currentslide+1,eventWidth-20, 1, variableslide.length);
} }
function start_slider(){ function start_slider(){
crossrotateobj=dom? document.getElementById("slidedom") : ie? document.all.slidedom : document.slidensmain.document.slidenssub; crossrotateobj = dom ? document.getElementById("slidedom") : ie ? document.all.slidedom : document.slidensmain.document.slidenssub;
if (document.layers) document.slidensmain.visibility="show"; if (document.layers) document.slidensmain.visibility="show";
rotateimages(); rotateimages();
} }
// seyi_code // seyi_code
function rotateimagesrewind(){ function rotateimagesrewind(){
if (currentslide==0) currentslide=variableslide.length-1; if (currentslide==0) currentslide=variableslide.length-1;
@ -366,12 +374,12 @@ function stepforward() {
document.getElementById('btnspeedup').disabled = true; document.getElementById('btnspeedup').disabled = true;
document.getElementById('btnspeeddown').disabled = true; document.getElementById('btnspeeddown').disabled = true;
if (currentslide==variableslide.length-1) currentslide=0; if ( currentslide == variableslide.length-1 ) currentslide=0;
else currentslide++; else currentslide++;
changeimage(); changeimage();
} }
function stepbackward() { function stepbackward() {
clearTimeout(mytimer); clearTimeout(mytimer);
// document.getElementById('btnrwd').style.borderTop='2px solid #ffffff'; // document.getElementById('btnrwd').style.borderTop='2px solid #ffffff';
@ -383,11 +391,10 @@ function stepbackward() {
document.getElementById('btnspeedup').disabled = true; document.getElementById('btnspeedup').disabled = true;
document.getElementById('btnspeeddown').disabled = true; document.getElementById('btnspeeddown').disabled = true;
if (currentslide==0) currentslide=variableslide.length-1; if ( currentslide == 0 ) currentslide = variableslide.length-1;
else currentslide--; else currentslide--;
changeimage(); changeimage();
} }
function speedup() { slidedelay = slidedelay/2; } function speedup() { slidedelay = slidedelay/2; }
function speeddown() { slidedelay = slidedelay*2; } function speeddown() { slidedelay = slidedelay*2; }
@ -430,7 +437,6 @@ function rewind() {
document.getElementById('btnspeedup').disabled = true; document.getElementById('btnspeedup').disabled = true;
document.getElementById('btnspeeddown').disabled = true; document.getElementById('btnspeeddown').disabled = true;
} }
} }
//---------------------------------+ //---------------------------------+
@ -501,65 +507,63 @@ function moveSlider(evnt) {
// seyi_code // seyi_code
currentslide = v-1; currentslide = v-1;
changeimage(); changeimage();
return false return false;
} }
return
} }
// moveSlider: Handles the start of a slider move. // moveSlider: Handles the start of a slider move.
function slide(evnt, orientation, length, from, to, count, decimals, display) { function slide(evnt, orientation, length, from, to, count, decimals, display) {
if (!evnt) evnt = window.event; if (!evnt) evnt = window.event;
sliderObj = (evnt.target) ? evnt.target : evnt.srcElement; // Get the activated slider element. sliderObj = (evnt.target) ? evnt.target : evnt.srcElement; // Get the activated slider element.
sliderObj.pxLen = length // The allowed slider movement in pixels. sliderObj.pxLen = length; // The allowed slider movement in pixels.
sliderObj.valCount = count ? count - 1 : length // Allowed number of values in the interval. sliderObj.valCount = count ? count - 1 : length; // Allowed number of values in the interval.
displayObj = carpeGetElementById(display) // Get the associated display element.\ displayObj = carpeGetElementById(display); // Get the associated display element.\
displayObj.dec = decimals // Number of decimals to be displayed. displayObj.dec = decimals; // Number of decimals to be displayed.
sliderObj.scale = (to - from) / length // Slider-display scale [value-change per pixel of movement]. sliderObj.scale = (to - from) / length; // Slider-display scale [value-change per pixel of movement].
if (orientation == 'horizontal') { // Set limits for horizontal sliders. if (orientation == 'horizontal') { // Set limits for horizontal sliders.
sliderObj.fromVal = from sliderObj.fromVal = from;
xMax = length xMax = length;
yMax = 0 yMax = 0;
} else if (orientation == 'vertical') { // Set limits and scale for vertical sliders.
sliderObj.fromVal = to;
xMax = 0;
yMax = length;
sliderObj.scale = -sliderObj.scale; // Invert scale for vertical sliders. "Higher is more."
} }
if (orientation == 'vertical') { // Set limits and scale for vertical sliders. pxLeft = carpeLeft(sliderObj.id); // Sliders horizontal position at start of slide.
sliderObj.fromVal = to pxTop = carpeTop(sliderObj.id); // Sliders vertical position at start of slide.
xMax = 0 xCoord = evnt.screenX; // Horizontal mouse position at start of slide.
yMax = length yCoord = evnt.screenY; // Vertical mouse position at start of slide.
sliderObj.scale = -sliderObj.scale // Invert scale for vertical sliders. "Higher is more." mouseover = true;
} document.onmousemove = moveSlider; // Start the action if the mouse is dragged.
pxLeft = carpeLeft(sliderObj.id) // Sliders horizontal position at start of slide. document.onmouseup = sliderMouseUp; // Stop sliding.
pxTop = carpeTop(sliderObj.id) // Sliders vertical position at start of slide.
xCoord = evnt.screenX // Horizontal mouse position at start of slide.
yCoord = evnt.screenY // Vertical mouse position at start of slide.
mouseover = true
document.onmousemove = moveSlider // Start the action if the mouse is dragged.
document.onmouseup = sliderMouseUp // Stop sliding.
} }
// sliderMouseup: Handles the mouseup event after moving a slider. // sliderMouseup: Handles the mouseup event after moving a slider.
// Snaps the slider position to allowed/displayed value. // Snaps the slider position to allowed/displayed value.
function sliderMouseUp() { function sliderMouseUp() {
mouseover = false // Stop the sliding. mouseover = false; // Stop the sliding.
v = (displayObj.value) ? displayObj.value : 0 // Find last display value. v = (displayObj.value) ? displayObj.value : 0; // Find last display value.
pos = (v - sliderObj.fromVal)/(sliderObj.scale) // Calculate slider position (regardless of orientation). pos = (v - sliderObj.fromVal)/(sliderObj.scale); // Calculate slider position (regardless of orientation).
if (yMax == 0) carpeLeft(sliderObj.id, pos) // Snap horizontal slider to corresponding display position. if (yMax == 0) carpeLeft(sliderObj.id, pos); // Snap horizontal slider to corresponding display position.
if (xMax == 0) carpeTop(sliderObj.id, pos) // Snap vertical slider to corresponding display position. if (xMax == 0) carpeTop(sliderObj.id, pos); // Snap vertical slider to corresponding display position.
if (document.removeEventListener) { // Remove event listeners from 'document' (Moz&co). if (document.removeEventListener) { // Remove event listeners from 'document' (Moz&co).
document.removeEventListener('mousemove', moveSlider) document.removeEventListener('mousemove', moveSlider);
document.removeEventListener('mouseup', sliderMouseUp) document.removeEventListener('mouseup', sliderMouseUp);
} }
else if (document.detachEvent) { // Remove event listeners from 'document' (IE&co). else if (document.detachEvent) { // Remove event listeners from 'document' (IE&co).
document.detachEvent('onmousemove', moveSlider) document.detachEvent('onmousemove', moveSlider);
document.detachEvent('onmouseup', sliderMouseUp) document.detachEvent('onmouseup', sliderMouseUp);
} }
} }
//seyi_code // seyi_code
//slide(event,'horizontal', 300, 1, 22, 22,0, 'imageslider_display_id'); //slide(event,'horizontal', 300, 1, 22, 22,0, 'imageslider_display_id');
//slide(evnt, orientation, length, from, to, count, decimals, display) { //slide(evnt, orientation, length, from, to, count, decimals, display) {
function slideManual(val,length,from,to) { function slideManual(val,length,from,to) {
scale = (to - from) / length // Slider-display scale [value-change per pixel of movement]. scale = (to - from) / length; // Slider-display scale [value-change per pixel of movement].
fromVal = from fromVal = from;
xMax = length xMax = length;
yMax = 0 yMax = 0;
sliderid = 'imageslider_id'; sliderid = 'imageslider_id';
@ -574,24 +578,26 @@ if (ie||dom) start_slider();
else if (document.layers) window.onload=start_slider; else if (document.layers) window.onload=start_slider;
</script> </script>
<?php
} # end if defaultvideo
?>
</body> </body>
</html> </html>
<?php <?php
return( ob_get_clean() ); return ob_get_clean();
} }
function exportEventImagesMaster( $eids ) { function exportEventImagesMaster($eids) {
ob_start(); ob_start();
exportHeader( translate('Images').' Master' ); exportHeader(translate('Images').' Master');
?> ?>
<body> <body>
<h2><?php echo translate('Images') ?> Master</h2> <h2><?php echo translate('Images') ?> Master</h2>
<?php <?php
// TODO: SHould use find to make this 1 db query // TODO: Should use find to make this 1 db query
foreach ($eids as $eid) { foreach ($eids as $eid) {
//get monitor id and event id //get monitor id and event id
$event = new Event( $eid ); $event = new Event($eid);
$eventMonitorId[$eid] = $event->MonitorId(); $eventMonitorId[$eid] = $event->MonitorId();
$eventPath[$eid] = $event->Relative_Path(); $eventPath[$eid] = $event->Relative_Path();
} }
@ -600,70 +606,66 @@ function exportEventImagesMaster( $eids ) {
$monitorNames = array(); $monitorNames = array();
//* //*
if(!empty($monitors)) { if ( !empty($monitors) ) {
$tmp = dbFetchAll("SELECT Id,Name FROM Monitors WHERE Id IN (".implode(',', $monitors).") "); $tmp = dbFetchAll('SELECT Id,Name FROM Monitors WHERE Id IN ('.implode(',', $monitors).') ');
foreach ( $tmp as $row ) { $monitorNames[$row['Id']] = $row['Name']; } foreach ( $tmp as $row ) { $monitorNames[$row['Id']] = $row['Name']; }
} }
//*/ //*/
//trigger_error(print_r($monitorNames,1)); //trigger_error(print_r($monitorNames,1));
?> ?>
<div id="tabs"> <div id="tabs">
<ul class="tabs"> <ul class="tabs">
<li class="active"><a href="#all"> All </a></li> <li class="active"><a href="#all"> All </a></li>
<?php <?php
foreach ($monitors as $monitor) { foreach ($monitors as $monitor) {
# code... echo "<li><a href=\"#tab$monitor\">" . $monitorNames[$monitor] . '</a></li>';
echo "<li><a href='#tab$monitor'>" . $monitorNames[$monitor] . '</a></li>';
} }
?> ?>
</ul> </ul>
</div> </div>
<table width="100%" height="100%" ><tr> <table width="100%" height="100%">
<td valign="top" bgcolor="#dddddd" style="padding:10px;"> <tr>
<div class='tab_content' id='all'> <td valign="top" bgcolor="#dddddd" style="padding:10px;">
<h2> All </h2> <div class="tab_content" id="all">
<?php <h2> All </h2>
if (!is_array($eids)) { <?php
echo "<div><a href=\"javascript:switchevent('$eids/zm/EventImages.html');\"> $eids </div>"; foreach($eids as $eid) {
} $Event = new Event($eid);
?> if ( $Event->SaveJPEGs() ) {
<?php foreach($eids as $eid) { ?>
?> <div><a href="#" onclick="switchevent('<?php echo $eid; ?>/zmEventImages.html');return false;"><?php echo $eid; ?></a></div>
<div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div> <?php
<?php } # end if saveJPEGs
} } # end foreach event id
?> ?>
</div> </div>
<?php <?php
foreach ($monitors as $monitor) { foreach ($monitors as $monitor) {
echo "<div class='tab_content' id='tab$monitor'>"; echo "<div class=\"tab_content\" id=\"tab$monitor\">";
echo "<h2>Monitor: " . $monitorNames[$monitor] . " </h2>"; echo '<h2>Monitor: ' . $monitorNames[$monitor] . ' </h2>';
foreach ($eids as $eid) { foreach ( $eids as $eid ) {
if ($eventMonitorId[$eid] == $monitor) { if ( $eventMonitorId[$eid] == $monitor ) {
?> ?>
<div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div> <div><a href="#" onclick="switchevent('<?php echo $eid; ?>/zmEventImages.html');return false;"><?php echo $eid; ?></a></div>
<?php <?php
}
} }
echo'</div>';
} }
?> echo '</div>';
} # end foreach monitor
</td><td> ?>
</td><td>
<iframe id="myframe" onload="resizeCaller();" name="myframe" src="#" <iframe id="myframe" onload="resizeCaller();" name="myframe" src="#"
scrolling="no" marginwidth="0" marginheight="0" frameborder="0" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"
vspace="0" hspace="0" style="overflow:visible; width:100%; display:none"> vspace="0" hspace="0" style="overflow:visible; width:100%; display:none">
</iframe> </iframe>
</td>
</td> </tr>
</tr></table> </table>
<script type="text/javascript"> <script type="text/javascript">
function switchevent(src) { function switchevent(src) {
if(document.all) document.all.myframe.src = src; $('#myframe').attr('src',src);
else window.frames['myframe'].location.href = src; $('#myframe').show();
} }
/*********************************************** /***********************************************
@ -674,72 +676,72 @@ function switchevent(src) {
//Input the IDs of the IFRAMES you wish to dynamically resize to match its content height: //Input the IDs of the IFRAMES you wish to dynamically resize to match its content height:
//Separate each ID with a comma. Examples: ["myframe1", "myframe2"] or ["myframe"] or [] for none: //Separate each ID with a comma. Examples: ["myframe1", "myframe2"] or ["myframe"] or [] for none:
var iframeids=["myframe"] var iframeids=["myframe"];
//Should script hide iframe from browsers that don't support this script (non IE5+/NS6+ browsers. Recommended): //Should script hide iframe from browsers that don't support this script (non IE5+/NS6+ browsers. Recommended):
var iframehide="yes" var iframehide="yes";
var getFFVersion=navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox")).split("/")[1] var getFFVersion=navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox")).split("/")[1];
var FFextraHeight=parseFloat(getFFVersion)>=0.1? 16 : 0 //extra height in px to add to iframe in FireFox 1.0+ browsers var FFextraHeight=parseFloat(getFFVersion)>=0.1? 16 : 0; //extra height in px to add to iframe in FireFox 1.0+ browsers
function resizeCaller() { function resizeCaller() {
var dyniframe=new Array() var dyniframe=new Array();
for (i=0; i<iframeids.length; i++){ for (i=0; i<iframeids.length; i++){
if (document.getElementById) resizeIframe(iframeids[i]); if (document.getElementById) resizeIframe(iframeids[i]);
//reveal iframe for lower end browsers? (see var above): //reveal iframe for lower end browsers? (see var above):
if ((document.all || document.getElementById) && iframehide=="no"){ if ( (document.all || document.getElementById) && iframehide=="no" ) {
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i]) var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i]);
tempobj.style.display="block" tempobj.style.display="block";
} }
} }
} }
function resizeIframe(frameid){ function resizeIframe(frameid) {
var currentfr=document.getElementById(frameid) var currentfr = document.getElementById(frameid);
if (currentfr && !window.opera){ if ( currentfr && !window.opera ) {
currentfr.style.display="block" currentfr.style.display = "block";
if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) //ns6 syntax if ( currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight ) //ns6 syntax
currentfr.height = currentfr.contentDocument.body.offsetHeight+FFextraHeight; currentfr.height = currentfr.contentDocument.body.offsetHeight+FFextraHeight;
else if (currentfr.Document && currentfr.Document.body.scrollHeight) //ie5+ syntax else if ( currentfr.Document && currentfr.Document.body.scrollHeight ) //ie5+ syntax
currentfr.height = currentfr.Document.body.scrollHeight; currentfr.height = currentfr.Document.body.scrollHeight;
if (currentfr.addEventListener) currentfr.addEventListener("load", readjustIframe, false);
else if (currentfr.attachEvent){ if ( currentfr.addEventListener ) {
currentfr.detachEvent("onload", readjustIframe) // Bug fix line currentfr.addEventListener("load", readjustIframe, false);
currentfr.attachEvent("onload", readjustIframe) } else if ( currentfr.attachEvent ) {
currentfr.detachEvent("onload", readjustIframe); // Bug fix line
currentfr.attachEvent("onload", readjustIframe);
} }
} }
} }
function readjustIframe(loadevt) { function readjustIframe(loadevt) {
var crossevt=(window.event)? event : loadevt; var crossevt = window.event ? event : loadevt;
var iframeroot=(crossevt.currentTarget)? crossevt.currentTarget : crossevt.srcElement var iframeroot = crossevt.currentTarget ? crossevt.currentTarget : crossevt.srcElement;
if (iframeroot) resizeIframe(iframeroot.id); if (iframeroot) resizeIframe(iframeroot.id);
} }
function loadintoIframe(iframeid, url){ function loadintoIframe(iframeid, url) {
if (document.getElementById) document.getElementById(iframeid).src=url; if (document.getElementById) document.getElementById(iframeid).src=url;
} }
//if (window.addEventListener) window.addEventListener("load", resizeCaller, false) //if (window.addEventListener) window.addEventListener("load", resizeCaller, false)
//else if (window.attachEvent) window.attachEvent("onload", resizeCaller) //else if (window.attachEvent) window.attachEvent("onload", resizeCaller)
//else window.onload=resizeCaller //else window.onload=resizeCaller
</script>
</script> </body>
</body>
</html> </html>
<?php <?php
return( ob_get_clean() ); return ob_get_clean();
} }
function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) { function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc) {
if ( (!canView('Events')) or ! $eid ) { if ( !canView('Events') or !$event ) {
return; return;
} }
$event = new Event($eid); $eventPath = $event->Path();
$eventPath = $event->Path(); $eventRelativePath = $event->Relative_Path();
$files = array(); $files = array();
if ( $dir = opendir($eventPath) ) { if ( $dir = opendir($eventPath) ) {
while ( ($file = readdir($dir)) !== false ) { while ( ($file = readdir($dir)) !== false ) {
@ -754,29 +756,29 @@ function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exp
if ( $exportDetail ) { if ( $exportDetail ) {
$file = 'zmEventDetail.html'; $file = 'zmEventDetail.html';
if ( !($fp = fopen( $eventPath.'/'.$file, 'w' )) ) { if ( !($fp = fopen($eventPath.'/'.$file, 'w')) ) {
Fatal( "Can't open event detail export file '$file'" ); Fatal("Can't open event detail export file '$file'");
} }
fwrite( $fp, exportEventDetail( $event, $exportFrames, $exportImages ) ); fwrite($fp, exportEventDetail($event, $exportFrames, $exportImages));
fclose( $fp ); fclose($fp);
$exportFileList[$file] = $eventPath."/".$file; $exportFileList[$file] = $event->Id().'/'.$file;
} }
if ( $exportFrames ) { if ( $exportFrames ) {
$file = 'zmEventFrames.html'; $file = 'zmEventFrames.html';
if ( !($fp = fopen( $eventPath.'/'.$file, 'w' )) ) { if ( !($fp = fopen($eventPath.'/'.$file, 'w')) ) {
Fatal( "Can't open event frames export file '$file'" ); Fatal("Can't open event frames export file '$file'");
} }
fwrite( $fp, exportEventFrames( $event, $exportDetail, $exportImages ) ); fwrite($fp, exportEventFrames($event, $exportDetail, $exportImages));
fclose( $fp ); fclose($fp);
$exportFileList[$file] = $eventPath."/".$file; $exportFileList[$file] = $event->Id().'/'.$file;
} }
if ( $exportImages ) { if ( $exportImages ) {
$filesLeft = array(); $filesLeft = array();
$myfilelist = array(); $myfilelist = array();
foreach ( $files as $file ) { foreach ( $files as $file ) {
if ( preg_match( '/-(?:capture|analyse).jpg$/', $file ) ) { if ( preg_match('/-(?:capture|analyse).jpg$/', $file ) ) {
$exportFileList[$file] = $eventPath."/".$file; $myfilelist[$file] = $exportFileList[$file] = $event->Id().'/'.$file;
$myfilelist[$file] = $eventPath."/".$file;
} else { } else {
$filesLeft[$file] = $file; $filesLeft[$file] = $file;
} }
@ -785,109 +787,160 @@ function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exp
// create an image slider // create an image slider
if ( !empty($myfilelist) ) { if ( !empty($myfilelist) ) {
$file = 'zmEventImages.html'; $file = $event->Id().'/zmEventImages.html';
if ( !($fp = fopen($eventPath.'/'.$file, 'w')) ) Fatal( "Can't open event images export file '$file'" ); if ( !($fp = fopen($file, 'w')) )
fwrite( $fp, exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist ) ); Fatal("Can't open event images export file '$file'");
fclose( $fp ); fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist));
$exportFileList[$file] = $eventPath."/".$file; fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file;
} }
} # end if exportImages } # end if exportImages
if ( $exportVideo ) { if ( $exportVideo ) {
$filesLeft = array(); $filesLeft = array();
foreach ( $files as $file ) { foreach ( $files as $file ) {
if ( preg_match( '/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file ) ) { if ( preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file) ) {
$exportFileList[$file] = $eventPath.'/'.$file; $exportFileList[$file] = $event->Id().'/'.$file;
} else { } else {
$filesLeft[$file] = $file; $filesLeft[$file] = $file;
} }
} }
$files = $filesLeft; $files = $filesLeft;
} # end if exportVideo } # end if exportVideo
if ( $exportMisc ) { if ( $exportMisc ) {
foreach ( $files as $file ) { foreach ( $files as $file ) {
$exportFileList[$file] = $eventPath.'/'.$file; $exportFileList[$file] = $event->Id().'/'.$file;
} }
$files = array(); $files = array();
} }
return array_values($exportFileList); return array_values($exportFileList);
} } # end exportFileList()
function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat, $exportStructure = false ) { function exportEvents(
$eids,
$connkey,
$exportDetail,
$exportFrames,
$exportImages,
$exportVideo,
$exportMisc,
$exportFormat,
$exportStructure = false
) {
if ( (!canView('Events')) || empty($eids) ) { if ( !canView('Events') ) {
Error("You do not have permission to view events.");
return false;
} else if ( empty($eids) ) {
Error("Attempt to export an empty list of events.");
return false; return false;
} }
# Ensure that we are going to be able to do this.
if ( ! file_exists(ZM_DIR_EXPORTS) ) {
if ( ! mkdir(ZM_DIR_EXPORTS) ) {
Fatal("Can't create exports dir at '".ZM_DIR_EXPORTS."'");
}
}
$export_dir = ZM_DIR_EXPORTS.'/zmExport_'.$connkey;
# Ensure that we are going to be able to do this.
if ( ! file_exists($export_dir) ) {
if ( ! mkdir($export_dir) ) {
Fatal("Can't create exports dir at '$export_dir'");
} else {
Logger::Debug("Successfully created dir '$export_dir'");
}
}
if ( !chdir($export_dir) )
Fatal("Can't chdir to $export_dir");
$export_root = 'zmExport'; $export_root = 'zmExport';
$export_listFile = 'zmFileList.txt'; $export_listFile = 'zmFileList.txt';
$exportFileList = array(); $exportFileList = array();
$html_eventMaster = ''; $html_eventMaster = '';
if ( is_array($eids) ) { if ( !is_array($eids) ) {
foreach ( $eids as $eid ) { $eids = array($eids);
$exportFileList = array_merge( $exportFileList, exportFileList( $eid , $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) );
}
} else {
$eid = $eids;
$exportFileList = exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc );
} }
foreach ( $eids as $eid ) {
// create an master image slider $event = new Event($eid);
if ( $exportImages ) { $event_dir = $export_dir.'/'.$event->Id();
if ( !is_array($eids) ) { if ( !mkdir($event_dir) )
$eids = array($eids); Error("Can't mkdir $event_dir");
$event_exportFileList = exportFileList($event, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc);
$exportFileList = array_merge($exportFileList,$event_exportFileList);
foreach ( $event_exportFileList as $file ) {
if ( preg_match('/\.html$/', $file ) )
continue;
Logger::Debug('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file);
exec('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file);
} }
$monitorPath = ZM_DIR_EVENTS.'/';
$html_eventMaster = 'zmEventImagesMaster_'.date('Ymd_His'). '.html';
if ( !($fp = fopen( $monitorPath.'/'.$html_eventMaster, 'w' )) ) Fatal( "Can't open event images export file '$html_eventMaster'" );
fwrite($fp, exportEventImagesMaster($eids));
fclose($fp);
$exportFileList[] = $monitorPath.'/'.$html_eventMaster;
} }
$listFile = ZM_DIR_EXPORTS.'/'.$export_listFile; // create an master image
if ( $exportImages ) {
if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/jquery.js', $export_dir.'/jquery.js') )
Error("Failed linking jquery.js");
//if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/video.js', $export_dir.'/video.js') )
//Error("Failed linking video.js");
$html_eventMaster_file = 'zmEventImagesMaster_'.date('Ymd_His'). '.html';
$html_eventMaster_path = $export_dir.'/'.$html_eventMaster_file;
if ( ($fp = fopen($html_eventMaster_path, 'w')) ) {
fwrite($fp, exportEventImagesMaster($eids));
fclose($fp);
$exportFileList[] = $html_eventMaster_file;
} else {
Error("Can't open event images export file '$html_eventMaster_path'");
}
}
$listFile = $export_dir.'/'.$export_listFile;
if ( !($fp = fopen($listFile, 'w')) ) { if ( !($fp = fopen($listFile, 'w')) ) {
Fatal( "Can't open event export list file '$listFile'" ); Fatal("Can't open event export list file '$listFile'");
} }
foreach ( $exportFileList as $exportFile ) { foreach ( $exportFileList as $exportFile ) {
fwrite( $fp, "$exportFile\n" ); $exportFile = 'zmExport'.$connkey.'/'.$exportFile;
fwrite($fp, "$exportFile\n");
} }
fclose( $fp ); fwrite($fp, "$listFile\n");
fclose($fp);
chdir(ZM_DIR_EXPORTS);
$archive = ''; $archive = '';
if ( $exportFormat == 'tar' ) { if ( $exportFormat == 'tar' ) {
$archive = ZM_DIR_EXPORTS.'/'.$export_root.'.tar.gz'; $archive = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'').'.tar.gz';
@unlink( $archive ); @unlink($archive);
if ( $exportStructure == 'flat' ) { //strip file paths if we choose $command = 'nice -10 tar --create --gzip --dereference --file='.escapeshellarg($archive).' zmExport_'.$connkey.'/';
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile)." --xform='s#^.+/##x'"; #$command = 'nice -10 tar --create --gzip --file='.escapeshellarg($archive).' --files-from='.escapeshellarg($listFile);
} else { if ( $exportStructure == 'flat' ) {
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile); //strip file paths if we
} $command .= " --xform='s#^.+/##x'";
exec( $command, $output, $status );
if ( $status ) {
Error( "Command '$command' returned with status $status" );
if ( $output[0] )
Error( "First line of output is '".$output[0]."'" );
return( false );
} }
} elseif ( $exportFormat == 'zip' ) { } elseif ( $exportFormat == 'zip' ) {
$archive = ZM_DIR_EXPORTS.'/'.$export_root.'.zip'; $archive = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'').'.zip';
@unlink( $archive ); @unlink($archive);
if ($exportStructure == 'flat') { if ( $exportStructure == 'flat' ) {
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q -j ".escapeshellarg($archive)." -@"; $command = 'nice -10 zip -j '.escapeshellarg($archive).' zmExport_'.$connkey.'/';
#$command = 'cat '.escapeshellarg($listFile).' | nice -10 zip -q -j '.escapeshellarg($archive).' -@';
} else { } else {
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q ".escapeshellarg($archive)." -@"; $command = 'nice -10 zip -r '.escapeshellarg($archive).' zmExport_' . $connkey.'/';
} #$command = 'cat '.escapeshellarg($listFile).' | nice -10 zip -q '.escapeshellarg($archive).' -@';
//cat zmFileList.txt | zip -q zm_export.zip -@
//-bash: zip: command not found
exec( $command, $output, $status );
if ( $status ) {
Error("Command '$command' returned with status $status");
if ( $output[0] )
Error("First line of output is '".$output[0]."'");
return false;
} }
} else {
Error("No exportFormat specified.");
return false;
} // if $exportFormat
Logger::Debug("Command is $command");
exec($command, $output, $status);
if ( $status ) {
Error("Command '$command' returned with status $status");
if ( isset($output[0]) )
Error("First line of output is '".$output[0]."'");
return false;
} }
//clean up temporary files //clean up temporary files
@ -895,5 +948,5 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo
unlink($monitorPath.'/'.$html_eventMaster); unlink($monitorPath.'/'.$html_eventMaster);
} }
return '?view=archive%26type='.$exportFormat; return '?view=archive%26type='.$exportFormat.'%26connkey='.$connkey;
} }

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