From d8465b1aae0d5513f524fea81ffaba9c10b58093 Mon Sep 17 00:00:00 2001
From: Snazzah <7025343+Snazzah@users.noreply.github.com>
Date: Mon, 30 Aug 2021 14:08:13 +0000
Subject: [PATCH] Add trusted link handling in renderer/prompt
---
src/components/markdown/Renderer.tsx | 39 ++++++++++++-------
.../modals/ExternalLinkPrompt.tsx | 16 ++++++++
2 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/src/components/markdown/Renderer.tsx b/src/components/markdown/Renderer.tsx
index 9fe876b4..5e84d2c1 100644
--- a/src/components/markdown/Renderer.tsx
+++ b/src/components/markdown/Renderer.tsx
@@ -18,13 +18,15 @@ import { useCallback, useContext } from "preact/hooks";
import { internalEmit } from "../../lib/eventEmitter";
+import { getState } from "../../redux";
+
+import { useIntermediate } from "../../context/intermediate/Intermediate";
import { AppContext } from "../../context/revoltjs/RevoltClient";
import { generateEmoji } from "../common/Emoji";
import { emojiDictionary } from "../../assets/emojis";
import { MarkdownProps } from "./Markdown";
-import {useIntermediate} from "../../context/intermediate/Intermediate";
// TODO: global.d.ts file for defining globals
declare global {
@@ -35,9 +37,9 @@ declare global {
const ALLOWED_ORIGINS = [
location.hostname,
- 'app.revolt.chat',
- 'nightly.revolt.chat',
- 'local.revolt.chat',
+ "app.revolt.chat",
+ "nightly.revolt.chat",
+ "local.revolt.chat",
];
// Handler for code block copy.
@@ -176,13 +178,16 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
element.removeAttribute("data-type");
element.removeAttribute("target");
- let internal;
+ let internal,
+ url: URL | null = null;
const href = element.href;
if (href) {
try {
- const url = new URL(href, location.href);
+ url = new URL(href, location.href);
- if (ALLOWED_ORIGINS.includes(url.hostname)) {
+ if (
+ ALLOWED_ORIGINS.includes(url.hostname)
+ ) {
internal = true;
element.addEventListener(
"click",
@@ -202,12 +207,20 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
if (!internal) {
element.setAttribute("target", "_blank");
element.onclick = (ev) => {
- ev.preventDefault();
- openScreen({
- id: "external_link_prompt",
- link: href
- })
- }
+ const { trustedLinks } = getState();
+ if (
+ !url ||
+ !trustedLinks.domains?.includes(
+ url.hostname,
+ )
+ ) {
+ ev.preventDefault();
+ openScreen({
+ id: "external_link_prompt",
+ link: href,
+ });
+ }
+ };
}
},
);
diff --git a/src/context/intermediate/modals/ExternalLinkPrompt.tsx b/src/context/intermediate/modals/ExternalLinkPrompt.tsx
index b0f5e6df..4c90b325 100644
--- a/src/context/intermediate/modals/ExternalLinkPrompt.tsx
+++ b/src/context/intermediate/modals/ExternalLinkPrompt.tsx
@@ -1,6 +1,7 @@
import { Text } from "preact-i18n";
import Modal from "../../../components/ui/Modal";
+import { dispatch } from "../../../redux";
interface Props {
onClose: () => void;
@@ -29,6 +30,21 @@ export function ExternalLinkModal({ onClose, link }: Props) {
confirmation: false,
children: "Cancel",
},
+ {
+ onClick: () => {
+ try {
+ const url = new URL(link);
+ dispatch({
+ type: "TRUSTED_LINKS_ADD_DOMAIN",
+ domain: url.hostname
+ });
+ } catch(e) {}
+ window.open(link, "_blank");
+ onClose();
+ },
+ plain: true,
+ children: "Trust this domain",
+ }
]}>
{link}