def _getTorrentData(self, dataPath, files, pieceHashes, pieceLength, mainTracker, trackerList, creationDate, comment, creator): torrentData = {} #tracker torrentData['announce'] = mainTracker.encode('UTF-8') if trackerList is not None: allTracker = [] for tier in trackerList: allTracker.append([trackerUrl.encode('UTF-8') for trackerUrl in tier]) torrentData['announce-list'] = allTracker #other torrentData['encoding'] = 'UTF-8' if creationDate is not None: torrentData['creation date'] = creationDate if comment is not None: torrentData['comment'] = comment.encode('UTF-8') if creator is not None: torrentData['created by'] = creator.encode('UTF-8') #info dict info = {} info['piece length'] = pieceLength info['pieces'] = pieceHashes if len(files) == 1: #single file info['name'] = files[0][0][0].encode('UTF-8') info['length'] = files[0][2] else: #multi file fileInfo = [] for fileSet in files: filePath = [pathComp.encode('UTF-8') for pathComp in fileSet[0]] fileInfo.append({'path':filePath, 'length':fileSet[2]}) info['files'] = fileInfo info['name'] = os.path.split(dataPath)[-1].encode('UTF-8') if info['name'] == '': info['name'] = os.path.split(dataPath[:-1])[-1].encode('UTF-8') assert not info['name'] == '', 'Name still empty?! Path: "%s"' % (dataPath,) torrentData['info'] = info return bencode(torrentData)
def load(self, torrentdata): #decode torrentdata torrentdata = bdecode(torrentdata) #encoding if 'encoding' in torrentdata: self.charset = torrentdata['encoding'] else: self.charset = 'UTF-8' #tracker urls self.announce = [[torrentdata['announce']]] self.amountOfTrackers = 1 if 'announce-list' in torrentdata: self.amountOfTrackers = 0 self.announce = torrentdata['announce-list'] for tier in self.announce: shuffle(tier) self.amountOfTrackers += len(tier) #check urls tierIdx = 0 while tierIdx < len(self.announce): tier = self.announce[tierIdx] urlIdx = 0 #check all url of tier while urlIdx < len(tier): if i2pHttpUrlRegexObj.match(tier[urlIdx]) is None: #invalid tracker url self.log.warn('Found invalid tracker url "%s", ignoring it', tier[urlIdx]) del tier[urlIdx] self.amountOfTrackers -= 1 else: #valid tracker url urlIdx += 1 #check if tier is empty if len(tier) == 0: self.log.warn('No valid tracker urls in tier, ignoring entire tier') del self.announce[tierIdx] else: tierIdx += 1 if self.amountOfTrackers == 0: raise TorrentException('Torrent contains no valid tracker urls!') #creation date of the torrent if 'creation date' in torrentdata: self.creationDate = torrentdata['creation date'] else: self.creationDate = None #torrent comment if 'comment' in torrentdata: self.comment = unicode(torrentdata['comment'], self.charset, 'ignore') else: self.comment = '' #creator of the torrent if 'created by' in torrentdata: self.createdBy = unicode(torrentdata['created by'], self.charset, 'ignore') else: self.createdBy = '' #torrent hash and name info = torrentdata['info'] self.torrentHash = sha1(bencode(info)).digest() self.torrentName = unicode(info['name'], self.charset, 'ignore') #files if 'files' in info: #multiple files self.files = [] sizesum = 0 for sfile in info['files']: #decode path for y in xrange(0, len(sfile['path'])): sfile['path'][y] = unicode(sfile['path'][y], self.charset, 'ignore') #add to list size = sfile['length'] self.files.append({'path':os.path.join(*sfile['path']), 'size':size, 'offset':sizesum}) sizesum += size #add dir name dirName = unicode(info['name'], self.charset, 'ignore') for i in xrange(0, len(self.files)): filePath = os.path.normpath(os.path.join(dirName, self.files[i]['path'])) if not filePath.startswith(dirName): #dangerous relative stuff => ../ and the like raise Exception('Security violation: file "%s" is not inside base directory "%s" (original path: "%s")' % (filePath, dirName, os.path.join((dirName, self.files[i]['path'])))) else: self.files[i]['path'] = filePath else: #only one file self.files = [{'path':os.path.normpath(unicode(info['name'], self.charset, 'ignore')), 'size':info['length'], 'offset':0}] #piece length self.pieceLength = info['piece length'] #piece hashes rawpieces = info['pieces'] self.pieceHashes = [] place = 0 while place < len(rawpieces): self.pieceHashes.append(rawpieces[place:place+20]) place += 20