Merge branch 'master' of github.com:zoneminder/ZoneMinder

This commit is contained in:
Isaac Connor 2020-08-20 17:12:41 -04:00
commit 519bfae1da
37 changed files with 3353 additions and 438 deletions

View File

@ -41,7 +41,6 @@ env:
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=knnniggett/packpack:ubuntu-eoan
- SMPFLAGS=-j4 OS=ubuntu DIST=focal DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack

View File

@ -484,7 +484,7 @@ CREATE TABLE `Monitors` (
`Hue` mediumint(7) NOT NULL default '-1',
`Colour` mediumint(7) NOT NULL default '-1',
`EventPrefix` varchar(32) NOT NULL default 'Event-',
`LabelFormat` varchar(64) default '%N - %y/%m/%d %H:%M:%S',
`LabelFormat` varchar(64),
`LabelX` smallint(5) unsigned NOT NULL default '0',
`LabelY` smallint(5) unsigned NOT NULL default '0',
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',

2
db/zm_update-1.34.20.sql Normal file
View File

@ -0,0 +1,2 @@
/* This was done in 1.31.0 but zm_create.sql.in wasn't updated to match. */
ALTER TABLE Monitors MODIFY LinkedMonitors varchar(255);

View File

@ -32,10 +32,14 @@ Version: 1.35.5
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
# Mootools is inder the MIT license: http://mootools.net/
# Mootools is under the MIT license: http://mootools.net/
# jQuery is under the MIT license: https://jquery.org/license/
# CakePHP is under the MIT license: https://github.com/cakephp/cakephp
# Crud is under the MIT license: https://github.com/FriendsOfCake/crud
# CakePHP-Enum-Behavior is under the MIT license: https://github.com/asper/CakePHP-Enum-Behavior
# Bootstrap is under the MIT license: https://getbootstrap.com/docs/4.5/about/license/
# Bootstrap-table is under the MIT license: https://bootstrap-table.com/docs/about/license/
# font-awesome is under CC-BY license: https://fontawesome.com/license/free
License: GPLv2+ and LGPLv2+ and MIT
URL: http://www.zoneminder.com/

View File

@ -23,7 +23,7 @@ override_dh_auto_configure:
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_RUNDIR="/run/zm" \
-DZM_SOCKDIR="/run/zm" \
-DZM_TMPDIR="/tmp/zm" \
-DZM_TMPDIR="/var/tmp/zm" \
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \

View File

@ -61,10 +61,10 @@ if [ "$1" = "configure" ]; then
exit 1;
fi
# This creates the user.
echo "CREATE USER '${ZM_DB_USER}'@localhost IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
echo "CREATE USER '${ZM_DB_USER}'@${ZM_DB_HOST} IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
echo "Updating permissions"
echo "grant lock tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
echo "GRANT LOCK tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine,trigger,execute ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@${ZM_DB_HOST};" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f

View File

@ -842,7 +842,8 @@ bool EventStream::sendFrame(int delta_us) {
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size) )
||
( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) ) {
Error("Unable to send stream frame: %s", strerror(errno));
if ( errno != EPIPE )
Error("Unable to send stream frame: %s", strerror(errno));
return false;
}
} // end if send_raw or not

View File

@ -81,7 +81,7 @@ void FFMPEGInit() {
av_log_set_callback(log_libav_callback);
Info("Enabling ffmpeg logs, as LOG_DEBUG+LOG_FFMPEG are enabled in options");
} else {
Info("Not enabling ffmpeg logs, as LOG_FFMPEG and/or LOG_DEBUG is disabled in options, or this monitor is not part of your debug targets");
Debug(1,"Not enabling ffmpeg logs, as LOG_FFMPEG and/or LOG_DEBUG is disabled in options, or this monitor is not part of your debug targets");
av_log_set_level(AV_LOG_QUIET);
}
#if !LIBAVFORMAT_VERSION_CHECK(58, 9, 0, 64, 0)

View File

