Ejemplo n.º 1
0
    def announce(self, event=None):
        self.last_time = time()
        s = ('%s&uploaded=%s&downloaded=%s&left=%s' % (self.url, str(
            self.up()), str(self.down()), str(self.amount_left())))
        if self.last is not None:
            s += '&last=' + quote(str(self.last))
        if self.trackerid is not None:
            s += '&trackerid=' + quote(str(self.trackerid))
        if self.howmany() >= self.maxpeers:
            s += '&numwant=0'
        else:
            s += '&compact=1'
        if event != None:
            s += '&event=' + ['started', 'completed', 'stopped'][event]
        set = SetOnce().set

        def checkfail(self=self, set=set):
            if set():
                if self.last_failed and self.upratefunc(
                ) < 100 and self.downratefunc() < 100:
                    self.errorfunc(
                        'Problem connecting to tracker - timeout exceeded')
                self.last_failed = True

        self.sched(checkfail, self.timeout)
        Thread(target=self.rerequest, args=[s, set]).start()
Ejemplo n.º 2
0
    def announce(self, event=None):
        self.last_time = time()
        s = "%s&uploaded=%s&downloaded=%s&left=%s" % (
            self.url,
            str(self.up()),
            str(self.down()),
            str(self.amount_left()),
        )
        if self.last is not None:
            s += "&last=" + quote(str(self.last))
        if self.trackerid is not None:
            s += "&trackerid=" + quote(str(self.trackerid))
        if self.howmany() >= self.maxpeers:
            s += "&numwant=0"
        else:
            s += "&compact=1"
        if event != None:
            s += "&event=" + ["started", "completed", "stopped"][event]
        set = SetOnce().set

        def checkfail(self=self, set=set):
            if set():
                if self.last_failed and self.upratefunc() < 100 and self.downratefunc() < 100:
                    self.errorfunc("Problem connecting to tracker - timeout exceeded")
                self.last_failed = True

        self.sched(checkfail, self.timeout)
        Thread(target=self.rerequest, args=[s, set]).start()
Ejemplo n.º 3
0
 def __init__(self, url, interval, sched, howmany, minpeers, connect,
              externalsched, amount_left, up, down, port, ip, myid,
              infohash, timeout, errorfunc, maxpeers, doneflag, upratefunc,
              downratefunc, ever_got_incoming):
     self.url = ('%s?info_hash=%s&peer_id=%s&port=%s&key=%s' %
                 (url, quote(infohash), quote(myid), str(port),
                  b2a_hex(''.join([chr(randrange(256))
                                   for i in xrange(4)]))))
     if ip != '':
         self.url += '&ip=' + quote(ip)
     self.interval = interval
     self.last = None
     self.trackerid = None
     self.announce_interval = 30 * 60
     self.sched = sched
     self.howmany = howmany
     self.minpeers = minpeers
     self.connect = connect
     self.externalsched = externalsched
     self.amount_left = amount_left
     self.up = up
     self.down = down
     self.timeout = timeout
     self.errorfunc = errorfunc
     self.maxpeers = maxpeers
     self.doneflag = doneflag
     self.upratefunc = upratefunc
     self.downratefunc = downratefunc
     self.ever_got_incoming = ever_got_incoming
     self.last_failed = True
     self.last_time = 0
Ejemplo n.º 4
0
 def __init__(self, url, interval, sched, howmany, minpeers, 
         connect, externalsched, amount_left, up, down,
         port, ip, myid, infohash, timeout, errorfunc, maxpeers, doneflag,
         upratefunc, downratefunc, ever_got_incoming):
     self.url = ('%s?info_hash=%s&peer_id=%s&port=%s&key=%s' %
         (url, quote(infohash), quote(myid), str(port),
         b2a_hex(''.join([chr(randrange(256)) for i in xrange(4)]))))
     self.ip = ip
     self.interval = interval
     self.last = None
     self.trackerid = None
     self.announce_interval = 30 * 60
     self.sched = sched
     self.howmany = howmany
     self.minpeers = minpeers
     self.connect = connect
     self.externalsched = externalsched
     self.amount_left = amount_left
     self.up = up
     self.down = down
     self.timeout = timeout
     self.errorfunc = errorfunc
     self.maxpeers = maxpeers
     self.doneflag = doneflag
     self.upratefunc = upratefunc
     self.downratefunc = downratefunc
     self.ever_got_incoming = ever_got_incoming
     self.last_failed = True
     self.last_time = 0
