diff --git a/include/thirdparty/elFinder/connector.php b/include/thirdparty/elFinder/connector.php index 3a6ea98..b8703dc 100644 --- a/include/thirdparty/elFinder/connector.php +++ b/include/thirdparty/elFinder/connector.php @@ -180,4 +180,9 @@ $opts = array( // run elFinder $connector = new elFinderConnector(new elFinder($opts)); -$connector->run(); + +try { + $connector->run(); +} catch (Exception $e) { +} + diff --git a/include/thirdparty/elFinder/js/elfinder.full.js b/include/thirdparty/elFinder/js/elfinder.full.js index b9217eb..8ceab5a 100644 --- a/include/thirdparty/elFinder/js/elfinder.full.js +++ b/include/thirdparty/elFinder/js/elfinder.full.js @@ -1,9 +1,9 @@ /*! * elFinder - file manager for web - * Version 2.1.50 (2019-08-20) + * Version 2.1.59 (2021-06-14) * http://elfinder.org * - * Copyright 2009-2019, Studio 42 + * Copyright 2009-2021, Studio 42 * Licensed under a 3-clauses BSD license */ (function(root, factory) { @@ -73,7 +73,7 @@ var elFinder = function(elm, opts, bootCallback) { * @see this.destroy * @type jQuery **/ - prevContent = $('
').append(node.contents()).attr('class', node.attr('class') || '').attr('style', node.attr('style') || ''), + prevContent = $('
').append(node.contents()).attr('class', node.attr('class') || '').attr('style', node.attr('style') || ''), /** * Instance ID. Required to get/set cookie @@ -170,6 +170,7 @@ var elFinder = function(elm, opts, bootCallback) { uploadMaxSize : 0, jpgQuality : 100, tmbCrop : false, + tmbReqCustomData : false, tmb : false // old API }, @@ -330,7 +331,7 @@ var elFinder = function(elm, opts, bootCallback) { // NOTES: Do not touch data object var volumeid, contextmenu, emptyDirs = {}, stayDirs = {}, - rmClass, hashes, calc, gc, collapsed, prevcwd, sorterStr; + rmClass, hashes, calc, gc, collapsed, prevcwd, sorterStr, diff; if (self.api >= 2.1) { // support volume driver option `uiCmdMap` @@ -423,7 +424,14 @@ var elFinder = function(elm, opts, bootCallback) { cache(data.files); if (!files[cwd]) { cache([data.cwd]); + } else { + diff = self.diff([data.cwd], true); + if (diff.changed.length) { + cache(diff.changed, 'change'); + self.change({changed: diff.changed}); + } } + data.changed && data.changed.length && cache(data.changed, 'change'); // trigger event 'sorterupdate' sorterStr = JSON.stringify(self.sorters); @@ -445,8 +453,10 @@ var elFinder = function(elm, opts, bootCallback) { * @return void **/ cache = function(data, type) { - var defsorter = { name: true, perm: true, date: true, size: true, kind: true }, - sorterChk = !self.sorters._checked, + var type = type || 'files', + keeps = ['sizeInfo', 'encoding'], + defsorter = { name: true, perm: true, date: true, size: true, kind: true }, + sorterChk = !self.sorters._checked && (type === 'files'), l = data.length, setSorter = function(file) { var f = file || {}, @@ -459,11 +469,10 @@ var elFinder = function(elm, opts, bootCallback) { self.sorters = self.arrayFlip(sorters, true); self.sorters._checked = true; }, - keeps = ['sizeInfo'], changedParents = {}, hideData = self.storage('hide') || {}, hides = hideData.items || {}, - f, i, keepProp, parents, hidden; + f, i, i1, keepProp, parents, hidden; for (i = 0; i < l; i++) { f = Object.assign({}, data[i]); @@ -475,7 +484,7 @@ var elFinder = function(elm, opts, bootCallback) { sorterChk = false; } - if (f.phash && (type === 'add' || type === 'change')) { + if (f.phash && (type === 'add' || (type === 'change' && (!files[f.hash] || f.size !== files[f.hash])))) { if (parents = self.parents(f.phash)) { $.each(parents, function() { changedParents[this] = true; @@ -485,11 +494,11 @@ var elFinder = function(elm, opts, bootCallback) { } if (files[f.hash]) { - $.each(keeps, function() { - if(files[f.hash][this] && ! f[this]) { - f[this] = files[f.hash][this]; + for (i1 =0; i1 < keeps.length; i1++) { + if(files[f.hash][keeps[i1]] && ! f[keeps[i1]]) { + f[keeps[i1]] = files[f.hash][keeps[i1]]; } - }); + } if (f.sizeInfo && !f.size) { f.size = f.sizeInfo.size; } @@ -600,6 +609,7 @@ var elFinder = function(elm, opts, bootCallback) { * * @param Array changed file objects * @return void + * @deprecated should be use `cache(updatesArrayData, 'change');` */ change = function(changed) { $.each(changed, function(i, file) { @@ -658,12 +668,12 @@ var elFinder = function(elm, opts, bootCallback) { requestQueue = [], /** - * Flag to cancel the `open` command waiting for connection + * Current open command instance * - * @type Boolean + * @type Object */ - requestQueueSkipOpen = false, - + currentOpenCmd = null, + /** * Exec shortcut * @@ -1126,7 +1136,7 @@ var elFinder = function(elm, opts, bootCallback) { baseUrl = ''; myTag = null; $('head > script').each(function() { - if (this.src && this.src.match(/js\/elfinder(?:-[a-z0-9_-]+)?\.(?:min|full)\.js$/i)) { + if (this.src && this.src.match(/js\/elfinder(?:-[a-z0-9_-]+)?\.(?:min|full)\.js(?:$|\?)/i)) { myTag = $(this); return false; } @@ -1972,7 +1982,7 @@ var elFinder = function(elm, opts, bootCallback) { } if (typeof baseUrl === 'undefined') { - baseUrl = self.option('url', (!self.isRoot(file) && file.phash) || file.hash); + baseUrl = getBaseUrl(); } if (baseUrl) { @@ -1988,32 +1998,37 @@ var elFinder = function(elm, opts, bootCallback) { params.current = file.phash; } return filter(self.options.url + (self.options.url.indexOf('?') === -1 ? '?' : '&') + $.param(params, true)); - }, + }, + getBaseUrl = function() { + return self.option('url', (!self.isRoot(file) && file.phash) || file.hash); + }, baseUrl, res; if (!file || !file.read) { return async? dfrd.resolve('') : ''; } - if (onetm) { + if (onetm && (!file.url || file.url == '1') && !(baseUrl = getBaseUrl())) { async = true; this.request({ data : { cmd : 'url', target : hash, options : { onetime: 1 } }, preventDefault : true, options: {async: async}, - notify: {type : 'file', cnt : 1, hideCnt : true} + notify: {type : 'file', cnt : 1, hideCnt : true}, + progressBar: opts.progressBar }).done(function(data) { dfrd.resolve(filter(data.url || '')); }).fail(function() { dfrd.resolve(''); }); } else { - if (file.url == '1' || (temp && !file.url && !(baseUrl = self.option('url', (!self.isRoot(file) && file.phash) || file.hash)))) { + if (file.url == '1' || (temp && !file.url && !(baseUrl = getBaseUrl()))) { this.request({ data : { cmd : 'url', target : hash, options : { temporary: temp? 1 : 0 } }, preventDefault : true, options: {async: async}, - notify: async? {type : temp? 'file' : 'url', cnt : 1, hideCnt : true} : {} + notify: async? {type : temp? 'file' : 'url', cnt : 1, hideCnt : true} : {}, + progressBar: opts.progressBar }) .done(function(data) { file.url = data.url || ''; @@ -2069,17 +2084,19 @@ var elFinder = function(elm, opts, bootCallback) { * * @param String file hash * @param Boolean for download link + * @param Object requestOpts The request options * @return String */ - this.openUrl = function(hash, download) { + this.openUrl = function(hash, download, callback, requestOpts) { var file = files[hash], - url = ''; + url = '', + onetimeSize = (requestOpts || {}).onetimeSize || (5 * 1024 * 1024); if (!file || !file.read) { return ''; } - if (!download) { + if (!download || download === 'sameorigin') { if (file.url) { if (file.url != 1) { url = file.url; @@ -2087,27 +2104,69 @@ var elFinder = function(elm, opts, bootCallback) { } else if (cwdOptions.url && file.hash.indexOf(self.cwd().volumeid) === 0) { url = cwdOptions.url + $.map(this.path2array(hash), function(n) { return encodeURIComponent(n); }).slice(1).join('/'); } - if (url) { - url += (url.match(/\?/)? '&' : '?') + '_'.repeat((url.match(/[\?&](_+)t=/g) || ['&t=']).sort().shift().match(/[\?&](_*)t=/)[1].length + 1) + 't=' + (file.ts || parseInt(+new Date()/1000)); - return url; + if (!download || this.isSameOrigin(url)) { + if (url) { + url += (url.match(/\?/)? '&' : '?') + '_'.repeat((url.match(/[\?&](_+)t=/g) || ['&t=']).sort().shift().match(/[\?&](_*)t=/)[1].length + 1) + 't=' + (file.ts || parseInt(+new Date()/1000)); + if (callback) { + callback(url); + return; + } else { + return url; + } + } } } - url = this.options.url; - url = url + (url.indexOf('?') === -1 ? '?' : '&') - + (this.oldAPI ? 'cmd=open¤t='+file.phash : 'cmd=file') - + '&target=' + file.hash - + '&_t=' + (file.ts || parseInt(+new Date()/1000)); - - if (download) { - url += '&download=1'; + if (callback && this.hasParrotHeaders()) { + if (!requestOpts) { + requestOpts = {}; + } else { + delete requestOpts.onetimeSize; + } + if (!requestOpts.onetime && !requestOpts.temporary && file.size > onetimeSize) { + if (file.mime.match(/^video|audio/)) { + requestOpts.temporary = true; + } else { + requestOpts.onetime = true; + } + } + if (requestOpts.onetime || requestOpts.temporary) { + return this.url(file.hash, Object.assign({ + async: true + }, requestOpts)).done(function(url) { + callback(url); + }).fail(function() { + callback(''); + }); + } else { + return this.getContents(hash, 'blob', requestOpts).done(function(blob){ + url = (window.URL || window.webkitURL).createObjectURL(blob); + callback(url); + }).fail(function() { + callback(''); + }); + } + } else { + url = this.options.url; + url = url + (url.indexOf('?') === -1 ? '?' : '&') + + (this.oldAPI ? 'cmd=open¤t='+file.phash : 'cmd=file') + + '&target=' + file.hash + + '&_t=' + (file.ts || parseInt(+new Date()/1000)); + + if (download === true) { + url += '&download=1'; + } + + $.each(this.customData, function(key, val) { + url += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(val); + }); + if (callback) { + callback(url); + return; + } else { + return url; + } } - - $.each(this.customData, function(key, val) { - url += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(val); - }); - - return url; }; /** @@ -2119,15 +2178,17 @@ var elFinder = function(elm, opts, bootCallback) { this.tmb = function(file) { var tmbUrl, tmbCrop, cls = 'elfinder-cwd-bgurl', - url = ''; + url = '', + cData = {}, + n = 0; if ($.isPlainObject(file)) { if (self.searchStatus.state && file.hash.indexOf(self.cwd().volumeid) !== 0) { tmbUrl = self.option('tmbUrl', file.hash); tmbCrop = self.option('tmbCrop', file.hash); } else { - tmbUrl = cwdOptions['tmbUrl']; - tmbCrop = cwdOptions['tmbCrop']; + tmbUrl = cwdOptions.tmbUrl; + tmbCrop = cwdOptions.tmbCrop; } if (tmbCrop) { cls += ' elfinder-cwd-bgurl-crop'; @@ -2141,8 +2202,19 @@ var elFinder = function(elm, opts, bootCallback) { url = file.tmb; } if (url) { - if (file.ts && tmbUrl !== 'self') { - url += (url.match(/\?/)? '&' : '?') + '_t=' + file.ts; + if (tmbUrl !== 'self') { + if (file.ts) { + cData._t = file.ts; + } + if (cwdOptions.tmbReqCustomData && Object.keys(this.customData).length) { + cData = Object.assign(cData, this.customData); + } + if (Object.keys(cData).length) { + url += (url.match(/\?/) ? '&' : '?'); + $.each(cData, function (key, val) { + url += ((n++ === 0)? '' : '&') + encodeURIComponent(key) + '=' + encodeURIComponent(val); + }); + } } return { url: url, className: cls }; } @@ -2256,8 +2328,14 @@ var elFinder = function(elm, opts, bootCallback) { deffail = !(isBinary || opts.preventDefault || opts.preventFail), // call default success callback ? defdone = !(isBinary || opts.preventDefault || opts.preventDone), + // current progress of receive data + prog = opts.progressVal || 20, + // timer of fake progress + progTm = null, + // whether the notification dialog is currently displayed + hasNotify= false, // options for notify dialog - notify = Object.assign({}, opts.notify), + notify = !opts.progressBar? (opts.notify? Object.assign({progress: prog * opts.notify.cnt}, opts.notify) : {}) : {}, // make cancel button cancel = !!opts.cancel, // do not normalize data - return as is @@ -2283,7 +2361,34 @@ var elFinder = function(elm, opts, bootCallback) { cache : (self.api >= 2.1029), // api >= 2.1029 has unique request ID data : data, headers : this.customHeaders, - xhrFields: this.xhrFields + xhrFields: this.xhrFields, + progress : function(e) { + var p = e.loaded / e.total * 100; + progTm && clearTimeout(progTm); + if (opts.progressBar) { + try { + opts.progressBar.width(p + '%'); + } catch(e) {} + } else { + if (hasNotify && notify.type) { + p = p * notify.cnt; + if (prog < p) { + self.notify({ + type: notify.type, + progress: p - prog, + cnt: 0, + hideCnt: notify.hideCnt + }); + prog = p; + } + } + } + if (opts.progress) { + try { + opts.progress(e); + } catch(e) {} + } + } }, opts.options || {}), /** * Default success handler. @@ -2301,8 +2406,6 @@ var elFinder = function(elm, opts, bootCallback) { self.updateCache(data); } - data.changed && data.changed.length && change(data.changed); - self.lazy(function() { // fire some event to update cache/ui data.removed && data.removed.length && self.remove(data); @@ -2396,19 +2499,13 @@ var elFinder = function(elm, opts, bootCallback) { * @return void **/ success = function(response) { - var d = self.options.debug; - // Set currrent request command name self.currentReqCmd = cmd; - if (response.debug && (!d || d !== 'all')) { - if (!d) { - d = self.options.debug = {}; - } - d['backend-error'] = true; - d['warning'] = true; - } + response.debug && self.responseDebug(response); + self.setCustomHeaderByXhr(xhr); + if (raw) { self.abortXHR(xhr); response && response.debug && self.debug('backend-debug', response); @@ -2516,7 +2613,7 @@ var elFinder = function(elm, opts, bootCallback) { if ((data || hashes.length) && t.action && (msg = t.action.msg) && (cmd = t.action.cmd) && (!t.action.cwdNot || t.action.cwdNot !== self.cwd().hash)) { done = t.action.done; data = t.action.data; - node = $('
') + node = $('
') .append( $('') + button = $('') .on('mouseenter mouseleave', function(e) { $(this).toggleClass(clhover, e.type === 'mouseenter'); }); notify.children('div.elfinder-notify-cancel').append(button); } + ndialog.trigger('resize'); } else if (typeof opts.msg !== 'undefined') { notify.children('span.elfinder-notify-msg').html(msg); } @@ -8273,7 +8637,13 @@ elFinder.prototype = { } !opts.hideCnt && notify.children('.elfinder-notify-cnt').text('('+cnt+')'); - ndialog.is(':hidden') && ndialog.elfinderdialog('open', this).height('auto'); + if (delta > 0 && ndialog.is(':hidden') && !hiddens[type]) { + if (dialog.data('minimized')) { + dialog.data('minimized').show(); + } else { + ndialog.elfinderdialog('open', this).height('auto'); + } + } notify.data('cnt', cnt); if ((progress != null) @@ -8288,12 +8658,15 @@ elFinder.prototype = { prc *= 100; total = Math.max(1, total); } - progress = parseInt(prc/total); + progress = Math.min(parseInt(prc/total), 100); notify.find('.elfinder-notify-progress') .animate({ width : (progress < 100 ? progress : 100)+'%' - }, 20); + }, 20, function() { + notify.data('cur', progress); + setProgressbar(); + }); } } else { @@ -8392,7 +8765,7 @@ elFinder.prototype = { if (opts.all) { options.create = function() { - var base = $('
'); + var base = $('
'); checkbox = $(''); $(this).next().find('.ui-dialog-buttonset') .prepend(base.append($('').prepend(checkbox))); @@ -8403,7 +8776,7 @@ elFinder.prototype = { opts.optionsCallback(options); } - return this.dialog('' + this.i18n(opts.text), options); + return this.dialog('' + this.i18n(opts.text), options); }, /** @@ -9052,13 +9425,13 @@ elFinder.prototype = { } } }); - bro.after($('
').append(select)) + bro.after($('
').append(select)) .closest('.ui-dialog').trigger('tabstopsInit'); select.trigger('focus'); } }, spinner = function() { - return $('
').append(''); + return $('
').append(''); }, xhr; return { @@ -9068,10 +9441,11 @@ elFinder.prototype = { offline : $('').on('change', function() { $(this).parents('table.elfinder-netmount-tb').find('select:first').trigger('change', 'reset'); }), - host : $(''), + host : $(''), path : $(''), user : $(''), - pass : $('') + pass : $(''), + mnt2res : $('') }, select: function(fm, ev, d){ var f = this.inputs, @@ -9088,7 +9462,7 @@ elFinder.prototype = { if (oline.parent().children().length === 1) { f.path.parent().prev().html(fm.i18n(opts.pathI18n)); oline.attr('title', fm.i18n('offlineAccess')); - oline.uniqueId().after($('