From 34d2fdd25545e73e4578200de8cbaa6396f87ab3 Mon Sep 17 00:00:00 2001 From: Chris Marslender Date: Mon, 29 Apr 2024 12:24:30 -0700 Subject: [PATCH] verify url format (#2331) verify url format Co-authored-by: Earle Lowe <30607889+emlowe@users.noreply.github.com> --- packages/core/src/hooks/useOpenExternal.ts | 10 +++- .../gui/src/components/nfts/NFTDetails.tsx | 53 ++++++++++--------- .../gui/src/components/nfts/NFTProperties.tsx | 22 +------- packages/gui/src/hooks/useOpenExternal.ts | 10 +++- 4 files changed, 44 insertions(+), 51 deletions(-) diff --git a/packages/core/src/hooks/useOpenExternal.ts b/packages/core/src/hooks/useOpenExternal.ts index 9f91264b69..93f52ab6d3 100644 --- a/packages/core/src/hooks/useOpenExternal.ts +++ b/packages/core/src/hooks/useOpenExternal.ts @@ -1,7 +1,13 @@ import isElectron from 'is-electron'; +import { useCallback } from 'react'; +import isURL from 'validator/es/lib/isURL'; export default function useOpenExternal(): (url: string) => void { - function handleOpen(url: string) { + const handleOpen = useCallback((url: string) => { + if (!isURL(url, { protocols: ['http', 'https', 'ipfs'], require_protocol: true })) { + return; + } + if (isElectron()) { // @ts-ignore window.shell.openExternal(url); @@ -9,7 +15,7 @@ export default function useOpenExternal(): (url: string) => void { } window.open(url, '_blank'); - } + }, []); return handleOpen; } diff --git a/packages/gui/src/components/nfts/NFTDetails.tsx b/packages/gui/src/components/nfts/NFTDetails.tsx index e2c003424b..b950890e4f 100644 --- a/packages/gui/src/components/nfts/NFTDetails.tsx +++ b/packages/gui/src/components/nfts/NFTDetails.tsx @@ -7,7 +7,6 @@ import { Tooltip, Truncate, truncateValue, - Link, useCurrencyCode, } from '@chia-network/core'; import { Trans } from '@lingui/macro'; @@ -302,35 +301,37 @@ export default function NFTDetails(props: NFTDetailsProps) { }); } - if (metadata?.preview_image_uris) { - const value = metadata?.preview_image_uris.map((uri: string) => ( - -   - - {uri} - - - )); - rows.push({ - key: 'preview_image_uris', - label: Preview image uris, - value, + if (Array.isArray(metadata?.preview_image_uris)) { + metadata.preview_image_uris.forEach((uri: string, i: number) => { + if (uri) { + const index = i + 1; + rows.push({ + key: `preview-image-uris-${i}`, + label: Preview image URL {index}, + value: ( + + {uri} + + ), + }); + } }); } if (Array.isArray(metadata?.preview_video_uris)) { - const value = metadata?.preview_video_uris.map((uri: string) => ( - -   - - {uri} - - - )); - rows.push({ - key: 'preview_video_uris', - label: Preview video uris, - value, + metadata.preview_video_uris.forEach((uri: string, i: number) => { + if (uri) { + const index = i + 1; + rows.push({ + key: `preview-video-uris-${i}`, + label: Preview video URL {index}, + value: ( + + {uri} + + ), + }); + } }); } diff --git a/packages/gui/src/components/nfts/NFTProperties.tsx b/packages/gui/src/components/nfts/NFTProperties.tsx index 2133fde19a..860f37fce4 100644 --- a/packages/gui/src/components/nfts/NFTProperties.tsx +++ b/packages/gui/src/components/nfts/NFTProperties.tsx @@ -6,7 +6,6 @@ import { useTheme } from '@mui/material/styles'; import React, { useMemo } from 'react'; import styled from 'styled-components'; -import useOpenUnsafeLink from '../../hooks/useOpenUnsafeLink'; import isRankingAttribute from '../../util/isRankingAttribute'; /* ========================================================================== */ @@ -34,7 +33,6 @@ export type NFTPropertiesProps = { export function NFTProperty(props: NFTPropertyProps) { const { attribute, size = 'regular', color = 'secondary' } = props; - const openUnsafeLink = useOpenUnsafeLink(); const theme = useTheme(); // eslint-disable-next-line @typescript-eslint/naming-convention -- Comes from API like this const { name, trait_type, value: rawValue } = attribute; @@ -50,24 +48,6 @@ export function NFTProperty(props: NFTPropertyProps) { p: size === 'small' ? 1 : 2, }; - function renderValueWithUrls(val: string) { - const urlRegex = /(https?:\/\/[^\s]+)/g; - const matches = val.split(urlRegex); - if (matches.length > 1) { - return matches.map((match, index) => { - if (index % 2 === 1) { - return ( - openUnsafeLink(match)}> - {match} - - ); - } - return match !== '' ? {match} : null; - }); - } - return val; - } - return ( @@ -93,7 +73,7 @@ export function NFTProperty(props: NFTPropertyProps) { } > - {renderValueWithUrls(value)} + {value} diff --git a/packages/gui/src/hooks/useOpenExternal.ts b/packages/gui/src/hooks/useOpenExternal.ts index 9f91264b69..93f52ab6d3 100644 --- a/packages/gui/src/hooks/useOpenExternal.ts +++ b/packages/gui/src/hooks/useOpenExternal.ts @@ -1,7 +1,13 @@ import isElectron from 'is-electron'; +import { useCallback } from 'react'; +import isURL from 'validator/es/lib/isURL'; export default function useOpenExternal(): (url: string) => void { - function handleOpen(url: string) { + const handleOpen = useCallback((url: string) => { + if (!isURL(url, { protocols: ['http', 'https', 'ipfs'], require_protocol: true })) { + return; + } + if (isElectron()) { // @ts-ignore window.shell.openExternal(url); @@ -9,7 +15,7 @@ export default function useOpenExternal(): (url: string) => void { } window.open(url, '_blank'); - } + }, []); return handleOpen; }