el_finder_s3 0.1.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.
- checksums.yaml +7 -0
- data/.editorconfig +12 -0
- data/.gitignore +36 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +37 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/el_finder_s3.gemspec +36 -0
- data/lib/el_finder_s3.rb +14 -0
- data/lib/el_finder_s3/action.rb +32 -0
- data/lib/el_finder_s3/adapter.rb +222 -0
- data/lib/el_finder_s3/base64.rb +24 -0
- data/lib/el_finder_s3/cache_connector.rb +27 -0
- data/lib/el_finder_s3/connector.rb +676 -0
- data/lib/el_finder_s3/image.rb +30 -0
- data/lib/el_finder_s3/mime_type.rb +83 -0
- data/lib/el_finder_s3/pathname.rb +250 -0
- data/lib/el_finder_s3/railties.rb +7 -0
- data/lib/el_finder_s3/s3_connector.rb +89 -0
- data/lib/el_finder_s3/s3_pathname.rb +179 -0
- data/lib/el_finder_s3/version.rb +3 -0
- metadata +126 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
if RUBY_VERSION < '1.9'
|
2
|
+
begin
|
3
|
+
require 'base64'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
|
7
|
+
if defined? ::Base64
|
8
|
+
# The Base64 module provides for the encoding (encode64, strict_encode64, urlsafe_encode64) and decoding (decode64, strict_decode64, urlsafe_decode64) of binary data using a Base64 representation.
|
9
|
+
# @note stdlib module.
|
10
|
+
module ::Base64
|
11
|
+
# Returns the Base64-encoded version of bin. This method complies with "Base 64 Encoding with URL and Filename Safe Alphabet" in RFC 4648. The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
12
|
+
# @note This method will be defined only on ruby 1.8 due to its absence in stdlib.
|
13
|
+
def self.urlsafe_encode64(bin)
|
14
|
+
[bin].pack("m0").tr("+/", "-_")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the Base64-decoded version of str. This method complies with "Base 64 Encoding with URL and Filename Safe Alphabet" in RFC 4648. The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
18
|
+
# @note This method will be defined only on ruby 1.8 due to its absence in stdlib.
|
19
|
+
def self.urlsafe_decode64(str)
|
20
|
+
str.tr("-_", "+/").unpack("m0").first
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ElFinderS3
|
2
|
+
class CacheConnector
|
3
|
+
|
4
|
+
def ls_folder(folder)
|
5
|
+
raise 'This is not implemented!'
|
6
|
+
end
|
7
|
+
|
8
|
+
def tree_for(root)
|
9
|
+
raise 'This is not implemented!'
|
10
|
+
end
|
11
|
+
|
12
|
+
def mkdirSuccess(folder)
|
13
|
+
raise 'This is not implemented!'
|
14
|
+
end
|
15
|
+
|
16
|
+
def list_objects search_parameters
|
17
|
+
raise 'This is not implemented!'
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
def update_ls_folder_results query, response
|
23
|
+
raise 'This is not implemented!'
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,676 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module ElFinderS3
|
5
|
+
|
6
|
+
# Represents ElFinder connector on Rails side.
|
7
|
+
class Connector
|
8
|
+
|
9
|
+
# Valid commands to run.
|
10
|
+
# @see #run
|
11
|
+
VALID_COMMANDS = %w[archive duplicate put file ls tree extract mkdir mkfile open paste ping get rename resize rm tmb upload]
|
12
|
+
|
13
|
+
attr_reader :adapter
|
14
|
+
|
15
|
+
# Default options for instances.
|
16
|
+
# @see #initialize
|
17
|
+
DEFAULT_OPTIONS = {
|
18
|
+
:mime_handler => ElFinderS3::MimeType,
|
19
|
+
:image_handler => ElFinderS3::Image,
|
20
|
+
:original_filename_method => lambda { |file| file.original_filename.respond_to?(:force_encoding) ? file.original_filename.force_encoding('utf-8') : file.original_filename },
|
21
|
+
:disabled_commands => %w(archive duplicate extract resize tmb),
|
22
|
+
:allow_dot_files => true,
|
23
|
+
:upload_max_size => '50M',
|
24
|
+
:name_validator => lambda { |name| name.strip != '.' && name =~ /^[^\x00-\x1f\\?*:"><|\/]+$/ },
|
25
|
+
:upload_file_mode => 0644,
|
26
|
+
:archivers => {},
|
27
|
+
:extractors => {},
|
28
|
+
:home => 'Home',
|
29
|
+
:default_perms => {:read => true, :write => true, :locked => false, :hidden => false},
|
30
|
+
:perms => [],
|
31
|
+
:thumbs => false,
|
32
|
+
:thumbs_directory => '.thumbs',
|
33
|
+
:thumbs_size => 48,
|
34
|
+
:thumbs_at_once => 5,
|
35
|
+
}
|
36
|
+
|
37
|
+
# Initializes new instance.
|
38
|
+
# @param [Hash] options Instance options. :url and :server options are required.
|
39
|
+
# @option options [String] :url Entry point of ElFinder router.
|
40
|
+
# @option options [String] :server A hash containing the :host, :username, :password, and, optionally, :port to connect to
|
41
|
+
# @see DEFAULT_OPTIONS
|
42
|
+
def initialize(options)
|
43
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
44
|
+
|
45
|
+
raise(ArgumentError, 'Missing required :url option') unless @options.key?(:url)
|
46
|
+
raise(ArgumentError, 'Missing required :server option') unless @options.key?(:server)
|
47
|
+
raise(ArgumentError, 'Mime Handler is invalid') unless mime_handler.respond_to?(:for)
|
48
|
+
raise(ArgumentError, 'Image Handler is invalid') unless image_handler.nil? || ([:size, :resize, :thumbnail].all? { |m| image_handler.respond_to?(m) })
|
49
|
+
|
50
|
+
raise(ArgumentError, 'Missing required :region option') unless @options[:server].key?(:region)
|
51
|
+
raise(ArgumentError, 'Missing required :access_key_id option') unless @options[:server].key?(:access_key_id)
|
52
|
+
raise(ArgumentError, 'Missing required :secret_access_key option') unless @options[:server].key?(:secret_access_key)
|
53
|
+
raise(ArgumentError, 'Missing required :bucket_name option') unless @options[:server].key?(:bucket_name)
|
54
|
+
|
55
|
+
@options[:url] = 'https://' + @options[:server][:bucket] + '.s3.amazonaws.com' unless @options.key?(:url)
|
56
|
+
|
57
|
+
@headers = {}
|
58
|
+
@response = {}
|
59
|
+
end
|
60
|
+
|
61
|
+
# of initialize
|
62
|
+
|
63
|
+
# Logger is a class property
|
64
|
+
class <<self
|
65
|
+
def logger
|
66
|
+
@logger ||= Logger.new(STDOUT)
|
67
|
+
end
|
68
|
+
|
69
|
+
def logger=(val)
|
70
|
+
@logger = val
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Runs request-response cycle.
|
75
|
+
# @param [Hash] params Request parameters. :cmd option is required.
|
76
|
+
# @option params [String] :cmd Command to be performed.
|
77
|
+
# @see VALID_COMMANDS
|
78
|
+
def run(params)
|
79
|
+
|
80
|
+
@adapter = ElFinderS3::Adapter.new(@options[:server])
|
81
|
+
# @adapter = ElFinderS3::FtpAdapter.new(@options[:server])
|
82
|
+
@root = ElFinderS3::Pathname.new(adapter)
|
83
|
+
|
84
|
+
begin
|
85
|
+
@params = params.dup
|
86
|
+
@headers = {}
|
87
|
+
@response = {}
|
88
|
+
@response[:errorData] = {}
|
89
|
+
|
90
|
+
if VALID_COMMANDS.include?(@params[:cmd])
|
91
|
+
|
92
|
+
if @options[:thumbs]
|
93
|
+
@thumb_directory = @root + @options[:thumbs_directory]
|
94
|
+
@thumb_directory.mkdir unless @thumb_directory.exist?
|
95
|
+
raise(RuntimeError, "Unable to create thumbs directory") unless @thumb_directory.directory?
|
96
|
+
end
|
97
|
+
|
98
|
+
@current = @params[:current] ? from_hash(@params[:current]) : nil
|
99
|
+
@target = (@params[:target] and !@params[:target].empty?) ? from_hash(@params[:target]) : nil
|
100
|
+
if params[:targets]
|
101
|
+
@targets = @params[:targets].map { |t| from_hash(t) }
|
102
|
+
end
|
103
|
+
|
104
|
+
begin
|
105
|
+
send("_#{@params[:cmd]}")
|
106
|
+
rescue Net::FTPPermError
|
107
|
+
@response[:error] = 'Access Denied'
|
108
|
+
end
|
109
|
+
else
|
110
|
+
invalid_request
|
111
|
+
end
|
112
|
+
|
113
|
+
@response.delete(:errorData) if @response[:errorData].empty?
|
114
|
+
|
115
|
+
return @headers, @response
|
116
|
+
ensure
|
117
|
+
adapter.close
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# of run
|
122
|
+
|
123
|
+
#
|
124
|
+
def to_hash(pathname)
|
125
|
+
# note that '=' are removed
|
126
|
+
Base64.urlsafe_encode64(pathname.path.to_s).chomp.tr("=\n", "")
|
127
|
+
end
|
128
|
+
|
129
|
+
# of to_hash
|
130
|
+
|
131
|
+
#
|
132
|
+
def from_hash(hash)
|
133
|
+
# restore missing '='
|
134
|
+
len = hash.length % 4
|
135
|
+
hash += '==' if len == 1 or len == 2
|
136
|
+
hash += '=' if len == 3
|
137
|
+
|
138
|
+
decoded_hash = Base64.urlsafe_decode64(hash)
|
139
|
+
decoded_hash = decoded_hash.respond_to?(:force_encoding) ? decoded_hash.force_encoding('utf-8') : decoded_hash
|
140
|
+
pathname = @root + decoded_hash
|
141
|
+
rescue ArgumentError => e
|
142
|
+
if e.message != 'invalid base64'
|
143
|
+
raise
|
144
|
+
end
|
145
|
+
nil
|
146
|
+
end
|
147
|
+
|
148
|
+
# of from_hash
|
149
|
+
|
150
|
+
# @!attribute [w] options
|
151
|
+
# Options setter.
|
152
|
+
# @param value [Hash] Options to be merged with instance ones.
|
153
|
+
# @return [Hash] Updated options.
|
154
|
+
def options=(value = {})
|
155
|
+
value.each_pair do |k, v|
|
156
|
+
@options[k.to_sym] = v
|
157
|
+
end
|
158
|
+
@options
|
159
|
+
end
|
160
|
+
|
161
|
+
# of options=
|
162
|
+
|
163
|
+
################################################################################
|
164
|
+
protected
|
165
|
+
|
166
|
+
#
|
167
|
+
def _open(target = nil)
|
168
|
+
target ||= @target
|
169
|
+
|
170
|
+
if target.nil?
|
171
|
+
_open(@root)
|
172
|
+
return
|
173
|
+
end
|
174
|
+
|
175
|
+
if perms_for(target)[:read] == false
|
176
|
+
@response[:error] = 'Access Denied'
|
177
|
+
return
|
178
|
+
end
|
179
|
+
|
180
|
+
if target.file?
|
181
|
+
command_not_implemented
|
182
|
+
elsif target.directory?
|
183
|
+
@response[:cwd] = cwd_for(target)
|
184
|
+
@response[:cdc] = target.children.
|
185
|
+
reject { |child| perms_for(child)[:hidden] }.
|
186
|
+
sort_by { |e| e.basename.to_s.downcase }.map { |e| cdc_for(e) }.compact
|
187
|
+
|
188
|
+
if @params[:tree]
|
189
|
+
@response[:tree] = {
|
190
|
+
:name => @options[:home],
|
191
|
+
:hash => to_hash(@root),
|
192
|
+
:dirs => tree_for(@root),
|
193
|
+
}.merge(perms_for(@root))
|
194
|
+
end
|
195
|
+
|
196
|
+
if @params[:init]
|
197
|
+
@response[:disabled] = @options[:disabled_commands]
|
198
|
+
@response[:params] = {
|
199
|
+
:dotFiles => @options[:allow_dot_files],
|
200
|
+
:uplMaxSize => @options[:upload_max_size],
|
201
|
+
:archives => @options[:archivers].keys,
|
202
|
+
:extract => @options[:extractors].keys,
|
203
|
+
:url => @options[:url]
|
204
|
+
}
|
205
|
+
end
|
206
|
+
|
207
|
+
else
|
208
|
+
@response[:error] = "Directory does not exist"
|
209
|
+
_open(@root) if File.directory?(@root)
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
# of open
|
215
|
+
|
216
|
+
def _ls
|
217
|
+
if @target.directory?
|
218
|
+
files = @target.files.reject { |child| perms_for(child)[:hidden] }
|
219
|
+
|
220
|
+
@response[:list] = files.map { |e| e.basename.to_s }.compact
|
221
|
+
else
|
222
|
+
@response[:error] = "Directory does not exist"
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
# of open
|
228
|
+
|
229
|
+
def _tree
|
230
|
+
if @target.directory?
|
231
|
+
@response[:tree] = tree_for(@target).map { |e| cdc_for(e) }.compact
|
232
|
+
else
|
233
|
+
@response[:error] = "Directory does not exist"
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
# of tree
|
239
|
+
|
240
|
+
#
|
241
|
+
def _mkdir
|
242
|
+
if perms_for(@target)[:write] == false
|
243
|
+
@response[:error] = 'Access Denied'
|
244
|
+
return
|
245
|
+
end
|
246
|
+
unless valid_name?(@params[:name])
|
247
|
+
@response[:error] = 'Unable to create folder'
|
248
|
+
return
|
249
|
+
end
|
250
|
+
|
251
|
+
dir = @target + @params[:name]
|
252
|
+
if !dir.exist? && dir.mkdir
|
253
|
+
@params[:tree] = true
|
254
|
+
@response[:added] = [to_hash(dir)]
|
255
|
+
_open(@target)
|
256
|
+
else
|
257
|
+
@response[:error] = "Unable to create folder"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# of mkdir
|
262
|
+
|
263
|
+
#
|
264
|
+
def _mkfile
|
265
|
+
if perms_for(@target)[:write] == false
|
266
|
+
@response[:error] = 'Access Denied'
|
267
|
+
return
|
268
|
+
end
|
269
|
+
unless valid_name?(@params[:name])
|
270
|
+
@response[:error] = 'Unable to create file'
|
271
|
+
return
|
272
|
+
end
|
273
|
+
|
274
|
+
file = @target + @params[:name]
|
275
|
+
if !file.exist? && file.touch
|
276
|
+
@response[:select] = [to_hash(file)]
|
277
|
+
_open(@target)
|
278
|
+
else
|
279
|
+
@response[:error] = "Unable to create file"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# of mkfile
|
284
|
+
|
285
|
+
#
|
286
|
+
def _rename
|
287
|
+
unless valid_name?(@params[:name])
|
288
|
+
@response[:error] = "Unable to rename #{@target.ftype}"
|
289
|
+
return
|
290
|
+
end
|
291
|
+
|
292
|
+
to = @target.dirname + @params[:name]
|
293
|
+
|
294
|
+
perms_for_target = perms_for(@target)
|
295
|
+
if perms_for_target[:locked] == true
|
296
|
+
@response[:error] = 'Access Denied'
|
297
|
+
return
|
298
|
+
end
|
299
|
+
|
300
|
+
perms_for_current = perms_for(@target)
|
301
|
+
if perms_for_current[:write] == false
|
302
|
+
@response[:error] = 'Access Denied'
|
303
|
+
return
|
304
|
+
end
|
305
|
+
|
306
|
+
if to.exist?
|
307
|
+
@response[:error] = "Unable to rename #{@target.ftype}. '#{to.basename}' already exists"
|
308
|
+
else
|
309
|
+
to = @target.rename(to)
|
310
|
+
if to
|
311
|
+
@response[:added] = [cdc_for(to)]
|
312
|
+
@response[:removed] = [to_hash(@target)]
|
313
|
+
else
|
314
|
+
@response[:error] = "Unable to rename #{@target.ftype}"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
# of rename
|
320
|
+
|
321
|
+
#
|
322
|
+
def _upload
|
323
|
+
if perms_for(@current)[:write] == false
|
324
|
+
@response[:error] = 'Access Denied'
|
325
|
+
return
|
326
|
+
end
|
327
|
+
select = []
|
328
|
+
@params[:upload].to_a.each do |io|
|
329
|
+
name = @options[:original_filename_method].call(io)
|
330
|
+
unless valid_name?(name)
|
331
|
+
@response[:error] = 'Unable to create file'
|
332
|
+
return
|
333
|
+
end
|
334
|
+
dst = @current + name
|
335
|
+
|
336
|
+
dst.write(io)
|
337
|
+
|
338
|
+
select << to_hash(dst)
|
339
|
+
end
|
340
|
+
@response[:select] = select unless select.empty?
|
341
|
+
_open(@current)
|
342
|
+
end
|
343
|
+
|
344
|
+
# of upload
|
345
|
+
|
346
|
+
#
|
347
|
+
def _ping
|
348
|
+
@headers['Connection'] = 'Close'
|
349
|
+
end
|
350
|
+
|
351
|
+
# of ping
|
352
|
+
|
353
|
+
#
|
354
|
+
def _paste
|
355
|
+
if perms_for(from_hash(@params[:dst]))[:write] == false
|
356
|
+
@response[:error] = 'Access Denied'
|
357
|
+
return
|
358
|
+
end
|
359
|
+
|
360
|
+
added_list = []
|
361
|
+
removed_list = []
|
362
|
+
@targets.to_a.each do |src|
|
363
|
+
if perms_for(src)[:read] == false || (@params[:cut].to_i > 0 && perms_for(src)[:locked] == true)
|
364
|
+
@response[:error] ||= 'Some files were not moved.'
|
365
|
+
@response[:errorData][src.basename.to_s] = "Access Denied"
|
366
|
+
return
|
367
|
+
else
|
368
|
+
dst = from_hash(@params[:dst]) + src.basename
|
369
|
+
if dst.exist?
|
370
|
+
@response[:error] ||= 'The target file already exists'
|
371
|
+
@response[:errorData][src.basename.to_s] = "already exists in '#{dst.dirname}'"
|
372
|
+
else
|
373
|
+
if @params[:cut].to_i > 0
|
374
|
+
adapter.move(src, dst)
|
375
|
+
|
376
|
+
added_list.push cdc_for(dst)
|
377
|
+
removed_list.push to_hash(src)
|
378
|
+
else
|
379
|
+
command_not_implemented
|
380
|
+
return
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
@response[:added] = added_list unless added_list.empty?
|
387
|
+
@response[:removed] = removed_list unless removed_list.empty?
|
388
|
+
end
|
389
|
+
|
390
|
+
# of paste
|
391
|
+
|
392
|
+
#
|
393
|
+
def _rm
|
394
|
+
if @targets.empty?
|
395
|
+
@response[:error] = "No files were selected for removal"
|
396
|
+
else
|
397
|
+
removed_list = []
|
398
|
+
@targets.to_a.each do |target|
|
399
|
+
removed_list.concat remove_target(target)
|
400
|
+
end
|
401
|
+
@response[:removed] = removed_list unless removed_list.empty?
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
# of rm
|
406
|
+
|
407
|
+
#
|
408
|
+
def _duplicate
|
409
|
+
command_not_implemented
|
410
|
+
end
|
411
|
+
|
412
|
+
# of duplicate
|
413
|
+
|
414
|
+
#
|
415
|
+
def _get
|
416
|
+
if perms_for(@target)[:read] == true
|
417
|
+
@response[:content] = @target.read
|
418
|
+
else
|
419
|
+
@response[:error] = 'Access Denied'
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
# of get
|
424
|
+
|
425
|
+
#
|
426
|
+
def _file
|
427
|
+
if perms_for(@target)[:read] == true
|
428
|
+
@response[:file_data] = @target.read
|
429
|
+
@response[:mime_type] = mime_handler.for(@target)
|
430
|
+
@response[:disposition] = 'attachment'
|
431
|
+
@response[:filename] = @target.basename.to_s
|
432
|
+
else
|
433
|
+
@response[:error] = 'Access Denied'
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
# of file
|
438
|
+
|
439
|
+
#
|
440
|
+
def _put
|
441
|
+
perms = perms_for(@target)
|
442
|
+
if perms[:read] == true && perms[:write] == true
|
443
|
+
@target.write @params[:content]
|
444
|
+
@response[:changed] = [cdc_for(@target)]
|
445
|
+
else
|
446
|
+
@response[:error] = 'Access Denied'
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
# of put
|
451
|
+
|
452
|
+
#
|
453
|
+
def _extract
|
454
|
+
command_not_implemented
|
455
|
+
end
|
456
|
+
|
457
|
+
# of extract
|
458
|
+
|
459
|
+
#
|
460
|
+
def _archive
|
461
|
+
command_not_implemented
|
462
|
+
end
|
463
|
+
|
464
|
+
# of archive
|
465
|
+
|
466
|
+
#
|
467
|
+
def _tmb
|
468
|
+
command_not_implemented
|
469
|
+
end
|
470
|
+
|
471
|
+
# of tmb
|
472
|
+
|
473
|
+
#
|
474
|
+
def _resize
|
475
|
+
command_not_implemented
|
476
|
+
end
|
477
|
+
|
478
|
+
# of resize
|
479
|
+
|
480
|
+
################################################################################
|
481
|
+
private
|
482
|
+
|
483
|
+
#
|
484
|
+
def upload_max_size_in_bytes
|
485
|
+
bytes = @options[:upload_max_size]
|
486
|
+
if bytes.is_a?(String) && bytes.strip =~ /(\d+)([KMG]?)/
|
487
|
+
bytes = $1.to_i
|
488
|
+
unit = $2
|
489
|
+
case unit
|
490
|
+
when 'K'
|
491
|
+
bytes *= 1024
|
492
|
+
when 'M'
|
493
|
+
bytes *= 1024 * 1024
|
494
|
+
when 'G'
|
495
|
+
bytes *= 1024 * 1024 * 1024
|
496
|
+
end
|
497
|
+
end
|
498
|
+
bytes.to_i
|
499
|
+
end
|
500
|
+
|
501
|
+
#
|
502
|
+
def thumbnail_for(pathname)
|
503
|
+
@thumb_directory + "#{to_hash(pathname)}.png"
|
504
|
+
end
|
505
|
+
|
506
|
+
#
|
507
|
+
def remove_target(target)
|
508
|
+
removed = []
|
509
|
+
if target.directory?
|
510
|
+
target.children.each do |child|
|
511
|
+
removed.concat remove_target(child)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
if perms_for(target)[:locked] == true
|
515
|
+
@response[:error] ||= 'Some files/directories were unable to be removed'
|
516
|
+
@response[:errorData][target.basename.to_s] = "Access Denied"
|
517
|
+
else
|
518
|
+
begin
|
519
|
+
removed.push to_hash(target)
|
520
|
+
target.unlink
|
521
|
+
if @options[:thumbs] && (thumbnail = thumbnail_for(target)).file?
|
522
|
+
removed.push to_hash(thumbnail)
|
523
|
+
thumbnail.unlink
|
524
|
+
end
|
525
|
+
rescue Exception => ex
|
526
|
+
@response[:error] ||= 'Some files/directories were unable to be removed'
|
527
|
+
@response[:errorData][target.basename.to_s] = "Remove failed"
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
removed
|
532
|
+
end
|
533
|
+
|
534
|
+
def mime_handler
|
535
|
+
@options[:mime_handler]
|
536
|
+
end
|
537
|
+
|
538
|
+
#
|
539
|
+
def image_handler
|
540
|
+
@options[:image_handler]
|
541
|
+
end
|
542
|
+
|
543
|
+
def cwd_for(pathname)
|
544
|
+
{
|
545
|
+
:name => pathname.basename.to_s,
|
546
|
+
:hash => to_hash(pathname),
|
547
|
+
:mime => 'directory',
|
548
|
+
:rel => pathname.is_root? ? @options[:home] : (@options[:home] + '/' + pathname.path.to_s),
|
549
|
+
:size => 0,
|
550
|
+
:date => pathname.mtime.to_s,
|
551
|
+
}.merge(perms_for(pathname))
|
552
|
+
end
|
553
|
+
|
554
|
+
def cdc_for(pathname)
|
555
|
+
return nil if @options[:thumbs] && pathname.to_s == @thumb_directory.to_s
|
556
|
+
response = {
|
557
|
+
:name => pathname.basename.to_s,
|
558
|
+
:hash => to_hash(pathname),
|
559
|
+
:date => pathname.mtime.to_s
|
560
|
+
}
|
561
|
+
response.merge! perms_for(pathname)
|
562
|
+
|
563
|
+
if pathname.directory?
|
564
|
+
response.merge!(
|
565
|
+
:size => 0,
|
566
|
+
:mime => 'directory'
|
567
|
+
)
|
568
|
+
elsif pathname.file?
|
569
|
+
response.merge!(
|
570
|
+
:size => pathname.size,
|
571
|
+
:mime => mime_handler.for(pathname),
|
572
|
+
:url => (@options[:url] + '/' + pathname.path.to_s)
|
573
|
+
)
|
574
|
+
|
575
|
+
if pathname.readable? && response[:mime] =~ /image/ && !image_handler.nil?
|
576
|
+
response.merge!(
|
577
|
+
:resize => true,
|
578
|
+
:dim => image_handler.size(pathname)
|
579
|
+
)
|
580
|
+
if @options[:thumbs]
|
581
|
+
if (thumbnail = thumbnail_for(pathname)).exist?
|
582
|
+
response.merge!(:tmb => (@options[:url] + '/' + thumbnail.path.to_s))
|
583
|
+
else
|
584
|
+
@response[:tmb] = true
|
585
|
+
end
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
end
|
590
|
+
|
591
|
+
if pathname.symlink?
|
592
|
+
response.merge!(
|
593
|
+
:link => to_hash(@root + pathname.readlink), # hash of file to which point link
|
594
|
+
:linkTo => (@root + pathname.readlink).relative_to(pathname.dirname.path).to_s, # relative path to
|
595
|
+
:parent => to_hash((@root + pathname.readlink).dirname) # hash of directory in which is linked file
|
596
|
+
)
|
597
|
+
end
|
598
|
+
|
599
|
+
return response
|
600
|
+
end
|
601
|
+
|
602
|
+
#
|
603
|
+
def tree_for(root)
|
604
|
+
root.child_directories(@options[:tree_sub_folders]).
|
605
|
+
reject { |child|
|
606
|
+
(@options[:thumbs] && child.to_s == @thumb_directory.to_s) || perms_for(child)[:hidden]
|
607
|
+
}.
|
608
|
+
sort_by { |e| e.basename.to_s.downcase }.
|
609
|
+
map { |child|
|
610
|
+
{:name => child.basename.to_s,
|
611
|
+
:hash => to_hash(child),
|
612
|
+
:dirs => tree_for(child),
|
613
|
+
}.merge(perms_for(child))
|
614
|
+
}
|
615
|
+
end
|
616
|
+
|
617
|
+
# of tree_for
|
618
|
+
|
619
|
+
#
|
620
|
+
def perms_for(pathname, options = {})
|
621
|
+
# skip = [options[:skip]].flatten
|
622
|
+
response = {}
|
623
|
+
|
624
|
+
response[:read] = pathname.readable?
|
625
|
+
response[:read] &&= specific_perm_for(pathname, :read)
|
626
|
+
response[:read] &&= @options[:default_perms][:read]
|
627
|
+
|
628
|
+
response[:write] = pathname.writable?
|
629
|
+
response[:write] &&= specific_perm_for(pathname, :write)
|
630
|
+
response[:write] &&= @options[:default_perms][:write]
|
631
|
+
|
632
|
+
response[:locked] = pathname.is_root?
|
633
|
+
response[:locked] &&= specific_perm_for(pathname, :locked)
|
634
|
+
response[:locked] &&= @options[:default_perms][:locked]
|
635
|
+
|
636
|
+
response[:hidden] = false
|
637
|
+
response[:hidden] ||= specific_perm_for(pathname, :hidden)
|
638
|
+
response[:hidden] ||= @options[:default_perms][:hidden]
|
639
|
+
|
640
|
+
response
|
641
|
+
end
|
642
|
+
|
643
|
+
# of perms_for
|
644
|
+
|
645
|
+
#
|
646
|
+
def specific_perm_for(pathname, perm)
|
647
|
+
pathname = pathname.path if pathname.is_a?(ElFinderS3::Pathname)
|
648
|
+
matches = @options[:perms].select { |k, v| pathname.to_s.send((k.is_a?(String) ? :== : :match), k) }
|
649
|
+
if perm == :hidden
|
650
|
+
matches.one? { |e| e.last[perm] }
|
651
|
+
else
|
652
|
+
matches.none? { |e| e.last[perm] == false }
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
# of specific_perm_for
|
657
|
+
|
658
|
+
#
|
659
|
+
def valid_name?(name)
|
660
|
+
@options[:name_validator].call(name)
|
661
|
+
end
|
662
|
+
|
663
|
+
#
|
664
|
+
def invalid_request
|
665
|
+
@response[:error] = "Invalid command '#{@params[:cmd]}'"
|
666
|
+
end
|
667
|
+
|
668
|
+
# of invalid_request
|
669
|
+
|
670
|
+
#
|
671
|
+
def command_not_implemented
|
672
|
+
@response[:error] = "Command '#{@params[:cmd]}' not implemented"
|
673
|
+
end # of command_not_implemented
|
674
|
+
|
675
|
+
end # of class Connector
|
676
|
+
end # of module ElFinderS3
|