Example #1
0
def makeinfo(input, userabortflag, userprogresscallback):
    """ Calculate hashes and create torrent file's 'info' part """
    encoding = input['encoding']

    pieces = []
    sh = sha()
    done = 0
    fs = []
    totalsize = 0
    totalhashed = 0

    # 1. Determine which files should go into the torrent (=expand any dirs
    # specified by user in input['files']
    subs = []
    for file in input['files']:
        inpath = file['inpath']
        outpath = file['outpath']

        if DEBUG:
            print >> sys.stderr, "makeinfo: inpath", inpath, "outpath", outpath

        if os.path.isdir(inpath):
            dirsubs = subfiles(inpath)
            subs.extend(dirsubs)
        else:
            if outpath is None:
                subs.append(([os.path.basename(inpath)], inpath))
            else:
                subs.append((filename2pathlist(outpath, skipfirst=True), inpath))

    subs.sort()

    # 2. Calc total size
    newsubs = []
    for p, f in subs:
        if 'live' in input:
            size = input['files'][0]['length']
        else:
            size = os.path.getsize(f)
        totalsize += size
        newsubs.append((p, f, size))
    subs = newsubs

    # 3. Calc piece length from totalsize if not set
    if input['piece length'] == 0:
        if input['createmerkletorrent']:
            # used to be 15=32K, but this works better with slow python
            piece_length = 2 ** 18
        else:
            # Niels we want roughly between 1000-2000 pieces
            # This results in the following logic:

            # We start with 32K pieces
            piece_length = 2 ** 15

            while totalsize / piece_length > 2000:
                # too many piece, double piece_size
                piece_length *= 2
    else:
        piece_length = input['piece length']

    # 4. Read files and calc hashes, if not live
    if 'live' not in input:
        for p, f, size in subs:
            pos = 0

            h = open(f, 'rb')

            if input['makehash_md5']:
                hash_md5 = md5.new()
            if input['makehash_sha1']:
                hash_sha1 = sha()
            if input['makehash_crc32']:
                hash_crc32 = zlib.crc32('')

            while pos < size:
                a = min(size - pos, piece_length - done)

                # See if the user cancelled
                if userabortflag is not None and userabortflag.isSet():
                    return (None, None)

                readpiece = h.read(a)

                # See if the user cancelled
                if userabortflag is not None and userabortflag.isSet():
                    return (None, None)

                sh.update(readpiece)

                if input['makehash_md5']:
                    # Update MD5
                    hash_md5.update(readpiece)

                if input['makehash_crc32']:
                    # Update CRC32
                    hash_crc32 = zlib.crc32(readpiece, hash_crc32)

                if input['makehash_sha1']:
                    # Update SHA1
                    hash_sha1.update(readpiece)

                done += a
                pos += a
                totalhashed += a

                if done == piece_length:
                    pieces.append(sh.digest())
                    done = 0
                    sh = sha()

                if userprogresscallback is not None:
                    userprogresscallback(float(totalhashed) / float(totalsize))

            newdict = {'length': num2num(size),
                       'path': uniconvertl(p, encoding),
                       'path.utf-8': uniconvertl(p, 'utf-8')}

            # Find and add playtime
            for file in input['files']:
                if file['inpath'] == f:
                    if file['playtime'] is not None:
                        newdict['playtime'] = file['playtime']
                    break

            if input['makehash_md5']:
                newdict['md5sum'] = hash_md5.hexdigest()
            if input['makehash_crc32']:
                newdict['crc32'] = "%08X" % hash_crc32
            if input['makehash_sha1']:
                newdict['sha1'] = hash_sha1.digest()

            fs.append(newdict)

            h.close()

        if done > 0:
            pieces.append(sh.digest())

    # 5. Create info dict
    if len(subs) == 1:
        flkey = 'length'
        flval = num2num(totalsize)
        name = subs[0][0][0]
    else:
        flkey = 'files'
        flval = fs

        if 'name' in input:  # allow someone to overrule the default name if multifile
            name = input['name']
        else:
            outpath = input['files'][0]['outpath']
            l = filename2pathlist(outpath)
            name = l[0]

    infodict = {'piece length': num2num(piece_length), flkey: flval,
            'name': uniconvert(name, encoding),
            'name.utf-8': uniconvert(name, 'utf-8')}

    if 'live' not in input:

        if input['createmerkletorrent']:
            merkletree = MerkleTree(piece_length, totalsize, None, pieces)
            root_hash = merkletree.get_root_hash()
            infodict.update({'root hash': root_hash})
        else:
            infodict.update({'pieces': ''.join(pieces)})
    else:
        # With source auth, live is a dict
        infodict['live'] = input['live']

    if 'cs_keys' in input:
        # This is a closed swarm - add torrent keys
        infodict['cs_keys'] = input['cs_keys']

    if 'ns-metadata' in input:
        # This has P2P-Next metadata, store in info field to make it
        # immutable.
        infodict['ns-metadata'] = input['ns-metadata']

    if len(subs) == 1:
        # Find and add playtime
        for file in input['files']:
            if file['inpath'] == f:
                if file['playtime'] is not None:
                    infodict['playtime'] = file['playtime']

    return (infodict, piece_length)
