diff --git a/src/js/events/encrypted.js b/src/js/events/encrypted.js index 6d9d6d0..32dbe19 100644 --- a/src/js/events/encrypted.js +++ b/src/js/events/encrypted.js @@ -1,6 +1,6 @@ -const {MatrixEvent} = require("./event") +const {Event} = require("./event") -class EncryptedMessage extends MatrixEvent { +class EncryptedMessage extends Event { render() { super.render() return this.text("Carbon cannot render encrypted messages yet") diff --git a/src/js/events/event.js b/src/js/events/event.js index 4ec6c54..ddb412d 100644 --- a/src/js/events/event.js +++ b/src/js/events/event.js @@ -1,7 +1,7 @@ const {ElemJS, ejs} = require("../basic") const {dateFormatter} = require("../dateFormatter") -class MatrixEvent extends ElemJS { +class Event extends ElemJS { constructor(data) { super("div") this.class("c-message") @@ -50,17 +50,10 @@ class MatrixEvent extends ElemJS { } } -function simpleEvent(filter, render) { - return class extends MatrixEvent { - render() { - super.render() - return this.text(render(this.data)) - } - static canRender(event) { - return filter(event) - } - } + +function renderEvent(event) { + return new events.find(e => e.canRender(event))(event) } -module.exports = {MatrixEvent, simpleEvent} +module.exports = {renderEvent, Event} diff --git a/src/js/events/membership.js b/src/js/events/membership.js index a81a3ca..97daea3 100644 --- a/src/js/events/membership.js +++ b/src/js/events/membership.js @@ -1,13 +1,21 @@ -const {simpleEvent} = require("./event") +const {Event} = require("./event") -const UnknownMembership = simpleEvent((e) => e.type == "m.room.member", (e) => "unknown membership event") +function createMembershipEvent(membership, text) { + return class extends Event { + render() { + super.render() + return this.text(text(this.data)) + } -function createMembershipEvent(membership, message) { - return simpleEvent((e) => e.type == "m.room.member" && e.content.membership === membership, message) + static canRender(event) { + return event.type == "m.room.member" && event.content.membership == membership + } + + } } -const JoinedEvent = createMembershipEvent("join", (e) => {console.log(e); return "joined the room"}) +const JoinedEvent = createMembershipEvent("join", () => "joined the room") const InvitedEvent = createMembershipEvent("invite", (e) => `invited ${e.content.displayname} the room`) const LeaveEvent = createMembershipEvent("leave", () => "left the room") -module.exports = [JoinedEvent, InvitedEvent, LeaveEvent, UnknownMembership] +module.exports = [JoinedEvent, InvitedEvent, LeaveEvent] diff --git a/src/js/events/message.js b/src/js/events/message.js index c50ec57..0218a60 100644 --- a/src/js/events/message.js +++ b/src/js/events/message.js @@ -1,73 +1,33 @@ const {ejs} = require("../basic") const DOMPurify = require("dompurify") const {resolveMxc} = require("../functions") -const {MatrixEvent} = require("./event") +const {Event} = require("./event") const purifier = DOMPurify() - -purifier.setConfig({ - ALLOWED_URI_REGEXP: /^mxc:\/\/[a-zA-Z0-9\.]+\/[a-zA-Z0-9]+$/, // As per the spec we only allow mxc uris - ALLOWED_TAGS: ['font', 'del', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'sup', 'sub', 'li', 'b', 'i', 'u', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'caption', 'pre', 'span', 'img'], - - // In case we mess up none of those attributes should read to XSS - ALLOWED_ATTR: ["data-mx-bg-color", "data-mx-color", "color", - "name", "target", "href", - "width", "height", "alt", "title", "src", "data-mx-emoticon", - "start", "class"], - //Custom config option that allows the array of attributes for a given tag - ALLOWED_ATTR_CUSTOM: { - "FONT": ["data-mx-bg-color", "data-mx-color", "color"], - "SPAN": ["data-mx-bg-color", "data-mx-color", "color"], - "A": ["name", "target", "href"], - "IMG": ["width", "height", "alt", "title", "src", "data-mx-emoticon"], - "OL": ["start"], - "CODE": ["class"], - } -}) - -//Handle our custom tag -purifier.addHook("uponSanitizeAttribute", (node, hookevent, config) => { - //If purifier already rejected an attribute there is no point in checking it - if (hookevent.keepAttr === false) return; - - const allowed_attributes = config.ALLOWED_ATTR_CUSTOM[node.tagName] || [] - hookevent.keepAttr = allowed_attributes.indexOf(hookevent.attrName) > -1; -}) - -//Remove bad classes from our code element -purifier.addHook("uponSanitizeElement", (node, hookevent, config) => { - if (node.tagName != "CODE") return - node.classList.forEach(c => { - if (!c.startsWith("language-")) { - node.classList.remove(c) - } - }) - return node -}) - purifier.addHook("afterSanitizeAttributes", (node, hookevent, config) => { - if (node.tagName == "IMG") { + if (node.tagName == "img") { let src = node.getAttribute("src") if (src) src = resolveMxc(src) node.setAttribute("src", src) - } else if (node.tagName == "A") { + + } + if (node.tagName = "a") { node.setAttribute("rel", "noopener") - } else if (node.tagName == "FONT" || node.tagName == "SPAN") { - const color = node.getAttribute("data-mx-color") - const bgColor = node.getAttribute("data-mx-bg-color") - if (color) node.style.color = color; - if (bgColor) node.style.backgroundColor = bgColor; } return node + }) - function sanitize(html) { - return purifier.sanitize(html) + return purifier.sanitize(html, DOMPURIFY_CONFIG) } +const DOMPURIFY_CONFIG = { + ALLOWED_URI_REGEXP: /^mxc:\/\/[a-zA-Z0-9\.]+\/[a-zA-Z0-9]+$/, // As per the spec we only allow mxc uris + ALLOWED_TAGS: ['font', 'del', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'sup', 'sub', 'li', 'b', 'i', 'u', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'caption', 'pre', 'span', 'img'], +}; -class HTMLMessage extends MatrixEvent { +class HTMLMessage extends Event { render() { super.render() let html = this.data.content.formatted_body @@ -89,7 +49,7 @@ class HTMLMessage extends MatrixEvent { } -class TextMessage extends MatrixEvent { +class TextMessage extends Event { render() { super.render() return this.text(this.data.content.body) diff --git a/src/js/events/unknown.js b/src/js/events/unknown.js index bbc40f8..d644de7 100644 --- a/src/js/events/unknown.js +++ b/src/js/events/unknown.js @@ -1,4 +1,15 @@ -const {simpleEvent} = require("./event") -const UnknownEvent = simpleEvent(() => true, () => "Cannot render event") -console.log(UnknownEvent) +const {Event} = require("./event") + +class UnknownEvent extends Event { + render() { + super.render() + this.text("Cannot render event") + } + + static canRender(_event) { + return true + } + +} + module.exports = [UnknownEvent]