예제 #1
0
def bencode_cmd():
    """
    Synopsis::

        beencode [999, 99, 1, 2218, 2318, 2462, 2250]
        li999ei99ei1ei2218ei2318ei2462ei2250ee

        beencode {'h': [890, 377], 't': [3455, 3455, 3455, 3455], 'w': 12333}
        d1:tli3455ei3455ei3455ei3455ee1:hli890ei377ee1:wi12333ee

    """

    boot_logging()

    if len(sys.argv) >= 2:
        return bencode.bencode(sys.argv[1])

    data_01 = [999, 99, 1, 2218, 2318, 2462, 2250]
    data_02 = {
        't': [1234, 5678, 4242],
        'h': [587, 476],
        'w': 42
    }
    data_03 = {'#': 999, '_': 'h1', 't': [2163, 1925, 1092, 1354], 'h': [488, 572], 'w': 10677}
    return bencode.bencode(data_03)
예제 #2
0
 def all():
     from cbencode import Decoder
     from itertools import islice
     import mmap, time
     dec = Decoder(json_decode=BenJson)
     f = file('/tmp/sa/testdata')
     buf = mmap.mmap(f.fileno(), 0, mmap.PROT_READ, mmap.MAP_SHARED)
     chu = ChunkedList()
     #it = islice(dec.decode_iter(buf), 500000)
     it = dec.decode_iter(buf)
     t1 = time.time()
     c = 0
     while True:
         try:
             n = it.next()
             chu.push((n,))
             c += 1
         except StopIteration:
             break
         chu.push(islice(it, 10))
         c += 10
     print 'iter (%d items) took %dms' % (c, (time.time() - t1) * 1000)
     buf = None
     f.close()
     t1 = time.time()
     enc = bencode(chu)
     print 'sze', len(bencode(chu))
     print 'encode took %dms' % ((time.time() - t1) * 1000)
     t1 = time.time()
     c = 0
     for item in dec.decode(enc): # bdecode(enc):
         c += 1
         #print item
     print 'decode (%d items) took %dms' % (c, (time.time() - t1) * 1000)
예제 #3
0
	def __init__(self, torrent_file):
		with open (torrent_file, 'r') as t:
			parsed_torrent = t.read()
		self.info_dict = bencode.bdecode(parsed_torrent)
		self.tracker_url = self.info_dict['announce']
		self.info_hash = hashlib.sha1(bencode.bencode(self.info_dict['info'])).digest()
		self.info_hash_readable = hashlib.sha1(bencode.bencode(self.info_dict['info'])).hexdigest()
		
		if self.info_dict['info'].get('name'):
			self.name = self.info_dict['info']['name']
		self.encoding = self.info_dict.get('encoding', None)
		
		if self.info_dict['info'].get('files'):
			self.no_of_files = len(self.info_dict['info']['files'])
			self.total_length = 0
			for files in self.info_dict['info']['files']:
				self.total_length += files['length']
		
		else:
			self.no_of_files = 1
			self.total_length = self.info_dict['info']['length']
		
		self.subpieces = self.info_dict['info']['pieces']
		self.piece_length = self.info_dict['info']['piece length']
		#['pieces'] is a concatenated string of the hashes of each piece (each takes 20 characters). Splitting these up into a list:
		self.list_of_subpieces_hashes = []
		for i in range(0, len(self.subpieces), 20):
			self.list_of_subpieces_hashes.append(self.subpieces[i:i+20])
		self.no_of_subpieces = len(self.list_of_subpieces_hashes)
		self.bitfield = Bitfield(self)
		self.block_size = 16384
예제 #4
0
def scrape():
    try:
        stats = Swarm.from_hex_hash(request.query["infohash"]).stats()
        return bencode(stats)
    except KeyError:
        stats = {}
        for swarm in Swarm.nonsecret():
            stats.update(swarm.stats())
        return bencode(stats)
예제 #5
0
 def test():
     c = ChunkedList(chunk_size=14)
     c.push(('0'))
     c.push(('1'))
     c.push(('2'))
     c.push(('a', 'b', 'c'))
     c.push(('d', 'e', 'f'))
     d = bdecode(bencode(c))
     d = ChunkedList(d.encode())
     d.push(('g', 'h', 'i'))
     print list(d)
     print list(bdecode(bencode(d)))
예제 #6
0
 def got_message(self, msg, conn):
     t = msg[0]
     r = None
     if t == UTORRENT_MSG:
         print "UTORRENT_MSG"
     if t == CHOKE:
         print "CHOKE"
     elif t == UNCHOKE:
         print "UNCHOKE"
     elif t == INTERESTED:
         print "INTERESTED"
     elif t == NOT_INTERESTED:
         print "NOT_INTERESTED"
     elif t == HAVE:
         i = struct.unpack("!i", msg[1:])[0]
         print "HAVE", i
     elif t == BITFIELD:
         print "BITFIELD"
         self.calc_bitfield(msg[1:])
     elif t == REQUEST:
         print "REQUEST"
     elif t == CANCEL:
         print "CANCEL"
     elif t == PIECE:
         print "PIECE"
     elif t == PORT:
         print "PORT", struct.unpack("!H", msg[1:])[0]
         #self.peerlist[conn.addr]["DHT"] = True
         #self.peerlist[conn.addr]["DHT_PORT"] = struct.unpack("!H", msg[1:])[0]
     #elif t == SUGGEST_PORT:
     #    print "SUGGEST_PORT"
     elif t == HAVE_ALL:
         print "HAVE_ALL"
     elif t == HAVE_NONE:
         print "HAVE_NONE"
     elif t == REJECT_REQUEST:
         print "REJECT_REQUEST"
     elif t == ALLOWED_FAST:
         print "ALLOWED FAST"
     elif t == UTORRENT_MSG:
         ext_type = ord(msg[1])
         d = bdecode(msg[2:])
         print "?"*10, d
         infodict = bencode(self.honey[self.honey.keys()[0]])
         response = {"msg_type": ord(chr(1)), "piece":d["piece"], "total_size":16*2**10}
         response = chr(20) + chr(conn.ut_metadata) + bencode(response) + infodict[d["piece"]*2**14: (d["piece"]+1)*2**14]
         response = struct.pack("!i", len(response)) + response
         print response[:300]
         conn.sock.sendall(response)
     else:
         print "got unknown message", repr(msg)
     # Continue
     return r
예제 #7
0
 def build_meta_file(self, path, file_length, piece_length, pieces_hash):
     port = TRACKER_PORT.__str__()
     ip = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1][0] #Gets the IP and port of the tracker.
     announce = "udp://" + ip + ":" + port #Creates an announce URL.
     filename = path.split("\\")[-1]
     temp = filename.split(".")
     temp[-1] = "torrent"
     torrent_name = temp[0]
     for i in temp[1:]:
         torrent_name += "." + i #turns the file into a .torrent file
     info = {'name' : filename, 'piece length': piece_length, 'length': file_length, 'pieces': pieces_hash }
     file = {"announce" : announce, "info" : info} #Builds the info dictionary and the file
     print file
     MemoryHandler.save_file(torrent_name, bencode.bencode(file)) #Saves them as bencoded data
     return self.hash_piece(bencode.bencode(info)) #Returns the info_hash
예제 #8
0
파일: torrent.py 프로젝트: nduhamel/Canape
def compute_hash(videoObj):
    """ Return torrent hash """
    torrent = urllib.urlopen(videoObj.download_url).read()
    info = bencode.bdecode(torrent)['info']
    h = hashlib.sha1()
    h.update(bencode.bencode(info))
    return h.hexdigest()
예제 #9
0
    def _get_torrent_hash(self, result):

        if result.url.startswith('magnet'):
            result.hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0]
            if len(result.hash) == 32:
                result.hash = b16encode(b32decode(result.hash)).lower()
        else:
            if not result.content:
                logger.log('Torrent without content', logger.ERROR)
                raise Exception('Torrent without content')

            try:
                torrent_bdecode = bdecode(result.content)
            except BTFailure as e:
                logger.log('Unable to bdecode torrent', logger.ERROR)
                logger.log('Torrent bencoded data: {0}'.format(str(result.content)), logger.DEBUG)
                raise
            try:
                info = torrent_bdecode["info"]
            except Exception as e:
                logger.log('Unable to find info field in torrent', logger.ERROR)
                raise
            result.hash = sha1(bencode(info)).hexdigest()

        return result
예제 #10
0
 def to_metainfo(self):
     try:
         info_as_dict = bdecode(redis_connection.get(self.info_hash + ".info"))
         return bencode({"announce": announce_url,
                         "info": info_as_dict })
     except TypeError:
         raise NoInfoException()
