From 4da95369f99387f34de432692e9e43cf53776de2 Mon Sep 17 00:00:00 2001
From: montagdude
Date: Wed, 23 Jan 2019 10:35:18 -0500
Subject: [PATCH 1/2] Fix zone area calculation (#2437)
Previous method resulted in bogus zone areas (in the range of
1000s of % of frame area) when entering points with the keyboard, even
after applying commit 4937a68650aeafaff78559f27818616ecd4dfbce. This
change implements the method here:
http://mathworld.wolfram.com/PolygonArea.html
It has been tested on ZoneMinder 1.32.3 and works correctly when
either entering coordinates with the keyboard or dragging points with
the mouse.
---
web/skins/classic/views/js/zone.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/web/skins/classic/views/js/zone.js b/web/skins/classic/views/js/zone.js
index b8e486199..cb9a83386 100644
--- a/web/skins/classic/views/js/zone.js
+++ b/web/skins/classic/views/js/zone.js
@@ -725,11 +725,13 @@ function Polygon_calcArea( coords ) {
var n_coords = coords.length;
var float_area = 0.0;
- for ( i = 0, j = n_coords-1; i < n_coords; j = i++ ) {
- var trap_area = ( ( coords[i].x - coords[j].x ) * ( coords[i].y + coords[j].y ) ) / 2;
+ for ( i = 0; i < n_coords-1; i++ ) {
+ var trap_area = (coords[i].x*coords[i+1].y - coords[i+1].x*coords[i].y) / 2;
float_area += trap_area;
//printf( "%.2f (%.2f)\n", float_area, trap_area );
}
+ float_area += (coords[n_coords-1].x*coords[0].y - coords[0].x*coords[n_coords-1].y) / 2;
+
return Math.round( Math.abs( float_area ) );
}
From 6eb4d7ae27553771b5b4ae3faa4684f2f3d3f9c0 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 23 Jan 2019 11:30:51 -0500
Subject: [PATCH 2/2] Filter improvements (#2438)
* Put back code to close the popup when view is none
* clean up and reduce depth of some logic
* Increase width of user popup
* fix code style
* Make execute_filter work on a filter Id instead of name
* rework logic to reduce code depth. Change view to events to display the results of execute.
* Change the redirect to stay on the new view. When redirecting from executing a filter, it was redirecting to filter.
* Set a form action for correctness. Change execute button to a button instead of a submit. Stay on the filter view when executing
---
web/includes/actions/filter.php | 109 ++++++++++++++-------------
web/includes/functions.php | 10 +--
web/index.php | 56 +++++++-------
web/skins/classic/js/base.js | 2 +-
web/skins/classic/views/events.php | 4 +-
web/skins/classic/views/filter.php | 12 +--
web/skins/classic/views/js/filter.js | 24 +++---
web/skins/classic/views/none.php | 6 ++
web/skins/classic/views/user.php | 53 ++++++-------
9 files changed, 141 insertions(+), 135 deletions(-)
diff --git a/web/includes/actions/filter.php b/web/includes/actions/filter.php
index 4067bdf9c..782d93885 100644
--- a/web/includes/actions/filter.php
+++ b/web/includes/actions/filter.php
@@ -19,63 +19,64 @@
//
// Event scope actions, view permissions only required
-if ( canView('Events') ) {
+if ( !canView('Events') ) {
+ Warning('You do not have permission to view Events.');
+ return;
+}
- if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
- if ( $action == 'addterm' ) {
- $_REQUEST['filter'] = addFilterTerm($_REQUEST['filter'], $_REQUEST['line']);
- } elseif ( $action == 'delterm' ) {
- $_REQUEST['filter'] = delFilterTerm($_REQUEST['filter'], $_REQUEST['line']);
- } else if ( canEdit('Events') ) {
- if ( $action == 'delete' ) {
- if ( ! empty($_REQUEST['Id']) ) {
- dbQuery('DELETE FROM Filters WHERE Id=?', array($_REQUEST['Id']));
- }
- } else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) {
- # or ( $action == 'submit' ) ) {
+if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
+ if ( $action == 'addterm' ) {
+ $_REQUEST['filter'] = addFilterTerm($_REQUEST['filter'], $_REQUEST['line']);
+ } elseif ( $action == 'delterm' ) {
+ $_REQUEST['filter'] = delFilterTerm($_REQUEST['filter'], $_REQUEST['line']);
+ } else if ( canEdit('Events') ) {
+ if ( $action == 'delete' ) {
+ if ( !empty($_REQUEST['Id']) ) {
+ dbQuery('DELETE FROM Filters WHERE Id=?', array($_REQUEST['Id']));
+ }
+ } else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) {
- $sql = '';
- $_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']);
- $_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
- $_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
- if ( $action == 'execute' ) {
- $tempFilterName = '_TempFilter'.time();
- $sql .= ' Name = \''.$tempFilterName.'\'';
- } else {
- $sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']);
- }
- $sql .= ', Query = '.dbEscape(jsonEncode($_REQUEST['filter']['Query']));
- $sql .= ', AutoArchive = '.(!empty($_REQUEST['filter']['AutoArchive']) ? 1 : 0);
- $sql .= ', AutoVideo = '. ( !empty($_REQUEST['filter']['AutoVideo']) ? 1 : 0);
- $sql .= ', AutoUpload = '. ( !empty($_REQUEST['filter']['AutoUpload']) ? 1 : 0);
- $sql .= ', AutoEmail = '. ( !empty($_REQUEST['filter']['AutoEmail']) ? 1 : 0);
- $sql .= ', AutoMessage = '. ( !empty($_REQUEST['filter']['AutoMessage']) ? 1 : 0);
- $sql .= ', AutoExecute = '. ( !empty($_REQUEST['filter']['AutoExecute']) ? 1 : 0);
- $sql .= ', AutoExecuteCmd = '.dbEscape($_REQUEST['filter']['AutoExecuteCmd']);
- $sql .= ', AutoDelete = '. ( !empty($_REQUEST['filter']['AutoDelete']) ? 1 : 0);
- if ( !empty($_REQUEST['filter']['AutoMove']) ? 1 : 0) {
- $sql .= ', AutoMove = 1, AutoMoveTo='. validInt($_REQUEST['filter']['AutoMoveTo']);
- } else {
- $sql .= ', AutoMove = 0';
- }
- $sql .= ', UpdateDiskSpace = '. ( !empty($_REQUEST['filter']['UpdateDiskSpace']) ? 1 : 0);
- $sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0);
- $sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 1 : 0);
+ $sql = '';
+ $_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']);
+ $_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
+ $_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
+ if ( $action == 'execute' ) {
+ $tempFilterName = '_TempFilter'.time();
+ $sql .= ' Name = \''.$tempFilterName.'\'';
+ } else {
+ $sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']);
+ }
+ $sql .= ', Query = '.dbEscape(jsonEncode($_REQUEST['filter']['Query']));
+ $sql .= ', AutoArchive = '.(!empty($_REQUEST['filter']['AutoArchive']) ? 1 : 0);
+ $sql .= ', AutoVideo = '. ( !empty($_REQUEST['filter']['AutoVideo']) ? 1 : 0);
+ $sql .= ', AutoUpload = '. ( !empty($_REQUEST['filter']['AutoUpload']) ? 1 : 0);
+ $sql .= ', AutoEmail = '. ( !empty($_REQUEST['filter']['AutoEmail']) ? 1 : 0);
+ $sql .= ', AutoMessage = '. ( !empty($_REQUEST['filter']['AutoMessage']) ? 1 : 0);
+ $sql .= ', AutoExecute = '. ( !empty($_REQUEST['filter']['AutoExecute']) ? 1 : 0);
+ $sql .= ', AutoExecuteCmd = '.dbEscape($_REQUEST['filter']['AutoExecuteCmd']);
+ $sql .= ', AutoDelete = '. ( !empty($_REQUEST['filter']['AutoDelete']) ? 1 : 0);
+ if ( !empty($_REQUEST['filter']['AutoMove']) ? 1 : 0) {
+ $sql .= ', AutoMove = 1, AutoMoveTo='. validInt($_REQUEST['filter']['AutoMoveTo']);
+ } else {
+ $sql .= ', AutoMove = 0';
+ }
+ $sql .= ', UpdateDiskSpace = '. ( !empty($_REQUEST['filter']['UpdateDiskSpace']) ? 1 : 0);
+ $sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0);
+ $sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 1 : 0);
- if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) {
- dbQuery('UPDATE Filters SET ' . $sql. ' WHERE Id=?', array($_REQUEST['Id']));
- } else {
- dbQuery('INSERT INTO Filters SET' . $sql);
- $_REQUEST['Id'] = dbInsertId();
- }
- if ( $action == 'execute' ) {
- executeFilter( $tempFilterName );
- }
+ if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) {
+ dbQuery('UPDATE Filters SET '.$sql.' WHERE Id=?', array($_REQUEST['Id']));
+ } else {
+ dbQuery('INSERT INTO Filters SET'.$sql);
+ $_REQUEST['Id'] = dbInsertId();
+ }
+ if ( $action == 'execute' ) {
+ executeFilter($_REQUEST['Id']);
+ $view = 'events';
+ }
- } // end if save or execute
- } // end if canEdit(Events)
- return;
- } // end if object == filter
-} // end canView(Events)
+ } // end if save or execute
+ } // end if canEdit(Events)
+} // end if object == filter
?>
diff --git a/web/includes/functions.php b/web/includes/functions.php
index 154a26046..77cd1ca47 100644
--- a/web/includes/functions.php
+++ b/web/includes/functions.php
@@ -958,11 +958,11 @@ Logger::Debug("generating Video $command: result($result outptu:(".implode("\n",
return( $status?"":rtrim($result) );
}
-function executeFilter( $filter ) {
- $command = ZM_PATH_BIN."/zmfilter.pl --filter ".escapeshellarg($filter);
- $result = exec( $command, $output, $status );
- dbQuery( "delete from Filters where Name like '_TempFilter%'" );
- return( $status );
+function executeFilter( $filter_id ) {
+ $command = ZM_PATH_BIN.'/zmfilter.pl --filter_id '.escapeshellarg($filter_id);
+ $result = exec($command, $output, $status);
+ dbQuery('DELETE FROM Filters WHERE Id=?', array($filter_id));
+ return $status;
}
# This takes more than one scale amount, so it runs through each and alters dimension.
diff --git a/web/index.php b/web/index.php
index 7d13e9ce1..5190fad65 100644
--- a/web/index.php
+++ b/web/index.php
@@ -51,7 +51,6 @@ require_once('includes/Event.php');
require_once('includes/Group.php');
require_once('includes/Monitor.php');
-
if (
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
or
@@ -118,12 +117,12 @@ $skinBase[] = $skin;
$currentCookieParams = session_get_cookie_params();
//Logger::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
-);
+ $currentCookieParams['lifetime'],
+ $currentCookieParams['path'],
+ $currentCookieParams['domain'],
+ $currentCookieParams['secure'],
+ true
+);
ini_set('session.name', 'ZMSESSID');
@@ -166,6 +165,7 @@ if ( !is_writable(ZM_DIR_EVENTS) ) {
}
# Globals
+$action = null;
$error_message = null;
$redirect = null;
$view = null;
@@ -185,9 +185,9 @@ foreach ( getSkinIncludes('skin.php') as $includeFile )
# User Login will be performed in auth.php
require_once('includes/auth.php');
-if ( isset($_REQUEST['action']) ) {
+if ( isset($_REQUEST['action']) )
$action = detaintPath($_REQUEST['action']);
-}
+
# The only variable we really need to set is action. The others are informal.
isset($view) || $view = NULL;
@@ -244,27 +244,27 @@ if ( $request ) {
require_once $includeFile;
}
return;
-} else {
- if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
- foreach ( $includeFiles as $includeFile ) {
- if ( !file_exists($includeFile) )
- Fatal("View '$view' does not exist");
- require_once $includeFile;
- }
- // If the view overrides $view to 'error', and the user is not logged in, then the
- // issue is probably resolvable by logging in, so provide the opportunity to do so.
- // The login view should handle redirecting to the correct location afterward.
- if ( $view == 'error' && !isset($user) ) {
- $view = 'login';
- foreach ( getSkinIncludes('views/login.php', true, true) as $includeFile )
- require_once $includeFile;
- }
+}
+
+if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
+ foreach ( $includeFiles as $includeFile ) {
+ if ( !file_exists($includeFile) )
+ Fatal("View '$view' does not exist");
+ require_once $includeFile;
}
- // If the view is missing or the view still returned error with the user logged in,
- // then it is not recoverable.
- if ( !$includeFiles || $view == 'error' ) {
- foreach ( getSkinIncludes('views/error.php', true, true) as $includeFile )
+ // If the view overrides $view to 'error', and the user is not logged in, then the
+ // issue is probably resolvable by logging in, so provide the opportunity to do so.
+ // The login view should handle redirecting to the correct location afterward.
+ if ( $view == 'error' && !isset($user) ) {
+ $view = 'login';
+ foreach ( getSkinIncludes('views/login.php', true, true) as $includeFile )
require_once $includeFile;
}
}
+// If the view is missing or the view still returned error with the user logged in,
+// then it is not recoverable.
+if ( !$includeFiles || $view == 'error' ) {
+ foreach ( getSkinIncludes('views/error.php', true, true) as $includeFile )
+ require_once $includeFile;
+}
?>
diff --git a/web/skins/classic/js/base.js b/web/skins/classic/js/base.js
index b77b350ef..41bec4ed9 100644
--- a/web/skins/classic/js/base.js
+++ b/web/skins/classic/js/base.js
@@ -64,7 +64,7 @@ var popupSizes = {
'stats': {'width': 840, 'height': 200},
'storage': {'width': 600, 'height': 405},
'timeline': {'width': 760, 'height': 540},
- 'user': {'width': 360, 'height': 720},
+ 'user': {'width': 460, 'height': 720},
'version': {'width': 360, 'height': 185},
'video': {'width': 420, 'height': 360},
'videoview': {'addWidth': 48, 'addHeight': 80},
diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php
index 1ae446b9e..885924e64 100644
--- a/web/skins/classic/views/events.php
+++ b/web/skins/classic/views/events.php
@@ -79,7 +79,9 @@ $pagination = getPagination($pages, $page, $maxShortcuts, $filterQuery.$sortQuer
$focusWindow = true;
if ( $_POST ) {
- header('Location: ' . $_SERVER['REQUEST_URI'].htmlspecialchars_decode($filterQuery).htmlspecialchars_decode($sortQuery).$limitQuery.'&page='.$page);
+ // I think this is basically so that a refresh doesn't repost
+ Logger::Debug("Redirecting to " . $_SERVER['REQUEST_URI']);
+ header('Location: ?view=' . $view.htmlspecialchars_decode($filterQuery).htmlspecialchars_decode($sortQuery).$limitQuery.'&page='.$page);
exit();
}
diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php
index bbce2973d..403a9b440 100644
--- a/web/skins/classic/views/filter.php
+++ b/web/skins/classic/views/filter.php
@@ -50,7 +50,7 @@ if ( isset($_REQUEST['sort_field']) && isset($_REQUEST['filter']) ) {
}
if ( isset($_REQUEST['filter']) ) {
- $filter->set( $_REQUEST['filter'] );
+ $filter->set($_REQUEST['filter']);
# Update our filter object with whatever changes we have made before saving
}
@@ -58,7 +58,7 @@ $conjunctionTypes = getFilterQueryConjunctionTypes();
$obracketTypes = array();
$cbracketTypes = array();
-if (count($filter->terms()) > 0) {
+if ( count($filter->terms()) > 0 ) {
$terms = $filter->terms();
} else {
$terms[] = array();
@@ -177,9 +177,9 @@ if ( (null !== $filter->Concurrent()) and $filter->Concurrent() )
?>
-
AutoMove() ) { ?> checked="checked" onclick="updateButtons(this);if(this.checked){$j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');}else{this.form.elements['filter[AutoMoveTo]'].hide();};"/>
- AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;' ) ); ?>
+ AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;' )); ?>
@@ -407,7 +407,7 @@ if ( ZM_OPT_MESSAGE ) {
-
+
diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js
index 2a211681d..f6f5b43e8 100644
--- a/web/skins/classic/views/js/filter.js
+++ b/web/skins/classic/views/js/filter.js
@@ -7,20 +7,21 @@ function validateForm( form ) {
obrCount += parseInt(form.elements['filter[Query][terms][' + i + '][obr]'].value);
cbrCount += parseInt(form.elements['filter[Query][terms][' + i + '][cbr]'].value);
}
- if (form.elements['filter[Query][terms][' + i + '][val]'].value == '') {
- alert( errorValue );
+ if ( form.elements['filter[Query][terms][' + i + '][val]'].value == '' ) {
+ alert(errorValue);
return false;
}
}
- if (obrCount - cbrCount != 0) {
- alert( errorBrackets );
+ if ( (obrCount - cbrCount) != 0 ) {
+ alert(errorBrackets);
return false;
}
var numbers_reg = /\D/;
- if ( numbers_reg.test( form.elements['filter[Query][limit]'].value ) ) {
- alert( "There appear to be non-numeric characters in your limit. Limit must be a positive integer value or empty." );
+ if ( numbers_reg.test(form.elements['filter[Query][limit]'].value) ) {
+ alert("There appear to be non-numeric characters in your limit. Limit must be a positive integer value or empty.");
return false;
}
+ console.log("Success validating");
return true;
}
@@ -82,9 +83,10 @@ function submitToEvents( element ) {
function executeFilter( element ) {
var form = element.form;
- form.action = thisUrl + '?view=events';
+ form.action = thisUrl + '?view=filter';
form.elements['action'].value = 'execute';
- history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
+ form.submit();
+ //history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
}
function saveFilter( element ) {
@@ -228,12 +230,12 @@ function stringFilter(term) {
function addTerm( element ) {
var row = $j(element).closest('tr');
- row.find('select').chosen("destroy");
+ row.find('select').chosen('destroy');
var newRow = row.clone().insertAfter(row);
- row.find('select').chosen({width: "101%"});
+ row.find('select').chosen({width: '101%'});
newRow.find('select').each( function() { //reset new row to default
this[0].selected = 'selected';
- }).chosen({width: "101%"});
+ }).chosen({width: '101%'});
newRow.find('input[type="text"]').val('');
var rows = $j(row).parent().children();
parseRows(rows);
diff --git a/web/skins/classic/views/none.php b/web/skins/classic/views/none.php
index e52105331..da04ed19b 100644
--- a/web/skins/classic/views/none.php
+++ b/web/skins/classic/views/none.php
@@ -32,6 +32,12 @@ require_once($skinJsPhpFile);
?>
+
diff --git a/web/skins/classic/views/user.php b/web/skins/classic/views/user.php
index ee0c7428c..95ed639a5 100644
--- a/web/skins/classic/views/user.php
+++ b/web/skins/classic/views/user.php
@@ -20,15 +20,14 @@
$selfEdit = ZM_USER_SELF_EDIT && $_REQUEST['uid'] == $user['Id'];
-if ( !canEdit( 'System' ) && !$selfEdit )
-{
- $view = "error";
- return;
+if ( !canEdit('System') && !$selfEdit ) {
+ $view = 'error';
+ return;
}
if ( $_REQUEST['uid'] ) {
- if ( !($newUser = dbFetchOne( 'SELECT * FROM Users WHERE Id = ?', NULL, ARRAY($_REQUEST['uid'])) ) ) {
- $view = "error";
+ if ( !($newUser = dbFetchOne('SELECT * FROM Users WHERE Id = ?', NULL, ARRAY($_REQUEST['uid']))) ) {
+ $view = 'error';
return;
}
} else {
@@ -38,29 +37,28 @@ if ( $_REQUEST['uid'] ) {
$newUser['MonitorIds'] = '';
}
-$monitorIds = array_flip(explode( ',', $newUser['MonitorIds'] ));
+$monitorIds = array_flip(explode(',', $newUser['MonitorIds']));
$yesno = array( 0=>translate('No'), 1=>translate('Yes') );
$nv = array( 'None'=>translate('None'), 'View'=>translate('View') );
$nve = array( 'None'=>translate('None'), 'View'=>translate('View'), 'Edit'=>translate('Edit') );
-$bandwidths = array_merge( array( ""=>"" ), $bandwidth_options );
-$langs = array_merge( array( ""=>"" ), getLanguages() );
+$bandwidths = array_merge( array( ''=>'' ), $bandwidth_options );
+$langs = array_merge( array( ''=>'' ), getLanguages() );
-$sql = "select Id,Name from Monitors order by Sequence asc";
+$sql = 'SELECT Id,Name FROM Monitors ORDER BY Sequence ASC';
$monitors = array();
-foreach( dbFetchAll( $sql ) as $monitor )
-{
- $monitors[] = $monitor;
+foreach( dbFetchAll($sql) as $monitor ) {
+ $monitors[] = $monitor;
}
$focusWindow = true;
-xhtmlHeaders(__FILE__, translate('User')." - ".$newUser['Username'] );
+xhtmlHeaders(__FILE__, translate('User').' - '.$newUser['Username']);
?>