refactor(client,server): support for URL schemes

This commit is contained in:
Elian Doran 2025-02-11 22:14:44 +02:00
parent f517e4a37a
commit 4d0969da0a
No known key found for this signature in database
4 changed files with 24 additions and 108 deletions

View File

@ -4,6 +4,15 @@ import appContext, { type NoteCommandData } from "../components/app_context.js";
import froca from "./froca.js"; import froca from "./froca.js";
import utils from "./utils.js"; import utils from "./utils.js";
// Be consistent with `allowedSchemes` in `src\services\html_sanitizer.ts`
// TODO: Deduplicate with server once we can.
export const ALLOWED_PROTOCOLS = [
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git',
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo'
];
function getNotePathFromUrl(url: string) { function getNotePathFromUrl(url: string) {
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url); const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
@ -296,58 +305,7 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent
electron.shell.openPath(hrefLink); electron.shell.openPath(hrefLink);
} else { } else {
// Enable protocols supported by CKEditor 5 to be clickable. // Enable protocols supported by CKEditor 5 to be clickable.
// Refer to `allowedProtocols` in https://github.com/TriliumNext/trilium-ckeditor5/blob/main/packages/ckeditor5-build-balloon-block/src/ckeditor.ts. if (ALLOWED_PROTOCOLS.some((protocol) => hrefLink.toLowerCase().startsWith(protocol + ":"))) {
// And be consistent with `allowedSchemes` in `src\services\html_sanitizer.ts`
const allowedSchemes = [
"http",
"https",
"ftp",
"ftps",
"mailto",
"data",
"evernote",
"file",
"facetime",
"gemini",
"git",
"gopher",
"imap",
"irc",
"irc6",
"jabber",
"jar",
"lastfm",
"ldap",
"ldaps",
"magnet",
"message",
"mumble",
"nfs",
"onenote",
"pop",
"rmi",
"s3",
"sftp",
"skype",
"sms",
"spotify",
"steam",
"svn",
"udp",
"view-source",
"vlc",
"vnc",
"ws",
"wss",
"xmpp",
"jdbc",
"slack",
"tel",
"smb",
"zotero",
"geo"
];
if (allowedSchemes.some((protocol) => hrefLink.toLowerCase().startsWith(protocol + ":"))) {
window.open(hrefLink, "_blank"); window.open(hrefLink, "_blank");
} }
} }

View File

@ -1,3 +1,4 @@
import { ALLOWED_PROTOCOLS } from "../../../services/link.js";
import options from "../../../services/options.js"; import options from "../../../services/options.js";
import utils from "../../../services/utils.js"; import utils from "../../../services/utils.js";
@ -101,12 +102,7 @@ export function buildConfig() {
}, },
link: { link: {
defaultProtocol: 'https://', defaultProtocol: 'https://',
allowedProtocols: [ allowedProtocols: ALLOWED_PROTOCOLS
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git',
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo'
]
}, },
// This value must be kept in sync with the language defined in webpack.config.js. // This value must be kept in sync with the language defined in webpack.config.js.
language: 'en' language: 'en'

View File

@ -2,6 +2,15 @@ import sanitizeHtml from "sanitize-html";
import sanitizeUrl from "@braintree/sanitize-url"; import sanitizeUrl from "@braintree/sanitize-url";
import optionService from "./options.js"; import optionService from "./options.js";
// Be consistent with `ALLOWED_PROTOCOLS` in `src\public\app\services\link.js`
// TODO: Deduplicate with client once we can.
export const ALLOWED_PROTOCOLS = [
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git',
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo'
];
// Default list of allowed HTML tags // Default list of allowed HTML tags
export const DEFAULT_ALLOWED_TAGS = [ export const DEFAULT_ALLOWED_TAGS = [
"h1", "h1",
@ -138,56 +147,7 @@ function sanitize(dirtyHtml: string) {
"*": ["class", "style", "title", "src", "href", "hash", "disabled", "align", "alt", "center", "data-*"], "*": ["class", "style", "title", "src", "href", "hash", "disabled", "align", "alt", "center", "data-*"],
input: ["type", "checked"] input: ["type", "checked"]
}, },
// Be consistent with `allowedSchemes` in `src\public\app\services\link.js` allowedSchemes: ALLOWED_PROTOCOLS,
allowedSchemes: [
"http",
"https",
"ftp",
"ftps",
"mailto",
"data",
"evernote",
"file",
"facetime",
"gemini",
"git",
"gopher",
"imap",
"irc",
"irc6",
"jabber",
"jar",
"lastfm",
"ldap",
"ldaps",
"magnet",
"message",
"mumble",
"nfs",
"onenote",
"pop",
"rmi",
"s3",
"sftp",
"skype",
"sms",
"spotify",
"steam",
"svn",
"udp",
"view-source",
"vlc",
"vnc",
"ws",
"wss",
"xmpp",
"jdbc",
"slack",
"tel",
"smb",
"zotero",
"geo"
],
nonTextTags: ["head"], nonTextTags: ["head"],
transformTags transformTags
}); });

View File

@ -302,7 +302,9 @@ async function importZip(taskContext: TaskContext, fileBuffer: Buffer, importRoo
}); });
if (taskContext.data?.safeImport) { if (taskContext.data?.safeImport) {
console.log("Before", content);
content = htmlSanitizer.sanitize(content); content = htmlSanitizer.sanitize(content);
console.log("After", content);
} }
content = content.replace(/<html.*<body[^>]*>/gis, ""); content = content.replace(/<html.*<body[^>]*>/gis, "");