Detect text files via MIME + binary heuristic instead of hardcoded extension list
Server-side _file_type() now uses mimetypes for images/known text, and falls back to null-byte check on first 8KB for everything else. Client uses the "type" field from /files API instead of local extension sets. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+6
-14
@@ -259,10 +259,7 @@ $('lang-sw').addEventListener('click', e => {
|
||||
if (e.target.dataset.l) setLang(e.target.dataset.l);
|
||||
});
|
||||
|
||||
const TEXT_EXT = new Set(
|
||||
'txt,log,json,xml,csv,html,css,js,ts,py,md,sh,yml,yaml,toml,ini,cfg,conf,env,sql,rs,go,java,c,h,cpp,rb,php'.split(',')
|
||||
);
|
||||
const IMG_EXT = new Set('png,jpg,jpeg,gif,webp,bmp,ico,svg'.split(','));
|
||||
/* File type is determined server-side via /files API ("text" | "image" | "other") */
|
||||
|
||||
/* ── Helpers ── */
|
||||
|
||||
@@ -287,10 +284,6 @@ function esc(s) {
|
||||
.replace(/"/g,'"').replace(/'/g,''');
|
||||
}
|
||||
|
||||
function fileExt(name) {
|
||||
return (name.split('.').pop() || '').toLowerCase();
|
||||
}
|
||||
|
||||
/* ── Clipboard ── */
|
||||
|
||||
function fallbackCopy(text) {
|
||||
@@ -332,15 +325,14 @@ function toPngBlob(blob) {
|
||||
});
|
||||
}
|
||||
|
||||
function copyFile(name) {
|
||||
function copyFile(name, type) {
|
||||
const url = '/dl/' + encodeURIComponent(name);
|
||||
const ext = fileExt(name);
|
||||
|
||||
if (TEXT_EXT.has(ext)) {
|
||||
if (type === 'text') {
|
||||
fetch(url).then(r => r.text()).then(text => copyText(text))
|
||||
.catch(() => toast(t().copyFail));
|
||||
|
||||
} else if (IMG_EXT.has(ext)) {
|
||||
} else if (type === 'image') {
|
||||
const link = location.origin + url;
|
||||
if (!navigator.clipboard?.write) {
|
||||
copyText(link, t().linkCopied);
|
||||
@@ -457,7 +449,7 @@ function renderFiles() {
|
||||
|
||||
flist.innerHTML = slice.map(f => `
|
||||
<div class="file">
|
||||
<span class="fname" data-action="copy" data-name="${esc(f.name)}" title="${t().copy}">${esc(f.name)}</span>
|
||||
<span class="fname" data-action="copy" data-name="${esc(f.name)}" data-type="${f.type}" title="${t().copy}">${esc(f.name)}</span>
|
||||
<div class="meta">
|
||||
<span class="fsize">${fmtSize(f.size)}</span>
|
||||
<a class="btn dl" href="/dl/${encodeURIComponent(f.name)}" title="${t().download}"><svg width="14" height="14"><use href="#icon-dl"/></svg></a>
|
||||
@@ -482,7 +474,7 @@ flist.addEventListener('click', e => {
|
||||
if (!el) return;
|
||||
const action = el.dataset.action;
|
||||
const name = el.dataset.name;
|
||||
if (action === 'copy') copyFile(name);
|
||||
if (action === 'copy') copyFile(name, el.dataset.type);
|
||||
else if (action === 'del') {
|
||||
fetch('/del/' + encodeURIComponent(name), { method: 'DELETE' })
|
||||
.then(() => { toast(t().deleted); loadFiles() });
|
||||
|
||||
Reference in New Issue
Block a user