Lista conteudo de .zip, .tar, .tar.gz e .gz sem extrair, com limite anti-bomba.
This commit is contained in:
1 parent
dc829b9d43
commit
f6a74e1092
6 files changed
+389
-15
No files matched your search
+120
-15
@@ -2433,27 +2433,132 @@
|
||||
F.lbDl.href = f.url;
|
||||
F.lbDl.setAttribute('download', f.name);
|
||||
F.lbBody.textContent = '';
|
||||
const kind = attachmentKind(f);
|
||||
if (kind !== 'doc' || (f.mime || '').includes('pdf')) {
|
||||
let el;
|
||||
if (kind === 'img') { el = document.createElement('img'); el.src = f.url; el.alt = f.name; }
|
||||
else if (kind === 'vid') { el = document.createElement('video'); el.src = f.url; el.controls = true; }
|
||||
else if (kind === 'aud') { el = document.createElement('audio'); el.src = f.url; el.controls = true; }
|
||||
else { el = document.createElement('iframe'); el.src = f.url; el.title = f.name; }
|
||||
if (isPreviewableImage(f)) {
|
||||
const el = document.createElement('img');
|
||||
el.src = f.url;
|
||||
el.alt = f.name;
|
||||
F.lbBody.appendChild(el);
|
||||
} else if (isSupportedArchive(f)) {
|
||||
await previewArchive(f);
|
||||
} else if (isArchiveFile(f)) {
|
||||
previewNotice(`Não foi possível mostrar o conteúdo de “${f.name}”.\nEsse formato de compactado não tem listagem suportada (vale para .zip, .tar, .tar.gz e .gz). Use Baixar para abrir o arquivo.`);
|
||||
} else {
|
||||
const pre = document.createElement('pre');
|
||||
pre.className = 'lightbox-text';
|
||||
pre.textContent = 'carregando…';
|
||||
F.lbBody.appendChild(pre);
|
||||
try {
|
||||
const r = await fetch(f.url);
|
||||
pre.textContent = (await r.text()).slice(0, 200000);
|
||||
} catch { pre.textContent = '(sem conexão para pré-visualizar)'; }
|
||||
const kind = attachmentKind(f);
|
||||
if (kind !== 'doc' || (f.mime || '').includes('pdf')) {
|
||||
let el;
|
||||
if (kind === 'img') { el = document.createElement('img'); el.src = f.url; el.alt = f.name; }
|
||||
else if (kind === 'vid') { el = document.createElement('video'); el.src = f.url; el.controls = true; }
|
||||
else if (kind === 'aud') { el = document.createElement('audio'); el.src = f.url; el.controls = true; }
|
||||
else { el = document.createElement('iframe'); el.src = f.url; el.title = f.name; }
|
||||
F.lbBody.appendChild(el);
|
||||
} else {
|
||||
const pre = document.createElement('pre');
|
||||
pre.className = 'lightbox-text';
|
||||
pre.textContent = 'carregando…';
|
||||
F.lbBody.appendChild(pre);
|
||||
try {
|
||||
const r = await fetch(f.url);
|
||||
pre.textContent = (await r.text()).slice(0, 200000);
|
||||
} catch { pre.textContent = '(sem conexão para pré-visualizar)'; }
|
||||
}
|
||||
}
|
||||
F.lightbox.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function isPreviewableImage(f) {
|
||||
const mime = f.mime || '';
|
||||
// svg é servido como attachment (anti-XSS), então não dá para exibir inline
|
||||
return mime.startsWith('image/') && mime !== 'image/svg+xml';
|
||||
}
|
||||
function archiveExt(name) {
|
||||
const l = (name || '').toLowerCase();
|
||||
if (l.endsWith('.tar.gz')) return '.tar.gz';
|
||||
const i = l.lastIndexOf('.');
|
||||
return i >= 0 ? l.slice(i) : '';
|
||||
}
|
||||
const SUPPORTED_ARCHIVE_EXTS = new Set(['.zip', '.tar', '.tar.gz', '.tgz', '.gz']);
|
||||
const ARCHIVE_EXTS = new Set(['.zip', '.tar', '.tar.gz', '.tgz', '.gz', '.rar', '.7z', '.bz2', '.xz', '.cab', '.iso']);
|
||||
function isSupportedArchive(f) {
|
||||
const mime = f.mime || '';
|
||||
if (SUPPORTED_ARCHIVE_EXTS.has(archiveExt(f.name))) return true;
|
||||
return mime.includes('zip') || mime.includes('x-tar') || mime.includes('x-gzip') || mime.includes('gzip') || mime.includes('compressed');
|
||||
}
|
||||
function isArchiveFile(f) {
|
||||
if (isSupportedArchive(f)) return true;
|
||||
return ARCHIVE_EXTS.has(archiveExt(f.name));
|
||||
}
|
||||
function previewNotice(msg) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'lightbox-empty';
|
||||
const icon = document.createElement('div');
|
||||
icon.className = 'lightbox-empty-icon';
|
||||
icon.textContent = '📦';
|
||||
const p = document.createElement('p');
|
||||
p.textContent = msg;
|
||||
div.append(icon, p);
|
||||
F.lbBody.appendChild(div);
|
||||
}
|
||||
async function previewArchive(f) {
|
||||
const loading = document.createElement('div');
|
||||
loading.className = 'lightbox-empty';
|
||||
loading.textContent = 'Listando conteúdo…';
|
||||
F.lbBody.appendChild(loading);
|
||||
let data;
|
||||
try {
|
||||
data = await api('GET', '/api/files/archive/' + f.id);
|
||||
} catch (err) {
|
||||
loading.textContent = '';
|
||||
previewNotice(err.message || `Não foi possível listar “${f.name}”. Use Baixar para abrir o arquivo.`);
|
||||
return;
|
||||
}
|
||||
F.lbBody.textContent = '';
|
||||
const box = document.createElement('div');
|
||||
box.className = 'lightbox-archive';
|
||||
const title = document.createElement('div');
|
||||
title.className = 'archive-title';
|
||||
title.textContent = '🗜️ ' + f.name;
|
||||
const meta = document.createElement('div');
|
||||
meta.className = 'archive-meta';
|
||||
const total = data.total || 0;
|
||||
meta.textContent = total === 0 ? 'Arquivo vazio.'
|
||||
: total === 1 ? '1 item · ' + fmtBytes(f.size || 0)
|
||||
: `${total} itens · ` + fmtBytes(f.size || 0);
|
||||
box.append(title, meta);
|
||||
const entries = data.entries || [];
|
||||
if (!entries.length) {
|
||||
const p = document.createElement('p');
|
||||
p.className = 'archive-note';
|
||||
p.textContent = total === 0 ? 'Nada para listar neste compactado.' : 'Nada para exibir.';
|
||||
box.appendChild(p);
|
||||
} else {
|
||||
const ul = document.createElement('ul');
|
||||
ul.className = 'archive-list';
|
||||
for (const e of entries) {
|
||||
const li = document.createElement('li');
|
||||
const ic = document.createElement('span');
|
||||
ic.className = 'archive-icon';
|
||||
ic.textContent = e.dir ? '📁' : '📄';
|
||||
const nm = document.createElement('span');
|
||||
nm.className = 'archive-name';
|
||||
nm.textContent = e.name;
|
||||
nm.title = e.name;
|
||||
const sz = document.createElement('span');
|
||||
sz.className = 'archive-size';
|
||||
sz.textContent = e.dir ? '' : fmtBytes(e.size < 0 ? 0 : e.size);
|
||||
li.append(ic, nm, sz);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
box.appendChild(ul);
|
||||
}
|
||||
if (data.truncated) {
|
||||
const note = document.createElement('p');
|
||||
note.className = 'archive-note';
|
||||
note.textContent = `Mostrando os primeiros ${entries.length} de ${total} itens. Baixe o arquivo para ver o restante.`;
|
||||
box.appendChild(note);
|
||||
}
|
||||
F.lbBody.appendChild(box);
|
||||
}
|
||||
|
||||
// wiring de eventos do gerenciador
|
||||
F.closeBtn.addEventListener('click', closeFiles);
|
||||
F.lbClose.addEventListener('click', () => F.lightbox.classList.add('hidden'));
|
||||
|
||||
Reference in new issue
Block a user