예제 #11
0
    def multi_file(self, basePath, check_md5=False):
        """
        Generate multi-file torrent
          check_md5: adds md5sum to the torrentlist
          basePath: path to folder
        Torrent name will automatically be basePath
        """
        if 'length' in self.tdict['info']:
            raise TypeError('Cannot add multi-file to single-file torrent')
        if basePath.endswith('/'):
            basePath = basePath[:-1]
        realPath = path.abspath(basePath)
        toGet = []
        fileList = []
        info_pieces = ''
        data = ''
        for root, subdirs, files in walk(realPath):
            for f in files:
                subPath = path.relpath(root, start=realPath).split('/')
                subPath.append(f)
                subPath = [str(p) for p in subPath]
                toGet.append(subPath)
        for pathList in toGet:
            length = 0
            filePath = ('/').join(pathList)
            if check_md5:
                md5sum = md5()
            fileDict = {
                'path': pathList,
                'length': len(open(path.join(basePath, filePath), "rb").read())
            }
            with open(path.join(basePath, filePath), "rb") as fn:
                while True:
                    filedata = fn.read(self.piece_length)

                    if len(filedata) == 0:
                        break
                    length += len(filedata)

                    data += filedata

                    if len(data) >= self.piece_length:
                        info_pieces += sha1(data[:self.piece_length]).digest()
                        data = data[self.piece_length:]

                    if check_md5:
                        md5sum.update(filedata)
                        fileDict['md5sum'] = md5sum.hexdigest()
            fileList.append(fileDict)
        if len(data) > 0:
            info_pieces += sha1(data).digest()
        self.tdict['info'].update(
            {
                'name': str(path.basename(realPath)),
                'files': fileList,
                'pieces': info_pieces
            }
        )
        info_hash = sha1(bencode(self.tdict['info'])).hexdigest()
        return({'Created': info_hash})
예제 #12
0
파일: Scrape.py 프로젝트: 0rient/TTracker
    def render_GET(self, request):

        HashTableNew.HashTable.do_clean_up()

        start = time.clock()

        info_hash_lst = []
        if 'info_hash' in request.args:
            info_hash_lst = request.args['info_hash']
        else:
            return bencode_faild_str('Mising info_hash')

        ret = {}
        for info_hash in info_hash_lst:
            peers_cnt = HashTable.get_torrent_peers_count(info_hash)
            seeders_cnt = HashTable.get_torrent_seeders_count(info_hash)
            leechers_cnt = peers_cnt - seeders_cnt
            completed_cnt = HashTable.get_completed_by_info_hash(info_hash)
            info_table = {"complete": seeders_cnt, "downloaded": completed_cnt, "incomplete": leechers_cnt}
            ret.update({info_hash:info_table})

        ret = {'files': ret}
        ret = bencode.bencode(ret)
        end = time.clock()
        logging.debug('process scrape query at:%lf' % (end-start))
        Config.process_scrape_query_at = end-start
        return ret
예제 #13
0
파일: connection.py 프로젝트: mct/kohorte
    def send_msg(self, name_, **msg):
        '''
        Send an outgoing Message, translating function keyword arguments into
        the Message arguments.  Before sending the message down the wire, run
        our own validation checks against it, and raise a DecoderError()
        Exception if it fails.

        After validation, bencode the Python dict, and prefix it with an ASCII
        length field.  For human readability, put a space between length field
        and the bencoded blob, and send a \r\n after the blob.
        '''
        try:
            msg['msg'] = name_
            self.validate_message(msg.copy())
        except DecoderError as e:

            # This debugging output is hard to read, but fortunately it
            # shouldn't happen very often.

            print timestamp(), self, "Our own outgoing message failed validation?", msg
            self.close()
            raise

        buf = bencode(msg)
        buf = ('%0' + str(config.msg_len_bytes) + 'x') % len(buf) + ' ' + buf + '\r\n'

        del msg['msg']
        print timestamp(), self, "--> ", name_, repr_msg(msg)
        self.send(buf)
예제 #14
0
def generate_magnet(metadata, dn=None):
    import hashlib
    import base64
    import urllib
    from bencode import bencode

    tr = []
    if "announce-list" in metadata:
        tmp = metadata["announce-list"]
        if isinstance(tmp, list):
            for i in tmp:
                if isinstance(i, list):
                    tr += i
                else:
                    tr.append(i)
    if "announce" in metadata and not metadata["announce"] in tr:
        tr.append(metadata["announce"])

    params = {
        "dn": dn or metadata["info"].get("name", None),
        "tr": tr
    }

    b32hash = base64.b32encode(hashlib.sha1(bencode(metadata["info"])).digest())
    return "magnet:?%s&%s" % ("xt=urn:btih:%s" % b32hash, urllib.urlencode(params, True))
예제 #15
0
파일: torrent.py 프로젝트: angusb/pyrate
    def create_torrent(cls, 
                       file_name, 
                       tracker_url, 
                       content, 
                       piece_length=512,
                       write=True):
        # TODO: add other options like: announce-list, creation date, comment, created by, encoding
        info_dict = {
            'name': file_name,
            'length': len(contents),
            # Fields common to single and multi-file below
            'piece length': piece_length * 1024,
            'pieces': cls._pieces_hashes(contents)
        }

        metainfo = {
            'info': info_dict,
            'announce': tracker_url
        }

        if write:
            with open(file_name, 'w') as f:
                f.write(bencode.bencode(metainfo))

        return cls(file_name, metainfo)
예제 #16
0
    def _get_info_hash(result):

        if result.url.startswith('magnet:'):
            result.hash = re.findall(r'urn:btih:([\w]{32,40})', result.url)[0]
            if len(result.hash) == 32:
                result.hash = b16encode(b32decode(result.hash)).lower()
        else:

            try:
                # `bencode.bdecode` is monkeypatched in `medusa.init`
                torrent_bdecode = bdecode(result.content, allow_extra_data=True)
                info = torrent_bdecode['info']
                result.hash = sha1(bencode(info)).hexdigest()
            except (BencodeDecodeError, KeyError):
                log.warning(
                    'Unable to bdecode torrent. Invalid torrent: {name}. '
                    'Deleting cached result if exists', {'name': result.name}
                )
                cache_db_con = db.DBConnection('cache.db')
                cache_db_con.action(
                    'DELETE FROM [{provider}] '
                    'WHERE name = ? '.format(provider=result.provider.get_id()),
                    [result.name]
                )
            except Exception:
                log.error(traceback.format_exc())

        return result
예제 #17
0
    def _get_torrent_hash(self, result):

        if result.url.startswith('magnet'):
            result.hash = re.findall(r'urn:btih:([\w]{32,40})', result.url)[0]
            if len(result.hash) == 32:
                result.hash = b16encode(b32decode(result.hash)).lower()
        else:
            if not result.content:
                sickrage.LOGGER.error('Torrent without content')
                raise Exception('Torrent without content')

            try:
                torrent_bdecode = bdecode(result.content)
            except BTFailure:
                sickrage.LOGGER.error('Unable to bdecode torrent')
                sickrage.LOGGER.debug('Torrent bencoded data: %r' % result.content)
                raise
            try:
                info = torrent_bdecode[b"info"]
            except Exception:
                sickrage.LOGGER.error('Unable to find info field in torrent')
                raise
            result.hash = sha1(bencode(info)).hexdigest()

        return result
예제 #18
0
파일: peers.py 프로젝트: clin88/bittorrent
    def __init__(self, trackerFile):
        """
        Initalizes the PeerManager, which handles all the peers it is connected
        to.

        Input:
        trackerFile -- takes in a .torrent tracker file.

        Instance Variables:
        self.peer_id     -- My id that I give to other peers.
        self.peers       -- List of peers I am currently connected to. Contains 
                            Peer Objects
        self.pieces      -- List of Piece objects that store the actual data we
                            we are downloading.
        self.tracker     -- The decoded tracker dictionary.
        self.infoHash    -- SHA1 hash of the file we are downloading.
        """
        self.peer_id = '-lita38470993824756-'
        self.peers = []
        self.pieces = []
        self.tracker = bencode.bdecode(open(trackerFile,'rb').read())
        bencodeInfo = bencode.bencode(self.tracker['info'])
        self.infoHash = hashlib.sha1(bencodeInfo).digest()
        self.getPeers()
        self.generatePieces()
        self.peer_id = '-lita38470993887523-'
예제 #19
0
파일: krpc.py 프로젝트: spylfy/DHTCrawler-1
    def handle_fn_qdata(self, data, addr):
        print "Receive find node query"
        
        target_node_id = data["a"]["target"]
        rtable_index = utility.get_rtable_index(utility.xor(self.node_id, target_node_id))
        
        response_nodes = []
        for node in self.rtable[rtable_index]:
            if node[0] == target_node_id:
                response_nodes.append(node)
                break

        if len(response_nodes) == 0:
            response_nodes = self.get_k_closest_nodes(target_node_id)

        node_message = utility.encode_nodes(response_nodes)

        response = {}
        response["t"] = data["t"]
        response["y"] = "r"
        response["r"] = {}
        response["r"]["id"] = self.node_id
        response["r"]["nodes"] = node_message
        response = bencode(response)
        
        try:
            self.socket.sendto(response, addr)
        except:
            pass
