ruby-ole 1.2.7 → 1.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +5 -0
- data/README +89 -6
- data/bin/oletool +0 -0
- data/lib/ole/ranges_io.rb +3 -2
- data/lib/ole/storage/base.rb +30 -64
- data/lib/ole/storage/file_system.rb +3 -24
- data/lib/ole/storage/meta_data.rb +25 -19
- data/lib/ole/support.rb +1 -1
- data/test/test_filesystem.rb +0 -0
- data/test/test_mbat.rb +0 -0
- data/test/test_meta_data.rb +1 -1
- data/test/test_property_set.rb +0 -0
- data/test/test_ranges_io.rb +0 -0
- data/test/test_storage.rb +2 -1
- data/test/test_support.rb +0 -0
- data/test/test_types.rb +0 -0
- metadata +18 -18
data/ChangeLog
CHANGED
data/README
CHANGED
@@ -1,22 +1,104 @@
|
|
1
1
|
= Introduction
|
2
2
|
|
3
|
-
|
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.
|
85
|
+
== 1.2.9
|
8
86
|
|
9
|
-
*
|
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
|
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
|
+
|
data/bin/oletool
CHANGED
File without changes
|
data/lib/ole/ranges_io.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/ole/storage/base.rb
CHANGED
@@ -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
|
-
#
|
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.
|
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
|
-
#
|
85
|
-
# +
|
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
|
-
|
154
|
-
|
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.
|
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
|
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
|
-
|
308
|
-
mbat_data
|
309
|
-
|
310
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
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
|
data/lib/ole/support.rb
CHANGED
@@ -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
|
data/test/test_filesystem.rb
CHANGED
File without changes
|
data/test/test_mbat.rb
CHANGED
File without changes
|
data/test/test_meta_data.rb
CHANGED
@@ -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
|
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
|
data/test/test_property_set.rb
CHANGED
File without changes
|
data/test/test_ranges_io.rb
CHANGED
File without changes
|
data/test/test_storage.rb
CHANGED
@@ -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
|
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
|
data/test/test_support.rb
CHANGED
File without changes
|
data/test/test_types.rb
CHANGED
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.
|
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
|
+
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/
|
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
|
-
-
|
41
|
+
- test/test_types.rb
|
41
42
|
- test/test_filesystem.rb
|
42
|
-
- test/
|
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/
|
47
|
-
- test/
|
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:
|
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/
|
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/
|
93
|
-
- test/
|
94
|
-
- test/test_types.rb
|
93
|
+
- test/test_property_set.rb
|
94
|
+
- test/test_mbat.rb
|