1;(function ($) { 2 function base64ToBlob(base64, mimeType) { 3 let byteString = atob(base64.split(',')[1]); 4 let ab = new ArrayBuffer(byteString.length); 5 let ia = new Uint8Array(ab); 6 for (let i = 0; i < byteString.length; i++) { 7 ia[i] = byteString.charCodeAt(i); 8 } 9 return new Blob([ab], {type: mimeType}); 10 } 11 12 function generateFileName(inputText, ext) { 13 const MAX_LENGTH = 150; 14 let extension = ext || '.png'; 15 16 // Remover acentuação 17 const normalizedText = inputText.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); 18 19 // Substituir espaços e caracteres especiais 20 let safeText = normalizedText.replace(/[^a-z0-9]/gi, '_').toLowerCase(); 21 22 // Truncar para o máximo permitido 23 safeText = safeText.substring(0, MAX_LENGTH); 24 25 // Remover sublinhados extras no inÃcio ou fim do nome do arquivo 26 safeText = safeText.replace(/^_+|_+$/g, ''); 27 28 // Evitar nomes de arquivo vazios ou inapropriados 29 if (safeText === '') { 30 safeText = 'file_' + new Date().getTime(); // Nome padrão baseado no timestamp 31 } 32 33 return safeText + extension 34 } 35 36 function getFileExtensionFromUrl(url) { 37 // Remover qualquer parâmetro de URL ou fragmento 38 let cleanUrl = url.split('?')[0].split('#')[0]; 39 40 // Obter a última parte da URL após a última '/' 41 let segments = cleanUrl.split('/'); 42 let lastSegment = segments.pop() || segments.pop(); // trata casos extras onde a URL termina com '/' 43 44 // Encontrar a última ocorrência do ponto '.', começando do final do segmento para trás 45 let lastDotPosition = lastSegment.lastIndexOf('.'); 46 if (lastDotPosition === -1 || lastDotPosition === 0) return null; // não há extensão encontrada ou é apenas um ponto 47 48 let potentialExtension = lastSegment.substring(lastDotPosition); 49 if (lastSegment.split('/').length > 1) { 50 return null; // Se a 'extensão' contém uma '/', não é uma extensão válida 51 } 52 return potentialExtension; 53 } 54 55 elFinder.prototype.commands.generate_image = function () { 56 let self = this, 57 fm = self.fm; 58 59 this.disableOnSearch = true; 60 this.updateOnSelect = false; 61 this.dialogLoaded = false; 62 63 this.fm.bind('load', function () { 64 if (!self.dialog) { 65 let height = self.fm.ui.toolbar.outerHeight(); 66 self.dialog = self.fmDialog('loading', { 67 title: self.title, 68 allowMinimize: false, 69 allowMaximize: false, 70 openMaximized: false, 71 modal: true, 72 absolute: false, 73 dialogContained: false, 74 propagationEvents: ['mousemove', 'mouseup', 'click'], 75 resizable: false, 76 resize: false, 77 draggable: false, 78 autoOpen: false, // Definido como false para não abrir automaticamente 79 destroyOnClose: false, 80 width: "80%", 81 height: 'calc(100% - ' + height + 'px)', 82 position: {left: "10%", top: height + 'px'} 83 }); 84 } 85 }); 86 87 this.init = function () { 88 self.title = "Gerador de imagem" 89 } 90 91 this.getstate = function (select) { 92 let fm = this.fm, f, 93 sel = (select || [fm.cwd().hash]); 94 if (!this._disabled && sel.length === 1) { 95 f = fm.file(sel[0]); 96 } 97 return (f && f.mime === 'directory' && f.write) ? 0 : -1; 98 }; 99 100 this.get_file_by_url = function (url, filename) { 101 var notifier = new self.make_progress_notifier("download"); 102 notifier.start(); 103 104 return new Promise((resolve, reject) => { 105 fetch(url) 106 .then(response => { 107 if (response.ok) return response.blob(); 108 reject(new Error('Network response was not ok.')); 109 }) 110 .then(blob => { 111 let blob_filename = filename || url.split('/').pop(); 112 notifier.end(); 113 return resolve(new File([blob], blob_filename, {type: blob.type})); 114 }) 115 .catch(error => { 116 reject(error); 117 notifier.end(); 118 }); 119 }); 120 } 121 122 this.get_file_by_base64 = function (base64, filename) { 123 return new Promise((resolve, reject) => {
124 // Extrair o tipo MIME da string base64 125 let mimeType = base64.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/)[1]; 126 127 if (!mimeType) { 128 reject(new Error('Tipo MIME não encontrado.')); 129 return; 130 } 131 132 try { 133 // Converter a string base64 para Blob 134 let imageBlob = base64ToBlob(base64, mimeType); 135 // Criar um objeto File a partir do Blob 136 let blob_fileName = filename || "imagem.png"; // Especifique o nome do arquivo conforme necessário 137 resolve(new File([imageBlob], blob_fileName, {type: mimeType})); 138 } catch (error) { 139 // 'Reject' a promessa se ocorrer um erro 140 reject(error); 141 } 142 }); 143 } 144 145 this.upload_to_elfinder = function (file, deferred) { 146 fm.upload({ 147 files: [file], 148 type: 'files', 149 target: fm.cwd().hash, 150 }).fail(function (error) { 151 deferred.reject(error); 152 }).progress(function () { 153 deferred.notifyWith(this, Array.from(arguments)); 154 }).done(function (data) { 155 let getTargets = function() { 156 let tgts = data && (data instanceof Array)? data : null, 157 sel; 158 if (! data || data instanceof Array) { 159 if (! tgts && (sel = fm.selected()).length === 1 && fm.file(sel[0]).mime === 'directory') { 160 tgts = sel; 161 } else if (!tgts || tgts.length !== 1 || fm.file(tgts[0]).mime !== 'directory') { 162 tgts = [ cwdHash ]; 163 } 164 } 165 return tgts; 166 } 167 let targets = getTargets(); 168 let cwdHash = fm.cwd().hash; 169 let check = targets? targets[0] : (data && data.target? data.target : null); 170 let targetDir = check? fm.file(check) : fm.cwd(); 171 if (data && data.added && data.added[0] && !fm.ui.notify.children('.elfinder-notify-upload').length) { 172 let newItem = fm.findCwdNodes(data.added); 173 if (newItem.length) { 174 newItem.trigger('scrolltoview'); 175 } else { 176 let node; 177 if (targetDir.hash !== cwdHash) { 178 node = $('<div></div>').append( 179 $('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all elfinder-tabstop"><span class="ui-button-text">' + fm.i18n('cmdopendir') + '</span></button>') 180 .on('mouseenter mouseleave', function (e) { 181 $(this).toggleClass('ui-state-hover', e.type === 'mouseenter'); 182 }).on('click', function () { 183 fm.exec('open', check).done(function () { 184 fm.one('opendone', function () { 185 fm.trigger('selectfiles', { 186 files: $.map(data.added, function (f) { 187 return f.hash; 188 }) 189 }); 190 }); 191 }); 192 }) 193 ); 194 } else { 195 fm.trigger('selectfiles', { 196 files: $.map(data.added, function (f) { 197 return f.hash; 198 }) 199 }); 200 } 201 fm.toast({ 202 msg: fm.i18n(['complete', fm.i18n('cmdupload')]), 203 extNode: node 204 }); 205 } 206 deferred.resolve(data); 207 } 208 209 self.dialog.elfinderdialog('close'); 210 }); 211 } 212 213 this.make_dialog_content = function () { 214 var generate_image_url; 215 try { 216 generate_image_url = Urls["xadmin:plus_elfinder_generate_image"](); 217 } catch (error) { 218 generate_image_url = Urls["plus_elfinder_hidra:generate_image"](); 219 } 220 221 if (!self.dialogLoaded) { 222 self.dialog.html('<iframe class="w-100 mb-0" style="height: calc(100% - 0.313rem);" frameborder="0" allowfullscreen allow="autoplay; fullscreen" src="' + generate_image_url + '"></iframe>'); 223 self.dialogLoaded = true; 224 } 225 } 226 227 this.make_progress_notifier = function (type) { 228 let obj = {} 229 obj.notifyId = 'generate_image'; 230 obj.progress = 0; 231 obj.notify_config = { 232 id: obj.notifyId, 233 type: 'download', 234 msg: `Iniciando ${type}...`, 235 cnt: 1, 236 size: 100, 237 hideCnt: true, 238 cancel: false 239 }; 240 241 obj.start = function() { 242 // Inicia a notificação 243 self.fm.notify(obj.notify_config); 244 }; 245 246 obj.end = function() { 247 // Finaliza a notificação 248 self.fm.notify($.extend({}, obj.notify_config, { 249 msg: `${type} completo.`, 250 progress: 100, 251 cnt: -1, 252 remove: true 253 })); 254 }; 255 return obj; 256 } 257 258 this.change_zindez_notify = function (type) { 259 let obj = {} 260 obj.$notify = $(".elfinder-dialog-notify"); 261 obj.notify_original_zindex = obj.$notify.css('z-index'); 262 263 obj.change = function() { 264 obj.$notify.css('z-index', self.fm.getMaximizeCss().zIndex + 2); 265 }; 266 267 obj.end = function() { 268 obj.$notify.css('z-index', obj.notify_original_zindex); 269 }; 270 return obj; 271 } 272 273 this.create_context_for_window = function (deferred) { 274 window.elfinder_generate_image = { 275 'dfrd': deferred, 276 'fm': fm, 277 'upload_by_url': function (url, filename) { 278 deferred.notifyWith(); 279 self.get_file_by_url(url, filename).then(function (file) { 280 self.upload_to_elfinder(file, deferred) 281 }).catch(function (error) { 282 deferred.reject(error); 283 }); 284 }, 285 'upload_by_base64': function (base64, filename) { 286 deferred.notifyWith(); 287 self.get_file_by_base64(base64, filename).then(function (file) { 288 self.upload_to_elfinder(file, deferred) 289 }).catch(function (error) { 290 deferred.reject(error); 291 });; 292 }, 293 'generate_filename_by_text': generateFileName, 294 'get_extension_from_url': getFileExtensionFromUrl 295 } 296 } 297 298 this.exec = function () { 299 let deferred = $.Deferred(); 300 let notify = new self.change_zindez_notify(deferred); 301 self.make_dialog_content(); 302 self.dialog.elfinderdialog('open'); 303 self.create_context_for_window(deferred); 304 305 deferred.progress(function() { 306 notify.change(); 307 }); 308 309 deferred.fail(function(error) { 310 if (error && error.message) { 311 fm.toast({mode: 'error', msg: error.message}); 312 } else { 313 fm.toast({mode: 'error', msg: "Error"}); 314 } 315 }); 316 317 deferred.always(function() { 318 notify.end(); 319 }); 320 321 return deferred.promise(); 322 }; 323 }; 324})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.