Giter Site home page Giter Site logo

torrent_parser's Introduction

Torrent file parser and creator for Python

A simple parser for .torrent file.

Can also edit and write back to torrent format after version 0.2.0.

Features

  • Decoder and encoder for torrent files
  • Auto decode bytes field to string with used specified encoding and error handler
  • Auto detect encoding when use auto as encoding(need chardet installed)
  • Auto decode hash value filed to hash blocks, also customizable
  • CLI provided, with JSON output

Install

pip install torrent_parser

Usage

CLI

pytp test.torrent
cat test.torrent | pytp

As a module

>>> import torrent_parser as tp
>>> data = tp.parse_torrent_file('test.torrent')
>>> data['announce']
http://tracker.trackerfix.com:80/announce
>>> data['announce'] = 'http://127.0.0.1:12345'
>>> tp.create_torrent_file('new.torrent', data)

or you don't operate with file, just raw bytes:

>>> import torrent_parser as tp
>>> data = tp.decode(b'd3:negi-1ee')
>>> data['neg']
-1
>>> tp.encode(data)
b'd3:negi-1ee'

Test

python -m unittest tests

Changelog

See Changelog.

LICENSE

See License.

torrent_parser's People

Contributors

7sdream avatar junwoo091400 avatar yasuotakei avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

torrent_parser's Issues

Changing trackers in announce-list corrupts save

Hi,

First thanks for taking the time to write this.

#

I’m trying to strip out existing (dead) trackers from torrent files and replace them with known good ones. But, changing trackers in the announce-list results in a corrupted (non-working) announce-list. [You can change the "announce" tracker successfully.]

For testing I’ve been using the MX-19.2_x64.iso torrent file. It seems to be no longer available, but similar files are at https://mxlinux.org/torrent-files/ .

Output testing is by loading into qBittorrent v4.2.3 and checking the “Trackers” tab. All tests fail by not loading the changed "announce-list" tracker to the Tracker List in qBittorrent.

See toradd.py code at bottom. I’ve used “pytp” to visualize the outputed torrent files.

Request:

Have the code,

tracker_03a        = 'http://tracker.opentrackr.org:1337/announce'
data['announce-list'][0] = tracker_03a

correctly replace the tracker so that it loads successfully into qBittorrent.

Control pass:

Changes:
Straight read, no changes, and a write to separate file.

Results:
All trackers show up in qBittorrent

