viewpoint 0.0.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/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
|