From b54afeefa5f6cb86a7a84c4d0d9b47c2b60602fc Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 24 Nov 2023 14:39:09 +0530 Subject: [PATCH] fix: app crash when the message links have special characters in it (#2318) * fix: app crash when the message links have special characters in it * refactor: added comments for the escapeRegExp function --- .../utils/generateMarkdownText.test.ts | 23 +++++++++++++++++ .../utils/generateMarkdownText.ts | 25 +++++++++---------- .../MessageSimple/utils/renderText.tsx | 3 ++- 3 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 package/src/components/Message/MessageSimple/utils/generateMarkdownText.test.ts diff --git a/package/src/components/Message/MessageSimple/utils/generateMarkdownText.test.ts b/package/src/components/Message/MessageSimple/utils/generateMarkdownText.test.ts new file mode 100644 index 0000000000..f7eb12d8c6 --- /dev/null +++ b/package/src/components/Message/MessageSimple/utils/generateMarkdownText.test.ts @@ -0,0 +1,23 @@ +import { generateMarkdownText } from './generateMarkdownText'; + +describe('generateMarkdownText', () => { + it.each([ + ['', null], + [' test message ', 'test message'], + ['https://www.getstream.io', '[https://www.getstream.io](https://www.getstream.io)'], + [ + 'https://getstream-production.s3-accelerate.amazonaws.com/N336903591601695/33e78ef89e64642862a75c5cca2541eaf6b1c924/trimmedVideos/alert/2_270_881/outputVideo.mp4?AWSAccessKeyId=AKIAVJAW2AD2SQVQCBXV&Expires=1699998768&Signature=zdEMCGzf4Pq++16YkPprvN5NAds=', + '[https://getstream-production.s3-accelerate.amazonaws.com/N336903591601695/33e78ef89e64642862a75c5cca2541eaf6b1c924/trimmedVideos/alert/2_270_881/outputVideo.mp4?AWSAccessKeyId=AKIAVJAW2AD2SQVQCBXV&...](https://getstream-production.s3-accelerate.amazonaws.com/N336903591601695/33e78ef89e64642862a75c5cca2541eaf6b1c924/trimmedVideos/alert/2_270_881/outputVideo.mp4?AWSAccessKeyId=AKIAVJAW2AD2SQVQCBXV&Expires=1699998768&Signature=zdEMCGzf4Pq++16YkPprvN5NAds=)', + ], + ['Hi @getstream.io', 'Hi @getstream.io'], + [ + 'Hi test@gmail.com @test@gmail.com', + 'Hi [test@gmail.com](mailto:test@gmail.com) @test@gmail.com', + ], + ['Hi @getstream.io getstream.io', 'Hi @getstream.io [getstream.io](http://getstream.io)'], + ['Hi ', 'Hi \\'], + ])('Returns the generated markdown text for %p and %p', (text, expected) => { + const result = generateMarkdownText(text); + expect(result).toBe(expected); + }); +}); diff --git a/package/src/components/Message/MessageSimple/utils/generateMarkdownText.ts b/package/src/components/Message/MessageSimple/utils/generateMarkdownText.ts index 020b9311b7..964b0d02dd 100644 --- a/package/src/components/Message/MessageSimple/utils/generateMarkdownText.ts +++ b/package/src/components/Message/MessageSimple/utils/generateMarkdownText.ts @@ -2,16 +2,12 @@ import truncate from 'lodash/truncate'; import { parseLinksFromText } from './parseLinks'; -import type { DefaultStreamChatGenerics } from '../../../../types/types'; -import type { MessageType } from '../../../MessageList/hooks/useMessageList'; - -export const generateMarkdownText = < - StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, ->( - message: MessageType, -) => { - const { text } = message; +// If you need to use any of the special characters literally (actually searching for a "*", for instance), you must escape it by putting a backslash in front of it. +function escapeRegExp(text: string) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); +} +export const generateMarkdownText = (text?: string) => { if (!text) return null; // Trim the extra spaces from the text. @@ -26,18 +22,21 @@ export const generateMarkdownText = < omission: '...', }); // Convert raw links/emails in the text to respective markdown syntax. - // Eg: Hi getstream.io -> Hi [getstream.io](getstream.io). - const normalRegEx = new RegExp(linkInfo.raw, 'g'); + // Eg: Hi @getstream.io -> Hi @[getstream.io](getstream.io). + const normalRegEx = new RegExp(escapeRegExp(linkInfo.raw), 'g'); const markdown = `[${displayLink}](${linkInfo.encodedUrl})`; resultText = text.replace(normalRegEx, markdown); // After previous step, in some cases, the mentioned user after `@` might have a link/email so we convert it back to normal raw text. // Eg: Hi, @[test.user@gmail.com](mailto:test.user@gmail.com) to @test.user@gmail.com. - const mentionsRegex = new RegExp(`@\\[${displayLink}\\]\\(${linkInfo.encodedUrl}\\)`, 'g'); + const mentionsRegex = new RegExp( + `@\\[${escapeRegExp(displayLink)}\\]\\(${escapeRegExp(linkInfo.encodedUrl)}\\)`, + 'g', + ); resultText = resultText.replace(mentionsRegex, `@${displayLink}`); } - resultText = resultText.replace(/[<&"'>]/g, '\\$&'); + resultText = resultText.replace(/[<"'>]/g, '\\$&'); return resultText; }; diff --git a/package/src/components/Message/MessageSimple/utils/renderText.tsx b/package/src/components/Message/MessageSimple/utils/renderText.tsx index bb98bf791e..c246c0a6ee 100644 --- a/package/src/components/Message/MessageSimple/utils/renderText.tsx +++ b/package/src/components/Message/MessageSimple/utils/renderText.tsx @@ -100,8 +100,9 @@ export const renderText = < onPress: onPressParam, preventPress, } = params; + const { text } = message; - const markdownText = generateMarkdownText(message); + const markdownText = generateMarkdownText(text); const styles: MarkdownStyle = { ...defaultMarkdownStyles,