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)
flkey = 'files' flval = fs 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'] return (infodict,piece_length)
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'] return (infodict, piece_length)