commit
2f7323043f
4 changed files with 183 additions and 5 deletions
|
@ -3,7 +3,7 @@ import urllib.request
|
|||
import struct
|
||||
import socket
|
||||
|
||||
import bencode
|
||||
import bencode_open
|
||||
from lib.subtl.subtl import UdpTrackerClient
|
||||
import socks
|
||||
import sockshandler
|
||||
|
@ -133,9 +133,7 @@ class SiteAnnouncerPlugin(object):
|
|||
|
||||
# Decode peers
|
||||
try:
|
||||
peer_data = bencode.decode(response)["peers"]
|
||||
if type(peer_data) is not bytes:
|
||||
peer_data = peer_data.encode()
|
||||
peer_data = bencode_open.loads(response)[b"peers"]
|
||||
response = None
|
||||
peer_count = int(len(peer_data) / 6)
|
||||
peers = []
|
||||
|
|
|
@ -7,6 +7,5 @@ PySocks>=1.6.8
|
|||
pyasn1
|
||||
websocket_client
|
||||
gevent-websocket
|
||||
bencode.py
|
||||
coincurve
|
||||
maxminddb
|
||||
|
|
21
src/lib/bencode_open/LICENSE
Normal file
21
src/lib/bencode_open/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Ivan Machugovskiy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
160
src/lib/bencode_open/__init__.py
Normal file
160
src/lib/bencode_open/__init__.py
Normal file
|
@ -0,0 +1,160 @@
|
|||
def loads(data):
|
||||
if not isinstance(data, bytes):
|
||||
raise TypeError("Expected 'bytes' object, got {}".format(type(data)))
|
||||
|
||||
offset = 0
|
||||
|
||||
|
||||
def parseInteger():
|
||||
nonlocal offset
|
||||
|
||||
offset += 1
|
||||
had_digit = False
|
||||
abs_value = 0
|
||||
|
||||
sign = 1
|
||||
if data[offset] == ord("-"):
|
||||
sign = -1
|
||||
offset += 1
|
||||
while offset < len(data):
|
||||
if data[offset] == ord("e"):
|
||||
# End of string
|
||||
offset += 1
|
||||
if not had_digit:
|
||||
raise ValueError("Integer without value")
|
||||
break
|
||||
if ord("0") <= data[offset] <= ord("9"):
|
||||
abs_value = abs_value * 10 + int(chr(data[offset]))
|
||||
had_digit = True
|
||||
offset += 1
|
||||
else:
|
||||
raise ValueError("Invalid integer")
|
||||
else:
|
||||
raise ValueError("Unexpected EOF, expected integer")
|
||||
|
||||
if not had_digit:
|
||||
raise ValueError("Empty integer")
|
||||
|
||||
return sign * abs_value
|
||||
|
||||
|
||||
def parseString():
|
||||
nonlocal offset
|
||||
|
||||
length = int(chr(data[offset]))
|
||||
offset += 1
|
||||
|
||||
while offset < len(data):
|
||||
if data[offset] == ord(":"):
|
||||
offset += 1
|
||||
break
|
||||
if ord("0") <= data[offset] <= ord("9"):
|
||||
length = length * 10 + int(chr(data[offset]))
|
||||
offset += 1
|
||||
else:
|
||||
raise ValueError("Invalid string length")
|
||||
else:
|
||||
raise ValueError("Unexpected EOF, expected string contents")
|
||||
|
||||
if offset + length > len(data):
|
||||
raise ValueError("Unexpected EOF, expected string contents")
|
||||
offset += length
|
||||
|
||||
return data[offset - length:offset]
|
||||
|
||||
|
||||
def parseList():
|
||||
nonlocal offset
|
||||
|
||||
offset += 1
|
||||
values = []
|
||||
|
||||
while offset < len(data):
|
||||
if data[offset] == ord("e"):
|
||||
# End of list
|
||||
offset += 1
|
||||
return values
|
||||
else:
|
||||
values.append(parse())
|
||||
|
||||
raise ValueError("Unexpected EOF, expected list contents")
|
||||
|
||||
|
||||
def parseDict():
|
||||
nonlocal offset
|
||||
|
||||
offset += 1
|
||||
items = {}
|
||||
|
||||
while offset < len(data):
|
||||
if data[offset] == ord("e"):
|
||||
# End of list
|
||||
offset += 1
|
||||
return items
|
||||
else:
|
||||
key, value = parse(), parse()
|
||||
if not isinstance(key, bytes):
|
||||
raise ValueError("A dict key must be a byte string")
|
||||
if key in items:
|
||||
raise ValueError("Duplicate dict key: {}".format(key))
|
||||
items[key] = value
|
||||
|
||||
raise ValueError("Unexpected EOF, expected dict contents")
|
||||
|
||||
|
||||
def parse():
|
||||
nonlocal offset
|
||||
|
||||
if data[offset] == ord("i"):
|
||||
return parseInteger()
|
||||
elif data[offset] == ord("l"):
|
||||
return parseList()
|
||||
elif data[offset] == ord("d"):
|
||||
return parseDict()
|
||||
elif ord("0") <= data[offset] <= ord("9"):
|
||||
return parseString()
|
||||
|
||||
raise ValueError("Unknown type specifier: '{}'".format(chr(data[offset])))
|
||||
|
||||
result = parse()
|
||||
|
||||
if offset != len(data):
|
||||
raise ValueError("Expected EOF, got {} bytes left".format(len(data) - offset))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def dumps(data):
|
||||
result = bytearray()
|
||||
|
||||
|
||||
def convert(data):
|
||||
nonlocal result
|
||||
|
||||
if isinstance(data, str):
|
||||
raise ValueError("bencode only supports bytes, not str. Use encode")
|
||||
|
||||
if isinstance(data, bytes):
|
||||
result += str(len(data)).encode() + b":" + data
|
||||
elif isinstance(data, int):
|
||||
result += b"i" + str(data).encode() + b"e"
|
||||
elif isinstance(data, list):
|
||||
result += b"l"
|
||||
for val in data:
|
||||
convert(val)
|
||||
result += b"e"
|
||||
elif isinstance(data, dict):
|
||||
result += b"d"
|
||||
for key in sorted(data.keys()):
|
||||
if not isinstance(key, bytes):
|
||||
raise ValueError("Dict key can only be bytes, not {}".format(type(key)))
|
||||
convert(key)
|
||||
convert(data[key])
|
||||
result += b"e"
|
||||
else:
|
||||
raise ValueError("bencode only supports bytes, int, list and dict")
|
||||
|
||||
|
||||
convert(data)
|
||||
|
||||
return bytes(result)
|
Loading…
Reference in a new issue