Ejemplo n.º 5
0
 def announce(self, event = None):
     self.last_time = time()
     url = self.get_url()
     s = ('%s&uploaded=%s&downloaded=%s&left=%s' %
         (url, str(self.up()), str(self.down()), 
         str(self.amount_left())))
     if self.last is not None:
         s += '&last=' + quote(str(self.last))
     if self.trackerid is not None:
         s += '&trackerid=' + quote(str(self.trackerid))
     if self.howmany() >= self.maxpeers:
         s += '&numwant=0'
     else:
         s += '&compact=1'
     if event != None:
         s += '&event=' + ['started', 'completed', 'stopped'][event]
     set = SetOnce().set
     def checkfail(self = self, set = set):
         if set():
             if self.last_failed:
                 if self.upratefunc() < 100 and self.downratefunc() < 100:
                     self.errorfunc('Problem connecting to tracker - timeout exceeded', 'tracker_timeout')
                 else:
                     self.errorfunc('Problem connecting to tracker - timeout exceeded', 'tracker_bcool')
             self.last_failed = True
     self.sched(checkfail, self.timeout)
     Thread(target = self.rerequest, args = [s, set]).start()
Ejemplo n.º 6
0
 def announce(self, event = None):
     # Update the time we last made a request to the tracker.
     self.last_time = time()
     # Append total uploaded, total downloaded, and bytes left to download. 
     s = ('%s&uploaded=%s&downloaded=%s&left=%s' %
         (self.url, str(self.up()), str(self.down()), 
         str(self.amount_left())))
     if self.last is not None:
         # Append the last time this client made a request to the tracker.
         s += '&last=' + quote(str(self.last))
     if self.trackerid is not None:
         # If not the first request, append the id this tracker previously returned.
         s += '&trackerid=' + quote(str(self.trackerid))
     if self.howmany() >= self.maxpeers:
         # Don't need any more peers to connect to.
         s += '&numwant=0'
     else:
         # Return peer IP and port addresses in 6 binary bytes.
         s += '&compact=1'
     # Event is not specified if this request is one performed at regular intervals.
     if event != None:
         s += '&event=' + ['started', 'completed', 'stopped'][event]
     # Method that returns True the first time and False every subsequent time.
     set = SetOnce().set
     def checkfail(self = self, set = set):
         if set():
             # Only get here if the tracker did not reply and call set() in rerequest first.
             if self.last_failed and self.upratefunc() < 100 and self.downratefunc() < 100:
                 self.errorfunc('Problem connecting to tracker - timeout exceeded')
             self.last_failed = True
     # Method checkfail will run if the tracker does not reply to this request.
     self.sched(checkfail, self.timeout)
     Thread(target = self.rerequest, args = [s, set]).start()
Ejemplo n.º 7
0
 def __init__(self, url, interval, sched, howmany, minpeers, connect,
              externalsched, amount_left, up, down, port, ip, myid,
              infohash, timeout, errorfunc, maxpeers, doneflag, upratefunc,
              downratefunc, ever_got_incoming):
     # The URL and query paramters to always pass.
     self.url = ('%s?info_hash=%s&peer_id=%s&port=%s&key=%s' %
                 (url, quote(infohash), quote(myid), str(port),
                  b2a_hex(''.join([chr(randrange(256))
                                   for i in xrange(4)]))))
     # The IP address of this client.
     self.ip = ip
     # The time in seconds between requesting more peers.
     self.interval = interval
     # The last time this client got a reply from the tracker.
     self.last = None
     # The identifier returned by the tracker, which this client uses on subsequent requests.
     self.trackerid = None
     # Maximum seconds between sending requests to the tracker.
     self.announce_interval = 30 * 60
     # Function to schedule events in the reactor loop of RawServer.
     self.sched = sched
     # Method that returns how many peers this client is connected to.
     self.howmany = howmany
     # If connected to this many peers, may skip making a request to the tracker.
     self.minpeers = minpeers
     # Method on Connecter that starts a connection to a peer.
     self.connect = connect
     # Function to schedule events in the reactor loop of RawServer.
     self.externalsched = externalsched
     # Method to get the amount of data left.
     self.amount_left = amount_left
     # Method to get the total bytes uploaded.
     self.up = up
     # Method to get the total bytes downloaded.
     self.down = down
     # HTTP timeout when making a request to the tracker.
     self.timeout = timeout
     # Callback invoked with a string describing any error.
     self.errorfunc = errorfunc
     # If connected to this many peers, will not request any more from the tracker.
     self.maxpeers = maxpeers
     # Flag set if we have all pieces and are seeding.
     self.doneflag = doneflag
     # Method to get the upload rate.
     self.upratefunc = upratefunc
     # Method to get the download rate.
     self.downratefunc = downratefunc
     # Method that returns True if we ever got an incoming connection.
     self.ever_got_incoming = ever_got_incoming
     # True if the last request to the tracker failed.
     self.last_failed = True
     # The last time this client made a request to the tracker.
     self.last_time = 0