예제 #20
0
 def _save_info_(self, info_as_dict):
     bencoded_info_dict = bencode(info_as_dict)
     h = hashlib.new("sha1")
     h.update(bencoded_info_dict)
     self.info_hash = h.hexdigest()
     print("info_hash = " + self.info_hash)
     redis_connection.set(self.info_hash + ".info", bencoded_info_dict)
예제 #21
0
    def __init__(self, raw, ip, pid):
        d = bencode.bdecode(raw)
        try:
            self.announce = [d['announce']]
        except KeyError:
            try:
                self.announce = [ l[0] for l in d['announce-list'] ]
            except KeyError:
                self.magnetinfo = d['magnet-info']
                self.announce = [self.magnetinfo['announce']]

        self.comment = getattr(d, 'comment', 'No Comment')
        self.creator = getattr(d, 'created by', 'Unknown')
        self.date = getattr(d, 'created on', None)
        self.encoding = getattr(d, 'encoding', None)
        info = d['info']
        sha = hashlib.sha1()
        sha.update(bencode.bencode(info))
        self.info_hash = sha.digest()
        print self.info_hash
        self.info = InfoDict(info, self.encoding)

        self.trackers = [ Tracker(TrackerRequest(na=ip, hash=self.info_hash, ID=pid, url=url, stats=self.info.sessionstats())) for url in self.announce ]

        self.info['started'] == True
예제 #22
0
def db_put(co, cdb, key, value, txn):
    cdb.put(key, bencode(value), txn=txn)
    try:
        cache = co.db_cache[db]
    except KeyError:
        cache = co.db_cache[db] = {}
    cache[key] = value
예제 #23
0
    def process(self, event):
        """
        event.event_type
            'modified' | 'created' | 'moved' | 'deleted'
        event.is_directory
            True | False
        event.src_path
            path/to/observed/file
        """

        if event.event_type == 'created' and event.is_directory == False:
            path = event.src_path
            logger.debug('New torrent file detected at: %s', path)
            logger.info('Uploading torrent to the cloud: %s', path)
            if upload_torrent(event.src_path):
                # Open torrent file to get hash
                torrent_file = open(sys.argv[1], "rb")
                metainfo = bencode.bdecode(torrent_file.read())
                info = metainfo['info']
                hash = hashlib.sha1(bencode.bencode(info)).hexdigest()
                dirname = os.path.dirname(path)
                if dirname in prem_config.get('downloads', 'download_categories').split(','):
                    category = dirname
                else:
                    category = ''
                add_task(hash, category)
                logger.debug('Deleting torrent from the watchdir: %s', path)
                os.remove(path)
예제 #24
0
def get_magnet(file_name):
        torrent = open(file_name, 'rb').read()
        metadata = bencode.bdecode(torrent)
        hash_info = metadata['info']
        hash_info = hashlib.sha1(bencode.bencode(hash_info)).hexdigest()
        magnet = "magnet:?xt=urn:btih:" + hash_info
        return magnet
def parse_torrent(torrent_path):
    """Reads a tracker from disk and returns metadata information about it,
    including a list of trackers for the torrent and the hash for the torrent.

    Args:
        torrent_path -- A path to read a torrent file from on disk

    Returns:
        A tuple of three values, 1) a list of zero or more trackers,
        2) the info hash for the files in the tracker, and 3) the total size of
        the files in the torrent
    """
    trackers = []
    size = 0
    info_hash = None
    with open(torrent_path, 'r') as h:
        torrent_data = h.read()
        data = bencode.bdecode(torrent_data)
        trackers.append(data['announce'])

        try:
            trackers += [t[0] for t in data['announce-list']]
        except KeyError:
            pass

        info_hash = hashlib.sha1(bencode.bencode(data['info'])).digest()
        try:
            for files_data in data['info']['files']:
                size += files_data['length']
        except KeyError:
            size = data['info']['length']

    return trackers, info_hash, size
예제 #26
0
파일: models.py 프로젝트: 1nv4d3r5/test
    def torrent(self):
        try:
            data = b64decode(self.torrent_data.encode('utf-8'))
        except TypeError:
            return None
        if not data:
            return None
        data = bdecode(data)
        # transform the data into a template-friendly dict
        info = data.get('info', {})
        metadata = {
            'comment': data.get('comment', None),
            'created_by': data.get('created by', None),
            'creation_date': None,
            'announce': data.get('announce', None),
            'file_name': info.get('name', None),
            'file_length': info.get('length', None),
            'piece_count': len(info.get('pieces', '')) / 20,
            'piece_length': info.get('piece length', None),
            'url_list': data.get('url-list', []),
            'info_hash': None,
        }
        if 'creation date' in data:
            created= datetime.utcfromtimestamp(data['creation date'])
            metadata['creation_date'] = created.replace(tzinfo=utc)
        if info:
            metadata['info_hash'] = hashlib.sha1(bencode(info)).hexdigest()

        return metadata
예제 #27
0
def addtorrent(context, request):
    u = get_current_user(request)
    announce_url = ('http://%s/%s/announce' % (request.registry.settings['hostname'], u.passkey)).encode('utf-8')
    if request.method=="POST":
        form = AddTorrentForm(request.params)
        if form.validate():
            
            filename = save_torrent(form.torrent_file.data, request)
            abs_filename = os.path.join(request.registry.settings['torrent_dir'], filename)
            info = bencode.bencode(bencode.bdecode(open(abs_filename).read())['info'])
            name = form.name.data
            info_hash = hashlib.sha1(info).hexdigest()
            log.error('INFOHASH: '+info_hash)
            torrent = Torrent()
            torrent.info_hash = info_hash
            torrent.name = unicode(name) 
            torrent.info = {}
            torrent.uploaded_time = datetime.datetime.now()
            torrent.torrent_file = filename
            torrent.last_checked = datetime.datetime.now()
            DBSession.add(torrent)
            DBSession.commit()
            log.error(filename)
        return {'form': form, 'announce': announce_url}
    else:
        form = AddTorrentForm()
        return {'form': form, 'announce': announce_url}
    def _send_command_v2(self, command, *parameters):
        """sends a command for protocol version 2. Input is the command name as string
           followed by an arbitrary amount of parameters.
        """

        # we need to add an empty parameter if none is supplied to satisfy the protocol:
        if not parameters:
            parameters = (0,)

        commandlist = [command]
        commandlist.extend(parameters)
        self.TAGNUMBER += 1
        commandlist.append(self.TAGNUMBER)
        payload = bencode(commandlist)
        hexlength = hex(len(payload))[2:].zfill(8)
        encoded = "%s%s" % (hexlength, payload)
        try:
            self.socket.send(encoded)
            return self.TAGNUMBER
        except Exception, info:
            try:
                errno, ermess = info
                if errno in [32, 57]:
                    self._connect(ping=False)
                    self.socket.send(encoded)
                    return self.TAGNUMBER
                elif errno == 61:
                    raise TransmissionClientFailure, """No socket at %s.
Make sure your daemon is up and running!""" % self.socketpath
            except ValueError:
                raise TransmissionClientFailure, "No connection."
예제 #29
0
 def initialize_from_torrent_file(self):
     torrent_dict = bencode.bdecode(open(self.filename).read())
     self.creation_date = datetime.datetime.fromtimestamp(torrent_dict['creation date'])
     self.announce_url = torrent_dict['announce']
     self.created_by = torrent_dict.get('created by', None)
     self.encoding = torrent_dict.get('encoding', None)
     info_dict = torrent_dict['info']
     self.info_hash = sha.new(bencode.bencode(info_dict)).digest()
     self.piece_length = info_dict['piece length']
     self.piece_hashes = [info_dict['pieces'][i:i+20] for i in range(0, len(info_dict['pieces']), 20)]
     self.private = bool(info_dict.get('private', 0))
     if 'files' in info_dict:
         self.mode = 'multi-file'
         self.files = [os.path.join(*f['path']) for f in info_dict['files']]
         self.file_sizes = [f['length'] for f in info_dict['files']]
         self.length = sum([f['length'] for f in info_dict['files']])
         self.name = '; '.join([f['path'][-1] for f in info_dict['files']])
     else:
         self.mode = 'single-file'
         self.name = info_dict['name']
         self.length = info_dict['length']
         self.files = [self.name]
         self.file_sizes = [self.length]
     if self.length > len(self.piece_hashes) * self.piece_length:
         raise Torrent.ParsingException('File size is greater than total size of all pieces')
