Class: Mapi::PropertySet
- Inherits:
-
Object
- Object
- Mapi::PropertySet
- Includes:
- Constants
- Defined in:
- lib/mapi/property_set.rb
Overview
The Mapi::PropertySet class is used to wrap the lower level Msg or Pst property stores, and provide a consistent and more friendly interface. It allows you to just say:
properties.subject
instead of:
properites.raw[0x0037, PS_MAPI]
The underlying store can be just a hash, or lazily loading directly from the file. A good compromise is to cache all the available keys, and just return the values on demand, rather than load up many possibly unwanted values.
Defined Under Namespace
Modules: Constants Classes: Key
Constant Summary collapse
- NAMES =
{ oleguid['00020328'] => 'PS_MAPI', oleguid['00020329'] => 'PS_PUBLIC_STRINGS', oleguid['00020380'] => 'PS_ROUTING_EMAIL_ADDRESSES', oleguid['00020381'] => 'PS_ROUTING_ADDRTYPE', oleguid['00020382'] => 'PS_ROUTING_DISPLAY_NAME', oleguid['00020383'] => 'PS_ROUTING_ENTRYID', oleguid['00020384'] => 'PS_ROUTING_SEARCH_KEY', # string properties in this namespace automatically get added to the internet headers oleguid['00020386'] => 'PS_INTERNET_HEADERS', # theres are bunch of outlook ones i think # http://blogs.msdn.com/stephen_griffin/archive/2006/05/10/outlook-2007-beta-documentation-notification-based-indexing-support.aspx # IPM.Appointment oleguid['00062002'] => 'PSETID_Appointment', # IPM.Task oleguid['00062003'] => 'PSETID_Task', # used for IPM.Contact oleguid['00062004'] => 'PSETID_Address', oleguid['00062008'] => 'PSETID_Common', # didn't find a source for this name. it is for IPM.StickyNote oleguid['0006200e'] => 'PSETID_Note', # for IPM.Activity. also called the journal? oleguid['0006200a'] => 'PSETID_Log', }
- SUPPORT_DIR =
duplicated here for now
File.dirname(__FILE__) + '/../..'
- TAGS =
data files that provide for the code to symbolic name mapping guids in named_map are really constant references to the above
YAML.load_file "#{SUPPORT_DIR}/data/mapitags.yaml"
- NAMED_MAP =
YAML.load_file("#{SUPPORT_DIR}/data/named_map.yaml").inject({}) do |hash, (key, value)| hash.update Key.new(key[0], const_get(key[1])) => value end
Instance Attribute Summary collapse
-
#raw ⇒ Object
readonly
Returns the value of attribute raw.
Instance Method Summary collapse
- #[](arg, guid = nil) ⇒ Object
- #[]=(arg, *args) ⇒ Object
-
#body ⇒ Object
for providing rtf to plain text conversion.
-
#body_html ⇒ Object
for providing rtf to html conversion.
-
#body_rtf ⇒ Object
for providing rtf decompression.
-
#initialize(raw) ⇒ PropertySet
constructor
rawshould be an hash-like object that mapsKeys to values. - #inspect ⇒ Object
- #keys ⇒ Object
- #method_missing(name, *args) ⇒ Object
-
#resolve(arg, guid = nil) ⇒ Object
resolve
arg(could be key, code, string, or symbol), and possibleguidto a key. -
#sym_to_key ⇒ Object
this is the function that creates a symbol to key mapping.
- #to_h ⇒ Object
- #values ⇒ Object
Constructor Details
#initialize(raw) ⇒ PropertySet
raw should be an hash-like object that maps Keys to values. Should respond_to? [], keys, values, each, and optionally []=, and delete.
150 151 152 |
# File 'lib/mapi/property_set.rb', line 150 def initialize raw @raw = raw end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object
212 213 214 215 216 217 218 219 220 |
# File 'lib/mapi/property_set.rb', line 212 def method_missing name, *args if name.to_s !~ /\=$/ and args.empty? self[name] elsif name.to_s =~ /(.*)\=$/ and args.length == 1 self[$1] = args[0] else super end end |
Instance Attribute Details
#raw ⇒ Object (readonly)
Returns the value of attribute raw.
146 147 148 |
# File 'lib/mapi/property_set.rb', line 146 def raw @raw end |
Instance Method Details
#[](arg, guid = nil) ⇒ Object
200 201 202 |
# File 'lib/mapi/property_set.rb', line 200 def [] arg, guid=nil raw[resolve(arg, guid)] end |
#[]=(arg, *args) ⇒ Object
204 205 206 207 208 209 210 |
# File 'lib/mapi/property_set.rb', line 204 def []= arg, *args args.unshift nil if args.length == 1 guid, value = args # FIXME this won't really work properly. it would need to go # to TAGS to resolve, as it often won't be there already... raw[resolve(arg, guid)] = value end |
#body ⇒ Object
for providing rtf to plain text conversion. later, html to text too.
238 239 240 241 242 243 244 245 246 247 |
# File 'lib/mapi/property_set.rb', line 238 def body return @body if defined?(@body) @body = (self[:body] rescue nil) # last resort if !@body or @body.strip.empty? Log.warn 'creating text body from rtf' @body = (::RTF::Converter.rtf2text body_rtf rescue nil) end @body end |
#body_html ⇒ Object
for providing rtf to html conversion
256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/mapi/property_set.rb', line 256 def body_html return @body_html if defined?(@body_html) @body_html = (self[:body_html].read rescue nil) @body_html = (RTF.rtf2html body_rtf rescue nil) if !@body_html or @body_html.strip.empty? # last resort if !@body_html or @body_html.strip.empty? Log.warn 'creating html body from rtf' @body_html = (::RTF::Converter.rtf2text body_rtf, :html rescue nil) end @body_html end |
#body_rtf ⇒ Object
for providing rtf decompression
250 251 252 253 |
# File 'lib/mapi/property_set.rb', line 250 def body_rtf return @body_rtf if defined?(@body_rtf) @body_rtf = (RTF.rtfdecompr rtf_compressed.read rescue nil) end |
#inspect ⇒ Object
226 227 228 229 230 231 |
# File 'lib/mapi/property_set.rb', line 226 def inspect "#<#{self.class} " + to_h.sort_by { |k, v| k.to_s }.map do |k, v| v = v.inspect "#{k}=#{v.length > 32 ? v[0..29] + '..."' : v}" end.join(' ') + '>' end |
#keys ⇒ Object
192 193 194 |
# File 'lib/mapi/property_set.rb', line 192 def keys sym_to_key.keys end |
#resolve(arg, guid = nil) ⇒ Object
resolve arg (could be key, code, string, or symbol), and possible guid to a key. returns nil on failure
156 157 158 159 160 161 162 163 164 165 |
# File 'lib/mapi/property_set.rb', line 156 def resolve arg, guid=nil if guid; Key.new arg, guid else case arg when Key; arg when Integer; Key.new arg else sym_to_key[arg.to_sym] end end end |
#sym_to_key ⇒ Object
this is the function that creates a symbol to key mapping. currently this works by making a pass through the raw properties, but conceivably you could map symbols to keys using the mapitags directly. problem with that would be that named properties wouldn’t map automatically, but maybe thats not too important.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/mapi/property_set.rb', line 171 def sym_to_key return @sym_to_key if @sym_to_key @sym_to_key = {} raw.keys.each do |key| sym = key.to_sym unless Symbol === sym Log.debug "couldn't find symbolic name for key #{key.inspect}" next end if @sym_to_key[sym] Log.warn "duplicate key #{key.inspect}" # we give preference to PS_MAPI keys @sym_to_key[sym] = key if key.guid == PS_MAPI else # just assign @sym_to_key[sym] = key end end @sym_to_key end |
#to_h ⇒ Object
222 223 224 |
# File 'lib/mapi/property_set.rb', line 222 def to_h sym_to_key.inject({}) { |hash, (sym, key)| hash.update sym => raw[key] } end |
#values ⇒ Object
196 197 198 |
# File 'lib/mapi/property_set.rb', line 196 def values sym_to_key.values.map { |key| raw[key] } end |