From e9053372d64fd380970f7282610878ad6af0df03 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Nov 2022 11:13:47 +0530 Subject: [PATCH 1/7] Encode ids as URI component --- src/domain/navigation/URLRouter.ts | 2 +- src/domain/navigation/index.ts | 30 ++++++++++++++----- .../session/rightpanel/MemberTileViewModel.js | 2 +- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/domain/navigation/URLRouter.ts b/src/domain/navigation/URLRouter.ts index bf1c218d..23503530 100644 --- a/src/domain/navigation/URLRouter.ts +++ b/src/domain/navigation/URLRouter.ts @@ -144,7 +144,7 @@ export class URLRouter implements IURLRou openRoomActionUrl(roomId: string): string { // not a segment to navigation knowns about, so append it manually - const urlPath = `${this._stringifyPath(this._navigation.path.until("session"))}/open-room/${roomId}`; + const urlPath = `${this._stringifyPath(this._navigation.path.until("session"))}/open-room/${encodeURIComponent(roomId)}`; return this._history.pathAsUrl(urlPath); } diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index af3c35bd..f580206e 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -147,7 +147,7 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, segments.push(new Segment("empty-grid-tile", selectedIndex)); } } else if (type === "open-room") { - const roomId = iterator.next().value; + const roomId = decodeURIComponent(iterator.next().value); if (!roomId) { break; } const rooms = currentNavPath.get("rooms"); if (rooms) { @@ -176,7 +176,7 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, } else if (type === "details" || type === "members") { pushRightPanelSegment(segments, type); } else if (type === "member") { - const userId = iterator.next().value; + const userId = decodeURIComponent(iterator.next().value); if (!userId) { break; } pushRightPanelSegment(segments, type, userId); } else if (type.includes("loginToken")) { @@ -185,7 +185,7 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, segments.push(new Segment("sso", loginToken)); } else { // might be undefined, which will be turned into true by Segment - const value = iterator.next().value; + const value = decodeURIComponent(iterator.next().value); segments.push(new Segment(type, value)); } } @@ -196,19 +196,20 @@ export function stringifyPath(path: Path): string { let urlPath = ""; let prevSegment: Segment | undefined; for (const segment of path.segments) { + const encodedSegmentValue = encodeSegmentValue(segment.value); switch (segment.type) { case "rooms": - urlPath += `/rooms/${segment.value.join(",")}`; + urlPath += `/rooms/${(encodedSegmentValue as string[]).join(",")}`; break; case "empty-grid-tile": - urlPath += `/${segment.value}`; + urlPath += `/${encodedSegmentValue}`; break; case "room": if (prevSegment?.type === "rooms") { const index = prevSegment.value.indexOf(segment.value); urlPath += `/${index}`; } else { - urlPath += `/${segment.type}/${segment.value}`; + urlPath += `/${segment.type}/${encodedSegmentValue}`; } break; case "right-panel": @@ -217,8 +218,8 @@ export function stringifyPath(path: Path): string { continue; default: urlPath += `/${segment.type}`; - if (segment.value && segment.value !== true) { - urlPath += `/${segment.value}`; + if (encodedSegmentValue && encodedSegmentValue !== true) { + urlPath += `/${encodedSegmentValue}`; } } prevSegment = segment; @@ -226,6 +227,19 @@ export function stringifyPath(path: Path): string { return urlPath; } +function encodeSegmentValue(value: SegmentType[keyof SegmentType]) { + if (typeof value === "boolean") { + // Nothing to encode for boolean + return value; + } + else if (Array.isArray(value)) { + return value.map(v => encodeURIComponent(v)); + } + else { + return encodeURIComponent(value); + } +} + export function tests() { function createEmptyPath() { const nav: Navigation = new Navigation(allowsChild); diff --git a/src/domain/session/rightpanel/MemberTileViewModel.js b/src/domain/session/rightpanel/MemberTileViewModel.js index c8dcf63a..9f9a5483 100644 --- a/src/domain/session/rightpanel/MemberTileViewModel.js +++ b/src/domain/session/rightpanel/MemberTileViewModel.js @@ -48,7 +48,7 @@ export class MemberTileViewModel extends ViewModel { get detailsUrl() { const roomId = this.navigation.path.get("room").value; - return `${this.urlRouter.openRoomActionUrl(roomId)}/member/${this._member.userId}`; + return `${this.urlRouter.openRoomActionUrl(roomId)}/member/${encodeURIComponent(this._member.userId)}`; } _updatePreviousName(newName) { From 80080074fa668c4e52c23517e8807a2e2b9880d7 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Nov 2022 11:20:47 +0530 Subject: [PATCH 2/7] Don't encode unknown segment values --- src/domain/navigation/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index f580206e..60da2435 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -185,7 +185,7 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, segments.push(new Segment("sso", loginToken)); } else { // might be undefined, which will be turned into true by Segment - const value = decodeURIComponent(iterator.next().value); + const value = iterator.next().value; segments.push(new Segment(type, value)); } } From 7bfadf37b42e953b3e12051c970fcc7894d89233 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Nov 2022 11:33:02 +0530 Subject: [PATCH 3/7] Decode all segment values that aren't undefined --- src/domain/navigation/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index 60da2435..935f7138 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -185,7 +185,11 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, segments.push(new Segment("sso", loginToken)); } else { // might be undefined, which will be turned into true by Segment - const value = iterator.next().value; + let value = iterator.next().value; + if (value) { + // decode only if value isn't undefined! + value = decodeURIComponent(value) + } segments.push(new Segment(type, value)); } } From 2d0122dda7781995d143d59812ed6d9667198bdf Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 25 Nov 2022 17:38:05 +0100 Subject: [PATCH 4/7] apply PR suggestions --- src/domain/navigation/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index 935f7138..5a4b9abc 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -147,8 +147,9 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, segments.push(new Segment("empty-grid-tile", selectedIndex)); } } else if (type === "open-room") { - const roomId = decodeURIComponent(iterator.next().value); + let roomId = iterator.next().value; if (!roomId) { break; } + roomId = decodeURIComponent(roomId); const rooms = currentNavPath.get("rooms"); if (rooms) { segments.push(roomsSegmentWithRoom(rooms, roomId, currentNavPath)); @@ -176,8 +177,9 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, } else if (type === "details" || type === "members") { pushRightPanelSegment(segments, type); } else if (type === "member") { - const userId = decodeURIComponent(iterator.next().value); + let userId = iterator.next().value; if (!userId) { break; } + userId = decodeURIComponent(userId); pushRightPanelSegment(segments, type, userId); } else if (type.includes("loginToken")) { // Special case for SSO-login with query parameter loginToken= From b8444a32c0f74cadabcc4db654d7378fe8b98fff Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 25 Nov 2022 17:38:13 +0100 Subject: [PATCH 5/7] add missing decode --- src/domain/navigation/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index 5a4b9abc..a75260d0 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -137,7 +137,7 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, if (type === "rooms") { const roomsValue = iterator.next().value; if (roomsValue === undefined) { break; } - const roomIds = roomsValue.split(","); + const roomIds = decodeURIComponent(roomsValue).split(","); segments.push(new Segment(type, roomIds)); const selectedIndex = parseInt(iterator.next().value || "0", 10); const roomId = roomIds[selectedIndex]; From 467a76c2231b9555a6d7deb4f19b4a5eddd6b3e3 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 25 Nov 2022 17:45:06 +0100 Subject: [PATCH 6/7] decode ids separately, as we encode them separately as well --- src/domain/navigation/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index a75260d0..3bbe4d3a 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -137,7 +137,7 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, if (type === "rooms") { const roomsValue = iterator.next().value; if (roomsValue === undefined) { break; } - const roomIds = decodeURIComponent(roomsValue).split(","); + const roomIds = roomsValue.split(",").map(id => decodeURIComponent(id)); segments.push(new Segment(type, roomIds)); const selectedIndex = parseInt(iterator.next().value || "0", 10); const roomId = roomIds[selectedIndex]; From f7132a48d9a30fcb10ac58981cb5ee8dd5c2629f Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 25 Nov 2022 17:45:31 +0100 Subject: [PATCH 7/7] implement PR suggestion to do all encoding in fn, so return type is str --- src/domain/navigation/index.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index 3bbe4d3a..a2705944 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -205,7 +205,7 @@ export function stringifyPath(path: Path): string { const encodedSegmentValue = encodeSegmentValue(segment.value); switch (segment.type) { case "rooms": - urlPath += `/rooms/${(encodedSegmentValue as string[]).join(",")}`; + urlPath += `/rooms/${encodedSegmentValue}`; break; case "empty-grid-tile": urlPath += `/${encodedSegmentValue}`; @@ -224,7 +224,7 @@ export function stringifyPath(path: Path): string { continue; default: urlPath += `/${segment.type}`; - if (encodedSegmentValue && encodedSegmentValue !== true) { + if (encodedSegmentValue) { urlPath += `/${encodedSegmentValue}`; } } @@ -233,13 +233,13 @@ export function stringifyPath(path: Path): string { return urlPath; } -function encodeSegmentValue(value: SegmentType[keyof SegmentType]) { - if (typeof value === "boolean") { +function encodeSegmentValue(value: SegmentType[keyof SegmentType]): string { + if (value === true) { // Nothing to encode for boolean - return value; + return ""; } else if (Array.isArray(value)) { - return value.map(v => encodeURIComponent(v)); + return value.map(v => encodeURIComponent(v)).join(","); } else { return encodeURIComponent(value);