-
Notifications
You must be signed in to change notification settings - Fork 325
/
Copy pathipfs-path.js
107 lines (92 loc) · 3.27 KB
/
ipfs-path.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
'use strict'
/* eslint-env browser */
const IsIpfs = require('is-ipfs')
function safeIpfsPath (urlOrPath) {
if (IsIpfs.subdomain(urlOrPath)) {
urlOrPath = subdomainToIpfsPath(urlOrPath)
}
// better safe than sorry: https://github.com/ipfs/ipfs-companion/issues/303
return decodeURIComponent(urlOrPath.replace(/^.*(\/ip(f|n)s\/.+)$/, '$1'))
}
function subdomainToIpfsPath (urlString) {
const url = new URL(urlString)
const fqdn = url.hostname.split('.')
const cid = fqdn[0]
const protocol = fqdn[1]
return `/${protocol}/${cid}${url.pathname}`
}
exports.safeIpfsPath = safeIpfsPath
function urlAtPublicGw (path, pubGwUrl) {
return new URL(`${pubGwUrl}${path}`).toString().replace(/([^:]\/)\/+/g, '$1')
}
exports.urlAtPublicGw = urlAtPublicGw
function createIpfsPathValidator (getState, dnsLink) {
const ipfsPathValidator = {
// Test if URL is a Public IPFS resource
// (pass validIpfsOrIpnsUrl(url) and not at the local gateway or API)
publicIpfsOrIpnsResource (url) {
// exclude custom gateway and api, otherwise we have infinite loops
if (!url.startsWith(getState().gwURLString) && !url.startsWith(getState().apiURLString)) {
return validIpfsOrIpnsUrl(url, dnsLink)
}
return false
},
// Test if URL is a valid IPFS or IPNS
// (IPFS needs to be a CID, IPNS can be PeerId or have dnslink entry)
validIpfsOrIpnsUrl (url) {
return validIpfsOrIpnsUrl(url, dnsLink)
},
// Same as validIpfsOrIpnsUrl (url) but for paths
// (we have separate methods to avoid 'new URL' where possible)
validIpfsOrIpnsPath (path) {
return validIpfsOrIpnsPath(path, dnsLink)
},
// Test if actions such as 'copy URL', 'pin/unpin' should be enabled for the URL
isIpfsPageActionsContext (url) {
return (IsIpfs.url(url) && !url.startsWith(getState().apiURLString)) || IsIpfs.subdomain(url)
}
}
return ipfsPathValidator
}
exports.createIpfsPathValidator = createIpfsPathValidator
function validIpfsOrIpnsUrl (url, dnsLink) {
// `/ipfs/` is easy to validate, we just check if CID is correct
if (IsIpfs.ipfsUrl(url)) {
return true
}
// `/ipns/` requires multiple stages/branches (can be FQDN with dnslink or CID)
if (validIpnsPath(new URL(url).pathname, dnsLink)) {
return true
}
// everything else is not IPFS-related
return false
}
function validIpfsOrIpnsPath (path, dnsLink) {
// `/ipfs/` is easy to validate, we just check if CID is correct
if (IsIpfs.ipfsPath(path)) {
return true
}
// `/ipns/` requires multiple stages/branches (can be FQDN with dnslink or CID)
if (validIpnsPath(path, dnsLink)) {
return true
}
// everything else is not IPFS-related
return false
}
function validIpnsPath (path, dnsLink) {
if (IsIpfs.ipnsPath(path)) {
// we may have false-positives here, so we do additional checks below
const ipnsRoot = path.match(/^\/ipns\/([^/]+)/)[1]
// console.log('==> IPNS root', ipnsRoot)
// first check if root is a regular CID
if (IsIpfs.cid(ipnsRoot)) {
// console.log('==> IPNS is a valid CID', ipnsRoot)
return true
}
if (dnsLink.isDnslookupPossible() && dnsLink.cachedDnslinkLookup(ipnsRoot)) {
// console.log('==> IPNS for FQDN with valid dnslink: ', ipnsRoot)
return true
}
}
return false
}