feat: blacklist extensions for strip tags

GIFs are known to not work without custom globally-installed libvips
with ImageMagick or GraphicsMagick support.
https://sharp.pixelplumbing.com/api-output#gif
https://sharp.pixelplumbing.com/install#custom-libvips

It's highly recommended to update your config following the changes to
the sample config file.

This also addressed a bug where images would still get recorded to DB
despite them not existing physically due to strip tags errors.
This commit is contained in:
Bobby Wibowo 2021-02-01 06:13:37 +07:00
parent 274d922b2f
commit ae6d7936c7
No known key found for this signature in database
GPG Key ID: 51C3A1E1E22D26CF
2 changed files with 27 additions and 6 deletions

View File

@ -474,11 +474,11 @@ module.exports = {
/*
Thumbnails are only used in the dashboard and album's public pages.
You need to install a separate binary called ffmpeg (https://ffmpeg.org/) for video thumbnails.
NOTE: Placeholder defaults to 'public/images/unavailable.png'.
*/
generateThumbs: {
image: true,
video: false,
// Placeholder defaults to 'public/images/unavailable.png'.
placeholder: null,
size: 200
},
@ -503,7 +503,14 @@ module.exports = {
stripTags: {
default: false,
video: false,
force: false
force: false,
// Supporting the extensions below requires using custom globally-installed libvips.
// https://sharp.pixelplumbing.com/install#custom-libvips
blacklistExtensions: [
// GIFs require libvips compiled with ImageMagick/GraphicsMagick support.
// https://sharp.pixelplumbing.com/api-output#gif
'.gif'
]
},
/*

View File

@ -8,6 +8,7 @@ const paths = require('./pathsController')
const perms = require('./permissionController')
const apiErrorsHandler = require('./handlers/apiErrorsHandler')
const ClientError = require('./utils/ClientError')
const ServerError = require('./utils/ServerError')
const config = require('./../config')
const logger = require('./../logger')
const db = require('knex')(config.database)
@ -32,6 +33,10 @@ const self = {
videoExts: ['.3g2', '.3gp', '.asf', '.avchd', '.avi', '.divx', '.evo', '.flv', '.h264', '.h265', '.hevc', '.m2p', '.m2ts', '.m4v', '.mk3d', '.mkv', '.mov', '.mp4', '.mpeg', '.mpg', '.mxf', '.ogg', '.ogv', '.ps', '.qt', '.rmvb', '.ts', '.vob', '.webm', '.wmv'],
audioExts: ['.flac', '.mp3', '.wav', '.wma'],
stripTagsBlacklistedExts: Array.isArray(config.uploads.stripTags.blacklistExtensions)
? config.uploads.stripTags.blacklistExtensions
: [],
thumbsSize: config.uploads.generateThumbs.size || 200,
ffprobe: promisify(ffmpeg.ffprobe),
@ -309,7 +314,7 @@ self.generateThumbs = async (name, extname, force) => {
return false
}
} catch (error) {
logger.error(`[${name}]: ${error.toString().trim()}`)
logger.error(`[${name}]: generateThumbs(): ${error.toString().trim()}`)
try {
await paths.unlink(thumbname).catch(() => {}) // try to unlink incomplete thumbs first
await paths.symlink(paths.thumbPlaceholder, thumbname)
@ -325,8 +330,10 @@ self.generateThumbs = async (name, extname, force) => {
self.stripTags = async (name, extname) => {
extname = extname.toLowerCase()
if (self.stripTagsBlacklistedExts.includes(extname)) return false
const fullpath = path.join(paths.uploads, name)
let tmpfile
let tmpfile, isError
try {
if (self.imageExts.includes(extname)) {
@ -351,9 +358,12 @@ self.stripTags = async (name, extname) => {
.on('end', () => resolve(true))
.run()
})
} else {
return false
}
} catch (error) {
logger.error(`[${name}]: ${error.toString().trim()}`)
logger.error(`[${name}]: stripTags(): ${error.toString().trim()}`)
isError = true
}
if (tmpfile) {
@ -361,11 +371,15 @@ self.stripTags = async (name, extname) => {
await paths.unlink(tmpfile)
} catch (error) {
if (error.code !== 'ENOENT') {
logger.error(`[${name}]: ${error.toString().trim()}`)
logger.error(`[${name}]: stripTags(): ${error.toString().trim()}`)
}
}
}
if (isError) {
throw new ServerError('An error occurred while stripping tags. The format may not be supported.')
}
return true
}