diff --git a/app/containers/markdown/index.js b/app/containers/markdown/index.js index 990b2fc66f955fe0c22a3bd56c7eecdad9539f7d..5f6b29a227cb14fe16cbf9801cea817c5e1cd69e 100644 --- a/app/containers/markdown/index.js +++ b/app/containers/markdown/index.js @@ -22,6 +22,7 @@ import MarkdownTableCell from './TableCell'; import mergeTextNodes from './mergeTextNodes'; import styles from './styles'; +import { isValidURL } from '../../utils/url'; // Support <http://link|Text> const formatText = text => text.replace( @@ -278,7 +279,18 @@ class Markdown extends PureComponent { ); } - renderImage = ({ src }) => <Image style={styles.inlineImage} source={{ uri: src }} />; + renderImage = ({ src }) => { + if (!isValidURL(src)) { + return null; + } + + return ( + <Image + style={styles.inlineImage} + source={{ uri: encodeURI(src) }} + /> + ); + } renderEditedIndicator = () => { const { theme } = this.props; diff --git a/app/utils/url.js b/app/utils/url.js new file mode 100644 index 0000000000000000000000000000000000000000..856eac771519b5e14f38dba4ab5e65b7b9dc4e78 --- /dev/null +++ b/app/utils/url.js @@ -0,0 +1,9 @@ +export const isValidURL = (url) => { + const pattern = new RegExp('^(https?:\\/\\/)?' // protocol + + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' // domain name + + '((\\d{1,3}\\.){3}\\d{1,3}))' // OR ip (v4) address + + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' // port and path + + '(\\?[;&a-z\\d%_.~+=-]*)?' // query string + + '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator + return !!pattern.test(url); +};