viewpoint 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.txt +674 -0
- data/README +60 -0
- data/Rakefile +39 -0
- data/examples/cal2ical.rb +29 -0
- data/examples/ews_fusefs.rb +364 -0
- data/examples/webclient/.gems +2 -0
- data/examples/webclient/README +1 -0
- data/examples/webclient/config.ru +26 -0
- data/examples/webclient/ews_access_handler.rb +42 -0
- data/examples/webclient/public/css/mail.css +33 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/jquery-ui-1.7.2.custom.css +406 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/jquery-ui-1.7.2.custom.css +406 -0
- data/examples/webclient/public/js/jquery-1.3.2.min.js +19 -0
- data/examples/webclient/public/js/jquery-ui-1.7.2.custom.min.js +145 -0
- data/examples/webclient/viewpoint_web.rb +295 -0
- data/examples/webclient/views/_footer.haml +1 -0
- data/examples/webclient/views/_header.haml +11 -0
- data/examples/webclient/views/_tagline.haml +1 -0
- data/examples/webclient/views/index.haml +20 -0
- data/examples/webclient/views/layout.haml +42 -0
- data/examples/webclient/views/mail.haml +45 -0
- data/examples/webclient/views/welcome.haml +0 -0
- data/lib/calendar.rb +121 -0
- data/lib/calendar_item.rb +110 -0
- data/lib/event.rb +0 -0
- data/lib/exchange_headers.rb +50 -0
- data/lib/exchwebserv.rb +228 -0
- data/lib/folder.rb +269 -0
- data/lib/item.rb +56 -0
- data/lib/mail.rb +118 -0
- data/lib/message.rb +134 -0
- data/lib/soap/viewpoint.conf +3 -0
- data/lib/task.rb +0 -0
- data/lib/tasks.rb +0 -0
- data/lib/viewpoint.rb +2 -0
- data/lib/wsdl/defaultMappingRegistry.rb +10680 -0
- data/lib/wsdl/exchangeServiceBinding.rb +349 -0
- data/lib/wsdl/exchangeServiceTypes.rb +11013 -0
- data/preamble +19 -0
- data/test/spec/authtest_spec.rb +12 -0
- data/test/spec/findfolders_spec.rb +14 -0
- data/test/test_client.rb +12 -0
- data/test/testrestrict.rb +75 -0
- metadata +130 -0
data/README
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--------------------------------------------------------------------------
|
2
|
+
Viewpoint for Exchange Web Services
|
3
|
+
--------------------------------------------------------------------------
|
4
|
+
This program attempts to create a client access library for Exchange Web
|
5
|
+
Services (EWS) in Ruby.
|
6
|
+
--------------------------------------------------------------------------
|
7
|
+
REQUIRED GEMS:
|
8
|
+
|
9
|
+
# Current SOAP4R ( http://dev.ctor.org/soap4r )
|
10
|
+
gem install -r soap4r
|
11
|
+
|
12
|
+
# iCalendar
|
13
|
+
gem install -r icalendar
|
14
|
+
|
15
|
+
CONFIGURATION:
|
16
|
+
Configure your user/pass and EWS endpoint in lib/soap/viewpoint.conf
|
17
|
+
or $HOME/.viewpointrc. If the file $HOME/.viewpointrc exists it takes
|
18
|
+
presidence. See the sample in lib/soap/viewpoint.conf for how this
|
19
|
+
file should be configured.
|
20
|
+
|
21
|
+
|
22
|
+
Running Examples:
|
23
|
+
To run the FuseFS example you need the 'fusefs' gem
|
24
|
+
|
25
|
+
|
26
|
+
******************** EXAMPLES *********************
|
27
|
+
# In the following examples the following are used:
|
28
|
+
# "item" is a type of Viewpoint::Item
|
29
|
+
# "folder" is a type of Viewpoint::Folder
|
30
|
+
# "new_folder" is a type of Viewpoint::Folder
|
31
|
+
|
32
|
+
# === Convert your Exchange Calendar to a Icalendar::Calendar object ===
|
33
|
+
require 'lib/exchwebserv'
|
34
|
+
vp = Viewpoint::ExchWebServ.instance
|
35
|
+
vp.authenticate
|
36
|
+
vp.find_folders
|
37
|
+
cal = vp.get_folder("Calendar")
|
38
|
+
ical = cal.to_ical
|
39
|
+
puts ical.to_ical
|
40
|
+
|
41
|
+
# === Get a listing of todays messages ===
|
42
|
+
# See test/test_client.rb
|
43
|
+
|
44
|
+
# === Moving an item ===
|
45
|
+
item.move_to!(new_folder)
|
46
|
+
|
47
|
+
# === Deleting an item ===
|
48
|
+
item.delete!
|
49
|
+
item.recycle! # Move to "Deleted Items"
|
50
|
+
|
51
|
+
|
52
|
+
--------------------------------------------------------------------------
|
53
|
+
DISCLAIMER: I am by no means a Ruby or EWS expert. There may be better
|
54
|
+
means of doing what I am attempting to do. If you see something that
|
55
|
+
could be done better or would like to help out in the development of this
|
56
|
+
code please feel free to clone the 'git' repository:
|
57
|
+
git clone git://github.com/zenchild/Viewpoint-for-MS-Exchange.git
|
58
|
+
or add an issue on GitHub:
|
59
|
+
http://github.com/zenchild/Viewpoint-for-MS-Exchange/issues
|
60
|
+
--------------------------------------------------------------------------
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
CLEAN.include("pkg")
|
6
|
+
CLEAN.include("doc")
|
7
|
+
|
8
|
+
GEMSPEC = Gem::Specification.new do |gem|
|
9
|
+
gem.name = "viewpoint"
|
10
|
+
gem.version = File.open('VERSION').readline.chomp
|
11
|
+
gem.date = Date.today.to_s
|
12
|
+
gem.platform = Gem::Platform::RUBY
|
13
|
+
gem.rubyforge_project = nil
|
14
|
+
|
15
|
+
gem.author = "Dan Wanek"
|
16
|
+
gem.email = "dan.wanek@gmail.com"
|
17
|
+
gem.homepage = "http://github.com/zenchild/Viewpoint"
|
18
|
+
|
19
|
+
gem.summary = "A Ruby client access library for Microsoft Exchange Web Services (EWS)"
|
20
|
+
gem.description = <<-EOF
|
21
|
+
A Ruby client access library for Microsoft Exchange Web Services (EWS). It is a work in progress. Methods are still being added from the EWS API docs. Please see them for further information: http://msdn.microsoft.com/en-us/library/bb204119.aspx
|
22
|
+
EOF
|
23
|
+
|
24
|
+
gem.files = `git ls-files`.split(/\n/)
|
25
|
+
gem.require_path = "lib"
|
26
|
+
gem.rdoc_options = %w(-x wsdl/ -x test/ -x examples/)
|
27
|
+
gem.extra_rdoc_files = %w(README COPYING.txt)
|
28
|
+
|
29
|
+
gem.required_ruby_version = '>= 1.8.7'
|
30
|
+
gem.requirements = []
|
31
|
+
#gem.add_runtime_dependency ''
|
32
|
+
gem.post_install_message = "Don't forget to create .viewpointrc. See README"
|
33
|
+
end
|
34
|
+
|
35
|
+
Rake::GemPackageTask.new(GEMSPEC) do |pkg|
|
36
|
+
pkg.need_tar = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => [:clean, :repackage]
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2009 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
require File.dirname(__FILE__) + '/../lib/exchwebserv'
|
21
|
+
include Viewpoint
|
22
|
+
|
23
|
+
vp = ExchWebServ.instance
|
24
|
+
vp.authenticate
|
25
|
+
vp.find_folders
|
26
|
+
cal = vp.get_folder("Calendar")
|
27
|
+
ical = cal.to_ical
|
28
|
+
puts ical.to_ical
|
29
|
+
|
@@ -0,0 +1,364 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2009 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
require 'fusefs'
|
21
|
+
require 'time'
|
22
|
+
include FuseFS
|
23
|
+
require File.dirname(__FILE__) + '/../lib/exchwebserv'
|
24
|
+
require File.dirname(__FILE__) + '/../lib/folder'
|
25
|
+
include Viewpoint
|
26
|
+
|
27
|
+
|
28
|
+
class EWSFuse < FuseDir
|
29
|
+
|
30
|
+
@@maildir_dirs = ['cur','new', 'tmp']
|
31
|
+
@@ewsfuse_dir = "#{ENV['HOME']}/.ewsfuse"
|
32
|
+
|
33
|
+
def initialize(mountpoint)
|
34
|
+
@vp = ExchWebServ.instance
|
35
|
+
@vp.authenticate
|
36
|
+
@vp.find_folders
|
37
|
+
@mf = (@vp.get_mail_folders)
|
38
|
+
puts "MF: #{@mf.class.to_s}"
|
39
|
+
@messages = {} # Message objects
|
40
|
+
@open_files = {} # Files open for RAW IO
|
41
|
+
@mountpoint = mountpoint
|
42
|
+
|
43
|
+
#File::umask(0077)
|
44
|
+
if( !File.directory?(@@ewsfuse_dir) )
|
45
|
+
Dir.mkdir(@@ewsfuse_dir)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# ----- FuserFS Methods ----- #
|
50
|
+
def contents(path)
|
51
|
+
puts "--- IN: contents ---"
|
52
|
+
if (local_path?(path))
|
53
|
+
puts "--- IN: contents: if ---"
|
54
|
+
Dir.entries(local_path(path))
|
55
|
+
else
|
56
|
+
puts "--- IN: contents: else ---"
|
57
|
+
parts = scan_path(path)
|
58
|
+
case parts.pop
|
59
|
+
when nil
|
60
|
+
puts "--- IN: contents: else --- while 'nil'"
|
61
|
+
output = @mf.keys do |folder_name|
|
62
|
+
folder_name
|
63
|
+
end
|
64
|
+
output + Dir.entries(local_path(path))
|
65
|
+
when 'cur'
|
66
|
+
np = parts.pop
|
67
|
+
puts "folder: #{np}"
|
68
|
+
mdir = @mf[np]
|
69
|
+
if( mdir == nil )
|
70
|
+
[]
|
71
|
+
else
|
72
|
+
mdir = @vp.get_folder(mdir.display_name)
|
73
|
+
puts "Fetching todays messages for #{mdir.display_name} of type #{mdir.class.to_s}"
|
74
|
+
mdir.get_todays_messages.map do |msg|
|
75
|
+
puts "Got message of type: #{msg.class.to_s}"
|
76
|
+
msg_hash = msg.item_id.hash.abs
|
77
|
+
@messages[msg_hash.to_s] = msg
|
78
|
+
"#{msg.date_time_recieved.strftime('%s')}_#{msg_hash}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
when 'new','tmp'
|
82
|
+
[]
|
83
|
+
else
|
84
|
+
['cur','new','tmp']
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def directory?(path)
|
90
|
+
if( local_path?(path) )
|
91
|
+
puts "Checking for Local_dir?"
|
92
|
+
File.directory?( local_path(path) )
|
93
|
+
else
|
94
|
+
parts = scan_path(path)
|
95
|
+
part = parts.pop
|
96
|
+
case part
|
97
|
+
when /^[0-9]{10,}_/
|
98
|
+
puts "NOT DIR: #{path}"
|
99
|
+
return false
|
100
|
+
when nil, 'cur','new','tmp'
|
101
|
+
puts "IS DIR: #{path}"
|
102
|
+
return true
|
103
|
+
else
|
104
|
+
if( (@mf[part] ) != nil )
|
105
|
+
puts "IS DIR: #{path}"
|
106
|
+
return true
|
107
|
+
else
|
108
|
+
puts "NOT DIR: #{path}"
|
109
|
+
return false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def file?(path)
|
116
|
+
if( local_path?(path) )
|
117
|
+
if(File.exists?(local_path(path)))
|
118
|
+
ans = !directory?(path)
|
119
|
+
else
|
120
|
+
ans = false
|
121
|
+
end
|
122
|
+
else
|
123
|
+
ans = !directory?(path)
|
124
|
+
end
|
125
|
+
puts "=> file?(#{path}) ... " + (ans ? "yes" : "no")
|
126
|
+
return ans
|
127
|
+
end
|
128
|
+
|
129
|
+
def executable?(path)
|
130
|
+
if( local_path?(path) )
|
131
|
+
return File.executable?(local_path(path))
|
132
|
+
else
|
133
|
+
return directory?(path)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def read_file(path)
|
138
|
+
if( local_path?(path) )
|
139
|
+
IO.read(local_path(path))
|
140
|
+
else
|
141
|
+
parts = scan_path(path)
|
142
|
+
msg_hash = parts.last.split('_').last
|
143
|
+
@messages[msg_hash.to_s].to_rfc822
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def can_write?(path)
|
148
|
+
return false if path =~ /folders.db/
|
149
|
+
parts = scan_path(path)
|
150
|
+
|
151
|
+
ans = local_path?(path) || path == '/' #||
|
152
|
+
#parts.last =~ /^[0-9]{10,}_/
|
153
|
+
|
154
|
+
puts "=> can_write?(#{path}) ... " + (ans ? "yes" : "no")
|
155
|
+
return ans
|
156
|
+
end
|
157
|
+
|
158
|
+
def write_to(path, str)
|
159
|
+
puts "=> write_to(#{path}, str...)"
|
160
|
+
io = File.open(local_path(path),'w+')
|
161
|
+
io.write(str)
|
162
|
+
io.close
|
163
|
+
end
|
164
|
+
|
165
|
+
def can_delete?(path)
|
166
|
+
parts = scan_path(path)
|
167
|
+
|
168
|
+
ans = local_path?(path) ||
|
169
|
+
parts.last =~ /^[0-9]{10,}_/
|
170
|
+
|
171
|
+
puts "=> can_delete?(#{path}) ... " + (ans ? "yes" : "no")
|
172
|
+
ans
|
173
|
+
end
|
174
|
+
|
175
|
+
def delete(path)
|
176
|
+
puts "=> delete(#{path})"
|
177
|
+
if( local_path?(path) )
|
178
|
+
puts "In LOCAL DELETE"
|
179
|
+
lpath = local_path(path)
|
180
|
+
if( File.directory?(lpath) )
|
181
|
+
puts "Removing local directory #{lpath}"
|
182
|
+
else
|
183
|
+
puts "Removing local file #{lpath}"
|
184
|
+
File.unlink(lpath)
|
185
|
+
end
|
186
|
+
else
|
187
|
+
puts "In NON LOCAL DELETE"
|
188
|
+
parts = scan_path(path)
|
189
|
+
msg_hash = parts.last.split('_').last
|
190
|
+
puts "In NON LOCAL DELETE 2: #{msg_hash}"
|
191
|
+
puts "In NON LOCAL DELETE 3: #{parts[-3]}"
|
192
|
+
#mdir = @vp.get_folder(parts[-3])
|
193
|
+
if ( (msg = @messages[msg_hash.to_s]) == nil)
|
194
|
+
npath = parts
|
195
|
+
npath.pop
|
196
|
+
contents(npath.join('/'))
|
197
|
+
msg = @messages[msg_hash.to_s]
|
198
|
+
end
|
199
|
+
puts "In NON LOCAL DELETE 4: #{msg.class.to_s}"
|
200
|
+
puts "MESG: #{msg.class.to_s}, ID: #{msg.item_id}, PARENT: #{msg.parent_folder.class.to_s}"
|
201
|
+
#puts "MESG: #{mdir.class.to_s}"
|
202
|
+
msg.parent_folder.recycle_item(msg.item_id)
|
203
|
+
true
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def can_mkdir?(path)
|
208
|
+
ans = local_path?(path)
|
209
|
+
puts "=> can_mkdir?(#{path}) ... " + (ans ? "yes" : "no")
|
210
|
+
ans
|
211
|
+
end
|
212
|
+
|
213
|
+
def mkdir(path)
|
214
|
+
puts "=> mkdir(#{path})"
|
215
|
+
lpath = local_path(path)
|
216
|
+
Dir.mkdir lpath
|
217
|
+
end
|
218
|
+
|
219
|
+
def can_rmdir?(path)
|
220
|
+
puts "=> can_rmdir?(#{path})"
|
221
|
+
local_path?(path)
|
222
|
+
end
|
223
|
+
|
224
|
+
def rmdir(path)
|
225
|
+
lpath = local_path(path)
|
226
|
+
puts "=> rmdir(#{lpath})"
|
227
|
+
Dir.rmdir(lpath)
|
228
|
+
end
|
229
|
+
|
230
|
+
def size(path)
|
231
|
+
if(local_path?(path))
|
232
|
+
File.size(local_path(path))
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# --- RAW FuserFS Methods --- #
|
237
|
+
def raw_open(path,mode) # mode is "r" "w" or "rw", with "a" if the file
|
238
|
+
puts "** => raw_open(#{path}, '#{mode}')"
|
239
|
+
|
240
|
+
if( !local_path?(path) )
|
241
|
+
return false
|
242
|
+
end
|
243
|
+
|
244
|
+
lpath = local_path(path)
|
245
|
+
|
246
|
+
case mode
|
247
|
+
when /^r$/
|
248
|
+
mode = 'r'
|
249
|
+
when /^w$/
|
250
|
+
mode = 'a'
|
251
|
+
when /^[wr]{2}$/, /a/
|
252
|
+
if(File.exists?(lpath))
|
253
|
+
mode = 'r+'
|
254
|
+
else
|
255
|
+
mode = 'w+'
|
256
|
+
end
|
257
|
+
else
|
258
|
+
raise "Unknown mode error #{mode}"
|
259
|
+
end
|
260
|
+
|
261
|
+
puts "Setting mode to '#{mode}'"
|
262
|
+
|
263
|
+
return true if @open_files.has_key?(path)
|
264
|
+
begin
|
265
|
+
puts "Raw opening.... File.open(#{lpath}, #{mode})"
|
266
|
+
@open_files[path] = File.open(lpath, mode)
|
267
|
+
return true
|
268
|
+
rescue => error
|
269
|
+
puts "Error opening raw file: #{error}"
|
270
|
+
return false
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def raw_read(path,offset,size)
|
275
|
+
begin
|
276
|
+
puts "** => raw_read(#{path}, #{offset}, #{size})"
|
277
|
+
file = @open_files[path]
|
278
|
+
return unless file
|
279
|
+
#file.sysseek(offset,IO::SEEK_SET)
|
280
|
+
#file.sysread(size)
|
281
|
+
file.seek(offset, File::SEEK_SET)
|
282
|
+
file.read(size)
|
283
|
+
rescue => error
|
284
|
+
puts "Error reading raw file: #{error}"
|
285
|
+
nil
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def raw_write(path,offset,size,buf)
|
290
|
+
begin
|
291
|
+
puts "** => raw_write(#{path}, #{offset}, #{size}, ... buf)"
|
292
|
+
file = @open_files[path]
|
293
|
+
return unless file
|
294
|
+
file.seek(offset, File::SEEK_CUR)
|
295
|
+
file.write(buf[0, size])
|
296
|
+
#file.sysseek(offset,IO::SEEK_CUR)
|
297
|
+
#file.syswrite(buf[0, size])
|
298
|
+
rescue => error
|
299
|
+
puts "Error writing to raw file: #{error}"
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def raw_close(path)
|
304
|
+
begin
|
305
|
+
puts "** => raw_close(#{path})"
|
306
|
+
file = @open_files[path]
|
307
|
+
return unless file
|
308
|
+
file.close
|
309
|
+
@open_files.delete path
|
310
|
+
rescue => error
|
311
|
+
puts "Error closing raw file: #{error}"
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
|
316
|
+
# --- End FuserFS Methods --- #
|
317
|
+
|
318
|
+
# Is this a virtual dir/file or a local file
|
319
|
+
def local_path?(path)
|
320
|
+
parts = scan_path(path)
|
321
|
+
|
322
|
+
if parts.empty?
|
323
|
+
ans = false
|
324
|
+
else
|
325
|
+
ans = ((!@@maildir_dirs.include? parts.last) &&
|
326
|
+
parts.last !~ /^[0-9]{10,}_/ &&
|
327
|
+
((@mf[parts.last]) == nil)
|
328
|
+
)
|
329
|
+
end
|
330
|
+
|
331
|
+
puts "==> local_path?(#{path}) ... " + (ans ? "yes" : "no")
|
332
|
+
return ans
|
333
|
+
end
|
334
|
+
|
335
|
+
# Return local path as a string
|
336
|
+
def local_path(path)
|
337
|
+
puts "==> local_path(#{path})"
|
338
|
+
#lpath = path.gsub(/#{@mountpoint}\/?/,'')
|
339
|
+
lpath = path.gsub(/^\/?/,'')
|
340
|
+
return "#{@@ewsfuse_dir}/#{lpath}"
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
# FuserFS set-up
|
345
|
+
if (File.basename($0) == File.basename(__FILE__))
|
346
|
+
if (ARGV.size != 1)
|
347
|
+
puts "Usage: #{$0} <directory>"
|
348
|
+
exit
|
349
|
+
end
|
350
|
+
|
351
|
+
dirname = ARGV.shift
|
352
|
+
|
353
|
+
unless File.directory?(dirname)
|
354
|
+
puts "Usage: #{dirname} is not a directory."
|
355
|
+
exit
|
356
|
+
end
|
357
|
+
|
358
|
+
root = EWSFuse.new(dirname)
|
359
|
+
|
360
|
+
# Set the root FuseFS
|
361
|
+
FuseFS.set_root(root)
|
362
|
+
FuseFS.mount_under(dirname)
|
363
|
+
FuseFS.run # This doesn't return until we're unmounted.
|
364
|
+
end
|