From 14d76f8023fd0ba10b43ce432e5df8c9988dbf74 Mon Sep 17 00:00:00 2001 From: Nachtalb Date: Sat, 3 Apr 2021 12:32:49 +0200 Subject: [PATCH 1/2] Add proper filename to the content-disposition header By default we take the slug given in the request, if this is not set we try to give a filename from known types. If we still have no filename we fallback to the previous method of setting no filename. If the filename is non ascii we will only create the encoded "filename*" and not the ascii only "filename". This is to prevent other applications to save a file like "?????.png" if the filename contains non ascii chars. For the browsers nothing will really change comapred to the behaviour before this change as good fallbacks if no content-disposition filename is set. But that is not the case for all application, thus it makes sense to include the proper way to set the filename. --- package.json | 1 + src/plugins/uploader.js | 58 +++++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 23830801..c3d297b0 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "chalk": "4.1.0", "cheerio": "1.0.0-rc.5", "commander": "7.2.0", + "content-disposition": "0.5.3", "express": "4.17.1", "file-type": "16.2.0", "filenamify": "4.2.0", diff --git a/src/plugins/uploader.js b/src/plugins/uploader.js index 3c877005..3effac7c 100644 --- a/src/plugins/uploader.js +++ b/src/plugins/uploader.js @@ -10,26 +10,27 @@ const readChunk = require("read-chunk"); const crypto = require("crypto"); const isUtf8 = require("is-utf8"); const log = require("../log"); +const contentDisposition = require("content-disposition"); -// List of allowed mime types that can be rendered in browser -// without forcing it to be downloaded -const inlineContentDispositionTypes = [ - "application/ogg", - "audio/midi", - "audio/mpeg", - "audio/ogg", - "audio/vnd.wave", - "image/bmp", - "image/gif", - "image/jpeg", - "image/png", - "image/webp", - "image/avif", - "text/plain", - "video/mp4", - "video/ogg", - "video/webm", -]; +// Map of allowed mime types to their respecive default filenames +// that will be rendered in browser without forcing them to be downloaded +const inlineContentDispositionTypes = { + "application/ogg": "media.ogx", + "audio/midi": "audio.midi", + "audio/mpeg": "audio.mp3", + "audio/ogg": "audio.ogg", + "audio/vnd.wave": "audio.wav", + "image/bmp": "image.bmp", + "image/gif": "image.gif", + "image/jpeg": "image.jpg", + "image/png": "image.png", + "image/webp": "image.webp", + "image/avif": "image.avif", + "text/plain": "text.txt", + "video/mp4": "video.mp4", + "video/ogg": "video.ogv", + "video/webm": "video.webm", +}; const uploadTokens = new Map(); @@ -92,9 +93,20 @@ class Uploader { } // Force a download in the browser if it's not an allowed type (binary or otherwise unknown) - const contentDisposition = inlineContentDispositionTypes.includes(detectedMimeType) - ? "inline" - : "attachment"; + let slug = req.params.slug; + const isInline = detectedMimeType in inlineContentDispositionTypes; + let disposition = isInline ? "inline" : "attachment"; + + if (!slug && isInline) { + slug = inlineContentDispositionTypes[detectedMimeType]; + } + + if (slug) { + disposition = contentDisposition(slug.trim(), { + fallback: false, + type: disposition, + }); + } if (detectedMimeType === "audio/vnd.wave") { // Send a more common mime type for wave audio files @@ -102,7 +114,7 @@ class Uploader { detectedMimeType = "audio/wav"; } - res.setHeader("Content-Disposition", contentDisposition); + res.setHeader("Content-Disposition", disposition); res.setHeader("Cache-Control", "max-age=86400"); res.contentType(detectedMimeType); From 3a42b5385e786fdc7d872cfab6fa46647be119af Mon Sep 17 00:00:00 2001 From: Nachtalb Date: Sun, 11 Apr 2021 15:43:42 +0200 Subject: [PATCH 2/2] Support inline flac audio --- src/plugins/uploader.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/uploader.js b/src/plugins/uploader.js index 3effac7c..3b5dd9ca 100644 --- a/src/plugins/uploader.js +++ b/src/plugins/uploader.js @@ -20,6 +20,7 @@ const inlineContentDispositionTypes = { "audio/mpeg": "audio.mp3", "audio/ogg": "audio.ogg", "audio/vnd.wave": "audio.wav", + "audio/flac": "audio.flac", "image/bmp": "image.bmp", "image/gif": "image.gif", "image/jpeg": "image.jpg",