diff --git a/client/plugins/init.client.js b/client/plugins/init.client.js index bf3a6734..bdc1b2f5 100644 --- a/client/plugins/init.client.js +++ b/client/plugins/init.client.js @@ -1,4 +1,5 @@ import Vue from 'vue' +import Path from 'path' import vClickOutside from 'v-click-outside' import { formatDistance, format, addDays, isDate } from 'date-fns' @@ -119,20 +120,36 @@ Vue.prototype.$sanitizeFilename = (input, colonReplacement = ' - ') => { if (typeof input !== 'string') { return false } + + // Max is actually 255-260 for windows but this leaves padding incase ext wasnt put on yet + const MAX_FILENAME_LEN = 240 + var replacement = '' - var illegalRe = /[\/\?<>\\:\*\|"]/g; - var controlRe = /[\x00-\x1f\x80-\x9f]/g; - var reservedRe = /^\.+$/; - var windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i; - var windowsTrailingRe = /[\. ]+$/; + var illegalRe = /[\/\?<>\\:\*\|"]/g + var controlRe = /[\x00-\x1f\x80-\x9f]/g + var reservedRe = /^\.+$/ + var windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i + var windowsTrailingRe = /[\. ]+$/ + var lineBreaks = /[\n\r]/g var sanitized = input .replace(':', colonReplacement) // Replace first occurrence of a colon .replace(illegalRe, replacement) .replace(controlRe, replacement) .replace(reservedRe, replacement) + .replace(lineBreaks, replacement) .replace(windowsReservedRe, replacement) - .replace(windowsTrailingRe, replacement); + .replace(windowsTrailingRe, replacement) + + + if (sanitized.length > MAX_FILENAME_LEN) { + var lenToRemove = sanitized.length - MAX_FILENAME_LEN + var ext = Path.extname(sanitized) + var basename = Path.basename(sanitized, ext) + basename = basename.slice(0, basename.length - lenToRemove) + sanitized = basename + ext + } + return sanitized } diff --git a/server/objects/PodcastEpisodeDownload.js b/server/objects/PodcastEpisodeDownload.js index fd083abf..09b9d71d 100644 --- a/server/objects/PodcastEpisodeDownload.js +++ b/server/objects/PodcastEpisodeDownload.js @@ -21,7 +21,6 @@ class PodcastEpisodeDownload { toJSONForClient() { return { id: this.id, - // podcastEpisode: this.podcastEpisode ? this.podcastEpisode.toJSON() : null, episodeDisplayTitle: this.podcastEpisode ? this.podcastEpisode.bestFilename : null, url: this.url, libraryItemId: this.libraryItem ? this.libraryItem.id : null, diff --git a/server/utils/fileUtils.js b/server/utils/fileUtils.js index a0db36ee..b2b0a85b 100644 --- a/server/utils/fileUtils.js +++ b/server/utils/fileUtils.js @@ -181,19 +181,33 @@ module.exports.sanitizeFilename = (filename, colonReplacement = ' - ') => { return false } + // Max is actually 255-260 for windows but this leaves padding incase ext wasnt put on yet + const MAX_FILENAME_LEN = 240 + var replacement = '' - var illegalRe = /[\/\?<>\\:\*\|"]/g; - var controlRe = /[\x00-\x1f\x80-\x9f]/g; - var reservedRe = /^\.+$/; - var windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i; - var windowsTrailingRe = /[\. ]+$/; + var illegalRe = /[\/\?<>\\:\*\|"]/g + var controlRe = /[\x00-\x1f\x80-\x9f]/g + var reservedRe = /^\.+$/ + var windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i + var windowsTrailingRe = /[\. ]+$/ + var lineBreaks = /[\n\r]/g sanitized = filename .replace(':', colonReplacement) // Replace first occurrence of a colon .replace(illegalRe, replacement) .replace(controlRe, replacement) .replace(reservedRe, replacement) + .replace(lineBreaks, replacement) .replace(windowsReservedRe, replacement) - .replace(windowsTrailingRe, replacement); + .replace(windowsTrailingRe, replacement) + + if (sanitized.length > MAX_FILENAME_LEN) { + var lenToRemove = sanitized.length - MAX_FILENAME_LEN + var ext = Path.extname(sanitized) + var basename = Path.basename(sanitized, ext) + basename = basename.slice(0, basename.length - lenToRemove) + sanitized = basename + ext + } + return sanitized } \ No newline at end of file