From cca6e4a2de9be6152a89dcb579d95e3f72ffe3cc Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 7 Aug 2023 13:58:49 +0000 Subject: [PATCH] enhance(backend): Improve behavior of correctFilename --- packages/backend/package.json | 1 + packages/backend/src/misc/correct-filename.ts | 53 ++++++++++++++++--- .../test/unit/misc/correct-filename.ts | 36 +++++++++++++ pnpm-lock.yaml | 16 ++++-- 4 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 packages/backend/test/unit/misc/correct-filename.ts diff --git a/packages/backend/package.json b/packages/backend/package.json index 8c5b67ced6..a8ec49d196 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -154,6 +154,7 @@ "stringz": "2.1.0", "summaly": "github:misskey-dev/summaly", "systeminformation": "5.18.9", + "text-extensions": "^2.4.0", "tinycolor2": "1.6.0", "tmp": "0.2.1", "tsc-alias": "1.8.7", diff --git a/packages/backend/src/misc/correct-filename.ts b/packages/backend/src/misc/correct-filename.ts index a702f0be0d..b4d2611062 100644 --- a/packages/backend/src/misc/correct-filename.ts +++ b/packages/backend/src/misc/correct-filename.ts @@ -3,17 +3,56 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -// 与えられた拡張子とファイル名が一致しているかどうかを確認し、 -// 一致していない場合は拡張子を付与して返す +import textExts from 'text-extensions'; + +/** + * Array.includes()よりSet.has()の方が高速 + */ + +const targetExtsToSkip = new Set([ + 'gz', + 'tar', + 'tgz', + 'bz2', + 'xz', + 'zip', + '7z', +]); + +const sourceExtsToSkip = new Set(textExts); + +const extRegExp = /\.([0-9a-zA-Z]+$)/i; + +/** + * 与えられた拡張子とファイル名が一致しているかどうかを確認し、 + * 一致していない場合は拡張子を付与して返す + * + * extはfile-typeのextを想定 + */ export function correctFilename(filename: string, ext: string | null) { const dotExt = ext ? ext.startsWith('.') ? ext : `.${ext}` : '.unknown'; - if (filename.endsWith(dotExt)) { + + const match = extRegExp.exec(filename); + if (!match || !match[1]) { + return `${filename}${dotExt}`; + } + const filenameExt = match[1].toLowerCase(); + if (filenameExt === ext) { return filename; } - if (ext === 'jpg' && filename.endsWith('.jpeg')) { - return filename; - } - if (ext === 'tif' && filename.endsWith('.tiff')) { + + if ( + ext === 'jpg' && filenameExt === 'jpeg' || + ext === 'tif' && filenameExt === 'tiff' || + + // 圧縮形式っぽければ下手に拡張子を変えない + // https://github.com/misskey-dev/misskey/issues/11482 + ext !== null && targetExtsToSkip.has(ext) || + + // テキストファイル?(ext === null)かつ拡張子がテキストファイルっぽい場合は + // 拡張子を変えない + ext === null && sourceExtsToSkip.has(filenameExt) + ) { return filename; } return `${filename}${dotExt}`; diff --git a/packages/backend/test/unit/misc/correct-filename.ts b/packages/backend/test/unit/misc/correct-filename.ts new file mode 100644 index 0000000000..155b38e5cb --- /dev/null +++ b/packages/backend/test/unit/misc/correct-filename.ts @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { correctFilename } from '@/misc/correct-filename.js'; + +describe(correctFilename, () => { + it('no ext to null', () => { + expect(correctFilename('test', null)).toBe('test.unknown'); + }); + it('no ext to jpg', () => { + expect(correctFilename('test', 'jpg')).toBe('test.jpg'); + }); + it('jpg to webp', () => { + expect(correctFilename('test.jpg', 'webp')).toBe('test.jpg.webp'); + }); + it('jpeg to jpg', () => { + expect(correctFilename('test.jpeg', 'jpg')).toBe('test.jpeg'); + }); + it('JPEG to jpg', () => { + expect(correctFilename('test.JPEG', 'jpg')).toBe('test.JPEG'); + }); + it('jpg to jpg', () => { + expect(correctFilename('test.jpg', 'jpg')).toBe('test.jpg'); + }); + it('tiff to tif', () => { + expect(correctFilename('test.tiff', 'tif')).toBe('test.tiff'); + }); + it('skip gz', () => { + expect(correctFilename('test.unitypackage', 'gz')).toBe('test.unitypackage'); + }); + it('skip text file', () => { + expect(correctFilename('test.txt', null)).toBe('test.txt'); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 13fc490731..441367fa01 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -358,10 +358,13 @@ importers: version: 2.1.0 summaly: specifier: github:misskey-dev/summaly - version: github.com/misskey-dev/summaly/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc + version: github.com/misskey-dev/summaly/d2d8db49943ccb201c1b1b283e9d0a630519fac7 systeminformation: specifier: 5.18.9 version: 5.18.9 + text-extensions: + specifier: ^2.4.0 + version: 2.4.0 tinycolor2: specifier: 1.6.0 version: 1.6.0 @@ -997,7 +1000,7 @@ importers: version: github.com/misskey-dev/storybook-addon-misskey-theme/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@7.0.27)(@storybook/components@7.1.0)(@storybook/core-events@7.0.27)(@storybook/manager-api@7.0.27)(@storybook/preview-api@7.0.27)(@storybook/theming@7.0.27)(@storybook/types@7.0.27)(react-dom@18.2.0)(react@18.2.0) summaly: specifier: github:misskey-dev/summaly - version: github.com/misskey-dev/summaly/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc + version: github.com/misskey-dev/summaly/d2d8db49943ccb201c1b1b283e9d0a630519fac7 vite-plugin-turbosnap: specifier: 1.0.2 version: 1.0.2 @@ -20428,6 +20431,11 @@ packages: resolution: {integrity: sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==} dev: false + /text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + dev: false + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true @@ -22129,8 +22137,8 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true - github.com/misskey-dev/summaly/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc: - resolution: {tarball: https://codeload.github.com/misskey-dev/summaly/tar.gz/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc} + github.com/misskey-dev/summaly/d2d8db49943ccb201c1b1b283e9d0a630519fac7: + resolution: {tarball: https://codeload.github.com/misskey-dev/summaly/tar.gz/d2d8db49943ccb201c1b1b283e9d0a630519fac7} name: summaly version: 4.0.2 dependencies: