Class: MsgExtractor::Mapi::PropertyStore
- Inherits:
-
Object
- Object
- MsgExtractor::Mapi::PropertyStore
- Defined in:
- lib/msg_extractor/mapi/property_store.rb
Overview
Reads the MAPI properties of one storage: fixed-width values from the __properties_version1.0 stream, variable-width values from companion __substg1.0_XXXXYYYY streams. The properties stream header length depends on what kind of storage this is.
Constant Summary collapse
- HEADER_SIZES =
{ root: 32, embedded: 24, attachment: 8, recipient: 8 }.freeze
- SUBSTG_RE =
/\A__SUBSTG1\.0_([0-9A-F]{4})([0-9A-F]{4})\z/- VARIABLE_WIDTH_TYPES =
Variable-width types (PT_UNICODE, PT_STRING8, PT_BINARY, PT_OBJECT, PT_CLSID) must be sourced from a substg stream. If one appears only in rather than decoding garbage.
[ MsgExtractor::Mapi::PT_UNICODE, MsgExtractor::Mapi::PT_STRING8, MsgExtractor::Mapi::PT_BINARY, MsgExtractor::Mapi::PT_OBJECT, MsgExtractor::Mapi::PT_CLSID ].freeze
Instance Attribute Summary collapse
-
#attachment_count ⇒ Object
readonly
These counts come directly from the file and are untrusted; the model layer iterates actual storages rather than relying on them.
-
#recipient_count ⇒ Object
readonly
These counts come directly from the file and are untrusted; the model layer iterates actual storages rather than relying on them.
Instance Method Summary collapse
- #[](id) ⇒ Object
- #codepage ⇒ Object
-
#initialize(cfbf, storage, kind) ⇒ PropertyStore
constructor
A new instance of PropertyStore.
- #internet_codepage ⇒ Object
- #key?(id) ⇒ Boolean
-
#raw(id) ⇒ Object
Raw bytes without decoding (binary props, or the 8-byte record field).
- #type_of(id) ⇒ Object
Constructor Details
#initialize(cfbf, storage, kind) ⇒ PropertyStore
Returns a new instance of PropertyStore.
16 17 18 19 20 21 22 23 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 16 def initialize(cfbf, storage, kind) @cfbf = cfbf @storage = storage @kind = kind @records = {} # id => [type, 8-byte value field] @streams = {} # id => [type, Cfbf::Entry] parse end |
Instance Attribute Details
#attachment_count ⇒ Object (readonly)
These counts come directly from the file and are untrusted; the model layer iterates actual storages rather than relying on them.
12 13 14 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 12 def @attachment_count end |
#recipient_count ⇒ Object (readonly)
These counts come directly from the file and are untrusted; the model layer iterates actual storages rather than relying on them.
12 13 14 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 12 def recipient_count @recipient_count end |
Instance Method Details
#[](id) ⇒ Object
39 40 41 42 43 44 45 46 47 48 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 39 def [](id) if (type_entry = @streams[id]) type, entry = type_entry Decoders.decode(type, @cfbf.read_stream(entry), codepage: codepage) elsif (type_value = @records[id]) type, value = type_value return nil if VARIABLE_WIDTH_TYPES.include?(type) Decoders.decode(type, value, codepage: codepage) end end |
#codepage ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 61 def codepage @codepage ||= if (record = @records[PR_MESSAGE_CODEPAGE]) record[1].unpack1("l<") else 1252 end end |
#internet_codepage ⇒ Object
70 71 72 73 74 75 76 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 70 def internet_codepage if (record = @records[PR_INTERNET_CPID]) record[1].unpack1("l<") else codepage end end |
#key?(id) ⇒ Boolean
25 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 25 def key?(id) = @streams.key?(id) || @records.key?(id) |
#raw(id) ⇒ Object
Raw bytes without decoding (binary props, or the 8-byte record field).
51 52 53 54 55 56 57 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 51 def raw(id) if (type_entry = @streams[id]) @cfbf.read_stream(type_entry[1]) elsif (type_value = @records[id]) type_value[1] end end |
#type_of(id) ⇒ Object
59 |
# File 'lib/msg_extractor/mapi/property_store.rb', line 59 def type_of(id) = (@streams[id] || @records[id])&.first |