return promisify((hash, opts, callback) => { if (typeof opts === 'function') { callback = opts opts = {} } try { hash = cleanCID(hash) } catch (err) { if (!v.ipfsPath(hash)) { return callback(err) } } const query = { offset: opts.offset, length: opts.length } send({ path: 'cat', args: hash, buffer: opts.buffer, qs: query }, (err, stream) => { if (err) { return callback(err) } stream.pipe(bl((err, data) => { if (err) { return callback(err) } callback(null, data) })) }) })
return (hash, opts) => { opts = opts || {} const pt = new Stream.PassThrough() try { hash = cleanCID(hash) } catch (err) { if (!v.ipfsPath(hash)) { return pt.destroy(err) } } const query = { offset: opts.offset, length: opts.length } send({ path: 'cat', args: hash, buffer: opts.buffer, qs: query }, (err, stream) => { if (err) { return pt.destroy(err) } pump(stream, pt) }) return pt }
function access (parts, obj, cb) { const isRoot = obj === null && (isIPFS.multihash(parts[0]) || isIPFS.ipfsPath('/' + parts.join('/'))) const next = parts.shift() const isLink = obj && Object.keys(obj).length === 1 && obj[LINK_SYMBOL] const fetchLink = obj && (next ? !includes(Object.keys(obj), next) : true) if (!obj && !isRoot) { cb(new Error('No root object provided')) } else if (isLink && fetchLink) { // resolve links in objects with an / property const link = obj[LINK_SYMBOL] const linkParts = splitLink(link) let blockLink = '' if (linkParts[0] === 'ipfs') { // /ipfs/<multihash> blockLink = linkParts[1] parts = linkParts.slice(2).concat(parts) } else if (isIPFS.multihash(linkParts[0])) { // /<multihash> blockLink = linkParts[0] parts = linkParts.slice(1).concat(parts) } else { return cb(new Error(`Invalid link: "${link}"`)) } is.get(blockLink, (err, block) => { if (err) { return cb(err) } if (next) { // Put back so it's resolved in the next node parts.unshift(next) } access(parts, block, cb) }) } else if (isRoot) { let blockLink = next if (next === 'ipfs') { blockLink = parts.shift() } is.get(blockLink, (err, block) => { if (err) { return cb(err) } access(parts, block, cb) }) } else if (next) { access(parts, obj[next], cb) } else { cb(null, obj) } }
return promisify(async (name, opts, cb) => { if (typeof opts === 'function') { cb = opts opts = {} } opts = opts || {} if (!isIpfs.path(name)) { return setImmediate(() => cb(new Error('invalid argument ' + name))) } // TODO remove this and update subsequent code when IPNS is implemented if (!isIpfs.ipfsPath(name)) { return setImmediate(() => cb(new Error('resolve non-IPFS names is not implemented'))) } const split = name.split('/') // ['', 'ipfs', 'hash', ...path] const cid = new CID(split[2]) if (split.length === 3) { return setImmediate(() => cb(null, `/ipfs/${cidToString(cid, { base: opts.cidBase })}`)) } const path = split.slice(3).join('/') const results = self._ipld.resolve(cid, path) let value = cid let remainderPath = path try { for await (const result of results) { if (result.remainderPath === '') { // Use values from previous iteration if the value isn't a CID if (CID.isCID(result.value)) { value = result.value remainderPath = '' } if (result.value && CID.isCID(result.value.Hash)) { value = result.value.Hash remainderPath = '' } break } value = result.value remainderPath = result.remainderPath } } catch (error) { return cb(error) } return cb(null, `/ipfs/${cidToString(value, { base: opts.cidBase })}${remainderPath ? '/' + remainderPath : ''}`) })
exports.parseKey = (request, h) => { const { arg } = request.query if (!arg) { throw Boom.badRequest("Argument 'key' is required") } const isArray = Array.isArray(arg) const args = isArray ? arg : [arg] for (const arg of args) { if (!isIpfs.ipfsPath(arg) && !isIpfs.cid(arg) && !isIpfs.ipfsPath('/ipfs/' + arg)) { throw Boom.badRequest(`invalid ipfs ref path '${arg}'`) } } return { key: isArray ? args : arg, options: { offset: numberFromQuery(request.query, 'offset'), length: numberFromQuery(request.query, 'length') } } }
return (path, opts) => { opts = opts || {} const pt = new Stream.PassThrough({ objectMode: true }) try { path = cleanCID(path) } catch (err) { if (!v.ipfsPath(path)) { return pt.destroy(err) } } const request = { path: 'get', args: path, qs: opts } // Convert the response stream to TarStream objects send.andTransform(request, TarStreamToObjects, (err, stream) => { if (err) { return pt.destroy(err) } pump(stream, pt) }) return pt }