Merge branch 'master' into 1786-Dockerfile-Xenial
This commit is contained in:
commit
8fc199c65e
|
@ -0,0 +1,4 @@
|
|||
web/api/lib
|
||||
web/skins/classic/js/jquery-1.11.3.js
|
||||
web/skins/classic/js/jquery.js
|
||||
web/tools/mootools
|
|
@ -0,0 +1,29 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"env": {
|
||||
"browser": true,
|
||||
},
|
||||
"extends": ["google"],
|
||||
"rules": {
|
||||
"brace-style": "off",
|
||||
"camelcase": "off",
|
||||
"comma-dangle": "off",
|
||||
"key-spacing": "off",
|
||||
"max-len": "off",
|
||||
"new-cap": ["error", {
|
||||
capIsNewExceptions: ["Error", "Warning", "Debug", "Polygon_calcArea", "Play", "Stop"],
|
||||
newIsCapExceptionPattern: "^Asset\.."
|
||||
}],
|
||||
"no-array-constructor": "off",
|
||||
"no-caller": "off",
|
||||
"no-new-object": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-var": "off",
|
||||
"object-curly-spacing": "off",
|
||||
"prefer-rest-params": "off",
|
||||
"quotes": "off",
|
||||
"require-jsdoc": "off",
|
||||
"spaced-comment": "off",
|
||||
},
|
||||
};
|
78
.travis.yml
78
.travis.yml
|
@ -2,50 +2,52 @@ language: cpp
|
|||
sudo: required
|
||||
dist: trusty
|
||||
notifications:
|
||||
irc: "chat.freenode.net#zoneminder-dev"
|
||||
irc: chat.freenode.net#zoneminder-dev
|
||||
branches:
|
||||
except:
|
||||
- modern
|
||||
- modern
|
||||
cache: ccache
|
||||
addons:
|
||||
sauce_connect:
|
||||
username: "zoneminder"
|
||||
access_key: "046ec7c1-c598-4e7e-949a-f86e725d1722"
|
||||
ssh_known_hosts: zmrepo.zoneminder.com
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: ppa:iconnor/zoneminder
|
||||
- key_url: http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x4D0BF748776FFB04
|
||||
packages:
|
||||
- gdebi
|
||||
- yum-utils
|
||||
- patch
|
||||
- git
|
||||
- curl
|
||||
- sshfs
|
||||
env:
|
||||
global:
|
||||
- LD_LIBRARY_PATH="/usr/local/lib:/opt/libjpeg-turbo/lib:$LD_LIBRARY_PATH"
|
||||
- DEB_HOST_GNU_TYPE=$(dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
- DEB_BUILD_GNU_TYPE=$(dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
- CFLAGS="-DZM_FFMPEG_CVS -DHAVE_LIBCRYPTO -I/usr/local/include"
|
||||
- CXXFLAGS="$CFLAGS"
|
||||
matrix:
|
||||
- ZM_BUILDMETHOD=cmake
|
||||
- OS=el DIST=6
|
||||
- OS=el DIST=7
|
||||
- OS=fedora DIST=24
|
||||
- OS=fedora DIST=25
|
||||
- OS=ubuntu DIST=trusty
|
||||
- OS=ubuntu DIST=xenial
|
||||
- OS=ubuntu DIST=trusty ARCH=i386
|
||||
- OS=ubuntu DIST=xenial ARCH=i386
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
- gcc
|
||||
services:
|
||||
- mysql
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y libpolkit-gobject-1-dev zlib1g-dev apache2 php5 php5-mysql build-essential libmysqlclient-dev libssl-dev libbz2-dev libpcre3-dev libdbi-perl libarchive-zip-perl libdate-manip-perl libdevice-serialport-perl libmime-perl libwww-perl libdbd-mysql-perl libsys-mmap-perl yasm automake autoconf cmake libjpeg-turbo8-dev apache2-mpm-prefork libapache2-mod-php5 php5-cli libtheora-dev libvorbis-dev libvpx-dev libx264-dev libvlccore-dev libvlc-dev
|
||||
install:
|
||||
- git clone -b n3.0 --depth=1 git://source.ffmpeg.org/ffmpeg.git
|
||||
- cd ffmpeg
|
||||
- ./configure --enable-shared --enable-swscale --enable-gpl --enable-libx264 --enable-libvpx --enable-libvorbis --enable-libtheora
|
||||
- make -j `grep processor /proc/cpuinfo|wc -l`
|
||||
- sudo make install
|
||||
- sudo make install-libs
|
||||
before_script:
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- mysql -uroot -e "CREATE DATABASE IF NOT EXISTS zm"
|
||||
- mysql -uroot -e "GRANT ALL ON zm.* TO 'zmuser'@'localhost' IDENTIFIED BY 'zmpass'";
|
||||
- mysql -uroot -e "FLUSH PRIVILEGES"
|
||||
- mysql
|
||||
- docker
|
||||
script:
|
||||
- if [ "$ZM_BUILDMETHOD" = "cmake" ]; then cmake -DZM_ONVIF=OFF -DCMAKE_INSTALL_PREFIX="/usr"; fi
|
||||
- make
|
||||
- sudo make install
|
||||
- if [ "$ZM_BUILDMETHOD" = "cmake" ]; then sudo ./zmlinkcontent.sh; fi
|
||||
- mysql -uzmuser -pzmpass < db/zm_create.sql
|
||||
- mysql -uzmuser -pzmpass zm < db/test.monitor.sql
|
||||
- sudo zmpkg.pl start
|
||||
- sudo zmfilter.pl -f purgewhenfull
|
||||
- utils/packpack/startpackpack.sh
|
||||
|
||||
before_deploy:
|
||||
- openssl aes-256-cbc -K $encrypted_62a62750aa73_key -iv $encrypted_62a62750aa73_iv -in ./utils/packpack/deploy_rsa.enc -out /tmp/deploy_rsa -d
|
||||
- eval "$(ssh-agent -s)"
|
||||
- chmod 600 /tmp/deploy_rsa
|
||||
- ssh-add /tmp/deploy_rsa
|
||||
|
||||
deploy:
|
||||
provider: script
|
||||
skip_cleanup: true
|
||||
script: utils/packpack/rsync_xfer.sh
|
||||
on:
|
||||
branch: master
|
||||
|
||||
|
|
|
@ -66,6 +66,24 @@ set(CMAKE_CXX_FLAGS_DEBUG "-Wall -D__STDC_CONSTANT_MACROS -g")
|
|||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
# GCC below 6.0 doesn't support __target__("fpu=neon") attribute, required for compiling ARM Neon code, otherwise compilation fails.
|
||||
# Must use -mfpu=neon compiler flag instead, but only do that for processors that support neon, otherwise strip the neon code alltogether,
|
||||
# because passing -fmpu=neon is unsafe to processors that don't support neon
|
||||
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
EXEC_PROGRAM(grep ARGS " neon " "/proc/cpuinfo" OUTPUT_VARIABLE neonoutput RETURN_VALUE neonresult)
|
||||
IF(neonresult EQUAL 0)
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfpu=neon")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpu=neon")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mfpu=neon")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mfpu=neon")
|
||||
ELSE(neonresult EQUAL 0)
|
||||
add_definitions(-DZM_STRIP_NEON=1)
|
||||
message(STATUS "ARM Neon is not available on this processor. Neon functions will be absent")
|
||||
ENDIF(neonresult EQUAL 0)
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
ENDIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
||||
# Modules that we need:
|
||||
include (GNUInstallDirs)
|
||||
include (CheckIncludeFile)
|
||||
|
@ -85,7 +103,8 @@ mark_as_advanced(
|
|||
ZM_PERL_MM_PARMS
|
||||
ZM_PERL_SEARCH_PATH
|
||||
ZM_TARGET_DISTRO
|
||||
ZM_CONFIG_DIR)
|
||||
ZM_CONFIG_DIR
|
||||
ZM_SYSTEMD)
|
||||
|
||||
set(ZM_RUNDIR "/var/run/zm" CACHE PATH
|
||||
"Location of transient process files, default: /var/run/zm")
|
||||
|
@ -148,6 +167,8 @@ set(ZM_PERL_SEARCH_PATH "" CACHE PATH
|
|||
installed outside Perl's default search path.")
|
||||
set(ZM_TARGET_DISTRO "" CACHE STRING
|
||||
"Build ZoneMinder for a specific distribution. Currently, valid names are: fc24, fc25, el6, el7, OS13, FreeBSD")
|
||||
set(ZM_SYSTEMD "OFF" CACHE BOOL
|
||||
"Set to ON to force building ZM with systemd support. default: OFF")
|
||||
|
||||
# Reassign some variables if a target distro has been specified
|
||||
if((ZM_TARGET_DISTRO STREQUAL "fc24") OR (ZM_TARGET_DISTRO STREQUAL "fc25"))
|
||||
|
@ -205,6 +226,11 @@ include_directories("${CMAKE_BINARY_DIR}")
|
|||
# This is required to enable searching in lib64 (if exists), do not change
|
||||
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ON)
|
||||
|
||||
# Set the systemd flag if systemd is autodetected or ZM_SYSTEMD has been set
|
||||
if(ZM_SYSTEMD OR (IS_DIRECTORY /usr/lib/systemd/system) OR (IS_DIRECTORY /lib/systemd/system))
|
||||
set(WITH_SYSTEMD 1)
|
||||
endif(ZM_SYSTEMD OR (IS_DIRECTORY /usr/lib/systemd/system) OR (IS_DIRECTORY /lib/systemd/system))
|
||||
|
||||
# System checks
|
||||
check_include_file("libv4l1-videodev.h" HAVE_LIBV4L1_VIDEODEV_H)
|
||||
if(NOT HAVE_LIBV4L1_VIDEODEV_H)
|
||||
|
@ -386,13 +412,13 @@ find_library(MYSQLCLIENT_LIBRARIES mysqlclient PATH_SUFFIXES mysql)
|
|||
if(MYSQLCLIENT_LIBRARIES)
|
||||
set(HAVE_LIBMYSQLCLIENT 1)
|
||||
list(APPEND ZM_BIN_LIBS "${MYSQLCLIENT_LIBRARIES}")
|
||||
find_path(MYSQLCLIENT_INCLUDE_DIR mysql/mysql.h)
|
||||
find_path(MYSQLCLIENT_INCLUDE_DIR mysql.h PATH_SUFFIXES mysql)
|
||||
if(MYSQLCLIENT_INCLUDE_DIR)
|
||||
include_directories("${MYSQLCLIENT_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_INCLUDES "${MYSQLCLIENT_INCLUDE_DIR}")
|
||||
endif(MYSQLCLIENT_INCLUDE_DIR)
|
||||
mark_as_advanced(FORCE MYSQLCLIENT_LIBRARIES MYSQLCLIENT_INCLUDE_DIR)
|
||||
check_include_file("mysql/mysql.h" HAVE_MYSQL_H)
|
||||
check_include_file("mysql.h" HAVE_MYSQL_H)
|
||||
if(NOT HAVE_MYSQL_H)
|
||||
message(FATAL_ERROR
|
||||
"ZoneMinder requires MySQL headers - check that MySQL development packages are installed")
|
||||
|
@ -659,12 +685,14 @@ endif(NOT ZM_WEB_GROUP)
|
|||
message(STATUS "Using web user: ${ZM_WEB_USER}")
|
||||
message(STATUS "Using web group: ${ZM_WEB_GROUP}")
|
||||
|
||||
# Check for polkit
|
||||
find_package(Polkit)
|
||||
if(NOT POLKIT_FOUND)
|
||||
message(FATAL_ERROR
|
||||
"Running ZoneMinder requires polkit. Building ZoneMinder requires the polkit development package.")
|
||||
endif(NOT POLKIT_FOUND)
|
||||
if(WITH_SYSTEMD)
|
||||
# Check for polkit
|
||||
find_package(Polkit)
|
||||
if(NOT POLKIT_FOUND)
|
||||
message(FATAL_ERROR
|
||||
"Running ZoneMinder requires polkit. Building ZoneMinder requires the polkit development package.")
|
||||
endif(NOT POLKIT_FOUND)
|
||||
endif(WITH_SYSTEMD)
|
||||
|
||||
# Some variables that zm expects
|
||||
set(ZM_PID "${ZM_RUNDIR}/zm.pid")
|
||||
|
|
|
@ -43,8 +43,8 @@ ADD utils/docker/start.sh /tmp/start.sh
|
|||
RUN chown -R www-data:www-data /usr/local/share/zoneminder/
|
||||
|
||||
# Adding apache virtual hosts file
|
||||
ADD utils/docker/apache-vhost /etc/apache2/sites-available/000-default.conf
|
||||
ADD utils/docker/phpdate.ini /etc/php/7.0/apache2/conf.d/25-phpdate.ini
|
||||
RUN cp misc/apache.conf /etc/apache2/sites-available/000-default.conf
|
||||
ADD utils/docker/phpdate.ini /etc/php5/apache2/conf.d/25-phpdate.ini
|
||||
|
||||
# Expose http port
|
||||
EXPOSE 80
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
--
|
||||
-- This updates a 1.30.2 database to 1.30.3
|
||||
--
|
||||
-- No changes required
|
||||
--
|
|
@ -0,0 +1,5 @@
|
|||
--
|
||||
-- This updates a 1.30.3 database to 1.30.4
|
||||
--
|
||||
-- No changes required
|
||||
--
|
|
@ -0,0 +1 @@
|
|||
redhat
|
|
@ -1,3 +0,0 @@
|
|||
Fedora rpm build files have been merged with redhat.
|
||||
See /distros/redhat.
|
||||
|
|
@ -51,6 +51,7 @@ file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp)
|
|||
# Install the empty folders
|
||||
install(DIRECTORY sock swap DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(DIRECTORY zoneminder DESTINATION /var/log DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(DIRECTORY zoneminder DESTINATION /var/run DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(DIRECTORY zoneminder-upload DESTINATION /var/spool DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(DIRECTORY events images temp DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
|
|
|
@ -157,7 +157,9 @@ Upgrades
|
|||
|
||||
sudo zmupdate.pl --user=root --pass=<mysql_root_pwd> --version=<from version>
|
||||
|
||||
5. Now start zoneminder:
|
||||
5. Now restart nginx and php-fpm then start and zoneminder:
|
||||
|
||||
sudo systemctl restart nginx
|
||||
sudo systemctl restart php-fpm
|
||||
sudo systemctl start zoneminder
|
||||
|
||||
|
|
|
@ -151,7 +151,8 @@ Upgrades
|
|||
|
||||
sudo zmupdate.pl --user=root --pass=<mysql_root_pwd> --version=<from version>
|
||||
|
||||
5. Now start zoneminder:
|
||||
5. Now restart the web server then start zoneminder:
|
||||
|
||||
sudo systemctl restart httpd
|
||||
sudo systemctl start zoneminder
|
||||
|
||||
|
|
|
@ -150,7 +150,8 @@ Upgrades
|
|||
|
||||
sudo zmupdate.pl --user=root --pass=<mysql_root_pwd> --version=<from version>
|
||||
|
||||
5. Now start zoneminder:
|
||||
5. Now restart the web server then start zoneminder:
|
||||
|
||||
sudo service httpd restart
|
||||
sudo service zoneminder start
|
||||
|
||||
|
|
|
@ -142,7 +142,9 @@ Upgrades
|
|||
|
||||
sudo zmupdate.pl --user=root --pass=<mysql_root_pwd> --version=<from version>
|
||||
|
||||
5. Now start zoneminder:
|
||||
5. Now restart the web server then start zoneminder:
|
||||
|
||||
sudo systemctl restart httpd
|
||||
sudo systemctl start zoneminder
|
||||
|
||||
|
||||
|
|
|
@ -23,3 +23,7 @@ here are a couple of considerations you may want to take.
|
|||
directives found in /etc/httpd/conf.d/zoneminder.conf. You should also
|
||||
comment out the HTTP -> HTTPS Rewrite rule.
|
||||
|
||||
3. Install a fully signed certificate from letsencrypt. See the Letsencrypt
|
||||
site for more information. https://letsencrypt.org/
|
||||
This service is totally free!
|
||||
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
# This will tell zoneminder's cmake process we are building against a known distro
|
||||
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
|
||||
|
||||
# Fedora >= 25 needs apcu backwards compatibility module
|
||||
%if 0%{?fedora} >= 25
|
||||
%global with_apcu_bc 1
|
||||
%endif
|
||||
|
||||
# Include files for SysV init or systemd
|
||||
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
|
||||
%global with_init_systemd 1
|
||||
|
@ -28,7 +33,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.30.2
|
||||
Version: 1.30.4
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
@ -39,7 +44,7 @@ Group: System Environment/Daemons
|
|||
License: GPLv2+ and LGPLv2+ and MIT
|
||||
URL: http://www.zoneminder.com/
|
||||
|
||||
Source0: https://github.com/ZoneMinder/ZoneMinder/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
|
||||
Source0: https://github.com/ZoneMinder/ZoneMinder/archive/%{version}.tar.gz#/zoneminder-%{version}.tar.gz
|
||||
Source1: https://github.com/FriendsOfCake/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz
|
||||
|
||||
%{?with_init_systemd:BuildRequires: systemd-devel}
|
||||
|
@ -86,6 +91,8 @@ BuildRequires: polkit-devel
|
|||
Requires: php-mysqli
|
||||
Requires: php-common
|
||||
Requires: php-gd
|
||||
Requires: php-pecl-apcu
|
||||
%{?with_apcu_bc:Requires: php-pecl-apcu-bc}
|
||||
Requires: cambozola
|
||||
Requires: net-tools
|
||||
Requires: psmisc
|
||||
|
@ -130,10 +137,9 @@ designed to support as many cameras as you can attach to your computer without
|
|||
too much degradation of performance.
|
||||
|
||||
%prep
|
||||
%autosetup
|
||||
%autosetup -a 1
|
||||
rmdir ./web/api/app/Plugin/Crud
|
||||
mv -f crud-%{crud_version} ./web/api/app/Plugin/Crud
|
||||
%autosetup -p 1 -a 1 -n ZoneMinder-%{version}
|
||||
%{__rm} -rf ./web/api/app/Plugin/Crud
|
||||
%{__mv} -f crud-%{crud_version} ./web/api/app/Plugin/Crud
|
||||
|
||||
# Change the following default values
|
||||
./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin-zm/nph-zms
|
||||
|
@ -333,11 +339,22 @@ rm -rf %{_docdir}/%{name}-%{version}
|
|||
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/temp
|
||||
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/log/zoneminder
|
||||
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/spool/zoneminder-upload
|
||||
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %ghost %{_localstatedir}/run/zoneminder
|
||||
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/run/zoneminder
|
||||
|
||||
%changelog
|
||||
* Tue May 09 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.4-1
|
||||
- modify autosetup macro parameters
|
||||
- modify requirements for php-pecl-acpu-bc package
|
||||
- 1.30.4 release
|
||||
|
||||
* Tue May 02 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.3-1
|
||||
- 1.30.3 release
|
||||
|
||||
* Thu Mar 30 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.2-2
|
||||
- 1.30.2 release
|
||||
|
||||
* Wed Feb 08 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.2-1
|
||||
- Bump version for 1.30.2 release
|
||||
- Bump version for 1.30.2 release candidate 1
|
||||
|
||||
* Wed Dec 28 2016 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.1-2
|
||||
- Changes from rpmfusion #4393
|
||||
|
|
|
@ -54,7 +54,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libdata-uuid-perl
|
||||
,mysql-client | virtual-mysql-client
|
||||
,perl-modules
|
||||
,php5-mysql, php5-gd
|
||||
,php5-mysql, php5-gd, php5-apcu, php-apc
|
||||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
,zip
|
||||
|
|
|
@ -58,8 +58,10 @@ override_dh_auto_install:
|
|||
|
||||
override_dh_fixperms:
|
||||
dh_fixperms
|
||||
## 637685
|
||||
chmod -c o-r $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
#
|
||||
# As requested by the Debian Webapps Policy Manual §3.2.1
|
||||
chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
|
||||
override_dh_installinit:
|
||||
dh_installinit --no-start
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_LDFLAGS_MAINT_APPEND += -Wl,--as-needed
|
||||
|
||||
ifeq ($(DEB_BUILD_ARCH_OS),hurd)
|
||||
ARGS:= -DZM_NO_MMAP=ON
|
||||
endif
|
||||
|
||||
%:
|
||||
dh $@ --parallel --buildsystem=cmake --builddirectory=dbuild \
|
||||
--with sphinxdoc,apache2,linktree
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- $(ARGS) \
|
||||
-DCMAKE_VERBOSE_MAKEFILE=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DZM_CONFIG_DIR="/etc/zm" \
|
||||
-DZM_RUNDIR="/var/run/zm" \
|
||||
-DZM_SOCKDIR="/var/run/zm" \
|
||||
-DZM_TMPDIR="/tmp/zm" \
|
||||
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
|
||||
-DZM_CONTENTDIR="/var/cache/zoneminder"
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean $(MANPAGES1)
|
||||
$(RM) -r docs/_build docs/installationguide
|
||||
|
||||
build-indep:
|
||||
#$(MAKE) -C docs text
|
||||
$(MAKE) -C docs html
|
||||
|
||||
MANPAGES1 = dbuild/scripts/zmupdate.pl.1
|
||||
$(MANPAGES1):
|
||||
# generate man page(s):
|
||||
pod2man -s1 --stderr --utf8 $(patsubst %.1, %, $@) $@
|
||||
|
||||
## reproducible build:
|
||||
LAST_CHANGE=$(shell dpkg-parsechangelog -S Date)
|
||||
BUILD_DATE=$(shell LC_ALL=C date -u "+%B %d, %Y" -d "$(LAST_CHANGE)")
|
||||
override_dh_installman: $(MANPAGES1)
|
||||
$(MAKE) -C docs man SPHINXOPTS="-D today=\"$(BUILD_DATE)\""
|
||||
dh_installman --language=C $(MANPAGES1)
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install --destdir=$(CURDIR)/debian/tmp
|
||||
# remove worthless files:
|
||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/perl5/*/*/*/.packlist
|
||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/perl5/*/*.in
|
||||
# remove empty directories:
|
||||
find $(CURDIR)/debian/tmp/usr -type d -empty -delete -printf 'removed %p\n'
|
||||
# remove extra-license-file:
|
||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/zoneminder/www/api/lib/Cake/LICENSE.txt
|
||||
|
||||
override_dh_fixperms:
|
||||
dh_fixperms
|
||||
#
|
||||
# As requested by the Debian Webapps Policy Manual §3.2.1
|
||||
chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
|
||||
override_dh_installinit:
|
||||
dh_installinit --no-start
|
||||
|
||||
override_dh_apache2:
|
||||
dh_apache2 --noenable
|
||||
|
||||
override_dh_strip:
|
||||
[ -d "$(CURDIR)/debian/zoneminder-dbg" ] \
|
||||
&& dh_strip --dbg-package=zoneminder-dbg \
|
||||
|| dh_strip
|
||||
|
||||
#%:
|
||||
# dh $@ --parallel --buildsystem=autoconf --with autoreconf
|
||||
#
|
||||
#override_dh_auto_configure:
|
||||
# dh_auto_configure -- \
|
||||
# --sysconfdir=/etc/zm \
|
||||
# --with-mysql=/usr \
|
||||
# --with-webdir=/usr/share/zoneminder \
|
||||
# --with-ffmpeg=/usr \
|
||||
# --with-cgidir=/usr/lib/cgi-bin \
|
||||
# --with-webuser=www-data \
|
||||
# --with-webgroup=www-data \
|
||||
# --enable-mmap=yes
|
|
@ -0,0 +1,28 @@
|
|||
--- distros/ubuntu1204/rules
|
||||
+++ distros/ubuntu1204/rules
|
||||
@@ -58,8 +58,10 @@ override_dh_auto_install:
|
||||
|
||||
override_dh_fixperms:
|
||||
dh_fixperms
|
||||
- ## 637685
|
||||
- chmod -c o-r $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
+ #
|
||||
+ # As requested by the Debian Webapps Policy Manual §3.2.1
|
||||
+ chown root:www-data debian/zoneminder-core/etc/zm/zm.conf
|
||||
+ chmod 640 debian/zoneminder-core/etc/zm/zm.conf
|
||||
|
||||
override_dh_installinit:
|
||||
dh_installinit --no-start
|
||||
--- distros/ubuntu1204/rules
|
||||
+++ distros/ubuntu1204/rules
|
||||
@@ -60,8 +60,8 @@ override_dh_fixperms:
|
||||
dh_fixperms
|
||||
#
|
||||
# As requested by the Debian Webapps Policy Manual §3.2.1
|
||||
- chown root:www-data debian/zoneminder-core/etc/zm/zm.conf
|
||||
- chmod 640 debian/zoneminder-core/etc/zm/zm.conf
|
||||
+ chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
+ chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
|
||||
override_dh_installinit:
|
||||
dh_installinit --no-start
|
|
@ -1,2 +1,3 @@
|
|||
d /var/run/zm 0755 www-data www-data
|
||||
d /tmp/zm 0755 www-data www-data
|
||||
d /var/tmp/zm 0755 www-data www-data
|
||||
|
|
|
@ -63,7 +63,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libdata-uuid-perl
|
||||
,mysql-client | virtual-mysql-client
|
||||
,perl-modules
|
||||
,php5-mysql | php-mysql, php5-gd | php-gd
|
||||
,php5-mysql | php-mysql, php5-gd | php-gd, php-apcu, php-apcu-bc
|
||||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
,zip
|
||||
|
|
|
@ -58,8 +58,10 @@ override_dh_auto_install:
|
|||
|
||||
override_dh_fixperms:
|
||||
dh_fixperms
|
||||
## 637685
|
||||
chmod -c o-r $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
#
|
||||
# As requested by the Debian Webapps Policy Manual §3.2.1
|
||||
chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
|
||||
override_dh_installinit:
|
||||
dh_installinit --no-start
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/var/cache/zoneminder/events /usr/share/zoneminder/www/events
|
||||
/var/cache/zoneminder/images /usr/share/zoneminder/www/images
|
||||
/var/cache/zoneminder/temp /usr/share/zoneminder/www/temp
|
||||
/var/tmp /usr/share/zoneminder/www/api/app/tmp
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
d /var/run/zm 0755 www-data www-data
|
||||
d /tmp/zm 0755 www-data www-data
|
||||
d /var/run/zm 0755 www-data www-data
|
||||
d /tmp/zm 0755 www-data www-data
|
||||
d /var/tmp/zm 0755 www-data www-data
|
||||
|
|
|
@ -309,7 +309,7 @@ The main causes are.
|
|||
* Capture frame rates. Unless there's a compelling reason in your case there is often little benefit in running cameras at 25fps when 5-10fps would often get you results just as good. Try changing your monitor settings to limit your cameras to lower frame rates. You can still configure ZM to ignore these limits and capture as fast as possible when motion is detected.
|
||||
* Run function. Obviously running in Record or Mocord modes or in Modect with lots of events generates a lot of DB and file activity and so CPU and load will increase.
|
||||
* Basic default detection zones. By default when a camera is added one detection zone is added which covers the whole image with a default set of parameters. If your camera covers a view in which various regions are unlikely to generate a valid alarm (ie the sky) then I would experiment with reducing the zone sizes or adding inactive zones to blank out areas you don't want to monitor. Additionally the actual settings of the zone themselves may not be optimal. When doing motion detection the number of changed pixels above a threshold is examined, then this is filter, then contiguous regions are calculated to see if an alarm is generated. If any maximum or minimum threshold is exceeded according to your zone settings at any time the calculation stops. If your settings always result in the calculations going through to the last stage before being failed then additional CPU time is used unnecessarily. Make sure your maximum and minimumzone thresholds are set to sensible values and experiment by switching RECORD_EVENT_STATS on and seeing what the actual values of alarmed pixels etc are during sample events.
|
||||
* Optimise your settings. After you've got some settings you're happy with then switching off RECORD_EVENT_STATS will prevent the statistics being written to the database which saves some time. Other settings which might make a difference are ZM_FAST_RGB_DIFFS, ZM_OPT_FRAME_SERVER and the JPEG_xxx_QUALITY ones.
|
||||
* Optimise your settings. After you've got some settings you're happy with then switching off RECORD_EVENT_STATS will prevent the statistics being written to the database which saves some time. Other settings which might make a difference are ZM_FAST_RGB_DIFFS and the JPEG_xxx_QUALITY ones.
|
||||
|
||||
I'm sure there are other things which might make a difference such as what else you have running on the box and memory sizes (make sure there's no swapping going on). Also speed of disk etc will make some difference during event capture and also if you are watching the whole time then you may have a bunch of zms processes running also.
|
||||
|
||||
|
|
|
@ -42,8 +42,6 @@ Note that these commands are just an example and might not be secure enough for
|
|||
|
||||
7. If you have chosen to change the ZoneMinder database account credentials to something other than zmuser/zmpass, you must now update zm.conf on each ZoneMinder Server. Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous step.
|
||||
|
||||
Additionally, you must also edit /usr/share/zoneminder/www/api/app/Config/database.php in a similar manner on each ZoneMinder Server. Scroll down and change login and password to the values you created in the previous step.
|
||||
|
||||
8. All ZoneMinders Servers must share a common events folder. This can be done in any manner supported by the underlying operating system. From the Storage Server, share/export a folder to be used for ZoneMinder events.
|
||||
|
||||
9. From each ZoneMinder Server, mount the shared events folder on the Storage Server to the events folder on the local ZoneMinder Server.
|
||||
|
|
|
@ -169,8 +169,6 @@ Now clone the ZoneMinder git repository:
|
|||
cd
|
||||
git clone https://github.com/ZoneMinder/ZoneMinder
|
||||
cd ZoneMinder
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
This will create a sub-folder called ZoneMinder, which will contain the latest development.
|
||||
|
||||
|
@ -180,21 +178,21 @@ We want to turn this into a tarball, but first we need to figure out what to nam
|
|||
|
||||
ls ~/rpmbuild/SOURCES
|
||||
|
||||
The tarball from the previsouly installed SRPM should be there. This is the name we will use. For this example, the name is ZoneMinder-1.28.1.tar.gz. From one folder above the local ZoneMinder git repository, execute the following:
|
||||
The tarball from the previsouly installed SRPM should be there. This is the name we will use. For this example, the name is ZoneMinder-1.28.1.tar.gz. From the root folder of the local ZoneMinder git repository, execute the following:
|
||||
|
||||
::
|
||||
|
||||
mv ZoneMinder ZoneMinder-1.28.1
|
||||
tar -cvzf ~/rpmbuild/SOURCES/ZoneMinder-1.28.1.tar.gz ZoneMinder-1.28.1/*
|
||||
git archive --prefix=ZoneMinder-1.28.1/ -o ~/rpmbuild/SOURCES/zoneminder-1.28.1.tar.gz HEAD
|
||||
|
||||
The trailing "/\*" leaves off the hidden dot "." file and folders from the git repo, which is what we want.
|
||||
Note that we are overwriting the original tarball. If you wish to keep the original tarball then create a copy prior to creating the new tarball.
|
||||
|
||||
Now build a new src.rpm:
|
||||
From the root of the local ZoneMinder git repo, execute the following:
|
||||
|
||||
::
|
||||
|
||||
rpmbuild -bs --nodeps ~/rpmbuild/SPECS/zoneminder.el7.spec
|
||||
rpmbuild -bs --nodeps distros/redhat/zoneminder.spec
|
||||
|
||||
Notice we used the rpm specfile that is part of the latest master branch you just downloaded, rather than the one that may be in your ~/rpmbbuild/SOURCES folder.
|
||||
|
||||
This step will overwrite the SRPM you originally downloaded, so you may want to back it up prior to completing this step. Note that the name of the specfile will vary slightly depending on the target distro.
|
||||
|
||||
|
|
|
@ -287,19 +287,19 @@ To build the latest master snapshot:
|
|||
|
||||
::
|
||||
|
||||
./do_debian_package.sh `lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'` `date +%Y%m%d`01 local master
|
||||
./do_debian_package.sh --snapshot=NOW --branch=master --type=local
|
||||
|
||||
|
||||
To build the latest stable release:
|
||||
|
||||
::
|
||||
|
||||
./do_debian_package.sh `lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'` `date +%Y%m%d`01 local stable
|
||||
./do_debian_package.sh --snapshot=stable --type=local
|
||||
|
||||
|
||||
Note that the ``lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'``
|
||||
part simply extracts your distribution name - like "vivid", "trusty" etc. You
|
||||
can always replace it by your distro name if you know it. As far as the script
|
||||
Note that the distribution will be guessed using ``lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'``
|
||||
which simply extracts your distribution name - like "vivid", "trusty" etc. You
|
||||
can always specify it using --distro=your distro name if you know it. As far as the script
|
||||
goes, it checks if your distro is "trusty" in which case it pulls in pre-systemd
|
||||
release configurations and if its not "trusty" it assumes its based on systemd
|
||||
and pulls in systemd related config files.
|
||||
|
@ -358,24 +358,6 @@ Changed Default DB User
|
|||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have changed your DB login/password from zmuser/zmpass, you need to
|
||||
update these values in zm.conf and the API's database.php file.
|
||||
update these values in zm.conf.
|
||||
|
||||
1. Edit zm.conf to change ZM_DB_USER and ZM_DB_PASS to the values you used.
|
||||
|
||||
2. Edit databse.php which can be found in the web server folder zoneminder/www/api/app/Config
|
||||
|
||||
There is a class there called DATABASE_CONFIG -
|
||||
change the $default array to reflect your new details. Example:
|
||||
|
||||
::
|
||||
|
||||
public $default = array(
|
||||
'datasource' => 'Database/Mysql',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
'login' => 'mynewDBusername',
|
||||
'password' => 'mynewDBpassword'
|
||||
'database' => 'zm',
|
||||
'prefix' => '',
|
||||
//'encoding' => 'utf8',
|
||||
);
|
|
@ -29,7 +29,7 @@ Here is what the filter window looks like
|
|||
events later and also make sure archived events don't get deleted, for example
|
||||
* Email details of all matches: Sends an email to the configured address with details about the event.
|
||||
The email can be customized as per TBD
|
||||
* Execute command on all matches: Allows you to execute any arbitrary command on the matched events
|
||||
* Execute command on all matches: Allows you to execute any arbitrary command on the matched events. You can use replacement tokens as subsequent arguents to the command, the last argument will be the absolute path to the event, preceeded by replacement arguents. eg: /usr/bin/script.sh %MN% will excecute as /usr/bin/script.sh MonitorName /path/to/event.
|
||||
* Delete all matches: Deletes all the matched events
|
||||
* *E*: Use 'Submit' to 'test' your matching conditions. This will just match and show you what filters match. Use 'Execute' to actually execute the action after matching your conditions. Use 'Save' to save the filter for future use and 'Reset' to clear your settings
|
||||
|
||||
|
|
|
@ -33,10 +33,6 @@ RUN_AUDIT - The zmaudit daemon exists to check that the saved information in the
|
|||
|
||||
AUDIT_CHECK_INTERVAL - The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.
|
||||
|
||||
OPT_FRAME_SERVER - In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon.
|
||||
|
||||
FRAME_SOCKET_SIZE - For large captured images it is possible for the writes from the analysis daemon to the frame server to fail as the amount to be written exceeds the default buffer size. While the images are then written by the analysis daemon so no data is lost, it defeats the object of the frame server daemon in the first place. You can use this option to indicate that a larger buffer size should be used. Note that you may have to change the existing maximum socket buffer size on your system via sysctl (or in /proc/sys/net/core/wmem_max) to allow this new size to be set. Alternatively you can change the default buffer size on your system in the same way in which case that will be used with no change necessary in this option
|
||||
|
||||
OPT_CONTROL - ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.
|
||||
|
||||
OPT_TRIGGERS - ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.
|
||||
|
|
|
@ -5,13 +5,22 @@
|
|||
# Some values may need to manually adjusted to suit your setup
|
||||
#
|
||||
<VirtualHost *:80>
|
||||
ServerName @WEB_HOST@
|
||||
ServerAdmin webmaster@localhost
|
||||
|
||||
DocumentRoot "@WEB_PREFIX@"
|
||||
Alias /zm/ "@WEB_PREFIX@/"
|
||||
<Directory "@WEB_PREFIX@">
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride All
|
||||
<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>
|
||||
|
||||
ScriptAlias /cgi-bin "@CGI_PREFIX@"
|
||||
|
|
|
@ -12,7 +12,7 @@ Type=forking
|
|||
ExecStart=@BINDIR@/zmpkg.pl start
|
||||
ExecReload=@BINDIR@/zmpkg.pl restart
|
||||
ExecStop=@BINDIR@/zmpkg.pl stop
|
||||
PIDFile="@ZM_RUNDIR@/zm.pid"
|
||||
PIDFile=@ZM_RUNDIR@/zm.pid
|
||||
Environment=TZ=:/etc/localtime
|
||||
|
||||
[Install]
|
||||
|
|
|
@ -26,9 +26,10 @@ configure_file(zm.in "${CMAKE_CURRENT_BINARY_DIR}/zm" @ONLY)
|
|||
#configure_file(zmeventdump.in zmeventdump @ONLY)
|
||||
|
||||
# Generate man files for the perl scripts destined for the bin folder
|
||||
file(GLOB perlscripts RELATIVE "${CMAKE_CURRENT_BINARY_DIR}" "*.pl")
|
||||
file(GLOB perlscripts "*.pl")
|
||||
FOREACH(PERLSCRIPT ${perlscripts})
|
||||
POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${PERLSCRIPT} zoneminder-${PERLSCRIPT} 8)
|
||||
get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME)
|
||||
POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8)
|
||||
ENDFOREACH(PERLSCRIPT ${perlscripts})
|
||||
|
||||
# Install the perl scripts
|
||||
|
|
|
@ -345,6 +345,26 @@ our @options = (
|
|||
type => $types{boolean},
|
||||
category => "system",
|
||||
},
|
||||
{
|
||||
name => "ZM_ENABLE_CSRF_MAGIC",
|
||||
default => "no",
|
||||
description => "Enable csrf-magic library",
|
||||
help => qqq("
|
||||
CSRF stands for Cross-Site Request Forgery which, under specific
|
||||
circumstances, can allow an attacker to perform any task your
|
||||
ZoneMinder user account has permission to perform. To accomplish
|
||||
this, the attacker must write a very specific web page and get
|
||||
you to navigate to it, while you are logged into the ZoneMinder
|
||||
web console at the same time. Enabling ZM_ENABLE_CSRF_MAGIC will
|
||||
help mitigate these kinds of attackes. Be warned this feature
|
||||
is experimental and may cause problems, particularly with the API.
|
||||
If you find a false positive and can document how to reproduce it,
|
||||
then please report it. This feature defaults to OFF currently due to
|
||||
its experimental nature.
|
||||
"),
|
||||
type => $types{boolean},
|
||||
category => "system",
|
||||
},
|
||||
{
|
||||
name => "ZM_OPT_USE_API",
|
||||
default => "yes",
|
||||
|
@ -2696,47 +2716,6 @@ our @options = (
|
|||
type => $types{boolean},
|
||||
category => "config",
|
||||
},
|
||||
{
|
||||
name => "ZM_OPT_FRAME_SERVER",
|
||||
default => "no",
|
||||
description => "Should analysis farm out the writing of images to disk",
|
||||
#requires => [ { name => "ZM_OPT_ADAPTIVE_SKIP", value => "yes" } ],
|
||||
help => qqq("
|
||||
In some circumstances it is possible for a slow disk to take so
|
||||
long writing images to disk that it causes the analysis daemon
|
||||
to fall behind especially during high frame rate events.
|
||||
Setting this option to yes enables a frame server daemon (zmf)
|
||||
which will be sent the images from the analysis daemon and will
|
||||
do the actual writing of images itself freeing up the analysis
|
||||
daemon to get on with other things. Should this transmission
|
||||
fail or other permanent or transient error occur, this function
|
||||
will fall back to the analysis daemon.
|
||||
"),
|
||||
type => $types{boolean},
|
||||
category => "system",
|
||||
},
|
||||
{
|
||||
name => "ZM_FRAME_SOCKET_SIZE",
|
||||
default => "0",
|
||||
description => "Specify the frame server socket buffer size if non-standard",
|
||||
requires => [ { name => "ZM_OPT_FRAME_SERVER", value => "yes" } ],
|
||||
help => qqq("
|
||||
For large captured images it is possible for the writes from
|
||||
the analysis daemon to the frame server to fail as the amount
|
||||
to be written exceeds the default buffer size. While the images
|
||||
are then written by the analysis daemon so no data is lost, it
|
||||
defeats the object of the frame server daemon in the first
|
||||
place. You can use this option to indicate that a larger buffer
|
||||
size should be used. Note that you may have to change the
|
||||
existing maximum socket buffer size on your system via sysctl
|
||||
(or in /proc/sys/net/core/wmem_max) to allow this new size to
|
||||
be set. Alternatively you can change the default buffer size on
|
||||
your system in the same way in which case that will be used
|
||||
with no change necessary in this option
|
||||
"),
|
||||
type => $types{integer},
|
||||
category => "system",
|
||||
},
|
||||
{
|
||||
name => "ZM_OPT_CONTROL",
|
||||
default => "no",
|
||||
|
|
|
@ -215,6 +215,55 @@ sub presetHome
|
|||
$self->sendCmd( 'decoder_control.cgi?command=25&' );
|
||||
}
|
||||
|
||||
sub moveRelUp
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Move Up" );
|
||||
$self->sendCmd( 'decoder_control.cgi?command=0&onestep=1&' );
|
||||
}
|
||||
|
||||
#Down Arrow
|
||||
sub moveRelDown
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Move Down" );
|
||||
$self->sendCmd( 'decoder_control.cgi?command=2&onestep=1&' );
|
||||
}
|
||||
|
||||
#Left Arrow
|
||||
sub moveRelLeft
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Move Left" );
|
||||
$self->sendCmd( 'decoder_control.cgi?command=6&onestep=1&' );
|
||||
}
|
||||
|
||||
#Right Arrow
|
||||
sub moveRelRight
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Move Right" );
|
||||
$self->sendCmd( 'decoder_control.cgi?command=4&onestep=1&' );
|
||||
}
|
||||
|
||||
#Go to preset
|
||||
sub presetGoto
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
my $result = undef;
|
||||
if ( $preset > 0 && $preset <= 32 ) {
|
||||
my $command=31+(($preset-1) * 2);
|
||||
Debug( "Goto Preset $preset with command $command" );
|
||||
$result=$self->sendCmd( 'decoder_control.cgi?command=' . $command . '&' );
|
||||
}
|
||||
else {
|
||||
Error( "Unsupported preset $preset : must be between 1 and 32" );
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ==========================================================================
|
||||
#
|
||||
|
|
|
@ -1,27 +1,34 @@
|
|||
# ==========================================================================
|
||||
#
|
||||
# ZoneMinder SunEyes SP-P1802SWPTZ IP Control Protocol Module, $Date: 2017-03-19 23:00:00 +1000 (Sat, 19 March 2017) $, $Revision: 0002 $
|
||||
# Copyright (C) 2001-2008 Philip Coombes
|
||||
# Modified for use with Foscam FI8918W IP Camera by Dave Harris
|
||||
# Modified Feb 2011 by Howard Durdle (http://durdl.es/x) to:
|
||||
# fix horizontal panning, add presets and IR on/off
|
||||
# use Control Device field to pass username and password
|
||||
# Modified May 2014 by Arun Horne (http://arunhorne.co.uk) to:
|
||||
# use HTTP basic auth as required by firmware 11.37.x.x upward
|
||||
# Modified on Sep 28 2015 by Bobby Billingsley
|
||||
# Changes made
|
||||
# - Copied FI8918W.pm to SPP1802SWPTZ.pm
|
||||
# - modified to control a SunEyes SP-P1802SWPTZ
|
||||
|
||||
# ==========================================================================
|
||||
# ZoneMinder SunEyes SP-P1802SWPTZ IP Control Protocol Module
|
||||
# Modified on 13 March 2017 by Steve Gilvarry
|
||||
# -Address license and copyright issues
|
||||
#
|
||||
# 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 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.
|
||||
# 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 SunEyes SP-P1802SWPTZ IP
|
||||
# camera control protocol
|
||||
#
|
||||
|
|
|
@ -43,8 +43,8 @@ our @ISA = qw(Exporter ZoneMinder::Base);
|
|||
# will save memory.
|
||||
our %EXPORT_TAGS = (
|
||||
'functions' => [ qw(
|
||||
) ]
|
||||
);
|
||||
) ]
|
||||
);
|
||||
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
|
@ -130,6 +130,8 @@ sub find {
|
|||
my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter );
|
||||
push @results, $filter;
|
||||
} # end while
|
||||
$sth->finish();
|
||||
|
||||
return @results;
|
||||
}
|
||||
|
||||
|
@ -176,78 +178,74 @@ sub Sql {
|
|||
my $self = $_[0];
|
||||
if ( ! $$self{Sql} ) {
|
||||
my $filter_expr = ZoneMinder::General::jsonDecode( $self->{Query} );
|
||||
my $sql = "SELECT E.Id,
|
||||
E.MonitorId,
|
||||
my $sql = "SELECT E.*,
|
||||
unix_timestamp(E.StartTime) as Time,
|
||||
M.Name as MonitorName,
|
||||
M.DefaultRate,
|
||||
M.DefaultScale,
|
||||
E.Name,
|
||||
E.Cause,
|
||||
E.Notes,
|
||||
E.StartTime,
|
||||
unix_timestamp(E.StartTime) as Time,
|
||||
E.Length,
|
||||
E.Frames,
|
||||
E.AlarmFrames,
|
||||
E.TotScore,
|
||||
E.AvgScore,
|
||||
E.MaxScore,
|
||||
E.Archived,
|
||||
E.Videoed,
|
||||
E.Uploaded,
|
||||
E.Emailed,
|
||||
E.Messaged,
|
||||
E.Executed
|
||||
M.DefaultScale
|
||||
FROM Events as E
|
||||
INNER JOIN Monitors as M on M.Id = E.MonitorId
|
||||
";
|
||||
$self->{Sql} = '';
|
||||
|
||||
if ( $filter_expr->{terms} ) {
|
||||
for ( my $i = 0; $i < @{$filter_expr->{terms}}; $i++ ) {
|
||||
if ( exists($filter_expr->{terms}[$i]->{cnj}) ) {
|
||||
$self->{Sql} .= " ".$filter_expr->{terms}[$i]->{cnj}." ";
|
||||
foreach my $term ( @{$filter_expr->{terms}} ) {
|
||||
|
||||
if ( exists($term->{cnj}) ) {
|
||||
$self->{Sql} .= " ".$term->{cnj}." ";
|
||||
}
|
||||
if ( exists($filter_expr->{terms}[$i]->{obr}) ) {
|
||||
$self->{Sql} .= " ".str_repeat( "(", $filter_expr->{terms}[$i]->{obr} )." ";
|
||||
if ( exists($term->{obr}) ) {
|
||||
$self->{Sql} .= " ".str_repeat( "(", $term->{obr} )." ";
|
||||
}
|
||||
my $value = $filter_expr->{terms}[$i]->{val};
|
||||
my $value = $term->{val};
|
||||
my @value_list;
|
||||
if ( $filter_expr->{terms}[$i]->{attr} ) {
|
||||
if ( $filter_expr->{terms}[$i]->{attr} =~ /^Monitor/ ) {
|
||||
my ( $temp_attr_name ) = $filter_expr->{terms}[$i]->{attr} =~ /^Monitor(.+)$/;
|
||||
if ( $term->{attr} ) {
|
||||
if ( $term->{attr} =~ /^Monitor/ ) {
|
||||
my ( $temp_attr_name ) = $term->{attr} =~ /^Monitor(.+)$/;
|
||||
$self->{Sql} .= "M.".$temp_attr_name;
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) {
|
||||
} elsif ( $term->{attr} =~ /^Server/ ) {
|
||||
$self->{Sql} .= "M.".$term->{attr};
|
||||
} elsif ( $term->{attr} eq 'DateTime' ) {
|
||||
$self->{Sql} .= "E.StartTime";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Date' ) {
|
||||
} elsif ( $term->{attr} eq 'Date' ) {
|
||||
$self->{Sql} .= "to_days( E.StartTime )";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Time' ) {
|
||||
} elsif ( $term->{attr} eq 'Time' ) {
|
||||
$self->{Sql} .= "extract( hour_second from E.StartTime )";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Weekday' ) {
|
||||
} elsif ( $term->{attr} eq 'Weekday' ) {
|
||||
$self->{Sql} .= "weekday( E.StartTime )";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DiskPercent' ) {
|
||||
} elsif ( $term->{attr} eq 'DiskPercent' ) {
|
||||
$self->{Sql} .= "zmDiskPercent";
|
||||
$self->{HasDiskPercent} = !undef;
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DiskBlocks' ) {
|
||||
} elsif ( $term->{attr} eq 'DiskBlocks' ) {
|
||||
$self->{Sql} .= "zmDiskBlocks";
|
||||
$self->{HasDiskBlocks} = !undef;
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'SystemLoad' ) {
|
||||
} elsif ( $term->{attr} eq 'SystemLoad' ) {
|
||||
$self->{Sql} .= "zmSystemLoad";
|
||||
$self->{HasSystemLoad} = !undef;
|
||||
} else {
|
||||
$self->{Sql} .= "E.".$filter_expr->{terms}[$i]->{attr};
|
||||
$self->{Sql} .= "E.".$term->{attr};
|
||||
}
|
||||
|
||||
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/;
|
||||
foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) {
|
||||
if ( $filter_expr->{terms}[$i]->{attr} =~ /^Monitor/ ) {
|
||||
if ( $term->{attr} =~ /^Monitor/ ) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Name'
|
||||
|| $filter_expr->{terms}[$i]->{attr} eq 'Cause'
|
||||
|| $filter_expr->{terms}[$i]->{attr} eq 'Notes'
|
||||
} elsif ( $term->{attr} eq 'ServerId' ) {
|
||||
if ( $temp_value eq 'ZM_SERVER_ID' ) {
|
||||
$value = "'$Config{ZM_SERVER_ID}'";
|
||||
# This gets used later, I forget for what
|
||||
$$self{Server} = new ZoneMinder::Server( $Config{ZM_SERVER_ID} );
|
||||
} else {
|
||||
$value = "'$temp_value'";
|
||||
# This gets used later, I forget for what
|
||||
$$self{Server} = new ZoneMinder::Server( $temp_value );
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'Name'
|
||||
|| $term->{attr} eq 'Cause'
|
||||
|| $term->{attr} eq 'Notes'
|
||||
) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) {
|
||||
} elsif ( $term->{attr} eq 'DateTime' ) {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
if ( !$value ) {
|
||||
Error( "Error parsing date/time '$temp_value', "
|
||||
|
@ -255,7 +253,7 @@ sub Sql {
|
|||
return;
|
||||
}
|
||||
$value = "'$value'";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Date' ) {
|
||||
} elsif ( $term->{attr} eq 'Date' ) {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
if ( !$value ) {
|
||||
Error( "Error parsing date/time '$temp_value', "
|
||||
|
@ -263,7 +261,7 @@ sub Sql {
|
|||
return;
|
||||
}
|
||||
$value = "to_days( '$value' )";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Time' ) {
|
||||
} elsif ( $term->{attr} eq 'Time' ) {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
if ( !$value ) {
|
||||
Error( "Error parsing date/time '$temp_value', "
|
||||
|
@ -277,21 +275,21 @@ sub Sql {
|
|||
push( @value_list, $value );
|
||||
} # end foreach temp_value
|
||||
} # end if has an attr
|
||||
if ( $filter_expr->{terms}[$i]->{op} ) {
|
||||
if ( $filter_expr->{terms}[$i]->{op} eq '=~' ) {
|
||||
if ( $term->{op} ) {
|
||||
if ( $term->{op} eq '=~' ) {
|
||||
$self->{Sql} .= " regexp $value";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{op} eq '!~' ) {
|
||||
} elsif ( $term->{op} eq '!~' ) {
|
||||
$self->{Sql} .= " not regexp $value";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{op} eq '=[]' ) {
|
||||
} elsif ( $term->{op} eq '=[]' ) {
|
||||
$self->{Sql} .= " in (".join( ",", @value_list ).")";
|
||||
} elsif ( $filter_expr->{terms}[$i]->{op} eq '!~' ) {
|
||||
} elsif ( $term->{op} eq '!~' ) {
|
||||
$self->{Sql} .= " not in (".join( ",", @value_list ).")";
|
||||
} else {
|
||||
$self->{Sql} .= " ".$filter_expr->{terms}[$i]->{op}." $value";
|
||||
$self->{Sql} .= " ".$term->{op}." $value";
|
||||
}
|
||||
} # end if has an operator
|
||||
if ( exists($filter_expr->{terms}[$i]->{cbr}) ) {
|
||||
$self->{Sql} .= " ".str_repeat( ")", $filter_expr->{terms}[$i]->{cbr} )." ";
|
||||
if ( exists($term->{cbr}) ) {
|
||||
$self->{Sql} .= " ".str_repeat( ")", $term->{cbr} )." ";
|
||||
}
|
||||
} # end foreach term
|
||||
} # end if terms
|
||||
|
@ -308,22 +306,22 @@ sub Sql {
|
|||
}
|
||||
my @auto_terms;
|
||||
if ( $self->{AutoArchive} ) {
|
||||
push( @auto_terms, "E.Archived = 0" )
|
||||
push @auto_terms, "E.Archived = 0";
|
||||
}
|
||||
if ( $self->{AutoVideo} ) {
|
||||
push( @auto_terms, "E.Videoed = 0" )
|
||||
push @auto_terms, "E.Videoed = 0";
|
||||
}
|
||||
if ( $self->{AutoUpload} ) {
|
||||
push( @auto_terms, "E.Uploaded = 0" )
|
||||
push @auto_terms, "E.Uploaded = 0";
|
||||
}
|
||||
if ( $self->{AutoEmail} ) {
|
||||
push( @auto_terms, "E.Emailed = 0" )
|
||||
push @auto_terms, "E.Emailed = 0";
|
||||
}
|
||||
if ( $self->{AutoMessage} ) {
|
||||
push( @auto_terms, "E.Messaged = 0" )
|
||||
push @auto_terms, "E.Messaged = 0";
|
||||
}
|
||||
if ( $self->{AutoExecute} ) {
|
||||
push( @auto_terms, "E.Executed = 0" )
|
||||
push @auto_terms, "E.Executed = 0";
|
||||
}
|
||||
if ( @auto_terms ) {
|
||||
$sql .= " and ( ".join( " or ", @auto_terms )." )";
|
||||
|
|
|
@ -103,8 +103,10 @@ sub getCmdFormat {
|
|||
my $suffix = "";
|
||||
my $command = $prefix.$null_command.$suffix;
|
||||
Debug( "Testing \"$command\"\n" );
|
||||
my $output = qx($command);
|
||||
my $output = qx($command 2>&1);
|
||||
my $status = $? >> 8;
|
||||
$output //= $!;
|
||||
|
||||
if ( !$status ) {
|
||||
Debug( "Test ok, using format \"$prefix<command>$suffix\"\n" );
|
||||
return( $prefix, $suffix );
|
||||
|
@ -116,8 +118,10 @@ sub getCmdFormat {
|
|||
$suffix = "'";
|
||||
$command = $prefix.$null_command.$suffix;
|
||||
Debug( "Testing \"$command\"\n" );
|
||||
my $output = qx($command);
|
||||
my $output = qx($command 2>&1);
|
||||
my $status = $? >> 8;
|
||||
$output //= $!;
|
||||
|
||||
if ( !$status ) {
|
||||
Debug( "Test ok, using format \"$prefix<command>$suffix\"\n" );
|
||||
return( $prefix, $suffix );
|
||||
|
@ -129,8 +133,10 @@ sub getCmdFormat {
|
|||
$suffix = "'";
|
||||
$command = $prefix.$null_command.$suffix;
|
||||
Debug( "Testing \"$command\"\n" );
|
||||
$output = qx($command);
|
||||
$output = qx($command 2>&1);
|
||||
$status = $? >> 8;
|
||||
$output //= $!;
|
||||
|
||||
if ( !$status ) {
|
||||
Debug( "Test ok, using format \"$prefix<command>$suffix\"\n" );
|
||||
return( $prefix, $suffix );
|
||||
|
|
|
@ -89,7 +89,6 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
|||
my @daemons = (
|
||||
'zmc',
|
||||
'zma',
|
||||
'zmf',
|
||||
'zmfilter.pl',
|
||||
'zmaudit.pl',
|
||||
'zmtrigger.pl',
|
||||
|
|
|
@ -982,6 +982,7 @@ sub executeCommand
|
|||
|
||||
my $command = $filter->{AutoExecuteCmd};
|
||||
$command .= " $event_path";
|
||||
$command = substituteTags( $command, $filter, $event );
|
||||
|
||||
Info( "Executing '$command'\n" );
|
||||
my $output = qx($command);
|
||||
|
|
|
@ -251,10 +251,6 @@ if ( $command =~ /^(?:start|restart)$/ )
|
|||
}
|
||||
if ( $monitor->{Function} ne 'Monitor' )
|
||||
{
|
||||
if ( $Config{ZM_OPT_FRAME_SERVER} )
|
||||
{
|
||||
runCommand( "zmdc.pl start zmf -m $monitor->{Id}" );
|
||||
}
|
||||
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
|
||||
}
|
||||
if ( $Config{ZM_OPT_CONTROL} )
|
||||
|
|
|
@ -12,21 +12,19 @@ add_library(zm STATIC ${ZM_BIN_SRC_FILES})
|
|||
add_executable(zmc zmc.cpp)
|
||||
add_executable(zma zma.cpp)
|
||||
add_executable(zmu zmu.cpp)
|
||||
add_executable(zmf zmf.cpp)
|
||||
add_executable(zms zms.cpp)
|
||||
|
||||
target_link_libraries(zmc zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zma zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zmu zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zmf zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
|
||||
# Generate man files for the binaries destined for the bin folder
|
||||
FOREACH(CBINARY zma zmc zmf zmu)
|
||||
FOREACH(CBINARY zma zmc zmu)
|
||||
POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8)
|
||||
ENDFOREACH(CBINARY zma zmc zmf zmu)
|
||||
ENDFOREACH(CBINARY zma zmc zmu)
|
||||
|
||||
install(TARGETS zmc zma zmu zmf RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(TARGETS zmc zma zmu RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(TARGETS zms RUNTIME DESTINATION "${ZM_CGIDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(CODE "execute_process(COMMAND ln -sf zms nph-zms WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})" )
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nph-zms DESTINATION "${ZM_CGIDIR}")
|
||||
|
|
|
@ -39,10 +39,10 @@ Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_co
|
|||
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",id,width,height,colours,subpixelorder,capture);
|
||||
|
||||
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
||||
if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 16) != 0) {
|
||||
Fatal("Image size is not multiples of 16");
|
||||
} else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 16) != 0 || (imagesize % 12) != 0)) {
|
||||
Fatal("Image size is not multiples of 12 and 16");
|
||||
if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 64) != 0) {
|
||||
Fatal("Image size is not multiples of 64");
|
||||
} else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 64) != 0 || (imagesize % 12) != 0)) {
|
||||
Fatal("Image size is not multiples of 12 and 64");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
141
src/zm_event.cpp
141
src/zm_event.cpp
|
@ -42,8 +42,6 @@ extern "C"
|
|||
#include "zm_sendfile.h"
|
||||
}
|
||||
|
||||
#include "zmf.h"
|
||||
|
||||
#if HAVE_SYS_SENDFILE_H
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
|
@ -221,141 +219,12 @@ void Event::createNotes( std::string ¬es )
|
|||
|
||||
int Event::sd = -1;
|
||||
|
||||
bool Event::OpenFrameSocket( int monitor_id )
|
||||
{
|
||||
if ( sd > 0 )
|
||||
{
|
||||
close( sd );
|
||||
}
|
||||
|
||||
sd = socket( AF_UNIX, SOCK_STREAM, 0);
|
||||
if ( sd < 0 )
|
||||
{
|
||||
Error( "Can't create socket: %s", strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
|
||||
int socket_buffer_size = config.frame_socket_size;
|
||||
if ( socket_buffer_size > 0 )
|
||||
{
|
||||
if ( setsockopt( sd, SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size) ) < 0 )
|
||||
{
|
||||
Error( "Can't get socket buffer size to %d, error = %s", socket_buffer_size, strerror(errno) );
|
||||
close( sd );
|
||||
sd = -1;
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
|
||||
int flags;
|
||||
if ( (flags = fcntl( sd, F_GETFL )) < 0 )
|
||||
{
|
||||
Error( "Can't get socket flags, error = %s", strerror(errno) );
|
||||
close( sd );
|
||||
sd = -1;
|
||||
return( false );
|
||||
}
|
||||
flags |= O_NONBLOCK;
|
||||
if ( fcntl( sd, F_SETFL, flags ) < 0 )
|
||||
{
|
||||
Error( "Can't set socket flags, error = %s", strerror(errno) );
|
||||
close( sd );
|
||||
sd = -1;
|
||||
return( false );
|
||||
}
|
||||
|
||||
char sock_path[PATH_MAX] = "";
|
||||
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
|
||||
|
||||
struct sockaddr_un addr;
|
||||
|
||||
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
if ( connect( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)+1) < 0 )
|
||||
{
|
||||
Warning( "Can't connect to frame server: %s", strerror(errno) );
|
||||
close( sd );
|
||||
sd = -1;
|
||||
return( false );
|
||||
}
|
||||
|
||||
Debug( 1, "Opened connection to frame server" );
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool Event::ValidateFrameSocket( int monitor_id )
|
||||
{
|
||||
if ( sd < 0 )
|
||||
{
|
||||
return( OpenFrameSocket( monitor_id ) );
|
||||
}
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool Event::SendFrameImage( const Image *image, bool alarm_frame )
|
||||
{
|
||||
if ( !ValidateFrameSocket( monitor->Id() ) )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
static int jpg_buffer_size = 0;
|
||||
static unsigned char jpg_buffer[ZM_MAX_IMAGE_SIZE];
|
||||
|
||||
image->EncodeJpeg( jpg_buffer, &jpg_buffer_size, (alarm_frame&&(config.jpeg_alarm_file_quality>config.jpeg_file_quality))?config.jpeg_alarm_file_quality:config.jpeg_file_quality );
|
||||
|
||||
static FrameHeader frame_header;
|
||||
|
||||
frame_header.event_id = id;
|
||||
if ( config.use_deep_storage )
|
||||
frame_header.event_time = start_time.tv_sec;
|
||||
frame_header.frame_id = frames;
|
||||
frame_header.alarm_frame = alarm_frame;
|
||||
frame_header.image_length = jpg_buffer_size;
|
||||
|
||||
struct iovec iovecs[2];
|
||||
iovecs[0].iov_base = &frame_header;
|
||||
iovecs[0].iov_len = sizeof(frame_header);
|
||||
iovecs[1].iov_base = jpg_buffer;
|
||||
iovecs[1].iov_len = jpg_buffer_size;
|
||||
|
||||
ssize_t writev_size = sizeof(frame_header)+jpg_buffer_size;
|
||||
ssize_t writev_result = writev( sd, iovecs, sizeof(iovecs)/sizeof(*iovecs));
|
||||
if ( writev_result != writev_size )
|
||||
{
|
||||
if ( writev_result < 0 )
|
||||
{
|
||||
if ( errno == EAGAIN )
|
||||
{
|
||||
Warning( "Blocking write detected" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Error( "Can't write frame: %s", strerror(errno) );
|
||||
close( sd );
|
||||
sd = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Error( "Incomplete frame write: %zd of %zd bytes written", writev_result, writev_size );
|
||||
close( sd );
|
||||
sd = -1;
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
Debug( 1, "Wrote frame image, %d bytes", jpg_buffer_size );
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame )
|
||||
{
|
||||
Image* ImgToWrite;
|
||||
Image* ts_image = NULL;
|
||||
|
||||
if ( config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped.
|
||||
if ( !config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped.
|
||||
{
|
||||
ts_image = new Image(*image);
|
||||
monitor->TimestampImage( ts_image, ×tamp );
|
||||
|
@ -364,11 +233,9 @@ bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char
|
|||
else
|
||||
ImgToWrite=image;
|
||||
|
||||
if ( !config.opt_frame_server || !SendFrameImage(ImgToWrite, alarm_frame) )
|
||||
{
|
||||
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
|
||||
ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
|
||||
}
|
||||
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
|
||||
ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
|
||||
|
||||
if(ts_image) delete(ts_image); // clean up if used.
|
||||
return( true );
|
||||
}
|
||||
|
|
1536
src/zm_image.cpp
1536
src/zm_image.cpp
File diff suppressed because it is too large
Load Diff
|
@ -54,7 +54,7 @@ extern imgbufcpy_fptr_t fptr_imgbufcpy;
|
|||
|
||||
/* Should be called from Image class functions */
|
||||
inline static uint8_t* AllocBuffer(size_t p_bufsize) {
|
||||
uint8_t* buffer = (uint8_t*)zm_mallocaligned(16,p_bufsize);
|
||||
uint8_t* buffer = (uint8_t*)zm_mallocaligned(64,p_bufsize);
|
||||
if(buffer == NULL)
|
||||
Fatal("Memory allocation failed: %s",strerror(errno));
|
||||
|
||||
|
@ -122,8 +122,8 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
enum { CHAR_HEIGHT=11, CHAR_WIDTH=6 };
|
||||
enum { LINE_HEIGHT=CHAR_HEIGHT+0 };
|
||||
enum { ZM_CHAR_HEIGHT=11, ZM_CHAR_WIDTH=6 };
|
||||
enum { LINE_HEIGHT=ZM_CHAR_HEIGHT+0 };
|
||||
|
||||
protected:
|
||||
static bool initialised;
|
||||
|
@ -264,6 +264,7 @@ public:
|
|||
/* Blend functions */
|
||||
void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||
void std_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||
void neon32_armv7_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||
void std_blend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||
|
||||
/* Delta functions */
|
||||
|
@ -274,6 +275,11 @@ void std_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result,
|
|||
void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void neon32_armv7_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void neon32_armv7_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void neon32_armv7_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void neon32_armv7_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void neon32_armv7_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||
|
@ -293,6 +299,9 @@ void std_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long
|
|||
void std_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void std_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void ssse3_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void ssse3_convert_bgra_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void ssse3_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void ssse3_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void ssse3_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void zm_convert_yuyv_rgb(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
void zm_convert_yuyv_rgba(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||
|
@ -309,8 +318,3 @@ void std_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int thre
|
|||
void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
void ssse3_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
void ssse3_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
void ssse3_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
void ssse3_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
void ssse3_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||
|
|
|
@ -182,8 +182,8 @@ int LibvlcCamera::PrimeCapture()
|
|||
|
||||
mLibvlcData.bufferSize = width * height * mBpp;
|
||||
// Libvlc wants 32 byte alignment for images (should in theory do this for all image lines)
|
||||
mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize);
|
||||
mLibvlcData.prevBuffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize);
|
||||
mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(64, mLibvlcData.bufferSize);
|
||||
mLibvlcData.prevBuffer = (uint8_t*)zm_mallocaligned(64, mLibvlcData.bufferSize);
|
||||
|
||||
mLibvlcData.newImage.setValueImmediate(false);
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
|
|||
palette = V4L2_PIX_FMT_YUYV;
|
||||
} else {
|
||||
if(capture) {
|
||||
Info("Selected capture palette: %s (%c%c%c%c)", palette_desc, palette&0xff, (palette>>8)&0xff, (palette>>16)&0xff, (palette>>24)&0xff);
|
||||
Info("Selected capture palette: %s (0x%02hhx%02hhx%02hhx%02hhx)", palette_desc, (palette>>24)&0xff, (palette>>16)&0xff, (palette>>8)&0xff, (palette)&0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -409,7 +409,8 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
|
|||
} else {
|
||||
if( capture )
|
||||
#if HAVE_LIBSWSCALE
|
||||
Info("No direct match for the selected palette (%c%c%c%c) and target colorspace (%d). Format conversion is required, performance penalty expected", (capturePixFormat)&0xff,((capturePixFormat>>8)&0xff),((capturePixFormat>>16)&0xff),((capturePixFormat>>24)&0xff), colours );
|
||||
Info("No direct match for the selected palette (0x%02hhx%02hhx%02hhx%02hhx) and target colorspace (%02u). Format conversion is required, performance penalty expected",
|
||||
(capturePixFormat>>24)&0xff,((capturePixFormat>>16)&0xff),((capturePixFormat>>8)&0xff),((capturePixFormat)&0xff), colours);
|
||||
#else
|
||||
Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected");
|
||||
#endif
|
||||
|
@ -427,16 +428,18 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
|
|||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
imagePixFormat = AV_PIX_FMT_GRAY8;
|
||||
} else {
|
||||
Panic("Unexpected colours: %d",colours);
|
||||
Panic("Unexpected colours: %u",colours);
|
||||
}
|
||||
if( capture ) {
|
||||
#if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0)
|
||||
if(!sws_isSupportedInput(capturePixFormat)) {
|
||||
Error("swscale does not support the used capture format: %c%c%c%c",(capturePixFormat)&0xff,((capturePixFormat>>8)&0xff),((capturePixFormat>>16)&0xff),((capturePixFormat>>24)&0xff));
|
||||
Error("swscale does not support the used capture format: 0x%02hhx%02hhx%02hhx%02hhx",
|
||||
(capturePixFormat>>24)&0xff,((capturePixFormat>>16)&0xff),((capturePixFormat>>8)&0xff),((capturePixFormat)&0xff));
|
||||
conversion_type = 2; /* Try ZM format conversions */
|
||||
}
|
||||
if(!sws_isSupportedOutput(imagePixFormat)) {
|
||||
Error("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff));
|
||||
Error("swscale does not support the target format: 0x%02hhx%02hhx%02hhx%02hhx",
|
||||
(imagePixFormat>>24)&0xff,((imagePixFormat>>16)&0xff),((imagePixFormat>>8)&0xff),((imagePixFormat)&0xff));
|
||||
conversion_type = 2; /* Try ZM format conversions */
|
||||
}
|
||||
#endif
|
||||
|
@ -545,7 +548,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
|
|||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
imagePixFormat = AV_PIX_FMT_GRAY8;
|
||||
} else {
|
||||
Panic("Unexpected colours: %d",colours);
|
||||
Panic("Unexpected colours: %u",colours);
|
||||
}
|
||||
if( capture ) {
|
||||
if(!sws_isSupportedInput(capturePixFormat)) {
|
||||
|
@ -613,7 +616,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
|
|||
#endif // ZM_HAS_V4L1
|
||||
|
||||
last_camera = this;
|
||||
Debug(3,"Selected subpixelorder: %d",subpixelorder);
|
||||
Debug(3,"Selected subpixelorder: %u",subpixelorder);
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
/* Initialize swscale stuff */
|
||||
|
@ -632,7 +635,7 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
|
|||
int pSize = avpicture_get_size( imagePixFormat, width, height );
|
||||
#endif
|
||||
if( (unsigned int)pSize != imagesize) {
|
||||
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
|
||||
Fatal("Image size mismatch. Required: %d Available: %u",pSize,imagesize);
|
||||
}
|
||||
|
||||
imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
|
||||
|
@ -789,7 +792,7 @@ void LocalCamera::Initialise()
|
|||
Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno) );
|
||||
} else {
|
||||
Debug(4, "JPEG quality: %d",jpeg_comp.quality);
|
||||
Debug(4, "JPEG markers: %#x",jpeg_comp.jpeg_markers);
|
||||
Debug(4, "JPEG markers: 0x%x",jpeg_comp.jpeg_markers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -853,7 +856,7 @@ void LocalCamera::Initialise()
|
|||
v4l2_data.buffers[i].start = mmap( NULL, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset );
|
||||
|
||||
if ( v4l2_data.buffers[i].start == MAP_FAILED )
|
||||
Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno );
|
||||
Fatal( "Can't map video buffer %u (%u bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno );
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
|
||||
|
@ -1177,7 +1180,8 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) {
|
|||
strcpy(fmt_desc[nIndex], (const char*)(fmtinfo.description));
|
||||
fmt_fcc[nIndex] = fmtinfo.pixelformat;
|
||||
|
||||
Debug(6, "Got format: %s (%c%c%c%c) at index %d",fmt_desc[nIndex],fmt_fcc[nIndex]&0xff, (fmt_fcc[nIndex]>>8)&0xff, (fmt_fcc[nIndex]>>16)&0xff, (fmt_fcc[nIndex]>>24)&0xff ,nIndex);
|
||||
Debug(6, "Got format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %d",
|
||||
fmt_desc[nIndex], (fmt_fcc[nIndex]>>24)&0xff, (fmt_fcc[nIndex]>>16)&0xff, (fmt_fcc[nIndex]>>8)&0xff, (fmt_fcc[nIndex])&0xff ,nIndex);
|
||||
|
||||
/* Proceed to the next index */
|
||||
memset(&fmtinfo, 0, sizeof(fmtinfo));
|
||||
|
@ -1205,12 +1209,14 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) {
|
|||
for( unsigned int i=0; i < n_preferedformats && nIndexUsed < 0; i++ ) {
|
||||
for( unsigned int j=0; j < nIndex; j++ ) {
|
||||
if( preferedformats[i] == fmt_fcc[j] ) {
|
||||
Debug(6, "Choosing format: %s (%c%c%c%c) at index %d",fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j);
|
||||
Debug(6, "Choosing format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %u",
|
||||
fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j);
|
||||
/* Found a format! */
|
||||
nIndexUsed = j;
|
||||
break;
|
||||
} else {
|
||||
Debug(6, "No match for format: %s (%c%c%c%c) at index %d",fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j);
|
||||
Debug(6, "No match for format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %u",
|
||||
fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1385,9 +1391,11 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
}
|
||||
}
|
||||
if ( verbose )
|
||||
sprintf( output+strlen(output), " %s (%c%c%c%c)\n", format.description, format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff );
|
||||
sprintf( output+strlen(output), " %s (0x%02hhx%02hhx%02hhx%02hhx)\n",
|
||||
format.description, (format.pixelformat>>24)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>8)&0xff, format.pixelformat&0xff);
|
||||
else
|
||||
sprintf( output+strlen(output), "%c%c%c%c/", format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff );
|
||||
sprintf( output+strlen(output), "0x%02hhx%02hhx%02hhx%02hhx/",
|
||||
(format.pixelformat>>24)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat)&0xff);
|
||||
}
|
||||
while ( formatIndex++ >= 0 );
|
||||
if ( !verbose )
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/thr.h>
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
bool Logger::smInitialised = false;
|
||||
|
@ -515,7 +515,8 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
va_list argPtr;
|
||||
struct timeval timeVal;
|
||||
|
||||
const char * const file = basename(filepath);
|
||||
char *filecopy = strdup(filepath);
|
||||
const char * const file = basename(filecopy);
|
||||
|
||||
if ( level < PANIC || level > DEBUG9 )
|
||||
Panic( "Invalid logger level %d", level );
|
||||
|
@ -631,6 +632,8 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
syslog( priority, "%s [%s]", classString, syslogStart );
|
||||
}
|
||||
|
||||
free(filecopy);
|
||||
|
||||
if ( level <= FATAL )
|
||||
{
|
||||
if ( level <= PANIC )
|
||||
|
|
|
@ -160,7 +160,7 @@ bool Monitor::MonitorLink::connect()
|
|||
return( false );
|
||||
}
|
||||
mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 );
|
||||
if ( mem_ptr < 0 )
|
||||
if ( mem_ptr < (void *)0 )
|
||||
{
|
||||
Debug( 3, "Can't shmat link memory: %s", strerror(errno) );
|
||||
connected = false;
|
||||
|
@ -194,7 +194,7 @@ bool Monitor::MonitorLink::disconnect()
|
|||
connected = false;
|
||||
|
||||
#if ZM_MEM_MAPPED
|
||||
if ( mem_ptr > 0 )
|
||||
if ( mem_ptr > (void *)0 )
|
||||
{
|
||||
msync( mem_ptr, mem_size, MS_ASYNC );
|
||||
munmap( mem_ptr, mem_size );
|
||||
|
@ -393,7 +393,7 @@ Monitor::Monitor(
|
|||
+ sizeof(TriggerData)
|
||||
+ (image_buffer_count*sizeof(struct timeval))
|
||||
+ (image_buffer_count*camera->ImageSize())
|
||||
+ 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */
|
||||
+ 64; /* Padding used to permit aligning the images buffer to 64 byte boundary */
|
||||
|
||||
Debug( 1, "mem.size=%d", mem_size );
|
||||
mem_ptr = NULL;
|
||||
|
@ -558,7 +558,7 @@ bool Monitor::connect() {
|
|||
exit( -1 );
|
||||
}
|
||||
mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 );
|
||||
if ( mem_ptr < 0 )
|
||||
if ( mem_ptr < (void *)0 )
|
||||
{
|
||||
Error( "Can't shmat: %s", strerror(errno));
|
||||
exit( -1 );
|
||||
|
@ -569,10 +569,10 @@ bool Monitor::connect() {
|
|||
struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData));
|
||||
unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval)));
|
||||
|
||||
if(((unsigned long)shared_images % 16) != 0) {
|
||||
/* Align images buffer to nearest 16 byte boundary */
|
||||
Debug(3,"Aligning shared memory images to the next 16 byte boundary");
|
||||
shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16)));
|
||||
if(((unsigned long)shared_images % 64) != 0) {
|
||||
/* Align images buffer to nearest 64 byte boundary */
|
||||
Debug(3,"Aligning shared memory images to the next 64 byte boundary");
|
||||
shared_images = (uint8_t*)((unsigned long)shared_images + (64 - ((unsigned long)shared_images % 64)));
|
||||
}
|
||||
image_buffer = new Snapshot[image_buffer_count];
|
||||
for ( int i = 0; i < image_buffer_count; i++ )
|
||||
|
|
|
@ -24,8 +24,16 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#if defined(__arm__)
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CURL_CURL_H
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
unsigned int sseversion = 0;
|
||||
unsigned int neonversion = 0;
|
||||
|
||||
std::string trimSet(std::string str, std::string trimset) {
|
||||
// Trim Both leading and trailing sets
|
||||
|
@ -234,30 +242,59 @@ int pairsplit(const char* string, const char delim, std::string& name, std::stri
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Sets sse_version */
|
||||
void ssedetect() {
|
||||
/* Detect special hardware features, such as SIMD instruction sets */
|
||||
void hwcaps_detect() {
|
||||
neonversion = 0;
|
||||
sseversion = 0;
|
||||
#if (defined(__i386__) || defined(__x86_64__))
|
||||
/* x86 or x86-64 processor */
|
||||
uint32_t r_edx, r_ecx;
|
||||
uint32_t r_edx, r_ecx, r_ebx;
|
||||
|
||||
#ifdef __x86_64__
|
||||
__asm__ __volatile__(
|
||||
#if defined(__i386__)
|
||||
"pushl %%ebx;\n\t"
|
||||
#endif
|
||||
"push %%rbx\n\t"
|
||||
"mov $0x0,%%ecx\n\t"
|
||||
"mov $0x7,%%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"push %%rbx\n\t"
|
||||
"mov $0x1,%%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
#if defined(__i386__)
|
||||
"popl %%ebx;\n\t"
|
||||
#endif
|
||||
: "=d" (r_edx), "=c" (r_ecx)
|
||||
"pop %%rax\n\t"
|
||||
"pop %%rbx\n\t"
|
||||
: "=d" (r_edx), "=c" (r_ecx), "=a" (r_ebx)
|
||||
:
|
||||
:
|
||||
: "%eax"
|
||||
#if !defined(__i386__)
|
||||
, "%ebx"
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
__asm__ __volatile__(
|
||||
"push %%ebx\n\t"
|
||||
"mov $0x0,%%ecx\n\t"
|
||||
"mov $0x7,%%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"push %%ebx\n\t"
|
||||
"mov $0x1,%%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"pop %%eax\n\t"
|
||||
"pop %%ebx\n\t"
|
||||
: "=d" (r_edx), "=c" (r_ecx), "=a" (r_ebx)
|
||||
:
|
||||
:
|
||||
);
|
||||
#endif
|
||||
|
||||
if (r_ecx & 0x00000200) {
|
||||
if (r_ebx & 0x00000020) {
|
||||
sseversion = 52; /* AVX2 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with AVX2");
|
||||
} else if (r_ecx & 0x10000000) {
|
||||
sseversion = 51; /* AVX */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with AVX");
|
||||
} else if (r_ecx & 0x00100000) {
|
||||
sseversion = 42; /* SSE4.2 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE4.2");
|
||||
} else if (r_ecx & 0x00080000) {
|
||||
sseversion = 41; /* SSE4.1 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE4.1");
|
||||
} else if (r_ecx & 0x00000200) {
|
||||
sseversion = 35; /* SSSE3 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
||||
} else if (r_ecx & 0x00000001) {
|
||||
|
@ -273,11 +310,19 @@ void ssedetect() {
|
|||
sseversion = 0;
|
||||
Debug(1,"Detected a x86\\x86-64 processor");
|
||||
}
|
||||
|
||||
#elif defined(__arm__)
|
||||
// ARM processor
|
||||
// To see if it supports NEON, we need to get that information from the kernel
|
||||
unsigned long auxval = getauxval(AT_HWCAP);
|
||||
if (auxval & HWCAP_ARM_NEON) {
|
||||
Debug(1,"Detected ARM processor with Neon");
|
||||
neonversion = 1;
|
||||
} else {
|
||||
Debug(1,"Detected ARM processor");
|
||||
}
|
||||
#else
|
||||
/* Non x86 or x86-64 processor, SSE2 is not available */
|
||||
Debug(1,"Detected a non x86\\x86-64 processor");
|
||||
sseversion = 0;
|
||||
// Unknown processor
|
||||
Debug(1,"Detected unknown processor architecture");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -345,3 +390,18 @@ void timespec_diff(struct timespec *start, struct timespec *end, struct timespec
|
|||
}
|
||||
}
|
||||
|
||||
std::string UriDecode( const std::string &encoded ) {
|
||||
#ifdef HAVE_LIBCURL
|
||||
CURL *curl = curl_easy_init();
|
||||
int outlength;
|
||||
char *cres = curl_easy_unescape(curl, encoded.c_str(), encoded.length(), &outlength);
|
||||
std::string res(cres, cres + outlength);
|
||||
curl_free(cres);
|
||||
curl_easy_cleanup(curl);
|
||||
return res;
|
||||
#else
|
||||
Warning("ZM Compiled without LIBCURL. UriDecoding not implemented.");
|
||||
return encoded;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -54,10 +54,13 @@ inline int min( int a, int b )
|
|||
return( a<=b?a:b );
|
||||
}
|
||||
|
||||
void ssedetect();
|
||||
void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes);
|
||||
void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff);
|
||||
|
||||
void hwcaps_detect();
|
||||
extern unsigned int sseversion;
|
||||
extern unsigned int neonversion;
|
||||
|
||||
std::string UriDecode( const std::string &encoded );
|
||||
|
||||
#endif // ZM_UTILS_H
|
||||
|
|
|
@ -990,12 +990,14 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
|
|||
Polygon polygon;
|
||||
if ( !ParsePolygonString( Coords, polygon ) ) {
|
||||
Error( "Unable to parse polygon string '%s' for zone %d/%s for monitor %s, ignoring", Coords, Id, Name, monitor->Name() );
|
||||
n_zones -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( polygon.LoX() < 0 || polygon.HiX() >= (int)monitor->Width()
|
||||
|| polygon.LoY() < 0 || polygon.HiY() >= (int)monitor->Height() ) {
|
||||
Error( "Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), ignoring", Id, Name, monitor->Name(), polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY() );
|
||||
n_zones -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ int main( int argc, char *argv[] )
|
|||
|
||||
logInit( log_id_string );
|
||||
|
||||
ssedetect();
|
||||
hwcaps_detect();
|
||||
|
||||
Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS );
|
||||
|
||||
|
@ -141,11 +141,6 @@ int main( int argc, char *argv[] )
|
|||
{
|
||||
Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() );
|
||||
|
||||
if ( config.opt_frame_server )
|
||||
{
|
||||
Event::OpenFrameSocket( monitor->Id() );
|
||||
}
|
||||
|
||||
zmSetDefaultHupHandler();
|
||||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
|
|
|
@ -27,7 +27,6 @@ zmc - The ZoneMinder Capture daemon
|
|||
|
||||
zmc -d <device_path>
|
||||
zmc --device <device_path>
|
||||
zmc -r <proto> -H <host> -P <port> -p <path>
|
||||
zmc -f <file_path>
|
||||
zmc --file <file_path>
|
||||
zmc -m <monitor_id>
|
||||
|
@ -45,7 +44,6 @@ possible, this should run at more or less constant speed.
|
|||
=head1 OPTIONS
|
||||
|
||||
-d, --device <device_path> - For local cameras, device to access. e.g /dev/video0 etc
|
||||
-r <proto> -H <host> -P <port> -p <path> - For remote cameras
|
||||
-f, --file <file_path> - For local images, jpg file to access.
|
||||
-m, --monitor_id - ID of the monitor to analyse
|
||||
-h, --help - Display usage information
|
||||
|
@ -83,7 +81,6 @@ void Usage()
|
|||
#else
|
||||
fprintf( stderr, " -d, --device <device_path> : For local cameras, device to access. E.g /dev/video0 etc\n" );
|
||||
#endif
|
||||
fprintf( stderr, " -r <proto> -H <host> -P <port> -p <path> : For remote cameras\n" );
|
||||
fprintf( stderr, " -f, --file <file_path> : For local images, jpg file to access.\n" );
|
||||
fprintf( stderr, " -m, --monitor <monitor_id> : For sources associated with a single monitor\n" );
|
||||
fprintf( stderr, " -h, --help : This screen\n" );
|
||||
|
@ -173,14 +170,14 @@ int main( int argc, char *argv[] )
|
|||
int modes = ( device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id>0?1:0) );
|
||||
if ( modes > 1 )
|
||||
{
|
||||
fprintf( stderr, "Only one of device, host/port/path, file or monitor id allowed\n" );
|
||||
fprintf( stderr, "Only one of device, file or monitor id allowed\n" );
|
||||
Usage();
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( modes < 1 )
|
||||
{
|
||||
fprintf( stderr, "One of device, host/port/path, file or monitor id must be specified\n" );
|
||||
fprintf( stderr, "One of device, file or monitor id must be specified\n" );
|
||||
Usage();
|
||||
exit( 0 );
|
||||
}
|
||||
|
@ -209,7 +206,7 @@ int main( int argc, char *argv[] )
|
|||
|
||||
logInit( log_id_string );
|
||||
|
||||
ssedetect();
|
||||
hwcaps_detect();
|
||||
|
||||
Monitor **monitors = 0;
|
||||
int n_monitors = 0;
|
||||
|
|
350
src/zmf.cpp
350
src/zmf.cpp
|
@ -1,350 +0,0 @@
|
|||
//
|
||||
// ZoneMinder Image File Writer Implementation, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
=head1 NAME
|
||||
|
||||
zmf - The ZoneMinder Frame daemon
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
zmf -m <monitor_id>
|
||||
zmf --monitor <monitor_id>
|
||||
zmf -h
|
||||
zmf --help
|
||||
zmf -v
|
||||
zmf --version
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is an optional daemon that can run in concert with the Analysis daemon and
|
||||
whose function it is to actually write captured frames to disk. This frees up
|
||||
the Analysis daemon to do more analysis (!) and so keep up with the Capture
|
||||
daemon better. If it isn't running or dies then the Analysis daemon just writes
|
||||
them itself.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
-m, --monitor_id - ID of the monitor to use
|
||||
-h, --help - Display usage information
|
||||
-v, --version - Print the installed version of ZoneMinder
|
||||
|
||||
=cut
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
#include "zm_signal.h"
|
||||
#include "zm_monitor.h"
|
||||
|
||||
#include "zmf.h"
|
||||
|
||||
int OpenSocket( int monitor_id )
|
||||
{
|
||||
int sd = socket( AF_UNIX, SOCK_STREAM, 0);
|
||||
if ( sd < 0 )
|
||||
{
|
||||
Error( "Can't create socket: %s", strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
char sock_path[PATH_MAX] = "";
|
||||
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
|
||||
if ( unlink( sock_path ) < 0 )
|
||||
{
|
||||
Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) );
|
||||
}
|
||||
|
||||
struct sockaddr_un addr;
|
||||
|
||||
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 )
|
||||
{
|
||||
Error( "Can't bind: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if ( listen( sd, SOMAXCONN ) < 0 )
|
||||
{
|
||||
Error( "Can't listen: %s", strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
struct sockaddr_un rem_addr;
|
||||
socklen_t rem_addr_len = sizeof(rem_addr);
|
||||
int new_sd = -1;
|
||||
if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 )
|
||||
{
|
||||
Error( "Can't accept: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
close( sd );
|
||||
|
||||
sd = new_sd;
|
||||
|
||||
Info( "Frame server socket open, awaiting images" );
|
||||
return( sd );
|
||||
}
|
||||
|
||||
int ReopenSocket( int &sd, int monitor_id )
|
||||
{
|
||||
close( sd );
|
||||
return( sd = OpenSocket( monitor_id ) );
|
||||
}
|
||||
|
||||
void Usage()
|
||||
{
|
||||
fprintf( stderr, "zmf -m <monitor_id>\n" );
|
||||
fprintf( stderr, "Options:\n" );
|
||||
fprintf( stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n" );
|
||||
fprintf( stderr, " -h, --help : This screen\n" );
|
||||
fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
self = argv[0];
|
||||
|
||||
srand( getpid() * time( 0 ) );
|
||||
|
||||
int id = -1;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"monitor", 1, 0, 'm'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"version", 0, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while (1)
|
||||
{
|
||||
int option_index = 0;
|
||||
|
||||
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
|
||||
if (c == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'm':
|
||||
id = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
Usage();
|
||||
break;
|
||||
case 'v':
|
||||
std::cout << ZM_VERSION << "\n";
|
||||
exit(0);
|
||||
default:
|
||||
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
fprintf( stderr, "Extraneous options, " );
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
Usage();
|
||||
}
|
||||
|
||||
if ( id < 0 )
|
||||
{
|
||||
fprintf( stderr, "Bogus monitor %d\n", id );
|
||||
Usage();
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
char log_id_string[16];
|
||||
snprintf( log_id_string, sizeof(log_id_string), "m%d", id );
|
||||
|
||||
zmLoadConfig();
|
||||
|
||||
logInit( "zmf" );
|
||||
|
||||
ssedetect();
|
||||
|
||||
Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );
|
||||
|
||||
if ( !monitor )
|
||||
{
|
||||
fprintf( stderr, "Can't find monitor with id of %d\n", id );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
char capt_path[PATH_MAX];
|
||||
char anal_path[PATH_MAX];
|
||||
snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
|
||||
snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
|
||||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
|
||||
sigset_t block_set;
|
||||
sigemptyset( &block_set );
|
||||
|
||||
int sd = OpenSocket( monitor->Id() );
|
||||
|
||||
FrameHeader frame_header = { 0, 0, false, 0 };
|
||||
//unsigned char *image_data = 0;
|
||||
|
||||
fd_set rfds;
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
while( 1 )
|
||||
{
|
||||
struct timeval temp_timeout = timeout;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(sd, &rfds);
|
||||
int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
|
||||
if( n_found == 0 )
|
||||
{
|
||||
Debug( 1, "Select timed out" );
|
||||
continue;
|
||||
}
|
||||
else if ( n_found < 0)
|
||||
{
|
||||
Error( "Select error: %s", strerror(errno) );
|
||||
ReopenSocket( sd, monitor->Id() );
|
||||
continue;
|
||||
}
|
||||
|
||||
sigprocmask( SIG_BLOCK, &block_set, 0 );
|
||||
|
||||
int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
|
||||
if ( n_bytes != sizeof(frame_header) )
|
||||
{
|
||||
if ( n_bytes < 0 )
|
||||
{
|
||||
Error( "Can't read frame header: %s", strerror(errno) );
|
||||
}
|
||||
else if ( n_bytes > 0 )
|
||||
{
|
||||
Error( "Incomplete read of frame header, %d bytes only", n_bytes );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Socket closed at remote end" );
|
||||
}
|
||||
ReopenSocket( sd, monitor->Id() );
|
||||
continue;
|
||||
}
|
||||
Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
|
||||
static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
|
||||
|
||||
// Read for pipe and loop until bytes expected have been read or an error occurs
|
||||
int bytes_read = 0;
|
||||
do
|
||||
{
|
||||
n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read );
|
||||
if (n_bytes < 0) break; // break on error
|
||||
if (n_bytes < (int)frame_header.image_length)
|
||||
{
|
||||
// print some informational messages
|
||||
if (bytes_read == 0)
|
||||
{
|
||||
Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length);
|
||||
}
|
||||
else if (bytes_read+n_bytes == (int)frame_header.image_length)
|
||||
{
|
||||
Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes);
|
||||
}
|
||||
}
|
||||
bytes_read+= n_bytes;
|
||||
} while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) );
|
||||
|
||||
// Print errors if there was a problem
|
||||
if ( n_bytes < 1 )
|
||||
{
|
||||
Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length);
|
||||
if ( n_bytes < 0 )
|
||||
{
|
||||
Error( "Can't read frame image data: %s", strerror(errno) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Socket closed at remote end" );
|
||||
}
|
||||
ReopenSocket( sd, monitor->Id() );
|
||||
continue;
|
||||
}
|
||||
|
||||
static char subpath[PATH_MAX] = "";
|
||||
if ( config.use_deep_storage )
|
||||
{
|
||||
struct tm *time = localtime( &frame_header.event_time );
|
||||
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
|
||||
}
|
||||
|
||||
static char path[PATH_MAX] = "";
|
||||
snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
|
||||
Debug( 1, "Got image, writing to %s", path );
|
||||
|
||||
FILE *fd = 0;
|
||||
if ( (fd = fopen( path, "w" )) < 0 )
|
||||
{
|
||||
Error( "Can't fopen '%s': %s", path, strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
|
||||
{
|
||||
Error( "Can't fwrite image data: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
fclose( fd );
|
||||
|
||||
sigprocmask( SIG_UNBLOCK, &block_set, 0 );
|
||||
}
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
}
|
32
src/zmf.h
32
src/zmf.h
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// ZoneMinder Image File Write Class Interface, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
#ifndef ZMFILE_H
|
||||
#define ZMFILE_H
|
||||
|
||||
struct FrameHeader
|
||||
{
|
||||
unsigned long event_id;
|
||||
time_t event_time;
|
||||
unsigned long frame_id;
|
||||
bool alarm_frame;
|
||||
unsigned long image_length;
|
||||
};
|
||||
|
||||
#endif // ZMFILE_H
|
20
src/zms.cpp
20
src/zms.cpp
|
@ -69,8 +69,8 @@ int main( int argc, const char *argv[] )
|
|||
unsigned int bitrate = 100000;
|
||||
unsigned int ttl = 0;
|
||||
EventStream::StreamMode replay = EventStream::MODE_SINGLE;
|
||||
char username[64] = "";
|
||||
char password[64] = "";
|
||||
std::string username;
|
||||
std::string password;
|
||||
char auth[64] = "";
|
||||
unsigned int connkey = 0;
|
||||
unsigned int playback_buffer = 0;
|
||||
|
@ -91,7 +91,7 @@ int main( int argc, const char *argv[] )
|
|||
|
||||
logInit( "zms" );
|
||||
|
||||
ssedetect();
|
||||
hwcaps_detect();
|
||||
|
||||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
|
@ -164,7 +164,7 @@ int main( int argc, const char *argv[] )
|
|||
{
|
||||
if ( !strcmp( name, "user" ) )
|
||||
{
|
||||
strncpy( username, value, sizeof(username) );
|
||||
username = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -180,11 +180,11 @@ int main( int argc, const char *argv[] )
|
|||
{
|
||||
if ( !strcmp( name, "user" ) )
|
||||
{
|
||||
strncpy( username, value, sizeof(username) );
|
||||
username = UriDecode( value );
|
||||
}
|
||||
if ( !strcmp( name, "pass" ) )
|
||||
{
|
||||
strncpy( password, value, sizeof(password) );
|
||||
password = UriDecode( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,9 +198,9 @@ int main( int argc, const char *argv[] )
|
|||
|
||||
if ( strcmp( config.auth_relay, "none" ) == 0 )
|
||||
{
|
||||
if ( *username )
|
||||
if ( username.length() )
|
||||
{
|
||||
user = zmLoadUser( username );
|
||||
user = zmLoadUser( username.c_str() );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -214,9 +214,9 @@ int main( int argc, const char *argv[] )
|
|||
}
|
||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||
{
|
||||
if ( *username && *password )
|
||||
if ( username.length() && password.length() )
|
||||
{
|
||||
user = zmLoadUser( username, password );
|
||||
user = zmLoadUser( username.c_str(), password.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,252 +0,0 @@
|
|||
//
|
||||
// ZoneMinder Streamer, $Date: 2010-10-14 23:21:00 +0200 (Thu, 14 Oct 2010) $
|
||||
// Copyright (C) 2001-2010 Philip Coombes, Chris Kistner
|
||||
//
|
||||
// This program is based on revision 3143 of
|
||||
// http://svn.zoneminder.com/svn/zm/trunk/src/zms.cpp
|
||||
//
|
||||
// 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.
|
||||
|
||||
/*
|
||||
|
||||
=head1 NAME
|
||||
|
||||
zmstreamer - eyeZM video streamer
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
zmstreamer -e <mode>
|
||||
zmstreamer -o <format>
|
||||
zmstreamer -u <buffer size>
|
||||
zmstreamer -f <maximum fps>
|
||||
zmstreamer -s <scale>
|
||||
zmstreamer -b <bitrate in bps>
|
||||
zmstreamer -m <monitor id>
|
||||
zmstreamer -d <debug mode>
|
||||
zmstreamer -i
|
||||
zmstreamer -?
|
||||
zmstreamer -h
|
||||
zmstreamer -v
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
*DEPRECIATED* The xml skin and all files associated with the xml skin are now
|
||||
depreciated. Please use the ZoneMinder API instead.
|
||||
|
||||
This binary works in conjunction with the XML skin to stream video to iPhones
|
||||
running the eyeZm app.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
-e <mode> - Specify output mode: mpeg/jpg/zip/single/raw.
|
||||
-o <format> - Specify output format.
|
||||
-u <buffer size> - Specify buffer size in ms.
|
||||
-f <maximum fps> - Specify maximum framerate.
|
||||
-s <scale> - Specify scale.
|
||||
-b <bitrate in bps> - Specify bitrate.
|
||||
-m <monitor id> - Specify monitor id.
|
||||
-d <debug mode> - 0 = off, 1 = no streaming, 2 = with streaming.
|
||||
-i, -?, -h - Display usage information
|
||||
-v - Print the installed version of ZoneMinder
|
||||
|
||||
=cut
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
#include "zm_user.h"
|
||||
#include "zm_signal.h"
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_stream.h"
|
||||
|
||||
// Possible command-line options
|
||||
#define OPTIONS "e:o:u:f:s:b:m:d:i:?:h:v"
|
||||
|
||||
// Default ZMS values
|
||||
#define ZMS_DEFAULT_DEBUG 0
|
||||
#define ZMS_DEFAULT_ID 1
|
||||
#define ZMS_DEFAULT_BITRATE 100000
|
||||
#define ZMS_DEFAULT_SCALE 100
|
||||
#define ZMS_DEFAULT_MODE "mpeg"
|
||||
#define ZMS_DEFAULT_FORMAT "asf"
|
||||
#define ZMS_DEFAULT_FPS 25.0
|
||||
#define ZMS_DEFAULT_BUFFER 1000
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
self = argv[0];
|
||||
// Set initial values to the default values
|
||||
int debug = ZMS_DEFAULT_DEBUG;
|
||||
int id = ZMS_DEFAULT_ID;
|
||||
int bitrate = ZMS_DEFAULT_BITRATE;
|
||||
int scale = ZMS_DEFAULT_SCALE;
|
||||
char mode[32];
|
||||
sprintf(mode, "%s", ZMS_DEFAULT_MODE);
|
||||
char format[32];
|
||||
sprintf(format, "%s", ZMS_DEFAULT_FORMAT);
|
||||
double maxfps = ZMS_DEFAULT_FPS;
|
||||
int buffer = ZMS_DEFAULT_BUFFER;
|
||||
|
||||
// Parse command-line options
|
||||
int arg;
|
||||
while ((arg = getopt(argc, argv, OPTIONS)) != -1) {
|
||||
switch (arg) {
|
||||
case 'e':
|
||||
sprintf(mode, "%s", optarg);
|
||||
break;
|
||||
case 'o':
|
||||
sprintf(format, "%s", optarg);
|
||||
break;
|
||||
case 'u':
|
||||
buffer = atoi(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
maxfps = atof(optarg);
|
||||
break;
|
||||
case 's':
|
||||
scale = atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
bitrate = atoi(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
id = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
debug = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
case 'i':
|
||||
case '?':
|
||||
printf("-e <mode> : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE);
|
||||
printf("-o <format> : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT);
|
||||
printf("-u <buffer size> : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER);
|
||||
printf("-f <maximum fps> : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS);
|
||||
printf("-s <scale> : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE);
|
||||
printf("-b <bitrate in bps> : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE);
|
||||
printf("-m <monitor id> : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID);
|
||||
printf("-d <debug mode> : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n");
|
||||
printf("-i or -? or -h: This information\n");
|
||||
printf("-v : This installed version of ZoneMinder\n");
|
||||
return EXIT_SUCCESS;
|
||||
case 'v':
|
||||
std::cout << ZM_VERSION << "\n";
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Set stream type
|
||||
StreamBase::StreamType streamtype;
|
||||
if (!strcasecmp("raw", mode))
|
||||
streamtype = MonitorStream::STREAM_RAW;
|
||||
else if (!strcasecmp("mpeg", mode))
|
||||
streamtype = MonitorStream::STREAM_MPEG;
|
||||
else if (!strcasecmp("jpg", mode))
|
||||
streamtype = MonitorStream::STREAM_JPEG;
|
||||
else if (!strcasecmp("single", mode))
|
||||
streamtype = MonitorStream::STREAM_SINGLE;
|
||||
else if (!strcasecmp("zip", mode))
|
||||
streamtype = MonitorStream::STREAM_ZIP;
|
||||
else
|
||||
streamtype = MonitorStream::STREAM_MPEG;
|
||||
|
||||
if (debug) {
|
||||
// Show stream parameters
|
||||
printf("Stream parameters:\n");
|
||||
switch (streamtype) {
|
||||
case MonitorStream::STREAM_MPEG:
|
||||
printf("Output mode (-e) = %s\n", "mpeg");
|
||||
printf("Output format (-o) = %s\n", format);
|
||||
break;
|
||||
default:
|
||||
printf("Output mode (-e) = %s\n", mode);
|
||||
}
|
||||
printf("Buffer size (-u) = %d ms\n", buffer);
|
||||
printf("Maximum FPS (-f) = %lf FPS\n", maxfps);
|
||||
printf("Scale (-s) = %d%%\n", scale);
|
||||
printf("Bitrate (-b) = %d bps\n", bitrate);
|
||||
printf("Monitor Id (-m) = %d\n", id);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
// Set ZM debugger to print to stdout
|
||||
printf("Setting up ZoneMinder debugger to print to stdout...");
|
||||
setenv("ZM_DBG_PRINT", "1", 1);
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
// Loading ZM configurations
|
||||
printf("Loading ZoneMinder configurations...");
|
||||
zmLoadConfig();
|
||||
printf("Done.\n");
|
||||
|
||||
logInit("zmstreamer");
|
||||
|
||||
ssedetect();
|
||||
|
||||
// Setting stream parameters
|
||||
MonitorStream stream;
|
||||
stream.setStreamScale(scale); // default = 100 (scale)
|
||||
stream.setStreamReplayRate(100); // default = 100 (rate)
|
||||
stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps)
|
||||
if (debug) stream.setStreamTTL(1);
|
||||
else stream.setStreamTTL(0); // default = 0 (ttl)
|
||||
stream.setStreamQueue(0); // default = 0 (connkey)
|
||||
stream.setStreamBuffer(buffer); // default = 0 (buffer)
|
||||
stream.setStreamStart(id); // default = 0 (monitor_id)
|
||||
stream.setStreamType(streamtype);
|
||||
if (streamtype == MonitorStream::STREAM_MPEG) {
|
||||
#if HAVE_LIBAVCODEC
|
||||
if (debug) printf("HAVE_LIBAVCODEC is set\n");
|
||||
stream.setStreamFormat(format); // default = "" (format)
|
||||
stream.setStreamBitrate(bitrate); // default = 100000 (bitrate)
|
||||
#else
|
||||
fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n");
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
return EXIT_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (debug != 1) {
|
||||
if (debug) printf("Running stream...");
|
||||
|
||||
// Output headers
|
||||
fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION);
|
||||
time_t now = time(0);
|
||||
char date_string[64];
|
||||
strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
|
||||
fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n");
|
||||
fprintf(stdout, "Last-Modified: %s\r\n", date_string);
|
||||
fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
|
||||
fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n");
|
||||
fprintf(stdout, "Pragma: no-cache\r\n");
|
||||
|
||||
// Run stream
|
||||
stream.runStream();
|
||||
}
|
||||
if (debug) printf("Done.\n");
|
||||
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
|
@ -8,88 +8,272 @@ exit;
|
|||
|
||||
fi
|
||||
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
-b=*|--branch=*)
|
||||
BRANCH="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-d=*|--distro=*)
|
||||
DISTRO="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-i=*|--interactive=*)
|
||||
INTERACTIVE="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-r=*|--release=*)
|
||||
RELEASE="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
-s=*|--snapshot=*)
|
||||
SNAPSHOT="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-t=*|--type=*)
|
||||
TYPE="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-u=*|--urgency=*)
|
||||
URGENCY="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-f=*|--fork=*)
|
||||
GITHUB_FORK="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-v=*|--version=*)
|
||||
PACKAGE_VERSION="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
--default)
|
||||
DEFAULT=YES
|
||||
shift # past argument with no value
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
read -p "Unknown option $i, continue? (Y|n)"
|
||||
[[ $REPLY == [yY] ]] && { echo "continuing..."; } || exit 1;
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
DATE=`date -R`
|
||||
DISTRO=$1
|
||||
SNAPSHOT=$2
|
||||
if [ "$SNAPSHOT" == "stable" ]; then
|
||||
SNAPSHOT="";
|
||||
fi;
|
||||
|
||||
|
||||
TYPE=$3
|
||||
if [ "$TYPE" == "" ]; then
|
||||
TYPE="source";
|
||||
echo "Defaulting to source build"
|
||||
TYPE="source";
|
||||
fi;
|
||||
BRANCH=$4
|
||||
|
||||
if [ "$DISTRO" == "" ]; then
|
||||
DISTRO=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
|
||||
echo "Defaulting to $DISTRO for distribution";
|
||||
else
|
||||
echo "Building for $DISTRO";
|
||||
fi;
|
||||
|
||||
# Release is a special mode... it uploads to the release ppa and cannot have a snapshot
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
if [ "$SNAPSHOT" != "" ]; then
|
||||
echo "Releases cannot have a snapshot.... exiting."
|
||||
exit 0;
|
||||
fi
|
||||
if [ "$GITHUB_FORK" != "" ] && [ "$GITHUB_FORK" != "ZoneMinder" ]; then
|
||||
echo "Releases cannot have a fork ($GITHUB_FORK).... exiting."
|
||||
exit 0;
|
||||
fi
|
||||
BRANCH="release-$RELEASE"
|
||||
else
|
||||
if [ "$GITHUB_FORK" == "" ]; then
|
||||
echo "Defaulting to ZoneMinder upstream git"
|
||||
GITHUB_FORK="ZoneMinder"
|
||||
fi;
|
||||
if [ "$SNAPSHOT" == "stable" ]; then
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
BRANCH=$(git describe --tags $(git rev-list --tags --max-count=1));
|
||||
echo "Latest stable branch is $BRANCH";
|
||||
fi;
|
||||
else
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
echo "Defaulting to master branch";
|
||||
BRANCH="master";
|
||||
fi;
|
||||
if [ "$SNAPSHOT" == "NOW" ]; then
|
||||
SNAPSHOT=`date +%Y%m%d%H%M%S`;
|
||||
fi;
|
||||
fi;
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -d 'zoneminder_release' ]; then
|
||||
git clone https://github.com/ZoneMinder/ZoneMinder.git zoneminder_release
|
||||
# Instead of cloning from github each time, if we have a fork lying around, update it and pull from there instead.
|
||||
if [ ! -d "${GITHUB_FORK}_zoneminder_release" ]; then
|
||||
if [ -d "${GITHUB_FORK}_ZoneMinder.git" ]; then
|
||||
echo "Using local clone ${GITHUB_FORK}_ZoneMinder.git to pull from."
|
||||
cd "${GITHUB_FORK}_ZoneMinder.git"
|
||||
echo "git pull..."
|
||||
git pull
|
||||
echo "git checkout $BRANCH"
|
||||
git checkout $BRANCH
|
||||
echo "git pull..."
|
||||
git pull
|
||||
cd ../
|
||||
echo "git clone ${GITHUB_FORK}_ZoneMinder.git ${GITHUB_FORK}_zoneminder_release"
|
||||
git clone "${GITHUB_FORK}_ZoneMinder.git" "${GITHUB_FORK}_zoneminder_release"
|
||||
else
|
||||
echo "git clone https://github.com/$GITHUB_FORK/ZoneMinder.git ${GITHUB_FORK}_zoneminder_release"
|
||||
git clone "https://github.com/$GITHUB_FORK/ZoneMinder.git" "${GITHUB_FORK}_zoneminder_release"
|
||||
fi
|
||||
else
|
||||
echo "release dir already exists. Please remove it."
|
||||
exit 0;
|
||||
fi;
|
||||
if [ "$BRANCH" != "" ]; then
|
||||
cd zoneminder_release
|
||||
if [ "$BRANCH" == "stable" ]; then
|
||||
BRANCH=$(git describe --tags $(git rev-list --tags --max-count=1));
|
||||
echo "Latest stable branch is $BRANCH";
|
||||
|
||||
fi
|
||||
git checkout $BRANCH
|
||||
cd ../
|
||||
cd "${GITHUB_FORK}_zoneminder_release"
|
||||
if [ $RELEASE ]; then
|
||||
git checkout $RELEASE
|
||||
else
|
||||
git checkout $BRANCH
|
||||
fi;
|
||||
VERSION=`cat zoneminder_release/version`
|
||||
cd ../
|
||||
|
||||
VERSION=`cat ${GITHUB_FORK}_zoneminder_release/version`
|
||||
|
||||
if [ $VERSION == "" ]; then
|
||||
exit 1;
|
||||
fi;
|
||||
echo "Doing $TYPE release zoneminder_$VERSION-$DISTRO-$SNAPSHOT";
|
||||
mv zoneminder_release zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
|
||||
cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
|
||||
git submodule init
|
||||
git submodule update --init --recursive
|
||||
if [ $DISTRO == "trusty" ]; then
|
||||
ln -sf distros/ubuntu1204 debian
|
||||
else
|
||||
ln -sf distros/ubuntu1604 debian
|
||||
if [ "$SNAPSHOT" != "stable" ] && [ "$SNAPSHOT" != "" ]; then
|
||||
VERSION="$VERSION~$SNAPSHOT";
|
||||
fi;
|
||||
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
sudo mk-build-deps -ir ./debian/control
|
||||
DIRECTORY="zoneminder_$VERSION";
|
||||
echo "Doing $TYPE release $DIRECTORY";
|
||||
mv "${GITHUB_FORK}_zoneminder_release" "$DIRECTORY.orig";
|
||||
cd "$DIRECTORY.orig";
|
||||
|
||||
if [ -z `hostname -d` ] ; then
|
||||
AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`.local>"
|
||||
git submodule init
|
||||
git submodule update --init --recursive
|
||||
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]; then
|
||||
mv distros/ubuntu1204 debian
|
||||
else
|
||||
AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`>"
|
||||
if [ "$DISTRO" == "wheezy" ]; then
|
||||
mv distros/debian debian
|
||||
else
|
||||
mv distros/ubuntu1604 debian
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then
|
||||
AUTHOR="$DEBFULLNAME <$DEBEMAIL>"
|
||||
else
|
||||
if [ -z `hostname -d` ] ; then
|
||||
AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`.local>"
|
||||
else
|
||||
AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`>"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$URGENCY" = "" ]; then
|
||||
URGENCY="medium"
|
||||
fi;
|
||||
|
||||
if [ "$SNAPSHOT" == "stable" ]; then
|
||||
cat <<EOF > debian/changelog
|
||||
zoneminder ($VERSION-$DISTRO-$SNAPSHOT) $DISTRO; urgency=medium
|
||||
zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY
|
||||
|
||||
* Release $VERSION
|
||||
|
||||
-- $AUTHOR $DATE
|
||||
|
||||
EOF
|
||||
else
|
||||
cat <<EOF > debian/changelog
|
||||
zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY
|
||||
|
||||
*
|
||||
|
||||
-- $AUTHOR $DATE
|
||||
|
||||
EOF
|
||||
#rm -rf .git
|
||||
#rm .gitignore
|
||||
#cd ../
|
||||
#tar zcf zoneminder_$VERSION-$DISTRO.orig.tar.gz zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
|
||||
#cd zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig
|
||||
fi;
|
||||
|
||||
rm -rf .git
|
||||
rm .gitignore
|
||||
cd ../
|
||||
tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig
|
||||
cd $DIRECTORY.orig
|
||||
|
||||
if [ $TYPE == "binary" ]; then
|
||||
debuild
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
sudo mk-build-deps -ir ./debian/control
|
||||
echo "Status: $?"
|
||||
DEBUILD=debuild
|
||||
else
|
||||
if [ $TYPE == "local" ]; then
|
||||
debuild -i -us -uc -b
|
||||
else
|
||||
debuild -S -sa
|
||||
fi;
|
||||
if [ $TYPE == "local" ]; then
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
sudo mk-build-deps -ir ./debian/control
|
||||
echo "Status: $?"
|
||||
DEBUILD="debuild -i -us -uc -b"
|
||||
else
|
||||
DEBUILD="debuild -S -sa"
|
||||
fi;
|
||||
fi;
|
||||
if [ "$DEBSIGN_KEYID" != "" ]; then
|
||||
DEBUILD="$DEBUILD -k$DEBSIGN_KEYID"
|
||||
fi
|
||||
$DEBUILD
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error status code is: $?"
|
||||
echo "Build failed.";
|
||||
exit $?;
|
||||
fi;
|
||||
|
||||
cd ../
|
||||
if [ "$INTERACTIVE" != "no" ]; then
|
||||
read -p "Do you want to keep the checked out version of Zoneminder (incase you want to modify it later) [y/N]"
|
||||
[[ $REPLY == [yY] ]] && { mv $DIRECTORY zoneminder_release; echo "The checked out copy is preserved in zoneminder_release"; } || { rm -fr $DIRECTORY; echo "The checked out copy has been deleted"; }
|
||||
echo "Done!"
|
||||
else
|
||||
rm -fr $DIRECTORY; echo "The checked out copy has been deleted";
|
||||
fi
|
||||
|
||||
read -p "Do you want to keep the checked out version of Zoneminder (incase you want to modify it later) [y/N]"
|
||||
[[ $REPLY == [yY] ]] && { mv zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig zoneminder_release; echo "The checked out copy is preserved in zoneminder_release"; } || { rm -fr zoneminder_$VERSION-$DISTRO-$SNAPSHOT.orig; echo "The checked out copy has been deleted"; }
|
||||
echo "Done!"
|
||||
|
||||
if [ $TYPE == "binary" ]; then
|
||||
if [ "$INTERACTIVE" != "no" ]; then
|
||||
echo "Not doing dput since it's a binary release. Do you want to install it? (Y/N)"
|
||||
read install
|
||||
if [ "$install" == "Y" ]; then
|
||||
sudo dpkg -i $DIRECTORY*.deb
|
||||
fi;
|
||||
if [ "$DISTRO" == "jessie" ]; then
|
||||
echo "Do you want to upload this binary to zmrepo? (y/N)"
|
||||
read install
|
||||
if [ "$install" == "Y" ]; then
|
||||
scp "zoneminder_*-${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/"
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
else
|
||||
SC="zoneminder_${VERSION}-${DISTRO}${PACKAGE_VERSION}_source.changes";
|
||||
PPA="";
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
PPA="ppa:iconnor/zoneminder";
|
||||
else
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
PPA="ppa:iconnor/zoneminder-master";
|
||||
else
|
||||
PPA="ppa:iconnor/zoneminder-$BRANCH";
|
||||
fi;
|
||||
fi;
|
||||
|
||||
dput="Y";
|
||||
if [ "$INTERACTIVE" != "no" ]; then
|
||||
echo "Ready to dput $SC to $PPA ? Y/N...";
|
||||
read dput
|
||||
fi
|
||||
if [ "$dput" == "Y" -o "$dput" == "y" ]; then
|
||||
dput $PPA $SC
|
||||
fi;
|
||||
fi;
|
||||
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
<VirtualHost *:80>
|
||||
DocumentRoot /usr/local/share/zoneminder/www
|
||||
DirectoryIndex index.php
|
||||
|
||||
ScriptAlias /cgi-bin/ /usr/local/libexec/zoneminder/cgi-bin/
|
||||
<Directory />
|
||||
Require all granted
|
||||
</Directory>
|
||||
<Directory "/usr/local/libexec/zoneminder/cgi-bin">
|
||||
AllowOverride None
|
||||
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
|
@ -29,6 +29,9 @@ mysql -u root < db/zm_create.sql
|
|||
# Add the ZoneMinder DB user
|
||||
mysql -u root -e "grant insert,select,update,delete,lock tables,alter on zm.* to 'zmuser'@'localhost' identified by 'zmpass';"
|
||||
|
||||
# Make ZM_LOGDIR
|
||||
mkdir /var/log/zm
|
||||
|
||||
# Activate CGI
|
||||
a2enmod cgi
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
--- a/packpack/pack/rpm.mk 2017-01-14 14:01:50.364217882 -0600
|
||||
+++ b/packpack/pack/rpm.mk 2017-01-14 14:01:19.594985311 -0600
|
||||
@@ -23,11 +23,13 @@
|
||||
-e 's/Release:\([ ]*\).*/Release: $(RELEASE)%{dist}/' \
|
||||
-e 's/Source0:\([ ]*\).*/Source0: $(TARBALL)/' \
|
||||
-e 's/%setup .*/%setup -q -n $(PRODUCT)-$(VERSION)/' \
|
||||
+ -e 's/%autosetup -n .*/%autosetup -n $(PRODUCT)-$(VERSION)/' \
|
||||
-i $@.tmp
|
||||
grep -F "Version: $(VERSION)" $@.tmp && \
|
||||
grep -F "Release: $(RELEASE)" $@.tmp && \
|
||||
grep -F "Source0: $(TARBALL)" $@.tmp && \
|
||||
- grep -F "%setup -q -n $(PRODUCT)-$(VERSION)" $@.tmp || \
|
||||
+ (grep -F "%setup -q -n $(PRODUCT)-$(VERSION)" $@.tmp || \
|
||||
+ grep -F "%autosetup" $@.tmp) || \
|
||||
(echo "Failed to patch RPM spec" && exit 1)
|
||||
@ mv -f $@.tmp $@
|
||||
@echo
|
|
@ -1,11 +0,0 @@
|
|||
--- a/packpack/pack/deb.mk 2017-01-15 16:41:32.938418279 -0600
|
||||
+++ b/packpack/pack/deb.mk 2017-02-16 15:44:43.267900717 -0600
|
||||
@@ -14,7 +14,7 @@
|
||||
DPKG_BUILD:=$(PRODUCT)_$(DEB_VERSION)-$(RELEASE)_$(DPKG_ARCH).build
|
||||
DPKG_DSC:=$(PRODUCT)_$(DEB_VERSION)-$(RELEASE).dsc
|
||||
DPKG_ORIG_TARBALL:=$(PRODUCT)_$(DEB_VERSION).orig.tar.$(TARBALL_COMPRESSOR)
|
||||
-DPKG_DEBIAN_TARBALL:=$(PRODUCT)_$(DEB_VERSION)-$(RELEASE).debian.tar.$(TARBALL_COMPRESSOR)
|
||||
+DPKG_DEBIAN_TARBALL:=$(PRODUCT)_$(DEB_VERSION)-$(RELEASE).tar.$(TARBALL_COMPRESSOR)
|
||||
|
||||
# gh-7: Ubuntu/Debian should export DEBIAN_FRONTEND=noninteractive
|
||||
export DEBIAN_FRONTEND=noninteractive
|
|
@ -0,0 +1 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC6tO+Kuj85uS4Z7ZmyAjmeAJbKbuv+pddPncgY/0/cSKfLbDo5f+TFM9K5AUlegcALbccUA9jt5p615KTgN0ZyGiCDcNs6/1DcDh4Nb/KgHsApVLZHZYpd7bnP5yadIqXroXw9VI2PWhUTasb97t4xvEepcsnepdfeGFegX7jyeRqucdEsZZa8kiSgU9hIdJyTeQXQQY5odYqABvR6ea7ff8iD2pdzjXIFHiA9527fXoPuUJo5rwIWOwtwstFG5xCT6ZPBgi2nECSZoRdG7zqkm2gqhAaNiR8PR5Qr0CbeYa4LWYl0v33CwLxFuyiP9AOqdFB+vF9c67do4E0yJ+heUNuOUbp3ePT1jJDOhQapAjkmyEb4A+RMNc9SEXmJh10nUiJ2zGGb9a3FyreopHfjdzKiZdk+uSV18kdG7KSiRvHep+sEK7xMepAQ3OiAprwOH2D2EoXC08TLehaeXmsOAuMGz0JvJKBXMGAow2SEa38v42PJwKsjn0qo72IjN1h/9ICgM/o+4oNHLHsu5GK1dornAt9OE6g1be1jXdij07QaSV831NiweOHqRTPpl2eglWfoyMjPuzebiyoAqb4tNBnMOk5BTaxx7ZZGXmdHyH9kKFAVj+WBkRHNlDhaMB2/QzhHUs0PRVRUexBKgog+1xnPE5gTie6NNnDB04NcDQ== zmrepo@zmrepo.zoneminder.com
|
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
# No longer needed. This was incorporated into startpackpack.sh
|
||||
|
||||
# Required, so that Travis marks the build as failed if any of the steps below fail
|
||||
set -ev
|
||||
|
||||
# Install and test the zoneminder package (only) for Ubuntu Trusty
|
||||
if [ ${OS} == "ubuntu" ] && [ ${DIST} == "trusty" ]; then
|
||||
sudo gdebi --non-interactive build/zoneminder_*amd64.deb
|
||||
sudo chmod 644 /etc/zm/zm.conf
|
||||
mysql -uzmuser -pzmpass zm < db/test.monitor.sql
|
||||
sudo /usr/bin/zmpkg.pl start
|
||||
sudo /usr/bin/zmfilter.pl -f purgewhenfull
|
||||
fi
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Check to see if this script has access to all the commands it needs
|
||||
for CMD in sshfs rsync find fusermount mkdir; do
|
||||
type $CMD 2>&1 > /dev/null
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo
|
||||
echo "ERROR: The script cannot find the required command \"${CMD}\"."
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# We only want to deploy packages during cron events
|
||||
# See https://docs.travis-ci.com/user/cron-jobs/
|
||||
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ]; then
|
||||
|
||||
if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
|
||||
targetfolder="debian/master/mini-dinstall/incoming"
|
||||
else
|
||||
targetfolder="travis"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Target subfolder set to $targetfolder"
|
||||
echo
|
||||
|
||||
mkdir -p ./zmrepo
|
||||
ssh_mntchk="$(sshfs zmrepo@zmrepo.zoneminder.com:./ ./zmrepo -o workaround=rename,reconnect)"
|
||||
|
||||
if [ -z "$ssh_mntchk" ]; then
|
||||
echo
|
||||
echo "Remote filesystem mounted successfully."
|
||||
echo "Begin transfering files..."
|
||||
echo
|
||||
|
||||
# Don't keep packages older than 5 days
|
||||
find ./zmrepo/$targetfolder/ -maxdepth 1 -type f -mtime +5 -delete
|
||||
rsync -vzh --ignore-errors build/* zmrepo/$targetfolder/
|
||||
fusermount -zu zmrepo
|
||||
else
|
||||
echo
|
||||
echo "ERROR: Attempt to mount zmrepo.zoneminder.com failed!"
|
||||
echo "sshfs gave the following error message:"
|
||||
echo \"$ssh_mntchk\"
|
||||
echo
|
||||
exit 99
|
||||
fi
|
||||
fi
|
|
@ -2,97 +2,71 @@
|
|||
# packpack setup file for the ZoneMinder project
|
||||
# Written by Andrew Bauer
|
||||
|
||||
# Check to see if this script has access to all the commands it needs
|
||||
for CMD in set echo curl repoquery git ln mkdir patch rmdir; do
|
||||
type $CMD 2>&1 > /dev/null
|
||||
###############
|
||||
# SUBROUTINES #
|
||||
###############
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo
|
||||
echo "ERROR: The script cannot find the required command \"${CMD}\"."
|
||||
echo
|
||||
exit $?
|
||||
fi
|
||||
done
|
||||
# General sanity checks
|
||||
checksanity () {
|
||||
# Check to see if this script has access to all the commands it needs
|
||||
for CMD in set echo curl repoquery git ln mkdir rmdir; do
|
||||
type $CMD 2>&1 > /dev/null
|
||||
|
||||
# Verify OS & DIST environment variables have been set before calling this script
|
||||
if [ -z "${OS}" ] || [ -z "${DIST}" ]; then
|
||||
echo "ERROR: both OS and DIST environment variables must be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ $? -ne 0 ]; then
|
||||
echo
|
||||
echo "ERROR: The script cannot find the required command \"${CMD}\"."
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Verify OS & DIST environment variables have been set before calling this script
|
||||
if [ -z "${OS}" ] || [ -z "${DIST}" ]; then
|
||||
echo "ERROR: both OS and DIST environment variables must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${ARCH}" ]; then
|
||||
ARCH="x86_64"
|
||||
fi
|
||||
|
||||
if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" ]]; then
|
||||
echo
|
||||
echo "ERROR: Unsupported architecture specified \"${ARCH}\"."
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# Steps common to all builds
|
||||
mkdir -p build
|
||||
if [ -e "packpack/Makefile" ]; then
|
||||
echo "Checking packpack github repo for changes..."
|
||||
git -C packpack pull origin master
|
||||
else
|
||||
echo "Cloning pakcpack github repo..."
|
||||
git clone https://github.com/packpack/packpack.git packpack
|
||||
fi
|
||||
|
||||
# The rpm specfile requires we download the tarball and manually move it into place
|
||||
# Might as well do this for Debian as well, rather than git submodule init
|
||||
CRUDVER="3.0.10"
|
||||
if [ -e "build/crud-${CRUDVER}.tar.gz" ]; then
|
||||
echo "Found existing Crud ${CRUDVER} tarball..."
|
||||
else
|
||||
echo "Retrieving Crud ${CRUDVER} submodule..."
|
||||
curl -L https://github.com/FriendsOfCake/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Crud tarball retreival failed..."
|
||||
exit $?
|
||||
fi
|
||||
fi
|
||||
|
||||
# Steps common to Redhat distros
|
||||
if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
|
||||
echo "Begin Redhat build..."
|
||||
|
||||
# %autosetup support has been merged upstream. No need to patch
|
||||
#patch -p1 < utils/packpack/autosetup.patch
|
||||
ln -sf distros/redhat rpm
|
||||
|
||||
# The rpm specfile requires the Crud submodule folder to be empty
|
||||
if [ -e "web/api/app/Plugin/Crud/LICENSE.txt" ]; then
|
||||
rm -rf web/api/app/Plugin/Crud
|
||||
mkdir web/api/app/Plugin/Crud
|
||||
fi
|
||||
|
||||
if [ "${OS}" == "el" ]; then
|
||||
zmrepodistro=${OS}
|
||||
commonprep () {
|
||||
mkdir -p build
|
||||
if [ -e "packpack/Makefile" ]; then
|
||||
echo "Checking packpack github repo for changes..."
|
||||
git -C packpack pull origin master
|
||||
else
|
||||
zmrepodistro="f"
|
||||
echo "Cloning pakcpack github repo..."
|
||||
git clone https://github.com/packpack/packpack.git packpack
|
||||
fi
|
||||
|
||||
# Let repoquery determine the full url and filename of the zmrepo rpm we are interested in
|
||||
result=`repoquery --repofrompath=zmpackpack,https://zmrepo.zoneminder.com/${zmrepodistro}/${DIST}/x86_64/ --repoid=zmpackpack --qf="%{location}" zmrepo 2> /dev/null`
|
||||
|
||||
if [ -n "$result" ] && [ $? -eq 0 ]; then
|
||||
echo "Retrieving ZMREPO rpm..."
|
||||
curl $result > build/zmrepo.noarch.rpm
|
||||
# The rpm specfile requires we download the tarball and manually move it into place
|
||||
# Might as well do this for Debian as well, rather than git submodule init
|
||||
CRUDVER="3.0.10"
|
||||
if [ -e "build/crud-${CRUDVER}.tar.gz" ]; then
|
||||
echo "Found existing Crud ${CRUDVER} tarball..."
|
||||
else
|
||||
echo "ERROR: Failed to retrieve zmrepo rpm..."
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $?
|
||||
else
|
||||
echo 1
|
||||
echo "Retrieving Crud ${CRUDVER} submodule..."
|
||||
curl -L https://github.com/FriendsOfCake/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Crud tarball retreival failed..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Starting packpack..."
|
||||
packpack/packpack -f utils/packpack/redhat_package.mk redhat_package
|
||||
|
||||
# Steps common the Debian based distros
|
||||
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
|
||||
echo "Begin Debian build..."
|
||||
|
||||
# patch packpack to remove "debian" from the source tarball filename
|
||||
patch --dry-run --silent -f -p1 < utils/packpack/deb.mk.patch 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
patch -p1 < utils/packpack/deb.mk.patch
|
||||
fi
|
||||
|
||||
# Uncompress the Crud tarball and move it into place
|
||||
# Uncompress the Crud tarball and move it into place
|
||||
movecrud () {
|
||||
if [ -e "web/api/app/Plugin/Crud/LICENSE.txt" ]; then
|
||||
echo "Crud plugin already installed..."
|
||||
else
|
||||
|
@ -101,17 +75,151 @@ elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
|
|||
rmdir web/api/app/Plugin/Crud
|
||||
mv -f crud-${CRUDVER} web/api/app/Plugin/Crud
|
||||
fi
|
||||
}
|
||||
|
||||
if [ ${DIST} == "trusty" ] || [ ${DIST} == "precise" ]; then
|
||||
ln -sf distros/ubuntu1204 debian
|
||||
elif [ ${DIST} == "wheezy" ]; then
|
||||
ln -sf distros/debian debian
|
||||
else
|
||||
ln -sf distros/ubuntu1604 debian
|
||||
# previsouly part of installzm.sh
|
||||
# install the trusty deb and test zoneminder
|
||||
installtrusty () {
|
||||
|
||||
# Check we've got gdebi installed
|
||||
type gdebi 2>&1 > /dev/null
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo
|
||||
echo "ERROR: The script cannot find the required command \"gdebi\"."
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install and test the zoneminder package (only) for Ubuntu Trusty
|
||||
pkgname="build/zoneminder_${VERSION}-${RELEASE}_amd64.deb"
|
||||
|
||||
if [ -e $pkgname ]; then
|
||||
sudo gdebi --non-interactive $pkgname
|
||||
mysql -uzmuser -pzmpass zm < db/test.monitor.sql
|
||||
sudo /usr/bin/zmpkg.pl start
|
||||
sudo /usr/bin/zmfilter.pl -f purgewhenfull
|
||||
else
|
||||
echo
|
||||
echo "ERROR: The script cannot find the package $pkgname"
|
||||
echo "Check the Travis log for a build failure."
|
||||
echo
|
||||
exit 99
|
||||
fi
|
||||
}
|
||||
|
||||
# This sets the naming convention for the deb packages
|
||||
setdebpkgver () {
|
||||
|
||||
# Set VERSION to x.xx.x+x e.g. 1.30.2+15
|
||||
# the last x is number of commits since release
|
||||
# Creates zoneminder packages in the format: zoneminder-{version}-{release}
|
||||
zmver=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\1/p')
|
||||
commitnum=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p')
|
||||
export VERSION="$zmver+$commitnum"
|
||||
export RELEASE="${DIST}"
|
||||
|
||||
echo
|
||||
echo "Packpack VERSION has been set to: ${VERSION}"
|
||||
echo "Packpack RELEASE has been set to: ${RELEASE}"
|
||||
echo
|
||||
|
||||
}
|
||||
|
||||
################
|
||||
# MAIN PROGRAM #
|
||||
################
|
||||
|
||||
checksanity
|
||||
|
||||
# We don't want to build packages for all supported distros after every commit
|
||||
# Only build all packages when executed via cron
|
||||
# See https://docs.travis-ci.com/user/cron-jobs/
|
||||
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
|
||||
commonprep
|
||||
|
||||
# Steps common to Redhat distros
|
||||
if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
|
||||
echo "Begin Redhat build..."
|
||||
|
||||
# Set VERSION to x.xx.x e.g. 1.30.2
|
||||
# Set RELEASE to x where x is number of commits since release
|
||||
# Creates zoneminder packages in the format: zoneminder-{version}-{release}
|
||||
export VERSION=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\1/p')
|
||||
export RELEASE=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p')
|
||||
|
||||
echo
|
||||
echo "Packpack VERSION has been set to: ${VERSION}"
|
||||
echo "Packpack RELEASE has been set to: ${RELEASE}"
|
||||
echo
|
||||
|
||||
ln -sfT distros/redhat rpm
|
||||
|
||||
# The rpm specfile requires the Crud submodule folder to be empty
|
||||
rm -rf web/api/app/Plugin/Crud
|
||||
mkdir web/api/app/Plugin/Crud
|
||||
|
||||
if [ "${OS}" == "el" ]; then
|
||||
zmrepodistro=${OS}
|
||||
else
|
||||
zmrepodistro="f"
|
||||
fi
|
||||
|
||||
# Let repoquery determine the full url and filename of the zmrepo rpm we are interested in
|
||||
result=`repoquery --repofrompath=zmpackpack,https://zmrepo.zoneminder.com/${zmrepodistro}/"${DIST}"/x86_64/ --repoid=zmpackpack --qf="%{location}" zmrepo 2> /dev/null`
|
||||
|
||||
if [ -n "$result" ] && [ $? -eq 0 ]; then
|
||||
echo "Retrieving ZMREPO rpm..."
|
||||
curl $result > build/zmrepo.noarch.rpm
|
||||
else
|
||||
echo "ERROR: Failed to retrieve zmrepo rpm..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting packpack..."
|
||||
packpack/packpack -f utils/packpack/redhat_package.mk redhat_package
|
||||
|
||||
# Steps common to Debian based distros
|
||||
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
|
||||
echo "Begin ${OS} ${DIST} build..."
|
||||
|
||||
setdebpkgver
|
||||
movecrud
|
||||
|
||||
if [ "${DIST}" == "trusty" ] || [ "${DIST}" == "precise" ]; then
|
||||
ln -sfT distros/ubuntu1204 debian
|
||||
elif [ "${DIST}" == "wheezy" ]; then
|
||||
ln -sfT distros/debian debian
|
||||
else
|
||||
ln -sfT distros/ubuntu1604 debian
|
||||
fi
|
||||
|
||||
echo "Starting packpack..."
|
||||
packpack/packpack
|
||||
|
||||
if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86_64" ] && [ "${TRAVIS}" == "true" ]; then
|
||||
installtrusty
|
||||
fi
|
||||
fi
|
||||
|
||||
# We were not triggered via cron so just build and test trusty
|
||||
elif [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86_64" ]; then
|
||||
echo "Begin Ubuntu Trusty build..."
|
||||
|
||||
commonprep
|
||||
setdebpkgver
|
||||
movecrud
|
||||
|
||||
ln -sfT distros/ubuntu1204 debian
|
||||
|
||||
echo "Starting packpack..."
|
||||
packpack/packpack
|
||||
|
||||
# If we are running inside Travis then attempt to install the deb we just built
|
||||
if [ "${TRAVIS}" == "true" ]; then
|
||||
installtrusty
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ if(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
|
|||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/core.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/database.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/bootstrap.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/lib/Cake/bootstrap.php" DESTINATION "${ZM_WEBDIR}/api/lib/Cake")
|
||||
endif(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
|
||||
|
||||
# Install the mootools symlinks (if its not in the source directory)
|
||||
|
|
|
@ -52,7 +52,7 @@ while ( !file_exists($remSockFile) && $max_socket_tries-- ) { //sometimes we are
|
|||
}
|
||||
|
||||
if ( !file_exists($remSockFile) ) {
|
||||
ajaxError("Socket $remSocketFile does not exist. This file is created by zms, and since it does not exist, either zms did not run, or zms exited early. Please check your zms logs and ensure that CGI is enabled in apache and check that the PATH_ZMS is set correctly. Make sure that ZM is actually recording. If you are trying to view a live stream and the capture process (zmc) is not running then zms will exit. Please go to http://zoneminder.readthedocs.io/en/latest/faq.html#why-can-t-i-see-streamed-images-when-i-can-see-stills-in-the-zone-window-etc for more information.");
|
||||
ajaxError("Socket $remSockFile does not exist. This file is created by zms, and since it does not exist, either zms did not run, or zms exited early. Please check your zms logs and ensure that CGI is enabled in apache and check that the PATH_ZMS is set correctly. Make sure that ZM is actually recording. If you are trying to view a live stream and the capture process (zmc) is not running then zms will exit. Please go to http://zoneminder.readthedocs.io/en/latest/faq.html#why-can-t-i-see-streamed-images-when-i-can-see-stills-in-the-zone-window-etc for more information.");
|
||||
} else {
|
||||
if ( !@socket_sendto( $socket, $msg, strlen($msg), 0, $remSockFile ) ) {
|
||||
ajaxError( "socket_sendto( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
||||
|
|
|
@ -11,5 +11,8 @@ configure_file(app/Config/database.php.default "${CMAKE_CURRENT_BINARY_DIR}/app/
|
|||
# Configure core.php
|
||||
configure_file(app/Config/core.php.default "${CMAKE_CURRENT_BINARY_DIR}/app/Config/core.php" @ONLY)
|
||||
|
||||
# Configure bootstrap.php
|
||||
# Configure app/Config/bootstrap.php
|
||||
configure_file(app/Config/bootstrap.php.in "${CMAKE_CURRENT_BINARY_DIR}/app/Config/bootstrap.php" @ONLY)
|
||||
|
||||
# Configure lib/Cake/bootstrap.php
|
||||
configure_file(lib/Cake/bootstrap.php.in "${CMAKE_CURRENT_BINARY_DIR}/lib/Cake/bootstrap.php" @ONLY)
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
// Setup a 'default' cache configuration for use in the application.
|
||||
Cache::config('default', array('engine' => 'File'));
|
||||
Cache::config('default', array('engine' => 'Apc'));
|
||||
|
||||
/**
|
||||
* The settings below can be used to set additional paths to models, views and controllers.
|
||||
|
@ -100,12 +100,16 @@ App::uses('CakeLog', 'Log');
|
|||
CakeLog::config('debug', array(
|
||||
'engine' => 'File',
|
||||
'types' => array('notice', 'info', 'debug'),
|
||||
'file' => 'debug',
|
||||
'file' => 'cake_debug',
|
||||
));
|
||||
CakeLog::config('error', array(
|
||||
'engine' => 'File',
|
||||
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
|
||||
'file' => 'error',
|
||||
'file' => 'cake_error',
|
||||
));
|
||||
CakeLog::config('custom_path', array(
|
||||
'engine' => 'File',
|
||||
'path' => '@ZM_LOGDIR@'
|
||||
));
|
||||
|
||||
Configure::write('ZM_CONFIG', '@ZM_CONFIG@');
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
* In production mode, flash messages redirect after a time interval.
|
||||
* In development mode, you need to click the flash message to continue.
|
||||
*/
|
||||
Configure::write('debug', 2);
|
||||
Configure::write('debug', 0);
|
||||
|
||||
/**
|
||||
* Configure the Error handler used to handle errors for your application. By default
|
||||
|
@ -352,7 +352,7 @@
|
|||
* Please check the comments in bootstrap.php for more info on the cache engines available
|
||||
* and their settings.
|
||||
*/
|
||||
$engine = 'File';
|
||||
$engine = 'Apc';
|
||||
|
||||
// In development mode, caches should expire quickly.
|
||||
$duration = '+999 days';
|
||||
|
|
|
@ -88,7 +88,7 @@ class DATABASE_CONFIG {
|
|||
public function __construct() {
|
||||
if (strpos(ZM_DB_HOST, ':')):
|
||||
$array = explode(':', ZM_DB_HOST, 2);
|
||||
if (is_numeric($array[1])):
|
||||
if (ctype_digit($array[1])):
|
||||
$this->default['host'] = $array[0];
|
||||
$this->default['port'] = $array[1];
|
||||
else:
|
||||
|
|
|
@ -91,7 +91,7 @@ class AppController extends Controller {
|
|||
if( ! $this->Session->Read('user.Username') ) {
|
||||
throw new UnauthorizedException(__('Not Authenticated'));
|
||||
return;
|
||||
} else if ( ! $this->Session->Read('user.Username') ) {
|
||||
} else if ( ! $this->Session->Read('user.Enabled') ) {
|
||||
throw new UnauthorizedException(__('User is not enabled'));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml version="1.0"?>
|
||||
<tags>
|
||||
<tag id="1">
|
||||
<name>defect</name>
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
// Force Cake's temp folder = ZoneMinder's temp folder
|
||||
define('TMP', '@ZM_TMPDIR@');
|
||||
|
||||
define('TIME_START', microtime(true));
|
||||
|
||||
if (!defined('E_DEPRECATED')) {
|
Binary file not shown.
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 384 B |
Binary file not shown.
Before Width: | Height: | Size: 61 B |
Binary file not shown.
After Width: | Height: | Size: 137 B |
|
@ -196,7 +196,7 @@ class Event {
|
|||
} // end function createListThumbnail
|
||||
|
||||
function getImageSrc( $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) {
|
||||
$Storage = new Storage( $this->{'StorageId'} );
|
||||
$Storage = new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
|
||||
$Event = $this;
|
||||
$eventPath = $Event->Path();
|
||||
|
||||
|
|
|
@ -1,51 +1,81 @@
|
|||
<?php
|
||||
require_once( 'database.php' );
|
||||
class Storage {
|
||||
public function __construct( $IdOrRow = NULL ) {
|
||||
$row = NULL;
|
||||
if ( $IdOrRow ) {
|
||||
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
||||
$row = dbFetchOne( 'SELECT * FROM Storage WHERE Id=?', NULL, array( $IdOrRow ) );
|
||||
if ( ! $row ) {
|
||||
Error("Unable to load Storage record for Id=" . $IdOrRow );
|
||||
}
|
||||
} elseif ( is_array( $IdOrRow ) ) {
|
||||
$row = $IdOrRow;
|
||||
}
|
||||
}
|
||||
if ( $row ) {
|
||||
foreach ($row as $k => $v) {
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
} else {
|
||||
$this->{'Name'} = '';
|
||||
$this->{'Path'} = '';
|
||||
}
|
||||
public function __construct( $IdOrRow = NULL ) {
|
||||
$row = NULL;
|
||||
if ( $IdOrRow ) {
|
||||
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
||||
$row = dbFetchOne( 'SELECT * FROM Storage WHERE Id=?', NULL, array( $IdOrRow ) );
|
||||
if ( ! $row ) {
|
||||
Error("Unable to load Storage record for Id=" . $IdOrRow );
|
||||
}
|
||||
} elseif ( is_array( $IdOrRow ) ) {
|
||||
$row = $IdOrRow;
|
||||
}
|
||||
}
|
||||
if ( $row ) {
|
||||
foreach ($row as $k => $v) {
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
} else {
|
||||
$this->{'Name'} = '';
|
||||
$this->{'Path'} = '';
|
||||
}
|
||||
}
|
||||
|
||||
public function Path() {
|
||||
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
|
||||
return $this->{'Path'};
|
||||
} else if ( ! isset($this->{'Id'}) ) {
|
||||
$path = ZM_DIR_EVENTS;
|
||||
if ( $path[0] != '/' ) {
|
||||
$this->{'Path'} = ZM_PATH_WEB.'/'.ZM_DIR_EVENTS;
|
||||
} else {
|
||||
$this->{'Path'} = ZM_DIR_EVENTS;
|
||||
}
|
||||
return $this->{'Path'};
|
||||
|
||||
public function Path() {
|
||||
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
|
||||
return $this->{'Path'};
|
||||
} else if ( ! isset($this->{'Id'}) ) {
|
||||
return ZM_DIR_EVENTS;
|
||||
}
|
||||
return $this->{'Name'};
|
||||
}
|
||||
public function __call( $fn, array $args= NULL){
|
||||
if(isset($this->{$fn})){
|
||||
return $this->{$fn};
|
||||
#array_unshift($args, $this);
|
||||
#call_user_func_array( $this->{$fn}, $args);
|
||||
}
|
||||
}
|
||||
public static function find_all() {
|
||||
$storage_areas = array();
|
||||
$result = dbQuery( 'SELECT * FROM Storage ORDER BY Name');
|
||||
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' );
|
||||
foreach ( $results as $row => $obj ) {
|
||||
$storage_areas[] = $obj;
|
||||
}
|
||||
return $storage_areas;
|
||||
return $this->{'Name'};
|
||||
}
|
||||
public function Name() {
|
||||
if ( isset( $this->{'Name'} ) and ( $this->{'Name'} != '' ) ) {
|
||||
return $this->{'Name'};
|
||||
} else if ( ! isset($this->{'Id'}) ) {
|
||||
return 'Default';
|
||||
}
|
||||
return $this->{'Name'};
|
||||
}
|
||||
|
||||
public function __call( $fn, array $args= NULL){
|
||||
if(isset($this->{$fn})){
|
||||
return $this->{$fn};
|
||||
#array_unshift($args, $this);
|
||||
#call_user_func_array( $this->{$fn}, $args);
|
||||
}
|
||||
}
|
||||
public static function find_all() {
|
||||
$storage_areas = array();
|
||||
$result = dbQuery( 'SELECT * FROM Storage ORDER BY Name');
|
||||
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' );
|
||||
foreach ( $results as $row => $obj ) {
|
||||
$storage_areas[] = $obj;
|
||||
}
|
||||
return $storage_areas;
|
||||
}
|
||||
public function disk_usage_percent() {
|
||||
$path = $this->Path();
|
||||
$total = disk_total_space( $path );
|
||||
if ( ! $total ) {
|
||||
Error("disk_total_space returned false for " . $path );
|
||||
return 0;
|
||||
}
|
||||
$free = disk_free_space( $path );
|
||||
if ( ! $free ) {
|
||||
Error("disk_free_space returned false for " . $path );
|
||||
}
|
||||
$usage = round(($total - $free) / $total * 100);
|
||||
return $usage;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -617,7 +617,7 @@ if ( !empty($action) )
|
|||
{
|
||||
if ( !$x10Monitor )
|
||||
{
|
||||
dbQuery( "insert into TriggersX10 set MonitorId = ?".implode( ", ", $x10Changes ), array( $mid ) );
|
||||
dbQuery( "insert into TriggersX10 set MonitorId = ?,".implode( ", ", $x10Changes ), array( $mid ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Copyright (c) 2008-2013, Edward Z. Yang
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
[[ news ]]
|
||||
|
||||
1.0.4 released 2013-07-17
|
||||
|
||||
[SECURITY FIXES]
|
||||
|
||||
- When secret key was not explicitly set, it was not being used
|
||||
by the csrf_hash() function. Thanks sparticvs for reporting.
|
||||
|
||||
[FEATURES]
|
||||
|
||||
- The default 'CSRF check failed' page now offers a handy 'Try
|
||||
again' button, which resubmits the form.
|
||||
|
||||
[BUG FIXES]
|
||||
|
||||
- The fix for 1.0.3 inadvertantly turned off XMLHttpRequest
|
||||
overloading for all browsers; it has now been fixed to only
|
||||
apply to IE.
|
||||
|
||||
1.0.3 released 2012-01-31
|
||||
|
||||
[BUG FIXES]
|
||||
|
||||
- Internet Explorer 8 adds support for XMLHttpRequest.prototype,
|
||||
but this support is broken for method overloading. We
|
||||
explicitly disable JavaScript overloading for Internet Explorer.
|
||||
Thanks Kelly Lu for reporting. <lubird@gmail.com>
|
||||
|
||||
- A global declaration was omitted, resulting in a variable
|
||||
not being properly introduced in PHP 5.3. Thanks Whitney Beck for
|
||||
reporting. <whitney.a.beck@gmail.com>
|
||||
|
||||
1.0.2 released 2009-03-08
|
||||
|
||||
[SECURITY FIXES]
|
||||
|
||||
- Due to a typo, csrf-magic accidentally treated the secret key
|
||||
as always present. This means that there was a possible CSRF
|
||||
attack against users without any cookies. No attacks in the
|
||||
wild were known at the time of this release. Thanks Jakub
|
||||
Vrána for reporting.
|
||||
|
||||
1.0.1 released 2008-11-02
|
||||
|
||||
[NEW FEATURES]
|
||||
|
||||
- Support for composite tokens; this also fixes a bug with using
|
||||
IP-based tokens for users with cookies disabled.
|
||||
|
||||
- Native support cookie tokens; use csrf_conf('cookie', $name) to
|
||||
specify the name of a cookie that the CSRF token should be
|
||||
placed in. This is useful if you have a Squid cache, and need
|
||||
to configure it to ignore this token.
|
||||
|
||||
- Tips/tricks section in README.txt.
|
||||
|
||||
- There is now a two hour expiration time on all tokens. This
|
||||
can be modified using csrf_conf('expires', $seconds).
|
||||
|
||||
- ClickJacking protection using an iframe breaker. Disable with
|
||||
csrf_conf('frame-breaker', false).
|
||||
|
||||
[BUG FIXES]
|
||||
|
||||
- CsrfMagic.send() incorrectly submitted GET requests twice,
|
||||
once without the magic token and once with the token. Reported
|
||||
by Kelly Lu <lubird@gmail.com>.
|
|
@ -0,0 +1,160 @@
|
|||
|
||||
[[ csrf-magic ]]
|
||||
|
||||
Add the following line to the top of all web-accessible PHP pages. If you have
|
||||
a common file included by everything, put it there.
|
||||
|
||||
include_once '/path/to/csrf-magic.php';
|
||||
|
||||
Do it, test it, then forget about it. csrf-magic is protecting you if nothing
|
||||
bad happens. Read on if you run into problems.
|
||||
|
||||
|
||||
TABLE OF CONTENTS
|
||||
+ ------------------- +
|
||||
1. TIPS AND TRICKS
|
||||
2. AJAX
|
||||
3. CONFIGURE
|
||||
4. THANKS
|
||||
5. FOOTNOTES
|
||||
+ ------------------- +
|
||||
|
||||
|
||||
1. TIPS AND TRICKS
|
||||
|
||||
* If your JavaScript and AJAX is persistently getting errors, check the
|
||||
AJAX section below on how to fix.
|
||||
|
||||
* The CSS overlay protection makes it impossible to display your website
|
||||
in frame/iframe elements. You can disable it with
|
||||
csrf_conf('frame-breaker', false) in your csrf_startup() function.
|
||||
|
||||
* csrf-magic will start a session. To disable, use csrf_conf('auto-session',
|
||||
false) in your csrf_startup() function.
|
||||
|
||||
* The default error message is a little user unfriendly. Write your own
|
||||
function which outputs an error message and set csrf_conf('callback',
|
||||
'myCallbackFunction') in your csrf_startup() function.
|
||||
|
||||
* Make sure csrf_conf('secret', 'ABCDEFG') has something random in it. If
|
||||
the directory csrf-magic.php is in is writable, csrf-magic will generate
|
||||
a secret key for you in the csrf-secret.php file.
|
||||
|
||||
* Remember you can use auto_prepend to include csrf-magic.php on all your
|
||||
pages. You may want to create a stub file which you can include that
|
||||
includes csrf-magic.php as well as performs configuration.
|
||||
|
||||
* The default expiration time for tokens is two hours. If you expect your
|
||||
users to need longer to fill out forms, be sure to enable double
|
||||
submission when the token is invalid.
|
||||
|
||||
|
||||
2. AJAX
|
||||
|
||||
csrf-magic has the ability to dynamically rewrite AJAX requests which use
|
||||
XMLHttpRequest. However, due to the invasiveness of this procedure, it is
|
||||
not enabled by default. You can enable it by adding this code before you
|
||||
include csrf-magic.php.
|
||||
|
||||
function csrf_startup() {
|
||||
csrf_conf('rewrite-js', '/web/path/to/csrf-magic.js');
|
||||
}
|
||||
// include_once '/path/to/csrf-magic.php';
|
||||
|
||||
(Be sure to place csrf-magic.js somewhere web accessible).
|
||||
|
||||
The default method CSRF Magic uses to rewrite AJAX requests will
|
||||
only work for browsers with support for XmlHttpRequest.prototype (this excludes
|
||||
all versions of Internet Explorer). See this page for more information:
|
||||
http://stackoverflow.com/questions/664315/internet-explorer-8-prototypes-and-xmlhttprequest
|
||||
|
||||
However, csrf-magic.js will
|
||||
automatically detect and play nice with the following JavaScript frameworks:
|
||||
|
||||
* jQuery
|
||||
* Prototype
|
||||
* MooTools
|
||||
* Ext
|
||||
* Dojo
|
||||
|
||||
(Note 2013-07-16: It has been a long time since this manual support has
|
||||
been updated, and some JavaScript libraries have placed their copies of XHR
|
||||
in local variables in closures, which makes it difficult for us to monkey-patch
|
||||
it in automatically.)
|
||||
|
||||
To rewrite your own JavaScript library to use csrf-magic.js, you should modify
|
||||
your function that generates XMLHttpRequest to have this at the end:
|
||||
|
||||
return new CsrfMagic(xhrObject);
|
||||
|
||||
With whatever xhrObject may be. If you have literal instances of XMLHttpRequest
|
||||
in your code, find and replace ''new XMLHttpRequest'' with ''new CsrfMagic''
|
||||
(CsrfMagic will automatically instantiate an XMLHttpRequest object in a
|
||||
cross-platform manner as necessary).
|
||||
|
||||
If you don't want csrf-magic monkeying around with your XMLHttpRequest object,
|
||||
you can manually rewrite your AJAX code to include the variable. The important
|
||||
information is stored in the global variables csrfMagicName and csrfMagicToken.
|
||||
CsrfMagic.process may also be of interest, as it takes one parameter, a
|
||||
querystring, and prepends the CSRF token to the value.
|
||||
|
||||
|
||||
3. CONFIGURE
|
||||
|
||||
csrf-magic has some configuration options that you can set inside the
|
||||
csrf_startup() function. They are described in csrf-magic.php, and you can
|
||||
set them using the convenience function csrf_conf($name, $value).
|
||||
|
||||
For example, this is a recommended configuration:
|
||||
|
||||
/**
|
||||
* This is a function that gets called if a csrf check fails. csrf-magic will
|
||||
* then exit afterwards.
|
||||
*/
|
||||
function my_csrf_callback() {
|
||||
echo "You're doing bad things young man!";
|
||||
}
|
||||
|
||||
function csrf_startup() {
|
||||
|
||||
// While csrf-magic has a handy little heuristic for determining whether
|
||||
// or not the content in the buffer is HTML or not, you should really
|
||||
// give it a nudge and turn rewriting *off* when the content is
|
||||
// not HTML. Implementation details will vary.
|
||||
if (isset($_POST['ajax'])) csrf_conf('rewrite', false);
|
||||
|
||||
// This is a secret value that must be set in order to enable username
|
||||
// and IP based checks. Don't show this to anyone. A secret id will
|
||||
// automatically be generated for you if the directory csrf-magic.php
|
||||
// is placed in is writable.
|
||||
csrf_conf('secret', 'ABCDEFG123456');
|
||||
|
||||
// This enables JavaScript rewriting and will ensure your AJAX calls
|
||||
// don't stop working.
|
||||
csrf_conf('rewrite-js', '/csrf-magic.js');
|
||||
|
||||
// This makes csrf-magic call my_csrf_callback() before exiting when
|
||||
// there is a bad csrf token. This lets me customize the error page.
|
||||
csrf_conf('callback', 'my_csrf_callback');
|
||||
|
||||
// While this is enabled by default to boost backwards compatibility,
|
||||
// for security purposes it should ideally be off. Some users can be
|
||||
// NATted or have dialup addresses which rotate frequently. Cookies
|
||||
// are much more reliable.
|
||||
csrf_conf('allow-ip', false);
|
||||
|
||||
}
|
||||
|
||||
// Finally, include the library
|
||||
include_once '/path/to/csrf-magic.php';
|
||||
|
||||
Configuration gets stored in the $GLOBALS['csrf'] array.
|
||||
|
||||
|
||||
4. THANKS
|
||||
|
||||
My thanks to Chris Shiflett, for unintentionally inspiring the idea, as well
|
||||
as telling me the original variant of the Bob and Mallory story,
|
||||
and the Django CSRF Middleware authors, who thought up of this before me.
|
||||
Gareth Heyes suggested using the frame-breaker option to protect against
|
||||
CSS overlay attacks.
|
|
@ -0,0 +1,191 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* Rewrites XMLHttpRequest to automatically send CSRF token with it. In theory
|
||||
* plays nice with other JavaScript libraries, needs testing though.
|
||||
*/
|
||||
|
||||
// Here are the basic overloaded method definitions
|
||||
// The wrapper must be set BEFORE onreadystatechange is written to, since
|
||||
// a bug in ActiveXObject prevents us from properly testing for it.
|
||||
CsrfMagic = function(real) {
|
||||
// try to make it ourselves, if you didn't pass it
|
||||
if (!real) try { real = new XMLHttpRequest; } catch (e) {;}
|
||||
if (!real) try { real = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) {;}
|
||||
if (!real) try { real = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {;}
|
||||
if (!real) try { real = new ActiveXObject('Msxml2.XMLHTTP.4.0'); } catch (e) {;}
|
||||
this.csrf = real;
|
||||
// properties
|
||||
var csrfMagic = this;
|
||||
real.onreadystatechange = function() {
|
||||
csrfMagic._updateProps();
|
||||
return csrfMagic.onreadystatechange ? csrfMagic.onreadystatechange() : null;
|
||||
};
|
||||
csrfMagic._updateProps();
|
||||
}
|
||||
|
||||
CsrfMagic.prototype = {
|
||||
|
||||
open: function(method, url, async, username, password) {
|
||||
if (method == 'POST') this.csrf_isPost = true;
|
||||
// deal with Opera bug, thanks jQuery
|
||||
if (username) return this.csrf_open(method, url, async, username, password);
|
||||
else return this.csrf_open(method, url, async);
|
||||
},
|
||||
csrf_open: function(method, url, async, username, password) {
|
||||
if (username) return this.csrf.open(method, url, async, username, password);
|
||||
else return this.csrf.open(method, url, async);
|
||||
},
|
||||
|
||||
send: function(data) {
|
||||
if (!this.csrf_isPost) return this.csrf_send(data);
|
||||
prepend = csrfMagicName + '=' + csrfMagicToken + '&';
|
||||
// XXX: Removed to eliminate 'Refused to set unsafe header "Content-length" ' errors in modern browsers
|
||||
// if (this.csrf_purportedLength === undefined) {
|
||||
// this.csrf_setRequestHeader("Content-length", this.csrf_purportedLength + prepend.length);
|
||||
// delete this.csrf_purportedLength;
|
||||
// }
|
||||
delete this.csrf_isPost;
|
||||
return this.csrf_send(prepend + data);
|
||||
},
|
||||
csrf_send: function(data) {
|
||||
return this.csrf.send(data);
|
||||
},
|
||||
|
||||
setRequestHeader: function(header, value) {
|
||||
// We have to auto-set this at the end, since we don't know how long the
|
||||
// nonce is when added to the data.
|
||||
if (this.csrf_isPost && header == "Content-length") {
|
||||
this.csrf_purportedLength = value;
|
||||
return;
|
||||
}
|
||||
return this.csrf_setRequestHeader(header, value);
|
||||
},
|
||||
csrf_setRequestHeader: function(header, value) {
|
||||
return this.csrf.setRequestHeader(header, value);
|
||||
},
|
||||
|
||||
abort: function() {
|
||||
return this.csrf.abort();
|
||||
},
|
||||
getAllResponseHeaders: function() {
|
||||
return this.csrf.getAllResponseHeaders();
|
||||
},
|
||||
getResponseHeader: function(header) {
|
||||
return this.csrf.getResponseHeader(header);
|
||||
} // ,
|
||||
}
|
||||
|
||||
// proprietary
|
||||
CsrfMagic.prototype._updateProps = function() {
|
||||
this.readyState = this.csrf.readyState;
|
||||
if (this.readyState == 4) {
|
||||
this.responseText = this.csrf.responseText;
|
||||
this.responseXML = this.csrf.responseXML;
|
||||
this.status = this.csrf.status;
|
||||
this.statusText = this.csrf.statusText;
|
||||
}
|
||||
}
|
||||
CsrfMagic.process = function(base) {
|
||||
if(typeof base == 'object') {
|
||||
base[csrfMagicName] = csrfMagicToken;
|
||||
return base;
|
||||
}
|
||||
var prepend = csrfMagicName + '=' + csrfMagicToken;
|
||||
if (base) return prepend + '&' + base;
|
||||
return prepend;
|
||||
}
|
||||
// callback function for when everything on the page has loaded
|
||||
CsrfMagic.end = function() {
|
||||
// This rewrites forms AGAIN, so in case buffering didn't work this
|
||||
// certainly will.
|
||||
forms = document.getElementsByTagName('form');
|
||||
for (var i = 0; i < forms.length; i++) {
|
||||
form = forms[i];
|
||||
if (form.method.toUpperCase() !== 'POST') continue;
|
||||
if (form.elements[csrfMagicName]) continue;
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute('name', csrfMagicName);
|
||||
input.setAttribute('value', csrfMagicToken);
|
||||
input.setAttribute('type', 'hidden');
|
||||
form.appendChild(input);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets things up for Mozilla/Opera/nice browsers
|
||||
// We very specifically match against Internet Explorer, since they haven't
|
||||
// implemented prototypes correctly yet.
|
||||
if (window.XMLHttpRequest && window.XMLHttpRequest.prototype && '\v' != 'v') {
|
||||
var x = XMLHttpRequest.prototype;
|
||||
var c = CsrfMagic.prototype;
|
||||
|
||||
// Save the original functions
|
||||
x.csrf_open = x.open;
|
||||
x.csrf_send = x.send;
|
||||
x.csrf_setRequestHeader = x.setRequestHeader;
|
||||
|
||||
// Notice that CsrfMagic is itself an instantiatable object, but only
|
||||
// open, send and setRequestHeader are necessary as decorators.
|
||||
x.open = c.open;
|
||||
x.send = c.send;
|
||||
x.setRequestHeader = c.setRequestHeader;
|
||||
} else {
|
||||
// The only way we can do this is by modifying a library you have been
|
||||
// using. We support YUI, script.aculo.us, prototype, MooTools,
|
||||
// jQuery, Ext and Dojo.
|
||||
if (window.jQuery) {
|
||||
// jQuery didn't implement a new XMLHttpRequest function, so we have
|
||||
// to do this the hard way.
|
||||
jQuery.csrf_ajax = jQuery.ajax;
|
||||
jQuery.ajax = function( s ) {
|
||||
if (s.type && s.type.toUpperCase() == 'POST') {
|
||||
s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
|
||||
if ( s.data && s.processData && typeof s.data != "string" ) {
|
||||
s.data = jQuery.param(s.data);
|
||||
}
|
||||
s.data = CsrfMagic.process(s.data);
|
||||
}
|
||||
return jQuery.csrf_ajax( s );
|
||||
}
|
||||
}
|
||||
if (window.Prototype) {
|
||||
// This works for script.aculo.us too
|
||||
Ajax.csrf_getTransport = Ajax.getTransport;
|
||||
Ajax.getTransport = function() {
|
||||
return new CsrfMagic(Ajax.csrf_getTransport());
|
||||
}
|
||||
}
|
||||
if (window.MooTools) {
|
||||
Browser.csrf_Request = Browser.Request;
|
||||
Browser.Request = function () {
|
||||
return new CsrfMagic(Browser.csrf_Request());
|
||||
}
|
||||
}
|
||||
if (window.YAHOO) {
|
||||
// old YUI API
|
||||
YAHOO.util.Connect.csrf_createXhrObject = YAHOO.util.Connect.createXhrObject;
|
||||
YAHOO.util.Connect.createXhrObject = function (transaction) {
|
||||
obj = YAHOO.util.Connect.csrf_createXhrObject(transaction);
|
||||
obj.conn = new CsrfMagic(obj.conn);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
if (window.Ext) {
|
||||
// Ext can use other js libraries as loaders, so it has to come last
|
||||
// Ext's implementation is pretty identical to Yahoo's, but we duplicate
|
||||
// it for comprehensiveness's sake.
|
||||
Ext.lib.Ajax.csrf_createXhrObject = Ext.lib.Ajax.createXhrObject;
|
||||
Ext.lib.Ajax.createXhrObject = function (transaction) {
|
||||
obj = Ext.lib.Ajax.csrf_createXhrObject(transaction);
|
||||
obj.conn = new CsrfMagic(obj.conn);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
if (window.dojo) {
|
||||
// NOTE: this doesn't work with latest dojo
|
||||
dojo.csrf__xhrObj = dojo._xhrObj;
|
||||
dojo._xhrObj = function () {
|
||||
return new CsrfMagic(dojo.csrf__xhrObj());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,405 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* csrf-magic is a PHP library that makes adding CSRF-protection to your
|
||||
* web applications a snap. No need to modify every form or create a database
|
||||
* of valid nonces; just include this file at the top of every
|
||||
* web-accessible page (or even better, your common include file included
|
||||
* in every page), and forget about it! (There are, of course, configuration
|
||||
* options for advanced users).
|
||||
*
|
||||
* This library is PHP4 and PHP5 compatible.
|
||||
*/
|
||||
|
||||
// CONFIGURATION:
|
||||
|
||||
/**
|
||||
* By default, when you include this file csrf-magic will automatically check
|
||||
* and exit if the CSRF token is invalid. This will defer executing
|
||||
* csrf_check() until you're ready. You can also pass false as a parameter to
|
||||
* that function, in which case the function will not exit but instead return
|
||||
* a boolean false if the CSRF check failed. This allows for tighter integration
|
||||
* with your system.
|
||||
*/
|
||||
$GLOBALS['csrf']['defer'] = true;
|
||||
|
||||
/**
|
||||
* This is the amount of seconds you wish to allow before any token becomes
|
||||
* invalid; the default is two hours, which should be more than enough for
|
||||
* most websites.
|
||||
*/
|
||||
$GLOBALS['csrf']['expires'] = 7200;
|
||||
|
||||
/**
|
||||
* Callback function to execute when there's the CSRF check fails and
|
||||
* $fatal == true (see csrf_check). This will usually output an error message
|
||||
* about the failure.
|
||||
*/
|
||||
$GLOBALS['csrf']['callback'] = 'csrf_callback';
|
||||
|
||||
/**
|
||||
* Whether or not to include our JavaScript library which also rewrites
|
||||
* AJAX requests on this domain. Set this to the web path. This setting only works
|
||||
* with supported JavaScript libraries in Internet Explorer; see README.txt for
|
||||
* a list of supported libraries.
|
||||
*/
|
||||
$GLOBALS['csrf']['rewrite-js'] = false;
|
||||
|
||||
/**
|
||||
* A secret key used when hashing items. Please generate a random string and
|
||||
* place it here. If you change this value, all previously generated tokens
|
||||
* will become invalid.
|
||||
*/
|
||||
$GLOBALS['csrf']['secret'] = '';
|
||||
// nota bene: library code should use csrf_get_secret() and not access
|
||||
// this global directly
|
||||
|
||||
/**
|
||||
* Set this to false to disable csrf-magic's output handler, and therefore,
|
||||
* its rewriting capabilities. If you're serving non HTML content, you should
|
||||
* definitely set this false.
|
||||
*/
|
||||
$GLOBALS['csrf']['rewrite'] = true;
|
||||
|
||||
/**
|
||||
* Whether or not to use IP addresses when binding a user to a token. This is
|
||||
* less reliable and less secure than sessions, but is useful when you need
|
||||
* to give facilities to anonymous users and do not wish to maintain a database
|
||||
* of valid keys.
|
||||
*/
|
||||
$GLOBALS['csrf']['allow-ip'] = true;
|
||||
|
||||
/**
|
||||
* If this information is available, use the cookie by this name to determine
|
||||
* whether or not to allow the request. This is a shortcut implementation
|
||||
* very similar to 'key', but we randomly set the cookie ourselves.
|
||||
*/
|
||||
$GLOBALS['csrf']['cookie'] = '__csrf_cookie';
|
||||
|
||||
/**
|
||||
* If this information is available, set this to a unique identifier (it
|
||||
* can be an integer or a unique username) for the current "user" of this
|
||||
* application. The token will then be globally valid for all of that user's
|
||||
* operations, but no one else. This requires that 'secret' be set.
|
||||
*/
|
||||
$GLOBALS['csrf']['user'] = false;
|
||||
|
||||
/**
|
||||
* This is an arbitrary secret value associated with the user's session. This
|
||||
* will most probably be the contents of a cookie, as an attacker cannot easily
|
||||
* determine this information. Warning: If the attacker knows this value, they
|
||||
* can easily spoof a token. This is a generic implementation; sessions should
|
||||
* work in most cases.
|
||||
*
|
||||
* Why would you want to use this? Lets suppose you have a squid cache for your
|
||||
* website, and the presence of a session cookie bypasses it. Let's also say
|
||||
* you allow anonymous users to interact with the website; submitting forms
|
||||
* and AJAX. Previously, you didn't have any CSRF protection for anonymous users
|
||||
* and so they never got sessions; you don't want to start using sessions either,
|
||||
* otherwise you'll bypass the Squid cache. Setup a different cookie for CSRF
|
||||
* tokens, and have Squid ignore that cookie for get requests, for anonymous
|
||||
* users. (If you haven't guessed, this scheme was(?) used for MediaWiki).
|
||||
*/
|
||||
$GLOBALS['csrf']['key'] = false;
|
||||
|
||||
/**
|
||||
* The name of the magic CSRF token that will be placed in all forms, i.e.
|
||||
* the contents of <input type="hidden" name="$name" value="CSRF-TOKEN" />
|
||||
*/
|
||||
$GLOBALS['csrf']['input-name'] = '__csrf_magic';
|
||||
|
||||
/**
|
||||
* Set this to false if your site must work inside of frame/iframe elements,
|
||||
* but do so at your own risk: this configuration protects you against CSS
|
||||
* overlay attacks that defeat tokens.
|
||||
*/
|
||||
$GLOBALS['csrf']['frame-breaker'] = true;
|
||||
|
||||
/**
|
||||
* Whether or not CSRF Magic should be allowed to start a new session in order
|
||||
* to determine the key.
|
||||
*/
|
||||
$GLOBALS['csrf']['auto-session'] = true;
|
||||
|
||||
/**
|
||||
* Whether or not csrf-magic should produce XHTML style tags.
|
||||
*/
|
||||
$GLOBALS['csrf']['xhtml'] = true;
|
||||
|
||||
// FUNCTIONS:
|
||||
|
||||
// Don't edit this!
|
||||
$GLOBALS['csrf']['version'] = '1.0.4';
|
||||
|
||||
/**
|
||||
* Rewrites <form> on the fly to add CSRF tokens to them. This can also
|
||||
* inject our JavaScript library.
|
||||
*/
|
||||
function csrf_ob_handler($buffer, $flags) {
|
||||
// Even though the user told us to rewrite, we should do a quick heuristic
|
||||
// to check if the page is *actually* HTML. We don't begin rewriting until
|
||||
// we hit the first <html tag.
|
||||
static $is_html = false;
|
||||
if (!$is_html) {
|
||||
// not HTML until proven otherwise
|
||||
if (stripos($buffer, '<html') !== false) {
|
||||
$is_html = true;
|
||||
} else {
|
||||
return $buffer;
|
||||
}
|
||||
}
|
||||
$tokens = csrf_get_tokens();
|
||||
$name = $GLOBALS['csrf']['input-name'];
|
||||
$endslash = $GLOBALS['csrf']['xhtml'] ? ' /' : '';
|
||||
$input = "<input type='hidden' name='$name' value=\"$tokens\"$endslash>";
|
||||
$buffer = preg_replace('#(<form[^>]*method\s*=\s*["\']post["\'][^>]*>)#i', '$1' . $input, $buffer);
|
||||
if ($GLOBALS['csrf']['frame-breaker']) {
|
||||
$buffer = str_ireplace('</head>', '<script type="text/javascript">if (top != self) {top.location.href = self.location.href;}</script></head>', $buffer);
|
||||
}
|
||||
if ($js = $GLOBALS['csrf']['rewrite-js']) {
|
||||
$buffer = str_ireplace(
|
||||
'</head>',
|
||||
'<script type="text/javascript">'.
|
||||
'var csrfMagicToken = "'.$tokens.'";'.
|
||||
'var csrfMagicName = "'.$name.'";</script>'.
|
||||
'<script src="'.$js.'" type="text/javascript"></script></head>',
|
||||
$buffer
|
||||
);
|
||||
$script = '<script type="text/javascript">CsrfMagic.end();</script>';
|
||||
$buffer = str_ireplace('</body>', $script . '</body>', $buffer, $count);
|
||||
if (!$count) {
|
||||
$buffer .= $script;
|
||||
}
|
||||
}
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is a post request, and if it is, checks if the nonce is valid.
|
||||
* @param bool $fatal Whether or not to fatally error out if there is a problem.
|
||||
* @return True if check passes or is not necessary, false if failure.
|
||||
*/
|
||||
function csrf_check($fatal = true) {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true;
|
||||
csrf_start();
|
||||
$name = $GLOBALS['csrf']['input-name'];
|
||||
$ok = false;
|
||||
$tokens = '';
|
||||
do {
|
||||
if (!isset($_POST[$name])) break;
|
||||
// we don't regenerate a token and check it because some token creation
|
||||
// schemes are volatile.
|
||||
$tokens = $_POST[$name];
|
||||
if (!csrf_check_tokens($tokens)) break;
|
||||
$ok = true;
|
||||
} while (false);
|
||||
if ($fatal && !$ok) {
|
||||
$callback = $GLOBALS['csrf']['callback'];
|
||||
if (trim($tokens, 'A..Za..z0..9:;,') !== '') $tokens = 'hidden';
|
||||
$callback($tokens);
|
||||
exit;
|
||||
}
|
||||
return $ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a valid token(s) for a particular context. Tokens are separated
|
||||
* by semicolons.
|
||||
*/
|
||||
function csrf_get_tokens() {
|
||||
$has_cookies = !empty($_COOKIE);
|
||||
|
||||
// $ip implements a composite key, which is sent if the user hasn't sent
|
||||
// any cookies. It may or may not be used, depending on whether or not
|
||||
// the cookies "stick"
|
||||
$secret = csrf_get_secret();
|
||||
if (!$has_cookies && $secret) {
|
||||
// :TODO: Harden this against proxy-spoofing attacks
|
||||
$IP_ADDRESS = (isset($_SERVER['IP_ADDRESS']) ? $_SERVER['IP_ADDRESS'] : $_SERVER['REMOTE_ADDR']);
|
||||
$ip = ';ip:' . csrf_hash($IP_ADDRESS);
|
||||
} else {
|
||||
$ip = '';
|
||||
}
|
||||
csrf_start();
|
||||
|
||||
// These are "strong" algorithms that don't require per se a secret
|
||||
if (session_id()) return 'sid:' . csrf_hash(session_id()) . $ip;
|
||||
if ($GLOBALS['csrf']['cookie']) {
|
||||
$val = csrf_generate_secret();
|
||||
setcookie($GLOBALS['csrf']['cookie'], $val);
|
||||
return 'cookie:' . csrf_hash($val) . $ip;
|
||||
}
|
||||
if ($GLOBALS['csrf']['key']) return 'key:' . csrf_hash($GLOBALS['csrf']['key']) . $ip;
|
||||
// These further algorithms require a server-side secret
|
||||
if (!$secret) return 'invalid';
|
||||
if ($GLOBALS['csrf']['user'] !== false) {
|
||||
return 'user:' . csrf_hash($GLOBALS['csrf']['user']);
|
||||
}
|
||||
if ($GLOBALS['csrf']['allow-ip']) {
|
||||
return ltrim($ip, ';');
|
||||
}
|
||||
return 'invalid';
|
||||
}
|
||||
|
||||
function csrf_flattenpost($data) {
|
||||
$ret = array();
|
||||
foreach($data as $n => $v) {
|
||||
$ret = array_merge($ret, csrf_flattenpost2(1, $n, $v));
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
function csrf_flattenpost2($level, $key, $data) {
|
||||
if(!is_array($data)) return array($key => $data);
|
||||
$ret = array();
|
||||
foreach($data as $n => $v) {
|
||||
$nk = $level >= 1 ? $key."[$n]" : "[$n]";
|
||||
$ret = array_merge($ret, csrf_flattenpost2($level+1, $nk, $v));
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tokens is safe for HTML consumption
|
||||
*/
|
||||
function csrf_callback($tokens) {
|
||||
// (yes, $tokens is safe to echo without escaping)
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
|
||||
$data = '';
|
||||
foreach (csrf_flattenpost($_POST) as $key => $value) {
|
||||
if ($key == $GLOBALS['csrf']['input-name']) continue;
|
||||
$data .= '<input type="hidden" name="'.htmlspecialchars($key).'" value="'.htmlspecialchars($value).'" />';
|
||||
}
|
||||
echo "<html><head><title>CSRF check failed</title></head>
|
||||
<body>
|
||||
<p>CSRF check failed. Your form session may have expired, or you may not have
|
||||
cookies enabled.</p>
|
||||
<form method='post' action=''>$data<input type='submit' value='Try again' /></form>
|
||||
<p>Debug: $tokens</p></body></html>
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a composite token is valid. Outward facing code should use this
|
||||
* instead of csrf_check_token()
|
||||
*/
|
||||
function csrf_check_tokens($tokens) {
|
||||
if (is_string($tokens)) $tokens = explode(';', $tokens);
|
||||
foreach ($tokens as $token) {
|
||||
if (csrf_check_token($token)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a token is valid.
|
||||
*/
|
||||
function csrf_check_token($token) {
|
||||
if (strpos($token, ':') === false) return false;
|
||||
list($type, $value) = explode(':', $token, 2);
|
||||
if (strpos($value, ',') === false) return false;
|
||||
list($x, $time) = explode(',', $token, 2);
|
||||
if ($GLOBALS['csrf']['expires']) {
|
||||
if (time() > $time + $GLOBALS['csrf']['expires']) return false;
|
||||
}
|
||||
switch ($type) {
|
||||
case 'sid':
|
||||
return $value === csrf_hash(session_id(), $time);
|
||||
case 'cookie':
|
||||
$n = $GLOBALS['csrf']['cookie'];
|
||||
if (!$n) return false;
|
||||
if (!isset($_COOKIE[$n])) return false;
|
||||
return $value === csrf_hash($_COOKIE[$n], $time);
|
||||
case 'key':
|
||||
if (!$GLOBALS['csrf']['key']) return false;
|
||||
return $value === csrf_hash($GLOBALS['csrf']['key'], $time);
|
||||
// We could disable these 'weaker' checks if 'key' was set, but
|
||||
// that doesn't make me feel good then about the cookie-based
|
||||
// implementation.
|
||||
case 'user':
|
||||
if (!csrf_get_secret()) return false;
|
||||
if ($GLOBALS['csrf']['user'] === false) return false;
|
||||
return $value === csrf_hash($GLOBALS['csrf']['user'], $time);
|
||||
case 'ip':
|
||||
if (!csrf_get_secret()) return false;
|
||||
// do not allow IP-based checks if the username is set, or if
|
||||
// the browser sent cookies
|
||||
if ($GLOBALS['csrf']['user'] !== false) return false;
|
||||
if (!empty($_COOKIE)) return false;
|
||||
if (!$GLOBALS['csrf']['allow-ip']) return false;
|
||||
$IP_ADDRESS = (isset($_SERVER['IP_ADDRESS']) ? $_SERVER['IP_ADDRESS'] : $_SERVER['REMOTE_ADDR']);
|
||||
return $value === csrf_hash($IP_ADDRESS, $time);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a configuration value.
|
||||
*/
|
||||
function csrf_conf($key, $val) {
|
||||
if (!isset($GLOBALS['csrf'][$key])) {
|
||||
trigger_error('No such configuration ' . $key, E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
$GLOBALS['csrf'][$key] = $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a session if we're allowed to.
|
||||
*/
|
||||
function csrf_start() {
|
||||
if ($GLOBALS['csrf']['auto-session'] && !session_id()) {
|
||||
session_start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the secret, and generates one if necessary.
|
||||
*/
|
||||
function csrf_get_secret() {
|
||||
if ($GLOBALS['csrf']['secret']) return $GLOBALS['csrf']['secret'];
|
||||
$dir = dirname(__FILE__);
|
||||
$file = $dir . '/csrf-secret.php';
|
||||
$secret = '';
|
||||
if (file_exists($file)) {
|
||||
include $file;
|
||||
return $secret;
|
||||
}
|
||||
if (is_writable($dir)) {
|
||||
$secret = csrf_generate_secret();
|
||||
$fh = fopen($file, 'w');
|
||||
fwrite($fh, '<?php $secret = "'.$secret.'";' . PHP_EOL);
|
||||
fclose($fh);
|
||||
return $secret;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random string as the hash of time, microtime, and mt_rand.
|
||||
*/
|
||||
function csrf_generate_secret($len = 32) {
|
||||
$r = '';
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$r .= chr(mt_rand(0, 255));
|
||||
}
|
||||
$r .= time() . microtime();
|
||||
return sha1($r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a hash/expiry double. If time isn't set it will be calculated
|
||||
* from the current time.
|
||||
*/
|
||||
function csrf_hash($value, $time = null) {
|
||||
if (!$time) $time = time();
|
||||
return sha1(csrf_get_secret() . $value . $time) . ',' . $time;
|
||||
}
|
||||
|
||||
// Load user configuration
|
||||
if (function_exists('csrf_startup')) csrf_startup();
|
||||
// Initialize our handler
|
||||
if ($GLOBALS['csrf']['rewrite']) ob_start('csrf_ob_handler');
|
||||
// Perform check
|
||||
if (!$GLOBALS['csrf']['defer']) csrf_check();
|
|
@ -33,7 +33,7 @@ function dbConnect()
|
|||
if (strpos(ZM_DB_HOST, ':')) {
|
||||
// Host variable may carry a port or socket.
|
||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||
if (is_numeric($portOrSocket)) {
|
||||
if (ctype_digit($portOrSocket)) {
|
||||
$socket = ':host='.$host . ';port='.$portOrSocket;
|
||||
} else {
|
||||
$socket = ':unix_socket='.$portOrSocket;
|
||||
|
|
|
@ -832,12 +832,13 @@ function packageControl( $command ) {
|
|||
function daemonControl( $command, $daemon=false, $args=false ) {
|
||||
$string = ZM_PATH_BIN."/zmdc.pl $command";
|
||||
if ( $daemon ) {
|
||||
$string .= " $daemon";
|
||||
$string .= ' ' . $daemon;
|
||||
if ( $args ) {
|
||||
$string .= " $args";
|
||||
$string .= ' ' . $args;
|
||||
}
|
||||
}
|
||||
$string .= " 2>/dev/null >&- <&- >/dev/null";
|
||||
$string = escapeshellcmd( $string );
|
||||
$string .= ' 2>/dev/null >&- <&- >/dev/null';
|
||||
exec( $string );
|
||||
}
|
||||
|
||||
|
@ -874,21 +875,12 @@ function zmaControl( $monitor, $mode=false ) {
|
|||
daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] );
|
||||
}
|
||||
daemonControl( "stop", "zma", "-m ".$monitor['Id'] );
|
||||
if ( ZM_OPT_FRAME_SERVER ) {
|
||||
daemonControl( "stop", "zmf", "-m ".$monitor['Id'] );
|
||||
}
|
||||
} else {
|
||||
if ( $mode == "restart" ) {
|
||||
if ( ZM_OPT_CONTROL ) {
|
||||
daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] );
|
||||
}
|
||||
daemonControl( "stop", "zma", "-m ".$monitor['Id'] );
|
||||
if ( ZM_OPT_FRAME_SERVER ) {
|
||||
daemonControl( "stop", "zmf", "-m ".$monitor['Id'] );
|
||||
}
|
||||
}
|
||||
if ( ZM_OPT_FRAME_SERVER ) {
|
||||
daemonControl( "start", "zmf", "-m ".$monitor['Id'] );
|
||||
}
|
||||
daemonControl( "start", "zma", "-m ".$monitor['Id'] );
|
||||
if ( ZM_OPT_CONTROL && $monitor['Controllable'] && $monitor['TrackMotion'] && ( $monitor['Function'] == 'Modect' || $monitor['Function'] == 'Mocord' ) ) {
|
||||
|
@ -944,10 +936,11 @@ function zmaStatus( $monitor ) {
|
|||
function daemonCheck( $daemon=false, $args=false ) {
|
||||
$string = ZM_PATH_BIN."/zmdc.pl check";
|
||||
if ( $daemon ) {
|
||||
$string .= " $daemon";
|
||||
$string .= ' ' . $daemon;
|
||||
if ( $args )
|
||||
$string .= " $args";
|
||||
$string .= ' '. $args;
|
||||
}
|
||||
$string = escapeshellcmd( $string );
|
||||
$result = exec( $string );
|
||||
return( preg_match( '/running/', $result ) );
|
||||
}
|
||||
|
@ -1221,6 +1214,9 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
case 'MonitorName':
|
||||
$filter['sql'] .= 'M.'.preg_replace( '/^Monitor/', '', $filter['terms'][$i]['attr'] );
|
||||
break;
|
||||
case 'ServerId':
|
||||
$filter['sql'] .= 'M.ServerId';
|
||||
break;
|
||||
case 'DateTime':
|
||||
$filter['sql'] .= "E.StartTime";
|
||||
break;
|
||||
|
@ -1266,6 +1262,13 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
case 'Notes':
|
||||
$value = dbEscape($value);
|
||||
break;
|
||||
case 'ServerId':
|
||||
if ( $value == 'ZM_SERVER_ID' ) {
|
||||
$value = ZM_SERVER_ID;
|
||||
} else {
|
||||
$value = dbEscape($value);
|
||||
}
|
||||
break;
|
||||
case 'DateTime':
|
||||
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
|
||||
break;
|
||||
|
@ -1434,20 +1437,23 @@ function getLoad() {
|
|||
|
||||
function getDiskPercent($path = ZM_DIR_EVENTS) {
|
||||
$total = disk_total_space($path);
|
||||
if ( ! $total ) {
|
||||
Error("disk_total_space returned false for " . $path );
|
||||
if ( $total === false ) {
|
||||
Error("disk_total_space returned false. Verify the web account user has access to " . $path );
|
||||
return 0;
|
||||
} elseif ( $total == 0 ) {
|
||||
Error("disk_total_space indicates the following path has a filesystem size of zero bytes" . $path );
|
||||
return 100;
|
||||
}
|
||||
$free = disk_free_space($path);
|
||||
if ( ! $free ) {
|
||||
Error("disk_free_space returned false for " . $path );
|
||||
if ( $free === false ) {
|
||||
Error("disk_free_space returned false. Verify the web account user has access to " . $path );
|
||||
}
|
||||
$space = round(($total - $free) / $total * 100);
|
||||
$space = round((($total - $free) / $total) * 100);
|
||||
return( $space );
|
||||
}
|
||||
|
||||
function getDiskBlocks() {
|
||||
$df = shell_exec( 'df '.ZM_DIR_EVENTS );
|
||||
$df = shell_exec( 'df '.escapeshellarg(ZM_DIR_EVENTS) );
|
||||
$space = -1;
|
||||
if ( preg_match( '/\s(\d+)\s+\d+\s+\d+%/ms', $df, $matches ) )
|
||||
$space = $matches[1];
|
||||
|
@ -2140,4 +2146,8 @@ function folder_size($dir) {
|
|||
return $size;
|
||||
} // end function folder_size
|
||||
|
||||
function csrf_startup() {
|
||||
csrf_conf('rewrite-js', 'includes/csrf/csrf-magic.js');
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -105,6 +105,7 @@ if ( ! in_array( $css, $css_skins ) ) {
|
|||
}
|
||||
|
||||
define( "ZM_BASE_PATH", dirname( $_SERVER['REQUEST_URI'] ) );
|
||||
define( "ZM_SKIN_NAME", $skin );
|
||||
define( "ZM_SKIN_PATH", "skins/$skin" );
|
||||
|
||||
$skinBase = array(); // To allow for inheritance of skins
|
||||
|
@ -147,6 +148,7 @@ else
|
|||
|
||||
require_once( 'includes/lang.php' );
|
||||
require_once( 'includes/functions.php' );
|
||||
require_once( 'includes/csrf/csrf-magic.php' );
|
||||
|
||||
# Add Cross domain access headers
|
||||
CORSHeaders();
|
||||
|
@ -169,6 +171,16 @@ if ( isset($_REQUEST['action']) )
|
|||
foreach ( getSkinIncludes( 'skin.php' ) as $includeFile )
|
||||
require_once $includeFile;
|
||||
|
||||
# The only variable we really need to set is action. The others are informal.
|
||||
isset($view) || $view = NULL;
|
||||
isset($request) || $request = NULL;
|
||||
isset($action) || $action = NULL;
|
||||
|
||||
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' ) {
|
||||
Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
||||
csrf_check();
|
||||
}
|
||||
|
||||
require_once( 'includes/actions.php' );
|
||||
|
||||
# If I put this here, it protects all views and popups, but it has to go after actions.php because actions.php does the actual logging in.
|
||||
|
|
|
@ -115,4 +115,4 @@ window.onerror =
|
|||
function( message, url, line )
|
||||
{
|
||||
logReport( "ERR", message, url, line );
|
||||
}
|
||||
};
|
||||
|
|
|
@ -116,7 +116,7 @@ function setupOverlays()
|
|||
overlay.getElements('.overlayCloser').each(
|
||||
function( closer )
|
||||
{
|
||||
closer.addEvent( 'click', function() { overlay.element.hide(); } )
|
||||
closer.addEvent( 'click', function() { overlay.element.hide(); } );
|
||||
}
|
||||
);
|
||||
overlay.overlayShow = function() { overlay.element.show(); };
|
||||
|
|
|
@ -125,8 +125,7 @@ $SLANG = array(
|
|||
'AttrMaxScore' => 'Max. Score',
|
||||
'AttrMonitorId' => 'Monitor Id',
|
||||
'AttrMonitorName' => 'Monitor Name',
|
||||
'AttrServerId' => 'Server Id',
|
||||
'AttrServerName' => 'Server Name',
|
||||
'AttrServer' => 'Server',
|
||||
'AttrName' => 'Name',
|
||||
'AttrNotes' => 'Notes',
|
||||
'AttrSystemLoad' => 'System Load',
|
||||
|
@ -614,6 +613,7 @@ $SLANG = array(
|
|||
'Rewind' => 'Rewind',
|
||||
'RotateLeft' => 'Rotate Left',
|
||||
'RotateRight' => 'Rotate Right',
|
||||
'RTSPTransport' => 'RTSP Transport Protocol',
|
||||
'RunLocalUpdate' => 'Please run zmupdate.pl to update',
|
||||
'RunMode' => 'Run Mode',
|
||||
'Running' => 'Running',
|
||||
|
@ -903,6 +903,13 @@ $OLANG = array(
|
|||
"\"reorder_queue_size=nnn\" Set number of packets to buffer for handling of reordered packets~~~~".
|
||||
"\"loglevel=debug\" Set verbosity of FFmpeg (quiet, panic, fatal, error, warning, info, verbose, debug)"
|
||||
),
|
||||
'OPTIONS_RTSPTrans' => array(
|
||||
'Help' => "This sets the RTSP Transport Protocol for FFmpeg.~~ ".
|
||||
"TCP - Use TCP (interleaving within the RTSP control channel) as transport protocol.~~".
|
||||
"UDP - Use UDP as transport protocol. Higher resolution cameras have experienced some 'smearing' while using UDP, if so try TCP~~".
|
||||
"UDP Multicast - Use UDP Multicast as transport protocol~~".
|
||||
"HTTP - Use HTTP tunneling as transport protocol, which is useful for passing proxies.~~"
|
||||
),
|
||||
'OPTIONS_LIBVLC' => array(
|
||||
'Help' => "Parameters in this field are passed on to libVLC. Multiple parameters can be separated by ,~~ ".
|
||||
"Examples (do not enter quotes)~~~~".
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
<?php
|
||||
//
|
||||
// ZoneMinder web Polish language file, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue