Compare commits

...

1 Commits

Author SHA1 Message Date
Henry
cb10b45e95 fix: encode attachment filename header to support non-ASCII characters 2026-06-09 12:11:16 +01:00
4 changed files with 19 additions and 5 deletions

View File

@@ -67,8 +67,15 @@ export default withRateLimit(
return res.status(400).json({ error: "File too large" }); return res.status(400).json({ error: "File too large" });
} }
const originalFilenameHeader = const rawFilenameHeader =
(req.headers["x-original-filename"] as string | undefined) ?? "file"; (req.headers["x-original-filename"] as string | undefined) ?? "file";
const originalFilenameHeader = (() => {
try {
return decodeURIComponent(rawFilenameHeader);
} catch {
return rawFilenameHeader;
}
})();
const sanitizedFilename = originalFilenameHeader const sanitizedFilename = originalFilenameHeader
.replace(/[^a-zA-Z0-9._-]/g, "_") .replace(/[^a-zA-Z0-9._-]/g, "_")

View File

@@ -64,8 +64,15 @@ export default withRateLimit(
return res.status(400).json({ error: "File too large" }); return res.status(400).json({ error: "File too large" });
} }
const originalFilenameHeader = const rawFilenameHeader =
(req.headers["x-original-filename"] as string | undefined) ?? "file"; (req.headers["x-original-filename"] as string | undefined) ?? "file";
const originalFilenameHeader = (() => {
try {
return decodeURIComponent(rawFilenameHeader);
} catch {
return rawFilenameHeader;
}
})();
const sanitizedFilename = originalFilenameHeader const sanitizedFilename = originalFilenameHeader
.replace(/[^a-zA-Z0-9._-]/g, "_") .replace(/[^a-zA-Z0-9._-]/g, "_")

View File

@@ -1,4 +1,5 @@
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { env } from "next-runtime-env";
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { HiOutlinePaperClip } from "react-icons/hi"; import { HiOutlinePaperClip } from "react-icons/hi";
import { HiCheckBadge } from "react-icons/hi2"; import { HiCheckBadge } from "react-icons/hi2";
@@ -7,7 +8,6 @@ import { twMerge } from "tailwind-merge";
import Button from "~/components/Button"; import Button from "~/components/Button";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { env } from "next-runtime-env";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation"; import { invalidateCard } from "~/utils/cardInvalidation";
@@ -30,7 +30,7 @@ export function AttachmentUpload({ cardPublicId }: { cardPublicId: string }) {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": file.type, "Content-Type": file.type,
"x-original-filename": file.name, "x-original-filename": encodeURIComponent(file.name),
}, },
body: file, body: file,
}, },

View File

@@ -172,7 +172,7 @@ export default function Avatar({
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": blob.type, "Content-Type": blob.type,
"x-original-filename": fileName, "x-original-filename": encodeURIComponent(fileName),
}, },
body: blob, body: blob,
}, },