From fc62fac9864ad8d07a644c9e67505204baf64a88 Mon Sep 17 00:00:00 2001 From: Oleg Broytman Date: Sun, 12 Jan 2025 23:36:11 +0300 Subject: [PATCH] Feat: List content of a torrent metafile --- eff_bdecode.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ ls-torrent | 12 ++++++++ 2 files changed, 89 insertions(+) create mode 100644 eff_bdecode.py create mode 100755 ls-torrent diff --git a/eff_bdecode.py b/eff_bdecode.py new file mode 100644 index 0000000..a3172ed --- /dev/null +++ b/eff_bdecode.py @@ -0,0 +1,77 @@ +# effbot.org/zone/bencode.htm +# +# Copyright (C) 1995-2013 by Fredrik Lundh +# +# By obtaining, using, and/or copying this software and/or its associated +# documentation, you agree that you have read, understood, and will comply with +# the following terms and conditions: +# +# Permission to use, copy, modify, and distribute this software and its +# associated documentation for any purpose and without fee is hereby granted, +# provided that the above copyright notice appears in all copies, and that both +# that copyright notice and this permission notice appear in supporting +# documentation, and that the name of Secret Labs AB or the author not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. +# +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN +# NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, +# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +from functools import partial +import re + + +def tokenize(text, match=re.compile(b"([idel])|(\\d+):|(-?\\d+)").match): + i = 0 + while i < len(text): + m = match(text, i) + s = m.group(m.lastindex) + i = m.end() + if m.lastindex == 2: + yield "s" + yield text[i:i+int(s)] + i = i + int(s) + else: + yield s.decode('ascii') + + +def decode_item(next_, token): + if token == "i": + # integer: "i" value "e" + data = int(next_()) + if next_() != "e": + raise ValueError + elif token == "s": + # string: "s" value (virtual tokens) + data = next_() + elif token == "l" or token == "d": + # container: "l" (or "d") values "e" + data = [] + tok = next_() + while tok != "e": + data.append(decode_item(next_, tok)) + try: + tok = next_() + except StopIteration: + break + if token == "d": + data = dict(zip(data[0::2], data[1::2])) + else: + raise ValueError + return data + + +def eff_bdecode(text): + try: + src = tokenize(text) + data = decode_item(partial(next, src), next(src)) + for token in src: # look for more tokens + raise SyntaxError("trailing junk") + except (AttributeError, ValueError, StopIteration): + raise SyntaxError("syntax error") + return data diff --git a/ls-torrent b/ls-torrent new file mode 100755 index 0000000..2804c85 --- /dev/null +++ b/ls-torrent @@ -0,0 +1,12 @@ +#! /usr/bin/env python3 + +import sys +from pprint import pprint +from eff_bdecode import eff_bdecode + +torrent_file = open(sys.argv[1], 'rb') +data = torrent_file.read() +torrent_file.close() + +torrent = eff_bdecode(data) +pprint(torrent) -- 2.39.5