chore: scope onboarding pack to iOS and pairing surfaces

This commit is contained in:
Mariano Belinky
2026-02-16 15:21:36 +00:00
committed by Mariano Belinky
parent 7ed2e1bfe9
commit a07790c384
3 changed files with 0 additions and 84 deletions

View File

@@ -451,6 +451,3 @@ export type { ProcessedLineMessage } from "../line/markdown-to-line.js";
// Media utilities
export { loadWebMedia, type WebMediaResult } from "../web/media.js";
// QR code utilities
export { renderQrPngBase64 } from "../web/qr-image.js";

View File

@@ -413,32 +413,4 @@ describe("local media root guard", () => {
}),
);
});
it("loads base64 data URLs", async () => {
const pngBuffer = await sharp({
create: { width: 2, height: 2, channels: 3, background: "#00aaff" },
})
.png()
.toBuffer();
const dataUrl = `data:image/png;base64,${pngBuffer.toString("base64")}`;
const result = await loadWebMedia(dataUrl, 1024 * 1024);
expect(result.kind).toBe("image");
expect(result.contentType).toBe("image/jpeg");
expect(result.buffer.length).toBeGreaterThan(0);
});
it("rejects non-base64 data URLs", async () => {
await expect(loadWebMedia("data:image/png,hello", 1024)).rejects.toThrow(
/Only base64 data: URLs are supported/i,
);
});
it("rejects oversized base64 data URLs before decode", async () => {
const body = Buffer.alloc(4096, 1).toString("base64");
const dataUrl = `data:application/octet-stream;base64,${body}`;
await expect(loadWebMediaRaw(dataUrl, 128)).rejects.toThrow(/exceeds .*limit/i);
});
});

View File

@@ -91,8 +91,6 @@ async function assertLocalMediaAllowed(
const HEIC_MIME_RE = /^image\/hei[cf]$/i;
const HEIC_EXT_RE = /\.(heic|heif)$/i;
const DATA_URL_RE = /^data:([^;,]+)?(;base64)?,(.*)$/i;
const BASE64_BODY_RE = /^[A-Za-z0-9+/]*={0,2}$/;
const MB = 1024 * 1024;
function formatMb(bytes: number, digits = 2): string {
@@ -132,38 +130,6 @@ function toJpegFileName(fileName?: string): string | undefined {
return path.format({ dir: parsed.dir, name: parsed.name, ext: ".jpg" });
}
function parseBase64DataUrl(mediaUrl: string): { contentType: string; base64Body: string } | null {
const match = mediaUrl.match(DATA_URL_RE);
if (!match) {
return null;
}
if (!match[2]) {
throw new Error("Only base64 data: URLs are supported");
}
const contentType = match[1] || "application/octet-stream";
const base64Body = (match[3] || "").replaceAll(/\s+/g, "");
if (base64Body.length === 0) {
return { contentType, base64Body };
}
if (!BASE64_BODY_RE.test(base64Body) || base64Body.length % 4 === 1) {
throw new Error("Invalid base64 data in data: URL");
}
return { contentType, base64Body };
}
function estimateDecodedBase64Bytes(base64Body: string): number {
if (base64Body.length === 0) {
return 0;
}
let padding = 0;
if (base64Body.endsWith("==")) {
padding = 2;
} else if (base64Body.endsWith("=")) {
padding = 1;
}
return Math.floor((base64Body.length * 3) / 4) - padding;
}
type OptimizedImage = {
buffer: Buffer;
optimizedSize: number;
@@ -307,25 +273,6 @@ async function loadWebMediaInternal(
};
};
const parsedDataUrl = parseBase64DataUrl(mediaUrl);
if (parsedDataUrl) {
const { contentType, base64Body } = parsedDataUrl;
const kind = mediaKindFromMime(contentType);
const defaultFetchCap = maxBytesForKind("unknown");
const decodeCap =
maxBytes === undefined
? defaultFetchCap
: optimizeImages && kind === "image"
? Math.max(maxBytes, defaultFetchCap)
: maxBytes;
const estimatedBytes = estimateDecodedBase64Bytes(base64Body);
if (estimatedBytes > decodeCap) {
throw new Error(formatCapLimit("Media", decodeCap, estimatedBytes));
}
const buffer = Buffer.from(base64Body, "base64");
return await clampAndFinalize({ buffer, contentType, kind });
}
if (/^https?:\/\//i.test(mediaUrl)) {
// Enforce a download cap during fetch to avoid unbounded memory usage.
// For optimized images, allow fetching larger payloads before compression.