Ejemplo n.º 8
0
 def __init__(self, url, interval, sched, howmany, minpeers, 
         connect, externalsched, amount_left, up, down,
         port, ip, myid, infohash, timeout, errorfunc, maxpeers, doneflag,
         upratefunc, downratefunc, ever_got_incoming):
     # The URL and query paramters to always pass.
     self.url = ('%s?info_hash=%s&peer_id=%s&port=%s&key=%s' %
         (url, quote(infohash), quote(myid), str(port),
         b2a_hex(''.join([chr(randrange(256)) for i in xrange(4)]))))
     # The IP address of this client.
     self.ip = ip
     # The time in seconds between requesting more peers.
     self.interval = interval
     # The last time this client got a reply from the tracker.
     self.last = None
     # The identifier returned by the tracker, which this client uses on subsequent requests.
     self.trackerid = None
     # Maximum seconds between sending requests to the tracker.
     self.announce_interval = 30 * 60
     # Function to schedule events in the reactor loop of RawServer.
     self.sched = sched
     # Method that returns how many peers this client is connected to.
     self.howmany = howmany
     # If connected to this many peers, may skip making a request to the tracker.
     self.minpeers = minpeers
     # Method on Connecter that starts a connection to a peer.
     self.connect = connect
     # Function to schedule events in the reactor loop of RawServer.
     self.externalsched = externalsched
     # Method to get the amount of data left.
     self.amount_left = amount_left
     # Method to get the total bytes uploaded.
     self.up = up
     # Method to get the total bytes downloaded.
     self.down = down
     # HTTP timeout when making a request to the tracker.
     self.timeout = timeout
     # Callback invoked with a string describing any error.
     self.errorfunc = errorfunc
     # If connected to this many peers, will not request any more from the tracker.
     self.maxpeers = maxpeers
     # Flag set if we have all pieces and are seeding.
     self.doneflag = doneflag
     # Method to get the upload rate.
     self.upratefunc = upratefunc
     # Method to get the download rate.
     self.downratefunc = downratefunc
     # Method that returns True if we ever got an incoming connection.
     self.ever_got_incoming = ever_got_incoming
     # True if the last request to the tracker failed.
     self.last_failed = True
     # The last time this client made a request to the tracker.
     self.last_time = 0
Ejemplo n.º 9
0
    def __init__(self, url, interval, url_list, sched, howmany, minpeers, 
            connect, externalsched, amount_left, up, down,
            port, ip, myid, infohash, timeout, errorfunc, maxpeers, doneflag,
            upratefunc, downratefunc, ever_got_incoming):
        
        self.url_params = ('?info_hash=%s&peer_id=%s&port=%s&key=%s' %
            (quote(infohash), quote(myid), str(port),
            b2a_hex(''.join([chr(randrange(256)) for i in xrange(4)]))))
        if ip != '':
            self.url_params += '&ip=' + quote(ip)
        
        self.url_list = []
        if url_list == None:
            self.url_list.append(url)
        else:
            for ugroup in url_list:
                for url in ugroup:
                    self.url_list.append(url)

        self.interval = interval
        self.last = None
        self.trackerid = None
        self.announce_interval = 30 * 60
        self.sched = sched
        self.howmany = howmany
        self.minpeers = minpeers
        self.connect = connect
        self.externalsched = externalsched
        self.amount_left = amount_left
        self.up = up
        self.down = down
        self.timeout = timeout
        self.errorfunc = errorfunc
        self.maxpeers = maxpeers
        self.doneflag = doneflag
        self.upratefunc = upratefunc
        self.downratefunc = downratefunc
        self.ever_got_incoming = ever_got_incoming
        self.last_failed = True
        self.last_time = 0
