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:
- 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/)
**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(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
set(ZM_PID "${ZM_RUNDIR}/zm.pid")
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)
[![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
## Overview

View File

@ -518,6 +518,7 @@ CREATE TABLE `Monitors` (
`ArchivedEvents` int(10) default NULL,
`ArchivedEventDiskSpace` bigint default NULL,
`ZoneCount` TINYINT NOT NULL DEFAULT 0,
`Refresh` int(10) unsigned default NULL,
PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -560,7 +561,7 @@ CREATE TABLE `Servers` (
`Name` varchar(64) NOT NULL default '',
`State_Id` int(10) unsigned,
`Status` enum('Unknown','NotRunning','Running') NOT NULL default 'Unknown',
`Load` DECIMAL(5,1),
`CpuLoad` DECIMAL(5,1) default NULL,
`TotalMem` bigint unsigned default null,
`FreeMem` 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-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,'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
--

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;
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(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()

View File

@ -16,7 +16,7 @@ SET @s = (SELECT IF(
AND column_name = 'Refresh'
) > 0,
"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;

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)
, libbz2-dev
, ffmpeg | libav-tools
, net-tools
, libnetpbm10-dev
, libvlccore-dev, libvlc-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(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
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 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}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
# Mootools is under the MIT license: http://mootools.net/
License: GPLv2+ and LGPLv2+ and MIT
URL: http://www.zoneminder.com/
@ -141,7 +140,7 @@ fi
%files
%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
%config %attr(640,root,%{zmgid_final}) /etc/zm.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)
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
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(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(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:
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
============

View File

@ -4,6 +4,11 @@ What's New
1. See the ZoneMinder release notes for a list of new features:
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
============
@ -80,7 +85,7 @@ New installs
When in doubt, proceed with the default:
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:

View File

@ -1,5 +1,5 @@
D @ZM_TMPDIR@ 0755 @WEB_USER@ @WEB_GROUP@
D @ZM_SOCKDIR@ 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@

View File

@ -26,11 +26,10 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.31.43
Version: 1.31.45
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
# Mootools is inder the MIT license: http://mootools.net/
# CakePHP is under the MIT license: https://github.com/cakephp/cakephp
# Crud is under the MIT license: https://github.com/FriendsOfCake/crud
@ -53,6 +52,7 @@ BuildRequires: pcre-devel
BuildRequires: libjpeg-turbo-devel
BuildRequires: findutils
BuildRequires: coreutils
BuildRequires: net-tools
BuildRequires: perl
BuildRequires: perl-generators
BuildRequires: perl(Archive::Tar)
@ -74,8 +74,11 @@ BuildRequires: gcc-c++
BuildRequires: vlc-devel
BuildRequires: libcurl-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: desktop-file-utils
# Required for mp4 container support
BuildRequires: libmp4v2-devel
@ -89,6 +92,7 @@ BuildRequires: x264-devel
Requires: php-mysqli
Requires: php-common
Requires: php-gd
%{?fedora:Requires: php-json}
Requires: php-pecl-apcu
%{?with_apcu_bc:Requires: php-pecl-apcu-bc}
Requires: cambozola
@ -248,7 +252,7 @@ EOF
%files
%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
# 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
Alias /zm/cache /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>
Alias /zm /usr/share/zoneminder/www
@ -45,4 +55,3 @@ Alias /zm /usr/share/zoneminder/www
RewriteRule ^ index.php [L]
RewriteBase /zm/api
</Directory>

View File

@ -9,7 +9,17 @@ ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
# Order matters. This alias must come first.
Alias /zm/cache /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>
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~)
,libavutil-dev (>= 6:10~)
,libswscale-dev (>= 6:10~)
,ffmpeg | libav-tools
,net-tools
,libbz2-dev
,libgcrypt-dev | libgcrypt11-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)
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
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
@ -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)
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.
@ -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
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:
::
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)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You will see each URL ending in either ``.xml`` or ``.json``. This is the
format of the request, and it determines the format that any data returned to
you will be in. I like json, however you can use xml if you'd like.
Please 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.
(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',
default => 'yes',
default => 'no',
description => 'Send usage information to ZoneMinder',
help => q`
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
X-Frame-Options set to sameorigin in the header, the site will
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
plugin or extension to ignore X-Frame headers, and then the page will
display properly. Once the plugin or extenstion has ben installed,
@ -2963,6 +2963,37 @@ our @options = (
type => $types{boolean},
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',
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}
);
};
if ( !$dbh or $@ ) {
if ( !$dbh or $@ ) {
Error("Error reconnecting to db: errstr:$DBI::errstr error val:$@");
} else {
$dbh->{AutoCommit} = 1;

View File

@ -347,14 +347,14 @@ sub delete {
my $event = $_[0];
if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartTime} ) ) {
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;
}
if ( ! -e $event->Storage()->Path() ) {
Warning("Not deleting event because storage path doesn't exist");
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->begin_work();
@ -362,9 +362,9 @@ sub delete {
{
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() );
my $res = $sth->execute( $event->{Id} )
my $res = $sth->execute($event->{Id})
or Error( "Can't execute '$sql': ".$sth->errstr() );
$sth->finish();
if ( $ZoneMinder::Database::dbh->errstr() ) {
@ -373,10 +373,10 @@ sub delete {
}
$sql = 'DELETE FROM Stats WHERE EventId=?';
$sth = $ZoneMinder::Database::dbh->prepare_cached( $sql )
or Error( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
$res = $sth->execute( $event->{Id} )
or Error( "Can't execute '$sql': ".$sth->errstr() );
$sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
or Error("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr());
$res = $sth->execute($event->{Id})
or Error("Can't execute '$sql': ".$sth->errstr());
$sth->finish();
if ( $ZoneMinder::Database::dbh->errstr() ) {
$ZoneMinder::Database::dbh->commit();
@ -387,10 +387,10 @@ sub delete {
# Do it individually to avoid locking up the table for new events
{
my $sql = 'DELETE FROM Events WHERE Id=?';
my $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql )
or Error( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
my $res = $sth->execute( $event->{Id} )
or Error( "Can't execute '$sql': ".$sth->errstr() );
my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
or Error("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr());
my $res = $sth->execute($event->{Id})
or Error("Can't execute '$sql': ".$sth->errstr());
$sth->finish();
}
$ZoneMinder::Database::dbh->commit();
@ -602,7 +602,7 @@ Debug("Files to move @files");
die "Unable to add key for $filename";
}
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.
$moved = 1;

View File

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

View File

@ -557,8 +557,8 @@ our $hasJSONAny = 0;
sub _testJSON {
return if ( $testedJSON );
my $result = eval {
require JSON::Any;
JSON::Any->import();
require JSON::MaybeXS;
JSON::MaybeXS->import();
};
$testedJSON = 1;
$hasJSONAny = 1 if ( $result );
@ -581,7 +581,7 @@ sub jsonEncode {
_testJSON();
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 );
return( $string );
}
@ -616,7 +616,7 @@ sub jsonDecode {
_testJSON();
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 );
return( $object );
}

View File

@ -198,6 +198,7 @@ sub initialise( @ ) {
my $this = shift;
my %options = @_;
$this->{hasTerm} = -t STDERR;
$this->{id} = $options{id} if defined($options{id});
$this->{logPath} = $options{logPath} if defined($options{logPath});
@ -245,7 +246,8 @@ sub initialise( @ ) {
$tempSyslogLevel = $level if defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG'));
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}
|| $target eq '_'.$this->{id}
|| $target eq $this->{idRoot}
@ -278,6 +280,9 @@ sub initialise( @ ) {
$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}}
.'/'.$codes{$this->{effectiveLevel}}
.', screen='.$codes{$this->{termLevel}}
@ -319,6 +324,8 @@ sub reinitialise {
my $screenLevel = $this->termLevel();
$this->termLevel(NOLOG);
$this->termLevel($screenLevel) if $screenLevel > NOLOG;
$this->{sth} = undef;
}
# 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.
#$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};
}
@ -474,7 +487,7 @@ sub openSyslog {
sub closeSyslog {
my $this = shift;
#closelog();
closelog();
}
sub logFile {
@ -517,54 +530,59 @@ sub logPrint {
if ( $level <= $this->{effectiveLevel} ) {
$string =~ s/[\r\n]+$//g;
my $code = $codes{$level};
if ( $level <= $this->{syslogLevel} ) {
syslog($priorities{$level}, $codes{$level}.' [%s]', $string);
}
my ($seconds, $microseconds) = gettimeofday();
my $message = sprintf(
'%s.%06d %s[%d].%s [%s]'
, strftime('%x %H:%M:%S', localtime($seconds))
, $microseconds
, $this->{id}
, $$
, $code
, $string
);
if ( $this->{trace} ) {
$message = Carp::shortmess($message);
} else {
$message = $message."\n";
if ( $level <= $this->{fileLevel} or $level <= $this->{termLevel} ) {
my $message = sprintf(
'%s.%06d %s[%d].%s [%s]'
, strftime('%x %H:%M:%S', localtime($seconds))
, $microseconds
, $this->{id}
, $$
, $codes{$level}
, $string
);
if ( $this->{trace} ) {
$message = Carp::shortmess($message);
} 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 ( ( $this->{dbh} and $this->{dbh}->ping() ) or ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) {
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->{dbh} and $this->{dbh}->ping() ) ) {
$this->{sth} = undef;
if ( ! ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) {
#print(STDERR "Can't log to database: ");
$this->{databaseLevel} = NOLOG;
Error("Can't prepare log entry '$sql': ".$this->{dbh}->errstr());
} 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());
}
return;
}
} 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 level < effectivelevel

View File

@ -252,36 +252,37 @@ MAIN: while( $loop ) {
foreach my $day_dir ( @day_dirs ) {
Debug( "Checking day dir $day_dir" );
( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint
if ( ! chdir( $day_dir ) ) {
Error( "Can't chdir to '$$Storage{Path}/$day_dir': $!" );
if ( !chdir($day_dir) ) {
Error("Can't chdir to '$$Storage{Path}/$day_dir': $!");
next;
}
if ( ! opendir( DIR, '.' ) ) {
Error( "Can't open directory '$$Storage{Path}/$day_dir': $!" );
if ( ! opendir(DIR, '.') ) {
Error("Can't open directory '$$Storage{Path}/$day_dir': $!");
next;
}
my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR );
closedir( DIR );
Debug("Have " . @event_links . ' event links');
closedir(DIR);
my $count = 0;
foreach my $event_link ( @event_links ) {
if ( $event_link =~ /[^\d\.]/ ) {
Warning("Non-event link found $event_link in $day_dir, skipping");
next;
}
Debug( "Checking link $event_link" );
Debug("Checking link $event_link");
( my $event = $event_link ) =~ s/^.*\.//;
#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) ) {
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() ) {
( $event_link ) = ( $event_link =~ /^(.*)$/ ); # De-taint
unlink( $event_link );
unlink($event_link);
$cleaned = 1;
}
} 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();
$$Event{Id} = $event;
$$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path);
@ -292,6 +293,42 @@ MAIN: while( $loop ) {
$Event->DiskSpace( undef );
} # event path exists
} # 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() );
} # end foreach day dir
}
@ -701,17 +738,18 @@ FROM Frames WHERE EventId=?';
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^(.*)s$/ ) {
$Config{ZM_LOG_DATABASE_LIMIT} = $1;
}
my $deleteLogByTimeSql =
'DELETE low_priority FROM Logs
WHERE TimeKey < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.')';
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() );
$res = $deleteLogByTimeSth->execute()
or Fatal( "Can't execute: ".$deleteLogByTimeSth->errstr() );
if ( $deleteLogByTimeSth->rows() ){
aud_print( 'Deleted '.$deleteLogByTimeSth->rows()
." log table entries by time\n" );
}
my $deleted_rows;
do {
my $deleteLogByTimeSql =
'DELETE FROM Logs
WHERE TimeKey < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 10';
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() );
$res = $deleteLogByTimeSth->execute()
or Fatal( "Can't execute: ".$deleteLogByTimeSth->errstr() );
$deleted_rows = $deleteLogByTimeSth->rows();
aud_print( "Deleted $deleted_rows log table entries by time\n" );
} while ( $deleted_rows );
}
} # end if ZM_LOG_DATABASE_LIMIT
$loop = $continuous;

View File

@ -119,13 +119,13 @@ if ( $command eq 'version' ) {
}
my $needs_daemon = $command !~ /(?:startup|shutdown|status|check|logrot|version)/;
my $daemon = shift @ARGV;
if ( $needs_daemon && ! $daemon ) {
if ( $needs_daemon && !$daemon ) {
print(STDERR "No daemon given\n");
pod2usage(-exitstatus => -1);
}
my @args;
my $daemon_patt = '('.join( '|', @daemons ).')';
my $daemon_patt = '('.join('|', @daemons).')';
if ( $needs_daemon ) {
if ( $daemon =~ /^${daemon_patt}$/ ) {
$daemon = $1;
@ -139,7 +139,7 @@ foreach my $arg ( @ARGV ) {
# Detaint arguments, if they look ok
#if ( $arg =~ /^(-{0,2}[\w]+)/ )
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
push( @args, $1 );
push @args, $1;
} else {
print(STDERR "Bogus argument '$arg' found");
exit(-1);
@ -172,7 +172,7 @@ if ( !$server_up ) {
exit();
} elsif ( $command ne 'startup' ) {
print("Unable to connect to server using socket at " . SOCK_FILE . "\n");
exit( -1 );
exit(-1);
}
# The server isn't there
@ -210,7 +210,7 @@ if ( ($command eq 'check') && !$daemon ) {
# The server is there, connect to it
CLIENT->autoflush();
my $message = join(';', $command, ( $daemon ? $daemon : () ), @args );
my $message = join(';', $command, ( $daemon ? $daemon : () ), @args);
print(CLIENT $message);
shutdown(CLIENT, 1);
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 %pid_hash;
our %terminating_processes;
our %pids_to_reap;
our $zm_terminate = 0;
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;
# THis also closes dbh and CLIENT and SERVER
while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
POSIX::close($fd++);
}
setpgrp();
# dbh got closed with the rest of the fd's above, so need to reconnect.
my $dbh = zmDbConnect(1);
logInit();
dPrint(ZoneMinder::Logger::INFO, 'Server starting at '
@ -259,24 +274,16 @@ sub run {
."\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
killAll(1);
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: $!");
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 . ": $!");
listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
$SIG{CHLD} = \&reaper;
$SIG{CHLD} = \&chld_sig_handler;
$SIG{INT} = \&shutdown_sig_handler;
$SIG{TERM} = \&shutdown_sig_handler;
$SIG{ABRT} = \&shutdown_sig_handler;
@ -287,35 +294,28 @@ sub run {
my $win = $rin;
my $ein = $win;
my $timeout = 1;
my $Server = undef;
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 ) {
if ( $Config{ZM_SERVER_ID} ) {
if ( ! ( $secs_count % 60 ) ) {
Debug("Connecting");
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();
}
last if $zm_terminate;
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,
'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;
}
my $nfound = select(my $rout = $rin, undef, undef, $timeout);
Debug("Aftere select $nfound");
if ( $nfound > 0 ) {
if ( vec($rout, fileno(SERVER), 1) ) {
my $paddr = accept(CLIENT, SERVER);
@ -337,7 +337,7 @@ Debug("Aftere select $nfound");
# Do nothing, this is all we're here for
dPrint(ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n");
} elsif ( $command eq 'shutdown' ) {
# Breka out of while loop
# Break out of while loop
last;
} elsif ( $command eq 'check' ) {
check($daemon, @args);
@ -370,19 +370,17 @@ Debug("Aftere select $nfound");
#print( "Select timed out\n" );
}
Debug("restartPending");
restartPending();
Debug("check_for_processes_to_kill");
check_for_processes_to_kill();
check_for_processes_to_kill() if %terminating_processes;
reaper() if %pids_to_reap;
} # end while
dPrint(ZoneMinder::Logger::INFO, 'Server exiting at '
.strftime( '%y/%m/%d %H:%M:%S', localtime() )
.strftime('%y/%m/%d %H:%M:%S', localtime())
."\n"
);
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}) ) {
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 {
# One thought here, if no client exists to read these... does it block?
if ( fileno(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.
sub dPrint {
my $logLevel = shift;
if ( fileno(CLIENT) ) {
print CLIENT @_
}
cPrint(@_);
if ( $logLevel == ZoneMinder::Logger::DEBUG ) {
Debug(@_);
} elsif ( $logLevel == ZoneMinder::Logger::INFO ) {
@ -435,12 +432,14 @@ sub start {
my $sigset = POSIX::SigSet->new;
my $blockset = POSIX::SigSet->new(SIGCHLD);
Debug("Blocking 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() ) {
$dbh = zmDbConnect(1);
# This logReinit is required. Not sure why.
logReinit();
#logReinit();
$process->{pid} = $cpid;
$process->{started} = time();
@ -453,9 +452,10 @@ sub start {
$cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process;
sigprocmask(SIG_SETMASK, $sigset) or Fatal("Can't restore SIGCHLD: $!");
Debug("unblocking child");
} 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);
logReinit();
@ -472,7 +472,7 @@ sub start {
my @good_args;
foreach my $arg ( @args ) {
# Detaint arguments, if they look ok
# Detaint arguments, if they look ok
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
push @good_args, $1;
} else {
@ -488,8 +488,8 @@ sub start {
POSIX::close($fd++);
}
# Child process
$SIG{CHLD} = 'DEFAULT';
$SIG{HUP} = 'DEFAULT';
$SIG{INT} = 'DEFAULT';
$SIG{TERM} = 'DEFAULT';
$SIG{ABRT} = 'DEFAULT';
@ -516,7 +516,7 @@ sub send_stop {
.strftime('%y/%m/%d %H:%M:%S', localtime())
."\n"
);
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
return();
}
@ -635,15 +635,24 @@ sub shutdown_sig_handler {
$zm_terminate = 1;
}
sub reaper {
sub chld_sig_handler {
my $saved_status = $!;
# Wait for a child to terminate
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};
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 ) {
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 $$process{term_sent_at};
$process->{stopped} = time();
$process->{stopped} = $stopped;
$process->{runtime} = ($process->{stopped}-$process->{started});
delete $process->{pid};
@ -701,15 +710,12 @@ sub reaper {
$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 {
delete $cmd_hash{$$process{command}};
}
} # end while waitpid
$SIG{CHLD} = \&reaper;
$! = $saved_status;
Debug("Leaving reaper");
}
} # end foreach pid_to_reap
} # end sub reaper
sub restartPending {
# 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}});
}
}
Debug("done restartPending");
}
sub shutdownAll {
@ -730,6 +735,8 @@ sub shutdownAll {
send_stop(1, $pid_hash{$pid});
}
while ( keys %terminating_processes ) {
reaper() if %pids_to_reap;
check_for_processes_to_kill();
if ( %terminating_processes ) {
Debug("Still " . %terminating_processes . ' to die. sleeping');
@ -808,7 +815,7 @@ sub status {
foreach my $process ( values %cmd_hash ) {
if ( $process->{pending} ) {
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"
);
}

View File

@ -70,16 +70,18 @@ use Getopt::Long;
use autouse 'Pod::Usage'=>qw(pod2usage);
use autouse 'Data::Dumper'=>qw(Dumper);
my $daemon = 0;
my $filter_name = '';
my $filter_id;
my $version = 0;
my $zm_terminate = 0;
GetOptions(
'filter=s' =>\$filter_name,
'filter_id=s' =>\$filter_id,
'version' =>\$version
) or pod2usage(-exitstatus => -1);
daemon =>\$daemon,
'filter=s' =>\$filter_name,
'filter_id=s' =>\$filter_id,
version =>\$version
) or pod2usage(-exitstatus => -1);
if ( $version ) {
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):());
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();
}
sub TermHandler {
Info("Received TERM, exiting");
Info('Received TERM, exiting');
$zm_terminate = 1;
}
sub Term {
exit( 0 );
exit(0);
}
$SIG{HUP} = \&HupHandler;
$SIG{TERM} = \&TermHandler;
@ -173,7 +181,7 @@ if ( $filter_name ) {
}
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);
}
@ -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");
sleep($delay);
@ -265,8 +273,7 @@ sub checkFilter {
Info(
join(' ',
'Checking filter', $filter->{Name},
join( ', ',
join(', ',
($filter->{AutoDelete}?'delete':()),
($filter->{AutoArchive}?'archive':()),
($filter->{AutoVideo}?'video':()),
@ -309,7 +316,7 @@ sub checkFilter {
}
if ( $Config{ZM_OPT_MESSAGE} && $filter->{AutoMessage} ) {
if ( !$event->{Messaged} ) {
$delete_ok = undef if !sendMessage($filter, $event);
$delete_ok = undef if !sendMessage($filter, $Event);
}
}
if ( $Config{ZM_OPT_UPLOAD} && $filter->{AutoUpload} ) {
@ -383,7 +390,7 @@ sub generateVideo {
$format = $ffmpeg_formats[0];
}
my $command = join( '',
my $command = join('',
$Config{ZM_PATH_BIN},
'/zmvideo.pl -e ',
$event->{Id},
@ -395,7 +402,7 @@ sub generateVideo {
$format,
);
my $output = qx($command);
chomp( $output );
chomp($output);
my $status = $? >> 8;
if ( $status || logDebugging() ) {
Debug("Output: $output\n");
@ -833,7 +840,7 @@ sub sendEmail {
sub sendMessage {
my $filter = shift;
my $event = shift;
my $Event = shift;
if ( ! $Config{ZM_FROM_EMAIL} ) {
Error('No from email address defined, not sending message');
@ -846,10 +853,10 @@ sub sendMessage {
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;
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;
Info("Sending notification message '$subject'");
@ -930,11 +937,11 @@ sub sendMessage {
my $sql = 'UPDATE Events SET Messaged = 1 WHERE Id = ?';
my $sth = $dbh->prepare_cached($sql)
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());
return 1;
}
} # end sub sendMessage
sub executeCommand {
my $filter = shift;

View File

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

View File

@ -33,6 +33,7 @@ use LWP::UserAgent;
use Sys::MemInfo qw(totalmem);
use Sys::CPU qw(cpu_count);
use POSIX qw(strftime uname);
use JSON::MaybeXS;
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$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
my %telemetry;
$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{monitor_count} = countQuery($dbh,'Monitors');
$telemetry{event_count} = countQuery($dbh,'Events');
@ -203,22 +204,25 @@ sub getUUID {
return $uuid;
}
# Retrieves the local server's external IP address
sub getIP {
my $ipaddr = '0.0.0.0';
# Retrieve this server's general location information from a GeoIP database
sub getGeo {
my $unknown = 'Unknown';
my $endpoint = 'https://ipinfo.io/geo';
my $ua = LWP::UserAgent->new;
my $server_endpoint = 'https://wiki.zoneminder.com/ip.php';
my $req = HTTP::Request->new(GET => $server_endpoint);
my $req = HTTP::Request->new(GET => $endpoint);
my $resp = $ua->request($req);
my $resp_msg = $resp->decoded_content;
my $resp_code = $resp->code;
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

View File

@ -173,6 +173,12 @@ my $cwd = getcwd;
my $video_name;
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 ) {
@event_ids = ( $event_id );

View File

@ -69,41 +69,44 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
logInit();
logSetSignal();
Info( "Watchdog starting, pausing for ".START_DELAY." seconds\n" );
sleep( START_DELAY );
Info('Watchdog starting, pausing for '.START_DELAY.' seconds');
sleep(START_DELAY);
my $dbh = zmDbConnect();
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr());
while( 1 ) {
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() ) {
my $now = time();
next if $monitor->{Function} eq 'None';
next if $monitor->{Type} eq 'WebSite';
my $now = time();
my $restart = 0;
if ( zmMemVerify( $monitor ) ) {
if ( zmMemVerify($monitor) ) {
# Check we have got an image recently
my $capture_time = zmGetLastWriteTime( $monitor );
my $capture_time = zmGetLastWriteTime($monitor);
if ( !defined($capture_time) ) {
# Can't read from shared data
Debug( "LastWriteTime is not defined." );
zmMemInvalidate( $monitor );
Debug('LastWriteTime is not defined.');
zmMemInvalidate($monitor);
next;
}
Debug( "LastWriteTime is = $capture_time." );
Debug("Monitor $$monitor{Id} LastWriteTime is $capture_time.");
if ( !$capture_time ) {
my $startup_time = zmGetStartupTime( $monitor );
my $startup_time = zmGetStartupTime($monitor);
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;
} else {
# 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;
}
}
@ -115,44 +118,44 @@ while( 1 ) {
: $Config{ZM_WATCH_MAX_DELAY}
;
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 ) {
Info( "Restarting capture daemon for "
.$monitor->{Name}.", time since last capture $image_delay seconds ($now-$capture_time)\n"
Info("Restarting capture daemon for "
.$monitor->{Name}.", time since last capture $image_delay seconds ($now-$capture_time)"
);
$restart = 1;
}
} # end if ! restart
} 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;
}
if ( $restart ) {
# 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.
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;
if ( $monitor->{Type} eq 'Local' ) {
$command = "zmdc.pl restart zmc -d $monitor->{Device}";
} else {
$command = "zmdc.pl restart zmc -m $monitor->{Id}";
}
runCommand( $command );
runCommand( "zmdc.pl start zma -m $$monitor{Id}" ) if $monitor->{Function} ne 'Monitor';
runCommand($command);
runCommand("zmdc.pl start zma -m $$monitor{Id}") if $monitor->{Function} ne 'Monitor';
} elsif ( $monitor->{Function} ne 'Monitor' ) {
# Now check analysis daemon
$restart = 0;
# Check we have got an image recently
my $image_time = zmGetLastReadTime( $monitor );
my $image_time = zmGetLastReadTime($monitor);
if ( !defined($image_time) ) {
# Can't read from shared data
$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 ) {
# We can't get the last capture time so can't be sure it's died.
$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 {
my $max_image_delay = ( $monitor->{MaxFPS}
@ -162,34 +165,34 @@ while( 1 ) {
: $Config{ZM_WATCH_MAX_DELAY}
;
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 ) {
Info( "Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting,"
." time since last analysis $image_delay seconds ($now-$image_time)\n"
Info("Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting,"
." time since last analysis $image_delay seconds ($now-$image_time)"
);
$restart = 1;
}
}
if ( $restart ) {
Info( "Restarting analysis daemon for $$monitor{Id} $$monitor{Name}\n");
Info("Restarting analysis daemon for $$monitor{Id} $$monitor{Name}\n");
my $command;
if ( $monitor->{Type} eq 'Local' ) {
$command = "zmdc.pl restart zmc -d $monitor->{Device}";
} else {
$command = "zmdc.pl restart zmc -m $monitor->{Id}";
}
runCommand( $command );
runCommand($command);
} # end if restart
} # end if check analysis daemon
# 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
sleep( $Config{ZM_WATCH_CHECK_INTERVAL} );
sleep($Config{ZM_WATCH_CHECK_INTERVAL});
} # end while (1)
Info( "Watchdog exiting\n" );
Info("Watchdog exiting");
exit();
1;

View File

@ -104,7 +104,10 @@ public:
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 PreCapture()=0;

View File

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

View File

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

View File

@ -67,7 +67,8 @@ Event::Event(
untimedEvent = true;
start_time = now;
} 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 = now;
@ -89,8 +90,8 @@ Event::Event(
snprintf(sql, sizeof(sql),
"INSERT INTO Events "
"( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme )"
" VALUES "
"( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '', %d, '%s' )",
" VALUES "
"( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '', %d, '%s' )",
monitor->Id(),
storage->Id(),
start_time.tv_sec,
@ -183,12 +184,13 @@ Event::Event(
}
// 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") )
fclose(id_fp);
else
Error("Can't fopen %s: %s", id_file.c_str(), strerror(errno));
} // deep storage or not
Debug(2,"Created event %d at %s", id, path.c_str());
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
bool rc;
Debug(3, "Writing image to %s", event_file );
Debug(3, "Writing image to %s", event_file);
if ( !config.timestamp_on_capture ) {
// 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++;
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 ) {
Debug(1, "Writing pre-capture frame %d", frames);
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,
// so I am changing this to 1, but we should overwrite it later with a better snapshot.
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());
}
}
@ -508,7 +510,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
frames++;
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 ) {
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
// On the first frame, max_score will be zero, this effectively makes us write out a thumbnail
// for the first frame as well.
if ( score > max_score ) {
std::string snapshot_file = std::string(path) + "/snapshot.jpg";
WriteFrameImage( image, timestamp, snapshot_file.c_str() );
if ( frames == 1 || score > (int)max_score ) {
std::string snapshot_file = path + "/snapshot.jpg";
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;
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 ) {
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>
bool Logger::smInitialised = false;
Logger *Logger::smInstance = 0;
Logger *Logger::smInstance = NULL;
Logger::StringMap Logger::smCodes;
Logger::IntMap Logger::smSyslogPriorities;
@ -59,9 +59,9 @@ static void subtractTime( struct timeval * const tp1, struct timeval * const tp2
void Logger::usrHandler( int sig ) {
Logger *logger = fetch();
if ( sig == SIGUSR1 )
logger->level( logger->level()+1 );
logger->level(logger->level()+1);
else if ( sig == SIGUSR2 )
logger->level( logger->level()-1 );
logger->level(logger->level()-1);
Info("Logger - Level changed to %d", logger->level());
}
@ -80,7 +80,7 @@ Logger::Logger() :
mFlush(false) {
if ( smInstance ) {
Panic( "Attempt to create second instance of Logger class" );
Panic("Attempt to create second instance of Logger class");
}
if ( !smInitialised ) {
@ -134,11 +134,11 @@ void Logger::initialise(const std::string &id, const Options &options) {
std::string tempLogFile;
if ( (envPtr = getTargettedEnv("LOG_FILE")) )
if ( (envPtr = getTargettedEnv("LOG_FILE")) ) {
tempLogFile = envPtr;
else if ( options.mLogFile.size() )
} else if ( options.mLogFile.size() ) {
tempLogFile = options.mLogFile;
else {
} else {
if ( options.mLogPath.size() ) {
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;
// Legacy
if ( (envPtr = getenv( "LOG_PRINT" )) )
if ( (envPtr = getenv("LOG_PRINT")) )
tempTerminalLevel = atoi(envPtr) ? DEBUG9 : NOLOG;
if ( (envPtr = getTargettedEnv("LOG_LEVEL")) )
@ -219,7 +219,7 @@ void Logger::initialise(const std::string &id, const Options &options) {
mFlush = false;
if ( (envPtr = getenv("LOG_FLUSH")) ) {
mFlush = atoi( envPtr );
mFlush = atoi(envPtr);
} else if ( config.log_debug ) {
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 )
Logger::smInstance = new Logger();
Logger::Options tempOptions = options;
tempOptions.mLogPath = staticConfig.PATH_LOGS;
Logger::smInstance->initialise( name, tempOptions );
Logger::smInstance->initialise(name, tempOptions);
}
void logTerm() {

View File

@ -890,6 +890,18 @@ bool Monitor::connect() {
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");
return true;
@ -1523,7 +1535,6 @@ bool Monitor::CheckSignal( const Image *image ) {
void Monitor::CheckAction() {
struct timeval now;
gettimeofday(&now, NULL);
if ( shared_data->action ) {
// Can there be more than 1 bit set in the action? Shouldn't these be elseifs?
if ( shared_data->action & RELOAD ) {
@ -1595,8 +1606,8 @@ bool Monitor::Analyse() {
// last_write_index is the last capture
// last_read_index is the last analysis
if ( ! Enabled() ) {
Warning("SHouldn't be doing Analyze when not Enabled");
if ( !Enabled() ) {
Warning("Shouldn't be doing Analyze when not Enabled");
return false;
}
@ -1726,7 +1737,7 @@ bool Monitor::Analyse() {
cause += ", ";
cause += LINKED_CAUSE;
}
noteSet.insert( linked_monitors[i]->Name() );
noteSet.insert(linked_monitors[i]->Name());
score += 50;
}
} // 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 -> %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);
if ( new_capture_fps != capture_fps ) {
capture_fps = new_capture_fps;
last_fps_time = now;
static char sql[ZM_SQL_SML_BUFSIZ];
db_mutex.lock();
snprintf(sql, sizeof(sql),
"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);
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
}
db_mutex.unlock();
} // end if fps has changed
capture_fps = new_capture_fps;
last_fps_time = now;
static char sql[ZM_SQL_SML_BUFSIZ];
db_mutex.lock();
snprintf(sql, sizeof(sql),
"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);
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
}
db_mutex.unlock();
}
} // end if report fps
} else { // result == 0

View File

@ -691,7 +691,7 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
} // end if buffered playback
frame_count++;
} 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 )
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);
hp = NULL;
}
if ( mAuthenticator ) {
delete mAuthenticator;
mAuthenticator = NULL;
}
}
void RemoteCamera::Initialise() {

View File

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

View File

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

View File

@ -27,15 +27,14 @@
namespace zm {
Authenticator::Authenticator( const std::string &username, const std::string &password) :
fCnonce( "0a4f113b" ),
fCnonce("0a4f113b"),
fUsername(username),
fPassword(password)
{
#ifdef HAVE_GCRYPT_H
// Special initialisation for libgcrypt
if ( !gcry_check_version( GCRYPT_VERSION ) )
{
Fatal( "Unable to initialise libgcrypt" );
if ( !gcry_check_version(GCRYPT_VERSION) ) {
Fatal("Unable to initialise libgcrypt");
}
gcry_control( GCRYCTL_DISABLE_SECMEM, 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);
// 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;
Debug( 2, "Set authMethod to Basic");
Debug(2, "Set authMethod to Basic");
}
// 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;
Debug( 2, "Set authMethod to Digest");
StringVector subparts = split(headerData.substr(digest_match_len, headerData.length() - digest_match_len), ",");
// subparts are key="value"
for ( size_t i = 0; i < subparts.size(); i++ )
{
StringVector kvPair = split( trimSpaces( subparts[i] ), "=" );
std::string key = trimSpaces( kvPair[0] );
if (key == "realm") {
fRealm = trimSet( kvPair[1], "\"");
for ( size_t i = 0; i < subparts.size(); i++ ) {
StringVector kvPair = split(trimSpaces(subparts[i]), "=");
std::string key = trimSpaces(kvPair[0]);
if ( key == "realm" ) {
fRealm = trimSet(kvPair[1], "\"");
continue;
}
if (key == "nonce") {
fNonce = trimSet( kvPair[1], "\"");
if ( key == "nonce" ) {
fNonce = trimSet(kvPair[1], "\"");
continue;
}
if (key == "qop") {
fQop = trimSet( kvPair[1], "\"");
if ( key == "qop" ) {
fQop = trimSet(kvPair[1], "\"");
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 result = "Authorization: ";
if (fAuthMethod == AUTH_BASIC)
{
if (fAuthMethod == AUTH_BASIC) {
result += "Basic " + base64Encode( username() + ":" + password() );
}
else if (fAuthMethod == AUTH_DIGEST)
{
} else if (fAuthMethod == AUTH_DIGEST) {
result += std::string("Digest ") +
"username=\"" + quote(username()) + "\", realm=\"" + quote(realm()) + "\", " +
"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_fingerprint( GNUTLS_DIG_MD5, &md5dataha1, md5buf, &md5len );
#endif
for ( unsigned int j = 0; j < md5len; j++ )
{
for ( unsigned int j = 0; j < md5len; j++ ) {
sprintf(&md5HexBuf[2*j], "%02x", md5buf[j] );
}
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_fingerprint( GNUTLS_DIG_MD5, &md5dataha2, md5buf, &md5len );
#endif
for ( unsigned int j = 0; j < md5len; j++ )
{
for ( unsigned int j = 0; j < md5len; j++ ) {
sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] );
}
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_fingerprint( GNUTLS_DIG_MD5, &md5datadigest, md5buf, &md5len );
#endif
for ( unsigned int j = 0; j < md5len; j++ )
{
for ( unsigned int j = 0; j < md5len; j++ ) {
sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] );
}
md5HexBuf[md5len*2]='\0';
return md5HexBuf;
#else // HAVE_DECL_MD5
Error( "You need to build with gnutls or openssl installed to use digest authentication" );
return( 0 );
Error("You need to build with gnutls or openssl installed to use digest authentication");
return 0;
#endif // HAVE_DECL_MD5
}
void Authenticator::checkAuthResponse(std::string &response) {
std::string authLine;
StringVector lines = split( response, "\r\n" );
StringVector lines = split(response, "\r\n");
const char* authenticate_match = "WWW-Authenticate:";
size_t authenticate_match_len = strlen(authenticate_match);

View File

@ -97,6 +97,15 @@ bool Mutex::locked() {
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 ) {
if ( pthread_cond_init( &mCondition, NULL ) < 0 )
Fatal( "Unable to create pthread condition: %s", strerror(errno) );

View File

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

View File

@ -376,7 +376,10 @@ int X264MP4Writer::x264config() {
x264params.b_annexb = 0;
/* 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) */
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->channels = audio_in_ctx->channels;
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 ) {
int found = 0;

View File

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

View File

@ -83,7 +83,7 @@ int main( int argc, char *argv[] ) {
while (1) {
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 ) {
break;
}
@ -144,7 +144,7 @@ int main( int argc, char *argv[] ) {
unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay();
time_t last_analysis_update_time, cur_time;
monitor->UpdateAdaptiveSkip();
last_analysis_update_time = time( 0 );
last_analysis_update_time = time(0);
while( (!zm_terminate) && monitor->ShmValid() ) {
// Process the next image
@ -181,5 +181,5 @@ int main( int argc, char *argv[] ) {
Image::Deinitialise();
logTerm();
zmDbClose();
return( 0 );
return 0;
}

View File

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

View File

@ -257,11 +257,14 @@ execpackpack () {
fi
if [ "${TRAVIS}" == "true" ]; then
utils/packpack/heartbeat.sh &
mypid=$!
packpack/packpack $parms > buildlog.txt 2>&1
kill $mypid
tail -n 3000 buildlog.txt | grep -v ONVIF
# Travis will fail the build if the output gets too long
# To mitigate that, use grep to filter out some of the noise
if [ "${ARCH}" != "armhf" ]; then
packpack/packpack $parms | grep -Ev '^(-- Installing:|-- Up-to-date:|Skip blib|Manifying|Installing /build|cp lib|writing output...|copying images...|reading sources...|[Working])'
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
packpack/packpack $parms
fi

View File

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

View File

@ -1 +1 @@
1.31.44
1.31.45

View File

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

View File

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

View File

@ -22,13 +22,9 @@ if ( sem_acquire($semaphore,1) !== false ) {
if ( file_exists( $localSocketFile ) ) {
Warning("sock file $localSocketFile already exists?! Is someone else talking to zms?");
// 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 ) ) {
ajaxError( "socket_bind( $localSocketFile ) failed: ".socket_strerror(socket_last_error()) );
} else {
Logger::Debug("Bound to $localSocketFile");
ajaxError("socket_bind( $localSocketFile ) failed: ".socket_strerror(socket_last_error()) );
}
switch ( $_REQUEST['command'] ) {
@ -81,7 +77,6 @@ if ( sem_acquire($semaphore,1) !== false ) {
$eSockets = NULL;
$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 );

View File

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

View File

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

View File

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

View File

@ -2,133 +2,164 @@
App::uses('AppController', 'Controller');
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';
if ( $daemon ) {
$string .= " $daemon";
if ( $args )
$string .= " $args";
$string .= " $daemon";
if ( $args )
$string .= " $args";
}
$result = exec($string);
$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(
'credentials'=> $credentials,
'append_password'=>$appendPassword,
'result' => $result,
'_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')
) );
}
}
// 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
// usage.
function getDiskPercent($mid = null) {
$this->loadModel('Config');
$this->loadModel('Monitor');
function getDiskPercent($mid = null) {
$this->loadModel('Config');
$this->loadModel('Monitor');
// If $mid is passed, see if it is valid
if ($mid) {
if (!$this->Monitor->exists($mid)) {
throw new NotFoundException(__('Invalid monitor'));
}
}
// If $mid is passed, see if it is valid
if ($mid) {
if (!$this->Monitor->exists($mid)) {
throw new NotFoundException(__('Invalid monitor'));
}
}
$zm_dir_events = $this->Config->find('list', array(
'conditions' => array('Name' => 'ZM_DIR_EVENTS'),
'fields' => array('Name', 'Value')
));
$zm_dir_events = $zm_dir_events['ZM_DIR_EVENTS' ];
$zm_dir_events = $this->Config->find('list', array(
'conditions' => array('Name' => 'ZM_DIR_EVENTS'),
'fields' => array('Name', 'Value')
));
$zm_dir_events = $zm_dir_events['ZM_DIR_EVENTS' ];
// Test to see if $zm_dir_events is relative or absolute
if ('/' === "" || strrpos($zm_dir_events, '/', -strlen($zm_dir_events)) !== TRUE) {
// relative - so add the full path
$zm_dir_events = Configure::read('ZM_PATH_WEB') . '/' . $zm_dir_events;
}
// Test to see if $zm_dir_events is relative or absolute
if ('/' === "" || strrpos($zm_dir_events, '/', -strlen($zm_dir_events)) !== TRUE) {
// relative - so add the full path
$zm_dir_events = Configure::read('ZM_PATH_WEB') . '/' . $zm_dir_events;
}
if ($mid) {
// Get disk usage for $mid
$usage = shell_exec ("du -sh0 $zm_dir_events/$mid | awk '{print $1}'");
} else {
$monitors = $this->Monitor->find('all', array(
'fields' => array('Id', 'Name', 'WebColour')
));
$usage = array();
if ($mid) {
// Get disk usage for $mid
$usage = shell_exec ("du -sh0 $zm_dir_events/$mid | awk '{print $1}'");
} else {
$monitors = $this->Monitor->find('all', array(
'fields' => array('Id', 'Name', 'WebColour')
));
$usage = array();
// Add each monitor's usage to array
foreach ($monitors as $key => $value) {
$id = $value['Monitor']['Id'];
$name = $value['Monitor']['Name'];
$color = $value['Monitor']['WebColour'];
// Add each monitor's usage to array
foreach ($monitors as $key => $value) {
$id = $value['Monitor']['Id'];
$name = $value['Monitor']['Name'];
$color = $value['Monitor']['WebColour'];
$space = shell_exec ("du -s0 $zm_dir_events/$id | awk '{print $1}'");
if ($space == null) {
$space = 0;
}
$space = $space/1024/1024;
$space = shell_exec ("du -s0 $zm_dir_events/$id | awk '{print $1}'");
if ($space == null) {
$space = 0;
}
$space = $space/1024/1024;
$usage[$name] = array(
'space' => rtrim($space),
'color' => $color
);
}
$usage[$name] = array(
'space' => rtrim($space),
'color' => $color
);
}
// Add total usage to array
$space = shell_exec( "df $zm_dir_events |tail -n1 | awk '{print $3 }'");
$space = $space/1024/1024;
$usage['Total'] = array(
'space' => rtrim($space),
'color' => '#F7464A'
);
}
// Add total usage to array
$space = shell_exec( "df $zm_dir_events |tail -n1 | awk '{print $3 }'");
$space = $space/1024/1024;
$usage['Total'] = array(
'space' => rtrim($space),
'color' => '#F7464A'
);
}
$this->set(array(
'usage' => $usage,
'_serialize' => array('usage')
));
}
$this->set(array(
'usage' => $usage,
'_serialize' => array('usage')
));
}
function getTimeZone() {
//http://php.net/manual/en/function.date-default-timezone-get.php
@ -139,18 +170,18 @@ class HostController extends AppController {
));
}
function getVersion() {
//throw new UnauthorizedException(__('API Disabled'));
$version = Configure::read('ZM_VERSION');
// not going to use the ZM_API_VERSION
// requires recompilation and dependency on ZM upgrade
//$apiversion = Configure::read('ZM_API_VERSION');
$apiversion = '1.0';
private function _getVersion() {
$version = Configure::read('ZM_VERSION');
$apiversion = '1.0';
return array($version, $apiversion);
}
$this->set(array(
'version' => $version,
'apiversion' => $apiversion,
'_serialize' => array('version', 'apiversion')
));
}
function getVersion() {
$val = $this->_getVersion();
$this->set(array(
'version' => $val[0],
'apiversion' => $val[1],
'_serialize' => array('version', 'apiversion')
));
}
}

View File

@ -18,10 +18,13 @@ class MonitorsController extends AppController {
public function beforeRender() {
$this->set($this->Monitor->enumValues());
}
public function beforeFilter() {
parent::beforeFilter();
$canView = $this->Session->Read('monitorPermission');
if ($canView == 'None') {
global $user;
# 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'));
return;
}
@ -35,7 +38,7 @@ class MonitorsController extends AppController {
public function index() {
$this->Monitor->recursive = 0;
if ($this->request->params['named']) {
if ( $this->request->params['named'] ) {
$this->FilterComponent = $this->Components->load('Filter');
//$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
$conditions = $this->request->params['named'];
@ -43,13 +46,14 @@ class MonitorsController extends AppController {
$conditions = array();
}
$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 ) {
$conditions['Monitor.Id' ] = $allowedMonitors;
}
$find_array = array('conditions'=>$conditions,'contain'=>array('Group'));
if ( isset( $conditions['GroupId'] ) ) {
if ( isset($conditions['GroupId']) ) {
$find_array['joins'] = array(
array(
'table' => 'Groups_Monitors',
@ -84,11 +88,12 @@ class MonitorsController extends AppController {
*/
public function view($id = null) {
$this->Monitor->recursive = 0;
if (!$this->Monitor->exists($id)) {
if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor'));
}
$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 ) {
$restricted = array('Monitor.' . $this->Monitor->primaryKey => $allowedMonitors);
} else {
$restricted = '';
@ -114,13 +119,15 @@ class MonitorsController extends AppController {
public function add() {
if ( $this->request->is('post') ) {
if ( $this->Session->Read('systemPermission') != 'Edit' ) {
throw new UnauthorizedException(__('Insufficient privileges'));
global $user;
$canAdd = (!$user) || ($user['System'] == 'Edit' );
if ( !$canAdd ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
$this->Monitor->create();
if ($this->Monitor->save($this->request->data)) {
if ( $this->Monitor->save($this->request->data) ) {
$this->daemonControl($this->Monitor->id, 'start');
//return $this->flash(__('The monitor has been saved.'), array('action' => 'index'));
$message = 'Saved';
@ -144,10 +151,12 @@ class MonitorsController extends AppController {
public function edit($id = null) {
$this->Monitor->id = $id;
if (!$this->Monitor->exists($id)) {
if ( !$this->Monitor->exists($id) ) {
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'));
return;
}
@ -163,9 +172,17 @@ class MonitorsController extends AppController {
// - restart or stop this monitor after change
$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
$this->daemonControl( $this->Monitor->id, 'stop' );
if ( ( $func != 'None' ) and ( (!defined('ZM_SERVER_ID')) or ($Monitor['ServerId']==ZM_SERVER_ID) ) ) {
$this->daemonControl( $this->Monitor->id, 'start' );
$this->daemonControl($this->Monitor->id, 'stop');
if (
( $func != 'None' )
and
(
(!defined('ZM_SERVER_ID'))
or
($Monitor['ServerId']==ZM_SERVER_ID)
)
) {
$this->daemonControl($this->Monitor->id, 'start');
}
} else {
$message = 'Error ' . print_r($this->Monitor->invalidFields(), true);
@ -187,10 +204,10 @@ class MonitorsController extends AppController {
*/
public function delete($id = null) {
$this->Monitor->id = $id;
if (!$this->Monitor->exists()) {
if ( !$this->Monitor->exists() ) {
throw new NotFoundException(__('Invalid monitor'));
}
if ($this->Session->Read('systemPermission') != 'Edit') {
if ( $this->Session->Read('systemPermission') != 'Edit' ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
@ -198,7 +215,7 @@ class MonitorsController extends AppController {
$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'));
} else {
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() {
$sourceTypes = $this->Monitor->query("describe Monitors Type;");
$sourceTypes = $this->Monitor->query('describe Monitors Type;');
preg_match('/^enum\((.*)\)$/', $sourceTypes[0]['COLUMNS']['Type'], $matches);
foreach( explode(',', $matches[1]) as $value ) {
@ -226,7 +243,7 @@ class MonitorsController extends AppController {
public function alarm() {
$id = $this->request->params['named']['id'];
$cmd = strtolower($this->request->params['named']['command']);
if (!$this->Monitor->exists($id)) {
if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor'));
}
if ( $cmd != 'on' && $cmd != 'off' && $cmd != 'status' ) {
@ -252,19 +269,18 @@ class MonitorsController extends AppController {
// form auth key based on auth credentials
$this->loadModel('Config');
$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'];
$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'];
$auth='';
$auth = '';
if ( $zmOptAuth ) {
if ( $zmAuthRelay == 'hashed' ) {
$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'];
$time = localtime();
@ -293,7 +309,7 @@ class MonitorsController extends AppController {
$id = $this->request->params['named']['id'];
$daemon = $this->request->params['named']['daemon'];
if (!$this->Monitor->exists($id)) {
if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor'));
}
@ -306,7 +322,7 @@ class MonitorsController extends AppController {
$monitor = Set::extract('/Monitor/.', $monitor);
// Pass -d for local, otherwise -m
if ($monitor[0]['Type'] == 'Local') {
if ( $monitor[0]['Type'] == 'Local' ) {
$args = '-d '. $monitor[0]['Device'];
} else {
$args = '-m '. $monitor[0]['Id'];
@ -315,7 +331,7 @@ class MonitorsController extends AppController {
// Build the command, and execute it
$zm_path_bin = Configure::read('ZM_PATH_BIN');
$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
// 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) {
$args = '';
$daemons = array();
if (!$monitor) {
if ( !$monitor ) {
// Need to see if it is local or remote
$monitor = $this->Monitor->find('first', array(
'fields' => array('Type', 'Function'),
'fields' => array('Type', 'Function', 'Device'),
'conditions' => array('Id' => $id)
));
$monitor = $monitor['Monitor'];
}
if ($monitor['Type'] == 'Local') {
$args = '-d ' . $monitor['Device'];
} else {
$args = '-m ' . $id;
}
if ($monitor['Function'] == 'Monitor') {
if ( $monitor['Function'] == 'Monitor' ) {
array_push($daemons, 'zmc');
} else {
array_push($daemons, 'zmc', 'zma');
@ -358,10 +367,16 @@ class MonitorsController extends AppController {
$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");
$status = exec( $shellcmd );
}
}
} // end class MonitorsController

View File

@ -8,7 +8,6 @@ App::uses('AppController', 'Controller');
*/
class ServersController extends AppController {
/**
* Components
*
@ -16,18 +15,16 @@ class ServersController extends AppController {
*/
public $components = array('Paginator', 'RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
$canView = $this->Session->Read('streamPermission');
if ($canView =='None') {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
public function beforeFilter() {
parent::beforeFilter();
global $user;
$canView = (!$user) || ($user['System'] != 'None');
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
}
}
/**
* index method
*
@ -36,7 +33,7 @@ public function beforeFilter() {
public function index() {
$this->Server->recursive = 0;
$options='';
$options = '';
$servers = $this->Server->find('all',$options);
$this->set(array(
'servers' => $servers,
@ -76,16 +73,17 @@ public function beforeFilter() {
* @return void
*/
public function add() {
if ($this->request->is('post')) {
if ( $this->request->is('post') ) {
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
global $user;
$canEdit = (!$user) || ($user['System'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
$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
#$this->daemonControl($this->Server->id, 'start', $this->request->data);
return $this->flash(__('The server has been saved.'), array('action' => 'index'));
@ -103,15 +101,17 @@ public function beforeFilter() {
public function edit($id = null) {
$this->Server->id = $id;
if (!$this->Server->exists($id)) {
throw new NotFoundException(__('Invalid server'));
}
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
global $user;
$canEdit = (!$user) || ($user['System'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
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';
} else {
$message = 'Error';
@ -133,20 +133,22 @@ public function beforeFilter() {
* @return void
*/
public function delete($id = null) {
$this->Server->id = $id;
if (!$this->Server->exists()) {
throw new NotFoundException(__('Invalid server'));
}
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
global $user;
$canEdit = (!$user) || ($user['System'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
$this->Server->id = $id;
if ( !$this->Server->exists() ) {
throw new NotFoundException(__('Invalid server'));
}
$this->request->allowMethod('post', 'delete');
#$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'));
} else {
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 function beforeFilter() {
parent::beforeFilter();
$canView = $this->Session->Read('systemPermission');
if ($canView =='None')
{
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
parent::beforeFilter();
global $user;
$canView = (!$user) || ($user['System'] != 'None');
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
}
/**
* index method
*
* @return void
*/
public function index() {
$this->State->recursive = 0;
$states = $this->State->find('all');
$this->set(array(
'states' => $states,
'_serialize' => array('states')
));
}
public function index() {
$this->State->recursive = 0;
$states = $this->State->find('all');
$this->set(array(
'states' => $states,
'_serialize' => array('states')
));
}
/**
* view method
@ -44,35 +42,35 @@ public function beforeFilter() {
* @param string $id
* @return void
*/
public function view($id = null) {
if (!$this->State->exists($id)) {
throw new NotFoundException(__('Invalid state'));
}
$options = array('conditions' => array('State.' . $this->State->primaryKey => $id));
$this->set('state', $this->State->find('first', $options));
}
public function view($id = null) {
if ( !$this->State->exists($id) ) {
throw new NotFoundException(__('Invalid state'));
}
$options = array('conditions' => array('State.' . $this->State->primaryKey => $id));
$this->set('state', $this->State->find('first', $options));
}
/**
* add method
*
* @return void
*/
public function add() {
if ($this->request->is('post')) {
public function add() {
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
if ($this->request->is('post')) {
$this->State->create();
if ($this->State->save($this->request->data)) {
return $this->flash(__('The state has been saved.'), array('action' => 'index'));
}
}
}
if ($this->Session->Read('systemPermission') != 'Edit')
{
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
@ -81,26 +79,27 @@ public function beforeFilter() {
* @param string $id
* @return void
*/
public function edit($id = null) {
if (!$this->State->exists($id)) {
throw new NotFoundException(__('Invalid state'));
}
public function edit($id = null) {
if (!$this->State->exists($id)) {
throw new NotFoundException(__('Invalid state'));
}
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
global $user;
$canEdit = (!$user) || ($user['System'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
if ($this->request->is(array('post', 'put'))) {
if ($this->State->save($this->request->data)) {
return $this->flash(__('The state has been saved.'), array('action' => 'index'));
}
} else {
$options = array('conditions' => array('State.' . $this->State->primaryKey => $id));
$this->request->data = $this->State->find('first', $options);
}
}
if ( $this->request->is(array('post', 'put')) ) {
if ( $this->State->save($this->request->data) ) {
return $this->flash(__('The state has been saved.'), array('action' => 'index'));
}
} else {
$options = array('conditions' => array('State.' . $this->State->primaryKey => $id));
$this->request->data = $this->State->find('first', $options);
}
}
/**
* delete method
@ -109,48 +108,50 @@ public function beforeFilter() {
* @param string $id
* @return void
*/
public function delete($id = null) {
$this->State->id = $id;
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
public function delete($id = null) {
$this->State->id = $id;
global $user;
$canEdit = (!$user) || ($user['System'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
if (!$this->State->exists()) {
throw new NotFoundException(__('Invalid state'));
}
$this->request->allowMethod('post', 'delete');
if ($this->State->delete()) {
return $this->flash(__('The state has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The state could not be deleted. Please, try again.'), array('action' => 'index'));
}
}
if (!$this->State->exists()) {
throw new NotFoundException(__('Invalid state'));
}
$this->request->allowMethod('post', 'delete');
if ($this->State->delete()) {
return $this->flash(__('The state has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The state could not be deleted. Please, try again.'), array('action' => 'index'));
}
}
public function change() {
if ($this->Session->Read('systemPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
public function change() {
global $user;
$canEdit = (!$user) || ($user['System'] == 'Edit');
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
$newState = $this->request->params['pass'][0];
$blah = $this->packageControl($newState);
$newState = $this->request->params['pass'][0];
$blah = $this->packageControl($newState);
$this->set(array(
'blah' => $blah,
'_serialize' => array('blah')
));
}
$this->set(array(
'blah' => $blah,
'_serialize' => array('blah')
));
}
public function packageControl( $command ) {
$zm_path_bin = Configure::read('ZM_PATH_BIN');
$string = $zm_path_bin.'/zmpkg.pl '.escapeshellarg( $command );
$status = exec( $string );
public function packageControl( $command ) {
$zm_path_bin = Configure::read('ZM_PATH_BIN');
$string = $zm_path_bin.'/zmpkg.pl '.escapeshellarg( $command );
$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 {
/**
* Components
*
* @var array
*/
public $components = array('RequestHandler');
/**
* Components
*
* @var array
*/
public $components = array('RequestHandler');
/**
* index method
*
* @return void
*/
public function index() {
$zonePresets = $this->ZonePreset->find('all');
$this->set(array(
'zonePresets' => $zonePresets,
'_serialize' => array('zonePresets')
));
}
/**
* index method
*
* @return void
*/
public function index() {
$zonePresets = $this->ZonePreset->find('all');
$this->set(array(
'zonePresets' => $zonePresets,
'_serialize' => array('zonePresets')
));
}
/**
* view method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function view($id = null) {
if (!$this->ZonePreset->exists($id)) {
throw new NotFoundException(__('Invalid zone preset'));
}
$options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id));
$this->set('zonePreset', $this->ZonePreset->find('first', $options));
}
/**
* view method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function view($id = null) {
if ( !$this->ZonePreset->exists($id) ) {
throw new NotFoundException(__('Invalid zone preset'));
}
$options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id));
$this->set('zonePreset', $this->ZonePreset->find('first', $options));
}
/**
* add method
*
* @return void
*/
public function add() {
if ($this->request->is('post')) {
$this->ZonePreset->create();
if ($this->ZonePreset->save($this->request->data)) {
return $this->flash(__('The zone preset has been saved.'), array('action' => 'index'));
}
}
}
/**
* add method
*
* @return void
*/
public function add() {
if ( $this->request->is('post') ) {
$this->ZonePreset->create();
if ( $this->ZonePreset->save($this->request->data) ) {
return $this->flash(__('The zone preset has been saved.'), array('action' => 'index'));
}
}
}
/**
* edit method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function edit($id = null) {
if (!$this->ZonePreset->exists($id)) {
throw new NotFoundException(__('Invalid zone preset'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->ZonePreset->save($this->request->data)) {
return $this->flash(__('The zone preset has been saved.'), array('action' => 'index'));
}
} else {
$options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id));
$this->request->data = $this->ZonePreset->find('first', $options);
}
}
/**
* edit method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function edit($id = null) {
if ( !$this->ZonePreset->exists($id) ) {
throw new NotFoundException(__('Invalid zone preset'));
}
if ( $this->request->is(array('post', 'put')) ) {
if ( $this->ZonePreset->save($this->request->data) ) {
return $this->flash(__('The zone preset has been saved.'), array('action' => 'index'));
}
} else {
$options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id));
$this->request->data = $this->ZonePreset->find('first', $options);
}
}
/**
* delete method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function delete($id = null) {
$this->ZonePreset->id = $id;
if (!$this->ZonePreset->exists()) {
throw new NotFoundException(__('Invalid zone preset'));
}
$this->request->allowMethod('post', 'delete');
if ($this->ZonePreset->delete()) {
return $this->flash(__('The zone preset has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The zone preset could not be deleted. Please, try again.'), array('action' => 'index'));
}
}}
/**
* delete method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function delete($id = null) {
$this->ZonePreset->id = $id;
if ( !$this->ZonePreset->exists() ) {
throw new NotFoundException(__('Invalid zone preset'));
}
$this->request->allowMethod('post', 'delete');
if ( $this->ZonePreset->delete() ) {
return $this->flash(__('The zone preset has been deleted.'), array('action' => 'index'));
} else {
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 {
/**
* Components
*
* @var array
*/
public $components = array('RequestHandler');
/**
* Components
*
* @var array
*/
public $components = array('RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
$canView = $this->Session->Read('monitorPermission');
if ($canView =='None')
{
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
public function beforeFilter() {
parent::beforeFilter();
}
global $user;
$canView = (!$user) || $user['Monitors'] != 'None';
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
}
// Find all zones which belong to a MonitorId
public function forMonitor($id = null) {
// Find all zones which belong to a MonitorId
public function forMonitor($id = null) {
$this->loadModel('Monitor');
if (!$this->Monitor->exists($id)) {
throw new NotFoundException(__('Invalid monitor'));
if ( !$this->Monitor->exists($id) ) {
throw new NotFoundException(__('Invalid monitor'));
}
$this->Zone->recursive = -1;
$zones = $this->Zone->find('all', array(
'conditions' => array('MonitorId' => $id)
'conditions' => array('MonitorId' => $id)
));
$this->set(array(
'zones' => $zones,
'_serialize' => array('zones')
'zones' => $zones,
'_serialize' => array('zones')
));
}
public function index() {
}
public function index() {
$this->Zone->recursive = -1;
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
if (!empty($allowedMonitors))
{
$mon_options = array('Zones.MonitorId' => $allowedMonitors);
}
else
{
$mon_options='';
global $user;
$allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'],NULL, PREG_SPLIT_NO_EMPTY) : null;
if ( $allowedMonitors ) {
$mon_options = array('Zones.MonitorId' => $allowedMonitors);
} else {
$mon_options = '';
}
$zones = $this->Zone->find('all',$mon_options);
$this->set(array(
'zones' => $zones,
'_serialize' => array('zones')
'zones' => $zones,
'_serialize' => array('zones')
));
}
/**
* add method
*
* @return void
*/
public function add() {
if ($this->request->is('post')) {
$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'));
}
/**
* add method
*
* @return void
*/
public function add() {
if ( $this->request->is('post') ) {
global $user;
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
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'));
}
/**
* edit method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function edit($id = null) {
$this->Zone->id = $id;
$this->loadModel('Config');
$zm_dir_images = $this->Config->find('list', array(
'conditions' => array('Name' => 'ZM_DIR_IMAGES'),
'fields' => array('Name', 'Value')
));
if (!$this->Zone->exists($id)) {
throw new NotFoundException(__('Invalid zone'));
}
if ($this->request->is(array('post', 'put'))) {
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'));
}
$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";
/**
* 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'));
}
}
chdir($images_path);
$command = escapeshellcmd("$zm_path_bin/zmu -z -m $id");
system($command, $status);
public function createZoneImage( $id = null ) {
$this->loadModel('Monitor');
$this->Monitor->id = $id;
if (!$this->Monitor->exists()) {
throw new NotFoundException(__('Invalid zone'));
}
$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')
));
}
}
$this->set(array(
'status' => $status,
'_serialize' => array('status')
));
}
} // end class

View File

@ -1,12 +1,28 @@
<?php
App::uses('AppModel', 'Model');
/**
* User Model
*
* @property Monitor $Monitor
* @property Frame $Frame
*/
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
*
@ -26,6 +42,48 @@ class User extends AppModel {
*
* @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,
'CanMoveCon' => 0,
'CanPan' => 0,
'CanReset' => 0,
'CanSleep' => 0,
'CanWake' => 0,
'MinPanRange' => NULL,
'MaxPanRange' => NULL,
'MinPanStep' => NULL,
@ -103,7 +106,7 @@ private $defaults = array(
if ( $IdOrRow ) {
$row = NULL;
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 ) {
Error("Unable to load Control record for Id=" . $IdOrRow );
}

View File

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

View File

@ -20,7 +20,7 @@ public $defaults = array(
'limit' => 100,
'Query' => array(),
'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 ) {

View File

@ -9,8 +9,10 @@ private $defaults = array(
'Name' => '',
'StorageId' => 0,
'ServerId' => 0,
'Type' => 'Ffmpeg',
'Function' => 'None',
'Enabled' => 1,
'LinkedMonitors' => null,
'Width' => null,
'Height' => null,
'Orientation' => null,
@ -20,9 +22,9 @@ private $defaults = array(
'OutputContainer' => 'auto',
'ZoneCount' => 0,
'Triggers' => null,
'Type' => 'Ffmpeg',
'MaxFPS' => null,
'AlarmMaxFPS' => null,
'Refresh' => null,
);
private $status_fields = array(
'AnalysisFPS' => null,
@ -218,7 +220,7 @@ private $control_fields = array(
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
$args['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
$args['auth'] = generateAuthHash(ZM_AUTH_HASH_IPS);
} elseif ( ZM_AUTH_RELAY == 'plain' ) {
$args['user'] = $_SESSION['username'];
$args['pass'] = $_SESSION['password'];
@ -338,13 +340,13 @@ private $control_fields = array(
}
if ( $mode == 'stop' ) {
daemonControl( 'stop', 'zmc', $zmcArgs );
daemonControl('stop', 'zmc', $zmcArgs);
} else {
if ( $mode == 'restart' ) {
daemonControl( 'stop', 'zmc', $zmcArgs );
daemonControl('stop', 'zmc', $zmcArgs);
}
if ( $this->{'Function'} != 'None' ) {
daemonControl( 'start', 'zmc', $zmcArgs );
daemonControl('start', 'zmc', $zmcArgs);
}
}
} else if ( $this->ServerId() ) {
@ -381,6 +383,8 @@ private $control_fields = array(
} catch ( Exception $e ) {
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
@ -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 ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) {
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 {
if ( $mode == 'restart' ) {
if ( ZM_OPT_CONTROL ) {
@ -407,7 +411,8 @@ private $control_fields = array(
}
}
} // end if we are on the recording server
}
} // end public function zmaControl
public function GroupIds( $new='') {
if ( $new != '' ) {
if(!is_array($new)) {
@ -468,6 +473,8 @@ private $control_fields = array(
$this->{'Storage'} = isset($this->{'StorageId'}) ?
Storage::find_one(array('Id'=>$this->{'StorageId'})) :
new Storage(NULL);
if ( ! $this->{'Storage'} )
$this->{'Storage'} = new Storage(NULL);
}
return $this->{'Storage'};
}
@ -485,14 +492,20 @@ private $control_fields = array(
$source = preg_replace( '/^.*\//', '', $this->{'Path'} );
} elseif ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) {
$url_parts = parse_url( $this->{'Path'} );
unset($url_parts['user']);
unset($url_parts['pass']);
#unset($url_parts['scheme']);
unset($url_parts['query']);
#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);
if ( ZM_WEB_FILTER_SOURCE == "Hostname" ) { # Filter out everything but the hostname
$source = $url_parts['host'];
} elseif ( ZM_WEB_FILTER_SOURCE == "NoCredentials" ) { # Filter out sensitive and common items
unset($url_parts['user']);
unset($url_parts['pass']);
#unset($url_parts['scheme']);
unset($url_parts['query']);
#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 == '' ) {
$source = 'Monitor ' . $this->{'Id'};

View File

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

View File

@ -140,20 +140,31 @@ class Storage {
return $usage;
}
public function disk_total_space() {
if ( ! array_key_exists('disk_total_space', $this) ) {
$this->{'disk_total_space'} = disk_total_space($this->Path());
if ( !array_key_exists('disk_total_space', $this) ) {
$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'};
}
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.
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' ) {
$this->{'disk_used_space'} = $this->disk_event_space();
} else {
$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'};

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
if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) {
if (!in_array('invalid-input-secret',$responseData['error-codes'])) {
Error ('reCaptcha authentication failed');
Error('reCaptcha authentication failed');
userLogout();
$view='login';
$refreshParent = true;
return;
} else {
//Let them login but show an error
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 using reCaptcha
$username = validStr( $_REQUEST['username'] );
$username = validStr($_REQUEST['username']);
$password = isset($_REQUEST['password'])?validStr($_REQUEST['password']):'';
userLogin( $username, $password );
userLogin($username, $password);
$refreshParent = true;
$view = 'console';
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console';
@ -476,15 +476,12 @@ if ( canEdit( 'Monitors' ) ) {
);
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');
Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] );
if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) {
$_REQUEST['newMonitor']['ServerId'] = 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');
@ -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 ( $monitor['Type'] != 'WebSite' ) {
zmaControl( $monitor, 'stop' );
zmcControl( $monitor, 'stop' );
zmaControl($monitor, 'stop');
zmcControl($monitor, 'stop');
}
dbQuery( 'UPDATE Monitors SET '.implode( ', ', $changes ).' WHERE Id=?', array($mid) );
// Groups will be added below
@ -570,23 +567,26 @@ if ( canEdit( 'Monitors' ) ) {
}
$restart = true;
} else {
Logger::Debug("No action due to no changes to Monitor");
} # 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']) ) {
foreach ( $_POST['newMonitor']['GroupIds'] as $group_id ) {
dbQuery('INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid));
}
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']) ) {
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 ) {
$x10Changes = getFormChanges( $x10Monitor, $_REQUEST['newX10Monitor'] );
@ -732,7 +732,7 @@ if ( canEdit( 'System' ) ) {
$_SESSION['zmMontageLayout'] = $Layout->Id();
setcookie('zmMontageLayout', $Layout->Id(), 1 );
session_write_close();
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montagereview';
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montage';
} // end if save
} else if ( $_REQUEST['object'] == 'server' ) {

View File

@ -19,7 +19,7 @@
//
function userLogin($username, $password='', $passwordHashed=false) {
global $user, $cookies;
global $user;
$sql = 'SELECT * FROM Users WHERE Enabled=1';
$sql_values = NULL;
@ -34,7 +34,12 @@ function userLogin($username, $password='', $passwordHashed=false) {
$sql .= ' AND 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;
if ( ZM_AUTH_RELAY == 'plain' ) {
// Need to save this in session
@ -54,7 +59,9 @@ function userLogin($username, $password='', $passwordHashed=false) {
$_SESSION['loginFailed'] = true;
unset($user);
}
session_write_close();
if ( $close_session )
session_write_close();
return isset($user) ? $user: null;
} # end function userLogin
function userLogout() {
@ -103,13 +110,13 @@ function getAuthUser($auth) {
return false;
} // 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'] ) {
# regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800
$time = time();
$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
$local_time = localtime();
$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] );
$auth = md5($authKey);
session_start();
$_SESSION['AuthHash'] = $auth;
$_SESSION['AuthHashGeneratedAt'] = $time;
session_write_close();
if ( !$force ) {
$close_session = 0;
if ( !is_session_started() ) {
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" );
#} else {
#} else {
#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
return $_SESSION['AuthHash'];
} else {
$auth = '';
}
return $auth;
} # end if using AUTH and AUTH_RELAY
return '';
}
function visibleMonitor($mid) {
@ -153,4 +166,17 @@ function canEdit($area, $mid=false) {
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() ) {
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
} 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_AUTH_RELAY == 'hashed' ) {
$zmuCommand .= ' -A '.generateAuthHash( false );
$zmuCommand .= ' -A '.generateAuthHash(false, true);
} elseif ( ZM_AUTH_RELAY == 'plain' ) {
$zmuCommand .= ' -U ' .escapeshellarg($_SESSION['username']).' -P '.escapeshellarg($_SESSION['password']);
} 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 ) {
if ( is_dir( $path ) ) {
system( escapeshellcmd( 'rm -rf '.$path ) );
} else {
} else if ( file_exists($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 ) {
$html = '';
foreach ( $contents as $value=>$text ) {
if ( is_array( $text ) )
$text = $text['Name'];
else if ( is_object( $text ) )
$text = $text->Name();
$selected = is_array( $values ) ? in_array( $value, $values ) : !strcmp($value, $values);
$html .= "<option value=\"$value\"".($selected?" selected=\"selected\"":'').">$text</option>";
function htmlOptions($contents, $values) {
$options_html = '';
foreach ( $contents as $value=>$option ) {
$disabled = 0;
$text = '';
if ( is_array($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 ) {
@ -2063,7 +2081,7 @@ function cache_bust( $file ) {
global $css;
$dirname = preg_replace( '/\//', '_', $parts['dirname'] );
$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;
} else {
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 ) ) {
//Warning("Scale to " . $options['scale'] );
$options['width'] = reScale( $monitor->Width(), $options['scale'] ) . 'px';
$options['height'] = reScale( $monitor->Height(), $options['scale'] ) . 'px';
$options['width'] = reScale( $monitor->Width(), $options['scale'] );
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
} else {
# scale is empty or 100
# 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'] ) ) {
$options['width'] = $monitor->Width() . 'px';
$options['width'] = $monitor->Width();
if ( ! ( isset($options['height']) and $options['height'] ) ) {
$options['height'] = $monitor->Height() . 'px';
$options['height'] = $monitor->Height();
}
} else if ( ! isset($options['height']) ) {
$options['height'] = '';
@ -2159,12 +2177,13 @@ function getStreamHTML( $monitor, $options = array() ) {
$options['buffer'] = $monitor->StreamReplayBuffer();
//Warning("width: " . $options['width'] . ' height: ' . $options['height']. ' scale: ' . $options['scale'] );
if ( $monitor->Type() == "WebSite" ) {
return getWebSiteUrl( 'liveStream'.$monitor->Id(), $monitor->Path(),
( isset($options['width']) ? $options['width'] : NULL ),
( isset($options['height']) ? $options['height'] : NULL ),
$monitor->Name()
);
if ( $monitor->Type() == 'WebSite' ) {
return getWebSiteUrl(
'liveStream'.$monitor->Id(), $monitor->Path(),
( isset($options['width']) ? $options['width'] : NULL ),
( isset($options['height']) ? $options['height'] : NULL ),
$monitor->Name()
);
//FIXME, the width and height of the image need to be scaled.
} else if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
$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() );
} else if ( $options['mode'] == 'stream' and canStream() ) {
$options['mode'] = 'jpeg';
$streamSrc = $monitor->getStreamSrc( $options );
$streamSrc = $monitor->getStreamSrc($options);
if ( canStreamNative() )
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/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';
} else {
$protocol = 'http';
@ -200,7 +205,7 @@ isset($view) || $view = NULL;
isset($request) || $request = 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' );
#Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
csrf_check();

View File

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

View File

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

View File

@ -71,62 +71,62 @@ setlocale( LC_ALL, 'he_IL' ); //All locale settings 4.3.0 and after
// Simple String Replacements
$SLANG = array(
'24BitColour' => 'צבע 24 ביט',
'32BitColour' => 'צבע 32 ביט', // Added - 2011-06-15
'8BitGrey' => 'גווני אפור 8 ביט',
'Action' => 'פעולה',
'Actual' => 'מקורי',
'AddNewControl' => 'הוסף קונטרול חדש',
'AddNewMonitor' => 'הוסף מוניטור חדש',
'AddNewUser' => 'הוסף משתמש חדש',
'AddNewZone' => 'הוסף איזור חדש',
'Alarm' => 'אזעקה',
'AlarmBrFrames' => 'אזעקת<br/>פריימים',
'AlarmFrame' => 'אזעקת פריימים',
'AlarmFrameCount' => 'ספירת אזעקות פריימים',
'AlarmLimits' => 'הגבלות אזעקה',
'24BitColour' => 'öáò 24 áéè',
'32BitColour' => 'öáò 32 áéè', // Added - 2011-06-15
'8BitGrey' => 'âååðé àôåø 8 áéè',
'Action' => 'ôòåìä',
'Actual' => 'î÷åøé',
'AddNewControl' => 'äåñó ÷åðèøåì çãù',
'AddNewMonitor' => 'äåñó îåðéèåø çãù',
'AddNewUser' => 'äåñó îùúîù çãù',
'AddNewZone' => 'äåñó àéæåø çãù',
'Alarm' => 'àæò÷ä',
'AlarmBrFrames' => 'àæò÷ú<br/>ôøééîéí',
'AlarmFrame' => 'àæò÷ú ôøééîéí',
'AlarmFrameCount' => 'ñôéøú àæò÷åú ôøééîéí',
'AlarmLimits' => 'äâáìåú àæò÷ä',
'AlarmMaximumFPS' => 'Alarm Maximum FPS',
'AlarmPx' => 'אזעקת Px',
'AlarmRGBUnset' => 'הינך חייב לאתחל אזעקת צבע',
'AlarmPx' => 'àæò÷ú Px',
'AlarmRGBUnset' => 'äéðê çééá ìàúçì àæò÷ú öáò',
'AlarmRefImageBlendPct'=> 'Alarm Reference Image Blend %ge', // Added - 2015-04-18
'Alert' => 'התראה',
'All' => 'הכל',
'Alert' => 'äúøàä',
'All' => 'äëì',
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
'Apply' => 'החל',
'ApplyingStateChange' => 'החל שינוי מצב',
'ArchArchived' => 'ארכיב בלבד',
'ArchUnarchived' => 'לא לארכיב בלבד',
'Archive' => 'ארכיב',
'Archived' => 'אורכב',
'Area' => 'אזור',
'AreaUnits' => 'אזור (px/%)',
'Apply' => 'äçì',
'ApplyingStateChange' => 'äçì ùéðåé îöá',
'ArchArchived' => 'àøëéá áìáã',
'ArchUnarchived' => 'ìà ìàøëéá áìáã',
'Archive' => 'àøëéá',
'Archived' => 'àåøëá',
'Area' => 'àæåø',
'AreaUnits' => 'àæåø (px/%)',
'AttrAlarmFrames' => 'Alarm Frames',
'AttrArchiveStatus' => 'Archive Status',
'AttrAvgScore' => 'ניקוד ממוצע',
'AttrCause' => 'סיבה',
'AttrDate' => 'תאריך',
'AttrDateTime' => 'תאריך/שעה',
'AttrAvgScore' => 'ðé÷åã îîåöò',
'AttrCause' => 'ñéáä',
'AttrDate' => 'úàøéê',
'AttrDateTime' => 'úàøéê/ùòä',
'AttrDiskBlocks' => 'Disk Blocks',
'AttrDiskPercent' => 'Disk Percent',
'AttrDuration' => 'משך זמן',
'AttrFrames' => 'פריימים',
'AttrDuration' => 'îùê æîï',
'AttrFrames' => 'ôøééîéí',
'AttrId' => 'Id',
'AttrMaxScore' => 'ניקוד מקסימלי',
'AttrMaxScore' => 'ðé÷åã î÷ñéîìé',
'AttrMonitorId' => 'Monitor Id',
'AttrMonitorName' => 'שם מוניטור',
'AttrName' => 'שם',
'AttrNotes' => 'הערות',
'AttrMonitorName' => 'ùí îåðéèåø',
'AttrName' => 'ùí',
'AttrNotes' => 'äòøåú',
'AttrSystemLoad' => 'System Load',
'AttrTime' => 'שעה',
'AttrTotalScore' => 'סך סכום',
'AttrWeekday' => 'יום בשבוע',
'Auto' => 'אוטו',
'AutoStopTimeout' => 'פסק זמן עצירה אוטו',
'AttrTime' => 'ùòä',
'AttrTotalScore' => 'ñê ñëåí',
'AttrWeekday' => 'éåí áùáåò',
'Auto' => 'àåèå',
'AutoStopTimeout' => 'ôñ÷ æîï òöéøä àåèå',
'Available' => 'Available', // Added - 2009-03-31
'AvgBrScore' => 'ניקוד<br/>ממוצע',
'Background' => 'רקע',
'BackgroundFilter' => 'הרץ מסנן ברקע',
'AvgBrScore' => 'ðé÷åã<br/>îîåöò',
'Background' => 'ø÷ò',
'BackgroundFilter' => 'äøõ îñðï áø÷ò',
'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',
'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',
'BadWebColour' => 'Web colour must be a valid web colour string',
'BadWidth' => 'Width must be set to a valid value',
'Bandwidth' => 'רוחב פס',
'Bandwidth' => 'øåçá ôñ',
'BandwidthHead' => 'Bandwidth', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
'BlobPx' => 'Blob Px',
'BlobSizes' => 'Blob Sizes',
'Blobs' => 'Blobs',
'Brightness' => 'בהירות',
'Brightness' => 'áäéøåú',
'Buffer' => 'Buffer', // Added - 2015-04-18
'Buffers' => 'Buffers',
'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18
'CanAutoFocus' => 'אפשר התמקדות אוטומטי',
'CanAutoFocus' => 'àôùø äúî÷ãåú àåèåîèé',
'CanAutoGain' => 'Can Auto Gain',
'CanAutoIris' => 'Can Auto Iris',
'CanAutoWhite' => 'Can Auto White Bal.',
'CanAutoZoom' => 'אפשר זום אוטומטי',
'CanFocus' => 'אפשר התמקדות',
'CanFocusAbs' => 'אפשר התמקדות אבסולוטי',
'CanFocusCon' => 'אפשר התמקדות מתמשך',
'CanFocusRel' => 'אפשר התמקדות יחסי',
'CanAutoZoom' => 'àôùø æåí àåèåîèé',
'CanFocus' => 'àôùø äúî÷ãåú',
'CanFocusAbs' => 'àôùø äúî÷ãåú àáñåìåèé',
'CanFocusCon' => 'àôùø äúî÷ãåú îúîùê',
'CanFocusRel' => 'àôùø äúî÷ãåú éçñé',
'CanGain' => 'Can Gain ',
'CanGainAbs' => 'Can Gain Absolute',
'CanGainCon' => 'Can Gain Continuous',
@ -183,136 +183,136 @@ $SLANG = array(
'CanIrisAbs' => 'Can Iris Absolute',
'CanIrisCon' => 'Can Iris Continuous',
'CanIrisRel' => 'Can Iris Relative',
'CanMove' => 'אפשר תנועה',
'CanMoveAbs' => 'אפשר תנועה אבסולוטית',
'CanMoveCon' => 'אפשר תזוזה מתמשכת',
'CanMove' => 'àôùø úðåòä',
'CanMoveAbs' => 'àôùø úðåòä àáñåìåèéú',
'CanMoveCon' => 'àôùø úæåæä îúîùëú',
'CanMoveDiag' => 'Can Move Diagonally',
'CanMoveMap' => 'Can Move Mapped',
'CanMoveRel' => 'אפשר תזוזה יחסית',
'CanMoveRel' => 'àôùø úæåæä éçñéú',
'CanPan' => 'Can Pan' ,
'CanReset' => 'אפשר אתחול',
'CanReset' => 'àôùø àúçåì',
'CanSetPresets' => 'Can Set Presets',
'CanSleep' => 'אפשר מצב שינה',
'CanTilt' => 'אפשר זעזוע',
'CanWake' => 'אפשר יציאה ממצב שינה',
'CanSleep' => 'àôùø îöá ùéðä',
'CanTilt' => 'àôùø æòæåò',
'CanWake' => 'àôùø éöéàä îîöá ùéðä',
'CanWhite' => 'Can White Balance',
'CanWhiteAbs' => 'Can White Bal. Absolute',
'CanWhiteBal' => 'Can White Bal.',
'CanWhiteCon' => 'Can White Bal. Continuous',
'CanWhiteRel' => 'Can White Bal. Relative',
'CanZoom' => 'אפשר זום',
'CanZoomAbs' => 'אפשר זום אבסולוטי',
'CanZoomCon' => 'אפשר זום מתמשך',
'CanZoomRel' => 'אפשר זום יחסי',
'Cancel' => 'בטל',
'CanZoom' => 'àôùø æåí',
'CanZoomAbs' => 'àôùø æåí àáñåìåèé',
'CanZoomCon' => 'àôùø æåí îúîùê',
'CanZoomRel' => 'àôùø æåí éçñé',
'Cancel' => 'áèì',
'CancelForcedAlarm' => 'Cancel Forced Alarm',
'CaptureHeight' => 'Capture Height',
'CaptureMethod' => 'Capture Method', // Added - 2009-02-08
'CapturePalette' => 'Capture Palette',
'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18
'CaptureWidth' => 'Capture Width',
'Cause' => 'סיבה',
'Cause' => 'ñéáä',
'CheckMethod' => 'Alarm Check Method',
'ChooseDetectedCamera' => 'Choose Detected Camera', // Added - 2009-03-31
'ChooseFilter' => 'בחר מסנן',
'ChooseFilter' => 'áçø îñðï',
'ChooseLogFormat' => 'Choose a log format', // Added - 2011-06-17
'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17
'ChoosePreset' => 'Choose Preset',
'Clear' => 'Clear', // Added - 2011-06-16
'Close' => 'סגור',
'Colour' => 'צבע',
'Command' => 'פקודה',
'Close' => 'ñâåø',
'Colour' => 'öáò',
'Command' => 'ô÷åãä',
'Component' => 'Component', // Added - 2011-06-16
'Config' => 'תצורה',
'ConfiguredFor' => 'תצורה עבור',
'Config' => 'úöåøä',
'ConfiguredFor' => 'úöåøä òáåø',
'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?',
'ConfirmPassword' => 'אשר סיסמא',
'ConjAnd' => 'ו',
'ConjOr' => 'או',
'Console' => 'קונסול',
'ContactAdmin' => 'צור קשר עם מנהל המערכת בשביל פרטים נוספים.',
'Continue' => 'המשך',
'Contrast' => 'ניגודיות',
'Control' => 'קונטרול',
'ControlAddress' => 'כתובת הקונטרול',
'ControlCap' => 'יכולת הקונטרול',
'ControlCaps' => 'יכולות הקונטרול',
'ControlDevice' => 'התקן הקונטרול',
'ControlType' => 'סוג הקונטרול',
'ConfirmPassword' => 'àùø ñéñîà',
'ConjAnd' => 'å',
'ConjOr' => 'àå',
'Console' => '÷åðñåì',
'ContactAdmin' => 'öåø ÷ùø òí îðäì äîòøëú áùáéì ôøèéí ðåñôéí.',
'Continue' => 'äîùê',
'Contrast' => 'ðéâåãéåú',
'Control' => '÷åðèøåì',
'ControlAddress' => 'ëúåáú ä÷åðèøåì',
'ControlCap' => 'éëåìú ä÷åðèøåì',
'ControlCaps' => 'éëåìåú ä÷åðèøåì',
'ControlDevice' => 'äú÷ï ä÷åðèøåì',
'ControlType' => 'ñåâ ä÷åðèøåì',
'Controllable' => 'Controllable',
'Current' => 'Current', // Added - 2015-04-18
'Cycle' => 'מחזורי',
'CycleWatch' => 'צפייה מחזורית',
'Cycle' => 'îçæåøé',
'CycleWatch' => 'öôééä îçæåøéú',
'DateTime' => 'Date/Time', // Added - 2011-06-16
'Day' => 'יום',
'Day' => 'éåí',
'Debug' => 'Debug',
'DefaultRate' => 'Default Rate',
'DefaultScale' => 'Default Scale',
'DefaultView' => 'Default View',
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18
'Delete' => 'מחק',
'DeleteAndNext' => 'מחק &amp; הבא',
'DeleteAndPrev' => 'מחק &amp; הקודם',
'DeleteSavedFilter' => 'מחק מסנן שמור',
'Description' => 'תיאור',
'Delete' => 'îç÷',
'DeleteAndNext' => 'îç÷ &amp; äáà',
'DeleteAndPrev' => 'îç÷ &amp; ä÷åãí',
'DeleteSavedFilter' => 'îç÷ îñðï ùîåø',
'Description' => 'úéàåø',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18
'Device' => 'Device', // Added - 2009-02-08
'DeviceChannel' => 'ערוץ ההתקן',
'DeviceFormat' => 'תבנית ההתקן',
'DeviceNumber' => 'מספר ההתקן',
'DevicePath' => 'נתיב ההתקן',
'Devices' => 'התקנים',
'Dimensions' => 'מימדים',
'DisableAlarms' => 'נטרל אזעקות',
'Disk' => 'דיסק',
'DeviceChannel' => 'òøåõ ääú÷ï',
'DeviceFormat' => 'úáðéú ääú÷ï',
'DeviceNumber' => 'îñôø ääú÷ï',
'DevicePath' => 'ðúéá ääú÷ï',
'Devices' => 'äú÷ðéí',
'Dimensions' => 'îéîãéí',
'DisableAlarms' => 'ðèøì àæò÷åú',
'Disk' => 'ãéñ÷',
'Display' => 'Display', // Added - 2011-01-30
'Displaying' => 'Displaying', // Added - 2011-06-16
'DoNativeMotionDetection'=> 'Do Native Motion Detection',
'Donate' => 'תרום בבקשה',
'DonateAlready' => 'לא, תרמתי כבר',
'Donate' => 'úøåí áá÷ùä',
'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.',
'DonateRemindDay' => 'עדיין לא, הזכר לא בעוד יום אחד',
'DonateRemindHour' => 'עדיין לא, הזכר לי בעוד שעה אחת',
'DonateRemindMonth' => 'עדיין לא, הזכר לי בעוד חודש אחד',
'DonateRemindNever' => 'לא, אני לא רוצה לתרום, אל תתזכר אותי',
'DonateRemindWeek' => 'עדיין לא, הזכר לי בעוד שבוע אחד',
'DonateYes' => 'כן, אני מעוניין לתרום עכשיו',
'Download' => 'הורד',
'DonateRemindDay' => 'òãééï ìà, äæëø ìà áòåã éåí àçã',
'DonateRemindHour' => 'òãééï ìà, äæëø ìé áòåã ùòä àçú',
'DonateRemindMonth' => 'òãééï ìà, äæëø ìé áòåã çåãù àçã',
'DonateRemindNever' => 'ìà, àðé ìà øåöä ìúøåí, àì úúæëø àåúé',
'DonateRemindWeek' => 'òãééï ìà, äæëø ìé áòåã ùáåò àçã',
'DonateYes' => 'ëï, àðé îòåðééï ìúøåí òëùéå',
'Download' => 'äåøã',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
'Duration' => 'משך זמן',
'Edit' => 'ערוך',
'Email' => 'דוא"ל',
'EnableAlarms' => 'אפשר אזעקות',
'Enabled' => 'אפשר',
'EnterNewFilterName' => 'הזן מסנן חדש',
'Error' => 'שגיאה',
'Duration' => 'îùê æîï',
'Edit' => 'òøåê',
'Email' => 'ãåà"ì',
'EnableAlarms' => 'àôùø àæò÷åú',
'Enabled' => 'àôùø',
'EnterNewFilterName' => 'äæï îñðï çãù',
'Error' => 'ùâéàä',
'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',
'Etc' => 'וכו\'',
'Event' => 'אירוע',
'EventFilter' => 'מסנן אירוע',
'EventId' => 'זיהוי אירוע',
'EventName' => 'שם אירוע',
'Etc' => 'åëå\'',
'Event' => 'àéøåò',
'EventFilter' => 'îñðï àéøåò',
'EventId' => 'æéäåé àéøåò',
'EventName' => 'ùí àéøåò',
'EventPrefix' => 'Event Prefix',
'Events' => 'אירועים',
'Exclude' => 'ללא',
'Execute' => 'בצע',
'Export' => 'יצא',
'ExportDetails' => 'יצא פרטי אירוע',
'ExportFailed' => 'יצוא נכשל',
'ExportFormat' => 'יצא תבנית קובץ',
'Events' => 'àéøåòéí',
'Exclude' => 'ììà',
'Execute' => 'áöò',
'Export' => 'éöà',
'ExportDetails' => 'éöà ôøèé àéøåò',
'ExportFailed' => 'éöåà ðëùì',
'ExportFormat' => 'éöà úáðéú ÷åáõ',
'ExportFormatTar' => 'Tar',
'ExportFormatZip' => 'Zip',
'ExportFrames' => 'Export Frame Details',
'ExportImageFiles' => 'יצא קבצי תמונה',
'ExportImageFiles' => 'éöà ÷áöé úîåðä',
'ExportLog' => 'Export Log', // Added - 2011-06-17
'ExportMiscFiles' => 'יצא קבצים אחרים (אם ישנם)',
'ExportOptions' => 'יצא אפשרויות',
'ExportMiscFiles' => 'éöà ÷áöéí àçøéí (àí éùðí)',
'ExportOptions' => 'éöà àôùøåéåú',
'ExportSucceeded' => 'Export Succeeded', // Added - 2009-02-08
'ExportVideoFiles' => 'Export Video Files (if present)',
'Exporting' => 'מייצא',
'Exporting' => 'îééöà',
'FPS' => 'fps',
'FPSReportInterval' => 'FPS Report Interval',
'FTP' => 'FTP',
@ -320,20 +320,20 @@ $SLANG = array(
'FastForward' => 'Fast Forward',
'Feed' => 'Feed',
'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08
'File' => 'קובץ',
'File' => '÷åáõ',
'Filter' => 'Filter', // Added - 2015-04-18
'FilterArchiveEvents' => 'ארכב תואמים',
'FilterDeleteEvents' => 'מחק תואמים',
'FilterEmailEvents' => 'שלח דואר של כל התואמים',
'FilterArchiveEvents' => 'àøëá úåàîéí',
'FilterDeleteEvents' => 'îç÷ úåàîéí',
'FilterEmailEvents' => 'ùìç ãåàø ùì ëì äúåàîéí',
'FilterExecuteEvents' => 'Execute command on all matches',
'FilterLog' => 'Filter log', // Added - 2015-04-18
'FilterMessageEvents' => 'Message details of all matches',
'FilterPx' => 'Filter Px',
'FilterUnset' => 'עליך לציין רוחב וגובה מסנן',
'FilterUploadEvents' => 'עלה את כל התואמים',
'FilterVideoEvents' => 'צור וידאו לכל התואמים',
'Filters' => 'מסננים',
'First' => 'הראשון',
'FilterUnset' => 'òìéê ìöééï øåçá åâåáä îñðï',
'FilterUploadEvents' => 'òìä àú ëì äúåàîéí',
'FilterVideoEvents' => 'öåø åéãàå ìëì äúåàîéí',
'Filters' => 'îñððéí',
'First' => 'äøàùåï',
'FlippedHori' => 'Flipped Horizontally',
'FlippedVert' => 'Flipped Vertically',
'FnMocord' => 'Mocord', // Added 2013.08.16.
@ -342,24 +342,24 @@ $SLANG = array(
'FnNodect' => 'Nodect', // Added 2013.08.16.
'FnNone' => 'None', // Added 2013.08.16.
'FnRecord' => 'Record', // Added 2013.08.16.
'Focus' => 'התמקד',
'ForceAlarm' => 'הכרח אזעקה',
'Format' => 'תבנית',
'Frame' => 'פריים',
'Focus' => 'äúî÷ã',
'ForceAlarm' => 'äëøç àæò÷ä',
'Format' => 'úáðéú',
'Frame' => 'ôøééí',
'FrameId' => 'Frame Id',
'FrameRate' => 'Frame Rate',
'FrameSkip' => 'דלג פריים',
'Frames' => 'פריימים',
'Func' => 'פונק',
'Function' => 'פונקציה',
'FrameSkip' => 'ãìâ ôøééí',
'Frames' => 'ôøééîéí',
'Func' => 'ôåð÷',
'Function' => 'ôåð÷öéä',
'Gain' => 'Gain',
'General' => 'כללי',
'GenerateVideo' => 'צור וידאו',
'GeneratingVideo' => 'מייצר וידאו',
'GoToZoneMinder' => 'בקר ZoneMinder.com',
'Grey' => 'אפור',
'Group' => 'קבוצה',
'Groups' => 'קבוצות',
'General' => 'ëììé',
'GenerateVideo' => 'öåø åéãàå',
'GeneratingVideo' => 'îééöø åéãàå',
'GoToZoneMinder' => 'á÷ø ZoneMinder.com',
'Grey' => 'àôåø',
'Group' => '÷áåöä',
'Groups' => '÷áåöåú',
'HasFocusSpeed' => 'Has Focus Speed',
'HasGainSpeed' => 'Has Gain Speed',
'HasHomePreset' => 'Has Home Preset',
@ -371,51 +371,51 @@ $SLANG = array(
'HasTurboTilt' => 'Has Turbo Tilt',
'HasWhiteSpeed' => 'Has White Bal. Speed',
'HasZoomSpeed' => 'Has Zoom Speed',
'High' => 'גבוה',
'HighBW' => 'גבוה&nbsp;ר/פ',
'Home' => 'בית',
'Hour' => 'שעה',
'High' => 'âáåä',
'HighBW' => 'âáåä&nbsp;ø/ô',
'Home' => 'áéú',
'Hour' => 'ùòä',
'Hue' => 'Hue',
'Id' => 'זיהוי',
'Idle' => 'המתנה',
'Ignore' => 'התעלם',
'Image' => 'תמונה',
'Id' => 'æéäåé',
'Idle' => 'äîúðä',
'Ignore' => 'äúòìí',
'Image' => 'úîåðä',
'ImageBufferSize' => 'Image Buffer Size (frames)',
'Images' => 'תמונות',
'In' => 'בתוך',
'Include' => 'כלול',
'Inverted' => 'הפוך',
'Images' => 'úîåðåú',
'In' => 'áúåê',
'Include' => 'ëìåì',
'Inverted' => 'äôåê',
'Iris' => 'Iris',
'KeyString' => 'מחרוזת תוים',
'Label' => 'תווית',
'Language' => 'שפה',
'Last' => 'אחרון',
'KeyString' => 'îçøåæú úåéí',
'Label' => 'úååéú',
'Language' => 'ùôä',
'Last' => 'àçøåï',
'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16
'Libvlc' => 'Libvlc',
'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'
'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'
'Line' => 'Line', // Added - 2011-06-16
'LinkedMonitors' => 'מוניטורים מקושרים',
'List' => 'רשימה',
'Load' => 'טען',
'Local' => 'מקומי',
'LinkedMonitors' => 'îåðéèåøéí î÷åùøéí',
'List' => 'øùéîä',
'Load' => 'èòï',
'Local' => 'î÷åîé',
'Log' => 'Log', // Added - 2011-06-16
'LoggedInAs' => 'התחבר כ',
'LoggedInAs' => 'äúçáø ë',
'Logging' => 'Logging', // Added - 2011-06-16
'LoggingIn' => 'מתחבר',
'Login' => 'התחבר',
'Logout' => 'התנתק',
'LoggingIn' => 'îúçáø',
'Login' => 'äúçáø',
'Logout' => 'äúðú÷',
'Logs' => 'Logs', // Added - 2011-06-17
'Low' => 'נמוך',
'LowBW' => 'נמוך&nbsp;ר/פ',
'Main' => 'מרכזי',
'Man' => 'מדריך',
'Manual' => 'מדריך',
'Mark' => 'סמן',
'Max' => 'מקס',
'MaxBandwidth' => 'רוחב פס מקס',
'MaxBrScore' => 'ניקוד<br/>מקסימלי',
'Low' => 'ðîåê',
'LowBW' => 'ðîåê&nbsp;ø/ô',
'Main' => 'îøëæé',
'Man' => 'îãøéê',
'Manual' => 'îãøéê',
'Mark' => 'ñîï',
'Max' => 'î÷ñ',
'MaxBandwidth' => 'øåçá ôñ î÷ñ',
'MaxBrScore' => 'ðé÷åã<br/>î÷ñéîìé',
'MaxFocusRange' => 'Max Focus Range',
'MaxFocusSpeed' => 'Max Focus Speed',
'MaxFocusStep' => 'Max Focus Step',
@ -438,7 +438,7 @@ $SLANG = array(
'MaxZoomSpeed' => 'Max Zoom Speed',
'MaxZoomStep' => 'Max Zoom Step',
'MaximumFPS' => 'Maximum FPS',
'Medium' => 'בינוני',
'Medium' => 'áéðåðé',
'MediumBW' => 'Medium&nbsp;B/W',
'Message' => 'Message', // Added - 2011-06-16
'MinAlarmAreaLtMax' => 'Minimum alarm area should be less than maximum',
@ -476,18 +476,18 @@ $SLANG = array(
'MinZoomStep' => 'Min Zoom Step',
'Misc' => 'Misc',
'Mode' => 'Mode', // Added - 2015-04-18
'Monitor' => 'מוניטור',
'Monitor' => 'îåðéèåø',
'MonitorIds' => 'Monitor&nbsp;Ids',
'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>',
'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
'Monitors' => 'מוניטורים',
'Monitors' => 'îåðéèåøéí',
'Montage' => 'Montage',
'Month' => 'חודש',
'Month' => 'çåãù',
'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip',
'Move' => 'הזז',
'Move' => 'äææ',
'Mtg2widgrd' => '2-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.
@ -498,48 +498,48 @@ $SLANG = array(
'MustConfirmPassword' => 'You must confirm the password',
'MustSupplyPassword' => 'You must supply a password',
'MustSupplyUsername' => 'You must supply a username',
'Name' => 'שם',
'Near' => 'ליד',
'Network' => 'רשת',
'New' => 'חדש',
'NewGroup' => 'קבוצה חדשה',
'NewLabel' => 'תווית חדשה',
'NewPassword' => 'סיסמא חדשה',
'NewState' => 'מצב חדש',
'NewUser' => 'משתמש חדש',
'Next' => 'הבא',
'No' => 'לא',
'Name' => 'ùí',
'Near' => 'ìéã',
'Network' => 'øùú',
'New' => 'çãù',
'NewGroup' => '÷áåöä çãùä',
'NewLabel' => 'úååéú çãùä',
'NewPassword' => 'ñéñîà çãùä',
'NewState' => 'îöá çãù',
'NewUser' => 'îùúîù çãù',
'Next' => 'äáà',
'No' => 'ìà',
'NoDetectedCameras' => 'No Detected Cameras', // Added - 2009-03-31
'NoFramesRecorded' => 'There are no frames recorded for this event',
'NoGroup' => 'ללא קבוצה',
'NoGroup' => 'ììà ÷áåöä',
'NoSavedFilters' => 'NoSavedFilters',
'NoStatisticsRecorded' => 'There are no statistics recorded for this event/frame',
'None' => 'ריק',
'NoneAvailable' => 'בלתי זמין',
'Normal' => 'נורמלי',
'None' => 'øé÷',
'NoneAvailable' => 'áìúé æîéï',
'Normal' => 'ðåøîìé',
'Notes' => 'Notes',
'NumPresets' => 'Num Presets',
'Off' => 'כבוי',
'On' => 'דלוק',
'Off' => 'ëáåé',
'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
'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
'OpEq' => 'שווה ל',
'OpGt' => 'גדול מ',
'OpEq' => 'ùååä ì',
'OpGt' => 'âãåì î',
'OpGtEq' => 'greater than or equal to',
'OpIn' => 'in set',
'OpLt' => 'פחות מ',
'OpLt' => 'ôçåú î',
'OpLtEq' => 'less than or equal to',
'OpMatches' => 'matches',
'OpNe' => 'אינו שווה',
'OpNe' => 'àéðå ùååä',
'OpNotIn' => 'not in set',
'OpNotMatches' => 'אינו תואם',
'Open' => 'פתח',
'OpNotMatches' => 'àéðå úåàí',
'Open' => 'ôúç',
'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.',
'Options' => 'אפשרויות',
'Options' => 'àôùøåéåú',
'OrEnterNewName' => 'or enter new name',
'Order' => 'מיון',
'Order' => 'îéåï',
'Orientation' => 'Orientation',
'Out' => 'Out',
'OverwriteExisting' => 'Overwrite Existing',
@ -548,200 +548,200 @@ $SLANG = array(
'PanLeft' => 'Pan Left',
'PanRight' => 'Pan Right',
'PanTilt' => 'Pan/Tilt',
'Parameter' => 'פרמטר',
'Password' => 'סיסמא',
'Parameter' => 'ôøîèø',
'Password' => 'ñéñîà',
'PasswordsDifferent' => 'The new and confirm passwords are different',
'Paths' => 'נתיבים',
'Paths' => 'ðúéáéí',
'Pause' => 'Pause',
'Phone' => 'טלפון',
'PhoneBW' => 'ר/פ&nbsp;טלפון',
'Phone' => 'èìôåï',
'PhoneBW' => 'ø/ô&nbsp;èìôåï',
'Pid' => 'PID', // Added - 2011-06-16
'PixelDiff' => 'Pixel Diff',
'Pixels' => 'פיקסלים',
'Pixels' => 'ôé÷ñìéí',
'Play' => 'Play',
'PlayAll' => 'נגן הכל',
'PleaseWait' => 'המתן בבקשה',
'PlayAll' => 'ðâï äëì',
'PleaseWait' => 'äîúï áá÷ùä',
'Plugins' => 'Plugins',
'Point' => 'נקודה',
'Point' => 'ð÷åãä',
'PostEventImageBuffer' => 'Post Event Image Count',
'PreEventImageBuffer' => 'Pre Event Image Count',
'PreserveAspect' => 'Preserve Aspect Ratio',
'Preset' => 'Preset',
'Presets' => 'Presets',
'Prev' => 'הקודם',
'Prev' => 'ä÷åãí',
'Probe' => 'Probe', // Added - 2009-03-31
'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18
'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .<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
'Protocol' => 'Protocol',
'Rate' => 'דירוג',
'Real' => 'אמיתי',
'Record' => 'הקלטה',
'Rate' => 'ãéøåâ',
'Real' => 'àîéúé',
'Record' => 'ä÷ìèä',
'RefImageBlendPct' => 'Reference Image Blend %ge',
'Refresh' => 'רענון',
'Remote' => 'מרוחק',
'RemoteHostName' => 'שם מארח מרוחק',
'RemoteHostPath' => 'נתיב מארח מרוחק',
'RemoteHostPort' => 'פורט מארח מרוחק',
'Refresh' => 'øòðåï',
'Remote' => 'îøåç÷',
'RemoteHostName' => 'ùí îàøç îøåç÷',
'RemoteHostPath' => 'ðúéá îàøç îøåç÷',
'RemoteHostPort' => 'ôåøè îàøç îøåç÷',
'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08
'RemoteImageColours' => 'Remote Image Colours',
'RemoteMethod' => 'Remote Method', // Added - 2009-02-08
'RemoteProtocol' => 'Remote Protocol', // Added - 2009-02-08
'Rename' => 'שנה שם',
'Rename' => 'ùðä ùí',
'Replay' => 'Replay',
'ReplayAll' => 'All Events',
'ReplayGapless' => 'Gapless Events',
'ReplaySingle' => 'Single Event',
'Reset' => 'אפס',
'Reset' => 'àôñ',
'ResetEventCounts' => 'Reset Event Counts',
'Restart' => 'אתחל',
'Restarting' => 'מאתחל',
'Restart' => 'àúçì',
'Restarting' => 'îàúçì',
'RestrictedCameraIds' => 'Restricted Camera Ids',
'RestrictedMonitors' => 'Restricted Monitors',
'ReturnDelay' => 'חזרה מהשהיה',
'ReturnLocation' => 'מיקום חזרה',
'ReturnDelay' => 'çæøä îäùäéä',
'ReturnLocation' => 'îé÷åí çæøä',
'Rewind' => 'Rewind',
'RotateLeft' => 'סובב שמאלה',
'RotateRight' => 'סובב ימינה',
'RotateLeft' => 'ñåáá ùîàìä',
'RotateRight' => 'ñåáá éîéðä',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunMode' => 'צורת ריצה',
'RunState' => 'מצב ריצה',
'Running' => 'מריץ',
'Save' => 'שמור',
'SaveAs' => 'שמור בשם',
'SaveFilter' => 'שמור מסנן',
'Scale' => 'סקאלה',
'Score' => 'ניקוד',
'Secs' => 'שניות',
'Sectionlength' => 'אורך קטע',
'Select' => 'בחר',
'RunMode' => 'öåøú øéöä',
'RunState' => 'îöá øéöä',
'Running' => 'îøéõ',
'Save' => 'ùîåø',
'SaveAs' => 'ùîåø áùí',
'SaveFilter' => 'ùîåø îñðï',
'Scale' => 'ñ÷àìä',
'Score' => 'ðé÷åã',
'Secs' => 'ùðéåú',
'Sectionlength' => 'àåøê ÷èò',
'Select' => 'áçø',
'SelectFormat' => 'Select Format', // Added - 2011-06-17
'SelectLog' => 'Select Log', // Added - 2011-06-17
'SelectMonitors' => 'בחר מוניטורים',
'SelectMonitors' => 'áçø îåðéèåøéí',
'SelfIntersecting' => 'Polygon edges must not intersect',
'Set' => 'קבע',
'Set' => '÷áò',
'SetNewBandwidth' => 'Set New Bandwidth',
'SetPreset' => 'Set Preset',
'Settings' => 'הגדרות',
'Settings' => 'äâãøåú',
'ShowFilterWindow' => 'Show Filter Window',
'ShowTimeline' => 'Show Timeline',
'SignalCheckColour' => 'Signal Check Colour',
'Size' => 'גודל',
'Size' => 'âåãì',
'SkinDescription' => 'Change the default skin for this computer', // Added - 2011-01-30
'Sleep' => 'שינה',
'Sleep' => 'ùéðä',
'SortAsc' => 'Asc',
'SortBy' => 'Sort by',
'SortDesc' => 'Desc',
'Source' => 'מקור',
'Source' => 'î÷åø',
'SourceColours' => 'Source Colours', // Added - 2009-02-08
'SourcePath' => 'Source Path', // Added - 2009-02-08
'SourceType' => 'סוג מקור',
'Speed' => 'מהירות',
'SpeedHigh' => 'מהירות גבוהה',
'SpeedLow' => 'מהירות נמוכה',
'SpeedMedium' => 'מצלמה בינונית',
'SpeedTurbo' => 'מהירות טורבו',
'Start' => 'התחל',
'State' => 'מצב',
'Stats' => 'מצבים',
'Status' => 'סטטוס',
'Step' => 'צעד',
'SourceType' => 'ñåâ î÷åø',
'Speed' => 'îäéøåú',
'SpeedHigh' => 'îäéøåú âáåää',
'SpeedLow' => 'îäéøåú ðîåëä',
'SpeedMedium' => 'îöìîä áéðåðéú',
'SpeedTurbo' => 'îäéøåú èåøáå',
'Start' => 'äúçì',
'State' => 'îöá',
'Stats' => 'îöáéí',
'Status' => 'ñèèåñ',
'Step' => 'öòã',
'StepBack' => 'Step Back',
'StepForward' => 'Step Forward',
'StepLarge' => 'צעד גדול',
'StepMedium' => 'צעד בינוני',
'StepNone' => 'אל תצעד',
'StepSmall' => 'צעד קטן',
'Stills' => 'סטילס',
'Stop' => 'עצור',
'Stopped' => 'נעצר',
'Stream' => 'סטרים',
'StepLarge' => 'öòã âãåì',
'StepMedium' => 'öòã áéðåðé',
'StepNone' => 'àì úöòã',
'StepSmall' => 'öòã ÷èï',
'Stills' => 'ñèéìñ',
'Stop' => 'òöåø',
'Stopped' => 'ðòöø',
'Stream' => 'ñèøéí',
'StreamReplayBuffer' => 'Stream Replay Image Buffer',
'Submit' => 'Submit',
'System' => 'מערכת',
'System' => 'îòøëú',
'SystemLog' => 'System Log', // Added - 2011-06-16
'TargetColorspace' => 'Target colorspace', // Added - 2015-04-18
'Tele' => 'טל',
'Tele' => 'èì',
'Thumbnail' => 'Thumbnail',
'Tilt' => 'Tilt',
'Time' => 'זמן',
'TimeDelta' => 'שינוי בזמן',
'TimeStamp' => 'חותמת זמן',
'Timeline' => 'קו זמן',
'Time' => 'æîï',
'TimeDelta' => 'ùéðåé áæîï',
'TimeStamp' => 'çåúîú æîï',
'Timeline' => '÷å æîï',
'TimelineTip1' => 'Pass your mouse over the graph to view a snapshot image and event details.', // Added 2013.08.15.
'TimelineTip2' => 'Click on the coloured sections of the graph, or the image, to view the event.', // Added 2013.08.15.
'TimelineTip3' => 'Click on the background to zoom in to a smaller time period based around your click.', // Added 2013.08.15.
'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // Added 2013.08.15.
'Timestamp' => 'חותמת זמן',
'Timestamp' => 'çåúîú æîï',
'TimestampLabelFormat' => 'Timestamp Label Format',
'TimestampLabelX' => 'Timestamp Label X',
'TimestampLabelY' => 'Timestamp Label Y',
'Today' => 'היום',
'Tools' => 'כלים',
'Today' => 'äéåí',
'Tools' => 'ëìéí',
'Total' => 'Total', // Added - 2011-06-16
'TotalBrScore' => 'סך<br/>ניקוד',
'TotalBrScore' => 'ñê<br/>ðé÷åã',
'TrackDelay' => 'Track Delay',
'TrackMotion' => 'Track Motion',
'Triggers' => 'טריגרים',
'Triggers' => 'èøéâøéí',
'TurboPanSpeed' => 'Turbo Pan Speed',
'TurboTiltSpeed' => 'Turbo Tilt Speed',
'Type' => 'סוג',
'Unarchive' => 'בלתי ארכיב',
'Type' => 'ñåâ',
'Unarchive' => 'áìúé àøëéá',
'Undefined' => 'Undefined', // Added - 2009-02-08
'Units' => 'יחידות',
'Unknown' => 'בלתי ידוע',
'Update' => 'עדכון',
'UpdateAvailable' => 'עדכון לזון-מינדר אפשרי.',
'UpdateNotNecessary' => 'עדכון אינו הכרחי.',
'Units' => 'éçéãåú',
'Unknown' => 'áìúé éãåò',
'Update' => 'òãëåï',
'UpdateAvailable' => 'òãëåï ìæåï-îéðãø àôùøé.',
'UpdateNotNecessary' => 'òãëåï àéðå äëøçé.',
'Updated' => 'Updated', // Added - 2011-06-16
'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'
'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',
'User' => 'משתמש',
'Username' => 'שם משתמש',
'Users' => 'משתמשים',
'User' => 'îùúîù',
'Username' => 'ùí îùúîù',
'Users' => 'îùúîùéí',
'V4L' => 'V4L', // Added - 2015-04-18
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
'Value' => 'ערך',
'Version' => 'גירסה',
'VersionIgnore' => 'התעלם מגירסה זו',
'VersionRemindDay' => 'הזכר לי בעוד יום אחד',
'VersionRemindHour' => 'הזכר לי בעוד שעה אחת',
'Value' => 'òøê',
'Version' => 'âéøñä',
'VersionIgnore' => 'äúòìí îâéøñä æå',
'VersionRemindDay' => 'äæëø ìé áòåã éåí àçã',
'VersionRemindHour' => 'äæëø ìé áòåã ùòä àçú',
'VersionRemindNever' => 'Don\'t remind about new versions',
'VersionRemindWeek' => 'Remind again in 1 week',
'Video' => 'וידאו',
'VideoFormat' => 'תבנית וידאו',
'Video' => 'åéãàå',
'VideoFormat' => 'úáðéú åéãàå',
'VideoGenFailed' => 'Video Generation Failed!',
'VideoGenFiles' => 'Existing Video Files',
'VideoGenNoFiles' => 'No Video Files Found',
'VideoGenParms' => 'Video Generation Parameters',
'VideoGenSucceeded' => 'Video Generation Succeeded!',
'VideoSize' => 'גודל וידאו',
'View' => 'הצג',
'ViewAll' => 'הצג הכל',
'ViewEvent' => 'הצג אירוע',
'VideoSize' => 'âåãì åéãàå',
'View' => 'äöâ',
'ViewAll' => 'äöâ äëì',
'ViewEvent' => 'äöâ àéøåò',
'ViewPaged' => 'View Paged',
'Wake' => 'הער',
'Wake' => 'äòø',
'WarmupFrames' => 'Warmup Frames',
'Watch' => 'צפה',
'Web' => 'אינטרנט',
'WebColour' => 'צבע אינטרנט',
'Week' => 'שבוע',
'White' => 'לבן',
'Watch' => 'öôä',
'Web' => 'àéðèøðè',
'WebColour' => 'öáò àéðèøðè',
'Week' => 'ùáåò',
'White' => 'ìáï',
'WhiteBalance' => 'White Balance',
'Wide' => 'רחב',
'Wide' => 'øçá',
'X' => 'X',
'X10' => 'X10',
'X10ActivationString' => 'X10 Activation String',
'X10InputAlarmString' => 'X10 Input Alarm String',
'X10OutputAlarmString' => 'X10 Output Alarm String',
'Y' => 'Y',
'Yes' => 'כן',
'YouNoPerms' => 'אין לך הרשאה להיכנס למקור זה.',
'Zone' => 'אזור',
'Yes' => 'ëï',
'YouNoPerms' => 'àéï ìê äøùàä ìäéëðñ ìî÷åø æä.',
'Zone' => 'àæåø',
'ZoneAlarmColour' => 'Alarm Colour (Red/Green/Blue)',
'ZoneArea' => 'Zone Area',
'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count',
@ -753,10 +753,10 @@ $SLANG = array(
'ZoneMinMaxPixelThres' => 'Min/Max Pixel Threshold (0-255)',
'ZoneMinderLog' => 'ZoneMinder Log', // Added - 2011-06-17
'ZoneOverloadFrames' => 'Overload Frame Ignore Count',
'Zones' => 'אזורים',
'Zoom' => 'זום',
'ZoomIn' => 'זום פנימה',
'ZoomOut' => 'זום החוצה',
'Zones' => 'àæåøéí',
'Zoom' => 'æåí',
'ZoomIn' => 'æåí ôðéîä',
'ZoomOut' => 'æåí äçåöä',
);
// 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
//
// 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
@ -18,7 +18,7 @@ $SLANG = array(
'Actual' => 'Atual',
'AddNewControl' => 'Add New Control',
'AddNewMonitor' => 'Adicionar Monitor',
'AddNewUser' => 'Adicionar Usuário',
'AddNewUser' => 'Adicionar Usuário',
'AddNewZone' => 'Adicionar Zona',
'Alarm' => 'Alarme',
'AlarmBrFrames' => 'Imagens<br/>Alarmadas',
@ -34,7 +34,7 @@ $SLANG = array(
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
'Apply' => 'Aplicar',
'ApplyingStateChange' => 'Aplicando mudança de estado',
'ApplyingStateChange' => 'Aplicando mudança de estado',
'ArchArchived' => 'Somente Arquivados',
'ArchUnarchived' => 'Somente Nao Arquivados',
'Archive' => 'Arquivar',
@ -49,7 +49,7 @@ $SLANG = array(
'AttrDateTime' => 'Data/Horario',
'AttrDiskBlocks' => 'Blocos de Disco',
'AttrDiskPercent' => 'Porcentagem de Disco',
'AttrDuration' => 'Duração',
'AttrDuration' => 'Duração',
'AttrFrames' => 'Imagens',
'AttrId' => 'Id',
'AttrMaxScore' => 'Max. Score',
@ -58,7 +58,7 @@ $SLANG = array(
'AttrName' => 'Nome',
'AttrNotes' => 'Notes',
'AttrSystemLoad' => 'System Load',
'AttrTime' => 'Horário',
'AttrTime' => 'Horário',
'AttrTotalScore' => 'Score Total',
'AttrWeekday' => 'Dia/Semana',
'Auto' => 'Auto',
@ -84,7 +84,7 @@ $SLANG = array(
'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',
'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
'BadPath' => 'Path must be set to a valid value',
'BadPort' => 'Port must be set to a valid number',
@ -145,7 +145,7 @@ $SLANG = array(
'CanZoomCon' => 'Can Zoom Continuous',
'CanZoomRel' => 'Can Zoom Relative',
'Cancel' => 'Cancelar',
'CancelForcedAlarm' => 'Cancelar Alarme Forçado',
'CancelForcedAlarm' => 'Cancelar Alarme Forçado',
'CaptureHeight' => 'Altura da Captura',
'CaptureMethod' => 'Capture Method', // Added - 2009-02-08
'CapturePalette' => 'Paleta de Captura',
@ -192,10 +192,10 @@ $SLANG = array(
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18
'Delete' => 'Deletar',
'DeleteAndNext' => 'Deletar &amp; Próx',
'DeleteAndNext' => 'Deletar &amp; Próx',
'DeleteAndPrev' => 'Deletar &amp; Ant',
'DeleteSavedFilter' => 'Deletar Filtros Salvos',
'Description' => 'Descrição',
'Description' => 'Descrição',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
'DetectedProfiles' => 'Detected Profiles', // Added - 2015-04-18
'Device' => 'Device', // Added - 2009-02-08
@ -204,7 +204,7 @@ $SLANG = array(
'DeviceNumber' => 'Num. do Dispos.',
'DevicePath' => 'Device Path',
'Devices' => 'Devices',
'Dimensions' => 'Dimensões',
'Dimensions' => 'Dimensões',
'DisableAlarms' => 'Disable Alarms',
'Disk' => 'Disco',
'Display' => 'Display', // Added - 2011-01-30
@ -221,15 +221,15 @@ $SLANG = array(
'DonateYes' => 'Yes, I\'d like to donate now',
'Download' => 'Download',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
'Duration' => 'Duração',
'Duration' => 'Duração',
'Edit' => 'Editar',
'Email' => 'Email',
'EnableAlarms' => 'Enable Alarms',
'Enabled' => 'Habilitado',
'EnterNewFilterName' => 'Digite nome do novo filtro',
'Error' => 'Erro',
'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',
'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',
'Etc' => 'etc',
'Event' => 'Evento',
'EventFilter' => 'Filtro de Evento',
@ -283,7 +283,7 @@ $SLANG = array(
'FnNone' => 'None', // Added 2013.08.16.
'FnRecord' => 'Record', // Added 2013.08.16.
'Focus' => 'Focus',
'ForceAlarm' => 'Forçar Alarme',
'ForceAlarm' => 'Forçar Alarme',
'Format' => 'Format',
'Frame' => 'Imagem',
'FrameId' => 'Id de Imagem',
@ -291,7 +291,7 @@ $SLANG = array(
'FrameSkip' => 'Salto de Imagem',
'Frames' => 'Imagens',
'Func' => 'Func',
'Function' => 'Função',
'Function' => 'Função',
'Gain' => 'Gain',
'General' => 'General',
'GenerateVideo' => 'Gerar Video',
@ -315,7 +315,7 @@ $SLANG = array(
'HighBW' => 'Alta&nbsp;L/B',
'Home' => 'Home',
'Hour' => 'Hora',
'Hue' => 'Saturação',
'Hue' => 'Saturação',
'Id' => 'Id',
'Idle' => 'Parado',
'Ignore' => 'Ignorar',
@ -329,7 +329,7 @@ $SLANG = array(
'KeyString' => 'Key String',
'Label' => 'Label',
'Language' => 'Linguagem',
'Last' => 'Último',
'Last' => 'Último',
'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16
'Libvlc' => 'Libvlc',
@ -383,7 +383,7 @@ $SLANG = array(
'Message' => 'Message', // Added - 2011-06-16
'MinAlarmAreaLtMax' => 'Minimum alarm area should be less than maximum',
'MinAlarmAreaUnset' => 'You must specify the minimum alarm pixel count',
'MinBlobAreaLtMax' => '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',
'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',
@ -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
'Monitors' => 'Monitores',
'Montage' => 'Montagem',
'Month' => 'Mês',
'Month' => 'Mês',
'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip',
'Move' => 'Move',
@ -437,7 +437,7 @@ $SLANG = array(
'MustBeLe' => 'deve ser menor ou igual a',
'MustConfirmPassword' => 'Voce deve Confirmar 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',
'Near' => 'Near',
'Network' => 'Rede',
@ -446,16 +446,16 @@ $SLANG = array(
'NewLabel' => 'New Label',
'NewPassword' => 'Nova Senha',
'NewState' => 'Novo Estado',
'NewUser' => 'Novo Usuário',
'Next' => 'Próx',
'No' => 'Não',
'NewUser' => 'Novo Usuário',
'Next' => 'Próx',
'No' => 'Não',
'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',
'NoSavedFilters' => 'SemFiltrosSalvos',
'NoStatisticsRecorded' => 'Não há estatísticas gravadas neste evento/imagem',
'NoStatisticsRecorded' => 'Não há estatísticas gravadas neste evento/imagem',
'None' => 'Nada',
'NoneAvailable' => 'Nada disponível',
'NoneAvailable' => 'Nada disponível',
'Normal' => 'Normal',
'Notes' => 'Notes',
'NumPresets' => 'Num Presets',
@ -472,15 +472,15 @@ $SLANG = array(
'OpLtEq' => 'menor que ou igual a',
'OpMatches' => 'combina',
'OpNe' => 'diferente de',
'OpNotIn' => 'não no set',
'OpNotMatches' => 'não combina',
'OpNotIn' => 'não no set',
'OpNotMatches' => 'não combina',
'Open' => 'Open',
'OptionHelp' => 'OpçãoAjuda',
'OptionRestartWarning' => 'Reinicie o Zoneminder para que as mudanças tenham efeito',
'Options' => 'Opções',
'OptionHelp' => 'OpçãoAjuda',
'OptionRestartWarning' => 'Reinicie o Zoneminder para que as mudanças tenham efeito',
'Options' => 'Opções',
'OrEnterNewName' => 'ou defina novo nome',
'Order' => 'Order',
'Orientation' => 'Orientação',
'Orientation' => 'Orientação',
'Out' => 'Out',
'OverwriteExisting' => 'Sobrescrever Existente',
'Paged' => 'Paginado',
@ -490,7 +490,7 @@ $SLANG = array(
'PanTilt' => 'Pan/Tilt',
'Parameter' => 'Parametro',
'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',
'Pause' => 'Pause',
'Phone' => 'Phone',
@ -503,8 +503,8 @@ $SLANG = array(
'PleaseWait' => 'Por Favor Espere',
'Plugins' => 'Plugins',
'Point' => 'Point',
'PostEventImageBuffer' => 'Buffer de imagem pós evento',
'PreEventImageBuffer' => 'Buffer de imagem pré evento',
'PostEventImageBuffer' => 'Buffer de imagem pós evento',
'PreEventImageBuffer' => 'Buffer de imagem pré evento',
'PreserveAspect' => 'Preserve Aspect Ratio',
'Preset' => 'Preset',
'Presets' => 'Presets',
@ -517,7 +517,7 @@ $SLANG = array(
'Rate' => 'Vel.',
'Real' => 'Real',
'Record' => 'Gravar',
'RefImageBlendPct' => 'Referência de imagem Blend %ge',
'RefImageBlendPct' => 'Referência de imagem Blend %ge',
'Refresh' => 'Atualizar',
'Remote' => 'Remoto',
'RemoteHostName' => 'Nome do host remoto',
@ -536,16 +536,16 @@ $SLANG = array(
'ResetEventCounts' => 'Resetar contagem de eventos',
'Restart' => 'Reiniciar',
'Restarting' => 'Reiniciando',
'RestrictedCameraIds' => 'Ids de camera proibídos',
'RestrictedCameraIds' => 'Ids de camera proibídos',
'RestrictedMonitors' => 'Restricted Monitors',
'ReturnDelay' => 'Return Delay',
'ReturnLocation' => 'Return Location',
'Rewind' => 'Rewind',
'RotateLeft' => 'Rotacionar à esquerda ',
'RotateRight' => 'Rotacionar à direita',
'RotateLeft' => 'Rotacionar à esquerda ',
'RotateRight' => 'Rotacionar à direita',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunMode' => 'Modo de Execução',
'RunState' => 'Estado de Execução',
'RunMode' => 'Modo de Execução',
'RunState' => 'Estado de Execução',
'Running' => 'Rodando',
'Save' => 'Salvar',
'SaveAs' => 'Salvar Como',
@ -562,7 +562,7 @@ $SLANG = array(
'Set' => 'Set',
'SetNewBandwidth' => 'Defina Nova L/B',
'SetPreset' => 'Set Preset',
'Settings' => 'Configurações',
'Settings' => 'Configurações',
'ShowFilterWindow' => 'MostrarJanelaDeFiltros',
'ShowTimeline' => 'Show Timeline',
'SignalCheckColour' => 'Signal Check Colour',
@ -595,7 +595,7 @@ $SLANG = array(
'Stills' => 'Imagens',
'Stop' => 'Parar',
'Stopped' => 'Parado',
'Stream' => 'Contínuo',
'Stream' => 'Contínuo',
'StreamReplayBuffer' => 'Stream Replay Image Buffer',
'Submit' => 'Submit',
'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.
'Timestamp' => 'Tempo',
'TimestampLabelFormat' => 'Formato de etiqueta de tempo',
'TimestampLabelX' => 'posição de etiqueta X',
'TimestampLabelY' => 'posição de etiqueta Y',
'TimestampLabelX' => 'posição de etiqueta X',
'TimestampLabelY' => 'posição de etiqueta Y',
'Today' => 'Today',
'Tools' => 'Ferramentas',
'Total' => 'Total', // Added - 2011-06-16
@ -631,35 +631,35 @@ $SLANG = array(
'Units' => 'Unidades',
'Unknown' => 'Desconhecido',
'Update' => 'Update',
'UpdateAvailable' => 'Um update ao zoneminder está disponível.',
'UpdateNotNecessary' => 'Não é necessário update.',
'UpdateAvailable' => 'Um update ao zoneminder está disponível.',
'UpdateNotNecessary' => 'Não é necessário update.',
'Updated' => 'Updated', // Added - 2011-06-16
'Upload' => 'Upload', // Added - 2011-08-23
'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'
'UsedPlugins' => 'Used Plugins',
'User' => 'Usuário',
'Username' => 'Nome de Usuário',
'Users' => 'Usuários',
'User' => 'Usuário',
'Username' => 'Nome de Usuário',
'Users' => 'Usuários',
'V4L' => 'V4L', // Added - 2015-04-18
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
'Value' => 'Valor',
'Version' => 'Versão',
'VersionIgnore' => 'Ignorar esta versão',
'Version' => 'Versão',
'VersionIgnore' => 'Ignorar esta versão',
'VersionRemindDay' => 'Lembre novamente em 1 dia',
'VersionRemindHour' => 'Lembre novamente em 1 hora',
'VersionRemindNever' => 'Nao lembrar novas versões',
'VersionRemindNever' => 'Nao lembrar novas versões',
'VersionRemindWeek' => 'Lembrar novamente em 1 semana',
'Video' => 'Video',
'VideoFormat' => 'Video Format',
'VideoGenFailed' => 'Geração de Vídeo falhou!',
'VideoGenFailed' => 'Geração de Vídeo falhou!',
'VideoGenFiles' => 'Existing Video Files',
'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!',
'VideoSize' => 'Tamanho do vídeo',
'VideoSize' => 'Tamanho do vídeo',
'View' => 'Ver',
'ViewAll' => 'Ver Tudo',
'ViewEvent' => 'View Event',
@ -675,12 +675,12 @@ $SLANG = array(
'Wide' => 'Wide',
'X' => 'X',
'X10' => 'X10',
'X10ActivationString' => 'String de Ativação X10',
'X10ActivationString' => 'String de Ativação 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',
'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',
'ZoneAlarmColour' => 'Cor de Alarme (Red/Green/Blue)',
'ZoneArea' => 'Zone Area',
@ -701,13 +701,13 @@ $SLANG = array(
// Complex replacements with formatting and/or placements, must be passed through sprintf
$CLANG = array(
'CurrentLogin' => 'Login atual é \'%1$s\'',
'CurrentLogin' => 'Login atual é \'%1$s\'',
'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)
'LatestRelease' => 'A Última versão é v%1$s, você tem v%2$s.',
'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.',
'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below)
'MonitorFunction' => 'Monitor %1$s Funcção',
'RunningRecentVer' => 'Você está usando a versão mais recente do ZoneMinder, v%s.',
'MonitorFunction' => 'Monitor %1$s Funcção',
'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
);

View File

@ -72,92 +72,92 @@
// Simple String Replacements
$SLANG = array(
'24BitColour' => '24 bitars färg',
'32BitColour' => '32 bitars färg', // Added - 2011-06-15
'8BitGrey' => '8 bit gråskala',
'24BitColour' => '24 bitars färg',
'32BitColour' => '32 bitars färg', // Added - 2011-06-15
'8BitGrey' => '8 bit gråskala',
'Action' => 'Action',
'Actual' => 'Verklig',
'AddNewControl' => 'Ny kontroll',
'AddNewMonitor' => 'Ny bevakare',
'AddNewUser' => 'Ny användare',
'AddNewUser' => 'Ny användare',
'AddNewZone' => 'Ny zon',
'Alarm' => 'Larm',
'AlarmBrFrames' => 'Larm<br/>ramar',
'AlarmFrame' => 'Larmram',
'AlarmFrameCount' => 'Larmramsräknare',
'AlarmLimits' => 'Larmgränser',
'AlarmMaximumFPS' => 'Max. ramar/s för larm',
'AlarmFrameCount' => 'Larmramsräknare',
'AlarmLimits' => 'Larmgränser',
'AlarmMaximumFPS' => 'Max. ramar/s för larm',
'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
'Alert' => 'Varning',
'All' => 'Alla',
'AnalysisFPS' => 'Analysis FPS', // Added - 2015-07-22
'AnalysisUpdateDelay' => 'Analysis Update Delay', // Added - 2015-07-23
'Apply' => 'Lägg till',
'ApplyingStateChange' => 'Aktivera statusändring',
'Apply' => 'Lägg till',
'ApplyingStateChange' => 'Aktivera statusändring',
'ArchArchived' => 'Arkivera endast',
'ArchUnarchived' => 'Endast ej arkiverade',
'Archive' => 'Arkiv',
'Archived' => 'Arkiverad',
'Area' => 'Område',
'AreaUnits' => 'Område (px/%)',
'Area' => 'Område',
'AreaUnits' => 'Område (px/%)',
'AttrAlarmFrames' => 'Larmramar',
'AttrArchiveStatus' => 'Arkivstatus',
'AttrAvgScore' => 'Ung. värde',
'AttrAvgScore' => 'Ung. värde',
'AttrCause' => 'Orsak',
'AttrDate' => 'Datum',
'AttrDateTime' => 'Datum/Tid',
'AttrDiskBlocks' => 'Diskblock',
'AttrDiskPercent' => 'Diskprocent',
'AttrDuration' => 'Längd',
'AttrDuration' => 'Längd',
'AttrFrames' => 'Ramar',
'AttrId' => 'Id',
'AttrMaxScore' => 'Max. värde',
'AttrMaxScore' => 'Max. värde',
'AttrMonitorId' => 'Bevakningsid',
'AttrMonitorName' => 'Bevakningsnamn',
'AttrName' => 'Namn',
'AttrNotes' => 'Notering',
'AttrSystemLoad' => 'Systemlast',
'AttrTime' => 'Tid',
'AttrTotalScore' => 'Totalvärde',
'AttrTotalScore' => 'Totalvärde',
'AttrWeekday' => 'Veckodag',
'Auto' => 'Automatik',
'AutoStopTimeout' => 'Tidsutlösning för automatstop',
'AutoStopTimeout' => 'Tidsutlösning för automatstop',
'Available' => 'Available', // Added - 2009-03-31
'AvgBrScore' => 'Ung.<br/>träff',
'AvgBrScore' => 'Ung.<br/>träff',
'Background' => 'Bakgrund',
'BackgroundFilter' => 'Kör filter i bakgrunden',
'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',
'BackgroundFilter' => 'Kör filter i bakgrunden',
'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',
'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
'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
'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',
'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',
'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://',
'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',
'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',
'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',
'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',
'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://',
'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',
'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',
'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
'BadPath' => 'Sökvägen måste innehålla ett giltigt värde',
'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',
'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',
'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',
'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',
'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',
'BadPath' => 'Sökvägen måste innehålla ett giltigt värde',
'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',
'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',
'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',
'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',
'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',
'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
'BlobPx' => 'Blob Px',
@ -168,7 +168,7 @@ $SLANG = array(
'Buffers' => 'Buffrar',
'CSSDescription' => 'Change the default css for this computer', // Added - 2015-04-18
'CanAutoFocus' => 'Har autofokus',
'CanAutoGain' => 'Har autonivå',
'CanAutoGain' => 'Har autonivå',
'CanAutoIris' => 'Har autoiris',
'CanAutoWhite' => 'Har autovitbalans.',
'CanAutoZoom' => 'Har autozoom',
@ -176,23 +176,23 @@ $SLANG = array(
'CanFocusAbs' => 'Har absolut fokus',
'CanFocusCon' => 'Har kontinuerlig fokus',
'CanFocusRel' => 'Har relativ fokus',
'CanGain' => 'Har nivå',
'CanGainAbs' => 'Har absolut nivå',
'CanGainCon' => 'Har kontinuerlig nivå',
'CanGainRel' => 'Har relativ nivå',
'CanGain' => 'Har nivå',
'CanGainAbs' => 'Har absolut nivå',
'CanGainCon' => 'Har kontinuerlig nivå',
'CanGainRel' => 'Har relativ nivå',
'CanIris' => 'Har iris',
'CanIrisAbs' => 'Har absolut iris',
'CanIrisCon' => 'Har kontinuerlig iris',
'CanIrisRel' => 'Har relativ iris',
'CanMove' => 'Har förflyttning',
'CanMoveAbs' => 'Har absolut förflyttning',
'CanMoveCon' => 'Har kontinuerlig förflyttning',
'CanMoveDiag' => 'Har diagonal förflyttning',
'CanMoveMap' => 'Har mappad förflyttning',
'CanMoveRel' => 'Har relativ förflyttning',
'CanMove' => 'Har förflyttning',
'CanMoveAbs' => 'Har absolut förflyttning',
'CanMoveCon' => 'Har kontinuerlig förflyttning',
'CanMoveDiag' => 'Har diagonal förflyttning',
'CanMoveMap' => 'Har mappad förflyttning',
'CanMoveRel' => 'Har relativ förflyttning',
'CanPan' => 'Har panorering',
'CanReset' => 'Har återställning',
'CanSetPresets' => 'Har förinställningar',
'CanReset' => 'Har återställning',
'CanSetPresets' => 'Har förinställningar',
'CanSleep' => 'Kan vila',
'CanTilt' => 'Kan tilta',
'CanWake' => 'Kan vakna',
@ -205,39 +205,39 @@ $SLANG = array(
'CanZoomAbs' => 'Kan zooma absolut',
'CanZoomCon' => 'Kan zooma kontinuerligt',
'CanZoomRel' => 'Kan zooma realativt',
'Cancel' => 'Ångra',
'CancelForcedAlarm' => 'Ångra tvingande larm',
'CaptureHeight' => 'Fångsthöjd',
'Cancel' => 'Ångra',
'CancelForcedAlarm' => 'Ångra tvingande larm',
'CaptureHeight' => 'Fångsthöjd',
'CaptureMethod' => 'Capture Method', // Added - 2009-02-08
'CapturePalette' => 'Fångstpalett',
'CapturePalette' => 'Fångstpalett',
'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18
'CaptureWidth' => 'Fångstbredd',
'CaptureWidth' => 'Fångstbredd',
'Cause' => 'Orsak',
'CheckMethod' => 'Larmkontrollmetod',
'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
'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17
'ChoosePreset' => 'Välj standard',
'ChoosePreset' => 'Välj standard',
'Clear' => 'Clear', // Added - 2011-06-16
'Close' => 'Stäng',
'Colour' => 'Färg',
'Close' => 'Stäng',
'Colour' => 'Färg',
'Command' => 'Kommando',
'Component' => 'Component', // Added - 2011-06-16
'Config' => 'Konfigurera',
'ConfiguredFor' => 'Konfigurerad för',
'ConfirmDeleteEvents' => 'Är du säker på att du vill ta bort dom valda händelserna?',
'ConfirmPassword' => 'Bekräfta lösenord',
'ConfiguredFor' => 'Konfigurerad för',
'ConfirmDeleteEvents' => 'Är du säker på att du vill ta bort dom valda händelserna?',
'ConfirmPassword' => 'Bekräfta lösenord',
'ConjAnd' => 'och',
'ConjOr' => 'eller',
'Console' => 'Konsoll',
'ContactAdmin' => 'Kontakta din administratör för detaljer.',
'Continue' => 'Fortsätt',
'ContactAdmin' => 'Kontakta din administratör för detaljer.',
'Continue' => 'Fortsätt',
'Contrast' => 'Kontrast',
'Control' => 'Kontroll',
'ControlAddress' => 'Kontrolladress',
'ControlCap' => 'Kontrollförmåga',
'ControlCaps' => 'Kontrollförmågor',
'ControlCap' => 'Kontrollförmåga',
'ControlCaps' => 'Kontrollförmågor',
'ControlDevice' => 'Kontrollenhet',
'ControlType' => 'Kontrolltyp',
'Controllable' => 'Kontrollerbar',
@ -253,8 +253,8 @@ $SLANG = array(
'Deinterlacing' => 'Deinterlacing', // Added - 2015-04-18
'Delay' => 'Delay', // Added - 2015-04-18
'Delete' => 'Radera',
'DeleteAndNext' => 'Radera &amp; Nästa',
'DeleteAndPrev' => 'Radera &amp; Föreg.',
'DeleteAndNext' => 'Radera &amp; Nästa',
'DeleteAndPrev' => 'Radera &amp; Föreg.',
'DeleteSavedFilter' => 'Radera sparade filter',
'Description' => 'Beskrivning',
'DetectedCameras' => 'Detected Cameras', // Added - 2009-03-31
@ -263,7 +263,7 @@ $SLANG = array(
'DeviceChannel' => 'Enhetskanal',
'DeviceFormat' => 'Enhetsformat',
'DeviceNumber' => 'Enhetsnummer',
'DevicePath' => 'Enhetssökväg',
'DevicePath' => 'Enhetssökväg',
'Devices' => 'Enheter',
'Dimensions' => 'Dimensioner',
'DisableAlarms' => 'Avaktivera larm',
@ -271,39 +271,39 @@ $SLANG = array(
'Display' => 'Display', // Added - 2011-01-30
'Displaying' => 'Displaying', // Added - 2011-06-16
'DoNativeMotionDetection'=> 'Do Native Motion Detection',
'Donate' => 'Var vänlig och donera',
'Donate' => 'Var vänlig och donera',
'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.',
'DonateRemindDay' => 'Inte än, påminn om 1 dag',
'DonateRemindHour' => 'Inte än, påminn om en 1 timme',
'DonateRemindMonth' => 'Inte än, påminn om 1 månad',
'DonateRemindNever' => 'Nej, Jag vill inte donera, påminn mig inte mer',
'DonateRemindWeek' => 'Inte än, påminn om 1 vecka',
'DonateYes' => 'Ja, jag vill gärna donera nu',
'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',
'DonateRemindHour' => 'Inte än, påminn om en 1 timme',
'DonateRemindMonth' => 'Inte än, påminn om 1 månad',
'DonateRemindNever' => 'Nej, Jag vill inte donera, påminn mig inte mer',
'DonateRemindWeek' => 'Inte än, påminn om 1 vecka',
'DonateYes' => 'Ja, jag vill gärna donera nu',
'Download' => 'Ladda ner',
'DuplicateMonitorName' => 'Duplicate Monitor Name', // Added - 2009-03-31
'Duration' => 'Längd',
'Duration' => 'Längd',
'Edit' => 'Redigera',
'Email' => 'E-post',
'EnableAlarms' => 'Aktivera larm',
'Enabled' => 'Aktiverad',
'EnterNewFilterName' => 'Mata in nytt filternamn',
'Error' => 'Fel',
'ErrorBrackets' => 'Fel, kontrollera att du har samma antal vänster som höger-hakar',
'ErrorValidValue' => 'Fel, kontrollera att alla parametrar har giltligt värde',
'ErrorBrackets' => 'Fel, kontrollera att du har samma antal vänster som höger-hakar',
'ErrorValidValue' => 'Fel, kontrollera att alla parametrar har giltligt värde',
'Etc' => 'etc',
'Event' => 'Händelse',
'EventFilter' => 'Händelsefilter',
'EventId' => 'Händelse nr',
'EventName' => 'Händelsenamn',
'EventPrefix' => 'Händelseprefix',
'Events' => 'Händelser',
'Event' => 'Händelse',
'EventFilter' => 'Händelsefilter',
'EventId' => 'Händelse nr',
'EventName' => 'Händelsenamn',
'EventPrefix' => 'Händelseprefix',
'Events' => 'Händelser',
'Exclude' => 'Exkludera',
'Execute' => 'Utför',
'Execute' => 'Utför',
'Export' => 'Exportera',
'ExportDetails' => 'Exportera händelsedetaljer',
'ExportDetails' => 'Exportera händelsedetaljer',
'ExportFailed' => 'Exporten misslyckades',
'ExportFormat' => 'Filformat för exporter',
'ExportFormat' => 'Filformat för exporter',
'ExportFormatTar' => 'Tar',
'ExportFormatZip' => 'Zip',
'ExportFrames' => 'Exportera ramdetaljer',
@ -323,20 +323,20 @@ $SLANG = array(
'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08
'File' => 'Fil',
'Filter' => 'Filter', // Added - 2015-04-18
'FilterArchiveEvents' => 'Arkivera alla träffar',
'FilterDeleteEvents' => 'Radera alla träffar',
'FilterEmailEvents' => 'Skicka e-post med detaljer om alla träffar',
'FilterExecuteEvents' => 'Utför kommando på alla träffar',
'FilterArchiveEvents' => 'Arkivera alla träffar',
'FilterDeleteEvents' => 'Radera alla träffar',
'FilterEmailEvents' => 'Skicka e-post med detaljer om alla träffar',
'FilterExecuteEvents' => 'Utför kommando på alla träffar',
'FilterLog' => 'Filter log', // Added - 2015-04-18
'FilterMessageEvents' => 'Meddela detaljer om alla träffar',
'FilterMessageEvents' => 'Meddela detaljer om alla träffar',
'FilterPx' => 'Filter Px',
'FilterUnset' => 'Du måste specificera filtrets bredd och höjd',
'FilterUploadEvents' => 'Ladda upp alla träffar',
'FilterVideoEvents' => 'Skapa video för alla träffar',
'FilterUnset' => 'Du måste specificera filtrets bredd och höjd',
'FilterUploadEvents' => 'Ladda upp alla träffar',
'FilterVideoEvents' => 'Skapa video för alla träffar',
'Filters' => 'Filter',
'First' => 'Först',
'FlippedHori' => 'Vänd horisontellt',
'FlippedVert' => 'Vänd vertikalt',
'First' => 'Först',
'FlippedHori' => 'Vänd horisontellt',
'FlippedVert' => 'Vänd vertikalt',
'FnMocord' => 'Mocord', // Added 2013.08.16.
'FnModect' => 'Modect', // Added 2013.08.16.
'FnMonitor' => 'Monitor', // Added 2013.08.16.
@ -349,31 +349,31 @@ $SLANG = array(
'Frame' => 'Ram',
'FrameId' => 'Ram id',
'FrameRate' => 'Ram hastighet',
'FrameSkip' => 'Hoppa över ram',
'FrameSkip' => 'Hoppa över ram',
'Frames' => 'Ramar',
'Func' => 'Funk',
'Function' => 'Funktion',
'Gain' => 'Nivå',
'Gain' => 'Nivå',
'General' => 'Generell',
'GenerateVideo' => 'Skapa video',
'GeneratingVideo' => 'Skapar video',
'GoToZoneMinder' => 'Gå till ZoneMinder.com',
'Grey' => 'Grå',
'GoToZoneMinder' => 'Gå till ZoneMinder.com',
'Grey' => 'Grå',
'Group' => 'Grupp',
'Groups' => 'Grupper',
'HasFocusSpeed' => 'Har focushastighet',
'HasGainSpeed' => 'Har nivåhastighet',
'HasHomePreset' => 'Har normalinställning',
'HasGainSpeed' => 'Har nivåhastighet',
'HasHomePreset' => 'Har normalinställning',
'HasIrisSpeed' => 'Har irishastighet',
'HasPanSpeed' => 'Har panoramahastighet',
'HasPresets' => 'Har förinställningar',
'HasPresets' => 'Har förinställningar',
'HasTiltSpeed' => 'Har tilthastighet',
'HasTurboPan' => 'Har turbopanorering',
'HasTurboTilt' => 'Har turbotilt',
'HasWhiteSpeed' => 'Har vitbalanshastighet',
'HasZoomSpeed' => 'Har Zoomhastighet',
'High' => 'Hög',
'HighBW' => 'Hög bandbredd',
'High' => 'Hög',
'HighBW' => 'Hög bandbredd',
'Home' => 'Hem',
'Hour' => 'Timme',
'Hue' => 'Hue',
@ -387,17 +387,17 @@ $SLANG = array(
'Include' => 'Inkludera',
'Inverted' => 'Inverterad',
'Iris' => 'Iris',
'KeyString' => 'Nyckelsträng',
'KeyString' => 'Nyckelsträng',
'Label' => 'Etikett',
'Language' => 'Språk',
'Language' => 'Språk',
'Last' => 'Sist',
'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16
'Libvlc' => 'Libvlc',
'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
'LinkedMonitors' => 'Länkade övervakare',
'LinkedMonitors' => 'Länkade övervakare',
'List' => 'Lista',
'Load' => 'Belastning',
'Local' => 'Lokal',
@ -408,8 +408,8 @@ $SLANG = array(
'Login' => 'Logga in',
'Logout' => 'Logga ut',
'Logs' => 'Logs', // Added - 2011-06-17
'Low' => 'Låg',
'LowBW' => 'Låg bandbredd',
'Low' => 'Låg',
'LowBW' => 'Låg bandbredd',
'Main' => 'Huvudmeny',
'Man' => 'Man',
'Manual' => 'Manuell',
@ -417,75 +417,75 @@ $SLANG = array(
'Max' => 'Max',
'MaxBandwidth' => 'Max bandbredd',
'MaxBrScore' => 'Max.<br/>Score',
'MaxFocusRange' => 'Max fokusområde',
'MaxFocusRange' => 'Max fokusområde',
'MaxFocusSpeed' => 'Max fokushastighet',
'MaxFocusStep' => 'Max fokussteg',
'MaxGainRange' => 'Max nivåområde',
'MaxGainSpeed' => 'Max nivåhastighet',
'MaxGainStep' => 'Max nivåsteg',
'MaxIrisRange' => 'Max irsiområde',
'MaxGainRange' => 'Max nivåområde',
'MaxGainSpeed' => 'Max nivåhastighet',
'MaxGainStep' => 'Max nivåsteg',
'MaxIrisRange' => 'Max irsiområde',
'MaxIrisSpeed' => 'Max irishastighet',
'MaxIrisStep' => 'Max irissteg',
'MaxPanRange' => 'Max panoramaområde',
'MaxPanRange' => 'Max panoramaområde',
'MaxPanSpeed' => 'Max panoramahastighet',
'MaxPanStep' => 'Max panoramasteg',
'MaxTiltRange' => 'Max tiltområde',
'MaxTiltRange' => 'Max tiltområde',
'MaxTiltSpeed' => 'Max tilthastighet',
'MaxTiltStep' => 'Max tiltsteg',
'MaxWhiteRange' => 'Max vitbalansområde',
'MaxWhiteRange' => 'Max vitbalansområde',
'MaxWhiteSpeed' => 'Max vitbalanshastighet',
'MaxWhiteStep' => 'Max vitbalanssteg',
'MaxZoomRange' => 'Max zoomområde',
'MaxZoomRange' => 'Max zoomområde',
'MaxZoomSpeed' => 'Max zoomhastighet',
'MaxZoomStep' => 'Max zoomsteg',
'MaximumFPS' => 'Max ramar/s',
'Medium' => 'Mellan',
'MediumBW' => 'Mellan bandbredd',
'Message' => 'Message', // Added - 2011-06-16
'MinAlarmAreaLtMax' => 'Minsta larmarean skall vara mindre än största',
'MinAlarmAreaUnset' => 'Du måste ange minsta antal larmbildpunkter',
'MinBlobAreaLtMax' => 'Minsta blobarean skall vara mindre än högsta',
'MinBlobAreaUnset' => 'Du måste ange minsta antalet blobpixlar',
'MinBlobLtMinFilter' => 'Minsta blobarean skall vara mindre än eller lika med minsta filterarean',
'MinBlobsLtMax' => 'Minsta antalet blobbar skall vara mindre än största',
'MinBlobsUnset' => 'Du måste ange minsta antalet blobbar',
'MinFilterAreaLtMax' => 'Minsta filterarean skall vara mindre än högsta',
'MinFilterAreaUnset' => 'Du måste ange minsta antal filterbildpunkter',
'MinFilterLtMinAlarm' => 'Minsta filterarean skall vara mindre än eller lika med minsta larmarean',
'MinFocusRange' => 'Min fokusområde',
'MinAlarmAreaLtMax' => 'Minsta larmarean skall vara mindre än största',
'MinAlarmAreaUnset' => 'Du måste ange minsta antal larmbildpunkter',
'MinBlobAreaLtMax' => 'Minsta blobarean skall vara mindre än högsta',
'MinBlobAreaUnset' => 'Du måste ange minsta antalet blobpixlar',
'MinBlobLtMinFilter' => 'Minsta blobarean skall vara mindre än eller lika med minsta filterarean',
'MinBlobsLtMax' => 'Minsta antalet blobbar skall vara mindre än största',
'MinBlobsUnset' => 'Du måste ange minsta antalet blobbar',
'MinFilterAreaLtMax' => 'Minsta filterarean skall vara mindre än högsta',
'MinFilterAreaUnset' => 'Du måste ange minsta antal filterbildpunkter',
'MinFilterLtMinAlarm' => 'Minsta filterarean skall vara mindre än eller lika med minsta larmarean',
'MinFocusRange' => 'Min fokusområde',
'MinFocusSpeed' => 'Min fokushastighet',
'MinFocusStep' => 'Min fokussteg',
'MinGainRange' => 'Min nivåområde',
'MinGainSpeed' => 'Min nivåhastighet',
'MinGainStep' => 'Min nivåsteg',
'MinIrisRange' => 'Min irisområde',
'MinGainRange' => 'Min nivåområde',
'MinGainSpeed' => 'Min nivåhastighet',
'MinGainStep' => 'Min nivåsteg',
'MinIrisRange' => 'Min irisområde',
'MinIrisSpeed' => 'Min irishastighet',
'MinIrisStep' => 'Min irissteg',
'MinPanRange' => 'Min panoramaområde',
'MinPanRange' => 'Min panoramaområde',
'MinPanSpeed' => 'Min panoramahastighet',
'MinPanStep' => 'Min panoramasteg',
'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',
'MinTiltRange' => 'Min tiltområde',
'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',
'MinTiltRange' => 'Min tiltområde',
'MinTiltSpeed' => 'Min tilthastighet',
'MinTiltStep' => 'Min tiltsteg',
'MinWhiteRange' => 'Min vitbalansområde',
'MinWhiteRange' => 'Min vitbalansområde',
'MinWhiteSpeed' => 'Min vitbalanshastighet',
'MinWhiteStep' => 'Min vitbalanssteg',
'MinZoomRange' => 'Min zoomområde',
'MinZoomRange' => 'Min zoomområde',
'MinZoomSpeed' => 'Min zoomhastighet',
'MinZoomStep' => 'Min zoomsteg',
'Misc' => 'Övrigt',
'Misc' => 'Övrigt',
'Mode' => 'Mode', // Added - 2015-04-18
'Monitor' => 'Bevakning',
'MonitorIds' => 'Bevakningsnr',
'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>',
'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>',
'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
'Monitors' => 'Bevakare',
'Montage' => 'Montera',
'Month' => 'Månad',
'Month' => 'Månad',
'More' => 'More', // Added - 2011-06-16
'MotionFrameSkip' => 'Motion Frame Skip',
'Move' => 'Flytta',
@ -494,65 +494,65 @@ $SLANG = array(
'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15.
'Mtg4widgrd' => '4-wide grid', // Added 2013.08.15.
'MtgDefault' => 'Default', // Added 2013.08.15.
'MustBeGe' => 'måste vara större än eller lika med',
'MustBeLe' => 'måste vara mindre än eller lika med',
'MustConfirmPassword' => 'Du måste bekräfta lösenordet',
'MustSupplyPassword' => 'Du måste ange ett lösenord',
'MustSupplyUsername' => 'Du måste ange ett användarnamn',
'MustBeGe' => 'måste vara större än eller lika med',
'MustBeLe' => 'måste vara mindre än eller lika med',
'MustConfirmPassword' => 'Du måste bekräfta lösenordet',
'MustSupplyPassword' => 'Du måste ange ett lösenord',
'MustSupplyUsername' => 'Du måste ange ett användarnamn',
'Name' => 'Namn',
'Near' => 'Nära',
'Network' => 'Nätverk',
'Near' => 'Nära',
'Network' => 'Nätverk',
'New' => 'Ny',
'NewGroup' => 'Ny grupp',
'NewLabel' => 'Ny etikett',
'NewPassword' => 'Nytt lösenord',
'NewState' => 'Nytt läge',
'NewUser' => 'Ny användare',
'Next' => 'Nästa',
'NewPassword' => 'Nytt lösenord',
'NewState' => 'Nytt läge',
'NewUser' => 'Ny användare',
'Next' => 'Nästa',
'No' => 'Nej',
'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',
'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',
'NoneAvailable' => 'Ingen tillgänglig',
'NoneAvailable' => 'Ingen tillgänglig',
'Normal' => 'Normal',
'Notes' => 'Not.',
'NumPresets' => 'Antal förinställningar',
'NumPresets' => 'Antal förinställningar',
'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
'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
'OpEq' => 'lika med',
'OpGt' => 'större än',
'OpGtEq' => 'större än eller lika med',
'OpGt' => 'större än',
'OpGtEq' => 'större än eller lika med',
'OpIn' => 'in set',
'OpLt' => 'mindre än',
'OpLtEq' => 'mindre än eller lika med',
'OpLt' => 'mindre än',
'OpLtEq' => 'mindre än eller lika med',
'OpMatches' => 'matchar',
'OpNe' => 'inte lika med',
'OpNotIn' => 'inte i set',
'OpNotMatches' => 'matchar inte',
'Open' => 'Öppna',
'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.',
'Open' => 'Öppna',
'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.',
'Options' => 'Alternativ',
'OrEnterNewName' => 'eller skriv in nytt namn',
'Order' => 'Sortera',
'Orientation' => 'Orientation',
'Out' => 'Ut',
'OverwriteExisting' => 'Skriv över',
'OverwriteExisting' => 'Skriv över',
'Paged' => 'Paged',
'Pan' => 'Panorera',
'PanLeft' => 'Panorera vänster',
'PanRight' => 'Panorera höger',
'PanLeft' => 'Panorera vänster',
'PanRight' => 'Panorera höger',
'PanTilt' => 'Pan/Tilt',
'Parameter' => 'Parameter',
'Password' => 'Lösenord',
'PasswordsDifferent' => 'Lösenorden skiljer sig åt',
'Paths' => 'Sökvägar',
'Password' => 'Lösenord',
'PasswordsDifferent' => 'Lösenorden skiljer sig åt',
'Paths' => 'Sökvägar',
'Pause' => 'Paus',
'Phone' => 'Mobil',
'PhoneBW' => 'Mobil bandbredd',
@ -561,15 +561,15 @@ $SLANG = array(
'Pixels' => 'bildpunkter',
'Play' => 'Spela',
'PlayAll' => 'Visa alla',
'PleaseWait' => 'Vänta...',
'PleaseWait' => 'Vänta...',
'Plugins' => 'Plugins',
'Point' => 'Punkt',
'PostEventImageBuffer' => 'Post Event Image Count',
'PreEventImageBuffer' => 'Pre Event Image Count',
'PreserveAspect' => 'Bevara lägesförhållande',
'Preset' => 'Förinställning',
'Presets' => 'Förinställningar',
'Prev' => 'Föreg.',
'PreserveAspect' => 'Bevara lägesförhållande',
'Preset' => 'Förinställning',
'Presets' => 'Förinställningar',
'Prev' => 'Föreg.',
'Probe' => 'Probe', // Added - 2009-03-31
'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18
'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .<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',
'RefImageBlendPct' => 'Reference Image Blend %ge',
'Refresh' => 'Uppdatera',
'Remote' => 'Fjärr',
'RemoteHostName' => 'Fjärrnamn',
'RemoteHostPath' => 'Fjärrsökväg',
'RemoteHostPort' => 'Fjärrport',
'Remote' => 'Fjärr',
'RemoteHostName' => 'Fjärrnamn',
'RemoteHostPath' => 'Fjärrsökväg',
'RemoteHostPort' => 'Fjärrport',
'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08
'RemoteImageColours' => 'Fjärrbildfärger',
'RemoteImageColours' => 'Fjärrbildfärger',
'RemoteMethod' => 'Remote Method', // Added - 2009-02-08
'RemoteProtocol' => 'Remote Protocol', // Added - 2009-02-08
'Rename' => 'Byt namn',
'Replay' => 'Repris',
'ReplayAll' => 'Alla händelser',
'ReplayAll' => 'Alla händelser',
'ReplayGapless' => 'Gapless Events',
'ReplaySingle' => 'Ensam händelse',
'Reset' => 'Återställ',
'ResetEventCounts' => 'Återställ händelseräknare',
'Restart' => 'Återstart',
'Restarting' => 'Återstartar',
'RestrictedCameraIds' => 'Begränsade kameranr.',
'RestrictedMonitors' => 'Begränsade bevakare',
'ReturnDelay' => 'Fördröjd retur',
'ReturnLocation' => 'Återvänd till position',
'ReplaySingle' => 'Ensam händelse',
'Reset' => 'Återställ',
'ResetEventCounts' => 'Återställ händelseräknare',
'Restart' => 'Återstart',
'Restarting' => 'Återstartar',
'RestrictedCameraIds' => 'Begränsade kameranr.',
'RestrictedMonitors' => 'Begränsade bevakare',
'ReturnDelay' => 'Fördröjd retur',
'ReturnLocation' => 'Återvänd till position',
'Rewind' => 'Backa',
'RotateLeft' => 'Rotera vänster',
'RotateRight' => 'Rotera höger',
'RotateLeft' => 'Rotera vänster',
'RotateRight' => 'Rotera höger',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunMode' => 'Körläge',
'RunState' => 'Körläge',
'Running' => 'Körs',
'RunMode' => 'Körläge',
'RunState' => 'Körläge',
'Running' => 'Körs',
'Save' => 'Spara',
'SaveAs' => 'Spara som',
'SaveFilter' => 'Spara filter',
'Scale' => 'Skala',
'Score' => 'Resultat',
'Secs' => 'Sek',
'Sectionlength' => 'Sektionslängd',
'Select' => 'Välj',
'Sectionlength' => 'Sektionslängd',
'Select' => 'Välj',
'SelectFormat' => 'Select Format', // Added - 2011-06-17
'SelectLog' => 'Select Log', // Added - 2011-06-17
'SelectMonitors' => 'Välj bevakare',
'SelfIntersecting' => 'Polygonändarna får inte överlappa',
'Set' => 'Ställ in',
'SetNewBandwidth' => 'Ställ in ny bandbredd',
'SetPreset' => 'Ställ in förinställning',
'Settings' => 'Inställningar',
'ShowFilterWindow' => 'Visa fönsterfilter',
'SelectMonitors' => 'Välj bevakare',
'SelfIntersecting' => 'Polygonändarna får inte överlappa',
'Set' => 'Ställ in',
'SetNewBandwidth' => 'Ställ in ny bandbredd',
'SetPreset' => 'Ställ in förinställning',
'Settings' => 'Inställningar',
'ShowFilterWindow' => 'Visa fönsterfilter',
'ShowTimeline' => 'Visa tidslinje',
'SignalCheckColour' => 'Signal Check Colour',
'Size' => 'Storlek',
@ -633,31 +633,31 @@ $SLANG = array(
'SortAsc' => 'Stigande',
'SortBy' => 'Sortera',
'SortDesc' => 'Fallande',
'Source' => 'Källa',
'Source' => 'Källa',
'SourceColours' => 'Source Colours', // Added - 2009-02-08
'SourcePath' => 'Source Path', // Added - 2009-02-08
'SourceType' => 'Källtyp',
'SourceType' => 'Källtyp',
'Speed' => 'Hastighet',
'SpeedHigh' => 'Höghastighet',
'SpeedLow' => 'Låghastighet',
'SpeedHigh' => 'Höghastighet',
'SpeedLow' => 'Låghastighet',
'SpeedMedium' => 'Normalhastighet',
'SpeedTurbo' => 'Turbohastighet',
'Start' => 'Start',
'State' => 'Läge',
'State' => 'Läge',
'Stats' => 'Statistik',
'Status' => 'Status',
'Step' => 'Steg',
'StepBack' => 'Stepga bakåt',
'StepForward' => 'Stega framåt',
'StepBack' => 'Stepga bakåt',
'StepForward' => 'Stega framåt',
'StepLarge' => 'Stora steg',
'StepMedium' => 'Normalsteg',
'StepNone' => 'Inga steg',
'StepSmall' => 'Små steg',
'StepSmall' => 'Små steg',
'Stills' => 'Stillbilder',
'Stop' => 'Stopp',
'Stopped' => 'Stoppad',
'Stream' => 'Strömmande',
'StreamReplayBuffer' => 'Buffert för strömmande uppspelning',
'Stream' => 'Strömmande',
'StreamReplayBuffer' => 'Buffert för strömmande uppspelning',
'Submit' => 'Skicka',
'System' => 'System',
'SystemLog' => 'System Log', // Added - 2011-06-16
@ -667,22 +667,22 @@ $SLANG = array(
'Tilt' => 'Tilt',
'Time' => 'Tid',
'TimeDelta' => 'tidsdelta',
'TimeStamp' => 'Tidsstämpel',
'TimeStamp' => 'Tidsstämpel',
'Timeline' => 'Tidslinje',
'TimelineTip1' => 'Pass your mouse over the graph to view a snapshot image and event details.', // Added 2013.08.15.
'TimelineTip2' => 'Click on the coloured sections of the graph, or the image, to view the event.', // Added 2013.08.15.
'TimelineTip3' => 'Click on the background to zoom in to a smaller time period based around your click.', // Added 2013.08.15.
'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // Added 2013.08.15.
'Timestamp' => 'Tidsstämpel',
'TimestampLabelFormat' => 'Format på tidsstämpel',
'TimestampLabelX' => 'Värde på tidsstämpel X',
'TimestampLabelY' => 'Värde på tidsstämpel Y',
'Timestamp' => 'Tidsstämpel',
'TimestampLabelFormat' => 'Format på tidsstämpel',
'TimestampLabelX' => 'Värde på tidsstämpel X',
'TimestampLabelY' => 'Värde på tidsstämpel Y',
'Today' => 'Idag',
'Tools' => 'Verktyg',
'Total' => 'Total', // Added - 2011-06-16
'TotalBrScore' => 'Total<br/>Score',
'TrackDelay' => 'Spårfördröjning',
'TrackMotion' => 'Spåra rörelse',
'TrackDelay' => 'Spårfördröjning',
'TrackMotion' => 'Spåra rörelse',
'Triggers' => 'Triggers',
'TurboPanSpeed' => 'Turbo panoramahastighet',
'TurboTiltSpeed' => 'Turbo tilthastighet',
@ -690,63 +690,63 @@ $SLANG = array(
'Unarchive' => 'Packa upp',
'Undefined' => 'Undefined', // Added - 2009-02-08
'Units' => 'Enheter',
'Unknown' => 'Okänd',
'Unknown' => 'Okänd',
'Update' => 'Uppdatera',
'UpdateAvailable' => 'En uppdatering till ZoneMinder finns tillgänglig.',
'UpdateNotNecessary' => 'Ingen uppdatering behövs.',
'UpdateAvailable' => 'En uppdatering till ZoneMinder finns tillgänglig.',
'UpdateNotNecessary' => 'Ingen uppdatering behövs.',
'Updated' => 'Updated', // Added - 2011-06-16
'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'
'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',
'User' => 'Användare',
'Username' => 'Användarnamn',
'Users' => 'Användare',
'User' => 'Användare',
'Username' => 'Användarnamn',
'Users' => 'Användare',
'V4L' => 'V4L', // Added - 2015-04-18
'V4LCapturesPerFrame' => 'Captures Per Frame', // Added - 2015-04-18
'V4LMultiBuffer' => 'Multi Buffering', // Added - 2015-04-18
'Value' => 'Värde',
'Value' => 'Värde',
'Version' => 'Version',
'VersionIgnore' => 'Ignorera denna version',
'VersionRemindDay' => 'Påminn om 1 dag',
'VersionRemindHour' => 'Påminn om 1 timme',
'VersionRemindNever' => 'Påminn inte om nya versioner',
'VersionRemindWeek' => 'Påminn om en 1 vecka',
'VersionRemindDay' => 'Påminn om 1 dag',
'VersionRemindHour' => 'Påminn om 1 timme',
'VersionRemindNever' => 'Påminn inte om nya versioner',
'VersionRemindWeek' => 'Påminn om en 1 vecka',
'Video' => 'Video',
'VideoFormat' => 'Videoformat',
'VideoGenFailed' => 'Videogenereringen misslyckades!',
'VideoGenFiles' => 'Befintliga videofiler',
'VideoGenNoFiles' => 'Inga videofiler',
'VideoGenParms' => 'Inställningar för videogenerering',
'VideoGenParms' => 'Inställningar för videogenerering',
'VideoGenSucceeded' => 'Videogenereringen lyckades!',
'VideoSize' => 'Videostorlek',
'View' => 'Visa',
'ViewAll' => 'Visa alla',
'ViewEvent' => 'Visa händelse',
'ViewEvent' => 'Visa händelse',
'ViewPaged' => 'Visa Paged',
'Wake' => 'Vakna',
'WarmupFrames' => 'Värm upp ramar',
'WarmupFrames' => 'Värm upp ramar',
'Watch' => 'Se',
'Web' => 'Webb',
'WebColour' => 'Webbfärg',
'WebColour' => 'Webbfärg',
'Week' => 'Vecka',
'White' => 'Vit',
'WhiteBalance' => 'Vitbalans',
'Wide' => 'Vid',
'X' => 'X',
'X10' => 'X10',
'X10ActivationString' => 'X10 aktiveringssträng',
'X10InputAlarmString' => 'X10 larmingångssträng',
'X10OutputAlarmString' => 'X10 larmutgångssträng',
'X10ActivationString' => 'X10 aktiveringssträng',
'X10InputAlarmString' => 'X10 larmingångssträng',
'X10OutputAlarmString' => 'X10 larmutgångssträng',
'Y' => 'J',
'Yes' => 'Ja',
'YouNoPerms' => 'Du har inte tillstånd till denna resurs.',
'YouNoPerms' => 'Du har inte tillstånd till denna resurs.',
'Zone' => 'Zon',
'ZoneAlarmColour' => 'Larmfärg (Röd/Grön/Blå)',
'ZoneAlarmColour' => 'Larmfärg (Röd/Grön/Blå)',
'ZoneArea' => 'Zonarea',
'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count',
'ZoneFilterSize' => 'Filterbredd/höjd (pixlar)',
'ZoneFilterSize' => 'Filterbredd/höjd (pixlar)',
'ZoneMinMaxAlarmArea' => 'Min/Max larmarea',
'ZoneMinMaxBlobArea' => 'Min/Max blobbarea',
'ZoneMinMaxBlobs' => 'Min/Max blobbar',
@ -762,13 +762,13 @@ $SLANG = array(
// Complex replacements with formatting and/or placements, must be passed through sprintf
$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)
'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)
'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
);
@ -806,7 +806,7 @@ $CLANG = array(
// Variable arrays expressing plurality, see the zmVlang description above
$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' ),
);
@ -826,7 +826,7 @@ function zmVlang( $langVarArray, $count )
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
@ -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_
$OLANG = array(
'LANG_DEFAULT' => array(
'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."
'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."
),
'OPTIONS_FFMPEG' => array(
'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;
}
#dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
margin: 0 3px;
}
#dvrControls input[disabled] {
color: #aaaaaa;
}

View File

@ -18,21 +18,19 @@
// 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 xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $title ?></title>
<style type="text/css">
<!--
<?php include( ZM_SKIN_PATH.'/css/'.ZM_SKIN_NAME.'/export.css' ); ?>
<html lang="en">
<head>
<meta charset="utf-8">
<title><?php echo $title ?></title>
<style type="text/css">
<!--
<?php include(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/css/'.ZM_SKIN_NAME.'/export.css'); ?>
ul.tabs {
margin: 0;
margin-bottom: -1px;
margin-bottom: -1px;
padding: 0;
float: left;
list-style: none;
@ -70,50 +68,46 @@ html ul.tabs li.active, html ul.tabs li.active a:hover {
border-bottom: 1px solid #e0e0e0;
}
-->
</style>
<script type="text/javascript">
<?php include(ZM_SKIN_PATH.'/js/jquery.js') ?>
</script>
<script type="text/javascript" language="javascript" charset="utf-8">
</style>
<script type="text/javascript" src="<?php echo ($title == translate('Images').' Master' ? '' : '../') ?>jquery.js"></script>
<!--<script type="text/javascript" src="<?php echo ($title == translate('Images').' Master' ? '' : '../') ?>video.js"></script>-->
<script type="text/javascript">
/*==========[tab code]==========*/
$(document).ready(function() {
/*==========[tab code]==========*/
$(document).ready(function() {
//When page loads...
$(".tab_content").hide(); //Hide all content
$("ul.tabs li:first").addClass("active").show(); //Activate first tab
$(".tab_content:first").show(); //Show first tab content
//When page loads...
$(".tab_content").hide(); //Hide all content
$("ul.tabs li:first").addClass("active").show(); //Activate first tab
$(".tab_content:first").show(); //Show first tab content
//On Click Event
$("ul.tabs li").click(function() {
//On Click Event
$("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
$("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".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
$(activeTab).fadeIn(); //Fade in the active ID content
return false;
});
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
return false;
});
});
// ]]>
</script>
</head>
});
// ]]>
</script>
</head>
<?php
}
function exportEventDetail( $event, $exportFrames, $exportImages )
{
ob_start();
exportHeader( translate('Event')." ".$event->Id() );
function exportEventDetail($event, $exportFrames, $exportImages) {
ob_start();
exportHeader(translate('Event').' '.$event->Id());
$otherlinks = '';
if( $exportFrames ) $otherlinks .= '<a href="zmEventFrames.html">'.translate('Frames').'</a>,';
if( $exportImages ) $otherlinks .= '<a href="zmEventImages.html">'.translate('Images').'</a>,';
$otherlinks = substr($otherlinks,0,-1);
?>
<body>
<div id="page">
@ -139,22 +133,20 @@ function exportEventDetail( $event, $exportFrames, $exportImages )
</body>
</html>
<?php
return( ob_get_clean() );
return ob_get_clean();
}
function exportEventFrames( $event, $exportDetail, $exportImages )
{
$sql = "SELECT *, unix_timestamp( TimeStamp ) AS UnixTimeStamp FROM Frames WHERE EventID = ? ORDER BY FrameId";
$frames = dbFetchAll( $sql, NULL, array( $event->Id() ) );
function exportEventFrames($event, $exportDetail, $exportImages) {
$sql = 'SELECT *, unix_timestamp( TimeStamp ) AS UnixTimeStamp FROM Frames WHERE EventID = ? ORDER BY FrameId';
$frames = dbFetchAll($sql, NULL, array($event->Id()));
ob_start();
exportHeader( translate('Frames')." ".$event->Id() );
ob_start();
exportHeader(translate('Frames').' '.$event->Id());
$otherlinks = '';
if( $exportDetail ) $otherlinks .= '<a href="zmEventDetail.html">'.translate('Event').'</a>,';
if( $exportImages ) $otherlinks .= '<a href="zmEventImages.html">'.translate('Images').'</a>,';
$otherlinks = substr($otherlinks,0,-1);
?>
<body>
<div id="page">
@ -168,56 +160,49 @@ function exportEventFrames( $event, $exportDetail, $exportImages )
<th><?php echo translate('TimeDelta') ?></th>
<th><?php echo translate('Score') ?></th>
<?php
if ( $exportImages )
{
if ( $exportImages ) {
?>
<th><?php echo translate('Image') ?></th>
<?php
}
}
?>
</tr>
<?php
if ( count($frames) )
{
$eventPath = $event->Path();
foreach ( $frames as $frame )
{
$imageFile = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $frame['FrameId'] );
$imagePath = $eventPath."/".$imageFile;
$analImage = preg_replace( "/capture/", "analyse", $imagePath );
if ( file_exists( $analImage ) )
{
$imageFile = preg_replace( "/capture/", "analyse", $imageFile );
}
if ( count($frames) ) {
$eventPath = $event->Path();
foreach ( $frames as $frame ) {
$imageFile = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId']);
$imagePath = $eventPath.'/'.$imageFile;
$analImage = preg_replace('/capture/', 'analyse', $imagePath);
if ( file_exists($analImage) ) {
$imageFile = preg_replace('/capture/', 'analyse', $imageFile);
}
$class = strtolower($frame['Type']);
$class = strtolower($frame['Type']);
?>
<tr class="<?php echo $class ?>">
<td><?php echo $frame['FrameId'] ?></td>
<td><?php echo $frame['Type'] ?></td>
<td><?php echo strftime( STRF_FMT_TIME, $frame['UnixTimeStamp'] ) ?></td>
<td><?php echo number_format( $frame['Delta'], 2 ) ?></td>
<td><?php echo strftime(STRF_FMT_TIME, $frame['UnixTimeStamp']) ?></td>
<td><?php echo number_format($frame['Delta'], 2) ?></td>
<td><?php echo $frame['Score'] ?></td>
<?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
}
}
?>
</tr>
<?php
}
}
else
{
} # end foreach frame
} else {
?>
<tr>
<td class="monoRow" colspan="<?php echo $exportImages?6:5 ?>"><?php echo translate('NoFramesRecorded') ?></td>
</tr>
<?php
}
} # end if count($frames)
?>
</table>
</div>
@ -225,13 +210,12 @@ function exportEventFrames( $event, $exportDetail, $exportImages )
</body>
</html>
<?php
return( ob_get_clean() );
return ob_get_clean();
}
function exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist )
{
ob_start();
exportHeader( translate('Images')." ".$event->Id() );
function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
ob_start();
exportHeader(translate('Images').' '.$event->Id());
$otherlinks = '';
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>
<?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>
<layer id="slidenssub" width=&{slidewidth}; left=auto top=auto></layer>
<layer id="slidenssub" width="&{slidewidth};" left="auto" top="auto"></layer>
</ilayer>
<div id="imagevideo" align="center"></div>
<br>
<div align="center">
<button onclick="stepbackward()">< Step</button><button
id="btnrwd" onclick="rewind()" >Rwd</button><button
id="btnplay" onclick="playstop()">Stop</button><button
onclick="stepforward()">Step ></button><button
id="btnspeedup" onclick="speedup()">speedup</button><button
id="btnspeeddown" onclick="speeddown()">slowdown</button>
<button type="button" onclick="stepbackward()">&lt; Step</button>
<button type="button" id="btnrwd" onclick="rewind()" >Rwd</button>
<button type="button" id="btnplay" onclick="playstop()">Stop</button>
<button type="button" onclick="stepforward()">Step &gt;</button>
<button type="button" id="btnspeedup" onclick="speedup()">speedup</button>
<button type="button" id="btnspeeddown" onclick="speeddown()">slowdown</button>
</div>
<div align="center"><div class="horizontal_track" >
<div class="horizontal_slit" >&nbsp;</div>
<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>
</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>
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 align="center"><div class="display_holder"><input id="imageslider_display_id" class="value_display" type="text" value="0" onfocus="blur(this);"/></div></div>
<script language="JavaScript1.2">
<script type="text/javascript">
/***********************************************
* 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
***********************************************/
var eventWidth = <?php echo$event->Width()?>;
var eventHeight = <?php echo$event->Height()?>;
var variableslide=[<?php echo$slides?>];
var eventWidth = <?php echo $event->Width()?>;
var eventHeight = <?php echo $event->Height()?>;
var variableslide=[<?php echo $slides?>];
//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 slideheight=eventHeight+'px' //set to height of LARGEST iamge in your slideshow, plus any text description
var slidebgcolor='#ffffff'
var slidewidth=eventWidth+'px'; //set to width of LARGEST image in your slideshow
var slideheight=eventHeight+'px'; //set to height of LARGEST image in your slideshow, plus any text description
var slidebgcolor='#ffffff';
//configure the below variable to determine the delay between image rotations (in miliseconds)
var origslidedelay=100;
@ -306,15 +316,15 @@ var ie=document.all;
var dom=document.getElementById;
for (i=0;i<variableslide.length;i++){
var cacheimage=new Image()
cacheimage.src=variableslide[i]
var cacheimage = new Image();
cacheimage.src = variableslide[i];
}
var currentslide=-1
var currentslide = -1;
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.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(){
if (currentslide==variableslide.length-1) currentslide=0;
@ -337,14 +347,12 @@ function changeimage() {
slideManual(currentslide+1,eventWidth-20, 1, variableslide.length);
}
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";
rotateimages();
}
// seyi_code
function rotateimagesrewind(){
if (currentslide==0) currentslide=variableslide.length-1;
@ -366,12 +374,12 @@ function stepforward() {
document.getElementById('btnspeedup').disabled = true;
document.getElementById('btnspeeddown').disabled = true;
if (currentslide==variableslide.length-1) currentslide=0;
if ( currentslide == variableslide.length-1 ) currentslide=0;
else currentslide++;
changeimage();
}
function stepbackward() {
clearTimeout(mytimer);
// document.getElementById('btnrwd').style.borderTop='2px solid #ffffff';
@ -383,11 +391,10 @@ function stepbackward() {
document.getElementById('btnspeedup').disabled = true;
document.getElementById('btnspeeddown').disabled = true;
if (currentslide==0) currentslide=variableslide.length-1;
if ( currentslide == 0 ) currentslide = variableslide.length-1;
else currentslide--;
changeimage();
}
function speedup() { slidedelay = slidedelay/2; }
function speeddown() { slidedelay = slidedelay*2; }
@ -430,7 +437,6 @@ function rewind() {
document.getElementById('btnspeedup').disabled = true;
document.getElementById('btnspeeddown').disabled = true;
}
}
//---------------------------------+
@ -501,65 +507,63 @@ function moveSlider(evnt) {
// seyi_code
currentslide = v-1;
changeimage();
return false
return false;
}
return
}
// moveSlider: Handles the start of a slider move.
function slide(evnt, orientation, length, from, to, count, decimals, display) {
if (!evnt) evnt = window.event;
sliderObj = (evnt.target) ? evnt.target : evnt.srcElement; // Get the activated slider element.
sliderObj.pxLen = length // The allowed slider movement in pixels.
sliderObj.valCount = count ? count - 1 : length // Allowed number of values in the interval.
displayObj = carpeGetElementById(display) // Get the associated display element.\
displayObj.dec = decimals // Number of decimals to be displayed.
sliderObj.scale = (to - from) / length // Slider-display scale [value-change per pixel of movement].
sliderObj.pxLen = length; // The allowed slider movement in pixels.
sliderObj.valCount = count ? count - 1 : length; // Allowed number of values in the interval.
displayObj = carpeGetElementById(display); // Get the associated display element.\
displayObj.dec = decimals; // Number of decimals to be displayed.
sliderObj.scale = (to - from) / length; // Slider-display scale [value-change per pixel of movement].
if (orientation == 'horizontal') { // Set limits for horizontal sliders.
sliderObj.fromVal = from
xMax = length
yMax = 0
sliderObj.fromVal = from;
xMax = length;
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.
sliderObj.fromVal = to
xMax = 0
yMax = length
sliderObj.scale = -sliderObj.scale // Invert scale for vertical sliders. "Higher is more."
}
pxLeft = carpeLeft(sliderObj.id) // Sliders horizontal position at start of slide.
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.
pxLeft = carpeLeft(sliderObj.id); // Sliders horizontal position at start of slide.
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.
// Snaps the slider position to allowed/displayed value.
function sliderMouseUp() {
mouseover = false // Stop the sliding.
v = (displayObj.value) ? displayObj.value : 0 // Find last display value.
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 (xMax == 0) carpeTop(sliderObj.id, pos) // Snap vertical slider to corresponding display position.
mouseover = false; // Stop the sliding.
v = (displayObj.value) ? displayObj.value : 0; // Find last display value.
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 (xMax == 0) carpeTop(sliderObj.id, pos); // Snap vertical slider to corresponding display position.
if (document.removeEventListener) { // Remove event listeners from 'document' (Moz&co).
document.removeEventListener('mousemove', moveSlider)
document.removeEventListener('mouseup', sliderMouseUp)
document.removeEventListener('mousemove', moveSlider);
document.removeEventListener('mouseup', sliderMouseUp);
}
else if (document.detachEvent) { // Remove event listeners from 'document' (IE&co).
document.detachEvent('onmousemove', moveSlider)
document.detachEvent('onmouseup', sliderMouseUp)
document.detachEvent('onmousemove', moveSlider);
document.detachEvent('onmouseup', sliderMouseUp);
}
}
//seyi_code
// seyi_code
//slide(event,'horizontal', 300, 1, 22, 22,0, 'imageslider_display_id');
//slide(evnt, orientation, length, from, to, count, decimals, display) {
function slideManual(val,length,from,to) {
scale = (to - from) / length // Slider-display scale [value-change per pixel of movement].
fromVal = from
xMax = length
yMax = 0
scale = (to - from) / length; // Slider-display scale [value-change per pixel of movement].
fromVal = from;
xMax = length;
yMax = 0;
sliderid = 'imageslider_id';
@ -574,24 +578,26 @@ if (ie||dom) start_slider();
else if (document.layers) window.onload=start_slider;
</script>
<?php
} # end if defaultvideo
?>
</body>
</html>
<?php
return( ob_get_clean() );
return ob_get_clean();
}
function exportEventImagesMaster( $eids ) {
function exportEventImagesMaster($eids) {
ob_start();
exportHeader( translate('Images').' Master' );
exportHeader(translate('Images').' Master');
?>
<body>
<h2><?php echo translate('Images') ?> Master</h2>
<?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) {
//get monitor id and event id
$event = new Event( $eid );
$event = new Event($eid);
$eventMonitorId[$eid] = $event->MonitorId();
$eventPath[$eid] = $event->Relative_Path();
}
@ -600,70 +606,66 @@ function exportEventImagesMaster( $eids ) {
$monitorNames = array();
//*
if(!empty($monitors)) {
$tmp = dbFetchAll("SELECT Id,Name FROM Monitors WHERE Id IN (".implode(',', $monitors).") ");
if ( !empty($monitors) ) {
$tmp = dbFetchAll('SELECT Id,Name FROM Monitors WHERE Id IN ('.implode(',', $monitors).') ');
foreach ( $tmp as $row ) { $monitorNames[$row['Id']] = $row['Name']; }
}
//*/
//trigger_error(print_r($monitorNames,1));
?>
<div id="tabs">
<ul class="tabs">
<li class="active"><a href="#all"> All </a></li>
<?php
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>
</div>
<table width="100%" height="100%" ><tr>
<td valign="top" bgcolor="#dddddd" style="padding:10px;">
<div class='tab_content' id='all'>
<h2> All </h2>
<?php
if (!is_array($eids)) {
echo "<div><a href=\"javascript:switchevent('$eids/zm/EventImages.html');\"> $eids </div>";
}
?>
<?php foreach($eids as $eid) {
?>
<div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div>
<?php
}
?>
<table width="100%" height="100%">
<tr>
<td valign="top" bgcolor="#dddddd" style="padding:10px;">
<div class="tab_content" id="all">
<h2> All </h2>
<?php
foreach($eids as $eid) {
$Event = new Event($eid);
if ( $Event->SaveJPEGs() ) {
?>
<div><a href="#" onclick="switchevent('<?php echo $eid; ?>/zmEventImages.html');return false;"><?php echo $eid; ?></a></div>
<?php
} # end if saveJPEGs
} # end foreach event id
?>
</div>
<?php
foreach ($monitors as $monitor) {
echo "<div class='tab_content' id='tab$monitor'>";
echo "<h2>Monitor: " . $monitorNames[$monitor] . " </h2>";
foreach ($eids as $eid) {
if ($eventMonitorId[$eid] == $monitor) {
?>
<div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div>
<?php
}
<?php
foreach ($monitors as $monitor) {
echo "<div class=\"tab_content\" id=\"tab$monitor\">";
echo '<h2>Monitor: ' . $monitorNames[$monitor] . ' </h2>';
foreach ( $eids as $eid ) {
if ( $eventMonitorId[$eid] == $monitor ) {
?>
<div><a href="#" onclick="switchevent('<?php echo $eid; ?>/zmEventImages.html');return false;"><?php echo $eid; ?></a></div>
<?php
}
echo'</div>';
}
?>
</td><td>
<iframe id="myframe" onload="resizeCaller();" name="myframe" src="#"
scrolling="no" marginwidth="0" marginheight="0" frameborder="0"
vspace="0" hspace="0" style="overflow:visible; width:100%; display:none">
</iframe>
</td>
</tr></table>
echo '</div>';
} # end foreach monitor
?>
</td><td>
<iframe id="myframe" onload="resizeCaller();" name="myframe" src="#"
scrolling="no" marginwidth="0" marginheight="0" frameborder="0"
vspace="0" hspace="0" style="overflow:visible; width:100%; display:none">
</iframe>
</td>
</tr>
</table>
<script type="text/javascript">
function switchevent(src) {
if(document.all) document.all.myframe.src = src;
else window.frames['myframe'].location.href = src;
$('#myframe').attr('src',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:
//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):
var iframehide="yes"
var iframehide="yes";
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 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
function resizeCaller() {
var dyniframe=new Array()
var dyniframe=new Array();
for (i=0; i<iframeids.length; i++){
if (document.getElementById) resizeIframe(iframeids[i]);
//reveal iframe for lower end browsers? (see var above):
if ((document.all || document.getElementById) && iframehide=="no"){
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i])
tempobj.style.display="block"
if ( (document.all || document.getElementById) && iframehide=="no" ) {
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i]);
tempobj.style.display="block";
}
}
}
function resizeIframe(frameid){
var currentfr=document.getElementById(frameid)
if (currentfr && !window.opera){
currentfr.style.display="block"
if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) //ns6 syntax
function resizeIframe(frameid) {
var currentfr = document.getElementById(frameid);
if ( currentfr && !window.opera ) {
currentfr.style.display = "block";
if ( currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight ) //ns6 syntax
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;
if (currentfr.addEventListener) currentfr.addEventListener("load", readjustIframe, false);
else if (currentfr.attachEvent){
currentfr.detachEvent("onload", readjustIframe) // Bug fix line
currentfr.attachEvent("onload", readjustIframe)
if ( currentfr.addEventListener ) {
currentfr.addEventListener("load", readjustIframe, false);
} else if ( currentfr.attachEvent ) {
currentfr.detachEvent("onload", readjustIframe); // Bug fix line
currentfr.attachEvent("onload", readjustIframe);
}
}
}
function readjustIframe(loadevt) {
var crossevt=(window.event)? event : loadevt;
var iframeroot=(crossevt.currentTarget)? crossevt.currentTarget : crossevt.srcElement
var crossevt = window.event ? event : loadevt;
var iframeroot = crossevt.currentTarget ? crossevt.currentTarget : crossevt.srcElement;
if (iframeroot) resizeIframe(iframeroot.id);
}
function loadintoIframe(iframeid, url){
function loadintoIframe(iframeid, url) {
if (document.getElementById) document.getElementById(iframeid).src=url;
}
//if (window.addEventListener) window.addEventListener("load", resizeCaller, false)
//else if (window.attachEvent) window.attachEvent("onload", resizeCaller)
//else window.onload=resizeCaller
</script>
</body>
</script>
</body>
</html>
<?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;
}
$event = new Event($eid);
$eventPath = $event->Path();
$eventPath = $event->Path();
$eventRelativePath = $event->Relative_Path();
$files = array();
if ( $dir = opendir($eventPath) ) {
while ( ($file = readdir($dir)) !== false ) {
@ -754,29 +756,29 @@ function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exp
if ( $exportDetail ) {
$file = 'zmEventDetail.html';
if ( !($fp = fopen( $eventPath.'/'.$file, 'w' )) ) {
Fatal( "Can't open event detail export file '$file'" );
if ( !($fp = fopen($eventPath.'/'.$file, 'w')) ) {
Fatal("Can't open event detail export file '$file'");
}
fwrite( $fp, exportEventDetail( $event, $exportFrames, $exportImages ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
fwrite($fp, exportEventDetail($event, $exportFrames, $exportImages));
fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file;
}
if ( $exportFrames ) {
$file = 'zmEventFrames.html';
if ( !($fp = fopen( $eventPath.'/'.$file, 'w' )) ) {
Fatal( "Can't open event frames export file '$file'" );
if ( !($fp = fopen($eventPath.'/'.$file, 'w')) ) {
Fatal("Can't open event frames export file '$file'");
}
fwrite( $fp, exportEventFrames( $event, $exportDetail, $exportImages ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
fwrite($fp, exportEventFrames($event, $exportDetail, $exportImages));
fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file;
}
if ( $exportImages ) {
$filesLeft = array();
$myfilelist = array();
foreach ( $files as $file ) {
if ( preg_match( '/-(?:capture|analyse).jpg$/', $file ) ) {
$exportFileList[$file] = $eventPath."/".$file;
$myfilelist[$file] = $eventPath."/".$file;
if ( preg_match('/-(?:capture|analyse).jpg$/', $file ) ) {
$myfilelist[$file] = $exportFileList[$file] = $event->Id().'/'.$file;
} else {
$filesLeft[$file] = $file;
}
@ -785,109 +787,160 @@ function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exp
// create an image slider
if ( !empty($myfilelist) ) {
$file = 'zmEventImages.html';
if ( !($fp = fopen($eventPath.'/'.$file, 'w')) ) Fatal( "Can't open event images export file '$file'" );
fwrite( $fp, exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
$file = $event->Id().'/zmEventImages.html';
if ( !($fp = fopen($file, 'w')) )
Fatal("Can't open event images export file '$file'");
fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist));
fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file;
}
} # end if exportImages
if ( $exportVideo ) {
$filesLeft = array();
foreach ( $files as $file ) {
if ( preg_match( '/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file ) ) {
$exportFileList[$file] = $eventPath.'/'.$file;
if ( preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file) ) {
$exportFileList[$file] = $event->Id().'/'.$file;
} else {
$filesLeft[$file] = $file;
}
}
$files = $filesLeft;
} # end if exportVideo
} # end if exportVideo
if ( $exportMisc ) {
foreach ( $files as $file ) {
$exportFileList[$file] = $eventPath.'/'.$file;
$exportFileList[$file] = $event->Id().'/'.$file;
}
$files = array();
}
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;
}
# 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_listFile = 'zmFileList.txt';
$exportFileList = array();
$html_eventMaster = '';
if ( is_array($eids) ) {
foreach ( $eids as $eid ) {
$exportFileList = array_merge( $exportFileList, exportFileList( $eid , $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) );
}
} else {
$eid = $eids;
$exportFileList = exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc );
if ( !is_array($eids) ) {
$eids = array($eids);
}
// create an master image slider
if ( $exportImages ) {
if ( !is_array($eids) ) {
$eids = array($eids);
foreach ( $eids as $eid ) {
$event = new Event($eid);
$event_dir = $export_dir.'/'.$event->Id();
if ( !mkdir($event_dir) )
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')) ) {
Fatal( "Can't open event export list file '$listFile'" );
Fatal("Can't open event export list file '$listFile'");
}
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 = '';
if ( $exportFormat == 'tar' ) {
$archive = ZM_DIR_EXPORTS.'/'.$export_root.'.tar.gz';
@unlink( $archive );
if ( $exportStructure == 'flat' ) { //strip file paths if we choose
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile)." --xform='s#^.+/##x'";
} else {
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile);
}
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 );
$archive = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'').'.tar.gz';
@unlink($archive);
$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);
if ( $exportStructure == 'flat' ) {
//strip file paths if we
$command .= " --xform='s#^.+/##x'";
}
} elseif ( $exportFormat == 'zip' ) {
$archive = ZM_DIR_EXPORTS.'/'.$export_root.'.zip';
@unlink( $archive );
if ($exportStructure == 'flat') {
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q -j ".escapeshellarg($archive)." -@";
$archive = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'').'.zip';
@unlink($archive);
if ( $exportStructure == 'flat' ) {
$command = 'nice -10 zip -j '.escapeshellarg($archive).' zmExport_'.$connkey.'/';
#$command = 'cat '.escapeshellarg($listFile).' | nice -10 zip -q -j '.escapeshellarg($archive).' -@';
} else {
$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;
$command = 'nice -10 zip -r '.escapeshellarg($archive).' zmExport_' . $connkey.'/';
#$command = 'cat '.escapeshellarg($listFile).' | nice -10 zip -q '.escapeshellarg($archive).' -@';
}
} 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
@ -895,5 +948,5 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo
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