




























@@ -0,0 +1,142 @@
1+import fs from "node:fs/promises";
2+import path from "node:path";
3+import { describe, expect, it } from "vitest";
4+import { resolveStateDir } from "../config/paths.js";
5+import {
6+classifyMediaReferenceSource,
7+MediaReferenceError,
8+normalizeMediaReferenceSource,
9+resolveInboundMediaReference,
10+resolveMediaReferenceLocalPath,
11+} from "./media-reference.js";
12+13+describe("media reference helpers", () => {
14+it("normalizes outbound MEDIA tags without changing canonical media URIs", () => {
15+expect(normalizeMediaReferenceSource(" MEDIA: ./out.png")).toBe("./out.png");
16+expect(normalizeMediaReferenceSource("media://inbound/a.png")).toBe("media://inbound/a.png");
17+});
18+19+it("classifies supported and unsupported media reference schemes", () => {
20+expect(classifyMediaReferenceSource("media://inbound/a.png")).toMatchObject({
21+isMediaStoreUrl: true,
22+hasUnsupportedScheme: false,
23+});
24+expect(classifyMediaReferenceSource("data:image/png;base64,cG5n")).toMatchObject({
25+isDataUrl: true,
26+hasUnsupportedScheme: false,
27+});
28+expect(
29+classifyMediaReferenceSource("data:image/png;base64,cG5n", { allowDataUrl: false }),
30+).toMatchObject({
31+isDataUrl: true,
32+hasUnsupportedScheme: true,
33+});
34+expect(classifyMediaReferenceSource("ftp://example.test/a.png")).toMatchObject({
35+hasUnsupportedScheme: true,
36+});
37+expect(classifyMediaReferenceSource("C:\\Users\\pete\\image.png")).toMatchObject({
38+looksLikeWindowsDrivePath: true,
39+hasUnsupportedScheme: false,
40+});
41+});
42+43+it("resolves canonical inbound media URIs", async () => {
44+const stateDir = resolveStateDir();
45+const id = `ref-${Date.now()}-${Math.random().toString(36).slice(2)}.png`;
46+const filePath = path.join(stateDir, "media", "inbound", id);
47+await fs.mkdir(path.dirname(filePath), { recursive: true });
48+await fs.writeFile(filePath, Buffer.from("png"));
49+50+try {
51+await expect(resolveInboundMediaReference(`media://inbound/${id}`)).resolves.toMatchObject({
52+ id,
53+normalizedSource: `media://inbound/${id}`,
54+physicalPath: filePath,
55+sourceType: "uri",
56+});
57+} finally {
58+await fs.rm(filePath, { force: true });
59+}
60+});
61+62+it("maps canonical inbound media URIs to local paths for direct file readers", async () => {
63+const stateDir = resolveStateDir();
64+const id = `ref-local-path-${Date.now()}-${Math.random().toString(36).slice(2)}.png`;
65+const filePath = path.join(stateDir, "media", "inbound", id);
66+await fs.mkdir(path.dirname(filePath), { recursive: true });
67+await fs.writeFile(filePath, Buffer.from("png"));
68+69+try {
70+await expect(resolveMediaReferenceLocalPath(`media://inbound/${id}`)).resolves.toBe(filePath);
71+await expect(resolveMediaReferenceLocalPath(" MEDIA: ./out.png")).resolves.toBe("./out.png");
72+} finally {
73+await fs.rm(filePath, { force: true });
74+}
75+});
76+77+it("resolves direct absolute paths only for first-level inbound media files", async () => {
78+const stateDir = resolveStateDir();
79+const id = `ref-path-${Date.now()}-${Math.random().toString(36).slice(2)}.png`;
80+const filePath = path.join(stateDir, "media", "inbound", id);
81+await fs.mkdir(path.dirname(filePath), { recursive: true });
82+await fs.writeFile(filePath, Buffer.from("png"));
83+84+try {
85+await expect(resolveInboundMediaReference(filePath)).resolves.toMatchObject({
86+ id,
87+physicalPath: filePath,
88+sourceType: "path",
89+});
90+await expect(
91+resolveInboundMediaReference(path.join(stateDir, "media", "inbound", "nested", id)),
92+).resolves.toBeNull();
93+await expect(
94+resolveInboundMediaReference(path.join(stateDir, "media", "outbound", id)),
95+).resolves.toBeNull();
96+} finally {
97+await fs.rm(filePath, { force: true });
98+}
99+});
100+101+it("rejects inbound media URIs with unsupported locations or unsafe ids", async () => {
102+await expect(resolveInboundMediaReference("media://outbound/a.png")).rejects.toMatchObject({
103+code: "path-not-allowed",
104+});
105+await expect(
106+resolveInboundMediaReference("media://inbound/nested%2Fa.png"),
107+).rejects.toBeInstanceOf(MediaReferenceError);
108+await expect(
109+resolveInboundMediaReference("media://inbound/nested%2Fa.png"),
110+).rejects.toMatchObject({ code: "invalid-path" });
111+await expect(resolveInboundMediaReference("media://inbound/")).rejects.toMatchObject({
112+code: "invalid-path",
113+});
114+await expect(resolveInboundMediaReference("media://inbound/%00.png")).rejects.toMatchObject({
115+code: "invalid-path",
116+});
117+});
118+119+it("rejects symlinked inbound media files", async () => {
120+const stateDir = resolveStateDir();
121+const targetDir = path.join(stateDir, "media-reference-test-target");
122+const targetPath = path.join(targetDir, "target.png");
123+const id = `ref-link-${Date.now()}-${Math.random().toString(36).slice(2)}.png`;
124+const linkPath = path.join(stateDir, "media", "inbound", id);
125+await fs.mkdir(targetDir, { recursive: true });
126+await fs.mkdir(path.dirname(linkPath), { recursive: true });
127+await fs.writeFile(targetPath, Buffer.from("png"));
128+await fs.symlink(targetPath, linkPath);
129+130+try {
131+await expect(resolveInboundMediaReference(`media://inbound/${id}`)).rejects.toMatchObject({
132+code: "invalid-path",
133+});
134+await expect(resolveInboundMediaReference(linkPath)).rejects.toMatchObject({
135+code: "invalid-path",
136+});
137+} finally {
138+await fs.rm(linkPath, { force: true });
139+await fs.rm(targetDir, { recursive: true, force: true });
140+}
141+});
142+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。