UNPKG

webseeded-torrent-generator

Version:

Generate webseeded torrent files from urls to files.

352 lines (324 loc) 13.3 kB
// var assert = require('assert'); // //var HttpFile = require('../lib/http-fs').HttpFile; // var nt = require('nt'); // describe('Torrent Generation', function () { // this.timeout(10000); // it('generates the same torrent as nt', function (done) { // }); // }); 'use strict'; var Torrent = require('../lib/torrent'); var fs = require('fs'); var path = require('path'); var assert = require('assert'); var q = require('q'); var _ = require('lodash'); var crypto = require('crypto'); var BunyanPromiseLogger = require('bunyan-promise'); var bencode = require('bencode'); var promiseLog = new BunyanPromiseLogger({ name: 'test-torrent' }); var kB = 0x400; var MB = kB * kB; describe('Piece Size', function () { it('uses correct piece size for small files', function (done) { var base = 'http://ia700201.us.archive.org/6/items/'; var name = 'jj2005-02-27.fm.shnf'; var files = [ 'jj2005-02-27.fm.d1.md5', 'jj2005-02-27.fm.d1t1_vbr.mp3' ]; var torrent = new Torrent(base, name, files); torrent.getPieceLength().then(function (length) { // should be the minimum piece size...16kB assert(length === 256 * kB); done(); }).fail(function (err) { done(new Error(err)); }); }); it('uses correct piece size for huge files', function (done) { var base = 'https://s3.amazonaws.com/content-bundles/production-df0ec56d-0fbb-bc2c-11e7-354ff3af9c4e/bf3a4aa8cfe2a908002c9981948f38a07c9997df752a9abeee537aa6dc7bcebf/originals/'; var name = 'Footsteps'; var files = [ '00_What\'s-Inside.html', 'FOOTSTEPS_2012_FEATUREFILM_1080p.mp4', 'FOOTSTEPS_2012_TRAILER_1080p.mp4' ]; var torrent = new Torrent(base, name, files); torrent.getPieceLength().then(function (length) { // should be 4 MB assert(length === 4 * MB); done(); }).fail(function (err) { done(new Error(err)); }); }); }); describe('Torrent Generation', function () { this.timeout(300000); it('provides progress updates when generating a torrent', function (done) { var base = 'http://ia700201.us.archive.org/6/items/'; var name = 'jj2005-02-27.fm.shnf'; var files = [ 'jj2005-02-27.fm.d1.md5', 'jj2005-02-27.fm.d1t1_vbr.mp3' ]; var torrent = new Torrent(base, name, files); var metadataRequest = torrent.getMetadata(); var expectedProgressNotifications = [ 16.573486745648847, 33.14697349129769, 49.720460236946536, 66.29394698259539, 82.86743372824424, 99.44092047389307, 100 ]; metadataRequest.progress(function (progress) { process.stdout.write('AAAA - ' + progress + '\n'); if (!_.contains(expectedProgressNotifications, progress)) { done(new Error('expected the received progress to be in the expected list')); } expectedProgressNotifications = _.without(expectedProgressNotifications, progress); }); metadataRequest.then(function () { assert(expectedProgressNotifications.length === 0, 'expected to see all the progress updates'); }).then(function () { done(); }, function (err) { done(new Error(err)); }); promiseLog.trace(metadataRequest, 'provides progress updates when generating a large torrent'); }); it('generates a private torrent', function (done) { var infoHash = '154f36b266a03e1f50bd469b038b944e043dbb16'; var base = 'http://ia700201.us.archive.org/6/items/'; var name = 'jj2005-02-27.fm.shnf'; var files = [ 'jj2005-02-27.fm.d1.md5', 'jj2005-02-27.fm.d1.txt' ]; var options = { private: true, 'announce-list': [] }; var torrent = new Torrent(base, name, files, options); var infoHashRequest = torrent.getInfoHash().then(function (res) { assert(infoHash === res, 'torrent info hash generated matches expected torrent file info hash'); }); infoHashRequest.then(function () { done(); }, function (err) { done(new Error(err)); }); }); it('generates a replica of a small working internet archive backed torrent', function (done) { var infoHash = 'ab715690d4c95dd147f6f2fe9f071705bbe22028'; var torrentFile = fs.readFileSync('./test/torrents/' + infoHash + '.torrent'); var base = 'http://ia700201.us.archive.org/6/items/'; var name = 'jj2005-02-27.fm.shnf'; var files = [ 'jj2005-02-27.fm.d1.md5', 'jj2005-02-27.fm.d1.txt' ]; var torrent = new Torrent(base, name, files); var metadataRequest = torrent.getMetadata().then(function (res) { assert(torrentFile.toString() === res.toString(), 'torrent generated matches expected torrent file'); return q.resolve(); }); var infoHashRequest = torrent.getInfoHash().then(function (res) { assert(infoHash === res, 'torrent info hash generated matches expected torrent file info hash'); return q.resolve(); }); var ret = q.all([ metadataRequest, infoHashRequest ]); promiseLog.trace(ret, 'generates a replica of a small working internet archive backed torrent'); ret.then(function () { done(); }, function (err) { done(new Error(err)); }); }); it('generates a torrent with non-ascii characters', function (done) { var base = 'http://s3.amazonaws.com/content-test/'; var name = '布碌崙滅門慘案報導'; var files = [ '布碌崙滅門慘案報導.mp4', '00_What\'s-Inside.html', 'folder/_#_布碌崙滅門慘案報導.png' ]; var torrent = new Torrent(base, name, files); torrent.getMetadata().then(function () { done(); }, function (err) { done(new Error(err)); }); }); it('generates torrents with url reserved characters in the file names', function (done) { var base = 'http://s3.amazonaws.com/'; var name = 'content-test'; var files = [ '!@#$%^&*().html', '{}[]<>,.?.html', 'file_with_a_#_in_it', 'and&?.png' ]; new Torrent(base, name, files).getMetadata().then(function () { done(); }, function (err) { done(new Error(err)); }); }); it('generates torrents correctly with url reserved characters in file names', function (done) { var base = 'http://s3.amazonaws.com/'; var name = 'content-test'; var files = [ '1+2=3.png', 'file_with_a_#_in_it', 'and&?.png' ]; var torrent = new Torrent(base, name, files); torrent.getMetadata().then(function (res) { var torrentFilePath = path.resolve(__dirname, 'torrents', '45676365a2639359e1291f4945f158a04e9934c8.torrent'); var torrentFile = fs.readFileSync(torrentFilePath); if (torrentFile.toString() === res.toString()) { done(); } else { done(new Error('torrent generated expected to match torrent file')); } }, function (err) { done(new Error(err)); }); }); it('generates torrents with similar and collections', function (done) { var base = 'http://ia700201.us.archive.org/6/items/'; var name = 'jj2005-02-27.fm.shnf'; var files = [ 'jj2005-02-27.fm.d1.md5', 'jj2005-02-27.fm.d1.txt' ]; var torrent = new Torrent(base, name, files, { similar: [ 'ab715690d4c95dd147f6f2fe9f071705bbe22028' ], collections: [ 'com.network.seriesname.season1', 'do.vo.pioneerone.season2' ] }); torrent.getMetadata().then(function (res) { var torrentFilePath = path.resolve(__dirname, 'torrents', 'c9dde7f0febd5105d1f1f531e780da7bff5fd6c5.torrent'); var torrentFile = fs.readFileSync(torrentFilePath); if (torrentFile.toString() === res.toString()) { done(); } else { done(new Error('torrent generated expected to match torrent file')); } }).fail(function (err) { done(new Error(err)); }); }); it('generates signed torrents', function (done) { var base = 'http://ia700201.us.archive.org/6/items/'; var name = 'jj2005-02-27.fm.shnf'; var files = [ 'jj2005-02-27.fm.d1.md5', 'jj2005-02-27.fm.d1.txt' ]; var key = fs.readFileSync(path.resolve(__dirname, 'signing', 'privkey.pem')); var cert = fs.readFileSync(path.resolve(__dirname, 'signing', 'cert.pem')); var torrent = new Torrent(base, name, files, { signing: { 'com.bittorrent': { key: key, cert: cert, info: { '_test': 'Genuine Torrent' } } }, originator: cert }); q.all([ torrent.getInfo(), torrent.getSignatures(), torrent.getSigningAlgorithm() ]).spread(function (info, signatures, algorithm) { /* Assert static info */ assert(signatures.hasOwnProperty('com.bittorrent'), 'expected signing entity'); var certificatePem = '-----BEGIN CERTIFICATE-----' + signatures['com.bittorrent'].certificate.toString('base64') + '-----END CERTIFICATE-----'; assert(certificatePem === cert.toString().replace(/\n/g, ''), 'expected certificate'); var originatorPem = '-----BEGIN CERTIFICATE-----' + info.originator.toString('base64') + '-----END CERTIFICATE-----'; assert(originatorPem === cert.toString().replace(/\n/g, ''), 'expected originator'); /* Verify signature */ var buf = Buffer.concat([ bencode.encode(info), bencode.encode(signatures['com.bittorrent'].info) ]); var verify = crypto.createVerify(algorithm); verify.update(buf); var verifyResult = verify.verify(cert, signatures['com.bittorrent'].signature); assert(verifyResult === true, 'signature verifies'); done(); }).fail(function (err) { done(err); }); }); it('generates signed torrents with a sign callback', function (done) { var base = 'http://ia700201.us.archive.org/6/items/'; var name = 'jj2005-02-27.fm.shnf'; var files = [ 'jj2005-02-27.fm.d1.md5', 'jj2005-02-27.fm.d1.txt' ]; var key = fs.readFileSync(path.resolve(__dirname, 'signing', 'privkey.pem')); var cert = fs.readFileSync(path.resolve(__dirname, 'signing', 'cert.pem')); var torrent = new Torrent(base, name, files, { signing: { 'com.bittorrent': { signCallback: function (buf) { var rsaSign = crypto.createSign('RSA-MD5'); rsaSign.update(buf); return q.resolve(rsaSign.sign(key)); }, cert: cert, info: { '_test': 'Genuine Torrent' } } }, originator: cert }); q.all([ torrent.getInfo(), torrent.getSignatures() ]).spread(function (info, signatures) { /* Assert static info */ assert(signatures.hasOwnProperty('com.bittorrent'), 'expected signing entity'); var certificatePem = '-----BEGIN CERTIFICATE-----' + signatures['com.bittorrent'].certificate.toString('base64') + '-----END CERTIFICATE-----'; assert(certificatePem === cert.toString().replace(/\n/g, ''), 'expected certificate'); var originatorPem = '-----BEGIN CERTIFICATE-----' + info.originator.toString('base64') + '-----END CERTIFICATE-----'; assert(originatorPem === cert.toString().replace(/\n/g, ''), 'expected originator'); /* Verify signature */ var buf = Buffer.concat([ bencode.encode(info), bencode.encode(signatures['com.bittorrent'].info) ]); var verify = crypto.createVerify('RSA-MD5'); verify.update(buf); var verifyResult = verify.verify(cert, signatures['com.bittorrent'].signature); assert(verifyResult === true, 'signature verifies'); done(); }).fail(function (err) { done(err); }); }); });