/
index.js
162 lines (138 loc) · 4 KB
/
index.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
'use strict'
const base58 = require('bs58')
const multihash = require('multihashes')
const multibase = require('multibase')
const Multiaddr = require('multiaddr')
const mafmt = require('mafmt')
const CID = require('cids')
const urlPattern = /^https?:\/\/[^/]+\/(ip(f|n)s)\/((\w+).*)/
const pathPattern = /^\/(ip(f|n)s)\/((\w+).*)/
const defaultProtocolMatch = 1
const defaultHashMath = 4
const fqdnPattern = /^https?:\/\/([^/]+)\.(ip(?:f|n)s)\.[^/]+/
const fqdnHashMatch = 1
const fqdnProtocolMatch = 2
function isMultihash (hash) {
const formatted = convertToString(hash)
try {
const buffer = Buffer.from(base58.decode(formatted))
multihash.decode(buffer)
return true
} catch (e) {
return false
}
}
function isMultibase (hash) {
try {
return multibase.isEncoded(hash)
} catch (e) {
return false
}
}
function isCID (hash) {
try {
new CID(hash) // eslint-disable-line no-new
return true
} catch (e) {
return false
}
}
function isMultiaddr (input) {
if (!input) return false
if (isString(input) || input instanceof Buffer) {
try {
new Multiaddr(input) // eslint-disable-line no-new
return true
} catch (e) {
return false
}
}
if (Multiaddr.isMultiaddr(input)) return true
return false
}
function isPeerMultiaddr (input) {
if (!isMultiaddr(input)) return false
if (input instanceof Buffer) {
// mafmt does not support Buffer input
input = new Multiaddr(input)
}
return mafmt.IPFS.matches(input)
}
function isIpfs (input, pattern, protocolMatch = defaultProtocolMatch, hashMatch = defaultHashMath) {
const formatted = convertToString(input)
if (!formatted) {
return false
}
const match = formatted.match(pattern)
if (!match) {
return false
}
if (match[protocolMatch] !== 'ipfs') {
return false
}
let hash = match[hashMatch]
if (hash && pattern === fqdnPattern) {
// when doing checks for subdomain context
// ensure hash is case-insensitive
// (browsers force-lowercase authority compotent anyway)
hash = hash.toLowerCase()
}
return isCID(hash)
}
function isIpns (input, pattern, protocolMatch = defaultProtocolMatch, hashMatch) {
const formatted = convertToString(input)
if (!formatted) {
return false
}
const match = formatted.match(pattern)
if (!match) {
return false
}
if (match[protocolMatch] !== 'ipns') {
return false
}
if (hashMatch && pattern === fqdnPattern) {
let hash = match[hashMatch]
// when doing checks for subdomain context
// ensure hash is case-insensitive
// (browsers force-lowercase authority compotent anyway)
hash = hash.toLowerCase()
return isCID(hash)
}
return true
}
function isString (input) {
return typeof input === 'string'
}
function convertToString (input) {
if (Buffer.isBuffer(input)) {
return base58.encode(input)
}
if (isString(input)) {
return input
}
return false
}
const ipfsSubdomain = (url) => isIpfs(url, fqdnPattern, fqdnProtocolMatch, fqdnHashMatch)
const ipnsSubdomain = (url) => isIpns(url, fqdnPattern, fqdnProtocolMatch, fqdnHashMatch)
module.exports = {
multihash: isMultihash,
multiaddr: isMultiaddr,
peerMultiaddr: isPeerMultiaddr,
cid: isCID,
base32cid: (cid) => (isMultibase(cid) === 'base32' && isCID(cid)),
ipfsSubdomain: ipfsSubdomain,
ipnsSubdomain: ipnsSubdomain,
subdomain: (url) => (ipfsSubdomain(url) || ipnsSubdomain(url)),
subdomainPattern: fqdnPattern,
ipfsUrl: (url) => isIpfs(url, urlPattern),
ipnsUrl: (url) => isIpns(url, urlPattern),
url: (url) => (isIpfs(url, urlPattern) || isIpns(url, urlPattern)),
urlPattern: urlPattern,
ipfsPath: (path) => isIpfs(path, pathPattern),
ipnsPath: (path) => isIpns(path, pathPattern),
path: (path) => (isIpfs(path, pathPattern) || isIpns(path, pathPattern)),
pathPattern: pathPattern,
urlOrPath: (x) => (isIpfs(x, urlPattern) || isIpns(x, urlPattern) || isIpfs(x, pathPattern) || isIpns(x, pathPattern)),
cidPath: path => isString(path) && !isCID(path) && isIpfs(`/ipfs/${path}`, pathPattern)
}