From 8e62c93f5f7ea65476176d993411a2ad03f7c528 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 6 Feb 2019 11:44:36 -0500 Subject: [PATCH 1/6] add to_json function to Storage. --- web/includes/Storage.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/web/includes/Storage.php b/web/includes/Storage.php index 95f1dab84..a7372b15a 100644 --- a/web/includes/Storage.php +++ b/web/includes/Storage.php @@ -223,5 +223,19 @@ class Storage { } return $this->{'Server'}; } + + public function to_json() { + $json = array(); + foreach ($this->defaults as $key => $value) { + if ( is_callable(array($this, $key)) ) { + $json[$key] = $this->$key(); + } else if ( array_key_exists($key, $this) ) { + $json[$key] = $this->{$key}; + } else { + $json[$key] = $this->defaults{$key}; + } + } + return json_encode($json); + } } ?> From edaf582eb49b70d340b828349e046a154d731ed0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 6 Feb 2019 11:46:48 -0500 Subject: [PATCH 2/6] Make montagereview more robust when the storage area of an event has been deleted. Add the onmouse events using javascript instead of in the html canvas element so that our CSP policy works. --- web/skins/classic/views/js/montagereview.js | 18 ++++++++++++++++-- .../classic/views/js/montagereview.js.php | 12 ++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index ccdea0a07..adb285f48 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -122,6 +122,11 @@ function getImageSource( monId, time ) { Event = events[Frame.EventId]; var storage = Storage[Event.StorageId]; + if ( ! storage ) { + // Storage[0] is guaranteed to exist as we make sure it is there in montagereview.js.php + console.log("No storage area for id " + Event.StorageId); + storage = Storage[0]; + } // monitorServerId may be 0, which gives us the default Server entry var server = storage.ServerId ? Servers[storage.ServerId] : Servers[monitorServerId[monId]]; return server.PathToIndex + @@ -500,7 +505,8 @@ HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords; var mouseisdown=false; function mdown(event) { - mouseisdown=true; mmove(event); + mouseisdown=true; + mmove(event); } function mup(event) { mouseisdown=false; @@ -509,7 +515,8 @@ function mout(event) { mouseisdown=false; } // if we go outside treat it as release function tmove(event) { - mouseisdown=true; mmove(event); + mouseisdown=true; + mmove(event); } function mmove(event) { @@ -910,6 +917,13 @@ function initPage() { } if ( !liveMode ) { canvas = $("timeline"); + + canvas.addEventListener('mousemove', mmove, false); + canvas.addEventListener('touchmove', tmove, false); + canvas.addEventListener('mousedown', mdown, false); + canvas.addEventListener('mouseup', mup, false); + canvas.addEventListener('mouseout', mout, false); + ctx = canvas.getContext('2d'); drawGraph(); } diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php index a31bbfa9e..c887bb0e3 100644 --- a/web/skins/classic/views/js/montagereview.js.php +++ b/web/skins/classic/views/js/montagereview.js.php @@ -119,13 +119,21 @@ echo " };\n"; } // end if initialmodeislive echo "\nvar Storage = [];\n"; +$have_storage_zero = 0; foreach ( Storage::find() as $Storage ) { - echo 'Storage[' . $Storage->Id() . '] = ' . json_encode($Storage). ";\n"; + echo 'Storage[' . $Storage->Id() . '] = ' . $Storage->to_json(). ";\n"; + if ( $Storage->Id() == 0 ) + $have_storage_zero = true; } +if ( !$have_storage_zero ) { + $Storage = new Storage(); + echo 'Storage[0] = ' . $Storage->to_json(). ";\n"; +} + echo "\nvar Servers = [];\n"; // Fall back to get Server paths, etc when no using multi-server mode $Server = new Server(); -echo 'Servers[0] = new Server(' . json_encode($Server). ");\n"; +echo 'Servers[0] = new Server(' . $Server->to_json(). ");\n"; foreach ( Server::find() as $Server ) { echo 'Servers[' . $Server->Id() . '] = new Server(' . $Server->to_json(). ");\n"; } From 6744a9a11671b5b61e7d208e5a35ad248b702417 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 6 Feb 2019 11:46:55 -0500 Subject: [PATCH 3/6] Make montagereview more robust when the storage area of an event has been deleted. Add the onmouse events using javascript instead of in the html canvas element so that our CSP policy works. --- web/skins/classic/views/montagereview.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 039938824..8e1ccdb9b 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -290,7 +290,7 @@ if ( (!$liveMode) and (count($displayMonitors) != 0) ) {
- + From b04b67c39d526c955499a403b89c4dc1722263f1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 6 Feb 2019 12:17:10 -0500 Subject: [PATCH 4/6] Fix CSP violation in the onclick of the monitor view in montagereview --- web/skins/classic/views/js/montagereview.js | 23 +++++++++++++++------ web/skins/classic/views/montagereview.php | 4 ++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index adb285f48..b50d59996 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -842,13 +842,15 @@ function zoom(monId, scale) { } } -function clickMonitor(event, monId) { - var monitor_element = $("Monitor"+monId.toString()); - var pos_x = event.offsetX ? (event.offsetX) : event.pageX - monitor_element.offsetLeft; - var pos_y = event.offsetY ? (event.offsetY) : event.pageY - monitor_element.offsetTop; - if ( pos_x < monitor_element.width/4 && pos_y < monitor_element.height/4 ) { +function clickMonitor(event) { + var element = event.target; + //var monitor_element = $("Monitor"+monId.toString()); + var monId = element.getAttribute('monitor_id'); + var pos_x = event.offsetX ? (event.offsetX) : event.pageX - element.offsetLeft; + var pos_y = event.offsetY ? (event.offsetY) : event.pageY - element.offsetTop; + if ( pos_x < element.width/4 && pos_y < element.height/4 ) { zoom(monId, 1.15); - } else if ( pos_x > monitor_element.width * 3/4 && pos_y < monitor_element.height/4 ) { + } else if ( pos_x > element.width * 3/4 && pos_y < element.height/4 ) { zoom(monId, 1/1.15); } else { showOneMonitor(monId); @@ -927,6 +929,15 @@ function initPage() { ctx = canvas.getContext('2d'); drawGraph(); } + for ( i=0, len=monitorPtr.length; i < len; i += 1 ) { + var monitor_id = monitorPtr[i]; + monitor_canvas = $('Monitor'+monitor_id); + if ( ! monitor_canvas ) { + console.log("No canvas found for monitor " + monitor_id); + continue; + } + monitor_canvas.addEventListener('click',clickMonitor,false); + } setSpeed(speedIndex); //setFit(fitMode); // will redraw //setLive(liveMode); // will redraw diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 8e1ccdb9b..a822febbe 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -304,8 +304,8 @@ if ( (!$liveMode) and (count($displayMonitors) != 0) ) {
Id().' ' .$m->Name().'" width="' . $m->Width() * $defaultScale . '" height="' . $m->Height() * $defaultScale . '" id="Monitor' . $m->Id() . '" style="border:1px solid ' . $m->WebColour() . '" onclick="clickMonitor(event,' . $m->Id() . ')">No Canvas Support!!'; + foreach ( $monitors as $m ) { + echo 'No Canvas Support!!'; } ?>
From 0783802d0cb625b8b501ac2471f336192d44ea04 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 6 Feb 2019 13:31:34 -0500 Subject: [PATCH 5/6] fix CSP violations on events --- web/skins/classic/views/events.php | 23 ++++++----- web/skins/classic/views/js/events.js | 61 ++++++++++++++++++---------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index 885924e64..35a3219aa 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -190,8 +190,8 @@ while ( $event_row = dbFetchNext($results) ) { $scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); ?> Archived()) echo ' class="archived"' ?>> - '.$event->Id().($event->Archived()?'*':'') ?> - '.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?> + '.$event->Id().($event->Archived()?'*':'') ?> + '.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?> MonitorId(), 'zmMonitor'.$event->Monitorid(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?> Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?> Notes() && ($event->Notes() != 'Forced Web: ')) echo "
".$event->Notes()."
" ?> @@ -227,12 +227,12 @@ while ( $event_row = dbFetchNext($results) ) { $streamSrc = $event->getStreamSrc(array( 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single')); - $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; + $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; echo ''.$imgHtml.''; echo ''; } // end if ZM_WEB_LIST_THUMBS ?> - +
- - - - - - -
@@ -301,6 +301,7 @@ if ( $pagination ) {
diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 9bdabdaef..f105b4cf7 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -17,12 +17,13 @@ function setButtonStates( element ) { form.deleteBtn.disabled = !(canEditEvents && checked); } -function configureButton( element, name ) { +function configureButton(event) { + var element = event.target; var form = element.form; var checked = element.checked; if ( !checked ) { - for (var i = 0; i < form.elements.length; i++) { - if ( form.elements[i].name.indexOf(name) == 0) { + for (var i = 0, len=form.elements.length; i < len; i++) { + if ( form.elements[i].name.indexOf('markEids') == 0) { if ( form.elements[i].checked ) { checked = true; break; @@ -42,15 +43,17 @@ function configureButton( element, name ) { form.deleteBtn.disabled = !(canEditEvents && checked); } -function deleteEvents( element, name ) { +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(name) == 0) { + if (form.elements[i].name.indexOf('markEids') == 0) { if ( form.elements[i].checked ) { count++; break; @@ -65,15 +68,15 @@ function deleteEvents( element, name ) { } } -function editEvents( element, name ) { +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; i < form.elements.length; i++) { - if (form.elements[i].name.indexOf(name) == 0) { + for (var i = 0, len=form.elements.length; i < len; i++) { + if (form.elements[i].name.indexOf('markEids') == 0) { if ( form.elements[i].checked ) { eids[eids.length] = 'eids[]='+form.elements[i].value; } @@ -82,24 +85,24 @@ function editEvents( element, name ) { createPopup( '?view=eventdetail&'+eids.join( '&' ), 'zmEventDetail', 'eventdetail' ); } -function downloadVideo( element, name ) { +function downloadVideo( element ) { var form = element.form; var eids = new Array(); - for (var i = 0; i < form.elements.length; i++) { - if (form.elements[i].name.indexOf(name) == 0) { + for (var i = 0, len=form.elements.length; i < len; i++) { + if (form.elements[i].name.indexOf('markEids') == 0 ) { if ( form.elements[i].checked ) { eids[eids.length] = 'eids[]='+form.elements[i].value; } } } - createPopup( '?view=download&'+eids.join( '&' ), 'zmDownload', 'download' ); + createPopup( '?view=download&'+eids.join('&'), 'zmDownload', 'download' ); } -function exportEvents( element, name ) { +function exportEvents( element ) { var form = element.form; var eids = new Array(); - for (var i = 0; i < form.elements.length; i++) { - if (form.elements[i].name.indexOf(name) == 0) { + for (var i = 0, len=form.elements.length; i < len; i++) { + if (form.elements[i].name.indexOf('markEids') == 0 ) { if ( form.elements[i].checked ) { eids[eids.length] = 'eids[]='+form.elements[i].value; } @@ -108,11 +111,11 @@ function exportEvents( element, name ) { createPopup( '?view=export&'+eids.join( '&' ), 'zmExport', 'export' ); } -function viewEvents( element, name ) { +function viewEvents( element ) { var form = element.form; var events = new Array(); - for (var i = 0; i < form.elements.length; i++) { - if ( form.elements[i].name.indexOf(name) == 0) { + for (var i = 0, len=form.elements.length; i < len; i++) { + if ( form.elements[i].name.indexOf('markEids') == 0 ) { if ( form.elements[i].checked ) { events[events.length] = form.elements[i].value; } @@ -124,13 +127,13 @@ function viewEvents( element, name ) { } } -function archiveEvents( element, name ) { +function archiveEvents(element) { var form = element.form; form.elements['action'].value = 'archive'; form.submit(); } -function unarchiveEvents(element, name) { +function unarchiveEvents(element) { if ( ! canEditEvents ) { alert("You do not have permission to delete events."); return; @@ -146,10 +149,26 @@ if ( openFilterWindow ) { location.replace( '?view='+currentView+'&page='+thisPage+filterQuery ); } +function thumbnail_onmouseover(event) { + var img = event.target; + img.src = img.getAttribute('stream_src'); +} +function thumbnail_onmouseout(event) { + var img = event.target; + img.src = img.getAttribute('still_src'); +} + function initPage() { - if (window.history.length == 1) { + if ( window.history.length == 1 ) { $j('#controls').children().eq(0).html(''); } + $j('.colThumbnail img').each(function(){ + this.addEventListener('mouseover',thumbnail_onmouseover,false); + this.addEventListener('mouseout',thumbnail_onmouseout,false); + }); + $j('input[name=markEids\\[\\]]').each(function(){ + this.addEventListener('click',configureButton,false); + }); } $j(document).ready(initPage); From 7e84a5914c7933bfe2f51a8d77a98e3231a36f2b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 6 Feb 2019 13:55:19 -0500 Subject: [PATCH 6/6] fix CSP policy violations on filters view --- web/skins/classic/views/filter.php | 4 ++-- web/skins/classic/views/js/filter.js | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 403a9b440..fab68941c 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -165,7 +165,7 @@ xhtmlHeaders(__FILE__, translate('EventFilter') );
1 ) { - echo htmlSelect('Id', $filterNames, $filter->Id(), 'this.form.submit();'); + echo htmlSelect('Id', $filterNames, $filter->Id(), array('data-on-change-this'=>'selectFilter')); } else { ?> Id() ) { ?> - +