[GTK] Fix unable to prefetch magnet in thinclient

A UnicodeDecodeError is raised in transfer module when attempting to
prefetch a magnet.

This is result of passing a Python dict containing text bytes and raw
bytes that cannot be decoded as utf-8 in rencode when recieving the
message. This could be handled in rencode by returning raw bytes if
decoding fails (perhaps with a strict mode?) however better to follow
convention of encoding raw bytes in base64 in API calls.

Fixed by retaining bencoding and encoding with base64 when sending
result.

Resolves: https://github.com/deluge-torrent/deluge/pull/334
This commit is contained in:
Calum Lind 2022-01-08 18:54:15 +00:00
parent 79b7e6093f
commit e50927f575
No known key found for this signature in database
GPG Key ID: 90597A687B836BA3
5 changed files with 45 additions and 35 deletions

View File

@ -432,12 +432,14 @@ class Core(component.Component):
Used by UIs to get magnet files for selection before adding to session.
The metadata is bencoded and for transfer base64 encoded.
Args:
magnet (str): The magnet URI.
timeout (int): Number of seconds to wait before canceling request.
Returns:
Deferred: A tuple of (torrent_id (str), metadata (dict)) for the magnet.
Deferred: A tuple of (torrent_id (str), metadata (str)) for the magnet.
"""

View File

@ -13,6 +13,7 @@ import operator
import os
import pickle
import time
from base64 import b64encode
from collections import namedtuple
from tempfile import gettempdir
@ -396,12 +397,12 @@ class TorrentManager(component.Component):
else:
self.session.remove_torrent(torrent_handle, 1)
metadata = None
metadata = b''
if isinstance(torrent_info, lt.torrent_info):
log.debug('prefetch metadata received')
metadata = lt.bdecode(torrent_info.metadata())
metadata = torrent_info.metadata()
return torrent_id, metadata
return torrent_id, b64encode(metadata)
def _build_torrent_options(self, options):
"""Load default options and update if needed."""

View File

@ -317,7 +317,7 @@ class CoreTestCase(BaseTestCase):
def test_prefetch_metadata_existing(self):
"""Check another call with same magnet returns existing deferred."""
magnet = 'magnet:?xt=urn:btih:ab570cdd5a17ea1b61e970bb72047de141bce173'
expected = ('ab570cdd5a17ea1b61e970bb72047de141bce173', None)
expected = ('ab570cdd5a17ea1b61e970bb72047de141bce173', b'')
def on_result(result):
self.assertEqual(result, expected)

View File

@ -15,6 +15,7 @@ from twisted.internet import defer, task
from twisted.trial import unittest
from deluge import component
from deluge.bencode import bencode
from deluge.common import windows_check
from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer
@ -82,34 +83,38 @@ class TorrentmanagerTestCase(BaseTestCase):
expected = (
'ab570cdd5a17ea1b61e970bb72047de141bce173',
{
b'piece length': 32768,
b'sha1': (
b'2\xce\xb6\xa8"\xd7\xf0\xd4\xbf\xdc^K\xba\x1bh'
b'\x9d\xc5\xb7\xac\xdd'
),
b'name': b'azcvsupdater_2.6.2.jar',
b'private': 0,
b'pieces': (
b"\xdb\x04B\x05\xc3'\xdab\xb8su97\xa9u"
b'\xca<w\\\x1ef\xd4\x9b\x16\xa9}\xc0\x9f:\xfd'
b'\x97qv\x83\xa2"\xef\x9d7\x0by!\rl\xe5v\xb7'
b'\x18{\xf7/"P\xe9\x8d\x01D\x9e8\xbd\x16\xe3'
b'\xfb-\x9d\xaa\xbcM\x11\xba\x92\xfc\x13F\xf0'
b'\x1c\x86x+\xc8\xd0S\xa9\x90`\xa1\xe4\x82\xe8'
b'\xfc\x08\xf7\xe3\xe5\xf6\x85\x1c%\xe7%\n\xed'
b'\xc0\x1f\xa1;\x9a\xea\xcf\x90\x0c/F>\xdf\xdagA'
b'\xc42|\xda\x82\xf5\xa6b\xa1\xb8#\x80wI\xd8f'
b'\xf8\xbd\xacW\xab\xc3s\xe0\xbbw\xf2K\xbe\xee'
b'\xa8rG\xe1W\xe8\xb7\xc2i\xf3\xd8\xaf\x9d\xdc'
b'\xd0#\xf4\xc1\x12u\xcd\x0bE?:\xe8\x9c\x1cu'
b'\xabb(oj\r^\xd5\xd5A\x83\x88\x9a\xa1J\x1c?'
b'\xa1\xd6\x8c\x83\x9e&'
),
b'length': 307949,
b'name.utf-8': b'azcvsupdater_2.6.2.jar',
b'ed2k': b'>p\xefl\xfa]\x95K\x1b^\xc2\\;;e\xb7',
},
b64encode(
bencode(
{
b'piece length': 32768,
b'sha1': (
b'2\xce\xb6\xa8"\xd7\xf0\xd4\xbf\xdc^K\xba\x1bh'
b'\x9d\xc5\xb7\xac\xdd'
),
b'name': b'azcvsupdater_2.6.2.jar',
b'private': 0,
b'pieces': (
b"\xdb\x04B\x05\xc3'\xdab\xb8su97\xa9u"
b'\xca<w\\\x1ef\xd4\x9b\x16\xa9}\xc0\x9f:\xfd'
b'\x97qv\x83\xa2"\xef\x9d7\x0by!\rl\xe5v\xb7'
b'\x18{\xf7/"P\xe9\x8d\x01D\x9e8\xbd\x16\xe3'
b'\xfb-\x9d\xaa\xbcM\x11\xba\x92\xfc\x13F\xf0'
b'\x1c\x86x+\xc8\xd0S\xa9\x90`\xa1\xe4\x82\xe8'
b'\xfc\x08\xf7\xe3\xe5\xf6\x85\x1c%\xe7%\n\xed'
b'\xc0\x1f\xa1;\x9a\xea\xcf\x90\x0c/F>\xdf\xdagA'
b'\xc42|\xda\x82\xf5\xa6b\xa1\xb8#\x80wI\xd8f'
b'\xf8\xbd\xacW\xab\xc3s\xe0\xbbw\xf2K\xbe\xee'
b'\xa8rG\xe1W\xe8\xb7\xc2i\xf3\xd8\xaf\x9d\xdc'
b'\xd0#\xf4\xc1\x12u\xcd\x0bE?:\xe8\x9c\x1cu'
b'\xabb(oj\r^\xd5\xd5A\x83\x88\x9a\xa1J\x1c?'
b'\xa1\xd6\x8c\x83\x9e&'
),
b'length': 307949,
b'name.utf-8': b'azcvsupdater_2.6.2.jar',
b'ed2k': b'>p\xefl\xfa]\x95K\x1b^\xc2\\;;e\xb7',
}
)
),
)
self.assertEqual(expected, self.successResultOf(d))
@ -117,7 +122,7 @@ class TorrentmanagerTestCase(BaseTestCase):
magnet = 'magnet:?xt=urn:btih:ab570cdd5a17ea1b61e970bb72047de141bce173'
d = self.tm.prefetch_metadata(magnet, 30)
self.clock.advance(30)
expected = ('ab570cdd5a17ea1b61e970bb72047de141bce173', None)
expected = ('ab570cdd5a17ea1b61e970bb72047de141bce173', b'')
return d.addCallback(self.assertEqual, expected)
@pytest.mark.todo

View File

@ -8,7 +8,7 @@
import logging
import os
from base64 import b64encode
from base64 import b64decode, b64encode
from xml.sax.saxutils import escape as xml_escape
from xml.sax.saxutils import unescape as xml_unescape
@ -16,6 +16,7 @@ from gi.repository import Gtk
from gi.repository.GObject import TYPE_INT64, TYPE_UINT64
import deluge.component as component
from deluge.bencode import bdecode
from deluge.common import (
create_magnet_uri,
decode_bytes,
@ -268,6 +269,7 @@ class AddTorrentDialog(component.Component):
return
if metadata:
metadata = bdecode(b64decode(metadata))
info = TorrentInfo.from_metadata(metadata, [[t] for t in trackers])
self.files[info_hash] = info.files
self.infos[info_hash] = info.filedata