예제 #1
0
 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)
예제 #2
0
    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