bencode 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+
2
+ Copyright (c) 2009 Daniel Schierbeck
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+
2
+ Ruby bencode binding
3
+ ====================
4
+
5
+ This is a simple library for reading and writing bencoded data.
6
+
7
+
8
+ What is bencode?
9
+ ----------------
10
+
11
+ Bencode is a simple data serialization format used by the popular
12
+ [BitTorrent](http://bittorrent.org/) P2P file sharing system.
13
+
14
+ It contains only four data types, namely:
15
+
16
+ - byte strings
17
+ - integers
18
+ - lists
19
+ - dictionaries
20
+
21
+
22
+ Examples
23
+ --------
24
+
25
+ "foo bar".bencode # => "7:foo bar"
26
+ 42.bencode # => "i42e"
27
+ [1, 2, 3].bencode # => "li1ei2ei3ee"
28
+ {"foo" => 1, "bar" => -10}.bencode # => "d3:bari-10e3:fooi1ee"
29
+
30
+
31
+ License
32
+ -------
33
+
34
+ Released under the MIT license.
35
+
36
+
37
+ Contributors
38
+ ------------
39
+
40
+ - Mike Hodgson
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ ##
6
+ # Run all unit tests.
7
+ Rake::TestTask.new
8
+
9
+
10
+ ##
11
+ # Generate RDoc documentation.
12
+ Rake::RDocTask.new :doc do |rdoc|
13
+ rdoc.rdoc_dir = 'doc'
14
+ end
data/lib/bencode.rb CHANGED
@@ -1,78 +1,9 @@
1
- # = bencode.rb - Bencode Library
2
- #
3
- # Bencode is a Ruby implementation of the Bencode data serialization
4
- # format used in the BitTorrent protocol.
5
- #
6
- # == Synopsis
7
- #
8
- # Bencoding (pronounced <i>bee-encode</i>) is a simple protocol,
9
- # consisting of only 4 value types.
10
- #
11
- # === Integers
12
- #
13
- # An integer is encoded as an _i_ followed by the numeral itself, followed
14
- # by an _e_. Leading zeros are not allowed. Negative values are prefixed
15
- # with a minus sign.
16
- #
17
- # 42.bencode #=> "i42e"
18
- # -2.bencode #=> "i-2e"
19
- # 0.bencode #=> "i0e"
20
- #
21
- # === Strings
22
- #
23
- # Strings are sequences of zero or more bytes. They are encoded as
24
- # <i>&lt;length&gt;:&lt;contents&gt;</i>, where _length_ is the
25
- # length of _contents_. _length_ must be non-negative.
26
- #
27
- # "".bencode #=> "0:"
28
- # "foo".bencode #=> "3:foo"
29
- #
30
- # === Lists
31
- #
32
- # Lists are encoded as _l_ followed by the elements, followed by _e_.
33
- # There is no element seperator.
34
- #
35
- # [1, 2, 3].bencode #=> "li1ei2ei3ee"
36
- #
37
- # === Dictionaries
38
- #
39
- # Dictionaries are encoded as _d_ followed by a sequence of key-value
40
- # pairs, followed by _e_. Each value must be immediately preceded by
41
- # a key. Keys must be strings, and must appear in lexicographical order.
42
- #
43
- # {"foo" => 3, "bar" => 1, "baz" => 2}.bencode
44
- # #=> "d3:bari1e3:bazi2e3:fooi3ee"
45
- #
46
- #
47
- # == Authors
48
- #
49
- # * Daniel Schierbeck
50
- #
51
- # == Contributors
52
- #
53
- # * Daniel Martin
54
- # * Phrogz
55
- # * Julien Pervillé
56
- #
57
- # == Copyright
58
- #
59
- # Bencode is free software; you can redistribute it and/or modify it under the
60
- # terms of the GNU General Public License as published by the Free Software
61
- # Foundation; either version 2 of the License, or (at your option) any later
62
- # version.
63
- #
64
- # Bencode is distributed in the hope that it will be useful, but WITHOUT ANY
65
- # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
66
- # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
67
- # details.
68
1
 
69
-
70
- prefix = File.dirname(__FILE__)
71
-
72
- %w[object integer string array hash].each do |type|
73
- require prefix + '/bencode/encode/' + type
2
+ # TODO: Write some documentation here.
3
+ module BEncode
4
+ VERSION = '0.5.0'
74
5
  end
75
6
 
76
- %w[decode io encode_error decode_error].each do |file|
77
- require prefix + '/bencode/' + file
78
- end
7
+ glob = File.join(File.dirname(__FILE__), 'bencode/**/*.rb')
8
+
9
+ Dir[glob].sort.each{|file| require file }
@@ -18,22 +18,23 @@ module BEncode
18
18
 
19
19
  # Bdecodes the file located at +path+
20
20
  def load_file(path)
21
- load(File.open(path).read)
21
+ if RUBY_PLATFORM =~ /(win|w)32$/
22
+ load(File.open(path, 'rb').read)
23
+ else
24
+ load(File.open(path).read)
25
+ end
22
26
  end
23
27
 
24
28
  def parse(scanner) # :nodoc:
25
- case token = scanner.scan(/[ild]|\d+:|\s/)
26
- when nil
27
- raise BEncode::DecodeError
29
+ case scanner.scan(/[ild]|\d+:/)
28
30
  when "i"
29
31
  number = scanner.scan(/0|(?:-?[1-9][0-9]*)/)
30
32
  raise BEncode::DecodeError unless number and scanner.scan(/e/)
31
33
  return number.to_i
32
34
  when "l"
33
35
  ary = []
34
- until scanner.peek(1) == "e"
35
- ary.push(parse(scanner))
36
- end
36
+ # TODO: There must be a smarter way of doing this...
37
+ ary.push(parse(scanner)) until scanner.peek(1) == "e"
37
38
  scanner.pos += 1
38
39
  return ary
39
40
  when "d"
@@ -50,7 +51,7 @@ module BEncode
50
51
  scanner.pos += 1
51
52
  return hsh
52
53
  when /\d+:/
53
- length = token.chop.to_i
54
+ length = Integer($~.string.chop)
54
55
  str = scanner.peek(length)
55
56
 
56
57
  begin
@@ -10,10 +10,7 @@ class Array
10
10
  begin
11
11
  "l#{map{|obj| obj.bencode }.join('')}e"
12
12
  rescue BEncode::EncodeError
13
- raise BEncode::EncodeError, "array items must be bencodable"
14
- # TODO: This is probably a bad idea...
15
- rescue SystemStackError
16
- raise BEncode::EncodeError, "cannot encode recursive array"
13
+ raise BEncode::EncodeError, "array items must be encodable"
17
14
  end
18
15
  end
19
16
  end
@@ -10,10 +10,6 @@ class Hash
10
10
  pairs = sort.map{|key, val| [key.to_str.bencode, val.bencode] }
11
11
  "d#{pairs.join('')}e"
12
12
  rescue NoMethodError => error
13
- if error.name == :to_str
14
- raise BEncode::EncodeError, "dictionary keys must be strings"
15
- else
16
- raise
17
- end
13
+ raise BEncode::EncodeError, "dictionary keys must be strings"
18
14
  end
19
15
  end
@@ -0,0 +1,2 @@
1
+
2
+ require File.dirname(__FILE__) + '/../lib/bencode'
Binary file
@@ -0,0 +1,13 @@
1
+
2
+ require 'test/unit'
3
+ require 'test/environment'
4
+
5
+ class TestDecodeUTF8 < Test::Unit::TestCase
6
+
7
+ def test_can_handle_utf8_encoded_data
8
+ assert_nothing_raised do
9
+ BEncode.load_file('test/fixtures/test.torrent')
10
+ end
11
+ end
12
+
13
+ end
metadata CHANGED
@@ -1,80 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
3
- specification_version: 1
4
2
  name: bencode
5
3
  version: !ruby/object:Gem::Version
6
- version: 0.5.0
7
- date: 2007-02-07 00:00:00 +01:00
8
- summary: A Ruby implementation of the Bencode encoding used by BitTorrent
9
- require_paths:
10
- - lib
11
- email:
12
- homepage: bencode.rubyforge.org
13
- rubyforge_project: bencode
14
- description:
15
- autorequire: bencode
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: 0.5.1
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - Daniel Schierbeck
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-06 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Ruby bindings for the bencode data serialization format.
17
+ email: daniel.schierbeck@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
31
24
  files:
25
+ - Rakefile
26
+ - LICENSE
27
+ - README.md
32
28
  - lib/bencode.rb
33
- - lib/bencode/io.rb
34
- - lib/bencode/encode_error.rb
35
29
  - lib/bencode/decode.rb
36
30
  - lib/bencode/decode_error.rb
37
- - lib/bencode/encode/object.rb
38
- - lib/bencode/encode/integer.rb
39
- - lib/bencode/encode/hash.rb
31
+ - lib/bencode/encode_error.rb
32
+ - lib/bencode/io.rb
40
33
  - lib/bencode/encode/array.rb
34
+ - lib/bencode/encode/integer.rb
41
35
  - lib/bencode/encode/string.rb
42
- - test/test_decode.rb
43
- - test/test_encode.rb
44
- - test/suite.rb
45
- - test/decode/test_invalid.rb
46
- - test/decode/test_dictionary.rb
47
- - test/decode/test_integer.rb
48
- - test/decode/test_string.rb
49
- - test/decode/test_list.rb
50
- - test/encode/test_float.rb
51
- - test/encode/test_hash.rb
52
- - test/encode/test_integer.rb
53
- - test/encode/test_string.rb
54
- - test/encode/test_array.rb
55
- test_files:
56
- - test/test_decode.rb
57
- - test/test_encode.rb
58
- - test/suite.rb
59
- - test/decode/test_invalid.rb
60
- - test/decode/test_dictionary.rb
61
- - test/decode/test_integer.rb
62
- - test/decode/test_string.rb
63
- - test/decode/test_list.rb
64
- - test/encode/test_float.rb
65
- - test/encode/test_hash.rb
66
- - test/encode/test_integer.rb
67
- - test/encode/test_string.rb
68
- - test/encode/test_array.rb
69
- rdoc_options: []
70
-
71
- extra_rdoc_files: []
72
-
73
- executables: []
36
+ - lib/bencode/encode/hash.rb
37
+ - lib/bencode/encode/object.rb
38
+ has_rdoc: true
39
+ homepage: http://github.com/dasch/ruby-bencode-bindings
40
+ licenses: []
74
41
 
75
- extensions: []
42
+ post_install_message:
43
+ rdoc_options: []
76
44
 
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
77
59
  requirements: []
78
60
 
79
- dependencies: []
80
-
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.5
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Ruby bencode bindings
66
+ test_files:
67
+ - test/test_decode_utf8.rb
68
+ - test/environment.rb
69
+ - test/fixtures/test.torrent
@@ -1,18 +0,0 @@
1
-
2
- require 'test/unit'
3
- require File.dirname(__FILE__) + "/../../lib/bencode.rb"
4
-
5
- class BdecodeDictionaryTest < Test::Unit::TestCase
6
- def test_empty
7
- assert_equal Hash.new, "de".bdecode
8
- end
9
-
10
- def test_single_pair
11
- assert_equal({"a" => 42}, 'd1:ai42ee'.bdecode)
12
- end
13
-
14
- def test_multi_pair
15
- hsh = {"a" => "monkey", "h" => "elephant", "z" => "zebra"}
16
- assert_equal hsh, "d1:a6:monkey1:h8:elephant1:z5:zebrae".bdecode
17
- end
18
- end
@@ -1,32 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BdecodeIntegerTest < Test::Unit::TestCase
6
- def test_zero
7
- assert_equal 0, 'i0e'.bdecode
8
- end
9
-
10
- def test_single_digit
11
- (1..9).each do |digit|
12
- assert_equal digit, "i#{digit}e".bdecode
13
- end
14
- end
15
-
16
- def test_multi_digit
17
- (1..10).each do |digit|
18
- assert_equal digit * 10, "i#{digit * 10}e".bdecode
19
- end
20
- end
21
-
22
- def test_negative
23
- (-9..-1).each do |digit|
24
- assert_equal digit, "i#{digit}e".bdecode
25
- end
26
- end
27
-
28
- def test_invalid
29
- assert_raise(BEncode::DecodeError){ 'i01e'.bdecode }
30
- assert_raise(BEncode::DecodeError){ 'i-0e'.bdecode }
31
- end
32
- end
@@ -1,17 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BdecodeInvalidTest < Test::Unit::TestCase
6
- errors = {:empty_string => '',
7
- :space_string => ' ',
8
- :unencoded_string => 'foobar',
9
- :multiple_top_items => 'i1ei2e',
10
- :string_length => '4:foo'}
11
-
12
- errors.each do |error, data|
13
- define_method("test_#{error}") do
14
- assert_raise(BEncode::DecodeError){ data.bdecode }
15
- end
16
- end
17
- end
@@ -1,24 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BdecodeListTest < Test::Unit::TestCase
6
- def test_empty
7
- assert_equal [], 'le'.bdecode
8
- end
9
-
10
- def test_string_list
11
- assert_equal %w[foo], 'l3:fooe'.bdecode
12
- assert_equal %w[a b c], 'l1:a1:b1:ce'.bdecode
13
- end
14
-
15
- def test_integer_list
16
- assert_equal [0], 'li0ee'.bdecode
17
- assert_equal [1, 2, 3], 'li1ei2ei3ee'.bdecode
18
- end
19
-
20
- def test_list_list
21
- assert_equal [[]], 'llee'.bdecode
22
- assert_equal [[], [], []], 'llelelee'.bdecode
23
- end
24
- end
@@ -1,23 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BdecodeStringTest < Test::Unit::TestCase
6
- def test_empty
7
- assert_equal '', '0:'.bdecode
8
- end
9
-
10
- def test_single_line
11
- assert_equal 'foo', '3:foo'.bdecode
12
- end
13
-
14
- def test_multi_line
15
- assert_equal "a\nb", "3:a\nb".bdecode
16
- end
17
-
18
- def test_whitespace
19
- [" ", "\t", "\n", "\r"].each do |char|
20
- assert_equal char, "1:#{char}".bdecode
21
- end
22
- end
23
- end
@@ -1,55 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BencodeListTest < Test::Unit::TestCase
6
- # Asserts that an empty array is encoded correctly.
7
- def test_empty
8
- assert_equal 'le', [].bencode
9
- end
10
-
11
- # Asserts that arrays of integers are encoded correctly.
12
- def test_integer_list
13
- assert_equal 'li1ee', [1].bencode
14
- assert_equal 'li1ei2ei3ei4ee', [1, 2, 3, 4].bencode
15
- end
16
-
17
- # Asserts that trying to encode a list containing a
18
- # floating point number raises a +BEncode::EncodeError+.
19
- def test_float_list
20
- assert_raise BEncode::EncodeError do
21
- [13.37].bencode
22
- end
23
- end
24
-
25
- def test_string_list
26
- assert_equal 'l3:fooe', %w[foo].bencode
27
- assert_equal 'l1:a1:b1:ce', %w[a b c].bencode
28
- end
29
-
30
- def test_list_list
31
- assert_equal 'llee', [[]].bencode
32
- assert_equal 'llleee', [[[]]].bencode
33
- assert_equal 'llelelee', [[], [], []].bencode
34
- end
35
-
36
- # Asserts that a recursive array is not bencoded.
37
- # TODO: Uses waaaaay too much time. What to do?
38
- def _test_recursive_list
39
- assert_raise BEncode::EncodeError do
40
- list = []
41
- list << list
42
- list.bencode
43
- end
44
-
45
- assert_raise BEncode::EncodeError do
46
- list = [[]]
47
- list.first << list
48
- list.bencode
49
- end
50
- end
51
-
52
- def test_dict_list
53
- assert_equal 'ldee', [{}].bencode
54
- end
55
- end
@@ -1,11 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BencodeFloatTest < Test::Unit::TestCase
6
- def test_illegal_number
7
- assert_raise BEncode::EncodeError do
8
- 13.37.bencode
9
- end
10
- end
11
- end
@@ -1,27 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BencodeDictionaryTest < Test::Unit::TestCase
6
- def test_empty
7
- assert_equal 'de', {}.bencode
8
- end
9
-
10
- def test_integer_hash
11
- assert_equal 'd1:ai1ee', {'a' => 1}.bencode
12
- assert_equal 'd1:ai1e1:bi2e1:ci3ee',
13
- {'a' => 1, 'b' => 2, 'c' => 3}.bencode
14
- end
15
-
16
- def test_illegal_keys
17
- assert_raise BEncode::EncodeError do
18
- {1 => 'foo'}.bencode
19
- end
20
- end
21
-
22
- # Thank you, Julien
23
- def test_key_order
24
- assert_equal 'd1:ai1e2:bbi3e1:ci2ee',
25
- {'a' => 1, 'c' => 2, 'bb' => 3}.bencode
26
- end
27
- end
@@ -1,27 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BencodeIntegerTest < Test::Unit::TestCase
6
- def test_zero
7
- assert_equal 'i0e', 0.bencode
8
- end
9
-
10
- def test_single_digit
11
- (1..9).each do |digit|
12
- assert_equal "i#{digit}e", digit.bencode
13
- end
14
- end
15
-
16
- def test_multi_digit
17
- (1..10).each do |digit|
18
- assert_equal "i#{digit * 10}e", (digit * 10).bencode
19
- end
20
- end
21
-
22
- def test_negative
23
- (-9..-1).each do |digit|
24
- assert_equal "i#{digit}e", digit.bencode
25
- end
26
- end
27
- end
@@ -1,32 +0,0 @@
1
-
2
- require 'test/unit'
3
- require "#{File.dirname(__FILE__)}/../../lib/bencode.rb"
4
-
5
- class BencodeStringTest < Test::Unit::TestCase
6
- def test_empty
7
- assert_equal '0:', ''.bencode
8
- end
9
-
10
- def test_single_char
11
- ('a'..'z').each do |char|
12
- assert_equal '1:' + char, char.bencode
13
- end
14
- end
15
-
16
- def test_single_line
17
- assert_equal '2:ab', 'ab'.bencode
18
- assert_equal '3:abc', 'abc'.bencode
19
- assert_equal '4:abcd', 'abcd'.bencode
20
- end
21
-
22
- def test_whitespace
23
- [" ", "\t", "\n", "\r"].each do |char|
24
- assert_equal '1:' + char, char.bencode
25
- assert_equal '2:' + char * 2, (char * 2).bencode
26
- end
27
- end
28
-
29
- def test_multi_line
30
- assert_equal "3:a\nb", "a\nb".bencode
31
- end
32
- end
data/test/suite.rb DELETED
@@ -1,5 +0,0 @@
1
-
2
- prefix = File.dirname(__FILE__)
3
-
4
- require prefix + '/test_encode'
5
- require prefix + '/test_decode'
data/test/test_decode.rb DELETED
@@ -1,4 +0,0 @@
1
-
2
- %w[string integer list dictionary invalid].each do |str|
3
- require File.dirname(__FILE__) + "/decode/test_#{str}"
4
- end
data/test/test_encode.rb DELETED
@@ -1,4 +0,0 @@
1
-
2
- %w[string integer float array hash].each do |str|
3
- require File.dirname(__FILE__) + "/encode/test_#{str}"
4
- end