bcodec 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,95 @@
1
+ # bcodec - Ruby library to decode/encode bencoded data
2
+ # Copyright (C) 2006 Thomas <tochiroNO@SPAMrubyforge.org>
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License along
15
+ # with this program; if not, write to the Free Software Foundation, Inc.,
16
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
+
18
+ module BCodec
19
+
20
+ class InvalidInteger < Exception; end
21
+ class InvalidString < Exception; end
22
+ class InvalidKey < Exception; end
23
+ class UnknownData < Exception; end
24
+ class InvalidDataType < Exception; end
25
+
26
+ # Decodes bencoded data from an IO-like object (IO, File, StringIO or similar
27
+ # that has a .getc method).
28
+ #
29
+ # Returns the decoded object which is either of these:
30
+ # * Array
31
+ # * Fixnum (or Bignum)
32
+ # * Hash
33
+ # * String
34
+ def BCodec.decode(io)
35
+ c = io.getc
36
+
37
+ case c.chr
38
+ when 'i'
39
+ i = ''
40
+ while c = io.getc
41
+ if c.chr == 'e'
42
+ if i.match(/^(0|-?[1-9][0-9]*)$/)
43
+ return i.to_i
44
+ else
45
+ raise InvalidInteger
46
+ end
47
+ else
48
+ i += c.chr
49
+ end
50
+ end
51
+ raise EOFError
52
+ when '0'..'9'
53
+ n = c.chr
54
+ while b = io.getc
55
+ case b.chr
56
+ when '0'..'9'
57
+ n += b.chr
58
+ when ':'
59
+ strlen = n.to_i
60
+ str = io.read(strlen)
61
+ if str.length == strlen
62
+ return str
63
+ else
64
+ raise EOFError
65
+ end
66
+ else
67
+ raise InvalidString
68
+ end
69
+ end
70
+ when 'l'
71
+ list = []
72
+
73
+ while item = decode(io)
74
+ list.push(item)
75
+ end
76
+
77
+ return list
78
+ when 'd'
79
+ dict = {}
80
+
81
+ while key = decode(io)
82
+ raise InvalidKey unless key.instance_of?(String)
83
+ val = decode(io)
84
+ dict[key] = val
85
+ end
86
+
87
+ return dict
88
+ when 'e'
89
+ return false
90
+ else
91
+ raise UnknownData
92
+ end
93
+ end
94
+
95
+ end
@@ -0,0 +1,56 @@
1
+ # BCodec - Ruby module to decode/encode bencoded data
2
+ # Copyright (C) 2006 Thomas <tochiro@freeshell.org>
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+
18
+ module BCodec
19
+
20
+ class InvalidKey < Exception; end
21
+ class InvalidDataType < Exception; end
22
+
23
+ # Bencodes a Ruby object which must be either of these:
24
+ #
25
+ # * Array
26
+ # * Fixnum (or Bignum)
27
+ # * Hash
28
+ # * String
29
+ #
30
+ # Returns the encoded object(s) as a String
31
+ def BCodec.encode(obj)
32
+ str = ""
33
+ if obj.class == String
34
+ str << "%d:%s" % [ obj.length, obj ]
35
+ elsif obj.class == Fixnum or obj.class == Integer or obj.class == Bignum
36
+ str << "i" << obj.to_s << "e"
37
+ elsif obj.class == Array
38
+ str << "l"
39
+ obj.each { |i| str += encode(i) }
40
+ str << "e"
41
+ elsif obj.class == Hash
42
+ str << "d"
43
+ obj.sort.each do |k, v|
44
+ raise InvalidKey unless k.instance_of?(String)
45
+ str << encode(k)
46
+ str << encode(v)
47
+ end
48
+ str << "e"
49
+ else
50
+ raise InvalidDataType
51
+ end
52
+
53
+ return str
54
+ end
55
+
56
+ end
data/lib/bcodec.rb ADDED
@@ -0,0 +1,55 @@
1
+ # bcodec - Ruby library to decode/encode bencoded data
2
+ # Copyright (C) 2006 Thomas <tochiroNO@SPAMrubyforge.org>
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License along
15
+ # with this program; if not, write to the Free Software Foundation, Inc.,
16
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
+
18
+ #=bcodec
19
+ #
20
+ #==Description
21
+ #bcodec is a Ruby library for encoding and decoding bencoded data used in the
22
+ #BitTorrent protocol (see http://www.bittorrent.org/).
23
+ #
24
+ #
25
+ #==Encoding example:
26
+ #
27
+ # require 'bcodec'
28
+ # BCodec.encode("abcd") # returns "4:abcd"
29
+ # BCodec.encode(1000) # returns "i1000e"
30
+ # BCodec.encode([1,2,3]) # returns "li1ei2ei3ee"
31
+ # BCodec.encode({"key" => "value"}) # returns "d3:key5:valuee"
32
+ #
33
+ #
34
+ #==Decoding example:
35
+ #
36
+ # require 'bcodec'
37
+ # BCodec.decode(StringIO.new("4:abcd")) # returns "abcd"
38
+ # BCodec.decode(StringIO.new("i666e")) # returns 666
39
+ # BCodec.decode(StringIO.new("l3abci666ee")) # returns [ "abc", 666 ]
40
+ # BCodec.decode(StringIO.new("d3abci666ee")) # returns { "abc" => 666 }
41
+ #
42
+ #To decode a BitTorrent metafile you could do something like:
43
+ #
44
+ # hash = BCodec.decode(open("some.torrent", "r"))
45
+ #
46
+ #The only legal objects are String, Fixnum (or Bignum), Hash and Array which
47
+ #corresponds to String, Integer, Dictionary and List in Python as
48
+ #specified in the BitTorrent protocol specification at:
49
+ #http://www.bittorrent.org/protocol.html
50
+
51
+ module BCodec
52
+ require 'bcodec/decode'
53
+ require 'bcodec/encode'
54
+ end
55
+
@@ -0,0 +1,37 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'lib/bcodec/decode'
4
+
5
+ class TestDecoding < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @tests = []
9
+ @tests << [ "4:test", "test" ]
10
+ @tests << [ "i666e", 666 ]
11
+ @tests << [ "l4:testi666ee", [ "test", 666 ] ]
12
+ @tests << [ "d4:testi666ee", { "test" => 666 } ]
13
+ @tests << [ "d4:testli1ei2ei3ed1:Ai1e1:Bl1:a1:b1:ceeee",
14
+ { "test" => [ 1, 2, 3, { "A" => 1, "B" => [ 'a', 'b', 'c' ] } ] } ]
15
+
16
+ @etests = []
17
+ @etests << [ BCodec::InvalidInteger, "i1.0e" ]
18
+ @etests << [ BCodec::InvalidInteger, "iAe" ]
19
+ @etests << [ BCodec::UnknownData, "f" ]
20
+ @etests << [ BCodec::InvalidKey, "di666e:3:keye" ]
21
+ @etests << [ EOFError, "i1" ]
22
+ @etests << [ EOFError, "4:ab" ]
23
+ end
24
+
25
+ def test_decoding
26
+ @tests.each do |test, result|
27
+ assert_equal BCodec.decode(StringIO.new(test)), result
28
+ end
29
+ end
30
+
31
+ def test_decoding_exceptions
32
+ @etests.each do |exception, test|
33
+ assert_raise(exception) { BCodec.decode(StringIO.new(test)) }
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,37 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'lib/bcodec/encode'
4
+
5
+ include BCodec
6
+
7
+ class TestEncoding < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @tests = []
11
+ @tests << [ "test", "4:test" ]
12
+ @tests << [ 666, "i666e" ]
13
+ @tests << [ [ "test", 666 ], "l4:testi666ee" ]
14
+ @tests << [ { "test" => 666 }, "d4:testi666ee" ]
15
+ @tests << [ { "test" => [ 1, 2, 3, { "A" => 1, "B" => [ 'a', 'b', 'c' ] } ] },
16
+ "d4:testli1ei2ei3ed1:Ai1e1:Bl1:a1:b1:ceeee" ]
17
+
18
+ @etests = []
19
+ @etests << [ BCodec::InvalidDataType, :symbol ]
20
+ @etests << [ BCodec::InvalidDataType, [1.0, "float"] ]
21
+ @etests << [ BCodec::InvalidKey, {1 => "key"} ]
22
+ @etests << [ BCodec::InvalidDataType, 1..666 ]
23
+ end
24
+
25
+ def test_basic_encoding
26
+ @tests.each do |test, result|
27
+ assert_equal(BCodec.encode(test), result)
28
+ end
29
+ end
30
+
31
+ def test_encoding_exceptions
32
+ @etests.each do |exception, test|
33
+ assert_raise(exception) { BCodec.encode(test) }
34
+ end
35
+ end
36
+
37
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: bcodec
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-11-18 00:00:00 +01:00
8
+ summary: Ruby library for encoding and decoding bencoded data used in the BitTorrent protocol
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage: http://bcodec.rubyforge.org/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: bcodec
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors: []
29
+
30
+ files:
31
+ - lib/bcodec
32
+ - lib/bcodec.rb
33
+ - lib/bcodec/encode.rb
34
+ - lib/bcodec/decode.rb
35
+ - test/test_encoding.rb
36
+ - test/test_decoding.rb
37
+ test_files:
38
+ - test/test_decoding.rb
39
+ - test/test_encoding.rb
40
+ rdoc_options: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ requirements: []
49
+
50
+ dependencies: []
51
+