Skip to content

Instantly share code, notes, and snippets.

@iwconfig
Created December 8, 2025 01:11
Show Gist options
  • Select an option

  • Save iwconfig/b973c8c7a974a94f114cd96337eb2280 to your computer and use it in GitHub Desktop.

Select an option

Save iwconfig/b973c8c7a974a94f114cd96337eb2280 to your computer and use it in GitHub Desktop.
bencode decoder
import sys
import json
def bdecode(bencoded_bytes):
def decode_int(b, i):
j = b.find(b'e', i)
return int(b[i:j]), j + 1
def decode_bytes(b, i):
colon = b.find(b':', i)
length = int(b[i:colon])
start = colon + 1
return b[start:start+length], start+length
def decode_list(b, i):
items = []
i += 1
while b[i:i+1] != b'e':
value, i = decode_element(b, i)
items.append(value)
return items, i + 1
def decode_dict(b, i):
items = {}
i += 1
while b[i:i+1] != b'e':
key, i = decode_bytes(b, i)
value, i = decode_element(b, i)
items[key] = value
return items, i + 1
def decode_element(b, i):
if b[i:i+1] == b'i':
return decode_int(b, i+1)
elif b[i:i+1] == b'l':
return decode_list(b, i)
elif b[i:i+1] == b'd':
return decode_dict(b, i)
elif b[i:i+1].isdigit():
return decode_bytes(b, i)
else:
raise ValueError("Invalid bencode format")
decoded_data, _ = decode_element(bencoded_bytes, 0)
return decoded_data
def convert_bytes_to_str(data):
"""Recursively converts bytes keys and values in a dict/list to UTF-8 strings."""
if isinstance(data, bytes):
try:
# Assume UTF-8 encoding for standard torrent metadata (filenames, etc.)
return data.decode('utf-8')
except UnicodeDecodeError:
# Handle non-UTF-8 data gracefully (maybe represent as hex or just skip)
return data.hex()
elif isinstance(data, list):
return [convert_bytes_to_str(item) for item in data]
elif isinstance(data, dict):
new_dict = {}
for key, value in data.items():
# Convert both the key (which is currently a bytes object)
# and the value recursively
new_key = convert_bytes_to_str(key)
new_value = convert_bytes_to_str(value)
new_dict[new_key] = new_value
return new_dict
else:
# Handle integers or other types
return data
raw_bencode_response = sys.stdin.buffer.read()
decoded_info = bdecode(raw_bencode_response)
# Convert all bytes to strings recursively
decoded_info_str = convert_bytes_to_str(decoded_info)
# Safely remove the "pieces" key now that keys are strings
if "pieces" in decoded_info_str:
del decoded_info_str["pieces"]
# Dump the fully stringified dictionary to stdout as JSON
print(json.dumps(decoded_info_str, indent=2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment