-
-
Notifications
You must be signed in to change notification settings - Fork 85
Expand file tree
/
Copy pathindex.js
More file actions
137 lines (126 loc) · 4.73 KB
/
index.js
File metadata and controls
137 lines (126 loc) · 4.73 KB
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
/* global Blob */
module.exports = parseTorrent
module.exports.remote = parseTorrentRemote
var blobToBuffer = require('blob-to-buffer')
var fs = require('fs') // browser exclude
var get = require('simple-get')
var magnet = require('magnet-uri')
var parseTorrentFile = require('parse-torrent-file')
var crypto = require('crypto')
module.exports.toMagnetURI = magnet.encode
module.exports.toTorrentFile = parseTorrentFile.encode
/**
* Parse a torrent identifier (magnet uri, .torrent file, info hash)
* @param {string|Buffer|Object} torrentId
* @return {Object}
*/
function parseTorrent (torrentId) {
if (typeof torrentId === 'string' && /^(stream-)?magnet:/.test(torrentId)) {
// magnet uri (string)
var m = magnet(torrentId)
if (m.xs) throw new Error('Exact source magnets need to call .remote()')
return m
} else if (typeof torrentId === 'string' && (/^[a-f0-9]{40}$/i.test(torrentId) || /^[a-z2-7]{32}$/i.test(torrentId))) {
// info hash (hex/base-32 string)
return magnet('magnet:?xt=urn:btih:' + torrentId)
} else if (Buffer.isBuffer(torrentId) && torrentId.length === 20) {
// info hash (buffer)
return magnet('magnet:?xt=urn:btih:' + torrentId.toString('hex'))
} else if (Buffer.isBuffer(torrentId)) {
// .torrent file (buffer)
return parseTorrentFile(torrentId) // might throw
} else if (torrentId && torrentId.infoHash) {
// parsed torrent (from `parse-torrent`, `parse-torrent-file`, or `magnet-uri`)
if (!torrentId.announce) torrentId.announce = []
if (typeof torrentId.announce === 'string') {
torrentId.announce = [ torrentId.announce ]
}
if (!torrentId.urlList) torrentId.urlList = []
return torrentId
} else {
throw new Error('Invalid torrent identifier')
}
}
function parseTorrentRemote (opts, cb) {
var torrentId = (typeof opts === 'object' && !isBlob(opts)) ? opts.torrentId : opts
var parsedTorrent
if (typeof cb !== 'function') throw new Error('second argument must be a Function')
try {
parsedTorrent = parseTorrent(torrentId)
} catch (err) {
// If torrent fails to parse, it could be a Blob, http/https URL or
// filesystem path, so don't consider it an error yet.
}
if (parsedTorrent && parsedTorrent.infoHash) {
process.nextTick(function () {
cb(null, parsedTorrent)
})
} else if (isBlob(torrentId)) {
blobToBuffer(torrentId, function (err, torrentBuf) {
if (err) return cb(new Error('Error converting Blob: ' + err.message))
parseOrThrow(torrentBuf)
})
} else if (opts.dht && /^(stream-)?magnet:/.test(torrentId)) {
var m = magnet(torrentId)
if (!m.xs) {
process.nextTick(function () {
cb(new Error('Missing xs (exact source) in magnet URI'))
})
} else {
if ((m = m.xs.match(/^urn:btpk:(.{64})/))) {
var publicKey = m[1].toLowerCase()
var publicKeyBuf = Buffer.from(publicKey, 'hex')
var targetId = crypto.createHash('sha1').update(publicKeyBuf).digest('hex') // XXX missing salt
opts.dht.get(targetId, function (err, res) {
if (err) return cb(new Error('Error finding this publicKey in the DHT'))
if (res.v && !res.v.ih) return cb(new Error('Found publicKey in DHT, but no torrent inside'))
parseOrThrow(res.v.ih)
})
} else {
process.nextTick(function () {
cb(new Error('Can\'t find publicKey in magnet URI'))
})
}
}
} else if (typeof get === 'function' && /^https?:/.test(torrentId)) {
// http, or https url to torrent file
get.concat({
url: torrentId,
timeout: 30 * 1000,
headers: { 'user-agent': 'WebTorrent (http://webtorrent.io)' }
}, function (err, res, torrentBuf) {
if (err) return cb(new Error('Error downloading torrent: ' + err.message))
parseOrThrow(torrentBuf)
})
} else if (typeof fs.readFile === 'function' && typeof torrentId === 'string') {
// assume it's a filesystem path
fs.readFile(torrentId, function (err, torrentBuf) {
if (err) return cb(new Error('Invalid torrent identifier'))
parseOrThrow(torrentBuf)
})
} else {
process.nextTick(function () {
cb(new Error('Invalid torrent identifier'))
})
}
function parseOrThrow (torrentBuf) {
try {
parsedTorrent = parseTorrent(torrentBuf)
} catch (err) {
return cb(err)
}
if (parsedTorrent && parsedTorrent.infoHash) cb(null, parsedTorrent)
else cb(new Error('Invalid torrent identifier'))
}
}
/**
* Check if `obj` is a W3C `Blob` or `File` object
* @param {*} obj
* @return {boolean}
*/
function isBlob (obj) {
return typeof Blob !== 'undefined' && obj instanceof Blob
}
// Workaround Browserify v13 bug
// https://github.com/substack/node-browserify/issues/1483
;(function () { Buffer.alloc(0) })()