[Py3] Fix TorrentInfo info_dict decoding

This commit is contained in:
Calum Lind 2018-10-08 21:34:59 +01:00
parent 41732fe38b
commit 673b6653a3
1 changed files with 39 additions and 32 deletions

View File

@ -15,6 +15,7 @@ from __future__ import unicode_literals
import logging import logging
import os import os
from binascii import hexlify
from hashlib import sha1 as sha from hashlib import sha1 as sha
from deluge import bencode from deluge import bencode
@ -201,52 +202,57 @@ class TorrentInfo(object):
log.warning('Failed to decode %s: %s', filename, ex) log.warning('Failed to decode %s: %s', filename, ex)
return return
info_dict = self._metainfo_dict[b'info'] # info_dict with keys decoded.
info_dict = {k.decode(): v for k, v in self._metainfo_dict[b'info'].items()}
self._info_hash = sha(bencode.bencode(info_dict)).hexdigest() self._info_hash = sha(bencode.bencode(info_dict)).hexdigest()
# Get encoding from torrent file if available # Get encoding from torrent file if available
encoding = self._metainfo_dict.get(b'encoding', None) encoding = info_dict.get('encoding', None)
codepage = self._metainfo_dict.get(b'codepage', None) codepage = info_dict.get('codepage', None)
if not encoding: if not encoding:
encoding = codepage if codepage else b'UTF-8' encoding = codepage if codepage else b'UTF-8'
# Decode 'name' with encoding unless 'name.utf-8' found.
if b'name.utf-8' in info_dict:
self._name = decode_bytes(info_dict[b'name.utf-8'])
else:
if encoding: if encoding:
encoding = encoding.decode() encoding = encoding.decode()
self._name = decode_bytes(info_dict[b'name'], encoding)
# Decode 'name' with encoding unless 'name.utf-8' found.
if 'name.utf-8' in info_dict:
self._name = decode_bytes(info_dict['name.utf-8'])
else:
self._name = decode_bytes(info_dict['name'], encoding)
# Get list of files from torrent info # Get list of files from torrent info
if b'files' in info_dict: if 'files' in info_dict:
paths = {} paths = {}
dirs = {} dirs = {}
prefix = self._name if len(info_dict[b'files']) > 1 else '' prefix = self._name if len(info_dict['files']) > 1 else ''
for index, f in enumerate(info_dict[b'files']): for index, f in enumerate(info_dict['files']):
if b'path.utf-8' in f: f = {k.decode(): v for k, v in f.items()}
path = decode_bytes(os.path.join(*f[b'path.utf-8']))
del f[b'path.utf-8'] if 'path.utf-8' in f:
path = decode_bytes(os.path.join(*f['path.utf-8']))
del f['path.utf-8']
else: else:
path = decode_bytes(os.path.join(*f[b'path']), encoding) path = decode_bytes(os.path.join(*f['path']), encoding)
if prefix: if prefix:
path = os.path.join(prefix, path) path = os.path.join(prefix, path)
f[b'path'] = path f['path'] = path
f[b'index'] = index f['index'] = index
if b'sha1' in f and len(f[b'sha1']) == 20:
f[b'sha1'] = f[b'sha1'].encode(b'hex') if 'sha1' in f and len(f['sha1']) == 20:
if b'ed2k' in f and len(f[b'ed2k']) == 16: f['sha1'] = hexlify(f['sha1']).decode()
f[b'ed2k'] = f['ed2k'].encode(b'hex') if 'ed2k' in f and len(f['ed2k']) == 16:
if b'filehash' in f and len(f[b'filehash']) == 20: f['ed2k'] = hexlify(f['ed2k']).decode()
f[b'filehash'] = f[b'filehash'].encode(b'hex') if 'filehash' in f and len(f['filehash']) == 20:
f['filehash'] = hexlify(f['filehash']).decode()
paths[path] = f paths[path] = f
dirname = os.path.dirname(path) dirname = os.path.dirname(path)
while dirname: while dirname:
dirinfo = dirs.setdefault(dirname, {}) dirinfo = dirs.setdefault(dirname, {})
dirinfo[b'length'] = dirinfo.get(b'length', 0) + f[b'length'] dirinfo['length'] = dirinfo.get('length', 0) + f['length']
dirname = os.path.dirname(dirname) dirname = os.path.dirname(dirname)
if filetree == 2: if filetree == 2:
@ -265,7 +271,7 @@ class TorrentInfo(object):
def walk(path, item): def walk(path, item):
if isinstance(item, dict): if isinstance(item, dict):
return item return item
return [paths[path][b'index'], paths[path][b'length'], True] return [paths[path]['index'], paths[path]['length'], True]
file_tree = FileTree(paths) file_tree = FileTree(paths)
file_tree.walk(walk) file_tree.walk(walk)
@ -277,27 +283,28 @@ class TorrentInfo(object):
self._name: { self._name: {
'type': 'file', 'type': 'file',
'index': 0, 'index': 0,
'length': info_dict[b'length'], 'length': info_dict['length'],
'download': True, 'download': True,
} }
} }
} }
else: else:
self._files_tree = {self._name: (0, info_dict[b'length'], True)} self._files_tree = {self._name: (0, info_dict['length'], True)}
self._files = [] self._files = []
if b'files' in info_dict: if 'files' in info_dict:
prefix = '' prefix = ''
if len(info_dict[b'files']) > 1: if len(info_dict['files']) > 1:
prefix = self._name prefix = self._name
for f in info_dict[b'files']: for f in info_dict['files']:
path_list = [k.decode(encoding) for k in f[b'path']]
self._files.append( self._files.append(
{'path': f[b'path'], 'size': f[b'length'], 'download': True} {'path': path_list, 'size': f[b'length'], 'download': True}
) )
else: else:
self._files.append( self._files.append(
{'path': self._name, 'size': info_dict[b'length'], 'download': True} {'path': self._name, 'size': info_dict['length'], 'download': True}
) )
def as_dict(self, *keys): def as_dict(self, *keys):