—#!/usr/bin/perl -w
package
Convert::Bencode;
=head1 NAME
Convert::Bencode - Functions for converting to/from bencoded strings
=head1 SYNOPSIS
use Convert::Bencode qw(bencode bdecode);
my $string = "d4:ainti12345e3:key5:value4:type4:teste";
my $hashref = bdecode($string);
foreach my $key (keys(%{$hashref})) {
print "Key: $key, Value: ${$hashref}{$key}\n";
}
my $encoded_string = bencode($hashref);
print $encoded_string."\n";
=head1 DESCRIPTION
This module provides two functions, C<bencode> and C<bdecode>, which
encode and decode bencoded strings respectivly.
=head2 Encoding
C<bencode()> expects to be passed a single value, which is either a scalar,
a arrary ref, or a hash ref, and it returns a scalar containing the bencoded
representation of the data structure it was passed. If the value passed was
a scalar, it returns either a bencoded string, or a bencoded integer (floating
points are not implemented, and would be returned as a string rather than a
integer). If the value was a array ref, it returns a bencoded list, with all
the values of that array also bencoded recursivly. If the value was a hash ref,
it returns a bencoded dictionary (which for all intents and purposes can be
thought of as a synonym for hash) containing the recursivly bencoded key and
value pairs of the hash.
=head2 Decoding
C<bdecode()> expects to be passed a single scalar containing the bencoded string
to be decoded. Its return value will be either a hash ref, a array ref, or a
scalar, depending on whether the outer most element of the bencoded string
was a dictionary, list, or a string/integer respectivly.
=head1 SEE ALSO
The description of bencode is part of the bittorrent protocol specification
which can be found at http://bitconjurer.org/BitTorrent/protocol.html
=head1 BUGS
No error detection of bencoded data. Damaged input will most likely cause very bad things to happen, up to and including causeing the bdecode function to recurse infintly.
=head1 AUTHOR & COPYRIGHT
Created by R. Kyle Murphy <orclev@rejectedmaterial.com>, aka Orclev.
Copyright 2003 R. Kyle Murphy. All rights reserved. Convert::Bencode
is free software; you may redistribute it and/or modify it under the
same terms as Perl itself.
=cut
use
strict;
use
warnings;
use
bytes;
BEGIN {
our
(
$VERSION
,
@ISA
,
@EXPORT
,
@EXPORT_OK
,
@EXPORT_FAIL
,
%EXPORT_TAGS
);
$VERSION
= 1.03;
@ISA
=
qw(Exporter)
;
@EXPORT_OK
=
qw(&bencode &bdecode)
;
@EXPORT_FAIL
=
qw(&_dechunk)
;
%EXPORT_TAGS
= (
all
=> [
qw(&bencode &bdecode)
]);
}
our
@EXPORT_OK
;
END { }
sub
bencode {
no
locale;
my
$item
=
shift
;
my
$line
=
''
;
if
(
ref
(
$item
) eq
'HASH'
) {
$line
=
'd'
;
foreach
my
$key
(
sort
(
keys
%{
$item
})) {
$line
.= bencode(
$key
);
$line
.= bencode(${
$item
}{
$key
});
}
$line
.=
'e'
;
return
$line
;
}
if
(
ref
(
$item
) eq
'ARRAY'
) {
$line
=
'l'
;
foreach
my
$l
(@{
$item
}) {
$line
.= bencode(
$l
);
}
$line
.=
'e'
;
return
$line
;
}
if
(
$item
=~ /^\d+$/) {
$line
=
'i'
;
$line
.=
$item
;
$line
.=
'e'
;
return
$line
;
}
$line
=
length
(
$item
).
":"
;
$line
.=
$item
;
return
$line
;
}
sub
bdecode {
my
$string
=
shift
;
my
@chunks
=
split
(//,
$string
);
my
$root
= _dechunk(\
@chunks
);
return
$root
;
}
sub
_dechunk {
my
$chunks
=
shift
;
my
$item
=
shift
(@{
$chunks
});
if
(
$item
eq
'd'
) {
$item
=
shift
(@{
$chunks
});
my
%hash
;
while
(
$item
ne
'e'
) {
unshift
(@{
$chunks
},
$item
);
my
$key
= _dechunk(
$chunks
);
$hash
{
$key
} = _dechunk(
$chunks
);
$item
=
shift
(@{
$chunks
});
}
return
\
%hash
;
}
if
(
$item
eq
'l'
) {
$item
=
shift
(@{
$chunks
});
my
@list
;
while
(
$item
ne
'e'
) {
unshift
(@{
$chunks
},
$item
);
push
(
@list
, _dechunk(
$chunks
));
$item
=
shift
(@{
$chunks
});
}
return
\
@list
;
}
if
(
$item
eq
'i'
) {
my
$num
;
$item
=
shift
(@{
$chunks
});
while
(
$item
ne
'e'
) {
$num
.=
$item
;
$item
=
shift
(@{
$chunks
});
}
return
$num
;
}
if
(
$item
=~ /\d/) {
my
$num
;
while
(
$item
=~ /\d/) {
$num
.=
$item
;
$item
=
shift
(@{
$chunks
});
}
my
$line
=
''
;
for
(1 ..
$num
) {
$line
.=
shift
(@{
$chunks
});
}
return
$line
;
}
return
$chunks
;
}
1;