Bdecode.pm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#!/usr/bin/perl -w package Bdecode; use strict; use Carp; our %bdecode_funcs = ( list => sub {return [bdecode_list($_[0])]}, dict => sub {return {bdecode_list($_[0])}}, int => sub {return 0 + $_[1]}, string => sub {return substr ${$_[0]}, 0, $_[1], ''}, ); # on return, contains unparsed text sub bdecode(\$) { my ($str) = @_; my $key = $$str =~ /^l/ ? 'list' : $$str =~ /^d/ ? 'dict' : $$str =~ /^i(0|-?[1-9]\d*)e/ ? 'int' : $$str =~ /^(0|[1-9]\d*):/ ? 'string' : undef; $key or croak 'invalid sequence'; $$str =~ s///; return $bdecode_funcs{$key}->($str, $+); } sub bdecode_list($) { my ($str) = @_; my @result; push @result, bdecode($$str) while $$str !~ /^e/; $$str =~ s///; return @result; } 1;
bdecode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/usr/bin/perl -w0777 use strict; use Bdecode; use Data::Dumper; my $input = <STDIN>; my $obj = Bdecode::bdecode($input); push @ARGV, '' unless @ARGV; for my $path (@ARGV) { my $cur = $obj; for my $item (split '/', $path) { my ($name, @indices) = split /:/, $item; $name =~ s/%([[:xdigit:]]{2})/chr hex $1/eg; $cur = $cur->{$name} if length $name; $cur = $cur->[$_] for @indices; } my $dumper = new Data::Dumper([$cur], [$path]); print $dumper->Dump; }
Refactorings
No refactoring yet !
The BitTorrent .torrent file format uses Bencode, so this program allows you to unpack .torrent files into something more intelligible. Note that the hashes are in binary, so be sure to escape the output before writing it to your terminal!