michael@local [~/trash]# toradd.py arg1 arg2
michael@local [~/trash]# ./pytp '/home/michael/data/Downloads/isos/torrentfiles/MX-19.2_x64.iso.torrent' -d -i 2 > /home/michael/trash/torout.txt
michael@local [~/trash]# head torout.txt
{
  "announce": "http://l2.mxrepo.com:6969/announce",
  "announce-list": [
    [
      "http://l2.mxrepo.com:6969/announce"
    ],
    [
      "http://it.mxrepo.com:6969/announce"
    ]
  ],

Test 01-a:

Changes:

data['announce-list'][0] = tracker_03a
#data['announce-list'][1] = tracker_01

Results:
Loads only tracker http://it.mxrepo.com:6969/announce

Output

michael@local [~/trash]# toradd.py arg1 arg2
michael@local [~/trash]# ./pytp '/home/michael/trash/test.torrent' -d -i 2 > /home/michael/trash/torout2.txt
michael@local [~/trash]# head torout2.txt
{
  "announce": "http://tracker.opentrackr.org:1337/announce",
  "announce-list": [
    "http://tracker.opentrackr.org:1337/announce",
    [
      "http://it.mxrepo.com:6969/announce"
    ]
  ],
  "created by": "mktorrent 1.0",
  "creation date": 1591050075,

Test 01-b:

Changes:

data['announce-list'][0] = tracker_03a
data['announce-list'][1] = tracker_01

Results:
Loads only tracker http://tracker.opentrackr.org:1337/announce

Output

michael@local [~/trash]# toradd.py arg1 arg2
michael@local [~/trash]# ./pytp '/home/michael/trash/test.torrent' -d -i 2 > /home/michael/trash/torout2.txt
michael@local [~/trash]# head torout2.txt
{
  "announce": "http://tracker.opentrackr.org:1337/announce",
  "announce-list": [
    "http://tracker.opentrackr.org:1337/announce",
    "http://tracker.dler.org:6969/announce"
  ],
  "created by": "mktorrent 1.0",
  "creation date": 1591050075,
  "info": {
    "length": 1609564160,

Test 02:

Changes:

data['announce-list'][0] = tracker_03b
data['announce-list'][1] = tracker_01

Results:
Loads only tracker http://tracker.opentrackr.org:1337/announce

Output

michael@local [~/trash]# toradd.py arg1 arg2
michael@local [~/trash]# ./pytp '/home/michael/trash/test.torrent' -d -i 2 > /home/michael/trash/torout2.txt
michael@local [~/trash]# head torout2.txt
{
  "announce": "http://tracker.opentrackr.org:1337/announce",
  "announce-list": [
    "[\"http://tracker.opentrackr.org:1337/announce\"]",
    "http://tracker.dler.org:6969/announce"
  ],
  "created by": "mktorrent 1.0",
  "creation date": 1591050075,
  "info": {
    "length": 1609564160,

Test 03:

Changes:

data['announce-list'][0] = tracker_03c
data['announce-list'][1] = tracker_01

Results:
Loads only tracker http://tracker.opentrackr.org:1337/announce

Output

michael@local [~/trash]# toradd.py arg1 arg2
michael@local [~/trash]# ./pytp '/home/michael/trash/test.torrent' -d -i 2 > /home/michael/trash/torout2.txt
michael@local [~/trash]# head torout2.txt
{
  "announce": "http://tracker.opentrackr.org:1337/announce",
  "announce-list": [
    "[http://tracker.opentrackr.org:1337/announce]",
    "http://tracker.dler.org:6969/announce"
  ],
  "created by": "mktorrent 1.0",
  "creation date": 1591050075,
  "info": {
    "length": 1609564160,

Test 04:

Changes:

data['announce-list'][0] = tracker_03d
data['announce-list'][1] = tracker_01

Results:
Loads only tracker http://tracker.opentrackr.org:1337/announce

Output

michael@local [~/trash]# toradd.py arg1 arg2
michael@local [~/trash]# ./pytp '/home/michael/trash/test.torrent' -d -i 2 > /home/michael/trash/torout2.txt
michael@local [~/trash]# head torout2.txt
{
  "announce": "http://tracker.opentrackr.org:1337/announce",
  "announce-list": [
    "['http://tracker.opentrackr.org:1337/announce']",
    "http://tracker.dler.org:6969/announce"
  ],
  "created by": "mktorrent 1.0",
  "creation date": 1591050075,
  "info": {
    "length": 1609564160,

Program used

I was in the middle of passing trackers into the program, so ignore the other testing junk...

michael@local [~/common/bin]# cat toradd.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import torrent_parser as tp

if  len(sys.argv) > 2:  # Need 2 arguments
  print(True)
else:
  print(False)
  sys.exit(43)

print ('Number of arguments:', len(sys.argv), 'arguments.')
print ('Argument List:', str(sys.argv))

tor_file_in       = '/home/michael/data/Downloads/isos/torrentfiles/MX-19.2_x64.iso.torrent'
tor_file_out      = '/home/michael/trash/test.torrent'
tracker_00        = "http://tracker.opentrackr.org:1337/announce"
tracker_01        = "http://tracker.dler.org:6969/announce"
tracker_02        = ''
tracker_03a        = 'http://tracker.opentrackr.org:1337/announce'
tracker_03b        = '["http://tracker.opentrackr.org:1337/announce"]'
tracker_03c        = '[http://tracker.opentrackr.org:1337/announce]'
tracker_03d        = "['http://tracker.opentrackr.org:1337/announce']"

data = tp.parse_torrent_file(tor_file_in)
print(data['announce'])
print(data['info']['name'])
print(data['announce-list'][0])
print(data['announce-list'][1])

data['announce'] = tracker_00
data['announce-list'][0] = tracker_03c
data['announce-list'][1] = tracker_01

print(data['announce'])
tp.create_torrent_file(tor_file_out, data)

sys.exit(0)

General output of toradd.py

It’s repetitive so I stripped it out of the above to reduce clutter...

michael@local [~/trash]# toradd.py arg1 arg2
True
Number of arguments: 3 arguments.
Argument List: ['/home/michael/common/bin/toradd.py', 'arg1', 'arg2']
http://l2.mxrepo.com:6969/announce
MX-19.2_x64.iso
['http://l2.mxrepo.com:6969/announce']
['http://it.mxrepo.com:6969/announce']
http://tracker.opentrackr.org:1337/announce

Edit:
Header bits for the input and output .torrent files

MX-19.2_x64.iso.torrent

d8:announce34:http://l2.mxrepo.com:6969/announce13:announce-listll34:http://l2.mxrepo.com:6969/announceel34:http://it.mxrepo.com:6969/announceee10:created by13:mktorrent 1.013:creation

test.torrent

d8:announce43:http://tracker.opentrackr.org:1337/announce13:announce-listl47:['http://tracker.opentrackr.org:1337/announce']37:http://tracker.dler.org:6969/announcee10:created by13:mktorrent 1.013:creation 

v2 Torrent supported?

hello,
use v2 torrent,
Getting "Fail to decode string at pos 145 using encoding utf-8 when parser field "pieces root", maybe it is an hash field. You can use self.hash_field("pieces root") to let it be treated as hash value, so this error may disappear" at torrent file parse.

Example torrent file:
https://libtorrent.org/bittorrent-v2-test.torrent

Web siders are sorted by length, but not by name.

Hi.

Web siders are sorted by length, but not by name, which makes the list of files turn into a dump of strings. Transmission-show sorts files by name, but its output is very hard to parse

Example

Through.The.Wormhole.1х06.avi
Through.The.Wormhole.1х08.avi
Through.The.Wormhole.1х04.avi
Through.The.Wormhole.1х01.avi
Through.The.Wormhole.1х05.avi
Through.The.Wormhole.1х02.avi
Through.The.Wormhole.1х03.avi
Through.The.Wormhole.1х07.avi

In transmission-show or torrent_parser + sort utility

Through.The.Wormhole.1х01.avi
Through.The.Wormhole.1х02.avi
Through.The.Wormhole.1х03.avi
Through.The.Wormhole.1х04.avi
Through.The.Wormhole.1х05.avi
Through.The.Wormhole.1х06.avi
Through.The.Wormhole.1х07.avi
Through.The.Wormhole.1х08.avi

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x92 in position 43

I parsed many torrent files successfully and among >1000 only 1 caused the following error. Hope the stack trace is enough.

Traceback (most recent call last):
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 290, in _next_string
    string = raw.decode(encoding, self._error_handler)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x92 in position 43: invalid start byte

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\user\appdata\local\programs\python\python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\user\appdata\local\programs\python\python38\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\Scripts\pytp.exe\__main__.py", line 7, in <module>
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 632, in __main
    data = TorrentFileParser(
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 202, in parse
    data = self._next_element()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 350, in _next_element
    element = self._type_to_func(element_type)()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 254, in _next_dict
    for key, element in self._dict_items_generator():
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 247, in _dict_items_generator
    v = self._next_element(k)
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 350, in _next_element
    element = self._type_to_func(element_type)()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 254, in _next_dict
    for key, element in self._dict_items_generator():
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 247, in _dict_items_generator
    v = self._next_element(k)
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 350, in _next_element
    element = self._type_to_func(element_type)()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 266, in _next_list
    return [element for element in self._list_items_generator()]
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 266, in <listcomp>
    return [element for element in self._list_items_generator()]
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 260, in _list_items_generator
    element = self._next_element()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 350, in _next_element
    element = self._type_to_func(element_type)()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 254, in _next_dict
    for key, element in self._dict_items_generator():
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 247, in _dict_items_generator
    v = self._next_element(k)
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 350, in _next_element
    element = self._type_to_func(element_type)()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 266, in _next_list
    return [element for element in self._list_items_generator()]
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 266, in <listcomp>
    return [element for element in self._list_items_generator()]
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 260, in _list_items_generator
    element = self._next_element()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 350, in _next_element
    element = self._type_to_func(element_type)()
  File "c:\users\user\appdata\local\programs\python\python38\lib\site-packages\torrent_parser.py", line 304, in _next_string
    raise InvalidTorrentDataException(
torrent_parser.InvalidTorrentDataException: Fail to decode string at pos 22408 using encoding utf-8

hello,I find something wrong in you code..

version = '0.1.2'

When I using you project to parser a torrent file , I got some wrong,here is my found, mybe it can help you ~

  • _seek_back nerver rollback _pos
def _seek_back(self, count):
        self._content.seek(-count, 1)
        #my_code_here
        self._pos = self._pos - count
  • the encoding element in torrent files maybe wrong,using charset instead
    def _next_string(self, decode=True):
        length = self._next_int(b':')
        raw = self._read_byte(length)
        if decode:

            #my code here
            self._encoding = chardet.detect(raw)["encoding"]
            if raw == b'':
                string = self._next_string()
            else:
                string = raw.decode(self._encoding)
                
            return string
        return raw
  • _next_int maybe the negative number.

like this: file-mediali-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei-1ei0ei-1ei-1ee

    def _next_int(self, end=END_INDICATOR):
        
        #以END_INDICATOR为分隔符读出字符串个数
        negative = False
        value = 0
        char = self._read_byte(1)
        while char != end:
            #my_code
            if char == b'-':
                char = self._read_byte(1)
                negative = True 
                
            # noinspection PyTypeChecker
            if not b'0' <= char <= b'9':
                raise InvalidTorrentFileException(self._pos)
            value = value * 10 + int(char) - int(b'0')
            char = self._read_byte(1)
            
        #my_code
        if negative:
            value = -value
        
        return value

Missing dependency typing_extensions

When I tried to import the torrent parser module, I got the following error:

ModuleNotFoundError: No module named 'typing_extensions'

I fixed it by running pip install typing_extensions. You probably need to add it as a dependency.

UnicodeDecodeError

I have encountered the following error:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfd in position 1: invalid start byte thrown on line 236 of torrent_parser.py

Your tests might not have encountered this due to a small sample size, since I use your library to processes a thousands of torrents in an hour. Thats how I found it.

I have temporarily fixed this by adding the ignore flag on the byte string decode function like so.

string = raw.decode(encoding, "ignore")

It would be lovely if you could add this to the upstream directory.

A test file I used is attached:
auratorrent.torrent.zip

The PR request is #5

This is covered here: https://docs.python.org/3/howto/unicode.html

Same error with every torrent.

Hi I was just having a look at this and I downloaded a test torrent using 'BitTorrent Now' and I got an error so I tried it on different files and I got the same one. It looks like this

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 290, in _next_string
string = raw.decode(encoding, self._error_handler)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/bin/pytp", line 10, in
sys.exit(__main())
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 633, in __main
target_file, not args.dict, args.coding, args.errors
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 202, in parse
data = self._next_element()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 350, in _next_element
element = self._type_to_func(element_type)()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 254, in _next_dict
for key, element in self._dict_items_generator():
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 247, in _dict_items_generator
v = self._next_element(k)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 350, in _next_element
element = self._type_to_func(element_type)()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 254, in _next_dict
for key, element in self._dict_items_generator():
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 247, in _dict_items_generator
v = self._next_element(k)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 348, in _next_element
element = self._type_to_func(element_type)(field=field)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 306, in _next_string
''.join(msg)
torrent_parser.InvalidTorrentDataException: Fail to decode string at pos 1242 using encoding utf-8 when parser field "originator", maybe it is an hash field. You can use self.hash_field("originator") to let it be treated as hash value, so this error may disappear
USER-MacBook:torrent_parser-master USER$ sudo pytp 'FOOL'S GOLD DAY OFF FIRE.torrent'
-bash: unexpected EOF while looking for matching `''
-bash: syntax error: unexpected end of file
USER-MacBook:torrent_parser-master USER$ sudo pytp "FOOL'S GOLD DAY OFF FIRE.torrent"
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 290, in _next_string
string = raw.decode(encoding, self._error_handler)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/bin/pytp", line 10, in
sys.exit(__main())
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 633, in __main
target_file, not args.dict, args.coding, args.errors
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 202, in parse
data = self._next_element()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 350, in _next_element
element = self._type_to_func(element_type)()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 254, in _next_dict
for key, element in self._dict_items_generator():
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 247, in _dict_items_generator
v = self._next_element(k)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 350, in _next_element
element = self._type_to_func(element_type)()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 254, in _next_dict
for key, element in self._dict_items_generator():
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 247, in _dict_items_generator
v = self._next_element(k)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 348, in _next_element
element = self._type_to_func(element_type)(field=field)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torrent_parser.py", line 306, in _next_string
''.join(msg)
torrent_parser.InvalidTorrentDataException: Fail to decode string at pos 1242 using encoding utf-8 when parser field "originator", maybe it is an hash field. You can use self.hash_field("originator") to let it be treated as hash value, so this error may disappear

I don't know if this is a known error. I assume the last error is the only informative one. This appears when using cli and as a module. I am running on mac OS python3.

UnicodeDecodeError: 'utf8' codec can't decode byte 0xb5 in position 1: invalid start byte

使用pytp 解析文件的使用报编码错误,完整报错如下:
Traceback (most recent call last):
File "/usr/local/bin/pytp", line 11, in
sys.exit(__main())
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 252, in __main
data = TorrentFileParser(target_file, not args.dict).parse()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 87, in parse
data = self._next_element()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 202, in _next_element
element = self._type_to_func(element_type)()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 138, in _next_dict
for key, element in self._dict_items_generator():
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 131, in _dict_items_generator
v = self._next_element()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 202, in _next_element
element = self._type_to_func(element_type)()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 138, in _next_dict
for key, element in self._dict_items_generator():
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 131, in _dict_items_generator
v = self._next_element()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 202, in _next_element
element = self._type_to_func(element_type)()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 151, in _next_list
return [element for element in self._list_items_generator()]
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 145, in _list_items_generator
element = self._next_element()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 202, in _next_element
element = self._type_to_func(element_type)()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 138, in _next_dict
for key, element in self._dict_items_generator():
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 131, in _dict_items_generator
v = self._next_element()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 202, in _next_element
element = self._type_to_func(element_type)()
File "/usr/local/lib/python2.7/dist-packages/torrent_parser.py", line 168, in _next_string
string = raw.decode(self._encoding)
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)

在centos 7环境下,Python版本为2.7, 打断点调试发现,报错时raw = '\x0e\xb5\xc1\x91\xfb\x83m\xae\xfb8f\x05\x13\xb0\x8bo'

add functions to calculate v1 and v2 info hashes of torrent files

currently the v1 hash appears only in this test

def test_info_hash_is_right(self):
torrent = parse_torrent_file(self.REAL_FILE, hash_raw=True)
info_bytes = encode(torrent["info"])
info_hash = binascii.hexlify(hashlib.sha1(info_bytes).digest()).decode()
# print(f"info_hash: {info_hash}")
self.assertEqual(info_hash, "f435d2324f313bad7ff941633320fe4d1c9c3079")

expected:

torrent = torrent_parser.parse_torrent_file("input.torrent", hash_raw=True) 

info_hash_v1_raw = torrent_parser.get_info_hash_v1_raw(torrent) # -> bytes
info_hash_v1_hex = torrent_parser.get_info_hash_v1_hex(torrent) # -> string

info_hash_v2_raw = torrent_parser.get_info_hash_v2_raw(torrent) # -> bytes
info_hash_v2_hex = torrent_parser.get_info_hash_v2_hex(torrent) # -> string

get_info_hash_v2 simply uses hashlib.sha256 instead of hashlib.sha1

binascii.hexlify can be avoided by using hexdigest

info_hash_v1 = hashlib.sha1(info_bytes).hexdigest()
info_hash_v2 = hashlib.sha256(info_bytes).hexdigest()

related: https://stackoverflow.com/questions/46025771/python3-calculating-torrent-hash


stupid question: does parse_torrent_file preserve the sort order of the info dict?
since python3, dict should be an ordered dict by default

https://stackoverflow.com/questions/19749085/calculating-the-info-hash-of-a-torrent-file

Be observant that the example torrent file given by Arvid, both the root-dictionary and the info-dictionary is unsorted. According to the bencode specification a dictionary must be sorted. However the agreed convention when a info-dictionary for some reason is unsorted, is to hash the info-dictionary raw as it is (unsorted), as explained by Arvid above.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.