dav4rack 0.2.11 → 0.3.0
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/CHANGELOG.rdoc +109 -0
- data/README.rdoc +8 -0
- data/dav4rack.gemspec +1 -22
- data/lib/dav4rack.rb +5 -0
- data/lib/dav4rack/controller.rb +123 -59
- data/lib/dav4rack/file.rb +1 -1
- data/lib/dav4rack/file_resource_lock.rb +159 -0
- data/lib/dav4rack/handler.rb +1 -1
- data/lib/dav4rack/resource.rb +25 -9
- data/lib/dav4rack/resources/file_resource.rb +366 -0
- data/lib/dav4rack/resources/mongo_resource.rb +341 -0
- data/lib/dav4rack/utils.rb +40 -0
- data/lib/dav4rack/version.rb +1 -1
- metadata +40 -24
- data/.gitignore +0 -7
- data/lib/dav4rack/file_resource.rb +0 -257
- data/spec/handler_spec.rb +0 -301
data/lib/dav4rack/file.rb
CHANGED
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'pstore'
|
2
|
+
|
3
|
+
module DAV4Rack
|
4
|
+
class FileResourceLock
|
5
|
+
attr_accessor :path
|
6
|
+
attr_accessor :token
|
7
|
+
attr_accessor :timeout
|
8
|
+
attr_accessor :depth
|
9
|
+
attr_accessor :user
|
10
|
+
attr_accessor :scope
|
11
|
+
attr_accessor :kind
|
12
|
+
attr_accessor :owner
|
13
|
+
attr_reader :created_at
|
14
|
+
attr_reader :root
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def explicitly_locked?(path, croot=nil)
|
18
|
+
store = init_pstore(croot)
|
19
|
+
!!store.transaction(true){
|
20
|
+
store[:paths][path]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def implicitly_locked?(path, croot=nil)
|
25
|
+
store = init_pstore(croot)
|
26
|
+
!!store.transaction(true){
|
27
|
+
store[:paths].keys.detect do |check|
|
28
|
+
check.start_with?(path)
|
29
|
+
end
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def explicit_locks(path, croot, args={})
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_by_path(path, croot=nil)
|
37
|
+
lock = self.class.new(:path => path, :root => croot)
|
38
|
+
lock.token.nil? ? nil : lock
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_by_token(token, croot=nil)
|
42
|
+
store = init_pstore(croot)
|
43
|
+
struct = store.transaction(true){
|
44
|
+
store[:tokens][token]
|
45
|
+
}
|
46
|
+
if(tok)
|
47
|
+
self.class.new(:path => struct[:path], :root => croot)
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate(path, user, token, croot)
|
54
|
+
lock = self.new(:root => croot)
|
55
|
+
lock.user = user
|
56
|
+
lock.path = path
|
57
|
+
lock.token = token
|
58
|
+
lock.save
|
59
|
+
lock
|
60
|
+
end
|
61
|
+
|
62
|
+
def root=(path)
|
63
|
+
@root = path
|
64
|
+
end
|
65
|
+
|
66
|
+
def root
|
67
|
+
@root || '/tmp/dav4rack'
|
68
|
+
end
|
69
|
+
|
70
|
+
def init_pstore(croot)
|
71
|
+
path = File.join(croot, '.attribs', 'locks.pstore')
|
72
|
+
FileUtils.mkdir_p(File.dirname(path)) unless File.directory?(File.dirname(path))
|
73
|
+
store = IS_18 ? PStore.new(path) : PStore.new(path, true)
|
74
|
+
store.transaction do
|
75
|
+
unless(store[:paths])
|
76
|
+
store[:paths] = {}
|
77
|
+
store[:tokens] = {}
|
78
|
+
store.commit
|
79
|
+
end
|
80
|
+
end
|
81
|
+
store
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def initialize(args={})
|
86
|
+
@path = args[:path]
|
87
|
+
@root = args[:root]
|
88
|
+
@owner = args[:owner]
|
89
|
+
@store = init_pstore(@root)
|
90
|
+
@max_timeout = args[:max_timeout] || 86400
|
91
|
+
@default_timeout = args[:max_timeout] || 60
|
92
|
+
load_if_exists!
|
93
|
+
@new_record = true if token.nil?
|
94
|
+
end
|
95
|
+
|
96
|
+
def owner?(user)
|
97
|
+
user == owner
|
98
|
+
end
|
99
|
+
|
100
|
+
def reload
|
101
|
+
load_if_exists
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
def remaining_timeout
|
106
|
+
t = timeout.to_i - (Time.now.to_i - created_at.to_i)
|
107
|
+
t < 0 ? 0 : t
|
108
|
+
end
|
109
|
+
|
110
|
+
def save
|
111
|
+
struct = {
|
112
|
+
:path => path,
|
113
|
+
:token => token,
|
114
|
+
:timeout => timeout,
|
115
|
+
:depth => depth,
|
116
|
+
:created_at => Time.now,
|
117
|
+
:owner => owner
|
118
|
+
}
|
119
|
+
@store.transaction do
|
120
|
+
@store[:paths][path] = struct
|
121
|
+
@store[:tokens][token] = struct
|
122
|
+
@store.commit
|
123
|
+
end
|
124
|
+
@new_record = false
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
def destroy
|
129
|
+
@store.transaction do
|
130
|
+
@store[:paths].delete(path)
|
131
|
+
@store[:tokens].delete(token)
|
132
|
+
@store.commit
|
133
|
+
end
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def load_if_exists!
|
140
|
+
struct = @store.transaction do
|
141
|
+
@store[:paths][path]
|
142
|
+
end
|
143
|
+
if(struct)
|
144
|
+
@path = struct[:path]
|
145
|
+
@token = struct[:token]
|
146
|
+
@timeout = struct[:timeout]
|
147
|
+
@depth = struct[:depth]
|
148
|
+
@created_at = struct[:created_at]
|
149
|
+
@owner = struct[:owner]
|
150
|
+
end
|
151
|
+
self
|
152
|
+
end
|
153
|
+
|
154
|
+
def init_pstore(croot=nil)
|
155
|
+
self.class.init_pstore(croot || @root)
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
data/lib/dav4rack/handler.rb
CHANGED
@@ -7,7 +7,7 @@ module DAV4Rack
|
|
7
7
|
def initialize(options={})
|
8
8
|
@options = options.dup
|
9
9
|
unless(@options[:resource_class])
|
10
|
-
require 'dav4rack/file_resource'
|
10
|
+
require 'dav4rack/resources/file_resource'
|
11
11
|
@options[:resource_class] = FileResource
|
12
12
|
@options[:root] ||= Dir.pwd
|
13
13
|
end
|
data/lib/dav4rack/resource.rb
CHANGED
@@ -117,7 +117,12 @@ module DAV4Rack
|
|
117
117
|
@runner.call(class_sym, :after, orig)
|
118
118
|
result
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
|
+
# Returns if resource supports locking
|
122
|
+
def supports_locking?
|
123
|
+
false #true
|
124
|
+
end
|
125
|
+
|
121
126
|
# If this is a collection, return the child resources.
|
122
127
|
def children
|
123
128
|
NotImplemented
|
@@ -138,6 +143,11 @@ module DAV4Rack
|
|
138
143
|
parent.exist?
|
139
144
|
end
|
140
145
|
|
146
|
+
# Is the parent resource a collection?
|
147
|
+
def parent_collection?
|
148
|
+
parent.collection?
|
149
|
+
end
|
150
|
+
|
141
151
|
# Return the creation time.
|
142
152
|
def creation_date
|
143
153
|
raise NotImplemented
|
@@ -341,14 +351,17 @@ module DAV4Rack
|
|
341
351
|
end
|
342
352
|
|
343
353
|
# Available properties
|
344
|
-
def
|
345
|
-
%w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength)
|
354
|
+
def properties
|
355
|
+
%w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength).collect do |prop|
|
356
|
+
{:name => prop, :ns_href => 'DAV:'}
|
357
|
+
end
|
346
358
|
end
|
347
359
|
|
348
360
|
# name:: String - Property name
|
349
361
|
# Returns the value of the given property
|
350
|
-
def get_property(
|
351
|
-
|
362
|
+
def get_property(element)
|
363
|
+
raise NotImplemented if (element[:ns_href] != 'DAV:')
|
364
|
+
case element[:name]
|
352
365
|
when 'resourcetype' then resource_type
|
353
366
|
when 'displayname' then display_name
|
354
367
|
when 'creationdate' then use_ms_compat_creationdate? ? creation_date.httpdate : creation_date.xmlschema
|
@@ -356,24 +369,27 @@ module DAV4Rack
|
|
356
369
|
when 'getcontenttype' then content_type
|
357
370
|
when 'getetag' then etag
|
358
371
|
when 'getlastmodified' then last_modified.httpdate
|
372
|
+
else raise NotImplemented
|
359
373
|
end
|
360
374
|
end
|
361
375
|
|
362
376
|
# name:: String - Property name
|
363
377
|
# value:: New value
|
364
378
|
# Set the property to the given value
|
365
|
-
def set_property(
|
366
|
-
|
379
|
+
def set_property(element, value)
|
380
|
+
raise NotImplemented if (element[:ns_href] != 'DAV:')
|
381
|
+
case element[:name]
|
367
382
|
when 'resourcetype' then self.resource_type = value
|
368
383
|
when 'getcontenttype' then self.content_type = value
|
369
384
|
when 'getetag' then self.etag = value
|
370
385
|
when 'getlastmodified' then self.last_modified = Time.httpdate(value)
|
386
|
+
else raise NotImplemented
|
371
387
|
end
|
372
388
|
end
|
373
389
|
|
374
390
|
# name:: Property name
|
375
391
|
# Remove the property from the resource
|
376
|
-
def remove_property(
|
392
|
+
def remove_property(element)
|
377
393
|
Forbidden
|
378
394
|
end
|
379
395
|
|
@@ -463,7 +479,7 @@ module DAV4Rack
|
|
463
479
|
auth = Rack::Auth::Basic::Request.new(request.env)
|
464
480
|
auth.provided? && auth.basic? ? auth.credentials : [nil,nil]
|
465
481
|
end
|
466
|
-
|
482
|
+
|
467
483
|
end
|
468
484
|
|
469
485
|
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'pstore'
|
4
|
+
require 'webrick/httputils'
|
5
|
+
require 'dav4rack/file_resource_lock'
|
6
|
+
|
7
|
+
module DAV4Rack
|
8
|
+
|
9
|
+
class FileResource < Resource
|
10
|
+
|
11
|
+
include WEBrick::HTTPUtils
|
12
|
+
include DAV4Rack::Utils
|
13
|
+
|
14
|
+
# If this is a collection, return the child resources.
|
15
|
+
def children
|
16
|
+
Dir[file_path + '/*'].map do |path|
|
17
|
+
child ::File.basename(path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Is this resource a collection?
|
22
|
+
def collection?
|
23
|
+
::File.directory?(file_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Does this recource exist?
|
27
|
+
def exist?
|
28
|
+
::File.exist?(file_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return the creation time.
|
32
|
+
def creation_date
|
33
|
+
stat.ctime
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return the time of last modification.
|
37
|
+
def last_modified
|
38
|
+
stat.mtime
|
39
|
+
end
|
40
|
+
|
41
|
+
# Set the time of last modification.
|
42
|
+
def last_modified=(time)
|
43
|
+
::File.utime(Time.now, time, file_path)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return an Etag, an unique hash value for this resource.
|
47
|
+
def etag
|
48
|
+
sprintf('%x-%x-%x', stat.ino, stat.size, stat.mtime.to_i)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Return the mime type of this resource.
|
52
|
+
def content_type
|
53
|
+
if stat.directory?
|
54
|
+
"text/html"
|
55
|
+
else
|
56
|
+
mime_type(file_path, DefaultMimeTypes)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return the size in bytes for this resource.
|
61
|
+
def content_length
|
62
|
+
stat.size
|
63
|
+
end
|
64
|
+
|
65
|
+
# HTTP GET request.
|
66
|
+
#
|
67
|
+
# Write the content of the resource to the response.body.
|
68
|
+
def get(request, response)
|
69
|
+
raise NotFound unless exist?
|
70
|
+
if stat.directory?
|
71
|
+
response.body = ""
|
72
|
+
Rack::Directory.new(root).call(request.env)[2].each do |line|
|
73
|
+
response.body << line
|
74
|
+
end
|
75
|
+
response['Content-Length'] = response.body.bytesize.to_s
|
76
|
+
else
|
77
|
+
file = Rack::File.new(root)
|
78
|
+
response.body = file
|
79
|
+
end
|
80
|
+
OK
|
81
|
+
end
|
82
|
+
|
83
|
+
# HTTP PUT request.
|
84
|
+
#
|
85
|
+
# Save the content of the request.body.
|
86
|
+
def put(request, response)
|
87
|
+
write(request.body)
|
88
|
+
Created
|
89
|
+
end
|
90
|
+
|
91
|
+
# HTTP POST request.
|
92
|
+
#
|
93
|
+
# Usually forbidden.
|
94
|
+
def post(request, response)
|
95
|
+
raise HTTPStatus::Forbidden
|
96
|
+
end
|
97
|
+
|
98
|
+
# HTTP DELETE request.
|
99
|
+
#
|
100
|
+
# Delete this resource.
|
101
|
+
def delete
|
102
|
+
if stat.directory?
|
103
|
+
FileUtils.rm_rf(file_path)
|
104
|
+
else
|
105
|
+
::File.unlink(file_path)
|
106
|
+
end
|
107
|
+
::File.unlink(prop_path) if ::File.exists?(prop_path)
|
108
|
+
@_prop_hash = nil
|
109
|
+
NoContent
|
110
|
+
end
|
111
|
+
|
112
|
+
# HTTP COPY request.
|
113
|
+
#
|
114
|
+
# Copy this resource to given destination resource.
|
115
|
+
# Copy this resource to given destination resource.
|
116
|
+
def copy(dest, overwrite)
|
117
|
+
if(collection?)
|
118
|
+
if(dest.exist?)
|
119
|
+
if(dest.collection? && overwrite)
|
120
|
+
FileUtils.cp_r(file_path, dest.send(:file_path))
|
121
|
+
Created
|
122
|
+
else
|
123
|
+
if(overwrite)
|
124
|
+
FileUtils.rm(dest.send(:file_path))
|
125
|
+
FileUtils.cp_r(file_path, dest.send(:file_path))
|
126
|
+
NoContent
|
127
|
+
else
|
128
|
+
PreconditionFailed
|
129
|
+
end
|
130
|
+
end
|
131
|
+
else
|
132
|
+
FileUtils.cp_r(file_path, dest.send(:file_path))
|
133
|
+
Created
|
134
|
+
end
|
135
|
+
else
|
136
|
+
if(dest.exist? && !overwrite)
|
137
|
+
PreconditionFailed
|
138
|
+
else
|
139
|
+
if(::File.directory?(::File.dirname(dest.send(:file_path))))
|
140
|
+
new = !dest.exist?
|
141
|
+
if(dest.collection? && dest.exist?)
|
142
|
+
FileUtils.rm_rf(dest.send(:file_path))
|
143
|
+
end
|
144
|
+
FileUtils.cp(file_path, dest.send(:file_path).sub(/\/$/, ''))
|
145
|
+
FileUtils.cp(prop_path, dest.prop_path) if ::File.exist? prop_path
|
146
|
+
new ? Created : NoContent
|
147
|
+
else
|
148
|
+
Conflict
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# HTTP MOVE request.
|
155
|
+
#
|
156
|
+
# Move this resource to given destination resource.
|
157
|
+
def move(*args)
|
158
|
+
result = copy(*args)
|
159
|
+
delete if [Created, NoContent].include?(result)
|
160
|
+
result
|
161
|
+
end
|
162
|
+
|
163
|
+
# HTTP MKCOL request.
|
164
|
+
#
|
165
|
+
# Create this resource as collection.
|
166
|
+
def make_collection
|
167
|
+
if(request.body.read.to_s == '')
|
168
|
+
if(::File.directory?(file_path))
|
169
|
+
MethodNotAllowed
|
170
|
+
else
|
171
|
+
if(::File.directory?(::File.dirname(file_path)) && !::File.exists?(file_path))
|
172
|
+
Dir.mkdir(file_path)
|
173
|
+
Created
|
174
|
+
else
|
175
|
+
Conflict
|
176
|
+
end
|
177
|
+
end
|
178
|
+
else
|
179
|
+
UnsupportedMediaType
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Write to this resource from given IO.
|
184
|
+
def write(io)
|
185
|
+
tempfile = "#{file_path}.#{Process.pid}.#{object_id}"
|
186
|
+
open(tempfile, "wb") do |file|
|
187
|
+
while part = io.read(8192)
|
188
|
+
file << part
|
189
|
+
end
|
190
|
+
end
|
191
|
+
::File.rename(tempfile, file_path)
|
192
|
+
ensure
|
193
|
+
::File.unlink(tempfile) rescue nil
|
194
|
+
end
|
195
|
+
|
196
|
+
# name:: String - Property name
|
197
|
+
# Returns the value of the given property
|
198
|
+
def get_property(name)
|
199
|
+
begin
|
200
|
+
super
|
201
|
+
rescue NotImplemented
|
202
|
+
custom_props(name)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# name:: String - Property name
|
207
|
+
# value:: New value
|
208
|
+
# Set the property to the given value
|
209
|
+
def set_property(name, value)
|
210
|
+
begin
|
211
|
+
super
|
212
|
+
rescue NotImplemented
|
213
|
+
set_custom_props(name,value)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def remove_property(element)
|
218
|
+
prop_hash.transaction do
|
219
|
+
prop_hash.delete(to_element_key(element))
|
220
|
+
prop_hash.commit
|
221
|
+
end
|
222
|
+
val = prop_hash.transaction{ prop_hash[to_element_key(element)] }
|
223
|
+
end
|
224
|
+
|
225
|
+
def lock(args)
|
226
|
+
unless(parent_exists?)
|
227
|
+
Conflict
|
228
|
+
else
|
229
|
+
lock_check(args[:type])
|
230
|
+
lock = FileResourceLock.explicit_locks(@path, root, :scope => args[:scope], :kind => args[:type], :user => @user)
|
231
|
+
unless(lock)
|
232
|
+
token = UUIDTools::UUID.random_create.to_s
|
233
|
+
lock = FileResourceLock.generate(@path, @user, token, root)
|
234
|
+
lock.scope = args[:scope]
|
235
|
+
lock.kind = args[:type]
|
236
|
+
lock.owner = args[:owner]
|
237
|
+
lock.depth = args[:depth]
|
238
|
+
if(args[:timeout])
|
239
|
+
lock.timeout = args[:timeout] <= @max_timeout && args[:timeout] > 0 ? args[:timeout] : @max_timeout
|
240
|
+
else
|
241
|
+
lock.timeout = @default_timeout
|
242
|
+
end
|
243
|
+
lock.save
|
244
|
+
end
|
245
|
+
begin
|
246
|
+
lock_check(args[:type])
|
247
|
+
rescue DAV4Rack::LockFailure => lock_failure
|
248
|
+
lock.destroy
|
249
|
+
raise lock_failure
|
250
|
+
rescue HTTPStatus::Status => status
|
251
|
+
status
|
252
|
+
end
|
253
|
+
[lock.remaining_timeout, lock.token]
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def unlock(token)
|
258
|
+
token = token.slice(1, token.length - 2)
|
259
|
+
if(token.nil? || token.empty?)
|
260
|
+
BadRequest
|
261
|
+
else
|
262
|
+
lock = FileResourceLock.find_by_token(token)
|
263
|
+
if(lock.nil? || lock.user_id != @user.id)
|
264
|
+
Forbidden
|
265
|
+
elsif(lock.path !~ /^#{Regexp.escape(@path)}.*$/)
|
266
|
+
Conflict
|
267
|
+
else
|
268
|
+
lock.destroy
|
269
|
+
NoContent
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
protected
|
275
|
+
|
276
|
+
def lock_check(lock_type=nil)
|
277
|
+
if(FileResourceLock.explicitly_locked?(@path, root))
|
278
|
+
raise Locked if lock_type && lock_type == 'exclusive'
|
279
|
+
#raise Locked if FileResourceLock.explicit_locks(@path, root).find(:all, :conditions => ["scope = 'exclusive' AND user_id != ?", @user.id]).size > 0
|
280
|
+
elsif(FileResourceLock.implicitly_locked?(@path, root))
|
281
|
+
if(lock_type.to_s == 'exclusive')
|
282
|
+
locks = FileResourceLock.implicit_locks(@path)
|
283
|
+
failure = DAV4Rack::LockFailure.new("Failed to lock: #{@path}")
|
284
|
+
locks.each do |lock|
|
285
|
+
failure.add_failure(@path, Locked)
|
286
|
+
end
|
287
|
+
raise failure
|
288
|
+
else
|
289
|
+
locks = FileResourceLock.implict_locks(@path).find(:all, :conditions => ["scope = 'exclusive' AND user_id != ?", @user.id])
|
290
|
+
if(locks.size > 0)
|
291
|
+
failure = LockFailure.new("Failed to lock: #{@path}")
|
292
|
+
locks.each do |lock|
|
293
|
+
failure.add_failure(@path, Locked)
|
294
|
+
end
|
295
|
+
raise failure
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def set_custom_props(element, val)
|
302
|
+
prop_hash.transaction do
|
303
|
+
prop_hash[to_element_key(element)] = val
|
304
|
+
prop_hash.commit
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def custom_props(element)
|
309
|
+
val = prop_hash.transaction(true) do
|
310
|
+
prop_hash[to_element_key(element)]
|
311
|
+
end
|
312
|
+
raise NotFound unless val
|
313
|
+
val
|
314
|
+
end
|
315
|
+
|
316
|
+
def store_directory
|
317
|
+
path = ::File.join(root, '.attrib_store')
|
318
|
+
unless(::File.directory?(::File.dirname(path)))
|
319
|
+
FileUtils.mkdir_p(::File.dirname(path))
|
320
|
+
end
|
321
|
+
path
|
322
|
+
end
|
323
|
+
|
324
|
+
def prop_path
|
325
|
+
path = ::File.join(store_directory, "#{::File.join(::File.dirname(file_path), ::File.basename(file_path)).gsub('/', '_')}.pstore")
|
326
|
+
unless(::File.directory?(::File.dirname(path)))
|
327
|
+
FileUtils.mkdir_p(::File.dirname(path))
|
328
|
+
end
|
329
|
+
path
|
330
|
+
end
|
331
|
+
|
332
|
+
def lock_path
|
333
|
+
path = ::File.join(store_directory, 'locks.pstore')
|
334
|
+
unless(::File.directory?(::File.dirname(path)))
|
335
|
+
FileUtils.mkdir_p(::File.dirname(path))
|
336
|
+
end
|
337
|
+
path
|
338
|
+
end
|
339
|
+
|
340
|
+
def prop_hash
|
341
|
+
@_prop_hash ||= IS_18 ? PStore.new(prop_path) : PStore.new(prop_path, true)
|
342
|
+
end
|
343
|
+
|
344
|
+
def authenticate(user, pass)
|
345
|
+
if(options[:username])
|
346
|
+
options[:username] == user && options[:password] == pass
|
347
|
+
else
|
348
|
+
true
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def root
|
353
|
+
@options[:root]
|
354
|
+
end
|
355
|
+
|
356
|
+
def file_path
|
357
|
+
::File.join(root, path)
|
358
|
+
end
|
359
|
+
|
360
|
+
def stat
|
361
|
+
@stat ||= ::File.stat(file_path)
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|