Example #2
0
    def setUpPostSession(self):
        """ override TestAsServer """
        TestAsServer.setUpPostSession(self)

        # Let Tribler start downloading an non-functioning torrent, so
        # we can talk to a normal download engine.
        self.tdef = TorrentDef()
        self.sourcefn = os.path.join(os.getcwd(), "API", "file2.wmv")
        self.tdef.add_content(self.sourcefn)
        self.tdef.set_create_merkle_torrent(True)
        self.tdef.set_tracker("http://127.0.0.1:12/announce")
        self.tdef.finalize()

        self.torrentfn = os.path.join(self.session.get_state_dir(), "gen.torrent")
        self.tdef.save(self.torrentfn)

        dscfg = self.setUpDownloadConfig()

        self.session.start_download(self.tdef, dscfg)

        self.infohash = self.tdef.get_infohash()
        self.mylistenport = 4810

        self.numpieces = (self.tdef.get_length() + self.tdef.get_piece_length() - 1) / self.tdef.get_piece_length()
        b = Bitfield(self.numpieces)
        for i in range(self.numpieces):
            b[i] = True
        self.assert_(b.complete())
        self.seederbitfieldstr = b.tostring()

        # piece_hashes = ['\x01\x02\x03\x04\x05\x06\x07\x08\x07\x06\x05\x04\x03\x02\x01\x00\x01\x02\x03\x04' ] * npieces
        # Construct Merkle tree
        tdef2 = TorrentDef()
        tdef2.add_content(self.sourcefn)
        tdef2.set_create_merkle_torrent(False)
        tdef2.set_tracker("http://127.0.0.1:12/announce")
        tdef2.set_piece_length(self.tdef.get_piece_length())
        tdef2.finalize()
        metainfo = tdef2.get_metainfo()

        piecesstr = metainfo['info']['pieces']
        print >> sys.stderr, "test: pieces has len", len(piecesstr)
        piece_hashes = []
        for i in range(0, len(piecesstr), 20):
            hash = piecesstr[i:i + 20]
            print >> sys.stderr, "test: piece", i / 20, "hash", repr(hash)
            piece_hashes.append(hash)

        print >> sys.stderr, "test: Putting", len(piece_hashes), "into MerkleTree, size", self.tdef.get_piece_length(), tdef2.get_piece_length()

        self.tree = MerkleTree(self.tdef.get_piece_length(), self.tdef.get_length(), None, piece_hashes)

        f = open(self.sourcefn, "rb")
        piece1 = f.read(2 ** 18)
        piece2 = f.read(2 ** 18)
        print >> sys.stderr, "read piece1", len(piece1)
        print >> sys.stderr, "read piece2", len(piece2)
        f.close()
        hash1 = sha(piece1).digest()
        hash2 = sha(piece2).digest()
        print >> sys.stderr, "hash piece1", repr(hash1)
        print >> sys.stderr, "hash piece2", repr(hash2)
        f2 = open("piece1.bin", "wb")
        f2.write(piece2)
        f2.close()
Example #3
0
        outpath = input['files'][0]['outpath']
        l = filename2pathlist(outpath)
        name = l[0]

    infodict = {
        'piece length': num2num(piece_length),
        flkey: flval,
        'name': uniconvert(name, encoding),
        'name.utf-8': uniconvert(name, 'utf-8')
    }

    if 'live' not in input:

        if input['createmerkletorrent']:
            merkletree = MerkleTree(piece_length, totalsize, None, pieces)
            root_hash = merkletree.get_root_hash()
            infodict.update({'root hash': root_hash})
        else:
            infodict.update({'pieces': ''.join(pieces)})
    else:
        # With source auth, live is a dict
        infodict['live'] = input['live']

    if len(subs) == 1:
        # Find and add playtime
        for file in input['files']:
            if file['inpath'] == f:
                if file['playtime'] is not None:
                    infodict['playtime'] = file['playtime']