diff --git a/deluge/common.py b/deluge/common.py index 19879aa64..7aea9b6af 100644 --- a/deluge/common.py +++ b/deluge/common.py @@ -839,6 +839,29 @@ def utf8_encoded(s, encoding='utf8'): return s +def convert_to_utf8(data): + """Recursively convert all unicode keys and values in a data structure to utf8. + + e.g. converting keys and values for a dict with nested dicts and lists etc. + + Args: + data (any): This can be any structure, dict, list or tuple. + + Returns: + input type: The data with unicode keys and values converted to utf8. + + """ + + if isinstance(data, unicode): + return data.encode('utf8') + elif isinstance(data, (list, tuple)): + return type(data)(map(convert_to_utf8, data)) + elif isinstance(data, dict): + return dict(map(convert_to_utf8, data.items())) + else: + return data + + @functools.total_ordering class VersionSplit(object): """ diff --git a/deluge/httpdownloader.py b/deluge/httpdownloader.py index 7d094c837..b3f1ce1a3 100644 --- a/deluge/httpdownloader.py +++ b/deluge/httpdownloader.py @@ -19,7 +19,7 @@ from twisted.python.failure import Failure from twisted.web import client, http from twisted.web.error import PageRedirect -from deluge.common import get_version +from deluge.common import convert_to_utf8, get_version log = logging.getLogger(__name__) @@ -175,8 +175,8 @@ def _download_file(url, filename, callback=None, headers=None, force_filename=Fa url = url.encode('utf8') filename = filename.encode('utf8') - if headers: - headers = {k.encode('utf8'): v.encode('utf8') for k, v in headers.items()} + headers = convert_to_utf8(headers) if headers else headers + factory = HTTPDownloader(url, filename, callback, headers, force_filename, allow_compression) # In Twisted 13.1.0 _parse() function replaced by _URI class. # In Twisted 15.0.0 _URI class renamed to URI. @@ -187,13 +187,12 @@ def _download_file(url, filename, callback=None, headers=None, force_filename=Fa from twisted.web.client import _URI as URI except ImportError: from twisted.web.client import URI + finally: + uri = URI.fromBytes(url) + scheme = uri.scheme + host = uri.host + port = uri.port - uri = URI.fromBytes(url) - scheme = uri.scheme - host = uri.host - port = uri.port - - factory = HTTPDownloader(url, filename, callback, headers, force_filename, allow_compression) if scheme == 'https': from twisted.internet import ssl # ClientTLSOptions in Twisted >= 14, see ticket #2765 for details on this addition. diff --git a/deluge/maketorrent.py b/deluge/maketorrent.py index 215f6784d..2dcd6e905 100644 --- a/deluge/maketorrent.py +++ b/deluge/maketorrent.py @@ -14,7 +14,7 @@ import sys from hashlib import sha1 as sha from deluge.bencode import bencode -from deluge.common import get_path_size +from deluge.common import convert_to_utf8, get_path_size class InvalidPath(Exception): @@ -72,7 +72,7 @@ class TorrentMetadata(object): } if self.comment: - torrent['comment'] = self.comment.encode('UTF-8') + torrent['comment'] = self.comment if self.private: torrent['info']['private'] = True @@ -113,10 +113,10 @@ class TorrentMetadata(object): num_pieces += 1 torrent['info']['piece length'] = piece_size + torrent['info']['name'] = os.path.split(self.data_path)[1] # Create the info if os.path.isdir(self.data_path): - torrent['info']['name'] = os.path.split(self.data_path)[1] files = [] padding_count = 0 # Collect a list of file paths and add padding files if necessary @@ -170,18 +170,14 @@ class TorrentMetadata(object): else: break r = _file.read(piece_size - len(buf)) - + torrent['info']['files'] = fs if buf: pieces.append(sha(buf).digest()) if progress: progress(len(pieces), num_pieces) buf = '' - torrent['info']['pieces'] = ''.join(pieces) - torrent['info']['files'] = fs - elif os.path.isfile(self.data_path): - torrent['info']['name'] = os.path.split(self.data_path)[1] torrent['info']['length'] = get_path_size(self.data_path) pieces = [] @@ -194,11 +190,11 @@ class TorrentMetadata(object): r = _file.read(piece_size) - torrent['info']['pieces'] = ''.join(pieces) + torrent['info']['pieces'] = b''.join(pieces) # Write out the torrent file with open(torrent_path, 'wb') as _file: - _file.write(bencode(torrent)) + _file.write(bencode(convert_to_utf8(torrent))) def get_data_path(self): """Get the path to the files that the torrent will contain.