예제 #30
0
def tracker_request_url(metainfo_file, peer_id, port, uploaded, downloaded, left, event):
    """Generate the URL to request from the tracker"""
    from urllib.parse import urlparse, urlencode, quote, urlunparse

    #create the info_hash from the info section of the metainfo file.
    info_string = bencode(metainfo_file["info"])
    s = sha1()
    s.update(bytes(info_string, "UTF-8"))
    info_hash = quote(s.digest())

    #generate the URL to request, take the existing announce URL from 
    #the metainfo_file
    scheme, netloc, path, params, query, fragment = urlparse(metainfo_file["announce"])

    #add query parameters
    query = urlencode({"info_hash": info_hash,
                       "peer_id": peer_id,
                       "port": port, 
                       "uploaded": uploaded, 
                       "downloaded": downloaded,
                       "left": left,
                       "event": event})

    #put the URL together and return it.
    return urlunparse((scheme, netloc, path, params, query, fragment))
예제 #31
0
 def send_krpc(self, msg, address):
     try:
         self.ufd.sendto(bencode(msg), address)
     except Exception:
         pass
예제 #32
0
 def _send_msg(self, s, data):
     self.nh.send_msg(s, bencode(data))
예제 #33
0
 def _send_response(self, s, mid, data):
     return self.nh.send_response(s, mid, bencode(data))
예제 #34
0
    def send_krpc(self, msg, address):
        try:
#            print(bencode(msg), address)
            self.socket.sendto(bencode(msg), address)
        except Exception:
            pass
예제 #35
0
 def __new__(typ, itr):
     obj = tuple.__new__(typ, itr)
     obj.md5hash = hashlib.md5(bencode.bencode(itr)).hexdigest()
     return obj
예제 #36
0
    def download(self, data, movie, filedata=None):
        log.debug('Sending "%s" to rTorrent.', (data.get('name')))

        if not self.connect():
            return False

        group_name = 'cp_' + data.get('provider').lower()
        if not self._update_provider_group(group_name, data):
            return False

        torrent_params = {}
        if self.conf('label'):
            torrent_params['label'] = self.conf('label')

        if not filedata and data.get('protocol') == 'torrent':
            log.error('Failed sending torrent, no data')
            return False

        # Try download magnet torrents
        if data.get('protocol') == 'torrent_magnet':
            filedata = self.magnetToTorrent(data.get('url'))

            if filedata is False:
                return False

            data['protocol'] = 'torrent'

        info = bdecode(filedata)["info"]
        torrent_hash = sha1(bencode(info)).hexdigest().upper()

        # Convert base 32 to hex
        if len(torrent_hash) == 32:
            torrent_hash = b16encode(b32decode(torrent_hash))

        # Send request to rTorrent
        try:
            # Send torrent to rTorrent
            torrent = self.rt.load_torrent(filedata)

            if not torrent:
                log.error('Unable to find the torrent, did it fail to load?')
                return False

            # Set label
            if self.conf('label'):
                torrent.set_custom(1, self.conf('label'))

            if self.conf('directory') and self.conf('append_label'):
                torrent.set_directory(
                    os.path.join(self.conf('directory'), self.conf('label')))
            elif self.conf('directory'):
                torrent.set_directory(self.conf('directory'))

            # Set Ratio Group
            torrent.set_visible(group_name)

            # Start torrent
            if not self.conf('paused', default=0):
                torrent.start()

            return self.downloadReturnId(torrent_hash)
        except Exception, err:
            log.error('Failed to send torrent to rTorrent: %s', err)
            return False
예제 #37
0
 def send_krpc(self, msg, address):
     self.message_queue.put((bencode(msg), address))
예제 #38
0
파일: m2t.py 프로젝트: cuijinyu/m2t
 def send_msg(self, msg, dst):
     self.s.sendto(bencode(msg), dst)
예제 #39
0
파일: parsedir.py 프로젝트: frimik/swarm
def parsedir(directory,
             parsed,
             files,
             blocked,
             exts=['.torrent'],
             return_metainfo=False,
             errfunc=_errfunc):
    if NOISY:
        errfunc('checking dir')
    dirs_to_check = [directory]
    new_files = {}
    new_blocked = {}
    torrent_type = {}
    while dirs_to_check:  # first, recurse directories and gather torrents
        directory = dirs_to_check.pop()
        newtorrents = False
        for f in os.listdir(directory):
            newtorrent = None
            for ext in exts:
                if f.endswith(ext):
                    newtorrent = ext[1:]
                    break
            if newtorrent:
                newtorrents = True
                p = os.path.join(directory, f)
                new_files[p] = [(os.path.getmtime(p), os.path.getsize(p)), 0]
                torrent_type[p] = newtorrent
        if not newtorrents:
            for f in os.listdir(directory):
                p = os.path.join(directory, f)
                if os.path.isdir(p):
                    dirs_to_check.append(p)

    new_parsed = {}
    to_add = []
    added = {}
    removed = {}
    # files[path] = [(modification_time, size), hash], hash is 0 if the file
    # has not been successfully parsed
    for p, v in new_files.items():  # re-add old items and check for changes
        oldval = files.get(p)
        if not oldval:  # new file
            to_add.append(p)
            continue
        h = oldval[1]
        if oldval[0] == v[0]:  # file is unchanged from last parse
            if h:
                if blocked.has_key(p):  # parseable + blocked means duplicate
                    to_add.append(p)  # other duplicate may have gone away
                else:
                    new_parsed[h] = parsed[h]
                new_files[p] = oldval
            else:
                new_blocked[p] = 1  # same broken unparseable file
            continue
        if parsed.has_key(h) and not blocked.has_key(p):
            if NOISY:
                errfunc('removing ' + p + ' (will re-add)')
            removed[h] = parsed[h]
        to_add.append(p)

    to_add.sort()
    for p in to_add:  # then, parse new and changed torrents
        new_file = new_files[p]
        v, h = new_file
        if new_parsed.has_key(h):  # duplicate
            if not blocked.has_key(p) or files[p][0] != v:
                errfunc('**warning** ' + p + ' is a duplicate torrent for ' +
                        new_parsed[h]['path'])
            new_blocked[p] = 1
            continue

        if NOISY:
            errfunc('adding ' + p)
        try:
            ff = open(p, 'rb')
            d = bdecode(ff.read())
            check_info(d['info'])
            h = sha(bencode(d['info'])).digest()
            new_file[1] = h
            if new_parsed.has_key(h):
                errfunc('**warning** ' + p + ' is a duplicate torrent for ' +
                        new_parsed[h]['path'])
                new_blocked[p] = 1
                continue

            a = {}
            a['path'] = p
            f = os.path.basename(p)
            a['file'] = f
            a['type'] = torrent_type[p]
            i = d['info']
            l = 0
            nf = 0
            if i.has_key('length'):
                l = i.get('length', 0)
                nf = 1
            elif i.has_key('files'):
                for li in i['files']:
                    nf += 1
                    if li.has_key('length'):
                        l += li['length']
            a['numfiles'] = nf
            a['length'] = l
            a['name'] = i.get('name', f)

            def setkey(k, d=d, a=a):
                if d.has_key(k):
                    a[k] = d[k]

            setkey('failure reason')
            setkey('warning message')
            setkey('announce-list')
            if return_metainfo:
                a['metainfo'] = d
        except:
            errfunc('**warning** ' + p + ' has errors')
            new_blocked[p] = 1
            continue
        try:
            ff.close()
        except:
            pass
        if NOISY:
            errfunc('... successful')
        new_parsed[h] = a
        added[h] = a

    for p, v in files.items():  # and finally, mark removed torrents
        if not new_files.has_key(p) and not blocked.has_key(p):
            if NOISY:
                errfunc('removing ' + p)
            removed[v[1]] = parsed[v[1]]

    if NOISY:
        errfunc('done checking')
    return (new_parsed, new_files, new_blocked, added, removed)
