ruby-ole 1.2.3 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +5 -0
- data/Rakefile +1 -1
- data/data/propids.yaml +56 -0
- data/lib/ole/file_system.rb +5 -1
- data/lib/ole/property_set.rb +85 -9
- data/lib/ole/storage.rb +14 -11
- data/lib/ole/types.rb +18 -7
- data/test/test.doc +0 -0
- data/test/test_filesystem.rb +4 -6
- data/test/test_mbat.rb +2 -0
- data/test/test_property_set.rb +13 -3
- data/test/test_storage.rb +45 -4
- data/test/test_support.rb +1 -1
- metadata +4 -2
data/ChangeLog
CHANGED
data/Rakefile
CHANGED
@@ -53,7 +53,7 @@ spec = Gem::Specification.new do |s|
|
|
53
53
|
s.rubyforge_project = %q{ruby-ole}
|
54
54
|
|
55
55
|
s.executables = ['oletool']
|
56
|
-
s.files = ['Rakefile', 'ChangeLog']
|
56
|
+
s.files = ['Rakefile', 'ChangeLog', 'data/propids.yaml']
|
57
57
|
s.files += FileList['lib/**/*.rb']
|
58
58
|
s.files += FileList['test/test_*.rb', 'test/*.doc']
|
59
59
|
s.files += FileList['test/oleWithDirs.ole', 'test/test_SummaryInformation']
|
data/data/propids.yaml
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
"{f29f85e0-4ff9-1068-ab91-08002b27b3d9}":
|
2
|
+
- FMTID_SummaryInformation
|
3
|
+
- 2: doc_title
|
4
|
+
3: doc_subject
|
5
|
+
4: doc_author
|
6
|
+
5: doc_keywords
|
7
|
+
6: doc_comments
|
8
|
+
7: doc_template
|
9
|
+
8: doc_last_author
|
10
|
+
9: doc_rev_number
|
11
|
+
10: doc_edit_time
|
12
|
+
11: doc_last_printed
|
13
|
+
12: doc_created_time
|
14
|
+
13: doc_last_saved_time
|
15
|
+
14: doc_page_count
|
16
|
+
15: doc_word_count
|
17
|
+
16: doc_char_count
|
18
|
+
18: doc_app_name
|
19
|
+
19: security
|
20
|
+
|
21
|
+
"{d5cdd502-2e9c-101b-9397-08002b2cf9ae}":
|
22
|
+
- FMTID_DocSummaryInfo
|
23
|
+
- 2: doc_category
|
24
|
+
3: doc_presentation_target
|
25
|
+
4: doc_byte_count
|
26
|
+
5: doc_line_count
|
27
|
+
6: doc_para_count
|
28
|
+
7: doc_slide_count
|
29
|
+
8: doc_note_count
|
30
|
+
9: doc_hidden_count
|
31
|
+
10: mmclips
|
32
|
+
11: scale_crop
|
33
|
+
12: heading_pairs
|
34
|
+
13: doc_part_titles
|
35
|
+
14: doc_manager
|
36
|
+
15: doc_company
|
37
|
+
16: links_up_to_date
|
38
|
+
|
39
|
+
"{d5cdd505-2e9c-101b-9397-08002b2cf9ae}":
|
40
|
+
- FMTID_UserDefinedProperties
|
41
|
+
- {}
|
42
|
+
|
43
|
+
# just dumped these all here. if i can confirm any of these
|
44
|
+
# better, i can update this file so they're recognized.
|
45
|
+
#0b63e343-9ccc-11d0-bcdb-00805fccce04
|
46
|
+
#0b63e350-9ccc-11d0-bcdb-00805fccce04 NetLibrary propset?
|
47
|
+
#31f400a0-fd07-11cf-b9bd-00aa003db18e ScriptInfo propset?
|
48
|
+
#49691c90-7e17-101a-a91c-08002b2ecda9 Query propset?
|
49
|
+
#560c36c0-503a-11cf-baa1-00004c752a9a
|
50
|
+
#70eb7a10-55d9-11cf-b75b-00aa0051fe20 HTMLInfo propset
|
51
|
+
#85ac0960-1819-11d1-896f-00805f053bab message propset?
|
52
|
+
#aa568eec-e0e5-11cf-8fda-00aa00a14f93 NNTP SummaryInformation propset?
|
53
|
+
#b725f130-47ef-101a-a5f1-02608c9eebac Storage propset
|
54
|
+
#c82bf596-b831-11d0-b733-00aa00a1ebd2 NetLibraryInfo propset
|
55
|
+
#c82bf597-b831-11d0-b733-00aa00a1ebd2 LinkInformation propset?
|
56
|
+
#d1b5d3f0-c0b3-11cf-9a92-00a0c908dbf1 LinkInformation propset?
|
data/lib/ole/file_system.rb
CHANGED
@@ -132,7 +132,11 @@ module Ole # :nodoc:
|
|
132
132
|
# just for the .. and . handling
|
133
133
|
# Hmmm, FIXME: won't work on windows i think. on windows it will prepend
|
134
134
|
# the current drive i believe. may just need to strip the first 2 chars.
|
135
|
-
|
135
|
+
if RUBY_PLATFORM =~ /win/o
|
136
|
+
File.expand_path(path)[2..-1]
|
137
|
+
else
|
138
|
+
File.expand_path path
|
139
|
+
end
|
136
140
|
end
|
137
141
|
|
138
142
|
# +orig_path+ is just so that we can use the requested path
|
data/lib/ole/property_set.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ole/types'
|
2
|
+
require 'yaml'
|
2
3
|
|
3
4
|
module Ole
|
4
5
|
module Types
|
@@ -13,30 +14,41 @@ module Ole
|
|
13
14
|
#
|
14
15
|
class PropertySet
|
15
16
|
HEADER_SIZE = 28
|
16
|
-
|
17
|
+
HEADER_PACK = "vvVa#{Clsid::SIZE}V"
|
17
18
|
OS_MAP = {
|
18
19
|
0 => :win16,
|
19
20
|
1 => :mac,
|
20
|
-
2 => :win32
|
21
|
+
2 => :win32,
|
22
|
+
0x20001 => :ooffice, # open office on linux...
|
21
23
|
}
|
22
24
|
|
23
25
|
# define a smattering of the property set guids.
|
24
|
-
FMTID_SummaryInformation = Clsid.parse '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}'
|
25
|
-
FMTID_DocSummaryInformation = Clsid.parse '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}'
|
26
|
-
FMTID_UserDefinedProperties = Clsid.parse '{d5cdd505-2e9c-101b-9397-08002b2cf9ae}'
|
26
|
+
#FMTID_SummaryInformation = Clsid.parse '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}'
|
27
|
+
#FMTID_DocSummaryInformation = Clsid.parse '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}'
|
28
|
+
#FMTID_UserDefinedProperties = Clsid.parse '{d5cdd505-2e9c-101b-9397-08002b2cf9ae}'
|
29
|
+
|
30
|
+
DATA = YAML.load_file(File.dirname(__FILE__) + '/../../data/propids.yaml').
|
31
|
+
inject({}) { |hash, (key, value)| hash.update Clsid.parse(key) => value }
|
32
|
+
|
33
|
+
module Constants
|
34
|
+
DATA.each { |guid, (name, map)| const_set name, guid }
|
35
|
+
end
|
36
|
+
|
37
|
+
include Constants
|
27
38
|
|
28
39
|
class Section < Struct.new(:guid, :offset)
|
29
40
|
include Variant::Constants
|
30
41
|
include Enumerable
|
31
42
|
|
32
43
|
SIZE = Clsid::SIZE + 4
|
33
|
-
|
44
|
+
PACK = "a#{Clsid::SIZE}v"
|
34
45
|
|
35
46
|
attr_reader :length
|
36
47
|
def initialize str, property_set
|
37
48
|
@property_set = property_set
|
38
|
-
super(*str.unpack(
|
49
|
+
super(*str.unpack(PACK))
|
39
50
|
self.guid = Clsid.load guid
|
51
|
+
@map = DATA[guid] ? DATA[guid][1] : nil
|
40
52
|
load_header
|
41
53
|
end
|
42
54
|
|
@@ -66,9 +78,30 @@ module Ole
|
|
66
78
|
self
|
67
79
|
end
|
68
80
|
|
81
|
+
def [] key
|
82
|
+
unless Integer === key
|
83
|
+
return unless @map and key = @map.invert[key]
|
84
|
+
end
|
85
|
+
return unless result = properties.assoc(key)
|
86
|
+
result.last
|
87
|
+
end
|
88
|
+
|
89
|
+
def method_missing name, *args
|
90
|
+
if args.empty? and @map and @map.values.include? name.to_s
|
91
|
+
self[name.to_s]
|
92
|
+
else
|
93
|
+
super
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
69
97
|
def properties
|
70
|
-
to_enum.to_a
|
98
|
+
@properties ||= to_enum.to_a
|
71
99
|
end
|
100
|
+
|
101
|
+
#def to_h
|
102
|
+
# properties.inject({}) do |hash, (key, type, value)|
|
103
|
+
# hash.update
|
104
|
+
#end
|
72
105
|
end
|
73
106
|
|
74
107
|
attr_reader :io, :signature, :unknown, :os, :guid, :sections
|
@@ -81,7 +114,7 @@ module Ole
|
|
81
114
|
end
|
82
115
|
|
83
116
|
def load_header str
|
84
|
-
@signature, @unknown, @os_id, @guid, @num_sections = str.unpack
|
117
|
+
@signature, @unknown, @os_id, @guid, @num_sections = str.unpack HEADER_PACK
|
85
118
|
# should i check that unknown == 0? it usually is. so is the guid actually
|
86
119
|
@guid = Clsid.load @guid
|
87
120
|
@os = OS_MAP[@os_id] || Log.warn("unknown operating system id #{@os_id}")
|
@@ -92,5 +125,48 @@ module Ole
|
|
92
125
|
end
|
93
126
|
end
|
94
127
|
end
|
128
|
+
|
129
|
+
class Storage
|
130
|
+
# i'm thinking - search for a property set in +filenames+ containing a
|
131
|
+
# section with guid +guid+. then yield it. can read/write to it in the
|
132
|
+
# block.
|
133
|
+
# propsets themselves can have guids, but they are often all null.
|
134
|
+
def with_property_set guid, filenames=nil
|
135
|
+
end
|
136
|
+
|
137
|
+
class PropertySetSectionProxy
|
138
|
+
attr_reader :obj, :section_num
|
139
|
+
def initialize obj, section_num
|
140
|
+
@obj, @section_num = obj, section_num
|
141
|
+
end
|
142
|
+
|
143
|
+
def method_missing name, *args, &block
|
144
|
+
obj.open do |io|
|
145
|
+
section = Types::PropertySet.new(io).sections[section_num]
|
146
|
+
section.send name, *args, &block
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# this will be changed to use with_property_set
|
152
|
+
def summary_information
|
153
|
+
dirent = root["\005SummaryInformation"]
|
154
|
+
dirent.open do |io|
|
155
|
+
propset = Types::PropertySet.new(io)
|
156
|
+
sections = propset.sections
|
157
|
+
# this will maybe get wrapped up as
|
158
|
+
# section = propset[guid]
|
159
|
+
# maybe taking it one step further, i'd hide the section thing,
|
160
|
+
# and let you use composite keys, like
|
161
|
+
# propset[4, guid] eg in MAPI, and just propset.doc_author.
|
162
|
+
section = sections.find do |section|
|
163
|
+
section.guid == Types::PropertySet::FMTID_SummaryInformation
|
164
|
+
end
|
165
|
+
return PropertySetSectionProxy.new(dirent, sections.index(section))
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
alias summary_info :summary_information
|
170
|
+
end
|
95
171
|
end
|
96
172
|
|
data/lib/ole/storage.rb
CHANGED
@@ -67,7 +67,7 @@ module Ole # :nodoc:
|
|
67
67
|
class FormatError < StandardError # :nodoc:
|
68
68
|
end
|
69
69
|
|
70
|
-
VERSION = '1.2.
|
70
|
+
VERSION = '1.2.4'
|
71
71
|
|
72
72
|
# options used at creation time
|
73
73
|
attr_reader :params
|
@@ -151,7 +151,7 @@ module Ole # :nodoc:
|
|
151
151
|
# create an empty bbat.
|
152
152
|
@bbat = AllocationTable::Big.new self
|
153
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 '
|
154
|
+
bbat_chain = (header_block[Header::SIZE..-1] + @bbat.read(mbat_blocks)).unpack 'V*'
|
155
155
|
# am i using num_bat in the right way?
|
156
156
|
@bbat.load @bbat.read(bbat_chain[0, @header.num_bat])
|
157
157
|
|
@@ -308,12 +308,12 @@ module Ole # :nodoc:
|
|
308
308
|
q = @bbat.block_size / 4
|
309
309
|
mbat_data += [AllocationTable::AVAIL] *((mbat_data.length / q.to_f).ceil * q - mbat_data.length)
|
310
310
|
ranges = @bbat.ranges((0...num_mbat_blocks).map { |i| @header.mbat_start + i })
|
311
|
-
RangesIO.open(@io, :ranges => ranges) { |io| io.write mbat_data.pack('
|
311
|
+
RangesIO.open(@io, :ranges => ranges) { |io| io.write mbat_data.pack('V*') }
|
312
312
|
end
|
313
313
|
|
314
314
|
# now seek back and write the header out
|
315
315
|
@io.seek 0
|
316
|
-
@io.write @header.to_s + bbat_chain[0, 109].pack('
|
316
|
+
@io.write @header.to_s + bbat_chain[0, 109].pack('V*')
|
317
317
|
@io.flush
|
318
318
|
end
|
319
319
|
|
@@ -333,10 +333,13 @@ module Ole # :nodoc:
|
|
333
333
|
end
|
334
334
|
|
335
335
|
# could be useful with mis-behaving ole documents. or to just clean them up.
|
336
|
-
# FIXME: heard Tempfile is not binary on windows. check
|
337
336
|
def repack temp=:file
|
338
337
|
case temp
|
339
|
-
when :file
|
338
|
+
when :file
|
339
|
+
Tempfile.open 'ole-repack' do |io|
|
340
|
+
io.binmode
|
341
|
+
repack_using_io io
|
342
|
+
end
|
340
343
|
when :mem; StringIO.open(&method(:repack_using_io))
|
341
344
|
else raise ArgumentError, "unknown temp backing #{temp.inspect}"
|
342
345
|
end
|
@@ -372,7 +375,7 @@ module Ole # :nodoc:
|
|
372
375
|
:reserved, :csectdir, :num_bat, :dirent_start, :transacting_signature, :threshold,
|
373
376
|
:sbat_start, :num_sbat, :mbat_start, :num_mbat
|
374
377
|
)
|
375
|
-
PACK = 'a8 a16
|
378
|
+
PACK = 'a8 a16 v2 a2 v2 a6 V3 a4 V5'
|
376
379
|
SIZE = 0x4c
|
377
380
|
# i have seen it pointed out that the first 4 bytes of hex,
|
378
381
|
# 0xd0cf11e0, is supposed to spell out docfile. hmmm :)
|
@@ -462,7 +465,7 @@ module Ole # :nodoc:
|
|
462
465
|
end
|
463
466
|
|
464
467
|
def load data
|
465
|
-
replace data.unpack('
|
468
|
+
replace data.unpack('V*')
|
466
469
|
end
|
467
470
|
|
468
471
|
def truncate
|
@@ -486,7 +489,7 @@ module Ole # :nodoc:
|
|
486
489
|
# do you really use AVAIL? they probably extend past end of file, and may shortly
|
487
490
|
# be used for the bat. not really good.
|
488
491
|
table += [AVAIL] * (num - (table.length % num)) if (table.length % num) != 0
|
489
|
-
table.pack '
|
492
|
+
table.pack 'V*'
|
490
493
|
end
|
491
494
|
|
492
495
|
# rewrote this to be non-recursive as it broke on a large attachment
|
@@ -716,7 +719,7 @@ module Ole # :nodoc:
|
|
716
719
|
)
|
717
720
|
include RecursivelyEnumerable
|
718
721
|
|
719
|
-
PACK = 'a64
|
722
|
+
PACK = 'a64 v C C V3 a16 V a8 a8 V2 a4'
|
720
723
|
SIZE = 128
|
721
724
|
TYPE_MAP = {
|
722
725
|
# this is temporary
|
@@ -754,7 +757,7 @@ module Ole # :nodoc:
|
|
754
757
|
super(*values)
|
755
758
|
|
756
759
|
# extra parsing from the actual struct values
|
757
|
-
@name = params[:name] || Types::Variant.load(Types::VT_LPWSTR, name_utf16[0...name_len]
|
760
|
+
@name = params[:name] || Types::Variant.load(Types::VT_LPWSTR, name_utf16[0...name_len])
|
758
761
|
@type = if params[:type]
|
759
762
|
unless TYPE_MAP.values.include?(params[:type])
|
760
763
|
raise ArgumentError, "unknown type #{params[:type].inspect}"
|
data/lib/ole/types.rb
CHANGED
@@ -22,7 +22,17 @@ module Ole # :nodoc:
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class Lpstr <
|
25
|
+
class Lpstr < String
|
26
|
+
def self.load str
|
27
|
+
# not sure if its always there, but there is often a trailing
|
28
|
+
# null byte.
|
29
|
+
new str.chomp(0.chr)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.dump str
|
33
|
+
# do i need to append the null byte?
|
34
|
+
str.to_s
|
35
|
+
end
|
26
36
|
end
|
27
37
|
|
28
38
|
# for VT_LPWSTR
|
@@ -31,10 +41,11 @@ module Ole # :nodoc:
|
|
31
41
|
TO_UTF16 = Iconv.new 'utf-16le', 'utf-8'
|
32
42
|
|
33
43
|
def self.load str
|
34
|
-
new FROM_UTF16.iconv(str)
|
44
|
+
new FROM_UTF16.iconv(str).chomp(0.chr)
|
35
45
|
end
|
36
46
|
|
37
47
|
def self.dump str
|
48
|
+
# need to append nulls?
|
38
49
|
TO_UTF16.iconv str
|
39
50
|
end
|
40
51
|
end
|
@@ -50,7 +61,7 @@ module Ole # :nodoc:
|
|
50
61
|
# Converts +str+ to two 32 bit time values, comprising the high and low 32 bits of
|
51
62
|
# the 100's of nanoseconds since 1st january 1601 (Epoch).
|
52
63
|
def self.load str
|
53
|
-
low, high = str.to_s.unpack '
|
64
|
+
low, high = str.to_s.unpack 'V2'
|
54
65
|
# we ignore these, without even warning about it
|
55
66
|
return nil if low == 0 and high == 0
|
56
67
|
# switched to rational, and fixed the off by 1 second error i sometimes got.
|
@@ -74,7 +85,7 @@ module Ole # :nodoc:
|
|
74
85
|
# don't bother to use const_get here
|
75
86
|
bignum = (time - EPOCH) * 86400 * 1e7.to_i
|
76
87
|
high, low = bignum.divmod 1 << 32
|
77
|
-
[low, high].pack '
|
88
|
+
[low, high].pack 'V2'
|
78
89
|
end
|
79
90
|
end
|
80
91
|
|
@@ -85,7 +96,7 @@ module Ole # :nodoc:
|
|
85
96
|
# helper method for creating a Guid from that readable form (#format).
|
86
97
|
class Clsid < String
|
87
98
|
SIZE = 16
|
88
|
-
|
99
|
+
PACK = 'V v v CC C6'
|
89
100
|
|
90
101
|
def self.load str
|
91
102
|
new str.to_s
|
@@ -103,14 +114,14 @@ module Ole # :nodoc:
|
|
103
114
|
# this is pretty ugly
|
104
115
|
vals[3] = ('%04x' % vals[3]).scan(/../).map(&:hex)
|
105
116
|
vals[4] = ('%012x' % vals[4]).scan(/../).map(&:hex)
|
106
|
-
guid = new vals.flatten.pack(
|
117
|
+
guid = new vals.flatten.pack(PACK)
|
107
118
|
return guid unless guid.delete('{}') == str.downcase.delete('{}')
|
108
119
|
end
|
109
120
|
raise ArgumentError, 'invalid guid - %p' % str
|
110
121
|
end
|
111
122
|
|
112
123
|
def format
|
113
|
-
"%08x-%04x-%04x-%02x%02x-#{'%02x' * 6}" % unpack(
|
124
|
+
"%08x-%04x-%04x-%02x%02x-#{'%02x' * 6}" % unpack(PACK)
|
114
125
|
end
|
115
126
|
|
116
127
|
def inspect
|
data/test/test.doc
ADDED
Binary file
|
data/test/test_filesystem.rb
CHANGED
@@ -49,7 +49,7 @@ end
|
|
49
49
|
|
50
50
|
class OleFsNonmutatingTest < Test::Unit::TestCase
|
51
51
|
def setup
|
52
|
-
@ole = Ole::Storage.open TEST_DIR + '/oleWithDirs.ole'
|
52
|
+
@ole = Ole::Storage.open TEST_DIR + '/oleWithDirs.ole', 'rb'
|
53
53
|
end
|
54
54
|
|
55
55
|
def teardown
|
@@ -502,7 +502,7 @@ end
|
|
502
502
|
class OleFsFileStatTest < Test::Unit::TestCase
|
503
503
|
|
504
504
|
def setup
|
505
|
-
@ole = Ole::Storage.open TEST_DIR + '/oleWithDirs.ole'
|
505
|
+
@ole = Ole::Storage.open TEST_DIR + '/oleWithDirs.ole', 'rb'
|
506
506
|
end
|
507
507
|
|
508
508
|
def teardown
|
@@ -569,7 +569,7 @@ class OleFsFileMutatingTest < Test::Unit::TestCase
|
|
569
569
|
def setup
|
570
570
|
# we use an in memory copy of the file instead of the original
|
571
571
|
# file based.
|
572
|
-
@io = StringIO.new
|
572
|
+
@io = StringIO.new open(TEST_DIR + '/oleWithDirs.ole', 'rb', &:read)
|
573
573
|
end
|
574
574
|
|
575
575
|
def teardown
|
@@ -660,12 +660,10 @@ class OleFsFileMutatingTest < Test::Unit::TestCase
|
|
660
660
|
end
|
661
661
|
|
662
662
|
class ZipFsDirectoryTest < Test::Unit::TestCase
|
663
|
-
TEST_ZIP = "zipWithDirs_copy.zip"
|
664
|
-
|
665
663
|
def setup
|
666
664
|
# we use an in memory copy of the file instead of the original
|
667
665
|
# file based.
|
668
|
-
@io = StringIO.new
|
666
|
+
@io = StringIO.new open(TEST_DIR + '/oleWithDirs.ole', 'rb', &:read)
|
669
667
|
end
|
670
668
|
|
671
669
|
def teardown
|
data/test/test_mbat.rb
CHANGED
@@ -10,6 +10,8 @@ require 'tempfile'
|
|
10
10
|
class TestWriteMbat < Test::Unit::TestCase
|
11
11
|
def test_write_mbat
|
12
12
|
Tempfile.open 'myolefile' do |temp|
|
13
|
+
temp.binmode
|
14
|
+
|
13
15
|
# this used to raise an error at flush time, due to failure to write the mbat
|
14
16
|
Ole::Storage.open temp do |ole|
|
15
17
|
# create a 10mb file
|
data/test/test_property_set.rb
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
$: << File.dirname(__FILE__) + '/../lib'
|
4
4
|
|
5
5
|
require 'test/unit'
|
6
|
+
require 'ole/storage'
|
6
7
|
require 'ole/property_set'
|
7
8
|
|
8
9
|
class TestTypes < Test::Unit::TestCase
|
9
10
|
include Ole::Types
|
10
11
|
|
11
12
|
def setup
|
12
|
-
@io = open File.dirname(__FILE__) + '/test_SummaryInformation'
|
13
|
+
@io = open File.dirname(__FILE__) + '/test_SummaryInformation', 'rb'
|
13
14
|
end
|
14
15
|
|
15
16
|
def teardown
|
@@ -18,13 +19,22 @@ class TestTypes < Test::Unit::TestCase
|
|
18
19
|
|
19
20
|
def test_property_set
|
20
21
|
propset = PropertySet.new @io
|
22
|
+
assert_equal :mac, propset.os
|
21
23
|
assert_equal 1, propset.sections.length
|
22
24
|
section = propset.sections.first
|
23
25
|
assert_equal 14, section.length
|
24
26
|
assert_equal 'f29f85e0-4ff9-1068-ab91-08002b27b3d9', section.guid.format
|
25
27
|
assert_equal PropertySet::FMTID_SummaryInformation, section.guid
|
26
|
-
|
27
|
-
|
28
|
+
assert_equal 'Charles Lowe', section.properties.assoc(4).last
|
29
|
+
# new named support
|
30
|
+
assert_equal 'Charles Lowe', section.doc_author
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_ole_storage_integration
|
34
|
+
Ole::Storage.open File.dirname(__FILE__) + '/test.doc', 'rb' do |ole|
|
35
|
+
assert_equal 'Charles Lowe', ole.summary_info.doc_author
|
36
|
+
assert_equal 'Title', ole.summary_info.doc_title
|
37
|
+
end
|
28
38
|
end
|
29
39
|
end
|
30
40
|
|
data/test/test_storage.rb
CHANGED
@@ -7,6 +7,8 @@ require 'ole/storage'
|
|
7
7
|
require 'digest/sha1'
|
8
8
|
require 'stringio'
|
9
9
|
require 'tempfile'
|
10
|
+
require 'zlib'
|
11
|
+
require 'base64'
|
10
12
|
|
11
13
|
#
|
12
14
|
# = TODO
|
@@ -60,12 +62,51 @@ class TestStorageRead < Test::Unit::TestCase
|
|
60
62
|
end
|
61
63
|
|
62
64
|
def test_read
|
65
|
+
# this data should probably be put elsewhere. not asserting
|
66
|
+
# using hashes anymore, cause they were different on the mac.
|
67
|
+
data = <<-end
|
68
|
+
eJxjZGBgYkADAABKAAQ=
|
69
|
+
|
70
|
+
eJxjZPj3n5mLgeE/EDBwMjGAwAEwyeAmAyR8M5OL8ovz00oUwvOLUhTM9Ax0
|
71
|
+
XfKzS3NT80oYuEDywSBxl/xkBgEgD8TWA3LA8npmYGMAKWQZqA==
|
72
|
+
|
73
|
+
eJztVs9rE0EU/mZ32m5smyZtUlKQunhIezAV6knwYGoRxRLQBG89zCabdiE7
|
74
|
+
K9kJpt7Es1DwLxCsP+jJqycv/S/8I9SrmPgmuy0pK1ilNZd8MPt233zz7dud
|
75
|
+
H+99OXBR+pziILgYgglkqaUvIYFs0pWEBSyzIfsHLKeA3Fl0Y6wTX4d2K7bH
|
76
|
+
uEvP6i90zhuf6P21fxpp0C9nOMOvGuMcUQ1811ZuqOjSVWuzszm8eb52cFR+
|
77
|
+
K/k7yd9L/kHyV6OO8gJBezwT7/UVaj/xY9QRjXHhMDoM5rapZ39o/ntRZ2+0
|
78
|
+
sY3xv0C5xkhT1rXo7gHmBr5VWg7f+gbZqU23KTotSqaT5L+Ba2waDmjR1AsQ
|
79
|
+
qZnf6BVRvv29/5rsUtkJhXpWqiohG6LdCOu7ba+pRFud5veuMBisiKl7rmh4
|
80
|
+
ckfn8jnkv2KxC4tNYpujfhk2NjKaZyNVo0PadoLGni4sMshDM3XlcD3D2DzL
|
81
|
+
gW95oaJcmj3Rv6r174gnyguk1p9HvqtHpdmE/pTHDIUBb50VMHFfNlwS5Fig
|
82
|
+
/ihKrcQH+wPoExCflMZJjWRSxZFf3Cd+zfPd0K64T+1HgS8kZshroLrnO0EL
|
83
|
+
00VNKbc90cKqpi9UPN/phBHXrgQ37a2EwpIelI6JVSFD4kQSGxQVs14WgCMK
|
84
|
+
ZXcQ7WHtYxPWw5JupyuJqLLgeLHPEt5jz4r5CxXWcbY=
|
85
|
+
|
86
|
+
eJzt0z1oU2EcRvE3rR+tWtGtOBQ3hS4tODgWKnQRlM5dHAoZCuIHaLcsBaGT
|
87
|
+
hIBksQmlQ1wCTgF3Q+Z0cHN1lZBQQhL/N60fUEEKh5bK+cHleXlJw+2hHY5S
|
88
|
+
yqXjsruvW++/HzzK3/jwdirN3/n4ZSHu2vspXY+9Gc/ro88txN107P3YK7EP
|
89
|
+
Yq/GPo6diV2LvRabj52KfRl7IbYQeyn2Xezl2N3Yi7H12MnYT7ETsc3Yley+
|
90
|
+
ndIoZN9xN55n8eyM32F2/M6F9vHfYyTa3lm/wH/Ipjyb8mzKsynPpjyb8mzK
|
91
|
+
synPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzK
|
92
|
+
synPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzK
|
93
|
+
synPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzK
|
94
|
+
synPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzK
|
95
|
+
synPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzK
|
96
|
+
synPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzK
|
97
|
+
synPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPpjyb8mzKsynPprx/NO33
|
98
|
+
+7VaLQ6VSqVUKpXL5cFg0Gq1Go1GtVptNpvFYrFer8dNp9M5lRc+B078dzoc
|
99
|
+
Dnu93uGh2+3G+deNDvm/z7Mpz6Y8m/JsyrMpz6Y8m/JsyrMpz6a8vYmU0rdB
|
100
|
+
SnOx2XkxnqX02/j8ZnXzb+fCrcr09r3Puexnc0efz84z8SznnzzfWH9x++HT
|
101
|
+
V+s/7//8zEnOPwDhN6kw
|
102
|
+
end
|
103
|
+
expect = data.split(/\n\s*\n/).map { |chunk| Zlib::Inflate.inflate Base64.decode64(chunk) }
|
104
|
+
|
63
105
|
# test the ole storage type
|
64
106
|
type = 'Microsoft Word 6.0-Dokument'
|
65
107
|
assert_equal type, (@ole.root/"\001CompObj").read[/^.{32}([^\x00]+)/m, 1]
|
66
108
|
# i was actually not loading data correctly before, so carefully check everything here
|
67
|
-
|
68
|
-
assert_equal hashes, @ole.root.children.map { |child| child.read.hash }
|
109
|
+
assert_equal expect, @ole.root.children.map { |child| child.read }
|
69
110
|
end
|
70
111
|
end
|
71
112
|
|
@@ -86,7 +127,7 @@ class TestStorageWrite < Test::Unit::TestCase
|
|
86
127
|
# of checks involving writes that resize their file bigger/smaller, that resize
|
87
128
|
# the bats to more blocks, that resizes the sb_blocks, that has migration etc.
|
88
129
|
def test_write_hash
|
89
|
-
io = StringIO.open
|
130
|
+
io = StringIO.open open("#{TEST_DIR}/test_word_6.doc", 'rb', &:read)
|
90
131
|
assert_equal '9974e354def8471225f548f82b8d81c701221af7', sha1(io.string)
|
91
132
|
Ole::Storage.open(io, :update_timestamps => false) { }
|
92
133
|
# hash changed. used to be efa8cfaf833b30b1d1d9381771ddaafdfc95305c
|
@@ -99,7 +140,7 @@ class TestStorageWrite < Test::Unit::TestCase
|
|
99
140
|
end
|
100
141
|
|
101
142
|
def test_plain_repack
|
102
|
-
io = StringIO.open
|
143
|
+
io = StringIO.open open("#{TEST_DIR}/test_word_6.doc", 'rb', &:read)
|
103
144
|
assert_equal '9974e354def8471225f548f82b8d81c701221af7', sha1(io.string)
|
104
145
|
Ole::Storage.open io, :update_timestamps => false, &:repack
|
105
146
|
# note equivalence to the above flush, repack, flush
|
data/test/test_support.rb
CHANGED
@@ -11,7 +11,7 @@ class TestSupport < Test::Unit::TestCase
|
|
11
11
|
def test_file
|
12
12
|
assert_equal 4096, open("#{TEST_DIR}/oleWithDirs.ole") { |f| f.size }
|
13
13
|
# point is to have same interface as:
|
14
|
-
assert_equal 4096, StringIO.open(
|
14
|
+
assert_equal 4096, StringIO.open(open("#{TEST_DIR}/oleWithDirs.ole", 'rb', &:read)).size
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_enumerable
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-ole
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.2.
|
7
|
-
date:
|
6
|
+
version: 1.2.4
|
7
|
+
date: 2008-01-10 00:00:00 +11:00
|
8
8
|
summary: Ruby OLE library.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -31,6 +31,7 @@ authors:
|
|
31
31
|
files:
|
32
32
|
- Rakefile
|
33
33
|
- ChangeLog
|
34
|
+
- data/propids.yaml
|
34
35
|
- bin/oletool
|
35
36
|
- lib/ole/ranges_io.rb
|
36
37
|
- lib/ole/property_set.rb
|
@@ -48,6 +49,7 @@ files:
|
|
48
49
|
- test/test_filesystem.rb
|
49
50
|
- test/test_word_6.doc
|
50
51
|
- test/test_word_95.doc
|
52
|
+
- test/test.doc
|
51
53
|
- test/test_word_97.doc
|
52
54
|
- test/oleWithDirs.ole
|
53
55
|
- test/test_SummaryInformation
|