Merge branch 'master' into feature-h264-videostorage

This commit is contained in:
Isaac Connor 2017-02-21 16:04:27 -05:00
commit 0880412e7f
20 changed files with 176 additions and 114 deletions

View File

@ -42,22 +42,12 @@ ADD utils/docker/start.sh /tmp/start.sh
# give files in /usr/local/share/zoneminder/ # give files in /usr/local/share/zoneminder/
RUN chown -R www-data:www-data /usr/local/share/zoneminder/ RUN chown -R www-data:www-data /usr/local/share/zoneminder/
# Creating SSH privilege escalation dir
RUN mkdir /var/run/sshd
# Adding apache virtual hosts file # Adding apache virtual hosts file
ADD utils/docker/apache-vhost /etc/apache2/sites-available/000-default.conf 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 ADD utils/docker/phpdate.ini /etc/php/7.0/apache2/conf.d/25-phpdate.ini
# Set the root passwd # Expose http ports
RUN echo 'root:root' | chpasswd EXPOSE 80
# Add a user we can actually login with
RUN useradd -m -s /bin/bash -G sudo zoneminder
RUN echo 'zoneminder:zoneminder' | chpasswd
# Expose ssh and http ports
EXPOSE 22 80
# Initial database and apache setup: # Initial database and apache setup:
RUN "/ZoneMinder/utils/docker/setup.sh" RUN "/ZoneMinder/utils/docker/setup.sh"

View File

@ -6,9 +6,9 @@
%if "%{zmuid_final}" == "nginx" %if "%{zmuid_final}" == "nginx"
%global with_nginx 1 %global with_nginx 1
%global wwwconfdir /etc/nginx/default.d %global wwwconfdir %{_sysconfdir}/nginx/default.d
%else %else
%global wwwconfdir /etc/httpd/conf.d %global wwwconfdir %{_sysconfdir}/httpd/conf.d
%endif %endif
%global sslcert %{_sysconfdir}/pki/tls/certs/localhost.crt %global sslcert %{_sysconfdir}/pki/tls/certs/localhost.crt
@ -24,19 +24,12 @@
%global with_init_sysv 1 %global with_init_sysv 1
%endif %endif
# php-mysql deprecated in f25
%if 0%{?fedora} >= 25
%global with_php_mysqlnd 1
%else
%global with_php_mysql 1
%endif
%global readme_suffix %{?rhel:Redhat%{?rhel}}%{!?rhel:Fedora} %global readme_suffix %{?rhel:Redhat%{?rhel}}%{!?rhel:Fedora}
%global _hardened_build 1 %global _hardened_build 1
Name: zoneminder Name: zoneminder
Version: 1.30.1 Version: 1.30.2
Release: 2%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons
# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/ # jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
@ -88,10 +81,9 @@ BuildRequires: polkit-devel
%{?with_nginx:Requires: nginx} %{?with_nginx:Requires: nginx}
%{?with_nginx:Requires: fcgiwrap} %{?with_nginx:Requires: fcgiwrap}
%{?with_nginx:Requires: php-fpm} %{?with_nginx:Requires: php-fpm}
%{!?with_nginx:Requires: httpd php} %{!?with_nginx:Requires: httpd}
%{!?with_nginx:Requires: php} %{!?with_nginx:Requires: php}
%{?with_php_mysqlnd:Requires: php-mysqlnd} Requires: php-mysqli
%{?with_php_mysql:Requires: php-mysql}
Requires: php-common Requires: php-common
Requires: php-gd Requires: php-gd
Requires: cambozola Requires: cambozola
@ -282,9 +274,9 @@ rm -rf %{_docdir}/%{name}-%{version}
%files %files
%license COPYING %license COPYING
%doc AUTHORS README.md distros/redhat/readme/README.%{readme_suffix} distros/redhat/readme/README.https distros/redhat/jscalendar-doc %doc AUTHORS README.md distros/redhat/readme/README.%{readme_suffix} distros/redhat/readme/README.https distros/redhat/jscalendar-doc
%config(noreplace) %attr(640,root,%{zmgid_final}) /etc/zm/zm.conf %config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/zm.conf
%config(noreplace) %attr(644,root,root) %{wwwconfdir}/zoneminder.conf %config(noreplace) %attr(644,root,root) %{wwwconfdir}/zoneminder.conf
%config(noreplace) /etc/logrotate.d/zoneminder %config(noreplace) %{_sysconfdir}/logrotate.d/zoneminder
%if 0%{?with_nginx} %if 0%{?with_nginx}
%config(noreplace) %{_sysconfdir}/php-fpm.d/zoneminder.conf %config(noreplace) %{_sysconfdir}/php-fpm.d/zoneminder.conf
@ -344,6 +336,9 @@ rm -rf %{_docdir}/%{name}-%{version}
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %ghost %{_localstatedir}/run/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) %ghost %{_localstatedir}/run/zoneminder
%changelog %changelog
* Wed Feb 08 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.2-1
- Bump version for 1.30.2 release
* Wed Dec 28 2016 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.1-2 * Wed Dec 28 2016 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.1-2
- Changes from rpmfusion #4393 - Changes from rpmfusion #4393

