fix(api,frontend): isolate active share files and allowlist link schemes
This commit is contained in:
1 parent
0399145791
commit
c832513e5c
10 files changed
+75
-16
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import type { EntityView } from "$lib/api/types";
|
||||
import { safeHref } from "$lib/format/url";
|
||||
|
||||
export interface TextNode {
|
||||
kind: "text";
|
||||
@@ -61,12 +62,6 @@ export function buildEntityTree(
|
||||
return buildNodes(text, sorted, 0, text.length);
|
||||
}
|
||||
|
||||
const PROTOCOL_RE = /^[a-z]+:/i;
|
||||
|
||||
function ensureProtocol(url: string): string {
|
||||
return PROTOCOL_RE.test(url) ? url : `https://${url}`;
|
||||
}
|
||||
|
||||
export function nodeText(node: EntityTreeNode): string {
|
||||
if (node.kind === "text") {
|
||||
return node.text;
|
||||
@@ -74,10 +69,10 @@ export function nodeText(node: EntityTreeNode): string {
|
||||
return node.children.map(nodeText).join("");
|
||||
}
|
||||
|
||||
export function linkHref(node: EntityNode): string {
|
||||
export function linkHref(node: EntityNode): string | undefined {
|
||||
const { entity } = node;
|
||||
if (entity.type === "text_link" && entity.url) {
|
||||
return ensureProtocol(entity.url);
|
||||
return safeHref(entity.url);
|
||||
}
|
||||
if (entity.type === "email") {
|
||||
return `mailto:${nodeText(node)}`;
|
||||
@@ -85,7 +80,7 @@ export function linkHref(node: EntityNode): string {
|
||||
if (entity.type === "phone_number") {
|
||||
return `tel:${nodeText(node)}`;
|
||||
}
|
||||
return ensureProtocol(nodeText(node));
|
||||
return safeHref(nodeText(node));
|
||||
}
|
||||
|
||||
const EMOJI_RE = /\p{Extended_Pictographic}/u;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
const SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;
|
||||
const SAFE_SCHEMES = new Set(["http", "https", "tg", "ton", "mailto", "tel"]);
|
||||
|
||||
export function safeHref(url: string | null | undefined): string | undefined {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
const trimmed = url.trim();
|
||||
const scheme = SCHEME_RE.exec(trimmed)?.[1].toLowerCase();
|
||||
if (scheme === undefined) {
|
||||
return `https://${trimmed}`;
|
||||
}
|
||||
return SAFE_SCHEMES.has(scheme) ? trimmed : undefined;
|
||||
}
|
||||
Reference in new issue
Block a user