Skip to content

Commit 20eafbb

Browse files
committed
More misc clean-ups.
git-svn-id: https://ruby-msg.googlecode.com/svn/trunk@121 c30d66de-b626-0410-988f-81f6512a6d81
1 parent 2eadc1f commit 20eafbb

File tree

5 files changed

+45
-99
lines changed

5 files changed

+45
-99
lines changed

Rakefile

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,21 @@ Rake::RDocTask.new do |t|
4545
end
4646

4747
spec = Gem::Specification.new do |s|
48-
s.name = PKG_NAME
49-
s.version = PKG_VERSION
50-
s.summary = %q{Ruby Msg library.}
48+
s.name = PKG_NAME
49+
s.version = PKG_VERSION
50+
s.summary = %q{Ruby Msg library.}
5151
s.description = %q{A library for reading Outlook msg files, and for converting them to RFC2822 emails.}
52-
s.authors = ["Charles Lowe"]
53-
s.email = %q{aquasync@gmail.com}
54-
s.homepage = %q{http://code.google.com/p/ruby-msg}
52+
s.authors = ["Charles Lowe"]
53+
s.email = %q{aquasync@gmail.com}
54+
s.homepage = %q{http://code.google.com/p/ruby-msg}
5555
s.rubyforge_project = %q{ruby-msg}
5656

5757
s.executables = ['msgtool']
58-
s.files = Dir.glob('data/*.yaml') + ['Rakefile', 'README', 'FIXES']
59-
s.files += Dir.glob("lib/**/*.rb")
60-
s.files += Dir.glob("test/test_*.rb")
61-
s.files += Dir.glob("bin/*")
58+
s.files = FileList['data/*.yaml', 'Rakefile', 'README', 'FIXES']
59+
s.files += FileList['lib/**/*.rb', 'test/test_*.rb', 'bin/*']
6260

63-
s.has_rdoc = true
61+
s.has_rdoc = true
62+
s.extra_rdoc_files = ['README']
6463
s.rdoc_options += ['--main', 'README',
6564
'--title', "#{PKG_NAME} documentation",
6665
'--tab-width', '2']

TODO

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
= Newer Msg
22

3+
* extend msgtool with support for the other kinds of msg files. things like,
4+
- dump properties to yaml / xml (with option on how the keys should be dumped).
5+
should be fairly easy to implement. hash, with array of attach & recips.
6+
- just write out the mime type
7+
- convert to a certain output type, maybe supporting an override of some
8+
sort.
9+
- options regarding preferring rtf / html / txt output for things. like, eg
10+
the output for note conversion, will be one of them i guess.
11+
312
* fix nameid handling for sub Properties objects. needs to inherit top-level @nameid.
413

514
* better handling for "Untitled Attachments", or attachments with no filename at all.

lib/mapi.rb

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,6 @@
22
require 'mapi/property_set'
33

44
module Mapi
5-
=begin
6-
# IMessage essentially, but there's also stuff like IMAPIFolder etc. so, for this to form
7-
# basis for PST Item, it'd need to be more general.
8-
class Item #< Msg
9-
# IAttach
10-
class Attachment #< Msg::Attachment
11-
end
12-
13-
14-
class Recipient #< Recipient
15-
end
16-
17-
# +props+ should be a PropertyStore object.
18-
def initialize props
19-
@properties = props
20-
@mime = Mime.new props.transport_message_headers.to_s, true
21-
22-
# hack
23-
@root = OpenStruct.new(:ole => OpenStruct.new(:dirents => [OpenStruct.new(:time => nil)]))
24-
populate_headers
25-
end
26-
end
27-
=end
28-
295
class ObjectWithProperties
306
attr_reader :properties
317
alias props properties
@@ -100,6 +76,9 @@ def inspect
10076

10177
# i refer to it as a message (as does mapi), although perhaps Item is better, as its a more general
10278
# concept than a message
79+
#
80+
# IMessage essentially, but there's also stuff like IMAPIFolder etc. so, for this to form
81+
# basis for PST Item, it'd need to be more general.
10382
class Message < ObjectWithProperties
10483
# these 2 collections should be provided by our subclasses
10584
def attachments
@@ -110,43 +89,5 @@ def recipients
11089
raise NotImplementedError
11190
end
11291
end
113-
114-
# the #to_mime logic will be refactored out into mapi/to_mime.rb
115-
# will probably ditch custom Mime class, and go with TMail. to_mime.rb
116-
# will include that mapping, as well as vcard, etc etc. or, i'll have
117-
# mapi/to_mime/message.rb mapi/to_mime/vcard.rb mapi/to_mime/ical.rb
118-
# i will add minimal functionality to the base classes beyond that.
119-
# the msg parsing will be consolidated into mapi/msg.rb
120-
# the pst parsing will go into mapi/pst.rb
121-
# rtf related code will be in rtf.rb and mapi/rtf.rb
12292
end
12393

124-
#message = Mapi::Msg.open 'test-swetlana_novikova.msg'
125-
#message = Mapi::Msg.open ARGV.first #'test-swetlana_novikova.msg'
126-
#p message.props
127-
#p message.props.message_class
128-
#puts message.convert
129-
130-
Mapi::Msg.open 'test_Blammo.msg' do |msg|
131-
puts msg.to_mime.to_tree
132-
puts msg.to_mime.to_s
133-
end if $0 == __FILE__
134-
135-
__END__
136-
137-
pst = Mapi::Pst.open 'test.pst'
138-
message2 = pst.find { |m| m.path =~ /^inbox\/test/i and m.subject == 'test' }
139-
140-
# what about conversion. i'm thinking something like:
141-
# Mapi::PropertyStore#replace and/or #update
142-
# and similarly, Message#replace. so you can do something like:
143-
144-
message3 = Mapi::Msg.open 'test2.msg', 'rb+' # creates empty msg file
145-
message3.update message2 # recursively copy all properties
146-
message3.close
147-
148-
# can define Message#to_msg as a shortcut to this. similarly, in the unlikely
149-
# event that pst write support is ever implemented.
150-
151-
# needs to be cheap to create a message, not like the current situation. ie, fully lazily loading.
152-
# on the other hand, the inspect strings will probably cause things to be loaded, but thats ok.

lib/mapi/msg.rb

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,11 @@ class Msg < Message
8787
#
8888
# = TODO
8989
#
90-
# * Test cases.
9190
# * While the key objects are sufficient, the value objects are just plain
9291
# ruby types. It currently isn't possible to write to the values, or to know
9392
# which encoding the value had.
94-
# * Consider other MAPI property stores, such as tnef/pst. Similar model?
95-
# Generalise this one?
93+
# * Update this doc.
94+
# * Perhaps change from eager loading, to be load-on-demand.
9695
#
9796
class PropertyStore
9897
include PropertySet::Constants
@@ -117,23 +116,19 @@ class PropertyStore
117116
NAMEID_RX = /^__nameid_version1\.0$/
118117
VALID_RX = /#{SUBSTG_RX}|#{PROPERTIES_RX}|#{NAMEID_RX}/
119118

120-
# access the underlying raw property hash
121-
attr_reader :raw
122119
attr_reader :nameid
123120

124121
def initialize
125-
@raw = {}
126-
@unused = []
127122
@nameid = nil
128-
# FIXME
129-
@body_rtf = @body_html = @body = false
123+
# not exactly a cache currently
124+
@cache = {}
130125
end
131126

132127
#--
133128
# The parsing methods
134129
#++
135130

136-
def self.load obj, ignore=nil
131+
def self.load obj
137132
prop = new
138133
prop.load obj
139134
prop
@@ -306,23 +301,21 @@ def add_property key, value, pos=nil
306301
key = Key.new key
307302
end
308303
if pos
309-
@raw[key] ||= []
310-
Log.warn "duplicate property" unless Array === @raw[key]
304+
@cache[key] ||= []
305+
Log.warn "duplicate property" unless Array === @cache[key]
311306
# ^ this is actually a trickier problem. the issue is more that they must all be of
312307
# the same type.
313-
@raw[key][pos] = value
308+
@cache[key][pos] = value
314309
else
315310
# take the last.
316-
Log.warn "duplicate property #{key.inspect}" if @raw[key]
317-
@raw[key] = value
311+
Log.warn "duplicate property #{key.inspect}" if @cache[key]
312+
@cache[key] = value
318313
end
319314
end
320315

321-
def inspect
322-
'#<Properties ' + to_h.map do |k, v|
323-
v = v.inspect
324-
"#{k}=#{v.length > 32 ? v[0..29] + '..."' : v}"
325-
end.join(' ') + '>'
316+
# delegate to cache
317+
def method_missing name, *args, &block
318+
@cache.send name, *args, &block
326319
end
327320
end
328321

@@ -355,7 +348,7 @@ def self.open arg, mode=nil
355348
def initialize root
356349
@root = root
357350
@close_parent = false
358-
super PropertySet.new(PropertyStore.load(@root).raw)
351+
super PropertySet.new(PropertyStore.load(@root))
359352
Msg.warn_unknown @root
360353
end
361354

@@ -396,11 +389,10 @@ class Attachment < Mapi::Attachment
396389

397390
def initialize obj
398391
@obj = obj
399-
@properties = Properties.load @obj
400392
@embedded_ole = nil
401393
@embedded_msg = nil
402394

403-
super PropertySet.new(PropertyStore.load(@obj).raw)
395+
super PropertySet.new(PropertyStore.load(@obj))
404396
Msg.warn_unknown @obj
405397

406398
@obj.children.each do |child|
@@ -448,7 +440,7 @@ class Recipient < Mapi::Recipient
448440

449441
def initialize obj
450442
@obj = obj
451-
super PropertySet.new(PropertyStore.load(@obj).raw)
443+
super PropertySet.new(PropertyStore.load(@obj))
452444
Msg.warn_unknown @obj
453445
end
454446
end

lib/mapi/property_set.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,13 @@ def method_missing name, *args
222222
def to_h
223223
sym_to_key.inject({}) { |hash, (sym, key)| hash.update sym => raw[key] }
224224
end
225-
226-
# the other pseudo properties like body_html, body_rtf etc that are inferred will exist here.
225+
226+
def inspect
227+
"#<#{self.class} " + to_h.sort_by { |k, v| k.to_s }.map do |k, v|
228+
v = v.inspect
229+
"#{k}=#{v.length > 32 ? v[0..29] + '..."' : v}"
230+
end.join(' ') + '>'
231+
end
227232

228233
# -----
229234

0 commit comments

Comments
 (0)