ruby-msg 1.2.17.3 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/FIXES +22 -0
- data/Rakefile +13 -16
- data/bin/msgtool +1 -1
- data/lib/msg.rb +26 -9
- data/lib/msg/properties.rb +28 -11
- metadata +19 -18
- data/bin/oletool +0 -35
- data/lib/ole/base.rb +0 -5
- data/lib/ole/file_system.rb +0 -181
- data/lib/ole/io_helpers.rb +0 -184
- data/lib/ole/storage.rb +0 -927
- data/lib/ole/types.rb +0 -36
- data/lib/support.rb +0 -51
- data/test/test_storage.rb +0 -139
- data/test/test_word_6.doc +0 -0
- data/test/test_word_95.doc +0 -0
- data/test/test_word_97.doc +0 -0
data/FIXES
CHANGED
@@ -32,3 +32,25 @@ recent fixes based on importing results into evolution
|
|
32
32
|
|
33
33
|
6. still unsure about how to do my "\r" handling.
|
34
34
|
|
35
|
+
7. need to join addresses with , instead of ; i think. evolution only shows the
|
36
|
+
first one otherwise it appears, but all when they are , separated.
|
37
|
+
|
38
|
+
8. need to solve ole storage issues with the very large file using extra bat
|
39
|
+
stuff.
|
40
|
+
|
41
|
+
9. retest a bit on evolution and thunderbird, and release. tested on a corups
|
42
|
+
of >1000 msg files, so should be starting to get pretty good quality.
|
43
|
+
|
44
|
+
10. longer term, things fall into a few basic categories:
|
45
|
+
|
46
|
+
- non mail conversions (look further into vcard, ical et al support for other
|
47
|
+
types of msg)
|
48
|
+
- further tests and robustness for what i handle now. ie, look into corner
|
49
|
+
cases covered so far, and work on the mime code. fix random charset encoding
|
50
|
+
issues, in the various weird mime ways, do header wrapping etc etc.
|
51
|
+
check fidelity of conversions, and capture some more properties as headers,
|
52
|
+
such as importance which i don't do yet.
|
53
|
+
- fix that named property bug. tidy up warnings, exceptions.
|
54
|
+
- extend conversion to make better html.
|
55
|
+
this is longer term. as i don't use the rtf, i need to make my html better.
|
56
|
+
emulating some rtf things. harder, not important atm.
|
data/Rakefile
CHANGED
@@ -6,8 +6,9 @@ require 'rake/gempackagetask'
|
|
6
6
|
require 'rbconfig'
|
7
7
|
require 'fileutils'
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
$:.unshift 'lib'
|
10
|
+
|
11
|
+
require 'msg'
|
11
12
|
|
12
13
|
PKG_NAME = 'ruby-msg'
|
13
14
|
PKG_VERSION = Msg::VERSION
|
@@ -23,18 +24,8 @@ end
|
|
23
24
|
# RDocTask wasn't working for me
|
24
25
|
desc 'Build the rdoc HTML Files'
|
25
26
|
task :rdoc do
|
26
|
-
system "rdoc -S -N
|
27
|
-
end
|
28
|
-
|
29
|
-
=begin
|
30
|
-
Rake::PackageTask.new(PKG_NAME, PKG_VERSION) do |p|
|
31
|
-
p.need_tar_gz = true
|
32
|
-
p.package_dir = 'build'
|
33
|
-
p.package_files.include("Rakefile", "README")
|
34
|
-
p.package_files.include("contrib/*.c")
|
35
|
-
p.package_files.include("test/test_*.rb", "test/*.doc", "lib/*.rb", "lib/ole/storage.rb")
|
27
|
+
system "rdoc -S -N --main Msg --tab-width 2 --title '#{PKG_NAME} documentation' lib"
|
36
28
|
end
|
37
|
-
=end
|
38
29
|
|
39
30
|
spec = Gem::Specification.new do |s|
|
40
31
|
s.name = PKG_NAME
|
@@ -46,20 +37,26 @@ spec = Gem::Specification.new do |s|
|
|
46
37
|
s.homepage = %q{http://code.google.com/p/ruby-msg}
|
47
38
|
#s.rubyforge_project = %q{ruby-msg}
|
48
39
|
|
49
|
-
s.executables = ['msgtool'
|
40
|
+
s.executables = ['msgtool']
|
50
41
|
s.files = Dir.glob('data/*.yaml') + ['Rakefile', 'README', 'FIXES']
|
51
42
|
s.files += Dir.glob("lib/**/*.rb")
|
52
|
-
s.files += Dir.glob("test/test_*.rb")
|
43
|
+
s.files += Dir.glob("test/test_*.rb")
|
53
44
|
s.files += Dir.glob("bin/*")
|
54
45
|
|
55
46
|
s.has_rdoc = true
|
47
|
+
s.rdoc_options += ['--main', 'Msg',
|
48
|
+
'--title', "#{PKG_NAME} documentation",
|
49
|
+
'--tab-width', '2']
|
50
|
+
|
56
51
|
|
57
52
|
s.autorequire = 'msg'
|
53
|
+
|
54
|
+
s.add_dependency 'ruby-ole', '>=1.2.1'
|
58
55
|
end
|
59
56
|
|
60
57
|
Rake::GemPackageTask.new(spec) do |p|
|
61
58
|
p.gem_spec = spec
|
62
|
-
|
59
|
+
p.need_tar = true
|
63
60
|
p.need_zip = false
|
64
61
|
p.package_dir = 'build'
|
65
62
|
end
|
data/bin/msgtool
CHANGED
data/lib/msg.rb
CHANGED
@@ -5,7 +5,7 @@ $: << File.dirname(__FILE__)
|
|
5
5
|
require 'yaml'
|
6
6
|
require 'base64'
|
7
7
|
|
8
|
-
require '
|
8
|
+
require 'rubygems'
|
9
9
|
require 'ole/storage'
|
10
10
|
require 'msg/properties'
|
11
11
|
require 'msg/rtf'
|
@@ -20,7 +20,7 @@ require 'mime'
|
|
20
20
|
#
|
21
21
|
|
22
22
|
class Msg
|
23
|
-
VERSION = '1.
|
23
|
+
VERSION = '1.3.1'
|
24
24
|
# we look here for the yaml files in data/, and the exe files for support
|
25
25
|
# decoding at the moment.
|
26
26
|
SUPPORT_DIR = File.dirname(__FILE__) + '/..'
|
@@ -144,9 +144,9 @@ class Msg
|
|
144
144
|
# of the ole name, or just leave it if we can't
|
145
145
|
recips = recips_by_type[type]
|
146
146
|
recips = (recips.sort_by { |r| r.obj.name[/\d{8}$/].hex } rescue recips)
|
147
|
-
#
|
147
|
+
# switched to using , for separation, not ;. see issue #4
|
148
148
|
# recips.empty? is strange. i wouldn't have thought it possible, but it was right?
|
149
|
-
headers[type.to_s.sub(/^(.)/) { $1.upcase }] = [recips.join('
|
149
|
+
headers[type.to_s.sub(/^(.)/) { $1.upcase }] = [recips.join(', ')] unless recips.empty?
|
150
150
|
end
|
151
151
|
headers['Subject'] = [props.subject] if props.subject
|
152
152
|
|
@@ -171,11 +171,28 @@ class Msg
|
|
171
171
|
headers['Date'] = [Time.iso8601(time.to_s).rfc2822] if time
|
172
172
|
end
|
173
173
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
174
|
+
# some very simplistic mapping between internet message headers and the
|
175
|
+
# mapi properties
|
176
|
+
# any of these could be causing duplicates due to case issues. the hack in #to_mime
|
177
|
+
# just stops re-duplication at that point. need to move some smarts into the mime
|
178
|
+
# code to handle it.
|
179
|
+
mapi_header_map = [
|
180
|
+
[:internet_message_id, 'Message-ID'],
|
181
|
+
[:in_reply_to_id, 'In-Reply-To'],
|
182
|
+
# don't set these values if they're equal to the defaults anyway
|
183
|
+
[:importance, 'Importance', proc { |val| val.to_s == '1' ? nil : val }],
|
184
|
+
[:priority, 'Priority', proc { |val| val.to_s == '1' ? nil : val }],
|
185
|
+
[:sensitivity, 'Sensitivity', proc { |val| val.to_s == '0' ? nil : val }],
|
186
|
+
# yeah?
|
187
|
+
[:conversation_topic, 'Thread-Topic'],
|
188
|
+
# not sure of the distinction here
|
189
|
+
# :originator_delivery_report_requested ??
|
190
|
+
[:read_receipt_requested, 'Disposition-Notification-To', proc { |val| from }]
|
191
|
+
]
|
192
|
+
mapi_header_map.each do |mapi, mime, *f|
|
193
|
+
next unless q = val = props.send(mapi) or headers.has_key?(mime)
|
194
|
+
next if f[0] and !(val = f[0].call(val))
|
195
|
+
headers[mime] = [val.to_s]
|
179
196
|
end
|
180
197
|
end
|
181
198
|
|
data/lib/msg/properties.rb
CHANGED
@@ -48,24 +48,28 @@ class Msg
|
|
48
48
|
# There also needs to be a way to look up properties more specifically:
|
49
49
|
#
|
50
50
|
# properties[0x0037] # => gets the subject
|
51
|
-
# properties[
|
52
|
-
# properties[
|
51
|
+
# properties[0x0037, PS_MAPI] # => still gets the subject
|
52
|
+
# properties['Keywords', PS_PUBLIC_STRINGS] # => gets outlook's categories array
|
53
53
|
#
|
54
|
-
# The
|
54
|
+
# The abbreviated versions work by "resolving" the symbols to full keys:
|
55
55
|
#
|
56
|
-
#
|
57
|
-
# properties.resolve :
|
56
|
+
# # the guid here is just PS_PUBLIC_STRINGS
|
57
|
+
# properties.resolve :keywords # => #<Key {00020329-0000-0000-c000-000000000046}/"Keywords">
|
58
|
+
# # the result here is actually also a key
|
59
|
+
# k = properties.resolve :subject # => 0x0037
|
60
|
+
# # it has a guid
|
61
|
+
# k.guid == Msg::Properties::PS_MAPI # => true
|
58
62
|
#
|
59
63
|
# = Parsing
|
60
64
|
#
|
61
65
|
# There are three objects that need to be parsed to load a +Msg+ property store:
|
62
66
|
#
|
63
|
-
#
|
67
|
+
# 1. The +nameid+ directory (<tt>Properties.parse_nameid</tt>)
|
64
68
|
# 2. The many +substg+ objects, whose names should match <tt>Properties::SUBSTG_RX</tt>
|
65
69
|
# (<tt>Properties#parse_substg</tt>)
|
66
70
|
# 3. The +properties+ file (<tt>Properties#parse_properties</tt>)
|
67
71
|
#
|
68
|
-
# Understanding of the formats is by no means perfect
|
72
|
+
# Understanding of the formats is by no means perfect.
|
69
73
|
#
|
70
74
|
# = TODO
|
71
75
|
#
|
@@ -79,7 +83,7 @@ class Msg
|
|
79
83
|
# current greedy-loading approach. still want strings to work nicely:
|
80
84
|
# props.subject
|
81
85
|
# but don't want to be loading up large binary blobs, typically attachments, eg
|
82
|
-
# props.attach_data
|
86
|
+
# props.attach_data
|
83
87
|
# probably the easiest solution is that the binary "encoding", be to return an io
|
84
88
|
# object instead. and you must read it if you want it as a string
|
85
89
|
# maybe i can avoid the greedy model anyway? rather than parsing the properties completely,
|
@@ -133,9 +137,13 @@ class Msg
|
|
133
137
|
attr_reader :unused
|
134
138
|
attr_reader :nameid
|
135
139
|
|
140
|
+
# +nameid+ is to provide a way to inherit from parent (needed for property sets for
|
141
|
+
# attachments and recipients, which inherit from the msg itself. what about nested
|
142
|
+
# msg??)
|
136
143
|
def initialize
|
137
144
|
@raw = {}
|
138
145
|
@unused = []
|
146
|
+
@nameid = nil
|
139
147
|
# FIXME
|
140
148
|
@body_rtf = @body_html = @body = false
|
141
149
|
end
|
@@ -144,7 +152,7 @@ class Msg
|
|
144
152
|
# The parsing methods
|
145
153
|
#++
|
146
154
|
|
147
|
-
def self.load obj
|
155
|
+
def self.load obj, ignore=nil
|
148
156
|
prop = Properties.new
|
149
157
|
prop.load obj
|
150
158
|
prop
|
@@ -154,9 +162,16 @@ class Msg
|
|
154
162
|
def load obj
|
155
163
|
# we need to do the nameid first, as it provides the map for later user defined properties
|
156
164
|
children = obj.children.dup
|
157
|
-
|
165
|
+
if nameid_obj = children.find { |child| child.name == '__nameid_version1.0' }
|
158
166
|
children.delete nameid_obj
|
159
|
-
Properties.parse_nameid nameid_obj
|
167
|
+
@nameid = Properties.parse_nameid nameid_obj
|
168
|
+
# hack to make it available to all msg files from the same ole storage object
|
169
|
+
class << obj.ole
|
170
|
+
attr_accessor :msg_nameid
|
171
|
+
end
|
172
|
+
obj.ole.msg_nameid = @nameid
|
173
|
+
elsif obj.ole
|
174
|
+
@nameid = obj.ole.msg_nameid rescue nil
|
160
175
|
end
|
161
176
|
# now parse the actual properties. i think dirs that match the substg should be decoded
|
162
177
|
# as properties to. 0x000d is just another encoding, the dir encoding. it should match
|
@@ -310,6 +325,8 @@ class Msg
|
|
310
325
|
elsif real_key = @nameid[key]
|
311
326
|
key = real_key
|
312
327
|
else
|
328
|
+
# i think i hit these when i have a named property, in the PS_MAPI
|
329
|
+
# guid
|
313
330
|
Log.warn "property in named range not in nameid #{key.inspect}"
|
314
331
|
key = Key.new key
|
315
332
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-msg
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2007-
|
6
|
+
version: 1.3.1
|
7
|
+
date: 2007-08-21 00:00:00 +10:00
|
8
8
|
summary: Ruby Msg library.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -36,36 +36,37 @@ files:
|
|
36
36
|
- README
|
37
37
|
- FIXES
|
38
38
|
- bin/msgtool
|
39
|
-
- bin/oletool
|
40
39
|
- lib/orderedhash.rb
|
41
40
|
- lib/rtf.rb
|
42
|
-
- lib/support.rb
|
43
41
|
- lib/mime.rb
|
44
42
|
- lib/msg.rb
|
45
|
-
- lib/ole/types.rb
|
46
|
-
- lib/ole/file_system.rb
|
47
|
-
- lib/ole/storage.rb
|
48
|
-
- lib/ole/io_helpers.rb
|
49
|
-
- lib/ole/base.rb
|
50
43
|
- lib/msg/rtf.rb
|
51
44
|
- lib/msg/properties.rb
|
52
45
|
- test/test_mime.rb
|
53
|
-
- test/test_storage.rb
|
54
|
-
- test/test_word_6.doc
|
55
|
-
- test/test_word_95.doc
|
56
|
-
- test/test_word_97.doc
|
57
46
|
test_files: []
|
58
47
|
|
59
|
-
rdoc_options:
|
60
|
-
|
48
|
+
rdoc_options:
|
49
|
+
- --main
|
50
|
+
- Msg
|
51
|
+
- --title
|
52
|
+
- ruby-msg documentation
|
53
|
+
- --tab-width
|
54
|
+
- "2"
|
61
55
|
extra_rdoc_files: []
|
62
56
|
|
63
57
|
executables:
|
64
58
|
- msgtool
|
65
|
-
- oletool
|
66
59
|
extensions: []
|
67
60
|
|
68
61
|
requirements: []
|
69
62
|
|
70
|
-
dependencies:
|
71
|
-
|
63
|
+
dependencies:
|
64
|
+
- !ruby/object:Gem::Dependency
|
65
|
+
name: ruby-ole
|
66
|
+
version_requirement:
|
67
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.2.1
|
72
|
+
version:
|
data/bin/oletool
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
#! /usr/bin/ruby
|
2
|
-
|
3
|
-
require 'optparse'
|
4
|
-
require 'rubygems'
|
5
|
-
require 'ole/storage'
|
6
|
-
|
7
|
-
def oletool
|
8
|
-
opts = {:verbose => false, :action => :tree}
|
9
|
-
op = OptionParser.new do |op|
|
10
|
-
op.banner = "Usage: oletool [options] [files]"
|
11
|
-
op.separator ''
|
12
|
-
op.on('-t', '--tree', 'Dump ole trees for files (default)') { opts[:action] = :tree }
|
13
|
-
op.on('-r', '--repack', 'Repack the ole files in canonical form') { opts[:action] = :repack }
|
14
|
-
op.separator ''
|
15
|
-
op.on('-v', '--[no-]verbose', 'Run verbosely') { |v| opts[:verbose] = v }
|
16
|
-
op.on_tail('-h', '--help', 'Show this message') { puts op; exit }
|
17
|
-
end
|
18
|
-
files = op.parse ARGV
|
19
|
-
if files.empty?
|
20
|
-
puts 'Must specify 1 or more msg files.'
|
21
|
-
puts op
|
22
|
-
exit 1
|
23
|
-
end
|
24
|
-
Ole::Log.level = opts[:verbose] ? Logger::WARN : Logger::FATAL
|
25
|
-
files.each do |file|
|
26
|
-
case opts[:action]
|
27
|
-
when :tree
|
28
|
-
Ole::Storage.open(file) { |ole| puts ole.root.to_tree }
|
29
|
-
when :repack
|
30
|
-
Ole::Storage.open(file, &:repack)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
oletool
|
data/lib/ole/base.rb
DELETED
data/lib/ole/file_system.rb
DELETED
@@ -1,181 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# = Introduction
|
3
|
-
#
|
4
|
-
# This file intends to provide file system-like api support, a la <tt>zip/zipfilesystem</tt>.
|
5
|
-
#
|
6
|
-
# Ideally, this will be the recommended interface, allowing Ole::Storage, Dir, and
|
7
|
-
# Zip::ZipFile to be used exchangablyk. It should be possible to write recursive copy using
|
8
|
-
# the plain api, such that you can copy dirs/files agnostically between any of ole docs, dirs,
|
9
|
-
# and zip files.
|
10
|
-
#
|
11
|
-
# = Usage
|
12
|
-
#
|
13
|
-
# Currently you can do something like the following:
|
14
|
-
#
|
15
|
-
# Ole::Storage.open 'test.doc' do |ole|
|
16
|
-
# ole.dir.entries '/' # => [".", "..", "\001Ole", "1Table", "\001CompObj", ...]
|
17
|
-
# ole.file.read "\001CompObj" # => "\001\000\376\377\003\n\000\000\377\377..."
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# = Notes
|
21
|
-
#
|
22
|
-
# *** This file is very incomplete
|
23
|
-
#
|
24
|
-
# i think its okay to have an api like this on top, but there are certain things that ole
|
25
|
-
# does that aren't captured.
|
26
|
-
# <tt>Ole::Storage</tt> can have multiple files with the same name, for example, or with
|
27
|
-
# / in the name, and other things that are probably invalid anyway.
|
28
|
-
# i think this should remain an addon, built on top of my core api.
|
29
|
-
# but still the ideas can be reflected in the core, ie, changing the read/write semantics.
|
30
|
-
#
|
31
|
-
# once the core changes are complete, this will be a pretty straight forward file to complete.
|
32
|
-
#
|
33
|
-
|
34
|
-
require 'ole/base'
|
35
|
-
|
36
|
-
module Ole # :nodoc:
|
37
|
-
class Storage
|
38
|
-
def file
|
39
|
-
@file ||= FileParent.new self
|
40
|
-
end
|
41
|
-
|
42
|
-
def dir
|
43
|
-
@dir ||= DirParent.new self
|
44
|
-
end
|
45
|
-
|
46
|
-
def dirent_from_path path_str
|
47
|
-
path = path_str.sub(/^\/*/, '').sub(/\/*$/, '')
|
48
|
-
dirent = @root
|
49
|
-
return dirent if path.empty?
|
50
|
-
path = path.split /\/+/
|
51
|
-
until path.empty?
|
52
|
-
raise "invalid path #{path_str.inspect}" if dirent.file?
|
53
|
-
if tmp = dirent[path.shift]
|
54
|
-
dirent = tmp
|
55
|
-
else
|
56
|
-
# allow write etc later.
|
57
|
-
raise "invalid path #{path_str.inspect}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
dirent
|
61
|
-
end
|
62
|
-
|
63
|
-
class FileParent
|
64
|
-
def initialize ole
|
65
|
-
@ole = ole
|
66
|
-
end
|
67
|
-
|
68
|
-
def open path_str, mode='r', &block
|
69
|
-
dirent = @ole.dirent_from_path path_str
|
70
|
-
# like Errno::EISDIR
|
71
|
-
raise "#{path_str.inspect} is a directory" unless dirent.file?
|
72
|
-
dirent.open(&block)
|
73
|
-
end
|
74
|
-
|
75
|
-
alias new :open
|
76
|
-
|
77
|
-
def read path
|
78
|
-
open(path) { |f| f.read }
|
79
|
-
end
|
80
|
-
|
81
|
-
# crappy copy from Dir.
|
82
|
-
def unlink path
|
83
|
-
dirent = @ole.dirent_from_path path
|
84
|
-
# EPERM
|
85
|
-
raise "operation not permitted #{path.inspect}" unless dirent.file?
|
86
|
-
# i think we should free all of our blocks. i think the best way to do that would be
|
87
|
-
# like:
|
88
|
-
# open(path) { |f| f.truncate 0 }. which should free all our blocks from the
|
89
|
-
# allocation table. then if we remove ourself from our parent, we won't be part of
|
90
|
-
# the bat at save time.
|
91
|
-
# i think if you run repack, all free blocks should get zeroed.
|
92
|
-
open(path) { |f| f.truncate 0 }
|
93
|
-
parent = @ole.dirent_from_path(('/' + path).sub(/\/[^\/]+$/, ''))
|
94
|
-
parent.children.delete dirent
|
95
|
-
1 # hmmm. as per ::File ?
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
class DirParent
|
100
|
-
def initialize ole
|
101
|
-
@ole = ole
|
102
|
-
end
|
103
|
-
|
104
|
-
def open path_str
|
105
|
-
dirent = @ole.dirent_from_path path_str
|
106
|
-
# like Errno::ENOTDIR
|
107
|
-
raise "#{path_str.inspect} is not a directory" unless dirent.dir?
|
108
|
-
dir = Dir.new dirent, path_str
|
109
|
-
if block_given?
|
110
|
-
yield dir
|
111
|
-
else
|
112
|
-
dir
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# certain Dir class methods proxy in this fashion:
|
117
|
-
def entries path
|
118
|
-
open(path) { |dir| dir.entries }
|
119
|
-
end
|
120
|
-
|
121
|
-
# there are some other important ones, like:
|
122
|
-
# chroot (!), mkdir, chdir, rmdir, glob etc etc. for now, i think
|
123
|
-
# mkdir, and rmdir are the main ones we'd need to support
|
124
|
-
def rmdir path
|
125
|
-
dirent = @ole.dirent_from_path path
|
126
|
-
# repeating myself
|
127
|
-
raise "#{path.inspect} is not a directory" unless dirent.dir?
|
128
|
-
# ENOTEMPTY:
|
129
|
-
raise "directory not empty #{path.inspect}" unless dirent.children.empty?
|
130
|
-
# now delete it, how to do that? the canonical representation that is
|
131
|
-
# maintained is the root tree, and the children array. we must remove it
|
132
|
-
# from the children array.
|
133
|
-
# we need the parent then. this sucks but anyway:
|
134
|
-
parent = @ole.dirent_from_path path.sub(/\/[^\/]+$/, '') || '/'
|
135
|
-
# note that the way this currently works, on save and repack time this will get
|
136
|
-
# reflected. to work properly, ie to make a difference now it would have to re-write
|
137
|
-
# the dirent. i think that Ole::Storage#close will handle that. and maybe include a
|
138
|
-
# #repack.
|
139
|
-
parent.children.delete dirent
|
140
|
-
0 # hmmm. as per ::Dir ?
|
141
|
-
end
|
142
|
-
|
143
|
-
class Dir
|
144
|
-
include Enumerable
|
145
|
-
attr_reader :dirent, :path, :entries, :pos
|
146
|
-
|
147
|
-
def initialize dirent, path
|
148
|
-
@dirent, @path = dirent, path
|
149
|
-
@pos = 0
|
150
|
-
# FIXME: hack, and probably not really desired
|
151
|
-
@entries = %w[. ..] + @dirent.children.map(&:name)
|
152
|
-
end
|
153
|
-
|
154
|
-
def each(&block)
|
155
|
-
@entries.each(&block)
|
156
|
-
end
|
157
|
-
|
158
|
-
def close
|
159
|
-
end
|
160
|
-
|
161
|
-
def read
|
162
|
-
@entries[@pos]
|
163
|
-
ensure
|
164
|
-
@pos += 1 if @pos < @entries.length
|
165
|
-
end
|
166
|
-
|
167
|
-
def pos= pos
|
168
|
-
@pos = [[0, pos].max, @entries.length].min
|
169
|
-
end
|
170
|
-
|
171
|
-
def rewind
|
172
|
-
@pos = 0
|
173
|
-
end
|
174
|
-
|
175
|
-
alias tell :pos
|
176
|
-
alias seek :pos=
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|