Class: Reader
- Inherits:
-
Object
- Object
- Reader
- Defined in:
- lib/surpass/document.rb
Constant Summary collapse
- DIR_ENTRY_SIZE =
128
Instance Attribute Summary collapse
-
#byte_order ⇒ Object
Returns the value of attribute byte_order.
-
#data ⇒ Object
Returns the value of attribute data.
-
#dir_entry_list ⇒ Object
Returns the value of attribute dir_entry_list.
-
#dir_start_sid ⇒ Object
Returns the value of attribute dir_start_sid.
-
#doc_magic ⇒ Object
Returns the value of attribute doc_magic.
-
#file_uid ⇒ Object
Returns the value of attribute file_uid.
-
#header ⇒ Object
Returns the value of attribute header.
-
#min_stream_size ⇒ Object
Returns the value of attribute min_stream_size.
-
#msat ⇒ Object
Returns the value of attribute msat.
-
#msat_start_sid ⇒ Object
Returns the value of attribute msat_start_sid.
-
#rev_num ⇒ Object
Returns the value of attribute rev_num.
-
#sat ⇒ Object
Returns the value of attribute sat.
-
#sect_size ⇒ Object
Returns the value of attribute sect_size.
-
#short_sect_size ⇒ Object
Returns the value of attribute short_sect_size.
-
#ssat ⇒ Object
Returns the value of attribute ssat.
-
#ssat_start_sid ⇒ Object
Returns the value of attribute ssat_start_sid.
-
#total_msat_sectors ⇒ Object
Returns the value of attribute total_msat_sectors.
-
#total_sat_sectors ⇒ Object
Returns the value of attribute total_sat_sectors.
-
#total_ssat_sectors ⇒ Object
Returns the value of attribute total_ssat_sectors.
-
#ver_num ⇒ Object
Returns the value of attribute ver_num.
Instance Method Summary collapse
- #build_directory ⇒ Object
- #build_header ⇒ Object
- #build_msat ⇒ Object
- #build_sat ⇒ Object
- #build_short_sectors_data ⇒ Object
- #build_ssat ⇒ Object
-
#initialize(file) ⇒ Reader
constructor
A new instance of Reader.
- #stream_data(data, sat, start_sid, sect_size) ⇒ Object
Constructor Details
#initialize(file) ⇒ Reader
Returns a new instance of Reader.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/surpass/document.rb', line 28 def initialize(file) @streams = {} file = File.open(file, 'rb') unless file.respond_to?(:read) doc = file.read @header, @data = doc[0...512], doc[512..-1] build_header build_msat build_sat build_directory build_short_sectors_data if @short_sectors_data.length > 0 build_ssat else @ssat_start_sid = -2 @total_ssat_sectors = 0 @ssat = [-2] end @dir_entry_list[1..-1].each do |d| did, sz, name, t, c, did_left, did_right, did_root, dentry_start_sid, stream_size = d stream_data = '' if stream_size > 0 if stream_size > @min_stream_size args = [@data, @sat, dentry_start_sid, @sect_size] else args = [@short_sectors_data, @ssat, dentry_start_sid, @short_sect_size] end stream_data = stream_data(*args) end # BAD IDEA: names may be equal. NEED use full paths... @streams[name] = stream_data if !name.length == 0 end end |
Instance Attribute Details
#byte_order ⇒ Object
Returns the value of attribute byte_order.
11 12 13 |
# File 'lib/surpass/document.rb', line 11 def byte_order @byte_order end |
#data ⇒ Object
Returns the value of attribute data.
5 6 7 |
# File 'lib/surpass/document.rb', line 5 def data @data end |
#dir_entry_list ⇒ Object
Returns the value of attribute dir_entry_list.
26 27 28 |
# File 'lib/surpass/document.rb', line 26 def dir_entry_list @dir_entry_list end |
#dir_start_sid ⇒ Object
Returns the value of attribute dir_start_sid.
16 17 18 |
# File 'lib/surpass/document.rb', line 16 def dir_start_sid @dir_start_sid end |
#doc_magic ⇒ Object
Returns the value of attribute doc_magic.
7 8 9 |
# File 'lib/surpass/document.rb', line 7 def doc_magic @doc_magic end |
#file_uid ⇒ Object
Returns the value of attribute file_uid.
8 9 10 |
# File 'lib/surpass/document.rb', line 8 def file_uid @file_uid end |
#header ⇒ Object
Returns the value of attribute header.
4 5 6 |
# File 'lib/surpass/document.rb', line 4 def header @header end |
#min_stream_size ⇒ Object
Returns the value of attribute min_stream_size.
17 18 19 |
# File 'lib/surpass/document.rb', line 17 def min_stream_size @min_stream_size end |
#msat ⇒ Object
Returns the value of attribute msat.
23 24 25 |
# File 'lib/surpass/document.rb', line 23 def msat @msat end |
#msat_start_sid ⇒ Object
Returns the value of attribute msat_start_sid.
20 21 22 |
# File 'lib/surpass/document.rb', line 20 def msat_start_sid @msat_start_sid end |
#rev_num ⇒ Object
Returns the value of attribute rev_num.
9 10 11 |
# File 'lib/surpass/document.rb', line 9 def rev_num @rev_num end |
#sat ⇒ Object
Returns the value of attribute sat.
24 25 26 |
# File 'lib/surpass/document.rb', line 24 def sat @sat end |
#sect_size ⇒ Object
Returns the value of attribute sect_size.
12 13 14 |
# File 'lib/surpass/document.rb', line 12 def sect_size @sect_size end |
#short_sect_size ⇒ Object
Returns the value of attribute short_sect_size.
13 14 15 |
# File 'lib/surpass/document.rb', line 13 def short_sect_size @short_sect_size end |
#ssat ⇒ Object
Returns the value of attribute ssat.
25 26 27 |
# File 'lib/surpass/document.rb', line 25 def ssat @ssat end |
#ssat_start_sid ⇒ Object
Returns the value of attribute ssat_start_sid.
18 19 20 |
# File 'lib/surpass/document.rb', line 18 def ssat_start_sid @ssat_start_sid end |
#total_msat_sectors ⇒ Object
Returns the value of attribute total_msat_sectors.
21 22 23 |
# File 'lib/surpass/document.rb', line 21 def total_msat_sectors @total_msat_sectors end |
#total_sat_sectors ⇒ Object
Returns the value of attribute total_sat_sectors.
15 16 17 |
# File 'lib/surpass/document.rb', line 15 def total_sat_sectors @total_sat_sectors end |
#total_ssat_sectors ⇒ Object
Returns the value of attribute total_ssat_sectors.
19 20 21 |
# File 'lib/surpass/document.rb', line 19 def total_ssat_sectors @total_ssat_sectors end |
#ver_num ⇒ Object
Returns the value of attribute ver_num.
10 11 12 |
# File 'lib/surpass/document.rb', line 10 def ver_num @ver_num end |
Instance Method Details
#build_directory ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/surpass/document.rb', line 110 def build_directory dir_stream = stream_data(@data, @sat, @dir_start_sid, @sect_size) @dir_entry_list = [] i = 0 while i < dir_stream.length do dentry = dir_stream[i...(i+DIR_ENTRY_SIZE)] i += DIR_ENTRY_SIZE did = @dir_entry_list.length sz = dentry[64...66].unpack('C')[0] if sz > 0 name = dentry[0...(sz-2)] # TODO unicode else name = '' end t = dentry[66...67].unpack('C')[0] c = dentry[67...68].unpack('C')[0] did_left = dentry[68...72].unpack('V')[0] did_right = dentry[72...76].unpack('V')[0] did_root = dentry[76...80].unpack('V')[0] dentry_start_sid = dentry[116...120].unpack('V')[0] stream_size = dentry[120...124].unpack('V')[0] @dir_entry_list << [did, sz, name, t, c, did_left, did_right, did_root, dentry_start_sid, stream_size] end end |
#build_header ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/surpass/document.rb', line 65 def build_header @doc_magic = @header[0...8] raise 'Not an OLE file.' unless @doc_magic === "\320\317\021\340\241\261\032\341" @file_uid = @header[8...24] @rev_num = @header[24...26] @ver_num = @header[26...28] @byte_order = @header[28...30] @log2_sect_size = @header[30...32].unpack('v')[0] @log2_short_sect_size = @header[32...34].unpack('v')[0] @total_sat_sectors = @header[44...48].unpack('V')[0] @dir_start_sid = @header[48...52].unpack('V')[0] @min_stream_size = @header[56...60].unpack('V')[0] @ssat_start_sid = @header[60...64].unpack('V')[0] @total_ssat_sectors = @header[64...68].unpack('V')[0] @msat_start_sid = @header[68...72].unpack('V')[0] @total_msat_sectors = @header[72...76].unpack('V')[0] @sect_size = 1 << @log2_sect_size @short_sect_size = 1 << @log2_short_sect_size end |
#build_msat ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/surpass/document.rb', line 87 def build_msat @msat = @header[76..-1].unpack('V109') next_sector = @msat_start_sid while next_sector > 0 do raise "not implemented" start = next_sector * @sect_size finish = (next_sector + 1) * @sect_size msat_sector = @data[start...finish] @msat << msat_sector next_sector = msat_sector[-1] end end |
#build_sat ⇒ Object
100 101 102 103 |
# File 'lib/surpass/document.rb', line 100 def build_sat sat_stream = @msat.collect {|i| i >= 0 ? @data[(i*@sect_size)...((i+1)*@sect_size)] : '' }.join @sat = sat_stream.unpack('V*') end |
#build_short_sectors_data ⇒ Object
139 140 141 142 143 144 145 146 147 148 |
# File 'lib/surpass/document.rb', line 139 def build_short_sectors_data did, sz, name, t, c, did_left, did_right, did_root, dentry_start_sid, stream_size = @dir_entry_list[0] raise unless t == 0x05 # Short-Stream Container Stream (SSCS) resides in Root Storage if stream_size == 0 @short_sectors_data = '' else @short_sectors_data = stream_data(@data, @sat, dentry_start_sid, @sect_size) end end |
#build_ssat ⇒ Object
105 106 107 108 |
# File 'lib/surpass/document.rb', line 105 def build_ssat ssat_stream = stream_data(@data, @sat, @ssat_start_sid, @sect_size) @ssat = ssat_stream.unpack('V*') end |
#stream_data(data, sat, start_sid, sect_size) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/surpass/document.rb', line 150 def stream_data(data, sat, start_sid, sect_size) sid = start_sid chunks = [[sid, sid]] stream_data = '' while sat[sid] >= 0 do next_in_chain = sat[sid] last_chunk_start, last_chunk_finish = chunks[-1] if next_in_chain == last_chunk_finish + 1 chunks[-1] = last_chunk_start, next_in_chain else chunks << [next_in_chain, next_in_chain] end sid = next_in_chain end chunks.each do |s, f| stream_data += data[s*sect_size...(f+1)*sect_size] end stream_data end |