예제 #40
0
def update_file(co, handle, pre_heads, rhead, names, dcache, txn):
    def gen_file_points(prune):
        file_points, points = [], ['1']

        true_pre_heads = simplify_precursors(co, handle, co.contents,
                                             pre_heads, txn)[0]

        # don't use pre_heads which are ancestors of rhead
        for pre, index in true_pre_heads:
            if prune and is_ancestor(co, pre, rhead, txn):
                continue

            info = handle_contents_at_point(co,
                                            handle,
                                            pre,
                                            txn,
                                            dcache=dcache)
            if info is None:
                continue
            points = dmerge(points, info['points'])
            file_points.append(
                (info['lines'], info['line points'], info['points']))
        return (file_points, points)

    if not co.merge:
        return 0

    rinfo = handle_contents_at_point(co, handle, rhead, txn, dcache=dcache)

    if rinfo.has_key('delete'):
        # File was deleted remotely, we're done
        # XXX: validate remote history
        return 0

    elif co.editsdb.has_key(handle) and bdecode(
            co.editsdb.get(handle)).has_key('hash'):
        lfile = _handle_to_filename(co, handle, names, txn)
        lfile = path.join(co.local, lfile)

        h = open(lfile, 'rb')
        lines = h.read().split('\n')
        h.close()
        file_points, points = gen_file_points(0)
        line_points = find_resolution(file_points, lines)[0]
        for i in xrange(len(line_points)):
            if line_points[i] is None:
                line_points[i] = '1'

        olines = find_conflict(lines, line_points, points, rinfo['lines'],
                               rinfo['line points'], rinfo['points'])

    else:
        file_points, points = gen_file_points(1)
        if file_points == []:
            # The remote copy is a superset of local changes
            olines = rinfo['lines']
        else:
            lines, line_points, points = find_conflict_multiple_safe(
                file_points)
            olines = find_conflict(lines, line_points, points, rinfo['lines'],
                                   rinfo['line points'], rinfo['points'])

    ls, conflict = [], 0
    for l in olines:
        if type(l) is str:
            ls.append(l)
        else:
            conflict = 1
            ls.append('<<<<<<< local')
            ls.extend(l[0])
            ls.append('=======')
            ls.extend(l[1])
            ls.append('>>>>>>> remote')
    lfile = path.join(co.temppath, binascii.hexlify(handle))
    h = open(lfile, 'wb')
    h.write('\n'.join(ls))
    h.close()
    if conflict:
        set_edit(co, handle, {'hash': 1}, txn)
    mtime = int(path.getmtime(lfile))
    co.modtimesdb.put(handle, bencode(mtime), txn=txn)

    return conflict
