Escape html with markdown off (#732)
authorAjay Bura <32841439+ajbura@users.noreply.github.com>
Thu, 11 Aug 2022 08:58:39 +0000 (14:28 +0530)
committerAjay Bura <32841439+ajbura@users.noreply.github.com>
Thu, 11 Aug 2022 08:58:39 +0000 (14:28 +0530)
src/app/molecules/message/Message.jsx
src/client/state/RoomsInput.js
src/util/sanitize.js

index 6e3def431fa3f089e49d04e96ac85304e74c4290..e4b68834bae1f766318747ce6091ee4bb94faa86 100644 (file)
@@ -206,7 +206,13 @@ const MessageBody = React.memo(({
   let content = null;
   if (isCustomHTML) {
     try {
-      content = twemojify(sanitizeCustomHtml(body), undefined, true, false, true);
+      content = twemojify(
+        sanitizeCustomHtml(initMatrix.matrixClient, body),
+        undefined,
+        true,
+        false,
+        true,
+      );
     } catch {
       console.error('Malformed custom html: ', body);
       content = twemojify(body, undefined);
index 6b085fb397204dd2b1e2f214e877f3996d094f66..e1d3acf9ae29ab9057d4511b8ed68ed3bce3e4e0 100644 (file)
@@ -6,6 +6,7 @@ import { math } from 'micromark-extension-math';
 import { encode } from 'blurhash';
 import { getShortcodeToEmoji } from '../../app/organisms/emoji-board/custom-emoji';
 import { mathExtensionHtml, spoilerExtension, spoilerExtensionHtml } from '../../util/markdown';
+import { sanitizeText } from '../../util/sanitize';
 import cons from './cons';
 import settings from './settings';
 
@@ -148,29 +149,25 @@ function findAndReplace(text, regex, filter, replace) {
   return copyText;
 }
 
-function formatAndEmojifyText(mx, roomList, room, text) {
+function formatUserPill(room, text) {
   const { userIdsToDisplayNames } = room.currentState;
-  const parentIds = roomList.getAllParentSpaces(room.roomId);
-  const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
-  const allEmoji = getShortcodeToEmoji(mx, [room, ...parentRooms]);
-
-  let formattedText;
-  if (settings.isMarkdown) {
-    formattedText = getFormattedBody(text);
-  } else {
-    formattedText = text;
-  }
-
-  formattedText = findAndReplace(
-    formattedText,
+  return findAndReplace(
+    text,
     MXID_REGEX,
     (match) => userIdsToDisplayNames[match[0]],
     (match) => (
       `<a href="https://matrix.to/#/${match[0]}">@${userIdsToDisplayNames[match[0]]}</a>`
     ),
   );
-  formattedText = findAndReplace(
-    formattedText,
+}
+
+function formatEmoji(mx, room, roomList, text) {
+  const parentIds = roomList.getAllParentSpaces(room.roomId);
+  const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
+  const allEmoji = getShortcodeToEmoji(mx, [room, ...parentRooms]);
+
+  return findAndReplace(
+    text,
     SHORTCODE_REGEX,
     (match) => allEmoji.has(match[1]),
     (match) => {
@@ -191,8 +188,6 @@ function formatAndEmojifyText(mx, roomList, room, text) {
       return tag;
     },
   );
-
-  return formattedText;
 }
 
 class RoomsInput extends EventEmitter {
@@ -295,25 +290,27 @@ class RoomsInput extends EventEmitter {
     }
 
     if (this.getMessage(roomId).trim() !== '') {
+      const rawMessage = input.message;
       let content = {
-        body: input.message,
+        body: rawMessage,
         msgtype: 'm.text',
       };
 
       // Apply formatting if relevant
-      const formattedBody = formatAndEmojifyText(
-        this.matrixClient,
-        this.roomList,
-        room,
-        input.message,
-      );
+      let formattedBody = settings.isMarkdown
+        ? getFormattedBody(rawMessage)
+        : sanitizeText(rawMessage);
+
+      formattedBody = formatUserPill(room, formattedBody);
+      formattedBody = formatEmoji(this.matrixClient, room, this.roomList, formattedBody);
+
       content.body = findAndReplace(
         content.body,
         MXID_REGEX,
         (match) => room.currentState.userIdsToDisplayNames[match[0]],
         (match) => `@${room.currentState.userIdsToDisplayNames[match[0]]}`,
       );
-      if (formattedBody !== input.message) {
+      if (formattedBody !== sanitizeText(rawMessage)) {
         // Formatting was applied, and we need to switch to custom HTML
         content.format = 'org.matrix.custom.html';
         content.formatted_body = formattedBody;
@@ -481,19 +478,19 @@ class RoomsInput extends EventEmitter {
     };
 
     // Apply formatting if relevant
-    const formattedBody = formatAndEmojifyText(
-      this.matrixClient,
-      this.roomList,
-      room,
-      editedBody,
-    );
+    let formattedBody = settings.isMarkdown
+      ? getFormattedBody(editedBody)
+      : sanitizeText(editedBody);
+    formattedBody = formatUserPill(room, formattedBody);
+    formattedBody = formatEmoji(this.matrixClient, room, this.roomList, formattedBody);
+
     content.body = findAndReplace(
       content.body,
       MXID_REGEX,
       (match) => room.currentState.userIdsToDisplayNames[match[0]],
       (match) => `@${room.currentState.userIdsToDisplayNames[match[0]]}`,
     );
-    if (formattedBody !== editedBody) {
+    if (formattedBody !== sanitizeText(editedBody)) {
       content.formatted_body = ` * ${formattedBody}`;
       content.format = 'org.matrix.custom.html';
       content['m.new_content'].formatted_body = formattedBody;
index 5351a1a016e38c4aaf39b51820c22ca26e82bb08..ade47ffcbc114f7b016f4649413f684ae5c04ffb 100644 (file)
@@ -1,7 +1,7 @@
 import sanitizeHtml from 'sanitize-html';
-import initMatrix from '../client/initMatrix';
 
 const MAX_TAG_NESTING = 100;
+let mx = null;
 
 const permittedHtmlTags = [
   'font', 'del', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
@@ -54,7 +54,7 @@ function transformATag(tagName, attribs) {
         'data-mx-pill': userId,
       },
     };
-    if (userId === initMatrix.matrixClient.getUserId()) {
+    if (userId === mx?.getUserId()) {
       pill.attribs['data-mx-ping'] = undefined;
     }
     return pill;
@@ -76,17 +76,17 @@ function transformATag(tagName, attribs) {
 
 function transformImgTag(tagName, attribs) {
   const { src } = attribs;
-  const mx = initMatrix.matrixClient;
   return {
     tagName,
     attribs: {
       ...attribs,
-      src: src.startsWith('mxc://') ? mx.mxcUrlToHttp(src) : src,
+      src: src.startsWith('mxc://') ? mx?.mxcUrlToHttp(src) : src,
     },
   };
 }
 
-export function sanitizeCustomHtml(body) {
+export function sanitizeCustomHtml(matrixClient, body) {
+  mx = matrixClient;
   return sanitizeHtml(body, {
     allowedTags: permittedHtmlTags,
     allowedAttributes: permittedTagToAttributes,