diff --git a/src/MatrixRoomHandler.ts b/src/MatrixRoomHandler.ts index f2f54235..aa4d19a0 100644 --- a/src/MatrixRoomHandler.ts +++ b/src/MatrixRoomHandler.ts @@ -25,10 +25,24 @@ const log = Logging.get("MatrixRoomHandler"); const ACCOUNT_LOCK_MS = 1000; const EVENT_MAPPING_SIZE = 16384; +const XEP0106_ESCAPING_TRANSFORMATIONS = { + '"': "\\22", + "&": "\\26", + "'": "\\27", + "/": "\\2f", + ":": "\\3a", + "<": "\\3c", + ">": "\\3e", + "@": "\\40", +}; + +export function XEP0106ApplyEscapingTransformations(roomId: string): string { + return roomId + .split("") + .map(char => XEP0106_ESCAPING_TRANSFORMATIONS[char] || char) + .join(""); +} -/** - * Handles creation and handling of rooms. - */ export class MatrixRoomHandler { private bridge: Bridge; private accountRoomLock: Set; @@ -161,6 +175,8 @@ export class MatrixRoomHandler { log.info("User joined, can now send messages"); } this.roomCreationLock.delete(remoteId); + roomId = XEP0106ApplyEscapingTransformations(roomId!); + return roomId!; } @@ -221,6 +237,8 @@ export class MatrixRoomHandler { throw Error("Room doesn't exist, refusing to make room"); } log.info(`Found ${roomId} for ${alias}`); + roomId = XEP0106ApplyEscapingTransformations(roomId); + return roomId; } @@ -251,6 +269,8 @@ export class MatrixRoomHandler { this.roomCreationLock.set(remoteId, createPromise as Promise); await createPromise; this.roomCreationLock.delete(remoteId); + roomId = XEP0106ApplyEscapingTransformations(roomId); + return roomId; } diff --git a/test/test_matrixroomhandler.ts b/test/test_matrixroomhandler.ts new file mode 100644 index 00000000..03ce23d3 --- /dev/null +++ b/test/test_matrixroomhandler.ts @@ -0,0 +1,30 @@ +// tslint:disable: no-any +import * as Chai from "chai"; +import { XEP0106ApplyEscapingTransformations } from "../src/MatrixRoomHandler"; +const expect = Chai.expect; + +describe("XEP0106JIDEscaping", () => { + it("implement XEP-0106 JID escaping for matrix room ID", () => { + expect(XEP0106ApplyEscapingTransformations('callme"ishmael"')).to.equal( + "callme\\22ishmael\\22" + ); + expect(XEP0106ApplyEscapingTransformations("at&tguy")).to.equal( + "at\\26tguy" + ); + expect(XEP0106ApplyEscapingTransformations("d'artagnan")).to.equal( + "d\\27artagnan" + ); + expect(XEP0106ApplyEscapingTransformations("/.fanboy")).to.equal( + "\\2f.fanboy" + ); + expect(XEP0106ApplyEscapingTransformations("::foo::")).to.equal( + "\\3a\\3afoo\\3a\\3a" + ); + expect(XEP0106ApplyEscapingTransformations("")).to.equal( + "\\3cfoo\\3e" + ); + expect(XEP0106ApplyEscapingTransformations("user@host")).to.equal( + "user\\40host" + ); + }); +});