From 568cf9ade658490a4c77b94d0d29e96a7ef575b6 Mon Sep 17 00:00:00 2001 From: JustAnotherArchivist Date: Wed, 22 Feb 2023 22:54:32 +0000 Subject: [PATCH] Add files mode --- torrent-tiny | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/torrent-tiny b/torrent-tiny index efce164..c859728 100755 --- a/torrent-tiny +++ b/torrent-tiny @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import enum +import functools import hashlib +import operator import sys @@ -85,6 +87,9 @@ def bdecode(fp, display = False, infoWrite = None): if c != b'd': raise ValueError stateStack = [ParserState.NONE, ParserState.DICTIONARY] + idxStack = [None, None] + out = {} + get_o = lambda: functools.reduce(operator.getitem, idxStack[2:], out) inInfo = False print_ = print if display else (lambda *args, **kwargs: None) print_(f'(global): {dictEntry}') @@ -95,6 +100,7 @@ def bdecode(fp, display = False, infoWrite = None): c = fp.read(1) if c == b'e': # End of dict stateStack.pop(-1) + idxStack.pop(-1) if len(stateStack) == 2 and inInfo and infoWrite: inInfo = False fp = fp.fp @@ -106,19 +112,31 @@ def bdecode(fp, display = False, infoWrite = None): fp = CopyingFileReader(fp, infoWrite) v = read_or_stack_value(fp, stateStack) print_(f'{indent}{key!r}: {v!r}') + if v is dictEntry or v is listEntry: + get_o()[key] = {} if v is dictEntry else [] + idxStack.append(key) + else: + get_o()[key] = v else: raise ValueError elif state == ParserState.LIST: c = fp.read(1) if c == b'e': stateStack.pop(-1) + idxStack.pop(-1) continue else: v = read_or_stack_value(fp, stateStack, c) print_(f'{indent}- {v!r}') + o = get_o() + if v is dictEntry or v is listEntry: + o.append({} if v is dictEntry else []) + idxStack.append(len(o) - 1) + else: + o.append(v) elif state == ParserState.NONE: assert len(stateStack) == 1 - return + return out def print_torrent(fp): @@ -131,10 +149,16 @@ def get_info_hash(fp): return hasher.hexdigest() +def print_files(fp): + o = bdecode(fp) + for f in o['info']['files']: + print('/'.join(f['path'])) + + def main(): - if len(sys.argv) < 3 or sys.argv[1] not in ('print', 'infohash'): + if len(sys.argv) < 3 or sys.argv[1] not in ('print', 'infohash', 'files'): print('Usage: torrent-tiny MODE FILE [FILE...]', file = sys.stderr) - print('MODEs: print, infohash', file = sys.stderr) + print('MODEs: print, infohash, files', file = sys.stderr) sys.exit(1) mode = sys.argv[1] @@ -144,6 +168,8 @@ def main(): print_torrent(fp) elif mode == 'infohash': print(get_info_hash(fp)) + elif mode == 'files': + print_files(fp) if __name__ == '__main__':