@ -40,6 +40,7 @@ extern "C" {
#include <libavutil/mathematics.h>
#include <libavutil/avstring.h>
#include "libavutil/audio_fifo.h"
#include "libavutil/imgutils.h"
/* LIBAVUTIL_VERSION_CHECK checks for the right version of libav and FFmpeg
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)

View File

@ -14,6 +14,18 @@ class UsersController extends AppController {
*/
public $components = array('RequestHandler', 'Paginator');
public function beforeFilter() {
parent::beforeFilter();
global $user;
# We already tested for auth in appController, so we just need to test for specific permission
$canView = (!$user) || ($user['System'] != 'None');
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
}
/**
* index method
*
@ -23,6 +35,12 @@ class UsersController extends AppController {
public function index() {
$this->User->recursive = 0;
global $user;
# We should actually be able to list our own user, but I'm not bothering at this time.
if ( $user['System'] == 'None' ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
$users = $this->Paginator->paginate('User');
$this->set(compact('users'));
@ -37,9 +55,19 @@ class UsersController extends AppController {
*/
public function view($id = null) {
$this->User->recursive = 1;
if (!$this->User->exists($id)) {
global $user;
# We can view ourselves
$canView = ($user['System'] != 'None') or ($user['Id'] == $id);
if ( !$canView ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
if ( !$this->User->exists($id) ) {
throw new NotFoundException(__('Invalid user'));
}
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
$user = $this->User->find('first', $options);
@ -55,9 +83,16 @@ class UsersController extends AppController {
* @return void
*/
public function add() {
if ($this->request->is('post')) {
if ( $this->request->is('post') ) {
global $user;
if ( $user['System'] != 'Edit' ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
$this->User->create();
if ($this->User->save($this->request->data)) {
if ( $this->User->save($this->request->data) ) {
return $this->flash(__('The user has been saved.'), array('action' => 'index'));
}
$this->Session->setFlash(
@ -76,7 +111,14 @@ class UsersController extends AppController {
public function edit($id = null) {
$this->User->id = $id;
if (!$this->User->exists($id)) {
global $user;
$canEdit = ($user['System'] == 'Edit') or (($user['Id'] == $id) and ZM_USER_SELF_EDIT);
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
if ( !$this->User->exists($id) ) {
throw new NotFoundException(__('Invalid user'));
}
@ -87,8 +129,10 @@ class UsersController extends AppController {
$message = 'Error';
}
} else {
# What is this doing? Resetting the request data? I understand clearing the password field
# but generally I feel like the request data should be read only
$this->request->data = $this->User->read(null, $id);
unset($this->request->data['User']['password']);
unset($this->request->data['User']['Password']);
}
$this->set(array(
@ -106,6 +150,13 @@ class UsersController extends AppController {
*/
public function delete($id = null) {
$this->User->id = $id;
global $user;
# Can't delete ourselves
if ( ($user['System'] != 'Edit') or ($user['Id'] == $id) ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
if ( !$this->User->exists() ) {
throw new NotFoundException(__('Invalid user'));
}
@ -120,35 +171,4 @@ class UsersController extends AppController {
'_serialize' => array('message')
));
}
public function beforeFilter() {
parent::beforeFilter();
if ( ZM_OPT_USE_AUTH ) {
$this->Auth->allow('add', 'logout');
} else {
$this->Auth->allow();
}
}
public function login() {
if ( !ZM_OPT_USE_AUTH ) {
$this->set(array(
'message' => 'Login is not required.',
'_serialize' => array('message')
));
return;
}
if ( $this->request->is('post') ) {
if ( $this->Auth->login() ) {
return $this->redirect($this->Auth->redirectUrl());
}
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
public function logout() {
return $this->redirect($this->Auth->logout());
}
}
} # end class UsersController

View File

@ -21,6 +21,20 @@ class User extends AppModel {
)
);
function beforeFind($query) {
if ( empty($query['fields']) ) {
$schema = $this->schema();
unset($schema['Password']);
foreach (array_keys($schema) as $field) {
$query['fields'][] = $this->alias . '.' . $field;
}
return $query;
}
return parent::beforeFind($query);
}
/**
* Use table
*

10
web/css/bootstrap-table.min.css vendored Normal file

File diff suppressed because one or more lines are too long

4
web/css/font-awesome.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -106,7 +106,7 @@ if ( ! is_dir("skins/$skin") ) {
$skin = $skins[0];
}
}
global $css;
if ( isset($_GET['css']) ) {
$css = $_GET['css'];
} else if ( isset($_COOKIE['zmCSS']) ) {

View File

@ -576,6 +576,13 @@ input[type=submit],
text-align: center;
}
.btn-normal,
.btn-normal:link {
color: #fff;
background-color: #3498db;
border: 1px solid #3498db;
}
button:hover,
input[type=button]:hover,
input[type=submit]:hover,
@ -701,6 +708,10 @@ li.search-choice {
.gi-4x{font-size: 4em;}
.gi-5x{font-size: 5em;}
.fa:hover{
color: black;
}
.filterBar {
margin-top:5px;
margin-bottom:5px;
@ -713,7 +724,11 @@ li.search-choice {
#dropdown_storage+div,
#dropdown_reminder+div,
#dropdown_bandwidth+div {
background-color:#485460;
background-color:#485460;
}
#framesTable td:hover {
cursor: pointer;
}
.zoom {
@ -723,6 +738,7 @@ background-color:#485460;
}
.zoom:hover {
transform: scale(5); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
transform-origin: 70% 50%;
transform: scale(5); /* (arbitray zoom value - Note if the zoom is too large, it will go outside of the viewport) */
}

View File

@ -1,5 +1,5 @@
.archived {
background-color: #f8f8f8;;
background-color: #ffc107;;
}
#contentTable.major .colTime {

View File

@ -27,6 +27,7 @@ function exportHeader($title) {
<title><?php echo $title ?></title>
<style>
<?php
global $css;
include(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/css/base/export.css');
if ( $css != 'base' ) {
include(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/css/'.$css.'/export.css');

View File

@ -85,7 +85,9 @@ if ( file_exists("skins/$skin/css/$css/graphics/favicon.ico") ) {
echo output_cache_busted_stylesheet_links(array(
'css/reset.css',
'css/overlay.css',
'css/font-awesome.min.css',
'css/bootstrap.min.css',
'css/bootstrap-table.min.css',
));
echo output_link_if_exists(array(
@ -130,6 +132,8 @@ if ( $css != 'base' )
<script src="skins/<?php echo $skin; ?>/js/jquery.js"></script>
<script src="skins/<?php echo $skin; ?>/js/jquery-ui-1.12.1/jquery-ui.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap-table.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap-table-cookie.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/chosen/chosen.jquery.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/dateTimePicker/jquery-ui-timepicker-addon.js"></script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -646,6 +646,17 @@ function setCookie(name, value, days) {
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i=0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
function delCookie(name) {
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}

View File

@ -106,51 +106,45 @@ xhtmlHeaders(__FILE__, translate('Events') );
<body>
<div id="page">
<?php echo getNavBarHTML() ?>
<div id="header">
<div id="info">
<h2><?php echo sprintf($CLANG['EventCount'], $nEvents, zmVlang($VLANG['Event'], $nEvents)) ?></h2>
<a href="?view=filter<?php echo $filterQuery ?>"><?php echo translate('Filter')?></a>
<a id="refreshLink" href="#"><?php echo translate('Refresh') ?></a>
</div>
<div id="pagination">
<?php
if ( $pagination ) {
?>
<h2 class="pagination hidden-xs"><?php echo $pagination ?></h2>
<?php
}
?>
<?php
if ( $pages > 1 ) {
if ( !empty($page) ) {
?>
<a href="?view=<?php echo $view ?>&amp;page=0<?php echo $filterQuery.$sortQuery.$limitQuery ?>"><?php echo translate('ViewAll') ?></a>
<?php
} else {
?>
<a href="?view=<?php echo $view ?>&amp;page=1<?php echo $filterQuery.$sortQuery.$limitQuery ?>"><?php echo translate('ViewPaged') ?></a>
<?php
}
}
?>
</div>
<div id="controls">
<a href="#" id="backLink"><?php echo translate('Back') ?></a>
<a id="timelineLink" href="?view=timeline<?php echo $filter->query() ?>"><?php echo translate('ShowTimeline') ?></a>
</div>
<!-- Toolbar button placement and styling handled by bootstrap-tables -->
<div id="toolbar">
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
<button id="tlineBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('ShowTimeline') ?>" ><i class="fa fa-history"></i></button>
<button id="viewBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('View') ?>" disabled><i class="fa fa-binoculars"></i></button>
<button id="archiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Archive') ?>" disabled><i class="fa fa-archive"></i></button>
<button id="unarchiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Unarchive') ?>" disabled><i class="fa fa-file-archive-o"></i></button>
<button id="editBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Edit') ?>" disabled><i class="fa fa-pencil"></i></button>
<button id="exportBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Export') ?>" disabled><i class="fa fa-external-link"></i></button>
<button id="downloadBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('DownloadVideo') ?>" disabled><i class="fa fa-download"></i></button>
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
</div>
<div id="content">
<form name="contentForm" id="contentForm" method="post" action="">
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value=""/>
<input type="hidden" name="page" value="<?php echo $page ?>"/>
<?php echo $filter->fields() ?>
<input type="hidden" name="sort_field" value="<?php echo validHtmlStr($_REQUEST['sort_field']) ?>"/>
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
<input type="hidden" name="limit" value="<?php echo $limit ?>"/>
<div class="table-responsive-sm">
<table id="contentTable" class="major">
<tbody>
<!-- Table styling handled by bootstrap-tables -->
<div class="table-responsive-sm p-3">
<table
id="eventTable"
data-toggle="table"
data-pagination="true"
data-show-pagination-switch="true"
data-page-list="[10, 25, 50, 100, 200, All]"
data-search="true"
data-cookie="true"
data-cookie-id-table="zmEventsTable"
data-cookie-expire="2y"
data-click-to-select="true"
data-remember-order="true"
data-show-columns="true"
data-uncheckAll="true"
data-toolbar="#toolbar"
data-show-fullscreen="true"
data-click-to-select="true"
data-maintain-meta-data="true"
data-mobile-responsive="true"
data-buttons-class="btn btn-normal"
class="table-sm table-borderless">
<thead>
<?php
$count = 0;
$disk_space_total = 0;
@ -158,49 +152,51 @@ $disk_space_total = 0;
$results = dbQuery($eventsSql);
while ( $event_row = dbFetchNext($results) ) {
$event = new ZM\Event($event_row);
if ( $event_row['Archived'] )
$archived = true;
else
$unarchived = true;
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 ) {
?>
<!-- Row styling is handled by bootstrap-tables -->
<tr>
<th class="colId"><a href="<?php echo sortHeader('Id') ?>"><?php echo translate('Id') ?><?php echo sortTag('Id') ?></a></th>
<th class="colName px-1"><a href="<?php echo sortHeader('Name') ?>"><?php echo translate('Name') ?><?php echo sortTag('Name') ?></a></th>
<th class="colMonitor px-1"><a href="<?php echo sortHeader('MonitorName') ?>"><?php echo translate('Monitor') ?><?php echo sortTag('MonitorName') ?></a></th>
<th class="colCause px-1"><a href="<?php echo sortHeader('Cause') ?>"><?php echo translate('Cause') ?><?php echo sortTag('Cause') ?></a></th>
<th class="colStartTime px-1"><a href="<?php echo sortHeader('StartTime') ?>"><?php echo translate('AttrStartTime') ?><?php echo sortTag('StartTime') ?></a></th>
<th class="colEndTime px-1"><a href="<?php echo sortHeader('EndTime') ?>"><?php echo translate('AttrEndTime') ?><?php echo sortTag('EndTime') ?></a></th>
<th class="colDuration px-1"><a href="<?php echo sortHeader('Length') ?>"><?php echo translate('Duration') ?><?php echo sortTag('Length') ?></a></th>
<th class="colFrames px-1"><a href="<?php echo sortHeader('Frames') ?>"><?php echo translate('Frames') ?><?php echo sortTag('Frames') ?></a></th>
<th class="colAlarmFrames px-1"><a href="<?php echo sortHeader('AlarmFrames') ?>"><?php echo translate('AlarmBrFrames') ?><?php echo sortTag('AlarmFrames') ?></a></th>
<th class="colTotScore px-1"><a href="<?php echo sortHeader('TotScore') ?>"><?php echo translate('TotalBrScore') ?><?php echo sortTag('TotScore') ?></a></th>
<th class="colAvgScore px-1"><a href="<?php echo sortHeader('AvgScore') ?>"><?php echo translate('AvgBrScore') ?><?php echo sortTag('AvgScore') ?></a></th>
<th class="colMaxScore px-1"><a href="<?php echo sortHeader('MaxScore') ?>"><?php echo translate('MaxBrScore') ?><?php echo sortTag('MaxScore') ?></a></th>
<th data-sortable="false" data-field="toggleCheck" data-checkbox="true"></th>
<th data-sortable="true" data-field="Id"><?php echo translate('Id') ?></th>
<th data-sortable="true" data-field="Name"><?php echo translate('Name') ?></th>
<th data-sortable="true" data-field="Archived"><?php echo translate('Archived') ?></th>
<th data-sortable="true" data-field="Emailed"><?php echo translate('Emailed') ?></th>
<th data-sortable="true" data-field="Monitor"><?php echo translate('Monitor') ?></th>
<th data-sortable="true" data-field="Cause"><?php echo translate('Cause') ?></th>
<th data-sortable="true" data-field="AttrStartTime"><?php echo translate('AttrStartTime') ?></th>
<th data-sortable="true" data-field="AttrEndTime"><?php echo translate('AttrEndTime') ?></th>
<th data-sortable="true" data-field="Duration"><?php echo translate('Duration') ?></th>
<th data-sortable="true" data-field="Frames"><?php echo translate('Frames') ?></th>
<th data-sortable="true" data-field="AlarmBrFrames"><?php echo translate('AlarmBrFrames') ?></th>
<th data-sortable="true" data-field="TotalBrScore"><?php echo translate('TotalBrScore') ?></th>
<th data-sortable="true" data-field="AvgBrScore"><?php echo translate('AvgBrScore') ?></th>
<th data-sortable="true" data-field="MaxBrScore"><?php echo translate('MaxBrScore') ?></th>
<?php
if ( count($storage_areas) > 1 ) {
?>
<th class="colStorage px-1"><?php echo translate('Storage') ?></th>
<th data-sortable="true" data-field="Storage"><?php echo translate('Storage') ?></th>
<?php
}
if ( ZM_WEB_EVENT_DISK_SPACE ) {
?>
<th class="colDiskSpace px-1"><a href="<?php echo sortHeader('DiskSpace') ?>"><?php echo translate('DiskSpace') ?><?php echo sortTag('DiskSpace') ?></a></th>
<th data-sortable="true" data-field="DiskSpace"><?php echo translate('DiskSpace') ?></th>
<?php
}
if ( ZM_WEB_LIST_THUMBS ) {
?>
<th class="colThumbnail px-1"><?php echo translate('Thumbnail') ?></th>
<th data-sortable="false" data-field="Thumbnail"><?php echo translate('Thumbnail') ?></th>
<?php
}
?>
<th class="colMark px-1"><input type="checkbox" name="toggleCheck" value="1" data-checkbox-name="eids[]" data-on-click-this="updateFormCheckboxesByName"/></th>
</tr>
</thead>
<tbody>
<?php
}
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
?>
<<<<<<< HEAD
<tr<?php if ($event->Archived()) echo ' class="archived"' ?>>
<td class="colId"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$event->Id().($event->Archived()?'*':'') ?></a></td>
<td class="colName px-1"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a><br/>
@ -225,26 +221,55 @@ while ( $event_row = dbFetchNext($results) ) {
}
}
?>
=======
<tr<?php echo ( $event->Archived() ) ? ' class="archived"' : '' ?>>
<td data-checkbox="true"></td>
<td><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$event->Id() ?></a></td>
<td><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.validHtmlStr($event->Name())?></a>
<?php
$archived = ( $event->Archived() ) ? translate('Archived') : '';
$emailed = ( $event->Emailed() ) ? ' '.translate('Emailed') : '';
echo '<br/><div class="small text-nowrap text-muted">'.$archived.$emailed.'</div>';
?>
>>>>>>> bec77c9ce3b185ba3055e23cbba88d9c420c66c7
</td>
<td class="colTime text-wrap px-1"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td>
<td class="colTime text-wrap px-1"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) ?></td>
<td class="colDuration px-1"><?php echo gmdate("H:i:s", $event->Length() ) ?></td>
<td class="colFrames px-1"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->Frames() ) ?></td>
<td class="colAlarmFrames px-1"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->AlarmFrames() ) ?></td>
<td class="colTotScore px-1"><?php echo $event->TotScore() ?></td>
<td class="colAvgScore px-1"><?php echo $event->AvgScore() ?></td>
<td class="colMaxScore px-1"><?php echo makePopupLink(
<td class="text-center"><?php echo ( $event->Archived() ) ? 'Yes' : 'No' ?></td>
<td class="text-center"><?php echo ( $event->Emailed() ) ? 'Yes' : 'No' ?></td>
<td><?php echo makePopupLink( '?view=monitor&amp;mid='.$event->MonitorId(), 'zmMonitor'.$event->MonitorId(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
<td><?php echo makePopupLink( '?view=eventdetail&amp;eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?>
<?php
# display notes as small text
if ( $event->Notes() ) {
# if notes include detection objects, then link it to objdetect.jpg
if ( strpos($event->Notes(), 'detected:') !== false ) {
# make a link
echo makePopupLink( '?view=image&amp;eid='.$event->Id().'&amp;fid=objdetect', 'zmImage',
array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)),
'<div class="small text-nowrap text-muted"><u>'.$event->Notes().'</u></div>');
} else if ( $event->Notes() != 'Forced Web: ' ) {
echo '<br/><div class="small text-nowrap text-muted">'.$event->Notes().'</div>';
}
}
?>
</td>
<td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td>
<td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) ?></td>
<td><?php echo gmdate("H:i:s", $event->Length() ) ?></td>
<td><a href="?view=frames&amp;eid=<?php echo $event->Id() ?>"><?php echo $event->Frames() ?></a></td>
<td><a href="?view=frames&amp;eid=<?php echo $event->Id() ?>"><?php echo $event->AlarmFrames() ?></a></td>
<td><?php echo $event->TotScore() ?></td>
<td><?php echo $event->AvgScore() ?></td>
<td><?php echo makePopupLink(
'?view=frame&amp;eid='.$event->Id().'&amp;fid=0', 'zmImage',
array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)), $event->MaxScore()
); ?></td>
<?php
if ( count($storage_areas) > 1 ) {
?>
<td class="colStorage px-1">
<td>
<?php
if ( $event->StorageId() ) {
echo isset($StorageById[$event->StorageId()]) ? $StorageById[$event->StorageId()]->Name() : 'Unknown Storage Id: '.$event->StorageId();
@ -262,11 +287,11 @@ while ( $event_row = dbFetchNext($results) ) {
if ( ZM_WEB_EVENT_DISK_SPACE ) {
$disk_space_total += $event->DiskSpace();
?>
<td class="colDiskSpace px-1"><?php echo human_filesize($event->DiskSpace()) ?></td>
<td class="colDiskSpace"><?php echo human_filesize($event->DiskSpace()) ?></td>
<?php
}
if ( ZM_WEB_LIST_THUMBS ) {
echo '<td class="colThumbnail px-1 zoom">';
echo '<td class="colThumbnail zoom">';
$imgSrc = $event->getThumbnailSrc(array(),'&amp;');
$streamSrc = $event->getStreamSrc(array(
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&amp;');
@ -276,7 +301,6 @@ while ( $event_row = dbFetchNext($results) ) {
echo '</td>';
} // end if ZM_WEB_LIST_THUMBS
?>
<td class="colMark px-1"><input type="checkbox" name="eids[]" value="<?php echo $event->Id() ?>"/></td>
</tr>
<?php
}
@ -310,45 +334,29 @@ while ( $event_row = dbFetchNext($results) ) {
}
?>
</table>
</div>
<?php
if ( $pagination ) {
?>
<h3 class="pagination"><?php echo $pagination ?></h3>
<?php
}
?>
<div id="contentButtons">
<button type="button" name="viewBtn" value="View" data-on-click-this="viewEvents" disabled="disabled">
<?php echo translate('View') ?>
</button>
<button type="button" name="archiveBtn" value="Archive" data-on-click-this="archiveEvents" disabled="disabled">
<?php echo translate('Archive') ?>
</button>
<button type="button" name="unarchiveBtn" value="Unarchive" data-on-click-this="unarchiveEvents" disabled="disabled">
<?php echo translate('Unarchive') ?>
</button>
<button type="button" name="editBtn" value="Edit" data-on-click-this="editEvents" disabled="disabled">
<?php echo translate('Edit') ?>
</button>
<button type="button" name="exportBtn" value="Export" data-on-click-this="exportEvents" disabled="disabled">
<?php echo translate('Export') ?>
</button>
<button type="button" name="downloadBtn" value="DownloadVideo" data-on-click-this="downloadVideo" disabled="disabled">
<?php echo translate('DownloadVideo') ?>
</button>
<button type="button" name="deleteBtn" value="Delete" data-on-click-this="deleteEvents" disabled="disabled">
<?php echo translate('Delete') ?>
</button>
</div>
</form>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div id="deleteConfirm" class="modal fade" class="modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Confirmation</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p><?php echo translate('ConfirmDeleteEvents') ?></p>
</div>
<div class="modal-footer">
<button id="delCancelBtn" type="button" class="btn btn-secondary" data-dismiss="modal"><?php echo translate('Cancel') ?></button>
<button id ="delConfirmBtn" type="button" class="btn btn-danger"><?php echo translate('Delete') ?></button>
</div>
</div>
</div>
<script nonce="<?php echo $cspNonce;?>">
// These are defined in the .js.php but need to be updated down here.
// This might be better done by selecting through the dom for the archived class
archivedEvents = <?php echo !empty($archived)?'true':'false' ?>;
unarchivedEvents = <?php echo !empty($unarchived)?'true':'false' ?>;
</script>
</div>
</body>
</html>

View File

@ -86,6 +86,7 @@ xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id().' - '.$Frame->Frame
?>
<body>
<div id="page">
<?php echo getNavBarHTML() ?>
<div id="header">
<form>
<div id="headerButtons">

View File

@ -109,100 +109,78 @@ $focusWindow = true;
xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id());
?>
<body>
<div id="page">
<div id="header">
<div id="headerButtons"><a href="#" data-on-click="closeWindow"><?php echo translate('Close') ?></a></div>
<h2><?php echo translate('Frames') ?> - <?php echo $Event->Id() ?></h2>
<div id="pagination">
<?php
if ( $pagination ) {
?>
<h2 class="pagination"><?php echo $pagination ?></h2>
<?php
}
?>
<?php
if ( $pages > 1 ) {
if ( !empty($page) ) {
?>
<a href="?view=<?php echo $view ?>&amp;page=0<?php echo $totalQuery ?>"><?php echo translate('ViewAll') ?></a>
<?php
} else {
?>
<a href="?view=<?php echo $view ?>&amp;page=1<?php echo $totalQuery ?>"><?php echo translate('ViewPaged') ?></a>
<?php
}
}
?>
</div>
<div id="page" class="container-fluid p-0">
<?php echo getNavBarHTML() ?>
<!-- Toolbar button placement and styling handled by bootstrap-tables -->
<div id="toolbar">
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
</div>
<div id="content">
<form name="contentForm" id="contentForm" method="get" action="?">
<input type="hidden" name="view" value="none"/>
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value=""/>
<input type="hidden" name="page" value="<?php echo $page ?>"/>
<input type="hidden" name="eid" value="<?php echo $eid ?>"/>
<?php echo $_REQUEST['filter']['fields'] ?>
<input type="hidden" name="sort_field" value="<?php echo validHtmlStr($_REQUEST['sort_field']) ?>"/>
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
<input type="hidden" name="limit" value="<?php echo $limit ?>"/>
<table id="contentTable" class="major">
<thead>
<tr>
<th class="colId"><a href="<?php echo sortHeader('FramesFrameId') ?>"><?php echo translate('Frame Id') ?><?php echo sortTag('FramesFrameId') ?></a></th>
<th class="colType"><a href="<?php echo sortHeader('FramesType') ?>"><?php echo translate('Type') ?><?php echo sortTag('FramesType') ?></a></th>
<th class="colTimeStamp"><a href="<?php echo sortHeader('FramesTimeStamp') ?>"><?php echo translate('TimeStamp') ?><?php echo sortTag('FramesTimeStamp') ?></a></th>
<th class="colTimeDelta"><a href="<?php echo sortHeader('FramesDelta') ?>"><?php echo translate('TimeDelta') ?><?php echo sortTag('FramesDelta') ?></a></th>
<th class="colScore"><a href="<?php echo sortHeader('FramesScore') ?>"><?php echo translate('Score') ?><?php echo sortTag('FramesScore') ?></a></th>
<!-- Table styling handled by bootstrap-tables -->
<div class="row justify-content-center">
<table
id="framesTable"
data-toggle="table"
data-pagination="true"
data-show-pagination-switch="true"
data-page-list="[10, 25, 50, 100, 200, All]"
data-search="true"
data-cookie="true"
data-cookie-id-table="zmFramesTable"
data-cookie-expire="2y"
data-remember-order="true"
data-show-columns="true"
data-toolbar="#toolbar"
data-show-fullscreen="true"
data-maintain-meta-data="true"
data-mobile-responsive="true"
data-buttons-class="btn btn-normal"
class="table-sm table-borderless">
<thead>
<!-- Row styling is handled by bootstrap-tables -->
<tr>
<th data-align="center" data-sortable="false" data-field="EventId"><?php echo translate('EventId') ?></th>
<th data-align="center" data-sortable="true" data-field="FramesId"><?php echo translate('FrameId') ?></th>
<th data-align="center" data-sortable="true" data-field="FramesType"><?php echo translate('Type') ?></th>
<th data-align="center" data-sortable="true" data-field="FramesTimeStamp"><?php echo translate('TimeStamp') ?></th>
<th data-align="center" data-sortable="true" data-field="FramesDelta"><?php echo translate('TimeDelta') ?></th>
<th data-align="center" data-sortable="true" data-field="FramesScore"><?php echo translate('Score') ?></th>
<?php
if ( ZM_WEB_LIST_THUMBS ) {
?>
<th class="colThumbnail"><?php echo translate('Thumbnail') ?></th>
<th data-align="center" data-sortable="false" data-field="Thumbnail"><?php echo translate('Thumbnail') ?></th>
<?php
}
?>
</tr>
</thead>
<tbody>
</tr>
</thead>
<tbody>
<?php
if ( count($frames) ) {
foreach ( $frames as $frame ) {
$Frame = new ZM\Frame($frame);
$class = strtolower($frame['Type']);
?>
<tr class="<?php echo $class ?>">
<td class="colId"><?php echo makePopupLink(
'?view=frame&amp;eid='.$Event->Id().'&amp;fid='.$frame['FrameId'], 'zmImage',
array(
'frame',
($scale ? $Event->Width()*$scale/100 : $Event->Width()),
($scale ? $Event->Height()*$scale/100 : $Event->Height())
),
$frame['FrameId'])
?></td>
<td class="colType"><?php echo $frame['Type'] ?></td>
<td class="colTimeStamp"><?php echo strftime(STRF_FMT_TIME, $frame['UnixTimeStamp']) ?></td>
<td class="colTimeDelta"><?php echo number_format( $frame['Delta'], 2 ) ?></td>
<tr<?php echo ( strtolower($frame['Type']) == "alarm" ) ? ' class="alarm"' : '' ?>>
<td><?php echo $frame['EventId'] ?></td>
<td><?php echo $frame['FrameId'] ?></td>
<td><?php echo $frame['Type'] ?></td>
<td><?php echo strftime(STRF_FMT_TIME, $frame['UnixTimeStamp']) ?></td>
<td><?php echo number_format( $frame['Delta'], 2 ) ?></td>
<td><?php echo $frame['Score'] ?></td>
<?php
if ( ZM_RECORD_EVENT_STATS && ($frame['Type'] == 'Alarm') ) {
?>
<td class="colScore"><?php echo makePopupLink('?view=stats&amp;eid='.$Event->Id().'&amp;fid='.$frame['FrameId'], 'zmStats', 'stats', $frame['Score']) ?></td>
<?php
} else {
?>
<td class="colScore"><?php echo $frame['Score'] ?></td>
<?php
}
if ( ZM_WEB_LIST_THUMBS ) {
?>
<td class="colThumbnail"><?php echo makePopupLink( '?view=frame&amp;eid='.$Event->Id().'&amp;fid='.$frame['FrameId'], 'zmImage', array('image', $Event->Width(), $Event->Height()), '<img src="?view=image&amp;fid='.$Frame->Id().'&amp;'.
(ZM_WEB_LIST_THUMB_WIDTH?'width='.ZM_WEB_LIST_THUMB_WIDTH.'&amp;':'').
(ZM_WEB_LIST_THUMB_HEIGHT?'height='.ZM_WEB_LIST_THUMB_HEIGHT.'&amp;':'').'filename='.$Event->MonitorId().'_'.$frame['EventId'].'_'.$frame['FrameId'].'.jpg" '.
(ZM_WEB_LIST_THUMB_WIDTH?'width="'.ZM_WEB_LIST_THUMB_WIDTH.'" ':'').
(ZM_WEB_LIST_THUMB_HEIGHT?'height="'.ZM_WEB_LIST_THUMB_HEIGHT.'" ':'').' alt="'.$frame['FrameId'].'"/>' ) ?></td>
<?php
$base_img_src = '?view=image&amp;fid=' .$Frame->Id();
$thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : '';
$thmb_height = ZM_WEB_LIST_THUMB_HEIGHT ? 'height='.ZM_WEB_LIST_THUMB_HEIGHT : '';
$thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$frame['EventId']. '_' .$frame['FrameId']. '.jpg';
$img_src = join('&amp;', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn)));
$full_img_src = join('&amp;', array_filter(array($base_img_src, $thmb_fn)));
$frame_src = '?view=frame&amp;eid=' .$Event->Id(). '&amp;fid=' .$frame['FrameId'];
echo '<td class="colThumbnail zoom"><img src="' .$img_src. '" '.$thmb_width. ' ' .$thmb_height. 'img_src="' .$img_src. '" full_img_src="' .$full_img_src. '"></td>'.PHP_EOL;
}
?>
</tr>
@ -218,19 +196,7 @@ if ( count($frames) ) {
?>
</tbody>
</table>
<?php
if ( $pagination ) {
?>
<h3 class="pagination"><?php echo $pagination ?></h3>
<?php
}
?>
<div id="contentButtons">
</div>
</form>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,16 +1,19 @@
<?php
if ( isset($_REQUEST['eids']) ) {
$eidParms = array();
foreach ( $_REQUEST['eids'] as $eid )
$eidParms[] = 'eids[]='.validInt($eid);
global $connkey;
global $exportFormat;
if ( isset($_REQUEST['eids']) ) {
$eidParms = array();
foreach ( $_REQUEST['eids'] as $eid )
$eidParms[] = 'eids[]='.validInt($eid);
?>
var eidParm = '<?php echo join('&', $eidParms) ?>';
<?php
} else if (isset($_REQUEST['eid'])) {
} else if (isset($_REQUEST['eid'])) {
?>
var eidParm = 'eid=<?php echo validInt($_REQUEST['eid']) ?>';
<?php
}
}
?>
var exportReady = <?php echo !empty($_REQUEST['generated'])?'true':'false' ?>;

View File

@ -1,179 +1,212 @@
function closeWindows() {
window.close();
// This is a hack. The only way to close an existing window is to try and open it!
var filterWindow = window.open( thisUrl+'?view=none', 'zmFilter', 'width=1,height=1' );
filterWindow.close();
}
function setButtonStates( element ) {
var form = element.form;
var checked = element.checked;
form.viewBtn.disabled = !(canViewEvents && checked);
form.editBtn.disabled = !(canEditEvents && checked);
form.archiveBtn.disabled = unarchivedEvents?!checked:true;
form.unarchiveBtn.disabled = !(canEditEvents && archivedEvents && checked);
form.downloadBtn.disabled = !(canViewEvents && checked);
form.exportBtn.disabled = !(canViewEvents && checked);
form.deleteBtn.disabled = !(canEditEvents && checked);
}
function configureButton(event) {
var element = event.target;
var form = element.form;
var checked = element.checked;
if ( !checked ) {
for (var i = 0, len=form.elements.length; i < len; i++) {
if ( form.elements[i].name.indexOf('eids') == 0) {
if ( form.elements[i].checked ) {
checked = true;
break;
}
}
}
}
if ( !element.checked ) {
form.toggleCheck.checked = false;
}
form.viewBtn.disabled = !(canViewEvents && checked);
form.editBtn.disabled = !(canEditEvents && checked);
form.archiveBtn.disabled = (!checked)||(!unarchivedEvents);
form.unarchiveBtn.disabled = !(canEditEvents && checked && archivedEvents);
form.downloadBtn.disabled = !(canViewEvents && checked);
form.exportBtn.disabled = !(canViewEvents && checked);
form.deleteBtn.disabled = !(canEditEvents && checked);
}
function deleteEvents( element ) {
if ( ! canEditEvents ) {
alert("You do not have permission to delete events.");
return;
}
var form = element.form;
var count = 0;
// This is slightly more efficient than a jquery selector because we stop after finding one.
for (var i = 0; i < form.elements.length; i++) {
if (form.elements[i].name.indexOf('eids') == 0) {
if ( form.elements[i].checked ) {
count++;
break;
}
}
}
if ( count > 0 ) {
if ( confirm(confirmDeleteEventsString) ) {
form.elements['action'].value = 'delete';
form.submit();
}
}
}
function editEvents( element ) {
if ( ! canEditEvents ) {
alert("You do not have permission to delete events.");
return;
}
var form = element.form;
var eids = new Array();
for (var i = 0, len=form.elements.length; i < len; i++) {
if (form.elements[i].name.indexOf('eids') == 0) {
if ( form.elements[i].checked ) {
eids[eids.length] = 'eids[]='+form.elements[i].value;
}
}
}
createPopup('?view=eventdetail&'+eids.join('&'), 'zmEventDetail', 'eventdetail');
}
function downloadVideo( element ) {
var form = element.form;
var eids = new Array();
for (var i = 0, len=form.elements.length; i < len; i++) {
if (form.elements[i].name.indexOf('eids') == 0 ) {
if ( form.elements[i].checked ) {
eids[eids.length] = 'eids[]='+form.elements[i].value;
}
}
}
createPopup( '?view=download&'+eids.join('&'), 'zmDownload', 'download' );
}
function exportEvents( element ) {
var form = element.form;
console.log(form);
form.action = '?view=export';
form.elements['view'].value='export';
form.submit();
}
function viewEvents( element ) {
var form = element.form;
var events = new Array();
for (var i = 0, len=form.elements.length; i < len; i++) {
if ( form.elements[i].name.indexOf('eids') == 0 ) {
if ( form.elements[i].checked ) {
events[events.length] = form.elements[i].value;
}
}
}
if ( events.length > 0 ) {
var filter = '&filter[Query][terms][0][attr]=Id&filter[Query][terms][0][op]=%3D%5B%5D&filter[Query][terms][0][val]='+events.join('%2C');
window.location.href = thisUrl+'?view=event&eid='+events[0]+filter+sortQuery+'&page=1&play=1';
}
}
function archiveEvents(element) {
var form = element.form;
form.elements['action'].value = 'archive';
form.submit();
}
function unarchiveEvents(element) {
if ( ! canEditEvents ) {
alert("You do not have permission to delete events.");
return;
}
var form = element.form;
form.elements['action'].value = 'unarchive';
form.submit();
}
if ( openFilterWindow ) {
//opener.location.reload(true);
createPopup( '?view=filter&page='+thisPage+filterQuery, 'zmFilter', 'filter' );
location.replace( '?view='+currentView+'&page='+thisPage+filterQuery );
}
function thumbnail_onmouseover(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('stream_src');
}
function thumbnail_onmouseout(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('still_src');
}
function initPage() {
if ( window.history.length == 1 ) {
$j('#controls').children().eq(0).html('');
}
function initThumbAnimation() {
$j('.colThumbnail img').each(function() {
this.addEventListener('mouseover', thumbnail_onmouseover, false);
this.addEventListener('mouseout', thumbnail_onmouseout, false);
});
$j('input[name=eids\\[\\]]').each(function() {
this.addEventListener('click', configureButton, false);
});
document.getElementById("refreshLink").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
document.getElementById("backLink").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
}
// Returns the event id's of the selected rows
function getIdSelections() {
var table = $j('#eventTable');
return $j.map(table.bootstrapTable('getSelections'), function(row) {
return row.Id.replace(/(<([^>]+)>)/gi, ""); // strip the html from the element before sending
});
}
$j(document).ready(initPage);
// Returns a boolen to indicate at least one selected row is archived
function getArchivedSelections() {
var table = $j('#eventTable');
var selection = $j.map(table.bootstrapTable('getSelections'), function(row) {
return row.Archived;
});
return selection.includes("Yes");
}
function initPage() {
var backBtn = $j('#backBtn');
var viewBtn = $j('#viewBtn');
var archiveBtn = $j('#archiveBtn');
var unarchiveBtn = $j('#unarchiveBtn');
var editBtn = $j('#editBtn');
var exportBtn = $j('#exportBtn');
var downloadBtn = $j('#downloadBtn');
var deleteBtn = $j('#deleteBtn');
var table = $j('#eventTable');
// Define the icons used in the bootstrap-table top-right toolbar
var icons = {
paginationSwitchDown: 'fa-caret-square-o-down',
paginationSwitchUp: 'fa-caret-square-o-up',
refresh: 'fa-sync',
toggleOff: 'fa-toggle-off',
toggleOn: 'fa-toggle-on',
columns: 'fa-th-list',
fullscreen: 'fa-arrows-alt',
detailOpen: 'fa-plus',
detailClose: 'fa-minus'
};
// Init the bootstrap-table
table.bootstrapTable('destroy').bootstrapTable({icons: icons});
// Hide these columns on first run when no cookie is saved
if ( !getCookie("zmEventsTable.bs.table.columns") ) {
table.bootstrapTable('hideColumn', 'Archived');
table.bootstrapTable('hideColumn', 'Emailed');
}
// enable or disable buttons based on current selection and user rights
table.on('check.bs.table uncheck.bs.table ' +
'check-all.bs.table uncheck-all.bs.table',
function() {
viewBtn.prop('disabled', !(table.bootstrapTable('getSelections').length && canViewEvents));
archiveBtn.prop('disabled', !(table.bootstrapTable('getSelections').length && canEditEvents));
unarchiveBtn.prop('disabled', !(getArchivedSelections()) && canEditEvents);
editBtn.prop('disabled', !(table.bootstrapTable('getSelections').length && canEditEvents));
exportBtn.prop('disabled', !(table.bootstrapTable('getSelections').length && canViewEvents));
downloadBtn.prop('disabled', !(table.bootstrapTable('getSelections').length && canViewEvents));
deleteBtn.prop('disabled', !(table.bootstrapTable('getSelections').length && canEditEvents));
});
// Don't enable the back button if there is no previous zm page to go back to
backBtn.prop('disabled', !document.referrer.length);
// Setup the thumbnail video animation
initThumbAnimation();
// Some toolbar events break the thumbnail animation, so re-init eventlistener
table.on('all.bs.table', initThumbAnimation);
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
// Manage the TIMELINE Button
document.getElementById("tlineBtn").addEventListener("click", function onTlineClick(evt) {
evt.preventDefault();
window.location.assign('?view=timeline'+filterQuery);
});
// Manage the VIEW button
document.getElementById("viewBtn").addEventListener("click", function onViewClick(evt) {
var selections = getIdSelections();
evt.preventDefault();
var filter = '&filter[Query][terms][0][attr]=Id&filter[Query][terms][0][op]=%3D%5B%5D&filter[Query][terms][0][val]='+selections.join('%2C');
window.location.href = thisUrl+'?view=event&eid='+selections[0]+filter+sortQuery+'&page=1&play=1';
});
// Manage the ARCHIVE button
document.getElementById("archiveBtn").addEventListener("click", function onArchiveClick(evt) {
var selections = getIdSelections();
evt.preventDefault();
$j.getJSON(thisUrl + '?view=events&action=archive&eids[]='+selections.join('&eids[]='));
window.location.reload(true);
});
// Manage the UNARCHIVE button
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
if ( ! canEditEvents ) {
alert("You do not have permission to Unarchive events.");
return;
}
var selections = getIdSelections();
evt.preventDefault();
$j.getJSON(thisUrl + '?view=events&action=unarchive&eids[]='+selections.join('&eids[]='));
if ( openFilterWindow ) {
//opener.location.reload(true);
createPopup( '?view=filter&page='+thisPage+filterQuery, 'zmFilter', 'filter' );
location.replace( '?view='+currentView+'&page='+thisPage+filterQuery );
} else {
window.location.reload(true);
}
});
// Manage the EDIT button
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
if ( ! canEditEvents ) {
alert("You do not have permission to edit events.");
return;
}
var selections = getIdSelections();
evt.preventDefault();
createPopup('?view=eventdetail&eids[]='+selections.join('&eids[]='), 'zmEventDetail', 'eventdetail');
});
// Manage the EXPORT button
document.getElementById("exportBtn").addEventListener("click", function onExportClick(evt) {
var selections = getIdSelections();
evt.preventDefault();
window.location.assign('?view=export&eids[]='+selections.join('&eids[]='));
});
// Manage the DOWNLOAD VIDEO button
document.getElementById("downloadBtn").addEventListener("click", function onDownloadClick(evt) {
var selections = getIdSelections();
evt.preventDefault();
createPopup('?view=download&eids[]='+selections.join('&eids[]='), 'zmDownload', 'download');
});
// Manage the DELETE button
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
if ( ! canEditEvents ) {
alert("You do not have permission to delete events.");
return;
}
evt.preventDefault();
$j('#deleteConfirm').modal('show');
});
// Manage the DELETE CONFIRMATION modal button
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
if ( ! canEditEvents ) {
alert("You do not have permission to delete events.");
return;
}
var selections = getIdSelections();
evt.preventDefault();
$j.getJSON(thisUrl + '?view=events&action=delete&eids[]='+selections.join('&eids[]='));
window.location.reload(true);
});
// Manage the CANCEL modal button
document.getElementById("delCancelBtn").addEventListener("click", function onDelCancelClick(evt) {
$j('#deleteConfirm').modal('hide');
});
}
$j(document).ready(function() {
initPage();
});

View File

@ -1,9 +1,6 @@
//var openFilterWindow = <?php echo $_REQUEST['filter']?'true':'false' ?>;
var openFilterWindow = false;
var archivedEvents = <?php echo !empty($archived)?'true':'false' ?>;
var unarchivedEvents = <?php echo !empty($unarchived)?'true':'false' ?>;
var filterQuery = '<?php echo isset($filterQuery)?validJsStr(htmlspecialchars_decode($filterQuery)):'' ?>';
var sortQuery = '<?php echo isset($sortQuery)?validJsStr(htmlspecialchars_decode($sortQuery)):'' ?>';

View File

@ -7,7 +7,7 @@ function validateForm( form ) {
var obrCount = 0;
var cbrCount = 0;
for ( var i = 0; i < rows.length; i++ ) {
if (rows.length > 2) {
if ( rows.length > 2 ) {
obrCount += parseInt(form.elements['filter[Query][terms][' + i + '][obr]'].value);
cbrCount += parseInt(form.elements['filter[Query][terms][' + i + '][cbr]'].value);
}
@ -22,9 +22,53 @@ function validateForm( form ) {
}
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.");
alert('There appear to be non-numeric characters in your limit. Limit must be a positive integer value or empty.');
return false;
}
if ( form.elements['filter[AutoDelete]'].checked ) {
// if Delete action is Enabled should also have an unarchived term
var have_archivestatus_term = false;
for ( var i = 0; i < rows.length; i++ ) {
if ( form.elements['filter[Query][terms][' + i + '][attr]'].value == 'Archived' ) {
have_archivestatus_term = true;
}
}
if ( ! have_archivestatus_term ) {
return confirm('You have enabled deleting events but do not have a term referencing the archived status of the event. This filter may delete events that you want to save! Are you sure?');
}
} else if ( form.elements['filter[UpdateDiskSpace]'].checked ) {
var have_endtime_term = false;
for ( var i = 0; i < rows.length; i++ ) {
if ( form.elements['filter[Query][terms][' + i + '][attr]'].value == 'EndDateTime' ) {
have_endtime_term = true;
}
}
if ( ! have_endtime_term ) {
return confirm('You don\'t have an EndTime term in your filter. This will match recordings that are still in progress and so the UpdateDiskSpace action will be a waste of time and resources. Ideally you should have an EndTime IS NOT NULL term. Do you want to continue?');
}
} else if ( form.elements['filter[Background]'].checked ) {
if ( ! (
form.elements['filter[AutoArchive]'].checked
||
form.elements['filter[UpdateDiskSpace]'].checked
||
form.elements['filter[AutoVideo]'].checked
||
form.elements['filter[AutoEmail]'].checked
||
form.elements['filter[AutoMessage]'].checked
||
form.elements['filter[AutoExecute]'].checked
||
form.elements['filter[AutoDelete]'].checked
||
form.elements['filter[AutoCopy]'].checked
||
form.elements['filter[AutoMove]'].checked
) ) {
alert('You have chosen to run this filter in the background but not selected any actions.');
}
}
return true;
}

View File

@ -1,3 +1,7 @@
<?php
global $scale;
?>
var scale = '<?php echo validJsStr($scale); ?>';
var SCALE_BASE = <?php echo SCALE_BASE ?>;

View File

@ -0,0 +1,83 @@
function thumbnail_onmouseover(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('full_img_src');
}
function thumbnail_onmouseout(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('img_src');
}
function initThumbAnimation() {
$j('.colThumbnail img').each(function() {
this.addEventListener('mouseover', thumbnail_onmouseover, false);
this.addEventListener('mouseout', thumbnail_onmouseout, false);
});
}
function processClicks(event, field, value, row, $element) {
if ( field == 'FramesScore' ) {
if ( value > 0 ) {
window.location.assign('?view=stats&eid='+row.EventId+'&fid='+row.FramesId);
} else {
alert("No statistics available");
}
} else {
window.location.assign('?view=frame&eid='+row.EventId+'&fid='+row.FramesId);
}
}
function initPage() {
var backBtn = $j('#backBtn');
var table = $j('#framesTable');
// Define the icons used in the bootstrap-table top-right toolbar
var icons = {
paginationSwitchDown: 'fa-caret-square-o-down',
paginationSwitchUp: 'fa-caret-square-o-up',
refresh: 'fa-sync',
toggleOff: 'fa-toggle-off',
toggleOn: 'fa-toggle-on',
columns: 'fa-th-list',
fullscreen: 'fa-arrows-alt',
detailOpen: 'fa-plus',
detailClose: 'fa-minus'
};
// Init the bootstrap-table
table.bootstrapTable('destroy').bootstrapTable({icons: icons});
// Hide these columns on first run when no cookie is saved
if ( !getCookie("zmFramesTable.bs.table.columns") ) {
table.bootstrapTable('hideColumn', 'FrameId');
}
// Disable the back button if there is nothing to go back to
backBtn.prop('disabled', !document.referrer.length);
// Setup the thumbnail animation
initThumbAnimation();
// Some toolbar events break the thumbnail animation, so re-init eventlistener
table.on('all.bs.table', initThumbAnimation);
// Load the associated frame image when the user clicks on a row
table.on('click-cell.bs.table', processClicks);
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
}
$j(document).ready(function() {
initPage();
});

View File

@ -815,10 +815,10 @@ switch ( $tab ) {
<td><?php echo translate('DeviceFormat') ?></td>
<td><?php echo htmlSelect('newMonitor[Format]', $v4l2DeviceFormats, $monitor->Format()); ?></td>
</tr>
<tr>
<td><?php echo translate('CapturePalette') ?></td>
<tr>
<td><?php echo translate('CapturePalette') ?></td>
<td><?php echo htmlSelect('newMonitor[Palette]', $v4l2LocalPalettes, $monitor->Palette()); ?></td>
</tr>
</tr>
<?php
}
?>

View File

@ -38,7 +38,7 @@ xhtmlHeaders(__FILE__, translate('Privacy'));
<h2><?php echo translate('Privacy') ?></h2>
<h1>ZoneMinder - <?php echo translate('Privacy') ?></h1>
</div>
<div id="content">
<div id="content" class="container pt-3">
<form name="contentForm" id="contentForm" method="post" action="?">
<input type="hidden" name="view" value="privacy"/>
<input type="hidden" name="action" value="privacy"/>
@ -61,9 +61,9 @@ xhtmlHeaders(__FILE__, translate('Privacy'));
<p><?php echo translate('PrivacyTelemetryList') ?></p>
<p><?php echo translate('PrivacyMonitorList') ?></p>
<p><?php echo translate('PrivacyConclusionText') ?></p>
<p><?php echo htmlSelect('option', $options, ZM_TELEMETRY_DATA); ?></p>
<div id="contentButtons">
<div id="contentButtons" class="pb-3">
<?php echo htmlSelect('option', $options, ZM_TELEMETRY_DATA); ?>
<button type="submit" value="Apply"><?php echo translate('Apply') ?></button>
</div>
</form>