bencode 0.5.0 → 0.5.1

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.
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