alchemy-custom-model 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.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +147 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/alchemy_custom_model_manifest.js +3 -0
  6. data/app/assets/images/alchemy-custom-model/no_image.png +0 -0
  7. data/app/assets/javascripts/alchemy-custom-model/change_language.js +11 -0
  8. data/app/assets/javascripts/alchemy-custom-model/common_init.js +16 -0
  9. data/app/assets/javascripts/alchemy-custom-model/custom_admin_element_editor.js.coffee +25 -0
  10. data/app/assets/javascripts/alchemy-custom-model/custom_tiny_mce.js.coffee.erb +95 -0
  11. data/app/assets/javascripts/alchemy-custom-model/el_finder.js.coffee.erb +241 -0
  12. data/app/assets/javascripts/alchemy-custom-model/elfinder_ui_manifest.js +4 -0
  13. data/app/assets/javascripts/alchemy-custom-model/manifest.js +23 -0
  14. data/app/assets/javascripts/alchemy-custom-model/nested_attributes_sortable.js.coffee +25 -0
  15. data/app/assets/javascripts/alchemy-custom-model/select2filter.js +51 -0
  16. data/app/assets/javascripts/alchemy-custom-model/subobjects.js +98 -0
  17. data/app/assets/javascripts/alchemy-custom-model/total_page_elfinder.js.coffee +15 -0
  18. data/app/assets/stylesheets/alchemy-custom-model/custom_elfinder.css.scss +130 -0
  19. data/app/assets/stylesheets/alchemy-custom-model/custom_style.css.scss +228 -0
  20. data/app/assets/stylesheets/alchemy-custom-model/custom_tiny_mce.scss +6 -0
  21. data/app/assets/stylesheets/alchemy-custom-model/manifest.css +16 -0
  22. data/app/controllers/alchemy/custom/model/admin/base_controller.rb +189 -0
  23. data/app/controllers/alchemy/custom/model/admin/files_controller.rb +106 -0
  24. data/app/controllers/alchemy/pages_controller_decorator.rb +1 -0
  25. data/app/helpers/alchemy/custom/model/admin/base_helper.rb +379 -0
  26. data/app/helpers/alchemy/custom/model/base_helper.rb +18 -0
  27. data/app/helpers/alchemy/custom/model/custom_model_helper.rb +112 -0
  28. data/app/helpers/alchemy/pages_helper_decorator.rb +95 -0
  29. data/app/models/admin_override_to_param.rb +9 -0
  30. data/app/models/application_record.rb +9 -0
  31. data/app/views/alchemy/custom/model/admin/base/_buttons_tool.html.erb +16 -0
  32. data/app/views/alchemy/custom/model/admin/base/_gallery_item.html.erb +4 -0
  33. data/app/views/alchemy/custom/model/admin/base/_language_tree_select.html.erb +9 -0
  34. data/app/views/alchemy/custom/model/admin/base/_search_box.html.erb +19 -0
  35. data/app/views/alchemy/custom/model/admin/base/_seo.html.erb +8 -0
  36. data/app/views/alchemy/custom/model/admin/base/_table.html.erb +33 -0
  37. data/app/views/alchemy/custom/model/admin/base/_title.html.erb +3 -0
  38. data/app/views/alchemy/custom/model/admin/base/edit.html.erb +18 -0
  39. data/app/views/alchemy/custom/model/admin/base/index.html.erb +39 -0
  40. data/app/views/alchemy/custom/model/admin/base/new.html.erb +19 -0
  41. data/app/views/alchemy/custom/model/admin/files/error_notice.json.jbuilder +1 -0
  42. data/app/views/alchemy/custom/model/admin/files/ui.html.erb +13 -0
  43. data/config/initializers/elfinder_abilities.rb +1 -0
  44. data/config/locales/en.yml +11 -0
  45. data/config/locales/it.yml +21 -0
  46. data/config/routes.rb +8 -0
  47. data/lib/alchemy-custom-model.rb +29 -0
  48. data/lib/alchemy/custom/model/el_finder.rb +17 -0
  49. data/lib/alchemy/custom/model/el_finder/ability.rb +16 -0
  50. data/lib/alchemy/custom/model/el_finder/connector.rb +435 -0
  51. data/lib/alchemy/custom/model/el_finder/image.rb +35 -0
  52. data/lib/alchemy/custom/model/el_finder/path_name.rb +220 -0
  53. data/lib/alchemy/custom/model/el_finder/paths.rb +21 -0
  54. data/lib/alchemy/custom/model/el_finder/paths/active_record_reference.rb +50 -0
  55. data/lib/alchemy/custom/model/el_finder/paths/base.rb +298 -0
  56. data/lib/alchemy/custom/model/el_finder/paths/component_file.rb +59 -0
  57. data/lib/alchemy/custom/model/el_finder/paths/component_files.rb +34 -0
  58. data/lib/alchemy/custom/model/el_finder/paths/file.rb +23 -0
  59. data/lib/alchemy/custom/model/el_finder/paths/files.rb +25 -0
  60. data/lib/alchemy/custom/model/el_finder/paths/image.rb +42 -0
  61. data/lib/alchemy/custom/model/el_finder/paths/images.rb +31 -0
  62. data/lib/alchemy/custom/model/el_finder/paths/root.rb +24 -0
  63. data/lib/alchemy/custom/model/el_finder/volumes.rb +18 -0
  64. data/lib/alchemy/custom/model/el_finder/volumes/alchemy_file.rb +197 -0
  65. data/lib/alchemy/custom/model/el_finder/volumes/alchemy_files.rb +51 -0
  66. data/lib/alchemy/custom/model/el_finder/volumes/alchemy_images.rb +69 -0
  67. data/lib/alchemy/custom/model/el_finder/volumes/base.rb +149 -0
  68. data/lib/alchemy/custom/model/el_finder/volumes/component_attribute.rb +130 -0
  69. data/lib/alchemy/custom/model/engine.rb +40 -0
  70. data/lib/alchemy/custom/model/global_id_setter.rb +35 -0
  71. data/lib/alchemy/custom/model/model_decoration.rb +82 -0
  72. data/lib/alchemy/custom/model/pages_controller_dec.rb +132 -0
  73. data/lib/alchemy/custom/model/translation_scope.rb +18 -0
  74. data/lib/alchemy/custom/model/version.rb +7 -0
  75. data/lib/alchemy/touching_decorator.rb +12 -0
  76. data/lib/tasks/alchemy_custom_model_tasks.rake +41 -0
  77. data/vendor/elfinder/css/elfinder.full.css +5117 -0
  78. data/vendor/elfinder/css/elfinder.min.css +9 -0
  79. data/vendor/elfinder/css/theme.css +349 -0
  80. data/vendor/elfinder/js/elfinder.full.js +34270 -0
  81. data/vendor/elfinder/js/elfinder.min.js +25 -0
  82. metadata +194 -0