View File

@ -8,7 +8,7 @@ ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
Alias /zm /usr/share/zoneminder/www Alias /zm /usr/share/zoneminder/www
<Directory /usr/share/zoneminder/www> <Directory /usr/share/zoneminder/www>
Options -Indexes +ollowSymLinks Options -Indexes +FollowSymLinks
<IfModule mod_dir.c> <IfModule mod_dir.c>
DirectoryIndex index.php DirectoryIndex index.php
</IfModule> </IfModule>

View File

@ -40,6 +40,8 @@ Type
Preset Preset
The preset chooser sets sensible default values based on computational needs (fast v. best) and sensitivity (low, medium, high.) It is not required that you select a preset, and you can alter any of the parameters after choosing a preset. For a small number of monitors with ZoneMinder running on modern equipment, Best, high sensitivity can be chosen as a good starting point. The preset chooser sets sensible default values based on computational needs (fast v. best) and sensitivity (low, medium, high.) It is not required that you select a preset, and you can alter any of the parameters after choosing a preset. For a small number of monitors with ZoneMinder running on modern equipment, Best, high sensitivity can be chosen as a good starting point.
It is important to understand that the available presets are intended merely as a starting point. Since every camera's view is unique, they are not guaranteed to work properly in every case. Presets tend to work acceptably for indoor cameras, where the objects of interest are relatively close and there typically are few or no unwanted objects moving within the cameras view. Presets, on the other hand, tend to not work acceptably for outdoor cameras, where the field of view is typically much wider, objects of interest are farther away, and changing weather patterns can cause false triggers. For outdoor cameras in particular, you will almost certainly have to tune your motion detection zone to get desired results. Please refer to `this guide <http://www.zoneminder.com/wiki/index.php/Understanding_ZoneMinder%27s_Zoning_system_for_Dummies>`__ to learn how to do this.
Units Units
* Pixels - Selecting this option will allow many of the following values to be entered (or viewed) in units of pixels. * Pixels - Selecting this option will allow many of the following values to be entered (or viewed) in units of pixels.
* Percentage - Selecting this option will allow may of the following values to be entered (or viewed) as a percentage. The sense of the percentage values refers to the area of the zone and not the image as a whole. This makes trying to work out necessary sizes rather easier. * Percentage - Selecting this option will allow may of the following values to be entered (or viewed) as a percentage. The sense of the percentage values refers to the area of the zone and not the image as a whole. This makes trying to work out necessary sizes rather easier.

View File

