From 8f0ed03117c46b576e06ddea7dd8d84885d25141 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Sat, 27 May 2023 19:14:13 +0800 Subject: [PATCH] filter zip name --- tasks/export_zip.ts | 4 ++-- utils.ts | 23 +++++++++++++++++++++++ utils_test.ts | 14 +++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/tasks/export_zip.ts b/tasks/export_zip.ts index fdee5f2..526fed7 100644 --- a/tasks/export_zip.ts +++ b/tasks/export_zip.ts @@ -1,7 +1,7 @@ import { join } from "std/path/mod.ts"; import { Uint8ArrayReader, ZipWriter } from "zipjs/index.js"; import { EhDb } from "../db.ts"; -import { addZero, asyncForEach } from "../utils.ts"; +import { addZero, asyncForEach, filterFilename } from "../utils.ts"; import { Config } from "../config.ts"; import { Task } from "../task.ts"; @@ -22,7 +22,7 @@ export async function export_zip( const g = db.get_gmeta_by_gid(gid); if (!g) throw Error("Gallery not found in database."); const output = ecfg.output === undefined - ? join(cfg.base, g.title + ".zip") + ? join(cfg.base, filterFilename(g.title + ".zip")) : ecfg.output; const f = await Deno.open(output, { create: true, diff --git a/utils.ts b/utils.ts index b88273d..963d954 100644 --- a/utils.ts +++ b/utils.ts @@ -1,4 +1,5 @@ import { exists, existsSync } from "std/fs/exists.ts"; +import { extname } from "std/path/mod.ts"; import { initParser } from "deno_dom/deno-dom-wasm-noinit.ts"; export function sleep(time: number): Promise { @@ -111,3 +112,25 @@ export function addZero(n: string | number, len: number) { while (s.length < len) s = "0" + s; return s; } + +export function filterFilename(p: string, maxLength = 256) { + // strip control chars + p = p.replace(/\p{C}/gu, ""); + // normalize newline + p = p.replace(/[\n\r]/g, ""); + p = p.replace(/\p{Zl}/gu, ""); + p = p.replace(/\p{Zp}/gu, ""); + // normalize space + p = p.replace(/\p{Zs}/gu, " "); + p = p.replace(/[\\/]/g, "_"); + if (Deno.build.os == "windows") { + p = p.replace(/[:\*\?\"<>\|]/g, "_"); + } else if (Deno.build.os == "linux") { + p = p.replace(/[!\$\"]/g, "_"); + } + if (p.length > maxLength) { + const ext = extname(p); + return p.slice(0, maxLength - ext.length) + ext; + } + return p; +} diff --git a/utils_test.ts b/utils_test.ts index 2c5112a..6e9f942 100644 --- a/utils_test.ts +++ b/utils_test.ts @@ -3,6 +3,7 @@ import { check_running } from "./pid_check.ts"; import { asyncFilter, asyncForEach, + filterFilename, promiseState, PromiseStatus, sleep, @@ -49,7 +50,7 @@ Deno.test("asyncFilter_test", async () => { await Promise.allSettled(e); }); -Deno.test("asyncForEach", async () => { +Deno.test("asyncForEach_test", async () => { const e = [new Promise((res) => setTimeout(() => res(100), 100))]; const t = { test: 2 }; await asyncForEach(e, async function (e) { @@ -57,3 +58,14 @@ Deno.test("asyncForEach", async () => { await e; }, t); }); + +Deno.test("filterFilename_test", () => { + assertEquals(filterFilename("abcdef.ts", 5), "ab.ts"); + assertEquals(filterFilename("\x00df\t\r.ts"), "df.ts"); + assertEquals(filterFilename("a\u200bd.ts"), "ad.ts"); + assertEquals(filterFilename("中文.ts"), "中文.ts"); + assertEquals(filterFilename("d\\s/.ts"), "d_s_.ts"); + if (Deno.build.os == "windows") { + assertEquals(filterFilename("d|?ad.ts"), "d__ad.ts"); + } +});