예제 #41
0
                      max_rate_period, fudge)

    ratemeasure = RateMeasure(storagewrapper.get_amount_left())
    rm[0] = ratemeasure.data_rejected
    picker = PiecePicker(len(pieces), config['rarest_first_cutoff'])
    for i in xrange(len(pieces)):
        if storagewrapper.do_I_have(i):
            picker.complete(i)
    downloader = Downloader(storagewrapper, picker, config['request_backlog'],
                            config['max_rate_period'], len(pieces),
                            downmeasure, config['snub_time'],
                            ratemeasure.data_came_in)
    connecter = Connecter(make_upload, downloader, choker, len(pieces),
                          upmeasure, config['max_upload_rate'] * 1024,
                          rawserver.add_task)
    infohash = sha(bencode(info)).digest()
    encoder = Encoder(connecter, rawserver, myid, config['max_message_length'],
                      rawserver.add_task, config['keepalive_interval'],
                      infohash, config['max_initiate'])
    rerequest = Rerequester(
        response['announce'], config['rerequest_interval'], rawserver.add_task,
        connecter.how_many_connections, config['min_peers'],
        encoder.start_connection, rawserver.add_task,
        storagewrapper.get_amount_left, upmeasure.get_total,
        downmeasure.get_total, listen_port, config['ip'], myid, infohash,
        config['http_timeout'], errorfunc, config['max_initiate'], doneflag,
        upmeasure.get_rate, downmeasure.get_rate, encoder.ever_got_incoming)
    if config['spew']:
        spewflag.set()
    DownloaderFeedback(choker, rawserver.add_task, statusfunc,
                       upmeasure.get_rate, downmeasure.get_rate,
예제 #42
0
 def _send_request(self, s, data):
     return self.nh.send_request(s, bencode(data))
예제 #43
0
    def ping(self, id):
        query = self.query_head("ping")
        query["a"] = dict(id=id)

        return bencode(query)
예제 #44
0
def main():
    ss = Preferences()

    oldfile = open(ss.get("utresumedat"),'rb').read()
    newfile = open(os.path.join(ss.get("maindir"),u"NEWDAT.dat"),'wb')
    namesandhashfile = open(ss.getwpath("outpath3"),'rb').readlines()

    beforeafterpath = ss.getwpath("outpath4")   #this holds the intermediate changes to happen before actually renaming so you have a chance to edit/change it. (4beforepath-afterpath.txt)

    torrentlist = bencode.bdecode(oldfile)

    #These two things interfere with the processing on the next line 
    fileguarduseless = torrentlist.pop(".fileguard",None)
    rec = torrentlist.pop("rec",None)   #Remove this. 
    #(dict. comprehension expects only dicts as the root keys)
    #create a reverse lookup dict with "Dict comprehension". nice and simple eh? ;-)
    reverselookup={base64.b16encode(value["info"]):[key,value["caption"],value["path"]] for key,value in torrentlist.iteritems()}

    listofbeforeafter = []
    #to modify paths in reverse lookup dict, start by getting the names and hash out of the namesandhashfile   
    for eachline in namesandhashfile:
        nameandhash = eachline.strip().split(' / ')   #strip out the \n with strip() and split on the " / " i put there as a seperator.
        theNewname = nameandhash[0]
        thehash = nameandhash[1]
        #searches the dict's keys for a Hash, if exists. and if so, can be used as the [indexid]
        if thehash in reverselookup:
            key = reverselookup[thehash][0]
            theOldPath = torrentlist[key]["path"]
            theNewPath = os.path.join(os.path.dirname(theOldPath),theNewname)
            if theOldPath != theNewPath:
                listofbeforeafter.append([theOldPath,theNewPath,thehash])   # make a list of a list (stringtoOutputtoFile=[0], hash=[1])            

    #sort, then write file detailing changes to path (before / after)
    listofbeforeafter.sort()
    beforeafterfile = open(beforeafterpath,'wb')
    for eachline in listofbeforeafter:
        try:
            beforeafterfile.write(eachline[0] + " / " + eachline[2] + "\n")         #write oldpath + hash on 1st line    /The hash is duplicated for error checking in case the user accidentally bungles a character while editing...
            beforeafterfile.write(eachline[1] + " / " + eachline[2] + "\n")         #write newpath + hash on 2nd line   /
        except:            
            print "Error writing the before+after file, probably a encoding/unicode error: \n", eachline[0],"\n",eachline[1]
            print "This was a fatal error and program could not continue."
            return
    beforeafterfile.close()

    #At this point the script pauses, and asks the user to confirm changes shown in the beforepath-afterpath.txt file
    raw_input("Press Enter to begin Renaming files.......\\> ")  #wait for the user to press Enter before continuing with anything.

#WRITE TORRENT RESUME.DAT
    beforeafterfile = open(beforeafterpath,'rb').readlines()
    for i in xrange(0, len(beforeafterfile), 2):
        beforeandhash = beforeafterfile[i].strip().split(' / ')
        afterandhash = beforeafterfile[i+1].strip().split(' / ')
        before = beforeandhash[0].decode('utf-8')
        beforehash = beforeandhash[1]
        after = afterandhash[0].decode('utf-8')
        afterhash = afterandhash[1]
        if beforehash == afterhash:
            thehash = beforehash
        else:
            print "Error. You have inadvertently modified one of the hash files, and there is a hash mismatch between before/after entries."
            print "Cannot continue. Exiting. Please save your changes into a new file, locate your error, and re-run and fix it..."
            print "Another possibility is you were missing a / (with 1 character of whitespace on each side surrounding it) as a seperator."
        #searches the dict's keys for a Hash, if exists. and if so, can be used as the [indexid]
        if thehash in reverselookup:
            key = reverselookup[thehash][0]
            torrentlist[key]["caption"] = after[after.rfind("\\")+1:]
            try:
               # prints a number to console to show progress. corresponds to the numbers in the file (every-two-lines).  (tip:) to show incremental numbers use (((i+1)/2)+1) 
               # filenames printed to console, will be missing any unicode chars because the windows console is not unicode compatible!!!! (annoying)
                print i,before.encode('ascii', errors='ignore')
                print i+1,after.encode('ascii', errors='ignore')
                os.rename(before, after)
            except Exception as e:
                traceback.print_exc()       #will output any errors to console but keep going
            torrentlist[key]["path"] = after
            if after.endswith(".mp3") or after.endswith(".flac"):     #.mp3 .flac = I personally didnt have any "Single file" .ogg, .aac, etc that needed special handling in this manner
                if torrentlist[key].has_key("targets"):                     #these lines are a quick fix, for an oversight in the uTorrent process. changing path is not enough
                    torrentlist[key]["targets"][0][1] = after[after.rfind("\\")+1:]           #single-file-mode torrents have a "targets" list that controls the filename

    torrentlist["rec"]=rec   #add the thing we removed back in so we dont break anything (not sure what this is)
                            #fileguard does not need to go back, in fact, purposefully needs to stay out.
    newfile.write(bencode.bencode(torrentlist))
    newfile.close()
    print "Finished writing: ", newfile.name
예제 #45
0
    def find_peer(self, id, node):
        query = self.query_head("find_node")
        query["a"] = dict(id=id, target=node)

        return bencode(query)
예제 #46
0
 def __send_metadata_request(self, extension_id, piece):
     msg_data = bencode({"msg_type": 0, "piece": piece})
     self.__send(
         (pack("!I",
               len(msg_data) + 2) + chr(20) + chr(extension_id) + msg_data))
예제 #47
0
def write_torrent_file(torrent_dict, output_file_path):
    """
    Bencodes, then writes the torrent file to disk.
    """
    with open(output_file_path, 'wb') as file_handle:
        file_handle.write(bencode(torrent_dict))
예제 #48
0
def get_info_hash(info_dict):
    """
    Calculates the hash of the info dictionary.
    """
    return sha1(bencode(info_dict)).hexdigest()
예제 #49
0
 def save_dfile(self):
     self.rawserver.add_task(self.save_dfile, self.save_dfile_interval)
     h = open(self.dfile, 'wb')
     h.write(bencode(self.state))
     h.close()
예제 #50
0
파일: snippet.py 프로젝트: szabo92/gistable
def transfer_torrent(a_url):
    t_hash = a_url.split('/')[-1]
    t_html = requests.get(a_url).content
    # Announce list for trackers
    announce_id = re.findall(
        r'href=.([^>]+)["\']',
        t_html.split('This lists all the active trackers',
                     1)[1].split('compatible list here',
                                 1)[0])[0].split('announcelist_', 1)[-1]
    announce_url = 'http://torrentz.eu/announcelist_%s' % announce_id
    alt_trackers = requests.get(announce_url).content
    alt_trackers = [x.strip() for x in alt_trackers.split('\n') if x.strip()]
    # Slice out the downloads
    downloads = t_html.split('<div class="download">',
                             1)[-1].split('<div class="trackers">', 1)[0]
    downloads = [
        x for x in downloads.split('<dl><dt>')[1:]
        if '<dd>Sponsored Link</dd>' not in x
    ]
    downloads = [re.findall('^.+(http://[^"\']+)', x)[0] for x in downloads]
    # Filter out sites that don't give obvious direct links to .torrent files
    site_blacklist = set([
        'www.torrenthound.com', 'www.houndmirror.com',
        'www.torrentreactor.net', 'www.limetorrents.com', 'www.monova.org',
        'www.torrentcrazy.com'
    ])
    downloads = [
        x for x in downloads
        if re.findall('//([^/]+)', x)[0] not in site_blacklist
    ]
    # Limit it to just 10 sites to visit
    downloads = downloads[:10]
    # Need some formulas
    # Try a generic link extraction, should be enough - we just need *a* torrent
    torrent_files = set()
    for a_site in downloads:
        print "> Getting:", a_site
        a_site_html = requests.get(a_site).content
        torrent_files.update(
            set([
                x for x in re.findall(
                    r'<a [^>]*href=["\'](http:[^"\'>]+\.torrent[^"\'>]*)["\']',
                    a_site_html) if t_hash in x.lower()
            ]))
    torrent_files = sorted(torrent_files)
    # Filter out malware downloads
    malware_blacklist = set(['clickdownloader.com'])
    torrent_files = [
        x for x in torrent_files if re.findall('//[^/]*?([^/.]+[.][^/.]+)/', x)
        [0] not in malware_blacklist
    ]
    # Keep only URLs for domains 'known good' to direct download so far
    site_whitelist = set(['torcache.net'])
    whitelist_torrent_files = [
        x for x in torrent_files
        if re.findall('//([^/]+)', x)[0] in site_whitelist
    ]
    # Check if we have at least one good URL
    if not whitelist_torrent_files:
        print "Error: No whitelisted download locations found"
        print "Downloads:", torrent_files.__repr__()
        print "Sites:", downloads.__repr__()
        return
    # We're only here if we have at least one confirmed direct downloadable .torrent URL
    target_tor = whitelist_torrent_files[0]
    print '\n*** Downloading .torrent:', target_tor
    # Get the contents of the .torrent file
    print '*** Modifying .torrent ...'
    bcode = requests.get(target_tor).content
    bdict = bencode.bdecode(bcode)
    # Get the announce-list - should be a list of lists
    b_announce = bdict.get('announce-list', [])
    # Need to flatten the list and inject our own alt_trackers, using that trick
    b_announce = [y for x in b_announce for y in x]
    # Combine in our alt_trackers and reset to unique and sorted
    b_announce = sorted(set(b_announce + alt_trackers))
    # Split and re-set with udp:// URLs first - and filter out non-sense urls, potentially
    http_t, udp_t = [
        x for x in b_announce if x.lower().startswith('http://')
    ], [x for x in b_announce if x.lower().startswith('udp://')]
    b_announce = udp_t + http_t
    # Refashion into list wrapped items
    b_announce = [[x] for x in b_announce]
    # Set the announce-list to the new value
    bdict['announce-list'] = b_announce
    # Form a newly encoded torrent file
    new_torrent = bencode.bencode(bdict)
    # Save the output to a tempfile
    temp_tor = tempfile.TemporaryFile()
    temp_tor.write(new_torrent)
    temp_tor.seek(0)
    # Upload the file to Dropbox
    print '*** Uploading .torrent:', t_hash + '.torrent'
    response = dropbox_client.put_file('/%s.torrent' % t_hash, temp_tor)
    # Release the tempfile
    temp_tor.close()
    # Get the sharing URL
    print '*** Getting share link ...'
    share_info = dropbox_client.share('/%s.torrent' % t_hash, short_url=False)
    share_url = share_info['url']
    # Fake download it at least once so Dropbox is famliar with our IP address (probably unnecessary)
    _ = requests.get(share_url).content[0:0]
    # Update the URL to include the direct download action
    share_url += '?dl=1'
    # Now to send this URL onto the web interface ...
    rpc_id = requests.get(rpc_url).headers['x-transmission-session-id']
    headers = {
        'Content-Type': 'application/json',
        'Accept': '*/*',
        'X-Requested-With': 'XMLHttpRequest',
        'X-Transmission-Session-Id': rpc_id
    }
    payload = {'method': 'torrent-add', 'arguments': {'filename': share_url}}
    print '*** Transferring to Transmission ...'
    r_upload = requests.post(rpc_url,
                             data=json.dumps(payload),
                             headers=headers)
    r_response = json.loads(r_upload.content)
    print r_response.__repr__()
    print "DONE !"
예제 #51
0
class Tracker:
    def __init__(self, config, rawserver):
        self.response_size = config['response_size']
        self.dfile = config['dfile']
        self.natcheck = config['nat_check']
        self.max_give = config['max_give']
        self.reannounce_interval = config['reannounce_interval']
        self.save_dfile_interval = config['save_dfile_interval']
        self.show_names = config['show_names']
        self.only_local_override_ip = config['only_local_override_ip']
        favicon = config['favicon']
        self.favicon = None
        if favicon:
            try:
                h = open(favicon, 'rb')
                self.favicon = h.read()
                h.close()
            except:
                print "**warning** specified favicon file -- %s -- does not exist." % favicon
        self.rawserver = rawserver
        self.becache1 = {}
        self.becache2 = {}
        self.cache1 = {}
        self.cache2 = {}
        self.times = {}
        if exists(self.dfile):
            h = open(self.dfile, 'rb')
            ds = h.read()
            h.close()
            tempstate = bdecode(ds)
        else:
            tempstate = {}
        if tempstate.has_key('peers'):
            self.state = tempstate
        else:
            self.state = {}
            self.state['peers'] = tempstate
        self.downloads = self.state.setdefault('peers', {})
        self.completed = self.state.setdefault('completed', {})
        statefiletemplate(self.state)
        for x, dl in self.downloads.items():
            self.times[x] = {}
            for y, dat in dl.items():
                self.times[x][y] = 0
                if not dat.get('nat', 1):
                    ip = dat['ip']
                    gip = dat.get('given ip')
                    if gip and is_valid_ipv4(gip) and (
                            not self.only_local_override_ip
                            or is_local_ip(ip)):
                        ip = gip
                    self.becache1.setdefault(x, {})[y] = Bencached(
                        bencode({
                            'ip': ip,
                            'port': dat['port'],
                            'peer id': y
                        }))
                    self.becache2.setdefault(x, {})[y] = compact_peer_info(
                        ip, dat['port'])
        rawserver.add_task(self.save_dfile, self.save_dfile_interval)
        self.prevtime = time()
        self.timeout_downloaders_interval = config[
            'timeout_downloaders_interval']
        rawserver.add_task(self.expire_downloaders,
                           self.timeout_downloaders_interval)
        self.logfile = None
        self.log = None
        if (config['logfile'] != '') and (config['logfile'] != '-'):
            try:
                self.logfile = config['logfile']
                self.log = open(self.logfile, 'a')
                sys.stdout = self.log
                print "# Log Started: ", isotime()
            except:
                print "Error trying to redirect stdout to log file:", sys.exc_info(
                )[0]
        self.allow_get = config['allow_get']
        if config['allowed_dir'] != '':
            self.allowed_dir = config['allowed_dir']
            self.parse_allowed_interval = config['parse_allowed_interval']
            self.parse_allowed()
        else:
            self.allowed = None
        if unquote('+') != ' ':
            self.uq_broken = 1
        else:
            self.uq_broken = 0
        self.keep_dead = config['keep_dead']

    def get_infopage(self):
        if not self.config['show_infopage']:
            return (404, 'Not Found', {
                'Content-Type': 'text/plain',
                'Pragma': 'no-cache'
            }, alas)
        red = self.config['infopage_redirect']
        if red != '':
            return (302, 'Found', {
                'Content-Type': 'text/html',
                'Location': red
            }, '<A HREF="' + red + '">Click Here</A>')

        s = StringIO()
        s.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n' \
            '<html><head><title>BitTorrent download info</title>\n')
        if self.favicon != None:
            s.write('<link rel="shortcut icon" href="/favicon.ico" />\n')
        s.write('</head>\n<body>\n' \
            '<h3>BitTorrent download info</h3>\n'\
            '<ul>\n'
            '<li><strong>tracker version:</strong> %s</li>\n' \
            '<li><strong>server time:</strong> %s</li>\n' \
            '</ul>\n' % (version, isotime()))
        names = self.downloads.keys()
        if not names:
            s.write('<p>not tracking any files yet...</p>\n')
        else:
            names.sort()
            tn = 0
            tc = 0
            td = 0
            tt = 0  # Total transferred
            ts = 0  # Total size
            nf = 0  # Number of files displayed
            uc = {}
            ud = {}
            if self.allowed != None and self.show_names:
                s.write('<table summary="files" border="1">\n' \
                    '<tr><th>info hash</th><th>torrent name</th><th align="right">size</th><th align="right">complete</th><th align="right">downloading</th><th align="right">downloaded</th><th align="right">transferred</th></tr>\n')
            else:
                s.write('<table summary="files">\n' \
                    '<tr><th>info hash</th><th align="right">complete</th><th align="right">downloading</th><th align="right">downloaded</th></tr>\n')
            for name in names:
                l = self.downloads[name]
                n = self.completed.get(name, 0)
                tn = tn + n
                lc = []
                for i in l.values():
                    if type(i) == DictType:
                        if i['left'] == 0:
                            lc.append(1)
                            uc[i['ip']] = 1
                        else:
                            ud[i['ip']] = 1
                c = len(lc)
                tc = tc + c
                d = len(l) - c
                td = td + d
                if self.allowed != None and self.show_names:
                    if self.allowed.has_key(name):
                        nf = nf + 1
                        sz = self.allowed[name]['length']  # size
                        ts = ts + sz
                        szt = sz * n  # Transferred for this torrent
                        tt = tt + szt
                        if self.allow_get == 1:
                            linkname = '<a href="/file?info_hash=' + quote(
                                name
                            ) + '">' + self.allowed[name]['name'] + '</a>'
                        else:
                            linkname = self.allowed[name]['name']
                        s.write('<tr><td><code>%s</code></td><td>%s</td><td align="right">%s</td><td align="right">%i</td><td align="right">%i</td><td align="right">%i</td><td align="right">%s</td></tr>\n' \
                            % (b2a_hex(name), linkname, size_format(sz), c, d, n, size_format(szt)))
                else:
                    s.write('<tr><td><code>%s</code></td><td align="right"><code>%i</code></td><td align="right"><code>%i</code></td><td align="right"><code>%i</code></td></tr>\n' \
                        % (b2a_hex(name), c, d, n))
            ttn = 0
            for i in self.completed.values():
                ttn = ttn + i
            if self.allowed != None and self.show_names:
                s.write(
                    '<tr><td align="right" colspan="2">%i files</td><td align="right">%s</td><td align="right">%i/%i</td><td align="right">%i/%i</td><td align="right">%i/%i</td><td align="right">%s</td></tr>\n'
                    % (nf, size_format(ts), len(uc), tc, len(ud), td, tn, ttn,
                       size_format(tt)))
            else:
                s.write(
                    '<tr><td align="right">%i files</td><td align="right">%i/%i</td><td align="right">%i/%i</td><td align="right">%i/%i</td></tr>\n'
                    % (nf, len(uc), tc, len(ud), td, tn, ttn))
            s.write('</table>\n' \
                '<ul>\n' \
                '<li><em>info hash:</em> SHA1 hash of the "info" section of the metainfo (*.torrent)</li>\n' \
                '<li><em>complete:</em> number of connected clients with the complete file (total: unique IPs/total connections)</li>\n' \
                '<li><em>downloading:</em> number of connected clients still downloading (total: unique IPs/total connections)</li>\n' \
                '<li><em>downloaded:</em> reported complete downloads (total: current/all)</li>\n' \
                '<li><em>transferred:</em> torrent size * total downloaded (does not include partial transfers)</li>\n' \
                '</ul>\n')
        s.write('</body>\n' \
            '</html>\n')
        return (200, 'OK', {
            'Content-Type': 'text/html; charset=iso-8859-1'
        }, s.getvalue())

    def scrapedata(self, name, return_name=True):
        l = self.downloads[name]
        n = self.completed.get(name, 0)
        c = len([1 for i in l.values() if i['left'] == 0])
        d = len(l) - c
        f = {'complete': c, 'incomplete': d, 'downloaded': n}
        if (return_name and self.show_names and self.allowed is not None
                and self.allowed.has_key(name)):
            f['name'] = self.allowed[name]['name']
        return (f)

    def get_scrape(self, paramslist):
        fs = {}
        if paramslist.has_key('info_hash'):
            if self.config['scrape_allowed'] not in ['specific', 'full']:
                return (
                    400, 'Not Authorized', {
                        'Content-Type': 'text/plain',
                        'Pragma': 'no-cache'
                    },
                    bencode({
                        'failure reason':
                        'specific scrape function is not available with this tracker.'
                    }))
            for infohash in paramslist['info_hash']:
                if infohash in self.downloads.keys():
                    fs[infohash] = self.scrapedata(infohash)
        else:
            if self.config['scrape_allowed'] != 'full':
                return (
                    400, 'Not Authorized', {
                        'Content-Type': 'text/plain',
                        'Pragma': 'no-cache'
                    },
                    bencode({
                        'failure reason':
                        'full scrape function is not available with this tracker.'
                    }))
            names = self.downloads.keys()
            names.sort()
            for name in names:
                fs[name] = self.scrapedata(name)

        return (200, 'OK', {
            'Content-Type': 'text/plain'
        }, bencode({'files': fs}))

    def get(self, connection, path, headers):
        try:
            (scheme, netloc, path, pars, query, fragment) = urlparse(path)
            if self.uq_broken == 1:
                path = path.replace('+', ' ')
                query = query.replace('+', ' ')
            path = unquote(path)[1:]
            paramslist = {}
            params = {}
            for s in query.split('&'):
                if s != '':
                    i = s.index('=')
                    kw = unquote(s[:i])
                    key, value = unquote(s[:i]), unquote(s[i + 1:])
                    paramslist.setdefault(key, []).append(value)
                    params[key] = value
        except ValueError, e:
            return (400, 'Bad Request', {
                'Content-Type': 'text/plain'
            }, 'you sent me garbage - ' + str(e))
        if path == '' or path == 'index.html':
            return self.get_infopage()
        elif path == 'scrape':
            return self.get_scrape(paramslist)
        elif (path == 'file') and (self.allow_get == 1) and params.has_key(
                'info_hash') and self.allowed.has_key(params['info_hash']):
            hash = params['info_hash']
            fname = self.allowed[hash]['file']
            fpath = self.allowed[hash]['path']
            return (200, 'OK', {
                'Content-Type': 'application/x-bittorrent',
                'Content-Disposition': 'attachment; filename=' + fname
            }, open(fpath, 'rb').read())
        elif path == 'favicon.ico' and self.favicon != None:
            return (200, 'OK', {'Content-Type': 'image/x-icon'}, self.favicon)
        if path != 'announce':
            return (404, 'Not Found', {
                'Content-Type': 'text/plain',
                'Pragma': 'no-cache'
            }, alas)
        try:
            if not params.has_key('info_hash'):
                raise ValueError, 'no info hash'
            if params.has_key('ip') and not is_valid_ipv4(params['ip']):
                raise ValueError('DNS name or invalid IP address given for IP')
            infohash = params['info_hash']
            if self.allowed != None:
                if not self.allowed.has_key(infohash):
                    return (
                        200, 'OK', {
                            'Content-Type': 'text/plain',
                            'Pragma': 'no-cache'
                        },
                        bencode({
                            'failure reason':
                            'Requested download is not authorized for use with this tracker.'
                        }))
            ip = connection.get_ip()
            ip_override = 0
            if params.has_key('ip') and is_valid_ipv4(
                    params['ip']) and (not self.only_local_override_ip
                                       or is_local_ip(ip)):
                ip_override = 1
            if params.has_key('event') and params['event'] not in [
                    'started', 'completed', 'stopped'
            ]:
                raise ValueError, 'invalid event'
            port = long(params.get('port', ''))
            uploaded = long(params.get('uploaded', ''))
            downloaded = long(params.get('downloaded', ''))
            left = long(params.get('left', ''))
            myid = params.get('peer_id', '')
            if len(myid) != 20:
                raise ValueError, 'id not of length 20'
            rsize = self.response_size
            if params.has_key('numwant'):
                rsize = min(long(params['numwant']), self.max_give)
        except ValueError, e:
            return (400, 'Bad Request', {
                'Content-Type': 'text/plain'
            }, 'you sent me garbage - ' + str(e))
예제 #52
0
 def __init__(self, config, rawserver):
     self.response_size = config['response_size']
     self.dfile = config['dfile']
     self.natcheck = config['nat_check']
     self.max_give = config['max_give']
     self.reannounce_interval = config['reannounce_interval']
     self.save_dfile_interval = config['save_dfile_interval']
     self.show_names = config['show_names']
     self.only_local_override_ip = config['only_local_override_ip']
     favicon = config['favicon']
     self.favicon = None
     if favicon:
         try:
             h = open(favicon, 'rb')
             self.favicon = h.read()
             h.close()
         except:
             print "**warning** specified favicon file -- %s -- does not exist." % favicon
     self.rawserver = rawserver
     self.becache1 = {}
     self.becache2 = {}
     self.cache1 = {}
     self.cache2 = {}
     self.times = {}
     if exists(self.dfile):
         h = open(self.dfile, 'rb')
         ds = h.read()
         h.close()
         tempstate = bdecode(ds)
     else:
         tempstate = {}
     if tempstate.has_key('peers'):
         self.state = tempstate
     else:
         self.state = {}
         self.state['peers'] = tempstate
     self.downloads = self.state.setdefault('peers', {})
     self.completed = self.state.setdefault('completed', {})
     statefiletemplate(self.state)
     for x, dl in self.downloads.items():
         self.times[x] = {}
         for y, dat in dl.items():
             self.times[x][y] = 0
             if not dat.get('nat', 1):
                 ip = dat['ip']
                 gip = dat.get('given ip')
                 if gip and is_valid_ipv4(gip) and (
                         not self.only_local_override_ip
                         or is_local_ip(ip)):
                     ip = gip
                 self.becache1.setdefault(x, {})[y] = Bencached(
                     bencode({
                         'ip': ip,
                         'port': dat['port'],
                         'peer id': y
                     }))
                 self.becache2.setdefault(x, {})[y] = compact_peer_info(
                     ip, dat['port'])
     rawserver.add_task(self.save_dfile, self.save_dfile_interval)
     self.prevtime = time()
     self.timeout_downloaders_interval = config[
         'timeout_downloaders_interval']
     rawserver.add_task(self.expire_downloaders,
                        self.timeout_downloaders_interval)
     self.logfile = None
     self.log = None
     if (config['logfile'] != '') and (config['logfile'] != '-'):
         try:
             self.logfile = config['logfile']
             self.log = open(self.logfile, 'a')
             sys.stdout = self.log
             print "# Log Started: ", isotime()
         except:
             print "Error trying to redirect stdout to log file:", sys.exc_info(
             )[0]
     self.allow_get = config['allow_get']
     if config['allowed_dir'] != '':
         self.allowed_dir = config['allowed_dir']
         self.parse_allowed_interval = config['parse_allowed_interval']
         self.parse_allowed()
     else:
         self.allowed = None
     if unquote('+') != ' ':
         self.uq_broken = 1
     else:
         self.uq_broken = 0
     self.keep_dead = config['keep_dead']
예제 #53
0
    def request_metadata(self):
        msgcode = self._remote_extension_handshake['m']['ut_metadata']
        self._meta_requested = True
        sz = self._remote_extension_handshake['metadata_size']

        chunksz = 2**14
        #request blocks...
        msg_types = { 'REQUEST': 0,
                      'DATA': 1,
                      'REJECT': 2 }

        for chunk in range(int( math.ceil(float(sz) / chunksz) )):
            offset = chunk * chunksz
            msg = {'msg_type': msg_types['REQUEST'],
                   'piece': chunk}
            self.send_message('UTORRENT_MSG', chr(self._remote_extension_handshake['m']['ut_metadata']) + bencode.bencode(msg))
예제 #54
0
         'Content-Type': 'text/plain'
     }, 'you sent me garbage - ' + str(e))
 peers = self.downloads.setdefault(infohash, {})
 self.completed.setdefault(infohash, 0)
 ts = self.times.setdefault(infohash, {})
 confirm = 0
 if peers.has_key(myid):
     myinfo = peers[myid]
     if myinfo.has_key('key'):
         if params.get('key') != myinfo['key']:
             return (200, 'OK', {
                 'Content-Type': 'text/plain',
                 'Pragma': 'no-cache'
             },
                     bencode({
                         'failure reason':
                         'key did not match key supplied earlier'
                     }))
         confirm = 1
     elif myinfo['ip'] == ip:
         confirm = 1
 else:
     confirm = 1
 if params.get('event', '') != 'stopped' and confirm:
     ts[myid] = time()
     if not peers.has_key(myid):
         peers[myid] = {'ip': ip, 'port': port, 'left': left}
         if params.has_key('key'):
             peers[myid]['key'] = params['key']
         if params.has_key('ip') and is_valid_ipv4(params['ip']):
             peers[myid]['given ip'] = params['ip']
         mip = ip
