Class: Mapi::Pst::Header

Inherits:
Object
  • Object
show all
Defined in:
lib/mapi/pst.rb

Overview

class which encapsulates the pst header

Constant Summary collapse

SIZE =
512
MAGIC =
0x2142444e
INDEX_TYPE_OFFSET =

these are the constants defined in libpst.c, that are referenced in pst_open()

0x0A
FILE_SIZE_POINTER =
0xA8
FILE_SIZE_POINTER_64 =
0xB8
SECOND_POINTER =
0xBC
INDEX_POINTER =
0xC4
SECOND_POINTER_64 =
0xE0
INDEX_POINTER_64 =
0xF0
ENC_OFFSET =
0x1CD

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Header

Returns a new instance of Header.



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/mapi/pst.rb', line 126

def initialize data
	@magic = data.unpack('N')[0]
	@index_type = data[INDEX_TYPE_OFFSET]
	@version = {0x0e => 1997, 0x17 => 2003}[@index_type]

	if version_2003?
		# don't know?
		# >> data1.unpack('V*').zip(data2.unpack('V*')).enum_with_index.select { |(c, d), i| c != d and not [46, 56, 60].include?(i) }.select { |(a, b), i| b == 0 }.map { |(a, b), i| [a / 256, i] }
		#   [8, 76], [32768, 84], [128, 89]
		# >> data1.unpack('C*').zip(data2.unpack('C*')).enum_with_index.select { |(c, d), i| c != d and not [184..187, 224..227, 240..243].any? { |r| r === i } }.select { |(a, b), i| b == 0 and ((Math.log(a) / Math.log(2)) % 1) < 0.0001 }
		#   [[[2, 0], 61], [[2, 0], 76], [[2, 0], 195], [[2, 0], 257], [[8, 0], 305], [[128, 0], 338], [[128, 0], 357]]
		# i have only 2 psts to base this guess on, so i can't really come up with anything that looks reasonable yet. not sure what the offset is. unfortunately there is so much in the header
		# that isn't understood...
		@encrypt_type = 1

		@index2_count, @index2 = data[SECOND_POINTER_64 - 4, 8].unpack('V2')
		@index1_count, @index1 = data[INDEX_POINTER_64  - 4, 8].unpack('V2')

		@size = data[FILE_SIZE_POINTER_64, 4].unpack('V')[0]
	else
		@encrypt_type = data[ENC_OFFSET]

		@index2_count, @index2 = data[SECOND_POINTER - 4, 8].unpack('V2')
		@index1_count, @index1 = data[INDEX_POINTER  - 4, 8].unpack('V2')

		@size = data[FILE_SIZE_POINTER, 4].unpack('V')[0]
	end

	validate!
end

Instance Attribute Details

#encrypt_typeObject (readonly)

Returns the value of attribute encrypt_type.



123
124
125
# File 'lib/mapi/pst.rb', line 123

def encrypt_type
  @encrypt_type
end

#index1Object (readonly)

Returns the value of attribute index1.



124
125
126
# File 'lib/mapi/pst.rb', line 124

def index1
  @index1
end

#index1_countObject (readonly)

Returns the value of attribute index1_count.



124
125
126
# File 'lib/mapi/pst.rb', line 124

def index1_count
  @index1_count
end

#index2Object (readonly)

Returns the value of attribute index2.



124
125
126
# File 'lib/mapi/pst.rb', line 124

def index2
  @index2
end

#index2_countObject (readonly)

Returns the value of attribute index2_count.



124
125
126
# File 'lib/mapi/pst.rb', line 124

def index2_count
  @index2_count
end

#index_typeObject (readonly)

Returns the value of attribute index_type.



123
124
125
# File 'lib/mapi/pst.rb', line 123

def index_type
  @index_type
end

#magicObject (readonly)

Returns the value of attribute magic.



123
124
125
# File 'lib/mapi/pst.rb', line 123

def magic
  @magic
end

#sizeObject (readonly)

Returns the value of attribute size.



123
124
125
# File 'lib/mapi/pst.rb', line 123

def size
  @size
end

#versionObject (readonly)

Returns the value of attribute version.



125
126
127
# File 'lib/mapi/pst.rb', line 125

def version
  @version
end

Instance Method Details

#encrypted?Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/mapi/pst.rb', line 161

def encrypted?
	encrypt_type != 0
end

#validate!Object

Raises:



165
166
167
168
169
# File 'lib/mapi/pst.rb', line 165

def validate!
	raise FormatError, "bad signature on pst file (#{'0x%x' % magic})" unless magic == MAGIC
	raise FormatError, "only index types 0x0e and 0x17 are handled (#{'0x%x' % index_type})" unless [0x0e, 0x17].include?(index_type)
	raise FormatError, "only encrytion types 0 and 1 are handled (#{encrypt_type.inspect})" unless [0, 1].include?(encrypt_type)
end

#version_2003?Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/mapi/pst.rb', line 157

def version_2003?
	version == 2003
end