mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-10-25 17:22:27 +08:00
The icon picker gets an "Upload Image" button (PNG, JPG, WebP or SVG, up to 2 MB and 4096 px). The image is redrawn on a canvas into a 96x96 PNG and stored as a data URI in the existing `icon` column, so it travels with the row through cloud sync, duplication and profiles. No new column, no files on disk, nothing keyed by provider id (ids are shared across apps). Opaque square images fill the icon box; anything else is padded to the size of a built-in transparent logo. Uploading only changes the form; nothing is written until Save. The original file never reaches the database: SVG is loaded through <img> (no scripts, no external requests) and rasterized, and re-encoding drops EXIF. Custom icons are only ever rendered with <img>; remote URLs are never loaded as icons. Validation at every way in: - Saving a provider or a universal provider, and syncing a universal provider to its apps, fully decodes the PNG with the `png` crate (already in the tree via `image`) under a 1 MiB decode limit and caps it at 64 KiB and 256x256. Other strings still pass as icon names so old rows stay editable. - SQL import and cloud sync bypass saving, so the staging database drops invalid custom icons from both `providers` and the universal provider JSON before it replaces the main one. The rest of the backup imports normally. - Rendering checks the length and reads the PNG signature, IHDR length and dimensions from the header before showing an image, and falls back to initials if it fails to decode. Browsers sniff image formats, so without the signature check a disguised GIF could slip past the size limit. Also: - Uploads still being processed are dropped once the user removes the icon, picks a built-in one, uploads again or closes the picker. - Aggregation mode no longer derives model key prefixes from a custom icon; it falls back to the provider name. - The deep-link `icon` parameter only accepts built-in icon names; other values are dropped instead of failing the link, so links cannot put a data URI straight into the database. Refs #8117
18 lines
620 B
TypeScript
18 lines
620 B
TypeScript
import { CUSTOM_ICON_PREFIX } from "@/utils/customIcon";
|
|
|
|
/** 只有签名和 IHDR 的 PNG 文件头,够渲染前的检查用(jsdom 不解码图片) */
|
|
export function pngDataUri(width: number, height: number): string {
|
|
const bytes = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0, 0, 0, 13];
|
|
bytes.push(..."IHDR".split("").map((c) => c.charCodeAt(0)));
|
|
for (const n of [width, height]) {
|
|
bytes.push(
|
|
(n >>> 24) & 0xff,
|
|
(n >>> 16) & 0xff,
|
|
(n >>> 8) & 0xff,
|
|
n & 0xff,
|
|
);
|
|
}
|
|
bytes.push(8, 6, 0, 0, 0);
|
|
return CUSTOM_ICON_PREFIX + btoa(String.fromCharCode(...bytes));
|
|
}
|