@ -307,7 +307,7 @@ $dbh->ping();
} }
if ( $filter->{AutoExecute} ) if ( $filter->{AutoExecute} )
{ {
if ( !$event->{Execute} ) if ( !$event->{Executed} )
{ {
$delete_ok = undef if ( !executeCommand( $filter, $event ) ); $delete_ok = undef if ( !executeCommand( $filter, $event ) );
} }

View File

@ -227,8 +227,6 @@ int RemoteCameraHttp::ReadData( Buffer &buffer, int bytes_expected )
if ( total_bytes_to_read == 0 ) if ( total_bytes_to_read == 0 )
{ {
if( mode == SINGLE_IMAGE )
return( 0 );
// If socket is closed locally, then select will fail, but if it is closed remotely // If socket is closed locally, then select will fail, but if it is closed remotely
// then we have an exception on our socket.. but no data. // then we have an exception on our socket.. but no data.
Debug( 3, "Socket closed remotely" ); Debug( 3, "Socket closed remotely" );

View File

@ -36,9 +36,6 @@ service apache2 restart
# Start ZoneMinder # Start ZoneMinder
/usr/local/bin/zmpkg.pl start /usr/local/bin/zmpkg.pl start
# Start SSHD
/usr/sbin/sshd
while : while :
do do
sleep 3600 sleep 3600

View File

@ -0,0 +1,11 @@
--- 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

View File

@ -52,6 +52,12 @@ if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
#patch -p1 < utils/packpack/autosetup.patch #patch -p1 < utils/packpack/autosetup.patch
ln -sf distros/redhat rpm 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 if [ "${OS}" == "el" ]; then
zmrepodistro=${OS} zmrepodistro=${OS}
else else
@ -80,6 +86,12 @@ if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
echo "Begin Debian build..." 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
if [ -e "web/api/app/Plugin/Crud/LICENSE.txt" ]; then if [ -e "web/api/app/Plugin/Crud/LICENSE.txt" ]; then
echo "Crud plugin already installed..." echo "Crud plugin already installed..."

View File

@ -1,5 +1,9 @@
<?php <?php
# Moved up here because it is used in several spots.
# These are the valid columns that you can filter on.
$filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' );
switch ( $_REQUEST['task'] ) switch ( $_REQUEST['task'] )
{ {
case 'create' : case 'create' :
@ -40,14 +44,26 @@ switch ( $_REQUEST['task'] )
$minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL; $minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL;
$maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL; $maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL;
$limit = isset($_POST['limit'])?$_POST['limit']:100; $limit = 100;
$filter = isset($_POST['filter'])?$_POST['filter']:array(); if ( isset($_POST['limit']) ) {
$sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey'; if ( ( !is_integer( $_POST['limit'] ) and !ctype_digit($_POST['limit']) ) ) {
Error("Invalid value for limit " . $_POST['limit'] );
} else {
$limit = $_POST['limit'];
}
}
$sortField = 'TimeKey';
if ( isset($_POST['sortField']) ) {
if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) {
Error("Invalid sort field " . $_POST['sortField'] );
} else {
$sortField = $_POST['sortField'];
}
}
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc'; $sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
$filter = isset($_POST['filter'])?$_POST['filter']:array();
$filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' ); $total = dbFetchOne( 'SELECT count(*) AS Total FROM Logs', 'Total' );
$total = dbFetchOne( "SELECT count(*) AS Total FROM Logs", 'Total' );
$sql = 'SELECT * FROM Logs'; $sql = 'SELECT * FROM Logs';
$where = array(); $where = array();
$values = array(); $values = array();
@ -58,7 +74,12 @@ switch ( $_REQUEST['task'] )
$where[] = "TimeKey < ?"; $where[] = "TimeKey < ?";
$values[] = $maxTime; $values[] = $maxTime;
} }
foreach ( $filter as $field=>$value ) { foreach ( $filter as $field=>$value ) {
if ( ! in_array( $field, $filterFields ) ) {
Error("$field is not in valid filter fields");
continue;
}
if ( $field == 'Level' ){ if ( $field == 'Level' ){
$where[] = $field." <= ?"; $where[] = $field." <= ?";
$values[] = $value; $values[] = $value;
@ -147,8 +168,15 @@ switch ( $_REQUEST['task'] )
} }
//$limit = isset($_POST['limit'])?$_POST['limit']:1000; //$limit = isset($_POST['limit'])?$_POST['limit']:1000;
$filter = isset($_POST['filter'])?$_POST['filter']:array(); $filter = isset($_POST['filter'])?$_POST['filter']:array();
$sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey'; $sortField = 'TimeKey';
$sortOrder = isset($_POST['sortOrder'])?$_POST['sortOrder']:'asc'; if ( isset($_POST['sortField']) ) {
if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) {
Error("Invalid sort field " . $_POST['sortField'] );
} else {
$sortField = $_POST['sortField'];
}
}
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
$servers = Server::find_all(); $servers = Server::find_all();
$servers_by_Id = array(); $servers_by_Id = array();

View File

@ -31,7 +31,7 @@
* In production mode, flash messages redirect after a time interval. * In production mode, flash messages redirect after a time interval.
* In development mode, you need to click the flash message to continue. * 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 * Configure the Error handler used to handle errors for your application. By default

View File

@ -196,7 +196,7 @@ class Event {
} // end function createListThumbnail } // end function createListThumbnail
function getImageSrc( $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) { 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; $Event = $this;
$eventPath = $Event->Path(); $eventPath = $Event->Path();

View File

@ -6,7 +6,7 @@ class Frame {
public function __construct( $IdOrRow ) { public function __construct( $IdOrRow ) {
$row = NULL; $row = NULL;
if ( $IdOrRow ) { if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { if ( is_integer( $IdOrRow ) or ctype_digit($IdOrRow) ) {
$row = dbFetchOne( 'SELECT * FROM Frames WHERE Id=?', NULL, array( $IdOrRow ) ); $row = dbFetchOne( 'SELECT * FROM Frames WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) { if ( ! $row ) {
Error("Unable to load Frame record for Id=" . $IdOrRow ); Error("Unable to load Frame record for Id=" . $IdOrRow );
@ -84,7 +84,15 @@ class Frame {
$values = array_values( $parameters ); $values = array_values( $parameters );
} }
if ( $limit ) { if ( $limit ) {
if ( is_integer( $limit ) or ctype_digit( $limit ) ) {
$sql .= ' LIMIT ' . $limit; $sql .= ' LIMIT ' . $limit;
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Error("Invalid value for limit($limit) passed to Frame::find from $file:$line");
return;
}
} }
$results = dbFetchAll( $sql, NULL, $values ); $results = dbFetchAll( $sql, NULL, $values );
if ( $results ) { if ( $results ) {

View File

@ -5,7 +5,7 @@ class Server {
public function __construct( $IdOrRow = NULL ) { public function __construct( $IdOrRow = NULL ) {
$row = NULL; $row = NULL;
if ( $IdOrRow ) { if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { if ( is_integer( $IdOrRow ) or ctype_digit( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) ); $row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) { if ( ! $row ) {
Error("Unable to load Server record for Id=" . $IdOrRow ); Error("Unable to load Server record for Id=" . $IdOrRow );
@ -63,8 +63,14 @@ class Server {
) ); ) );
$values = array_values( $parameters ); $values = array_values( $parameters );
} }
if ( $limit ) { if ( is_integer( $limit ) or ctype_digit( $limit ) ) {
$sql .= ' LIMIT ' . $limit; $sql .= ' LIMIT ' . $limit;
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Error("Invalid value for limit($limit) passed to Server::find from $file:$line");
return;
} }
$results = dbFetchAll( $sql, NULL, $values ); $results = dbFetchAll( $sql, NULL, $values );
if ( $results ) { if ( $results ) {

View File

@ -44,6 +44,7 @@ function dbConnect()
try { try {
$dbConn = new PDO( ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS ); $dbConn = new PDO( ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS );
$dbConn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $ex ) { } catch(PDOException $ex ) {
echo "Unable to connect to ZM db." . $ex->getMessage(); echo "Unable to connect to ZM db." . $ex->getMessage();

View File

@ -56,6 +56,7 @@ function userLogin( $username, $password="", $passwordHashed=false ) {
if ( ZM_AUTH_TYPE == "builtin" ) { if ( ZM_AUTH_TYPE == "builtin" ) {
$_SESSION['passwordHash'] = $user['Password']; $_SESSION['passwordHash'] = $user['Password'];
} }
session_regenerate_id();
} else { } else {
Warning( "Login denied for user \"$username\"" ); Warning( "Login denied for user \"$username\"" );
$_SESSION['loginFailed'] = true; $_SESSION['loginFailed'] = true;
@ -1444,15 +1445,18 @@ function getLoad() {
function getDiskPercent($path = ZM_DIR_EVENTS) { function getDiskPercent($path = ZM_DIR_EVENTS) {
$total = disk_total_space($path); $total = disk_total_space($path);
if ( ! $total ) { if ( $total === false ) {
Error("disk_total_space returned false for " . $path ); Error("disk_total_space returned false. Verify the web account user has access to " . $path );
return 0; 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); $free = disk_free_space($path);
if ( ! $free ) { if ( $free === false ) {
Error("disk_free_space returned false for " . $path ); 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 ); return( $space );
} }

View File

@ -528,7 +528,7 @@ function Error( $string )
function Fatal( $string ) function Fatal( $string )
{ {
Logger::fetch()->logPrint( Logger::FATAL, $string ); Logger::fetch()->logPrint( Logger::FATAL, $string );
die( $string ); die( htmlentities($string) );
} }
function Panic( $string ) function Panic( $string )

View File

@ -112,6 +112,16 @@ if ( !file_exists( ZM_SKIN_PATH ) )
Fatal( "Invalid skin '$skin'" ); Fatal( "Invalid skin '$skin'" );
$skinBase[] = $skin; $skinBase[] = $skin;
$currentCookieParams = session_get_cookie_params();
Debug('Setting cookie parameters to lifetime('.$currentCookieParams['lifetime'].') path('.$currentCookieParams['path'].') domain ('.$currentCookieParams['domain'].') secure('.$currentCookieParams['secure'].') httpOnly(1)');
session_set_cookie_params(
$currentCookieParams["lifetime"],
$currentCookieParams["path"],
$currentCookieParams["domain"],
$currentCookieParams["secure"],
true
);
ini_set( "session.name", "ZMSESSID" ); ini_set( "session.name", "ZMSESSID" );
session_start(); session_start();

View File

@ -772,7 +772,7 @@ switch ( $tab )
{ {
?> ?>
<tr><td><?php echo translate('RefImageBlendPct') ?></td><td><select name="newMonitor[RefBlendPerc]"><?php foreach ( $fastblendopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['RefBlendPerc'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr> <tr><td><?php echo translate('RefImageBlendPct') ?></td><td><select name="newMonitor[RefBlendPerc]"><?php foreach ( $fastblendopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['RefBlendPerc'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<tr><td><?php echo translate('AlmRefImageBlendPct') ?></td><td><select name="newMonitor[AlarmRefBlendPerc]"><?php foreach ( $fastblendopts_alarm as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['AlarmRefBlendPerc'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr> <tr><td><?php echo translate('AlarmRefImageBlendPct') ?></td><td><select name="newMonitor[AlarmRefBlendPerc]"><?php foreach ( $fastblendopts_alarm as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['AlarmRefBlendPerc'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<?php <?php
} else { } else {
?> ?>