예제 #55
0
    def download(self, data = None, media = None, filedata = None):
        """ Send a torrent/nzb file to the downloader

        :param data: dict returned from provider
            Contains the release information
        :param media: media dict with information
            Used for creating the filename when possible
        :param filedata: downloaded torrent/nzb filedata
            The file gets downloaded in the searcher and send to this function
            This is done to have failed checking before using the downloader, so the downloader
            doesn't need to worry about that
        :return: boolean
            One faile returns false, but the downloaded should log his own errors
        """

        if not media: media = {}
        if not data: data = {}

        log.debug('Sending "%s" to rTorrent.', (data.get('name')))

        if not self.connect():
            return False

        torrent_params = {}
        if self.conf('label'):
            torrent_params['label'] = self.conf('label')

        if not filedata and data.get('protocol') == 'torrent':
            log.error('Failed sending torrent, no data')
            return False

        # Try download magnet torrents
        if data.get('protocol') == 'torrent_magnet':
            filedata = self.magnetToTorrent(data.get('url'))

            if filedata is False:
                return False

            data['protocol'] = 'torrent'

        info = bdecode(filedata)["info"]
        torrent_hash = sha1(bencode(info)).hexdigest().upper()

        # Convert base 32 to hex
        if len(torrent_hash) == 32:
            torrent_hash = b16encode(b32decode(torrent_hash))

        # Send request to rTorrent
        try:
            # Send torrent to rTorrent
            torrent = self.rt.load_torrent(filedata, verify_retries=10)

            if not torrent:
                log.error('Unable to find the torrent, did it fail to load?')
                return False

            # Set label
            if self.conf('label'):
                torrent.set_custom(1, self.conf('label'))

            if self.conf('directory'):
                torrent.set_directory(self.conf('directory'))

            # Start torrent
            if not self.conf('paused', default = 0):
                torrent.start()

            return self.downloadReturnId(torrent_hash)
        except Exception as err:
            log.error('Failed to send torrent to rTorrent: %s', err)
            return False
예제 #56
0
def get_info_hash_from_data(torrent_data):
    metainfo = bencode.bdecode(torrent_data)
    info = metainfo['info']
    return hashlib.sha1(bencode.bencode(info)).hexdigest().upper()
예제 #57
0
    def error_message(self, code, msg):
        resp = {"t": "aa", "y": "e", "e": [code, msg]}

        return bencode(resp)
예제 #58
0
    def get_peers(self, id, torrent):
        query = self.query_head("get_peers")
        query["a"] = dict(id=id, info_hash=torrent)

        return bencode(query)
예제 #59
0
def request_metadata(the_socket, ut_metadata, piece):
    """bep_0009"""
    msg = chr(BT_MSG_ID) + chr(ut_metadata) + bencode({"msg_type": 0, "piece": piece})
    send_message(the_socket, msg)
예제 #60
0
def send_ext_handshake(the_socket):
    msg = chr(BT_MSG_ID) + chr(EXT_HANDSHAKE_ID) + bencode(
        {"m": {
            "ut_metadata": 1
        }})
    send_message(the_socket, msg)