Skip to content

Commit

Permalink
Strip direction override characters from display names (#1992)
Browse files Browse the repository at this point in the history
Strip RLO and LRO characters from name and rawDisplayName so they
can safely be embedded into other text without messing up the text
ordering.

Fixes element-hq/element-web#1712
  • Loading branch information
dbkr authored Oct 20, 2021
1 parent d5ab4ba commit 59b3960
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/models/room-member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ export class RoomMember extends EventEmitter {
this.disambiguate,
);

this.rawDisplayName = event.getDirectionalContent().displayname;
// not quite raw: we strip direction override chars so it can safely be inserted into
// blocks of text without breaking the text direction
this.rawDisplayName = utils.removeDirectionOverrideChars(event.getDirectionalContent().displayname);
if (!this.rawDisplayName || !utils.removeHiddenChars(this.rawDisplayName)) {
this.rawDisplayName = this.userId;
}
Expand Down Expand Up @@ -355,15 +357,26 @@ function calculateDisplayName(
roomState: RoomState,
disambiguate: boolean,
): string {
if (disambiguate) return displayName + " (" + selfUserId + ")";
if (disambiguate) return utils.removeDirectionOverrideChars(displayName) + " (" + selfUserId + ")";

if (!displayName || displayName === selfUserId) return selfUserId;

// First check if the displayname is something we consider truthy
// after stripping it of zero width characters and padding spaces
if (!utils.removeHiddenChars(displayName)) return selfUserId;

return displayName;
// We always strip the direction override characters (LRO and RLO).
// These override the text direction for all subsequent characters
// in the paragraph so if display names contained these, they'd
// need to be wrapped in something to prevent this from leaking out
// (which we can do in HTML but not text) or we'd need to add
// control characters to the string to reset any overrides (eg.
// adding PDF characters at the end). As far as we can see,
// there should be no reason these would be necessary - rtl display
// names should flip into the correct direction automatically based on
// the characters, and you can still embed rtl in ltr or vice versa
// with the embed chars or marker chars.
return utils.removeDirectionOverrideChars(displayName);
}

/**
Expand Down
12 changes: 12 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,18 @@ export function removeHiddenChars(str: string): string {
return "";
}

/**
* Removes the direction override characters from a string
* @param {string} input
* @returns string with chars removed
*/
export function removeDirectionOverrideChars(str: string): string {
if (typeof str === "string") {
return str.replace(/[\u202d-\u202e]/g, '');
}
return "";
}

export function normalize(str: string): string {
// Note: we have to match the filter with the removeHiddenChars() because the
// function strips spaces and other characters (M becomes RN for example, in lowercase).
Expand Down

0 comments on commit 59b3960

Please sign in to comment.