11import React from "react" ;
22import t from "prop-types" ;
33import styled from "styled-components/macro" ;
4- import { Divider , Popover } from "antd" ;
4+ import { Divider , Popover , Tooltip } from "antd" ;
55import isImage from "is-image" ;
66import isTextPath from "is-text-path" ;
77import isVideo from "is-video" ;
@@ -10,6 +10,7 @@ import { ReactComponent as Image } from "../assets/images/image.svg";
1010import { ReactComponent as Link } from "../assets/images/link.svg" ;
1111import { ReactComponent as PDF } from "../assets/images/pdf.svg" ;
1212import { ReactComponent as Video } from "../assets/images/video.svg" ;
13+ import { isSafeNavigationUrl } from "../utils/urlValidation" ;
1314
1415const StyledPopover = styled ( ( { className, ...rest } ) => (
1516 < Popover className = { className } overlayClassName = { className } { ...rest } />
@@ -29,6 +30,11 @@ const StyledIFrame = styled.iframe`
2930 margin-top: -8px;
3031 width: 300px;
3132` ;
33+ const DisabledAttachment = styled . span `
34+ cursor: not-allowed;
35+ display: inline-flex;
36+ opacity: 0.5;
37+ ` ;
3238
3339const isPDF = ( extension ) => extension . toLowerCase ( ) === ".pdf" ;
3440
@@ -44,15 +50,31 @@ const Attachment = ({ URI, description, extension: _extension, previewURI, title
4450 else if ( isVideo ( extension ) ) Component = Video ;
4551 else Component = Link ;
4652 Component = < Component className = "primary-purple-fill theme-fill" /> ;
53+
54+ const href = URI . replace ( / ^ \/ i p f s \/ / , "https://cdn.kleros.link/ipfs/" ) ;
55+
56+ // Unsafe attachment URL still indicate that a file was attached,
57+ // but render it as a disabled, non-clickable icon with an explanation.
58+ if ( ! isSafeNavigationUrl ( href ) ) {
59+ return (
60+ < Tooltip
61+ overlayStyle = { { wordBreak : "break-all" } }
62+ title = { `This attachment link was flagged as unsafe and has been disabled: "${ href } "` }
63+ >
64+ < DisabledAttachment > { Component } </ DisabledAttachment >
65+ </ Tooltip >
66+ ) ;
67+ }
68+
69+ const LinkedComponent = (
70+ < a href = { href } rel = "noopener noreferrer" target = "_blank" >
71+ { Component }
72+ </ a >
73+ ) ;
74+
4775 // No popover
4876 if ( ! title && ! description ) {
49- if ( URI )
50- return (
51- < a href = { URI . replace ( / ^ \/ i p f s \/ / , "https://cdn.kleros.link/ipfs/" ) } rel = "noopener noreferrer" target = "_blank" >
52- { Component }
53- </ a >
54- ) ;
55- return Component ;
77+ return LinkedComponent ;
5678 }
5779
5880 return (
@@ -72,13 +94,7 @@ const Attachment = ({ URI, description, extension: _extension, previewURI, title
7294 }
7395 title = { title }
7496 >
75- { URI ? (
76- < a href = { URI . replace ( / ^ \/ i p f s \/ / , "https://cdn.kleros.link/ipfs/" ) } rel = "noopener noreferrer" target = "_blank" >
77- { Component }
78- </ a >
79- ) : (
80- Component
81- ) }
97+ { LinkedComponent }
8298 </ StyledPopover >
8399 ) ;
84100} ;
0 commit comments