@@ -0,0 +1 @@
1
+ Alchemy.register_ability(Alchemy::Custom::Model::ElFinder::Ability)
@@ -0,0 +1,11 @@
1
+ en:
2
+ alchemy_custom_model:
3
+ you_are_editing_site_language: "You are editing the <strong>%{language}</strong> language of the site <strong>%{site}</strong>"
4
+ title_action: "%{action} %{model}"
5
+ actions:
6
+ new: New
7
+ edit: Edit
8
+ show: View
9
+ update: Edit
10
+ index: View all
11
+ create: New
@@ -0,0 +1,21 @@
1
+ it:
2
+ alchemy_custom_model:
3
+ you_are_editing_site_language: "Stai modificando la lingua <strong>%{language}</strong> del sito <strong>%{site}</strong>"
4
+ title_action: "%{action} %{model}"
5
+ actions:
6
+ new: Nuovo
7
+ edit: Modifica
8
+ show: Visualizza
9
+ update: Modifica
10
+ index: Visualizza tutti
11
+ create: Nuovo
12
+
13
+ elfinder:
14
+ alchemy_images:
15
+ volume: "Immagini"
16
+
17
+ sub_objects:
18
+ title_add: Aggiungi
19
+ minimize_all: Minimizza
20
+ maxzimize_all: Massimizza
21
+
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ Alchemy::Custom::Model::Engine.routes.draw do
2
+
3
+ namespace :admin do
4
+ match '/elfinder_ui' => 'files#ui', via: [:get]
5
+ match '/elfinder' => 'files#elfinder', via: [:get, :post]
6
+ end
7
+
8
+ end
@@ -0,0 +1,29 @@
1
+ require "alchemy_cms"
2
+ require "jquery/ui/rails"
3
+ require "el_finder"
4
+ require "friendly_id"
5
+ require "alchemy/custom/model/engine"
6
+
7
+
8
+ module Alchemy
9
+ module Custom
10
+ module Model
11
+ extend ActiveSupport::Autoload
12
+
13
+ autoload :GlobalIdSetter
14
+ autoload :ModelDecoration
15
+ autoload :TranslationScope
16
+ autoload :PagesControllerDec
17
+
18
+
19
+ mattr_accessor :base_admin_controller_class
20
+
21
+ @@base_admin_controller_class = 'Alchemy::Admin::BaseController'
22
+
23
+
24
+ def self.admin_controller_class
25
+ @@base_admin_controller_class.constantize
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ module Alchemy
2
+ module Custom
3
+ module Model
4
+ module ElFinder
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Ability
8
+ autoload :Connector
9
+ autoload :Image
10
+ autoload :PathName
11
+
12
+ # eager_autoload do
13
+ # end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Alchemy::Custom::Model
2
+ module ElFinder
3
+ class Ability
4
+ include CanCan::Ability
5
+
6
+ def initialize(user)
7
+ if user.present? && user.is_admin?
8
+ can :usage, Alchemy::Custom::Model::ElFinder
9
+ can :ui_usage, Alchemy::Custom::Model::ElFinder
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+
@@ -0,0 +1,435 @@
1
+ module Alchemy::Custom::Model::ElFinder
2
+ class Connector
3
+
4
+ VERSION = 2.1
5
+
6
+ # Valid commands to run.
7
+ # @see #run
8
+ VALID_COMMANDS = %w[open tree file paste upload search rm ls dim resize duplicate] #%w[archive duplicate edit extract mkdir mkfile open parents paste ping read rename resize rm tmb upload]
9
+
10
+ # Default options for instances.
11
+ # @see #initialize
12
+ DEFAULT_OPTIONS = {
13
+ :mime_handler => ::ElFinder::MimeType,
14
+ # :image_handler => ElFinder::Image,
15
+ :original_filename_method => lambda {|file| file.original_filename.respond_to?(:force_encoding) ? file.original_filename.force_encoding('utf-8') : file.original_filename},
16
+ :disabled_commands => [],
17
+ :allow_dot_files => true,
18
+ :upload_max_size => '50M',
19
+ # :upload_file_mode => 0644,
20
+ # :archivers => {},
21
+ # :extractors => {},
22
+ :home => 'Home',
23
+ :default_perms => {:read => true, :write => true, :rm => true, :hidden => false},
24
+ :perms => [],
25
+ :thumbs => false,
26
+ :thumbs_directory => '.thumbs',
27
+ :thumbs_size => 48,
28
+ :thumbs_at_once => 5,
29
+ # :tree_sub_folders => true, # list sub/sub folders in the tree
30
+ }
31
+
32
+ # Initializes new instance.
33
+ # @param [Hash] options Instance options. :url and :root options are required.
34
+ # @option options [String] :url Entry point of ElFinder router.
35
+ # @option options [String] :root Root directory of ElFinder directory structure.
36
+ # @see DEFAULT_OPTIONS
37
+ def initialize(options)
38
+ @options = DEFAULT_OPTIONS.merge(options)
39
+
40
+ @options[:disabled_commands] += ['mkdir', 'rename']
41
+
42
+ raise(ArgumentError, "Missing required :volumes option") unless @options.key?(:volumes)
43
+ # raise(ArgumentError, "Missing required :url option") unless @options.key?(:url)
44
+ # raise(ArgumentError, "Missing required :root option") unless @options.key?(:root)
45
+ raise(ArgumentError, "Mime Handler is invalid") unless mime_handler.respond_to?(:for)
46
+ # raise(ArgumentError, "Image Handler is invalid") unless image_handler.nil? || ([:size, :resize, :thumbnail].all? {|m| image_handler.respond_to?(m)})
47
+
48
+ @volumes = options[:volumes]
49
+ @root = PathName.new(options[:root])
50
+
51
+ @headers = {}
52
+ @response = {}
53
+ end
54
+
55
+ # of initialize
56
+
57
+ # Runs request-response cycle.
58
+ # @param [Hash] params Request parameters. :cmd option is required.
59
+ # @option params [String] :cmd Command to be performed.
60
+ # @see VALID_COMMANDS
61
+ def run(params)
62
+ @params = params.dup
63
+ @headers = {}
64
+ @response = {}
65
+ @response[:errorData] = {}
66
+ @file = nil
67
+
68
+ if VALID_COMMANDS.include?(@params[:cmd])
69
+
70
+ if @options[:thumbs]
71
+ @thumb_directory = @root + @options[:thumbs_directory]
72
+ @thumb_directory.mkdir unless @thumb_directory.exist?
73
+ raise(RuntimeError, "Unable to create thumbs directory") unless @thumb_directory.directory?
74
+ end
75
+
76
+ @current = @params[:current] ? from_hash(@params[:current]) : nil
77
+ @volume, @target = (@params[:target] and !@params[:target].empty?) ? from_hash(@params[:target]) : [nil, nil]
78
+ if params[:targets]
79
+ @targets = @params[:targets].map {|t| from_hash(t)}
80
+ end
81
+
82
+ send("_#{@params[:cmd]}")
83
+ else
84
+ invalid_request
85
+ end
86
+
87
+ @response.delete(:errorData) if @response[:errorData].empty?
88
+
89
+ return @headers, @response, @file
90
+ end
91
+
92
+ # of run
93
+
94
+ #
95
+ def to_hash(pathname)
96
+ # note that '=' are removed
97
+ Base64.urlsafe_encode64(pathname.path.to_s).chomp.tr("=\n", "")
98
+ end
99
+
100
+ # of to_hash
101
+
102
+ #
103
+ def from_hash(hash)
104
+ volume = @volumes.find {|v| v.contains?(hash)}
105
+ if volume
106
+ [volume, volume.decode(hash)]
107
+ else
108
+ @response[:error] = 'errFileNotFound'
109
+ nil
110
+ end
111
+ # restore missing '='
112
+ # len = hash.length % 4
113
+ # hash += '==' if len == 1 or len == 2
114
+ # hash += '=' if len == 3
115
+
116
+ # decoded_hash = Base64.urlsafe_decode64(hash)
117
+ # decoded_hash = decoded_hash.respond_to?(:force_encoding) ? decoded_hash.force_encoding('utf-8') : decoded_hash
118
+ # pathname = @root + decoded_hash
119
+ # rescue ArgumentError => e
120
+ # if e.message != 'invalid base64'
121
+ # raise
122
+ # end
123
+ # nil
124
+ end
125
+
126
+ # of from_hash
127
+
128
+ # @!attribute [w] options
129
+ # Options setter.
130
+ # @param value [Hash] Options to be merged with instance ones.
131
+ # @return [Hash] Updated options.
132
+ def options=(value = {})
133
+ value.each_pair do |k, v|
134
+ @options[k.to_sym] = v
135
+ end
136
+ @options
137
+ end
138
+
139
+ # of options=
140
+
141
+ ################################################################################
142
+
143
+ protected
144
+
145
+ def _file
146
+ if @volume && @target
147
+ path = @volume.pathname(@target)
148
+ @file = {path: path}
149
+ end
150
+ end
151
+
152
+ def _search
153
+ type = @params.delete(:type) {"full_search"}
154
+ q = @params.delete(:q)
155
+ if @params[:mimes]
156
+ type = 'mimes'
157
+ q = @params[:mimes]
158
+ end
159
+
160
+ @response[:files] = @volume.search(type: type, q: q)
161
+
162
+ end
163
+
164
+ ##
165
+ # Funzione lanciata praticamente all'upload dei file, dato che non abbiamo problemi di duplicati
166
+ # dato che sono tutti in database, inviamo sempre un vuoto
167
+ # nel caso dobbiamo implementare invece questo: https://github.com/Studio-42/elFinder/wiki/Client-Server-API-2.1#ls
168
+ def _ls
169
+ @response[:list] = []
170
+ end
171
+
172
+ #
173
+ def _open(volume = nil, target = nil, payload: {})
174
+ if @params[:init]
175
+ _open_init
176
+ return
177
+ end
178
+
179
+ volume ||= @volume
180
+ target ||= @target
181
+
182
+ if volume.nil?
183
+ _open(@volumes[0], nil, payload: payload)
184
+ return
185
+ end
186
+
187
+ if target.nil?
188
+ _open(volume, '.', payload: payload)
189
+ return
190
+ end
191
+
192
+ # if perms_for(target)[:read] == false
193
+ # @response[:error] = 'Access Denied'
194
+ # return
195
+ # end
196
+
197
+ if target.file?
198
+ command_not_implemented
199
+ elsif target.directory?
200
+ @response[:cwd] = volume.cwd(target)
201
+ @response[:files] = volume.files(target)
202
+ @response.merge!(payload)
203
+
204
+ # @response[:cdc] = target.children.
205
+ # reject{ |child| perms_for(child)[:hidden]}.
206
+ # sort_by{|e| e.basename.to_s.downcase}.map{|e| cdc_for(e)}.compact
207
+
208
+ # if @params[:tree]
209
+ # @response[:tree] = {
210
+ # :name => @options[:home],
211
+ # :hash => to_hash(@root),
212
+ # :dirs => tree_for(@root),
213
+ # }.merge(perms_for(@root))
214
+ # end
215
+ @response[:options] = {}
216
+ if @params[:init]
217
+ @response = init_request(@response, volume: volume)
218
+ else
219
+ #se non siamo in init, allora inseriamo l'elenco dei comandi che il volume aperto non supporta
220
+ @response[:options][:disabled] = init_request(@response.dup, volume: volume)[:options][:disabled]
221
+ end
222
+
223
+ else
224
+ @response[:error] = "Directory does not exist"
225
+ _open(@root) if File.directory?(@root)
226
+ end
227
+
228
+ end
229
+
230
+ # of open
231
+
232
+
233
+ def _dim
234
+ if @target.is_a? ElFinder::Paths::Image
235
+ @response[:dim] = @target.dim
236
+ else
237
+ @response[:error] = "Operazione non supportata"
238
+ end
239
+ end
240
+
241
+
242
+ def _tree(volume = nil, target = nil)
243
+ volume ||= @volume
244
+ target ||= @target
245
+
246
+ @response[:api] = VERSION
247
+ @response[:tree] = volume.tree(target)
248
+
249
+ end
250
+
251
+ def init_request(payload, volume:)
252
+ payload[:api] = VERSION
253
+ # payload[:disabled] = @options[:disabled_commands]
254
+ payload[:options] = {
255
+ :dotFiles => @options[:allow_dot_files],
256
+ :uplMaxSize => @options[:upload_max_size],
257
+ :uploadMaxConn => -1, #configurazione per cui non deve spezzare in chucks i files
258
+ :archives => [], #@options[:archivers].keys,
259
+ :extract => [], #@options[:extractors].keys,
260
+ :url => @options[:url],
261
+ disabled: @options[:disabled_commands] + volume.disabled_commands
262
+ }
263
+
264
+ payload
265
+ end
266
+
267
+ def _open_init
268
+ @response[:cwd] = @volumes[0].cwd
269
+
270
+ files = []
271
+ @volumes.each {|v| files.concat(v.files)}
272
+ @response[:files] = files
273
+ @response = init_request(@response, volume: @volumes[0])
274
+ end
275
+
276
+ # of open_init
277
+
278
+ def _paste
279
+
280
+ moved_files = []
281
+ @targets.to_a.each do |src_v, src_f|
282
+
283
+ #scopro il volume di destinazione
284
+ dst_v, dst_f = from_hash(@params[:dst])
285
+
286
+ if dst_v.is_a?(Volumes::ComponentAttribute)
287
+ moved_files << dst_v.copy(src_f)
288
+ else
289
+ @response[:error] ||= 'Copia non consentita'
290
+ end
291
+
292
+ end
293
+ @params[:tree] = true
294
+
295
+ # dest_vlm = @targets.first[0]
296
+ dest_vlm = from_hash(@params[:dst])[0]
297
+
298
+ dest_target = dest_vlm.decode(dest_vlm.encode('.'))
299
+
300
+ _open(dest_vlm, dest_target, payload: {moved_files: moved_files.collect {|v| dest_vlm.path_info(v)}})
301
+ end
302
+
303
+ # of paste
304
+
305
+
306
+ def _rm
307
+ @response[:removed] = @targets.to_a.collect do |src_v, src_f|
308
+ src_v.rm(src_f)
309
+ src_v.encode(src_f.path.to_s)
310
+ end
311
+ end
312
+
313
+ #
314
+ def _resize
315
+ if @target.is_image?
316
+
317
+ file = @target.file
318
+ case @params[:mode]
319
+ when 'resize'
320
+ file = file.thumb("#{@params[:width]}x#{@params[:height]}!")
321
+ when 'crop'
322
+ file = file.thumb("#{@params[:width]}x#{@params[:height]}+#{@params[:x]}+#{@params[:y]}")
323
+ when 'rotate'
324
+
325
+ command = []
326
+ command << "-background #{@params[:bg]}" unless @params[:bg].blank?
327
+ command << "-rotate #{@params[:degree]}"
328
+
329
+ file = file.convert(command.join(' '))
330
+ else
331
+ @response[:error] = "Mode:#{@params[:mode]} not implemented"
332
+ return
333
+ end
334
+ file = file.convert("-quality #{@params[:quality]}") if @params[:quality].to_i < 100
335
+ @target.file = file
336
+ @target.save
337
+
338
+ @response[:changed] = [to_hash(@target)]
339
+ _open(@volume, @volume.root_path)
340
+ else
341
+ @response[:error] = "Unable to resize file. It does not exist"
342
+ end
343
+ end
344
+
345
+ # of resize
346
+
347
+ def _duplicate
348
+
349
+ @targets.each do |v, f|
350
+ unless f.is_image?
351
+ @response[:error] = "#{f.name} non è un'immagine"
352
+ return
353
+ end
354
+ end
355
+
356
+ @targets.each do |v, f|
357
+ unless v.duplicable?(f)
358
+ @response[:error] = "#{f.name} non può essere duplicato"
359
+ return
360
+ end
361
+ end
362
+
363
+ added = @targets.collect do |v, t|
364
+ v.path_info(v.duplicate(t))
365
+ end
366
+
367
+ @response[:added] = added
368
+ # _open(@targets.first[0], @targets.first[0].root_path)
369
+ end
370
+
371
+ # of duplicate
372
+
373
+
374
+ #
375
+ def _upload
376
+ if @volume && @target
377
+ response = @volume.upload(@target, @params[:upload])
378
+ @response.merge!(response)
379
+ # _open(@volume, @target)
380
+ else
381
+ @response[:error] = "errUploadCommon"
382
+ end
383
+ # if perms_for(@current)[:write] == false
384
+ # @response[:error] = 'Access Denied'
385
+ # return
386
+ # end
387
+ # select = []
388
+ # @params[:upload].to_a.each do |file|
389
+ # if file.respond_to?(:tempfile)
390
+ # the_file = file.tempfile
391
+ # else
392
+ # the_file = file
393
+ # end
394
+ # if upload_max_size_in_bytes > 0 && File.size(the_file.path) > upload_max_size_in_bytes
395
+ # @response[:error] ||= "Some files were not uploaded"
396
+ # @response[:errorData][@options[:original_filename_method].call(file)] = 'File exceeds the maximum allowed filesize'
397
+ # else
398
+ # dst = @current + @options[:original_filename_method].call(file)
399
+ # the_file.close
400
+ # src = the_file.path
401
+ # FileUtils.mv(src, dst.fullpath)
402
+ # FileUtils.chmod @options[:upload_file_mode], dst
403
+ # select << to_hash(dst)
404
+ # end
405
+ # end
406
+ # @response[:select] = select unless select.empty?
407
+ # _open(@current)
408
+ end
409
+
410
+ # of upload
411
+
412
+ private
413
+
414
+ def mime_handler
415
+ @options[:mime_handler]
416
+ end
417
+
418
+ #
419
+ # def image_handler
420
+ # @options[:image_handler]
421
+ # end
422
+
423
+ #
424
+ def invalid_request
425
+ @response[:error] = "Invalid command '#{@params[:cmd]}'"
426
+ end
427
+
428
+ # of invalid_request
429
+
430
+ #
431
+ def command_not_implemented
432
+ @response[:error] = "Command '#{@params[:cmd]}' not yet implemented"
433
+ end # of command_not_implemented
434
+ end
435
+ end