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

pull/4693/head
Isaac Connor 2026-03-08 13:19:58 -04:00
commit 2a899efbcd
4 changed files with 57 additions and 8 deletions

View File

@ -315,7 +315,7 @@ EOF
sudo apt-get install devscripts equivs
sudo mk-build-deps -ir $DIRECTORY.orig/debian/control
echo "Status: $?"
DEBUILD=debuild
DEBUILD=debuild -b -uc -us
else
if [ $TYPE == "local" ]; then
# Auto-install all ZoneMinder's dependencies using the Debian control file

View File

@ -30,6 +30,7 @@ function MonitorStream(monitorData) {
this.wsMSE = null;
this.streamStartTime = 0; // Initial point of flow start time. Used for flow lag time analysis.
this.waitingStart;
this.handlerEventListener = {};
this.mseListenerSourceopenBind = null;
this.streamListenerBind = null;
this.mseSourceBufferListenerUpdateendBind = null;
@ -441,7 +442,7 @@ function MonitorStream(monitorData) {
clearInterval(this.statusCmdTimer); // Fix for issues in Chromium when quickly hiding/showing a page. Doesn't clear statusCmdTimer when minimizing a page https://stackoverflow.com/questions/9501813/clearinterval-not-working
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), statusRefreshTimeout);
this.started = true;
this.streamListenerBind();
this.handlerEventListener['killStream'] = this.streamListenerBind();
if (typeof observerMontage !== 'undefined') observerMontage.observe(stream);
this.activePlayer = 'go2rtc';
@ -482,7 +483,7 @@ function MonitorStream(monitorData) {
attachVideo(this);
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), statusRefreshTimeout);
this.started = true;
this.streamListenerBind();
this.handlerEventListener['killStream'] = this.streamListenerBind();
this.activePlayer = 'janus';
this.updateStreamInfo('Janus', 'loading');
return;
@ -554,7 +555,7 @@ function MonitorStream(monitorData) {
clearInterval(this.statusCmdTimer); // Fix for issues in Chromium when quickly hiding/showing a page. Doesn't clear statusCmdTimer when minimizing a page https://stackoverflow.com/questions/9501813/clearinterval-not-working
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), statusRefreshTimeout);
this.started = true;
this.streamListenerBind();
this.handlerEventListener['killStream'] = this.streamListenerBind();
this.updateStreamInfo((typeof players !== "undefined" && players) ? players[this.activePlayer] : 'RTSP2Web ' + this.RTSP2WebType, 'loading');
return;
} else {
@ -618,12 +619,14 @@ function MonitorStream(monitorData) {
}
} // end if paused or not
this.started = true;
this.streamListenerBind();
this.handlerEventListener['killStream'] = this.streamListenerBind();
this.activePlayer = 'zms';
this.updateStreamInfo('ZMS MJPEG');
}; // this.start
this.stop = function() {
manageEventListener.removeEventListener(this.handlerEventListener['killStream']);
/* Stop should stop the stream (killing zms) but NOT set src=''; This leaves the last jpeg up on screen instead of a broken image */
const stream = this.getElement();
if (!stream) {
@ -1976,10 +1979,10 @@ function startRTSP2WebPlay(videoEl, url, stream) {
}
function streamListener(stream) {
window.addEventListener('beforeunload', function(event) {
return manageEventListener.addEventListener(window, 'beforeunload', function() {
console.log('streamListener');
stream.kill();
});
}, {capture: false});
}
function mseListenerSourceopen(context, videoEl, url) {

View File

@ -898,6 +898,11 @@ function exportEvents(
return false;
}
// Sanitize user-supplied values used in file paths and shell commands
$export_root = preg_replace('/[^\w\-.]/', '', $export_root);
if (empty($export_root)) $export_root = 'zmExport';
$connkey = preg_replace('/[^\w\-.]/', '', $connkey);
if (!($exportFormat == 'tar' or $exportFormat == 'zip')) {
ZM\Error("None or invalid exportFormat specified $exportFormat.");
return false;
@ -1027,7 +1032,7 @@ function exportEvents(
} // if $exportFormat
@unlink($archive_path);
$command .= ' '.$export_root.($connkey?'_'.$connkey:'').'/';
$command .= ' '.escapeshellarg($export_root.($connkey?'_'.$connkey:'').'/');
ZM\Debug($command);
exec($command, $output, $status);
if ($status) {

View File

@ -2867,4 +2867,45 @@ const waitUntil = (condition, timeout = 0) => {
});
};
// https://stackoverflow.com/a/69273090
class ManageEventListener {
#listeners = {}; // # in a JS class signifies private
#idx = 1;
// add event listener, returns integer ID of new listener
addEventListener(element, type, listener, options = {}) {
this.#privateAddEventListener(element, this.#idx, type, listener, options);
return this.#idx++;
}
// add event listener with custom ID (avoids need to retrieve return ID since you are providing it yourself)
addEventListenerById(element, id, type, listener, options = {}) {
this.#privateAddEventListener(element, id, type, listener, options);
return id;
}
#privateAddEventListener(element, id, type, listener, options) {
if (this.#listeners[id]) throw Error(`A listener with id ${id} already exists`);
element.addEventListener(type, listener, options);
this.#listeners[id] = {element, type, listener, options};
}
// remove event listener with given ID, returns ID of removed listener or null (if listener with given ID does not exist)
removeEventListener(id) {
const listen = this.#listeners[id];
if (listen) {
listen.element.removeEventListener(listen.type, listen.listener, listen.options);
delete this.#listeners[id];
}
return !!listen ? id : null;
}
// returns number of events listeners
length() {
return Object.keys(this.#listeners).length;
}
}
const manageEventListener = new ManageEventListener();
window.manageEventListener = manageEventListener;
$j( window ).on("load", initPageGeneral);