Ejemplo n.º 10
0
    def announce(self, event=None):
        # Update the time we last made a request to the tracker.
        self.last_time = time()
        # Append total uploaded, total downloaded, and bytes left to download.
        s = ('%s&uploaded=%s&downloaded=%s&left=%s' % (self.url, str(
            self.up()), str(self.down()), str(self.amount_left())))
        if self.last is not None:
            # Append the last time this client made a request to the tracker.
            s += '&last=' + quote(str(self.last))
        if self.trackerid is not None:
            # If not the first request, append the id this tracker previously returned.
            s += '&trackerid=' + quote(str(self.trackerid))
        if self.howmany() >= self.maxpeers:
            # Don't need any more peers to connect to.
            s += '&numwant=0'
        else:
            # Return peer IP and port addresses in 6 binary bytes.
            s += '&compact=1'
        # Event is not specified if this request is one performed at regular intervals.
        if event != None:
            s += '&event=' + ['started', 'completed', 'stopped'][event]
        # Method that returns True the first time and False every subsequent time.
        set = SetOnce().set

        def checkfail(self=self, set=set):
            if set():
                # Only get here if the tracker did not reply and call set() in rerequest first.
                if self.last_failed and self.upratefunc(
                ) < 100 and self.downratefunc() < 100:
                    self.errorfunc(
                        'Problem connecting to tracker - timeout exceeded')
                self.last_failed = True

        # Method checkfail will run if the tracker does not reply to this request.
        self.sched(checkfail, self.timeout)
        Thread(target=self.rerequest, args=[s, set]).start()
Ejemplo n.º 11
0
def encode_for_filesystem(path):
    assert isinstance(path, unicode)

    bad = False
    encoding = get_filesystem_encoding()
    if encoding == None:
        encoded_path = path
    else:
        try:
            encoded_path = path.encode(encoding)
        except:
            bad = True
            path.replace(u"%", urllib.quote(u"%"))
            encoded_path = path.encode(encoding, 'urlquote')

    return (encoded_path, bad)
Ejemplo n.º 12
0
    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())
Ejemplo n.º 13
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:
            if isfile(favicon):
                h = open(favicon, 'rb')
                self.favicon = h.read()
                h.close()
            else:
                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(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:]
            params = {}
            for s in query.split('&'):
                if s != '':
                    i = s.index('=')
                    params[unquote(s[:i])] = unquote(s[i + 1:])
        except ValueError, e:
            return (400, 'Bad Request', {
                'Content-Type': 'text/plain'
            }, 'you sent me garbage - ' + str(e))
        if path == '' or path == 'index.html':
            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 names:
                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')
            else:
                s.write('<p>not tracking any files yet...</p>\n')
            s.write('</body>\n' \
                '</html>\n')
            return (200, 'OK', {
                'Content-Type': 'text/html; charset=iso-8859-1'
            }, s.getvalue())
        elif path == 'scrape':
            fs = {}
            names = []
            if params.has_key('info_hash'):
                if self.downloads.has_key(params['info_hash']):
                    names = [params['info_hash']]
                # else return nothing
            else:
                names = self.downloads.keys()
                names.sort()
            for name in names:
                l = self.downloads[name]
                n = self.completed.get(name, 0)
                c = len([
                    1 for i in l.values()
                    if type(i) == DictType and i['left'] == 0
                ])
                d = len(l) - c
                fs[name] = {'complete': c, 'incomplete': d, 'downloaded': n}
                if (self.allowed is not None
                    ) and self.allowed.has_key(name) and self.show_names:
                    fs[name]['name'] = self.allowed[name]['name']
            r = {'files': fs}
            return (200, 'OK', {'Content-Type': 'text/plain'}, bencode(r))
        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))
Ejemplo n.º 14
0
    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())