bindata 1.8.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bindata might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.travis.yml +1 -1
- data/ChangeLog.rdoc +5 -14
- data/INSTALL +10 -9
- data/NEWS.rdoc +19 -0
- data/README.md +2 -6
- data/Rakefile +0 -2
- data/bindata.gemspec +0 -3
- data/examples/gzip.rb +70 -106
- data/examples/tcp_ip.rb +8 -10
- data/lib/bindata.rb +4 -0
- data/lib/bindata/base.rb +5 -10
- data/lib/bindata/bits.rb +15 -84
- data/lib/bindata/buffer.rb +1 -1
- data/lib/bindata/choice.rb +24 -8
- data/lib/bindata/deprecated.rb +3 -26
- data/lib/bindata/int.rb +10 -2
- data/lib/bindata/io.rb +5 -17
- data/lib/bindata/lazy.rb +1 -1
- data/lib/bindata/params.rb +1 -1
- data/lib/bindata/record.rb +19 -1
- data/lib/bindata/sanitize.rb +0 -20
- data/lib/bindata/string.rb +4 -5
- data/lib/bindata/struct.rb +23 -124
- data/lib/bindata/version.rb +1 -1
- data/test/alignment_test.rb +1 -1
- data/test/array_test.rb +3 -3
- data/test/bits_test.rb +34 -38
- data/test/common.rb +1 -5
- data/test/io_test.rb +0 -15
- data/test/lazy_test.rb +3 -11
- data/test/record_test.rb +21 -27
- data/test/string_test.rb +23 -25
- data/test/struct_test.rb +21 -52
- data/test/system_test.rb +9 -9
- metadata +48 -119
- data/doc/manual.haml +0 -407
- data/doc/manual.md +0 -1682
- data/setup.rb +0 -1585
- data/tasks/manual.rake +0 -36
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a1591b7284eb5311a1577007b50506a3169849cc
|
4
|
+
data.tar.gz: a60a5656dcb5586f12bc7fe88e98af7d12652d7a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 57b52b55ca1ab97820293d9c73b3e085542a955052b64e3873a87e7b8f0fdd84635a33843ad4aeb92dd7b089a7b988e2b9fe236c265189dbe310766811d7c5cc
|
7
|
+
data.tar.gz: 01a0327084e334cd02459daf396253b11f266a3c443dcf3f57e144dea6f653e98e5aa4d03249a8f5794bd867e727df609137b5e7519b400aa00cdec9c2cfc64b
|
data/.travis.yml
CHANGED
data/ChangeLog.rdoc
CHANGED
@@ -1,21 +1,12 @@
|
|
1
1
|
= BinData Changelog
|
2
2
|
|
3
|
-
== Version
|
4
|
-
|
5
|
-
* #eval_parameters can now call private methods. Requested by Ole Rasmussen.
|
6
|
-
* Can now determine state of :onlyif fields. Requested by Ole Rasmussen.
|
7
|
-
* Renamed #offset to #abs_offset for clarity. #offset is now deprecated.
|
8
|
-
* Support :byte_align for fields in structs. Requested by Igor Yamolov.
|
9
|
-
* Added bit fields with dynamic length. Requested by Jacob Dam.
|
10
|
-
|
11
|
-
== Version 1.8.2 (2014-02-02)
|
12
|
-
|
13
|
-
* Virtual fields can now have values.
|
14
|
-
* Bug fixes.
|
15
|
-
|
16
|
-
== Version 1.8.1 (2014-01-15)
|
3
|
+
== Version 2.0.0 (2014-02-02)
|
17
4
|
|
5
|
+
* Ruby 1.8 now has its own separate branch.
|
6
|
+
* Struct now uses symbols for field names instead of strings.
|
18
7
|
* Added signed bitfields. Requested by redood.
|
8
|
+
* Virtual fields can now have names.
|
9
|
+
* Bug fixes.
|
19
10
|
|
20
11
|
== Version 1.8.0 (2014-01-06)
|
21
12
|
|
data/INSTALL
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
This package is designed to be installed with rubygems.
|
2
|
-
have rubygems installed on your system, the older setup.rb is
|
3
|
-
included as a convenience.
|
1
|
+
This package is designed to be installed with rubygems.
|
4
2
|
|
5
|
-
|
6
|
-
# ruby setup.rb
|
3
|
+
$ gem install bindata
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
If you are using ruby 1.8
|
6
|
+
|
7
|
+
$ gem install bindata -v '~> 1.8.0'
|
8
|
+
|
9
|
+
If you are not using rubygems, you may like to install BinData with
|
10
|
+
Minero Aoki's setup.rb found at:
|
11
|
+
|
12
|
+
https://github.com/rubyworks/setup
|
data/NEWS.rdoc
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
= 2.0.0
|
2
|
+
|
3
|
+
BinData 2.0.0 requires ruby 1.9 or greater. Support for ruby 1.8 is found in
|
4
|
+
BinData versions 1.8.x.
|
5
|
+
|
6
|
+
Prior to version 2.0.0, BinData used the Ruby 1.8 conversion of strings for
|
7
|
+
method names. As of 2.0.0, BinData uses symbols.
|
8
|
+
|
9
|
+
class A < BinData::Record
|
10
|
+
uint8 :a
|
11
|
+
uint8 :b
|
12
|
+
end
|
13
|
+
|
14
|
+
# BinData 1.8.x
|
15
|
+
A.read "\001\002" #=> {"a"=>1, "b"=>2}
|
16
|
+
|
17
|
+
# BinData >= 2.0.0
|
18
|
+
A.read "\001\002" #=> {:a=>1, :b=>2}
|
19
|
+
|
1
20
|
= 1.6.0
|
2
21
|
|
3
22
|
Added :assert as a replacement for :check_value. Note that :assert performs
|
data/README.md
CHANGED
@@ -43,18 +43,14 @@ for dependent and variable length fields is built in.
|
|
43
43
|
|
44
44
|
$ gem install bindata
|
45
45
|
|
46
|
-
|
46
|
+
or if running ruby 1.8
|
47
47
|
|
48
|
-
$
|
48
|
+
$ gem install bindata -v '~> 1.8.0'
|
49
49
|
|
50
50
|
# Documentation
|
51
51
|
|
52
52
|
[Read the wiki](http://github.com/dmendel/bindata/wiki).
|
53
53
|
|
54
|
-
-or-
|
55
|
-
|
56
|
-
$ rake manual
|
57
|
-
|
58
54
|
# Contact
|
59
55
|
|
60
56
|
If you have any queries / bug reports / suggestions, please contact me
|
data/Rakefile
CHANGED
data/bindata.gemspec
CHANGED
@@ -19,9 +19,6 @@ Gem::Specification.new do |s|
|
|
19
19
|
|
20
20
|
s.add_development_dependency('rake')
|
21
21
|
s.add_development_dependency('minitest', "> 5.0.0")
|
22
|
-
s.add_development_dependency('haml', ["< 4.0.0"])
|
23
|
-
s.add_development_dependency('maruku')
|
24
|
-
s.add_development_dependency('syntax')
|
25
22
|
s.description = <<-END.gsub(/^ +/, "")
|
26
23
|
BinData is a declarative way to read and write binary file formats.
|
27
24
|
|
data/examples/gzip.rb
CHANGED
@@ -1,115 +1,65 @@
|
|
1
1
|
require 'bindata'
|
2
|
-
require '
|
2
|
+
require 'zlib'
|
3
3
|
|
4
4
|
# An example of a reader / writer for the GZIP file format as per rfc1952.
|
5
|
-
#
|
6
|
-
class Gzip
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
uint16 :len, :length => lambda { data.length }
|
16
|
-
string :data, :read_length => :len
|
17
|
-
end
|
18
|
-
|
19
|
-
class Header < BinData::Record
|
20
|
-
endian :little
|
21
|
-
|
22
|
-
uint16 :ident, :asserted_value => 0x8b1f
|
23
|
-
uint8 :compression_method, :initial_value => DEFLATE
|
24
|
-
|
25
|
-
bit3 :freserved, :asserted_value => 0
|
26
|
-
bit1 :fcomment, :value => lambda { comment.length > 0 ? 1 : 0 }
|
27
|
-
bit1 :ffile_name, :value => lambda { file_name.length > 0 ? 1 : 0 }
|
28
|
-
bit1 :fextra, :value => lambda { extra.len > 0 ? 1 : 0 }
|
29
|
-
bit1 :fcrc16, :value => 0 # see comment below
|
30
|
-
bit1 :ftext
|
31
|
-
|
32
|
-
# Never include header crc. This is because the current versions of the
|
33
|
-
# command-line version of gzip (up through version 1.3.x) do not
|
34
|
-
# support header crc's, and will report that it is a "multi-part gzip
|
35
|
-
# file" and give up.
|
36
|
-
|
37
|
-
uint32 :mtime
|
38
|
-
uint8 :extra_flags
|
39
|
-
uint8 :os, :initial_value => 255 # unknown OS
|
40
|
-
|
41
|
-
# These fields are optional depending on the bits in flags
|
42
|
-
extra :extra, :onlyif => lambda { fextra.nonzero? }
|
43
|
-
stringz :file_name, :onlyif => lambda { ffile_name.nonzero? }
|
44
|
-
stringz :comment, :onlyif => lambda { fcomment.nonzero? }
|
45
|
-
uint16 :crc16, :onlyif => lambda { fcrc16.nonzero? }
|
46
|
-
end
|
47
|
-
|
48
|
-
class Footer < BinData::Record
|
49
|
-
endian :little
|
5
|
+
# See notes at the end of this file for implementation discussions.
|
6
|
+
class Gzip < BinData::Record
|
7
|
+
# Binary representation of a ruby Time object
|
8
|
+
class Mtime < BinData::Primitive
|
9
|
+
uint32le :time
|
10
|
+
|
11
|
+
def set(val)
|
12
|
+
self.time = val.to_i
|
13
|
+
end
|
50
14
|
|
51
|
-
|
52
|
-
|
15
|
+
def get
|
16
|
+
Time.at(time)
|
17
|
+
end
|
53
18
|
end
|
54
19
|
|
55
|
-
|
56
|
-
|
57
|
-
@footer = Footer.new
|
58
|
-
end
|
20
|
+
# Known compression methods
|
21
|
+
DEFLATE = 8
|
59
22
|
|
60
|
-
|
61
|
-
def_delegators :@header, :file_name=, :file_name
|
62
|
-
def_delegators :@header, :comment=, :comment, :comment?
|
63
|
-
def_delegators :@header, :compression_method
|
64
|
-
def_delegators :@footer, :crc32, :uncompressed_size
|
23
|
+
endian :little
|
65
24
|
|
66
|
-
|
67
|
-
|
68
|
-
end
|
25
|
+
uint16 :ident, :asserted_value => 0x8b1f
|
26
|
+
uint8 :compression_method, :initial_value => DEFLATE
|
69
27
|
|
70
|
-
|
71
|
-
|
72
|
-
|
28
|
+
bit3 :freserved, :asserted_value => 0
|
29
|
+
bit1 :fcomment, :value => lambda { comment.length > 0 ? 1 : 0 }
|
30
|
+
bit1 :ffile_name, :value => lambda { file_name.length > 0 ? 1 : 0 }
|
31
|
+
bit1 :fextra, :value => lambda { extra.len > 0 ? 1 : 0 }
|
32
|
+
bit1 :fcrc16, :value => 0 # see note at end of file
|
33
|
+
bit1 :ftext
|
73
34
|
|
74
|
-
|
75
|
-
|
76
|
-
|
35
|
+
mtime :mtime
|
36
|
+
uint8 :extra_flags
|
37
|
+
uint8 :os, :initial_value => 255 # unknown OS
|
77
38
|
|
78
|
-
|
79
|
-
@compressed
|
80
|
-
end
|
39
|
+
# The following fields are optional depending on the bits in flags
|
81
40
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
@footer.uncompressed_size = uncompressed_size
|
41
|
+
struct :extra, :onlyif => lambda { fextra.nonzero? } do
|
42
|
+
uint16 :len, :length => lambda { data.length }
|
43
|
+
string :data, :read_length => :len
|
86
44
|
end
|
45
|
+
stringz :file_name, :onlyif => lambda { ffile_name.nonzero? }
|
46
|
+
stringz :comment, :onlyif => lambda { fcomment.nonzero? }
|
47
|
+
uint16 :crc16, :onlyif => lambda { fcrc16.nonzero? }
|
87
48
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
# Determine the size of the compressed data. This is needed because
|
93
|
-
# we don't actually uncompress the data. Ideally the uncompression
|
94
|
-
# method would read the correct number of bytes from the IO and the
|
95
|
-
# IO would be positioned ready to read the footer.
|
49
|
+
# The length of compressed data must be calculated from the current file offset
|
50
|
+
count_bytes_remaining :bytes_remaining
|
51
|
+
string :compressed_data, :read_length => lambda { bytes_remaining - footer.num_bytes }
|
96
52
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
io.seek(pos)
|
101
|
-
|
102
|
-
@compressed = io.read(compressed_size)
|
103
|
-
@footer.read(io)
|
104
|
-
end
|
53
|
+
struct :footer do
|
54
|
+
uint32 :crc32
|
55
|
+
uint32 :uncompressed_size
|
105
56
|
end
|
106
57
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
58
|
+
def data=(data)
|
59
|
+
# Zlib.deflate includes a header + footer which we must discard
|
60
|
+
self.compressed_data = Zlib::Deflate.deflate(data)[2..-5]
|
61
|
+
self.footer.crc32 = Zlib::crc32(data)
|
62
|
+
self.footer.uncompressed_size = data.size
|
113
63
|
end
|
114
64
|
end
|
115
65
|
|
@@ -117,28 +67,30 @@ if __FILE__ == $0
|
|
117
67
|
# Write a gzip file.
|
118
68
|
print "Creating a gzip file ... "
|
119
69
|
g = Gzip.new
|
120
|
-
|
121
|
-
g.set_compressed_data("+\311HUHN,Q(\006\342\374<\205\022 77\261\004\000",
|
122
|
-
3464689835, 22)
|
70
|
+
g.data = "the cat sat on the mat"
|
123
71
|
g.file_name = "poetry"
|
124
72
|
g.mtime = Time.now
|
125
73
|
g.comment = "A stunning piece of prose"
|
126
|
-
|
74
|
+
File.open("poetry.gz", "w") do |io|
|
75
|
+
g.write(io)
|
76
|
+
end
|
127
77
|
puts "done."
|
128
78
|
puts
|
129
79
|
|
130
80
|
# Read the created gzip file.
|
131
81
|
print "Reading newly created gzip file ... "
|
132
82
|
g = Gzip.new
|
133
|
-
|
83
|
+
File.open("poetry.gz", "r") do |io|
|
84
|
+
g.read(io)
|
85
|
+
end
|
134
86
|
puts "done."
|
135
87
|
puts
|
136
88
|
|
137
89
|
puts "Printing gzip file details in the format of gzip -l -v"
|
138
90
|
|
139
91
|
# compression ratio
|
140
|
-
ratio = 100.0 * (g.uncompressed_size - g.
|
141
|
-
g.uncompressed_size
|
92
|
+
ratio = 100.0 * (g.footer.uncompressed_size - g.compressed_data.size) /
|
93
|
+
g.footer.uncompressed_size
|
142
94
|
|
143
95
|
comp_meth = (g.compression_method == Gzip::DEFLATE) ? "defla" : ""
|
144
96
|
|
@@ -146,16 +98,28 @@ if __FILE__ == $0
|
|
146
98
|
puts "method crc date time compressed " +
|
147
99
|
"uncompressed ratio uncompressed_name"
|
148
100
|
puts "%5s %08x %6s %5s %19s %19s %5.1f%% %s" % [comp_meth,
|
149
|
-
g.crc32,
|
101
|
+
g.footer.crc32,
|
150
102
|
g.mtime.strftime('%b %d'),
|
151
103
|
g.mtime.strftime('%H:%M'),
|
152
|
-
g.
|
153
|
-
g.uncompressed_size,
|
104
|
+
g.num_bytes,
|
105
|
+
g.footer.uncompressed_size,
|
154
106
|
ratio,
|
155
107
|
g.file_name]
|
156
|
-
puts "Comment: #{g.comment}" if g.comment
|
108
|
+
puts "Comment: #{g.comment}" if g.comment != ""
|
157
109
|
puts
|
158
110
|
|
159
111
|
puts "Executing gzip -l -v"
|
160
112
|
puts `gzip -l -v poetry.gz`
|
161
113
|
end
|
114
|
+
|
115
|
+
# Notes:
|
116
|
+
#
|
117
|
+
# Mtime: A convenience wrapper that allow a ruby Time object to be used instead
|
118
|
+
# of manually dealing with the raw form (seconds since 1 Jan 1970)
|
119
|
+
#
|
120
|
+
# rfc1952 specifies an optional crc16 field. The gzip command line client
|
121
|
+
# uses this field for multi-part gzip. Hence we ignore this.
|
122
|
+
|
123
|
+
# We are cheating and using the Zlib library for compression. We can't use
|
124
|
+
# this library for decompression as zlib requires an adler32 checksum while
|
125
|
+
# gzip uses crc32.
|
data/examples/tcp_ip.rb
CHANGED
@@ -39,8 +39,6 @@ end
|
|
39
39
|
|
40
40
|
# TCP Protocol Data Unit
|
41
41
|
class TCP_PDU < BinData::Record
|
42
|
-
mandatory_parameter :packet_length
|
43
|
-
|
44
42
|
endian :big
|
45
43
|
|
46
44
|
uint16 :src_port
|
@@ -60,7 +58,7 @@ class TCP_PDU < BinData::Record
|
|
60
58
|
uint16 :checksum
|
61
59
|
uint16 :urg_ptr
|
62
60
|
string :options, :read_length => :options_length_in_bytes
|
63
|
-
|
61
|
+
rest :payload
|
64
62
|
|
65
63
|
def options_length_in_bytes
|
66
64
|
(doff - 5 ) * 4
|
@@ -69,15 +67,13 @@ end
|
|
69
67
|
|
70
68
|
# UDP Protocol Data Unit
|
71
69
|
class UDP_PDU < BinData::Record
|
72
|
-
mandatory_parameter :packet_length
|
73
|
-
|
74
70
|
endian :big
|
75
71
|
|
76
72
|
uint16 :src_port
|
77
73
|
uint16 :dst_port
|
78
74
|
uint16 :len
|
79
75
|
uint16 :checksum
|
80
|
-
|
76
|
+
rest :payload
|
81
77
|
end
|
82
78
|
|
83
79
|
# IP Protocol Data Unit
|
@@ -97,10 +93,12 @@ class IP_PDU < BinData::Record
|
|
97
93
|
ip_addr :src_addr
|
98
94
|
ip_addr :dest_addr
|
99
95
|
string :options, :read_length => :options_length_in_bytes
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
96
|
+
buffer :payload, :length => :payload_length_in_bytes do
|
97
|
+
choice :payload, :selection => :protocol do
|
98
|
+
tcp_pdu 6
|
99
|
+
udp_pdu 17
|
100
|
+
rest :default
|
101
|
+
end
|
104
102
|
end
|
105
103
|
|
106
104
|
def header_length_in_bytes
|
data/lib/bindata.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# BinData -- Binary data manipulator.
|
2
2
|
# Copyright (c) 2007 - 2014 Dion Mendel.
|
3
3
|
|
4
|
+
if RUBY_VERSION <= "1.9"
|
5
|
+
fail "BinData requires ruby >= 1.9.3. Use BinData version 1.8.x instead"
|
6
|
+
end
|
7
|
+
|
4
8
|
require 'bindata/version'
|
5
9
|
require 'bindata/array'
|
6
10
|
require 'bindata/bits'
|
data/lib/bindata/base.rb
CHANGED
@@ -233,17 +233,16 @@ module BinData
|
|
233
233
|
end
|
234
234
|
end
|
235
235
|
|
236
|
-
# Returns the offset
|
237
|
-
|
238
|
-
def abs_offset
|
236
|
+
# Returns the offset of this object wrt to its most distant ancestor.
|
237
|
+
def offset
|
239
238
|
if @parent
|
240
|
-
@parent.
|
239
|
+
@parent.offset + @parent.offset_of(self)
|
241
240
|
else
|
242
241
|
0
|
243
242
|
end
|
244
243
|
end
|
245
244
|
|
246
|
-
# Returns the offset
|
245
|
+
# Returns the offset of this object wrt to its parent.
|
247
246
|
def rel_offset
|
248
247
|
if @parent
|
249
248
|
@parent.offset_of(self)
|
@@ -282,11 +281,7 @@ module BinData
|
|
282
281
|
end
|
283
282
|
|
284
283
|
def binary_string(str)
|
285
|
-
|
286
|
-
str.to_s.dup.force_encoding(Encoding::BINARY)
|
287
|
-
else
|
288
|
-
str.dup
|
289
|
-
end
|
284
|
+
str.to_s.dup.force_encoding(Encoding::BINARY)
|
290
285
|
end
|
291
286
|
end
|
292
287
|
end
|