|
|
Últimos Cambios |
Blog personal: El hilo del laberinto
|
|
|
Última Actualización: 20 de febrero de 2008 - Miércoles
Hace unos días me bajé un torrent pero, al activarlo, el tracker me decía que no existía. Haciendo un "scrap" del tracker compruebo que hay "peers" a los que el torrent funciona sin problemas. Aparentemente se trata, pues, de un problema con BitTornado.
Tras investigar el asunto, llego a la conclusión de que BitTornado está codificando el "announce" al tracker de forma incorrecta. En particular, no está escapando el carácter "/".
BitTornado llama a la rutina "urllib.quote()", pero la emplea mal. La invoca sin darse cuenta de que, por defecto, "urllib.quote()" no escapa el carácter "/", como está claramente documentado en el manual.
El parche es largo pero trivial:
Index: BitTornado/BT1/StreamCheck.py
===================================================================
--- BitTornado/BT1/StreamCheck.py (revision 5)
+++ BitTornado/BT1/StreamCheck.py (working copy)
@@ -40,7 +40,7 @@
def make_readable(s):
if not s:
return ''
- if quote(s).find('%') >= 0:
+ if quote(s,safe="").find('%') >= 0:
return tohex(s)
return '"'+s+'"'
Index: BitTornado/BT1/HTTPDownloader.py
===================================================================
--- BitTornado/BT1/HTTPDownloader.py (revision 5)
+++ BitTornado/BT1/HTTPDownloader.py (working copy)
@@ -48,7 +48,7 @@
self.seedurl += '?'
if query:
self.seedurl += query+'&'
- self.seedurl += 'info_hash='+quote(self.downloader.infohash)
+ self.seedurl += 'info_hash='+quote(self.downloader.infohash,safe="")
self.measure = Measure(downloader.max_rate_period)
self.index = None
Index: BitTornado/BT1/track.py
===================================================================
--- BitTornado/BT1/track.py (revision 5)
+++ BitTornado/BT1/track.py (working copy)
@@ -451,7 +451,7 @@
szt = sz * n # Transferred for this torrent
tt = tt + szt
if self.allow_get == 1:
- linkname = '<a href="/file?info_hash=' + quote(hash) + '">' + name + '</a>'
+ linkname = '<a href="/file?info_hash=' + quote(hash,safe="") + '">' + name + '</a>'
else:
linkname = 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' \
@@ -906,7 +906,7 @@
def natchecklog(self, peerid, ip, port, result):
year, month, day, hour, minute, second, a, b, c = localtime(time())
print '%s - %s [%02d/%3s/%04d:%02d:%02d:%02d] "!natcheck-%s:%i" %i 0 - -' % (
- ip, quote(peerid), day, months[month], year, hour, minute, second,
+ ip, quote(peerid,safe=""), day, months[month], year, hour, minute, second,
ip, port, result)
def connectback_result(self, result, downloadid, peerid, ip, port):
Index: BitTornado/BT1/Rerequester.py
===================================================================
--- BitTornado/BT1/Rerequester.py (revision 5)
+++ BitTornado/BT1/Rerequester.py (working copy)
@@ -70,7 +70,7 @@
self.rejectedmessage = 'rejected by tracker - '
self.url = ('?info_hash=%s&peer_id=%s&port=%s' %
- (quote(infohash), quote(myid), str(port)))
+ (quote(infohash,safe=""), quote(myid,safe=""), str(port)))
self.ip = ip
self.interval = interval
self.last = None
@@ -92,7 +92,7 @@
self.downratefunc = downratefunc
self.unpauseflag = unpauseflag
if seed_id:
- self.url += '&seed_id='+quote(seed_id)
+ self.url += '&seed_id='+quote(seed_id,safe="")
self.seededfunc = seededfunc
if seededfunc:
self.url += '&check_seeded=1'
@@ -160,9 +160,9 @@
(self.url, str(self.up()), str(self.down()),
str(self.amount_left())))
if self.last is not None:
- s += '&last=' + quote(str(self.last))
+ s += '&last=' + quote(str(self.last,safe=""))
if self.trackerid is not None:
- s += '&trackerid=' + quote(str(self.trackerid))
+ s += '&trackerid=' + quote(str(self.trackerid),safe="")
if self.howmany() >= self.maxpeers:
s += '&numwant=0'
else:
Index: BitTornado/BT1/T2T.py
===================================================================
--- BitTornado/BT1/T2T.py (revision 5)
+++ BitTornado/BT1/T2T.py (working copy)
@@ -62,7 +62,7 @@
self.lastsuccessful = True
self.newpeerdata = []
if DEBUG:
- print 'contacting %s for info_hash=%s' % (self.tracker, quote(self.hash))
+ print 'contacting %s for info_hash=%s' % (self.tracker, quote(self.hash,safe=""))
self.rerequester.snoop(self.peers, self.callback)
def callback(self):
@@ -76,7 +76,7 @@
self.operatinginterval = self.rerequester.announce_interval
if DEBUG:
print ("%s with info_hash=%s returned %d peers" %
- (self.tracker, quote(self.hash), len(self.newpeerdata)))
+ (self.tracker, quote(self.hash,safe=""), len(self.newpeerdata)))
self.peerlists.append(self.newpeerdata)
self.peerlists = self.peerlists[-10:] # keep up to the last 10 announces
if self.isactive():
@@ -89,7 +89,7 @@
def errorfunc(self, r):
self.lastsuccessful = False
if DEBUG:
- print "%s with info_hash=%s gives error: '%s'" % (self.tracker, quote(self.hash), r)
+ print "%s with info_hash=%s gives error: '%s'" % (self.tracker, quote(self.hash,safe=""), r)
if r == self.rerequester.rejectedmessage + 'disallowed': # whoops!
if DEBUG:
print ' -- disallowed - deactivating'
Index: BitTornado/BT1/Encrypter.py
===================================================================
--- BitTornado/BT1/Encrypter.py (revision 5)
+++ BitTornado/BT1/Encrypter.py (working copy)
@@ -38,7 +38,7 @@
def make_readable(s):
if not s:
return ''
- if quote(s).find('%') >= 0:
+ if quote(s,safe="").find('%') >= 0:
return tohex(s)
return '"'+s+'"'
El parche se limita a cambiar las llamadas a "urllib.quote()" para que se escape también el carácter "/". Se podría haber hecho más simple utilizando la técnica que ya expliqué hace unos meses, pero -en este caso concreto- prefiero hacerlo explícito.
Mi agradecimiento a Adriá por ayudarme a diagnosticar el problema.
Más información sobre los OpenBadges
Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS
