ruby-ole 1.2.7 → 1.2.8

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/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ == 1.2.8 / 2008-10-08
2
+
3
+ - check in the new fixes to the mbat support.
4
+ - update README to be a bit more useful.
5
+
1
6
  == 1.2.7 / 2008-08-12
2
7
 
3
8
  - Prepare Ole::Types::PropertySet for write support.
data/README CHANGED
@@ -1,22 +1,104 @@
1
1
  = Introduction
2
2
 
3
- For now, see the docs for the Ole::Storage class.
3
+ The ruby-ole library provides a variety of functions primarily for
4
+ working with OLE2 structured storage files, such as those produced by
5
+ Microsoft Office - eg *.doc, *.msg etc.
6
+
7
+ = Example Usage
8
+
9
+ Here are some examples of how to use the library functionality,
10
+ categorised roughly by purpose.
11
+
12
+ 1. Reading and writing files within an OLE container
13
+
14
+ The recommended way to manipulate the contents is via the
15
+ "file_system" API, whereby you use Ole::Storage instance methods
16
+ similar to the regular File and Dir class methods.
17
+
18
+ ole = Ole::Storage.open('oleWithDirs.ole', 'rb+')
19
+ p ole.dir.entries('.') # => [".", "..", "dir1", "dir2", "file1"]
20
+ p ole.file.read('file1')[0, 25] # => "this is the entry 'file1'"
21
+ ole.dir.mkdir('newdir')
22
+
23
+ 2. Accessing OLE meta data
24
+
25
+ Some convenience functions are provided for (currently read only)
26
+ access to OLE property sets and other sources of meta data.
27
+
28
+ ole = Ole::Storage.open('test_word_95.doc')
29
+ p ole.meta_data.file_format # => "MSWordDoc"
30
+ p ole.meta_data.mime_type # => "application/msword"
31
+ p ole.meta_data.doc_author.split.first # => "Charles"
32
+
33
+ 3. Raw access to underlying OLE internals
34
+
35
+ This is probably of little interest to most developers using the
36
+ library, but for some use cases you may need to drop down to the
37
+ lower level API on which the "file_system" API is constructed,
38
+ which exposes more of the format details.
39
+
40
+ <tt>Ole::Storage</tt> files can have multiple files with the same name,
41
+ or with a slash in the name, and other things that are probably
42
+ strictly invalid. This API is the only way to access those files.
43
+
44
+ You can access the header object directly:
45
+
46
+ p ole.header.num_sbat # => 1
47
+ p ole.header.magic.unpack('H*') # => ["d0cf11e0a1b11ae1"]
48
+
49
+ You can directly access the array of all Dirent objects,
50
+ including the root:
51
+
52
+ p ole.dirents.length # => 5
53
+ puts ole.root.to_tree
54
+ # =>
55
+ - #<Dirent:"Root Entry">
56
+ |- #<Dirent:"\001Ole" size=20 data="\001\000\000\002\000...">
57
+ |- #<Dirent:"\001CompObj" size=98 data="\001\000\376\377\003...">
58
+ |- #<Dirent:"WordDocument" size=2574 data="\334\245e\000-...">
59
+ \- #<Dirent:"\005SummaryInformation" size=54788 data="\376\377\000\000\001...">
60
+
61
+ You can access (through RangesIO methods, or by using the
62
+ relevant Dirent and AllocationTable methods) information like where within
63
+ the container a stream is located (these are offset/length pairs):
64
+
65
+ p ole.root["\001CompObj"].open { |io| io.ranges } # => [[0, 64], [64, 34]]
66
+
67
+ See the documentation for each class for more details.
68
+
69
+ = Thanks
70
+
71
+ * The code contained in this project was initially based on chicago's libole
72
+ (source available at http://prdownloads.sf.net/chicago/ole.tgz).
73
+
74
+ * It was later augmented with some corrections by inspecting pole, and (purely
75
+ for header definitions) gsf.
76
+
77
+ * The property set parsing code came from the apache java project POIFS.
78
+
79
+ * The excellent idea for using a pseudo file system style interface by providing
80
+ #file and #dir methods which mimic File and Dir, was borrowed (along with almost
81
+ unchanged tests!) from Thomas Sondergaard's rubyzip.
4
82
 
5
83
  = TODO
6
84
 
7
- == 1.2.8
85
+ == 1.2.9
8
86
 
9
- * fix property sets a bit more. see TODO in Ole::Storage::MetaData
87
+ * add buffering to rangesio so that performance for small reads and writes
88
+ isn't so awful. maybe try and remove the bottlenecks of unbuffered first
89
+ with more profiling, then implement the buffering on top of that.
10
90
  * fix mode strings - like truncate when using 'w+', supporting append
11
91
  'a+' modes etc. done?
12
92
  * make ranges io obey readable vs writeable modes.
13
93
  * more RangesIO completion. ie, doesn't support #<< at the moment.
14
- * ability to zero out padding and unused blocks
15
- * case insensitive mode for ole/file_system?
16
94
 
17
95
  == 1.3.1
18
96
 
19
- * fix this README :). maybe move todo out, and put something useful here.
97
+ * fix property sets a bit more. see TODO in Ole::Storage::MetaData
98
+ * ability to zero out padding and unused blocks
99
+ * case insensitive mode for ole/file_system?
100
+ * better tests for mbat support.
101
+ * further doc cleanup
20
102
 
21
103
  == Longer term
22
104
 
@@ -25,3 +107,4 @@ For now, see the docs for the Ole::Storage class.
25
107
  ole implementations (maybe perl's, and poifs) just to check its in the
26
108
  ballpark, with no remaining silly bottlenecks.
27
109
  * supposedly vba does something weird to ole files. test that.
110
+
File without changes
@@ -217,8 +217,9 @@ end
217
217
  # this subclass of ranges io explicitly ignores the truncate part of 'w' modes.
218
218
  # only really needed for the allocation table writes etc. maybe just use explicit modes
219
219
  # for those
220
- # better yet write a test that breaks before I fix it.
221
- class RangesIONonResizeable < RangesIO
220
+ # better yet write a test that breaks before I fix it. added nodoc for the
221
+ # time being.
222
+ class RangesIONonResizeable < RangesIO # :nodoc:
222
223
  def initialize io, mode='r', params={}
223
224
  mode, params = 'r', mode if Hash === mode
224
225
  flags = IO::Mode.new(mode).flags & ~IO::TRUNC
@@ -5,54 +5,8 @@ require 'ole/types'
5
5
  require 'ole/ranges_io'
6
6
 
7
7
  module Ole # :nodoc:
8
- #
9
- # = Introduction
10
8
  #
11
- # <tt>Ole::Storage</tt> is a class intended to abstract away details of the
12
- # access to OLE2 structured storage files, such as those produced by
13
- # Microsoft Office, eg *.doc, *.msg etc.
14
- #
15
- # = Usage
16
- #
17
- # Usage should be fairly straight forward:
18
- #
19
- # # get the parent ole storage object
20
- # ole = Ole::Storage.open 'myfile.msg', 'r+'
21
- # # => #<Ole::Storage io=#<File:myfile.msg> root=#<Dirent:"Root Entry">>
22
- # # read some data
23
- # ole.root[1].read 4
24
- # # => "\001\000\376\377"
25
- # # get the top level root object and output a tree structure for
26
- # # debugging
27
- # puts ole.root.to_tree
28
- # # =>
29
- # - #<Dirent:"Root Entry" size=3840 time="2006-11-03T00:52:53Z">
30
- # |- #<Dirent:"__nameid_version1.0" size=0 time="2006-11-03T00:52:53Z">
31
- # | |- #<Dirent:"__substg1.0_00020102" size=16 data="CCAGAAAAAADAAA...">
32
- # ...
33
- # |- #<Dirent:"__substg1.0_8002001E" size=4 data="MTEuMA==">
34
- # |- #<Dirent:"__properties_version1.0" size=800 data="AAAAAAAAAAABAA...">
35
- # \- #<Dirent:"__recip_version1.0_#00000000" size=0 time="2006-11-03T00:52:53Z">
36
- # |- #<Dirent:"__substg1.0_0FF60102" size=4 data="AAAAAA==">
37
- # ...
38
- # # write some data, and finish up (note that open is 'r+', so this overwrites
39
- # # but doesn't truncate)
40
- # ole.root["\001CompObj"].open { |f| f.write "blah blah" }
41
- # ole.close
42
- #
43
- # = Thanks
44
- #
45
- # * The code contained in this project was initially based on chicago's libole
46
- # (source available at http://prdownloads.sf.net/chicago/ole.tgz).
47
- #
48
- # * It was later augmented with some corrections by inspecting pole, and (purely
49
- # for header definitions) gsf.
50
- #
51
- # * The property set parsing code came from the apache java project POIFS.
52
- #
53
- # * The excellent idea for using a pseudo file system style interface by providing
54
- # #file and #dir methods which mimic File and Dir, was borrowed (along with almost
55
- # unchanged tests!) from Thomas Sondergaard's rubyzip.
9
+ # This class is the primary way the user interacts with an OLE storage file.
56
10
  #
57
11
  # = TODO
58
12
  #
@@ -67,7 +21,7 @@ module Ole # :nodoc:
67
21
  class FormatError < StandardError # :nodoc:
68
22
  end
69
23
 
70
- VERSION = '1.2.7'
24
+ VERSION = '1.2.8'
71
25
 
72
26
  # options used at creation time
73
27
  attr_reader :params
@@ -81,8 +35,8 @@ module Ole # :nodoc:
81
35
  # Low level internals, you probably shouldn't need to mess with these
82
36
  attr_reader :header, :bbat, :sbat, :sb_file
83
37
 
84
- # maybe include an option hash, and allow :close_parent => true, to be more general.
85
- # +arg+ should be either a file, or an +IO+ object, and needs to be seekable.
38
+ # +arg+ should be either a filename, or an +IO+ object, and needs to be seekable.
39
+ # +mode+ is optional, and should be a regular mode string.
86
40
  def initialize arg, mode=nil, params={}
87
41
  params, mode = mode, nil if Hash === mode
88
42
  params = {:update_timestamps => true}.merge(params)
@@ -118,6 +72,8 @@ module Ole # :nodoc:
118
72
  @io.size > 0 ? load : clear
119
73
  end
120
74
 
75
+ # somewhat similar to File.open, the open class method allows a block form where
76
+ # the Ole::Storage object is automatically closed on completion of the block.
121
77
  def self.open arg, mode=nil, params={}
122
78
  ole = new arg, mode, params
123
79
  if block_given?
@@ -150,8 +106,13 @@ module Ole # :nodoc:
150
106
 
151
107
  # create an empty bbat.
152
108
  @bbat = AllocationTable::Big.new self
153
- mbat_blocks = (0...@header.num_mbat).map { |i| i + @header.mbat_start }
154
- bbat_chain = (header_block[Header::SIZE..-1] + @bbat.read(mbat_blocks)).unpack 'V*'
109
+ bbat_chain = header_block[Header::SIZE..-1].unpack 'V*'
110
+ mbat_block = @header.mbat_start
111
+ @header.num_mbat.times do
112
+ blocks = @bbat.read([mbat_block]).unpack 'V*'
113
+ mbat_block = blocks.pop
114
+ bbat_chain += blocks
115
+ end
155
116
  # am i using num_bat in the right way?
156
117
  @bbat.load @bbat.read(bbat_chain[0, @header.num_bat])
157
118
 
@@ -268,7 +229,7 @@ module Ole # :nodoc:
268
229
  # mbat must remain contiguous.
269
230
  bbat_data_len = ((@bbat.length + num_mbat_blocks) * 4 / @bbat.block_size.to_f).ceil * @bbat.block_size
270
231
  # now storing the excess mbat blocks also increases the size of the bbat:
271
- new_num_mbat_blocks = ([bbat_data_len / @bbat.block_size - 109, 0].max * 4 / @bbat.block_size.to_f).ceil
232
+ new_num_mbat_blocks = ([bbat_data_len / @bbat.block_size - 109, 0].max * 4 / (@bbat.block_size.to_f - 4)).ceil
272
233
  if new_num_mbat_blocks != num_mbat_blocks
273
234
  # need more space for the mbat.
274
235
  num_mbat_blocks = new_num_mbat_blocks
@@ -284,13 +245,16 @@ module Ole # :nodoc:
284
245
  # now extract the info we want:
285
246
  ranges = io.ranges
286
247
  bbat_chain = @bbat.chain io.first_block
287
- # the extra mbat data is a set of contiguous blocks at the end
288
248
  io.close
289
249
  bbat_chain.each { |b| @bbat[b] = AllocationTable::BAT }
290
250
  # tack on the mbat stuff
291
- @header.mbat_start = @bbat.length # need to record this here before tacking on the mbat
292
251
  @header.num_bat = bbat_chain.length
293
- num_mbat_blocks.times { @bbat << AllocationTable::META_BAT }
252
+ mbat_blocks = (0...num_mbat_blocks).map do
253
+ block = @bbat.free_block
254
+ @bbat[block] = AllocationTable::META_BAT
255
+ block
256
+ end
257
+ @header.mbat_start = mbat_blocks.first || AllocationTable::EOC
294
258
 
295
259
  # now finally write the bbat, using a not resizable io.
296
260
  # the mode here will be 'r', which allows write atm.
@@ -299,15 +263,17 @@ module Ole # :nodoc:
299
263
  # this is the mbat. pad it out.
300
264
  bbat_chain += [AllocationTable::AVAIL] * [109 - bbat_chain.length, 0].max
301
265
  @header.num_mbat = num_mbat_blocks
302
- if num_mbat_blocks == 0
303
- @header.mbat_start = AllocationTable::EOC
304
- else
266
+ if num_mbat_blocks != 0
305
267
  # write out the mbat blocks now. first of all, where are they going to be?
306
268
  mbat_data = bbat_chain[109..-1]
307
- q = @bbat.block_size / 4
308
- mbat_data += [AllocationTable::AVAIL] *((mbat_data.length / q.to_f).ceil * q - mbat_data.length)
309
- ranges = @bbat.ranges((0...num_mbat_blocks).map { |i| @header.mbat_start + i })
310
- RangesIO.open(@io, :ranges => ranges) { |f| f.write mbat_data.pack('V*') }
269
+ # expand the mbat_data to include the linked list forward pointers.
270
+ mbat_data = mbat_data.to_enum(:each_slice, @bbat.block_size / 4 - 1).to_a.
271
+ zip(mbat_blocks[1..-1] + [nil]).map { |a, b| b ? a + [b] : a }
272
+ # pad out the last one.
273
+ mbat_data.last.push(*([AllocationTable::AVAIL] * (@bbat.block_size / 4 - mbat_data.last.length)))
274
+ RangesIO.open @io, :ranges => @bbat.ranges(mbat_blocks) do |f|
275
+ f.write mbat_data.flatten.pack('V*')
276
+ end
311
277
  end
312
278
 
313
279
  # now seek back and write the header out
@@ -561,7 +527,7 @@ module Ole # :nodoc:
561
527
  length - 1
562
528
  end
563
529
 
564
- # must return first_block
530
+ # must return first_block. modifies +blocks+ in place
565
531
  def resize_chain blocks, size
566
532
  new_num_blocks = (size / block_size.to_f).ceil
567
533
  old_num_blocks = blocks.length
@@ -3,32 +3,11 @@
3
3
  #
4
4
  # This file intends to provide file system-like api support, a la <tt>zip/zipfilesystem</tt>.
5
5
  #
6
- # Ideally, this will be the recommended interface, allowing Ole::Storage, Dir, and
7
- # Zip::ZipFile to be used exchangably. It should be possible to write recursive copy using
8
- # the plain api, such that you can copy dirs/files agnostically between any of ole docs, dirs,
9
- # and zip files.
10
- #
11
- # = Usage
12
- #
13
- # Currently you can do something like the following:
14
- #
15
- # Ole::Storage.open 'test.doc' do |ole|
16
- # ole.dir.entries '/' # => [".", "..", "\001Ole", "1Table", "\001CompObj", ...]
17
- # ole.file.read "\001CompObj" # => "\001\000\376\377\003\n\000\000\377\377..."
18
- # end
19
- #
20
- # = Notes
21
- #
22
- # <tt>Ole::Storage</tt> files can have multiple files with the same name,
23
- # or with / in the name, and other things that are probably invalid anyway.
24
- # This API is unable to access those files, but of course the core, low-
25
- # level API can.
26
- #
27
- # need to implement some more IO functions on RangesIO, like #puts, #print
28
- # etc, like AbstractOutputStream from zipfile.
29
- #
30
6
  # = TODO
31
7
  #
8
+ # - need to implement some more IO functions on RangesIO, like #puts, #print
9
+ # etc, like AbstractOutputStream from zipfile.
10
+ #
32
11
  # - check Dir.mkdir, and File.open, and File.rename, to add in filename
33
12
  # length checks (max 32 / 31 or something).
34
13
  # do the automatic truncation, and add in any necessary warnings.
@@ -1,6 +1,6 @@
1
1
  require 'ole/types/property_set'
2
2
 
3
- module Ole
3
+ module Ole
4
4
  class Storage
5
5
  #
6
6
  # The MetaData class is designed to be high level interface to all the
@@ -35,33 +35,37 @@ module Ole
35
35
  FORMAT_MAP = {
36
36
  'MSWordDoc' => :doc
37
37
  }
38
-
38
+
39
39
  CLSID_EXCEL97 = Types::Clsid.parse "{00020820-0000-0000-c000-000000000046}"
40
40
  CLSID_EXCEL95 = Types::Clsid.parse "{00020810-0000-0000-c000-000000000046}"
41
41
  CLSID_WORD97 = Types::Clsid.parse "{00020906-0000-0000-c000-000000000046}"
42
42
  CLSID_WORD95 = Types::Clsid.parse "{00020900-0000-0000-c000-000000000046}"
43
-
44
- CLSID_MAP = {
45
- CLSID_EXCEL97 => :xls,
46
- CLSID_EXCEL95 => :xls,
47
- CLSID_WORD97 => :doc,
48
- CLSID_WORD95 => :doc
49
- }
43
+
44
+ CLSID_MAP = {
45
+ CLSID_EXCEL97 => :xls,
46
+ CLSID_EXCEL95 => :xls,
47
+ CLSID_WORD97 => :doc,
48
+ CLSID_WORD95 => :doc
49
+ }
50
50
 
51
51
  MIME_TYPES = {
52
52
  :xls => 'application/vnd.ms-excel',
53
53
  :doc => 'application/msword',
54
54
  :ppt => 'application/vnd.ms-powerpoint',
55
- :msg => 'application/vnd.ms-outlook' # not registered at IANA, but sdeems most common usage
55
+ # not registered at IANA, but seems most common usage
56
+ :msg => 'application/vnd.ms-outlook',
57
+ # this is my default fallback option. also not registered at IANA.
58
+ # file(1)'s default is application/msword, which is useless...
59
+ nil => 'application/x-ole-storage'
56
60
  }
57
-
61
+
58
62
  def initialize ole
59
63
  @ole = ole
60
64
  end
61
65
 
62
66
  # i'm thinking of making file_format and mime_type available through
63
67
  # #[], #each, and #to_h also, as calculated meta data (not assignable)
64
-
68
+
65
69
  def comp_obj
66
70
  return {} unless dirent = @ole.root["\001CompObj"]
67
71
  data = dirent.read
@@ -70,7 +74,7 @@ module Ole
70
74
  # byte_order: 0xffe
71
75
  # windows_version: 0x00000a03 (win31 apparently)
72
76
  # marker: 0xffffffff
73
- compobj_version, byte_order, windows_version, marker, clsid =
77
+ compobj_version, byte_order, windows_version, marker, clsid =
74
78
  data.unpack("vvVVa#{Types::Clsid::SIZE}")
75
79
  strings = []
76
80
  i = 28
@@ -84,7 +88,7 @@ module Ole
84
88
  {:username => strings[0], :file_format => strings[1], :unknown => strings[2..-1]}
85
89
  end
86
90
  private :comp_obj
87
-
91
+
88
92
  def file_format
89
93
  comp_obj[:file_format]
90
94
  end
@@ -93,7 +97,7 @@ module Ole
93
97
  # based on the CompObj stream contents
94
98
  type = FORMAT_MAP[file_format]
95
99
  return MIME_TYPES[type] if type
96
-
100
+
97
101
  # based on the root clsid
98
102
  type = CLSID_MAP[Types::Clsid.load(@ole.root.clsid)]
99
103
  return MIME_TYPES[type] if type
@@ -103,19 +107,21 @@ module Ole
103
107
  return MIME_TYPES[:msg] if has_file['__nameid_version1.0'] or has_file['__properties_version1.0']
104
108
  return MIME_TYPES[:doc] if has_file['worddocument'] or has_file['document']
105
109
  return MIME_TYPES[:xls] if has_file['workbook'] or has_file['book']
110
+
111
+ MIME_TYPES[nil]
106
112
  end
107
-
113
+
108
114
  def [] key
109
115
  pair = Types::PropertySet::PROPERTY_MAP[key.to_s] or return nil
110
116
  file = FILE_MAP[pair.first] or return nil
111
117
  dirent = @ole.root[file] or return nil
112
118
  dirent.open { |io| return Types::PropertySet.new(io)[key] }
113
119
  end
114
-
120
+
115
121
  def []= key, value
116
122
  raise NotImplementedError, 'meta data writes not implemented'
117
123
  end
118
-
124
+
119
125
  def each(&block)
120
126
  FILE_MAP.values.each do |file|
121
127
  dirent = @ole.root[file] or next
@@ -126,7 +132,7 @@ module Ole
126
132
  def to_h
127
133
  inject({}) { |hash, (name, value)| hash.update name.to_sym => value }
128
134
  end
129
-
135
+
130
136
  def method_missing name, *args, &block
131
137
  return super unless args.empty?
132
138
  pair = Types::PropertySet::PROPERTY_MAP[name.to_s] or return super
@@ -89,7 +89,7 @@ end
89
89
  # breadth first iteration holds its own copy of the children around.
90
90
  #
91
91
  # Main methods are #recursive, and #to_tree
92
- module RecursivelyEnumerable
92
+ module RecursivelyEnumerable # :nodoc:
93
93
  def each_recursive_depth_first(&block)
94
94
  each_child do |child|
95
95
  yield child
File without changes
File without changes
@@ -32,7 +32,7 @@ class TestMetaData < Test::Unit::TestCase
32
32
 
33
33
  ole.root.clsid = 0.chr * Ole::Types::Clsid::SIZE
34
34
  assert_equal nil, ole.meta_data.file_format
35
- assert_equal nil, ole.meta_data.mime_type
35
+ assert_equal 'application/x-ole-storage', ole.meta_data.mime_type
36
36
 
37
37
  ole.file.open('Book', 'w') { |f| }
38
38
  assert_equal 'application/vnd.ms-excel', ole.meta_data.mime_type
File without changes
File without changes
@@ -173,7 +173,8 @@ class TestStorageRead < Test::Unit::TestCase
173
173
 
174
174
  def test_dirent
175
175
  dirent = @ole.root.children.first
176
- assert_equal '#<Dirent:"\001Ole" size=20 data="\001\000\000\002\000...">', dirent.inspect
176
+ assert_equal "\001Ole", dirent.name
177
+ assert_equal 20, dirent.size
177
178
  assert_equal '#<Dirent:"Root Entry">', @ole.root.inspect
178
179
 
179
180
  # exercise Dirent#[]. note that if you use a number, you get the Struct
File without changes
File without changes
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-ole
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.7
5
- platform: ""
4
+ version: 1.2.8
5
+ platform: ruby
6
6
  authors:
7
7
  - Charles Lowe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-12 00:00:00 +10:00
12
+ date: 2008-10-08 00:00:00 +11:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -27,29 +27,29 @@ files:
27
27
  - ChangeLog
28
28
  - data/propids.yaml
29
29
  - bin/oletool
30
+ - lib/ole/support.rb
30
31
  - lib/ole/base.rb
32
+ - lib/ole/storage.rb
31
33
  - lib/ole/file_system.rb
32
34
  - lib/ole/ranges_io.rb
33
35
  - lib/ole/storage/base.rb
34
36
  - lib/ole/storage/file_system.rb
35
37
  - lib/ole/storage/meta_data.rb
36
- - lib/ole/storage.rb
37
- - lib/ole/support.rb
38
+ - lib/ole/types.rb
38
39
  - lib/ole/types/base.rb
39
40
  - lib/ole/types/property_set.rb
40
- - lib/ole/types.rb
41
+ - test/test_types.rb
41
42
  - test/test_filesystem.rb
42
- - test/test_mbat.rb
43
+ - test/test_support.rb
44
+ - test/test_storage.rb
43
45
  - test/test_meta_data.rb
44
- - test/test_property_set.rb
45
46
  - test/test_ranges_io.rb
46
- - test/test_storage.rb
47
- - test/test_support.rb
48
- - test/test_types.rb
47
+ - test/test_property_set.rb
48
+ - test/test_mbat.rb
49
49
  - test/test.doc
50
50
  - test/test_word_6.doc
51
- - test/test_word_95.doc
52
51
  - test/test_word_97.doc
52
+ - test/test_word_95.doc
53
53
  - test/oleWithDirs.ole
54
54
  - test/test_SummaryInformation
55
55
  has_rdoc: true
@@ -79,16 +79,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
79
  requirements: []
80
80
 
81
81
  rubyforge_project: ruby-ole
82
- rubygems_version: 0.9.5
82
+ rubygems_version: 1.2.0
83
83
  signing_key:
84
84
  specification_version: 2
85
85
  summary: Ruby OLE library.
86
86
  test_files:
87
+ - test/test_types.rb
87
88
  - test/test_filesystem.rb
88
- - test/test_mbat.rb
89
+ - test/test_support.rb
90
+ - test/test_storage.rb
89
91
  - test/test_meta_data.rb
90
- - test/test_property_set.rb
91
92
  - test/test_ranges_io.rb
92
- - test/test_storage.rb
93
- - test/test_support.rb
94
- - test/test_types.rb
93
+ - test/test_property_set.rb
94
+ - test/test_mbat.rb