drg_elfinder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/drg_elfinder_manifest.js +1 -0
  6. data/app/assets/javascripts/drg_elfinder.js +15 -0
  7. data/app/assets/javascripts/elfinder/Changelog +1283 -0
  8. data/app/assets/javascripts/elfinder/LICENSE.md +15 -0
  9. data/app/assets/javascripts/elfinder/README.md +216 -0
  10. data/app/assets/javascripts/elfinder/bower.json +28 -0
  11. data/app/assets/javascripts/elfinder/composer.json +39 -0
  12. data/app/assets/javascripts/elfinder/css/elfinder.full.css +5350 -0
  13. data/app/assets/javascripts/elfinder/css/elfinder.min.css +9 -0
  14. data/app/assets/javascripts/elfinder/css/theme.css +430 -0
  15. data/app/assets/javascripts/elfinder/elfinder.html +74 -0
  16. data/app/assets/javascripts/elfinder/elfinder.legacy.html +94 -0
  17. data/app/assets/javascripts/elfinder/img/arrows-active.png +0 -0
  18. data/app/assets/javascripts/elfinder/img/arrows-normal.png +0 -0
  19. data/app/assets/javascripts/elfinder/img/crop.gif +0 -0
  20. data/app/assets/javascripts/elfinder/img/dialogs.png +0 -0
  21. data/app/assets/javascripts/elfinder/img/edit_aceeditor.png +0 -0
  22. data/app/assets/javascripts/elfinder/img/edit_ckeditor.png +0 -0
  23. data/app/assets/javascripts/elfinder/img/edit_ckeditor5.png +0 -0
  24. data/app/assets/javascripts/elfinder/img/edit_codemirror.png +0 -0
  25. data/app/assets/javascripts/elfinder/img/edit_creativecloud.png +0 -0
  26. data/app/assets/javascripts/elfinder/img/edit_onlineconvert.png +0 -0
  27. data/app/assets/javascripts/elfinder/img/edit_pixlreditor.png +0 -0
  28. data/app/assets/javascripts/elfinder/img/edit_pixlrexpress.png +0 -0
  29. data/app/assets/javascripts/elfinder/img/edit_simplemde.png +0 -0
  30. data/app/assets/javascripts/elfinder/img/edit_tinymce.png +0 -0
  31. data/app/assets/javascripts/elfinder/img/edit_tuiimgedit.png +0 -0
  32. data/app/assets/javascripts/elfinder/img/edit_zohooffice.png +0 -0
  33. data/app/assets/javascripts/elfinder/img/editor-icons.png +0 -0
  34. data/app/assets/javascripts/elfinder/img/icons-big.png +0 -0
  35. data/app/assets/javascripts/elfinder/img/icons-big.svg +1 -0
  36. data/app/assets/javascripts/elfinder/img/icons-small.png +0 -0
  37. data/app/assets/javascripts/elfinder/img/logo.png +0 -0
  38. data/app/assets/javascripts/elfinder/img/progress.gif +0 -0
  39. data/app/assets/javascripts/elfinder/img/quicklook-bg.png +0 -0
  40. data/app/assets/javascripts/elfinder/img/quicklook-icons.png +0 -0
  41. data/app/assets/javascripts/elfinder/img/resize.png +0 -0
  42. data/app/assets/javascripts/elfinder/img/spinner-mini.gif +0 -0
  43. data/app/assets/javascripts/elfinder/img/toolbar.png +0 -0
  44. data/app/assets/javascripts/elfinder/img/trashmesh.png +0 -0
  45. data/app/assets/javascripts/elfinder/img/tui-icon-a.svg +235 -0
  46. data/app/assets/javascripts/elfinder/img/tui-icon-b.svg +224 -0
  47. data/app/assets/javascripts/elfinder/img/tui-icon-c.svg +224 -0
  48. data/app/assets/javascripts/elfinder/img/tui-icon-d.svg +224 -0
  49. data/app/assets/javascripts/elfinder/img/ui-icons_ffffff_256x240.png +0 -0
  50. data/app/assets/javascripts/elfinder/img/volume_icon_box.png +0 -0
  51. data/app/assets/javascripts/elfinder/img/volume_icon_box.svg +1 -0
  52. data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.png +0 -0
  53. data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.svg +1 -0
  54. data/app/assets/javascripts/elfinder/img/volume_icon_ftp.png +0 -0
  55. data/app/assets/javascripts/elfinder/img/volume_icon_ftp.svg +1 -0
  56. data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.png +0 -0
  57. data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.svg +1 -0
  58. data/app/assets/javascripts/elfinder/img/volume_icon_local.png +0 -0
  59. data/app/assets/javascripts/elfinder/img/volume_icon_local.svg +1 -0
  60. data/app/assets/javascripts/elfinder/img/volume_icon_network.png +0 -0
  61. data/app/assets/javascripts/elfinder/img/volume_icon_network.svg +1 -0
  62. data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.png +0 -0
  63. data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.svg +1 -0
  64. data/app/assets/javascripts/elfinder/img/volume_icon_sql.png +0 -0
  65. data/app/assets/javascripts/elfinder/img/volume_icon_sql.svg +1 -0
  66. data/app/assets/javascripts/elfinder/img/volume_icon_trash.png +0 -0
  67. data/app/assets/javascripts/elfinder/img/volume_icon_trash.svg +1 -0
  68. data/app/assets/javascripts/elfinder/img/volume_icon_zip.png +0 -0
  69. data/app/assets/javascripts/elfinder/img/volume_icon_zip.svg +1 -0
  70. data/app/assets/javascripts/elfinder/js/elfinder.full.js +36019 -0
  71. data/app/assets/javascripts/elfinder/js/elfinder.min.js +25 -0
  72. data/app/assets/javascripts/elfinder/js/extras/editors.default.js +2643 -0
  73. data/app/assets/javascripts/elfinder/js/extras/editors.default.min.js +2 -0
  74. data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.js +75 -0
  75. data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.min.js +1 -0
  76. data/app/assets/javascripts/elfinder/js/i18n/elfinder.LANG.js +587 -0
  77. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ar.js +580 -0
  78. data/app/assets/javascripts/elfinder/js/i18n/elfinder.bg.js +559 -0
  79. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ca.js +375 -0
  80. data/app/assets/javascripts/elfinder/js/i18n/elfinder.cs.js +581 -0
  81. data/app/assets/javascripts/elfinder/js/i18n/elfinder.da.js +580 -0
  82. data/app/assets/javascripts/elfinder/js/i18n/elfinder.de.js +582 -0
  83. data/app/assets/javascripts/elfinder/js/i18n/elfinder.el.js +374 -0
  84. data/app/assets/javascripts/elfinder/js/i18n/elfinder.es.js +546 -0
  85. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fa.js +580 -0
  86. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fallback.js +11 -0
  87. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fo.js +419 -0
  88. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr.js +578 -0
  89. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr_CA.js +580 -0
  90. data/app/assets/javascripts/elfinder/js/i18n/elfinder.he.js +375 -0
  91. data/app/assets/javascripts/elfinder/js/i18n/elfinder.hr.js +434 -0
  92. data/app/assets/javascripts/elfinder/js/i18n/elfinder.hu.js +580 -0
  93. data/app/assets/javascripts/elfinder/js/i18n/elfinder.id.js +498 -0
  94. data/app/assets/javascripts/elfinder/js/i18n/elfinder.it.js +552 -0
  95. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ja.js +581 -0
  96. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ko.js +582 -0
  97. data/app/assets/javascripts/elfinder/js/i18n/elfinder.nl.js +581 -0
  98. data/app/assets/javascripts/elfinder/js/i18n/elfinder.no.js +374 -0
  99. data/app/assets/javascripts/elfinder/js/i18n/elfinder.pl.js +580 -0
  100. data/app/assets/javascripts/elfinder/js/i18n/elfinder.pt_BR.js +580 -0
  101. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ro.js +417 -0
  102. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ru.js +582 -0
  103. data/app/assets/javascripts/elfinder/js/i18n/elfinder.si.js +537 -0
  104. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sk.js +581 -0
  105. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sl.js +374 -0
  106. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sr.js +374 -0
  107. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sv.js +375 -0
  108. data/app/assets/javascripts/elfinder/js/i18n/elfinder.tr.js +583 -0
  109. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ug_CN.js +374 -0
  110. data/app/assets/javascripts/elfinder/js/i18n/elfinder.uk.js +580 -0
  111. data/app/assets/javascripts/elfinder/js/i18n/elfinder.vi.js +579 -0
  112. data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_CN.js +585 -0
  113. data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_TW.js +582 -0
  114. data/app/assets/javascripts/elfinder/js/i18n/help/cs.html.js +10 -0
  115. data/app/assets/javascripts/elfinder/js/i18n/help/de.html.js +15 -0
  116. data/app/assets/javascripts/elfinder/js/i18n/help/en.html.js +10 -0
  117. data/app/assets/javascripts/elfinder/js/i18n/help/es.html.js +10 -0
  118. data/app/assets/javascripts/elfinder/js/i18n/help/ja.html.js +10 -0
  119. data/app/assets/javascripts/elfinder/js/i18n/help/ko.html.js +10 -0
  120. data/app/assets/javascripts/elfinder/js/i18n/help/pl.html.js +10 -0
  121. data/app/assets/javascripts/elfinder/js/i18n/help/ru.html.js +10 -0
  122. data/app/assets/javascripts/elfinder/js/i18n/help/sk.html.js +10 -0
  123. data/app/assets/javascripts/elfinder/js/i18n/help/tr.html.js +10 -0
  124. data/app/assets/javascripts/elfinder/js/proxy/elFinderSupportVer1.js +408 -0
  125. data/app/assets/javascripts/elfinder/js/worker/calcfilehash.js +20 -0
  126. data/app/assets/javascripts/elfinder/js/worker/quicklook.tiff.js +7 -0
  127. data/app/assets/javascripts/elfinder/js/worker/quicklook.unzip.js +55 -0
  128. data/app/assets/javascripts/elfinder/main.default.js +175 -0
  129. data/app/assets/javascripts/elfinder/package.json +13 -0
  130. data/app/assets/javascripts/elfinder/php/MySQLStorage.sql +47 -0
  131. data/app/assets/javascripts/elfinder/php/autoload.php +56 -0
  132. data/app/assets/javascripts/elfinder/php/connector.maximal.php-dist +449 -0
  133. data/app/assets/javascripts/elfinder/php/connector.minimal.php-dist +180 -0
  134. data/app/assets/javascripts/elfinder/php/editors/OnlineConvert/editor.php +113 -0
  135. data/app/assets/javascripts/elfinder/php/editors/ZipArchive/editor.php +12 -0
  136. data/app/assets/javascripts/elfinder/php/editors/ZohoOffice/editor.php +206 -0
  137. data/app/assets/javascripts/elfinder/php/editors/editor.php +79 -0
  138. data/app/assets/javascripts/elfinder/php/elFinder.class.php +5401 -0
  139. data/app/assets/javascripts/elfinder/php/elFinderConnector.class.php +380 -0
  140. data/app/assets/javascripts/elfinder/php/elFinderFlysystemGoogleDriveNetmount.php +380 -0
  141. data/app/assets/javascripts/elfinder/php/elFinderPlugin.php +113 -0
  142. data/app/assets/javascripts/elfinder/php/elFinderSession.php +335 -0
  143. data/app/assets/javascripts/elfinder/php/elFinderSessionInterface.php +57 -0
  144. data/app/assets/javascripts/elfinder/php/elFinderVolumeBox.class.php +1972 -0
  145. data/app/assets/javascripts/elfinder/php/elFinderVolumeDriver.class.php +7651 -0
  146. data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox.class.php +1464 -0
  147. data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox2.class.php +1516 -0
  148. data/app/assets/javascripts/elfinder/php/elFinderVolumeFTP.class.php +1810 -0
  149. data/app/assets/javascripts/elfinder/php/elFinderVolumeGoogleDrive.class.php +2163 -0
  150. data/app/assets/javascripts/elfinder/php/elFinderVolumeGroup.class.php +315 -0
  151. data/app/assets/javascripts/elfinder/php/elFinderVolumeLocalFileSystem.class.php +1477 -0
  152. data/app/assets/javascripts/elfinder/php/elFinderVolumeMySQL.class.php +1022 -0
  153. data/app/assets/javascripts/elfinder/php/elFinderVolumeOneDrive.class.php +2131 -0
  154. data/app/assets/javascripts/elfinder/php/elFinderVolumeSFTPphpseclib.class.php +838 -0
  155. data/app/assets/javascripts/elfinder/php/elFinderVolumeTrash.class.php +51 -0
  156. data/app/assets/javascripts/elfinder/php/elFinderVolumeTrashMySQL.class.php +51 -0
  157. data/app/assets/javascripts/elfinder/php/libs/GdBmp.php +473 -0
  158. data/app/assets/javascripts/elfinder/php/mime.types +781 -0
  159. data/app/assets/javascripts/elfinder/php/plugins/AutoResize/plugin.php +151 -0
  160. data/app/assets/javascripts/elfinder/php/plugins/AutoRotate/plugin.php +148 -0
  161. data/app/assets/javascripts/elfinder/php/plugins/Normalizer/plugin.php +204 -0
  162. data/app/assets/javascripts/elfinder/php/plugins/Sanitizer/plugin.php +157 -0
  163. data/app/assets/javascripts/elfinder/php/plugins/Watermark/logo.png +0 -0
  164. data/app/assets/javascripts/elfinder/php/plugins/Watermark/plugin.php +432 -0
  165. data/app/assets/javascripts/elfinder/php/plugins/WinRemoveTailDots/plugin.php +114 -0
  166. data/app/assets/javascripts/elfinder/php/resources/image.png +0 -0
  167. data/app/assets/javascripts/elfinder/php/resources/video.png +0 -0
  168. data/app/assets/javascripts/elfinder/sounds/rm.wav +0 -0
  169. data/app/controllers/dc_elfinder_controller.rb +63 -0
  170. data/app/models/drgcms_form_fields/elfinder.rb +85 -0
  171. data/changelog.md +0 -0
  172. data/lib/drg_elfinder/engine.rb +5 -0
  173. data/lib/drg_elfinder/version.rb +3 -0
  174. data/lib/drg_elfinder.rb +9 -0
  175. data/lib/el_finder/action.rb +19 -0
  176. data/lib/el_finder/base64.rb +24 -0
  177. data/lib/el_finder/connector.rb +625 -0
  178. data/lib/el_finder/image.rb +33 -0
  179. data/lib/el_finder/mime_type.rb +86 -0
  180. data/lib/el_finder/pathname.rb +185 -0
  181. data/lib/el_finder/version.rb +5 -0
  182. data/lib/el_finder.rb +8 -0
  183. data/lib/patches/patch_for_elfinder.rb +115 -0
  184. data/lib/tasks/drg_elfinder_tasks.rake +10 -0
  185. metadata +245 -0
@@ -0,0 +1,625 @@
1
+ #
2
+ # http://elrte.org/redmine/projects/elfinder/wiki/Client-Server_Protocol_EN
3
+ #
4
+
5
+ require 'base64'
6
+
7
+ module ElFinder
8
+
9
+ # Represents ElFinder connector on Rails side.
10
+ class Connector
11
+
12
+ # Valid commands to run.
13
+ # @see #run
14
+ VALID_COMMANDS = %w[archive duplicate edit extract mkdir mkfile open paste ping read rename resize rm tmb upload]
15
+
16
+ # Default options for instances.
17
+ # @see #initialize
18
+ DEFAULT_OPTIONS = {
19
+ :mime_handler => ElFinder::MimeType,
20
+ :image_handler => ElFinder::Image,
21
+ :original_filename_method => lambda { |file| file.original_filename.respond_to?(:force_encoding) ? file.original_filename.force_encoding('utf-8') : file.original_filename },
22
+ :disabled_commands => [],
23
+ :allow_dot_files => true,
24
+ :upload_max_size => '50M',
25
+ :upload_file_mode => 0644,
26
+ :archivers => {},
27
+ :extractors => {},
28
+ :home => 'Home',
29
+ :default_perms => { :read => true, :write => true, :rm => true, :hidden => false },
30
+ :perms => [],
31
+ :thumbs => false,
32
+ :thumbs_directory => '.thumbs',
33
+ :thumbs_size => 48,
34
+ :thumbs_at_once => 5,
35
+ :tree_sub_folders => true, # list sub/sub folders in the tree
36
+ }
37
+
38
+ # Initializes new instance.
39
+ # @param [Hash] options Instance options. :url and :root options are required.
40
+ # @option options [String] :url Entry point of ElFinder router.
41
+ # @option options [String] :root Root directory of ElFinder directory structure.
42
+ # @see DEFAULT_OPTIONS
43
+ def initialize(options)
44
+ @options = DEFAULT_OPTIONS.merge(options)
45
+
46
+ raise(ArgumentError, "Missing required :url option") unless @options.key?(:url)
47
+ raise(ArgumentError, "Missing required :root option") unless @options.key?(:root)
48
+ raise(ArgumentError, "Mime Handler is invalid") unless mime_handler.respond_to?(:for)
49
+ raise(ArgumentError, "Image Handler is invalid") unless image_handler.nil? || ([:size, :resize, :thumbnail].all?{|m| image_handler.respond_to?(m)})
50
+
51
+ @root = ElFinder::Pathname.new(options[:root])
52
+
53
+ @headers = {}
54
+ @response = {}
55
+ end # 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
+
67
+ if VALID_COMMANDS.include?(@params[:cmd])
68
+
69
+ if @options[:thumbs]
70
+ @thumb_directory = @root + @options[:thumbs_directory]
71
+ @thumb_directory.mkdir unless @thumb_directory.exist?
72
+ raise(RuntimeError, "Unable to create thumbs directory") unless @thumb_directory.directory?
73
+ end
74
+
75
+ @current = @params[:current] ? from_hash(@params[:current]) : nil
76
+ @target = (@params[:target] and !@params[:target].empty?) ? from_hash(@params[:target]) : nil
77
+ if params[:targets]
78
+ @targets = @params[:targets].map{|t| from_hash(t)}
79
+ end
80
+
81
+ send("_#{@params[:cmd]}")
82
+ else
83
+ invalid_request
84
+ end
85
+
86
+ @response.delete(:errorData) if @response[:errorData].empty?
87
+
88
+ return @headers, @response
89
+ end # of run
90
+
91
+ #
92
+ def to_hash(pathname)
93
+ # note that '=' are removed
94
+ Base64.urlsafe_encode64(pathname.path.to_s).chomp.tr("=\n", "")
95
+ end # of to_hash
96
+
97
+ #
98
+ def from_hash(hash)
99
+ # restore missing '='
100
+ len = hash.length % 4
101
+ hash += '==' if len == 1 or len == 2
102
+ hash += '=' if len == 3
103
+
104
+ decoded_hash = Base64.urlsafe_decode64(hash)
105
+ decoded_hash = decoded_hash.respond_to?(:force_encoding) ? decoded_hash.force_encoding('utf-8') : decoded_hash
106
+ pathname = @root + decoded_hash
107
+ rescue ArgumentError => e
108
+ if e.message != 'invalid base64'
109
+ raise
110
+ end
111
+ nil
112
+ end # of from_hash
113
+
114
+ # @!attribute [w] options
115
+ # Options setter.
116
+ # @param value [Hash] Options to be merged with instance ones.
117
+ # @return [Hash] Updated options.
118
+ def options=(value = {})
119
+ value.each_pair do |k, v|
120
+ @options[k.to_sym] = v
121
+ end
122
+ @options
123
+ end # of options=
124
+
125
+ ################################################################################
126
+ protected
127
+
128
+ #
129
+ def _open(target = nil)
130
+ target ||= @target
131
+
132
+ if target.nil?
133
+ _open(@root)
134
+ return
135
+ end
136
+
137
+ if perms_for(target)[:read] == false
138
+ @response[:error] = 'Access Denied'
139
+ return
140
+ end
141
+
142
+ if target.file?
143
+ command_not_implemented
144
+ elsif target.directory?
145
+ @response[:cwd] = cwd_for(target)
146
+ @response[:cdc] = target.children.
147
+ reject{ |child| perms_for(child)[:hidden]}.
148
+ sort_by{|e| e.basename.to_s.downcase}.map{|e| cdc_for(e)}.compact
149
+
150
+ if @params[:tree]
151
+ @response[:tree] = {
152
+ :name => @options[:home],
153
+ :hash => to_hash(@root),
154
+ :dirs => tree_for(@root),
155
+ }.merge(perms_for(@root))
156
+ end
157
+
158
+ if @params[:init]
159
+ @response[:disabled] = @options[:disabled_commands]
160
+ @response[:params] = {
161
+ :dotFiles => @options[:allow_dot_files],
162
+ :uplMaxSize => @options[:upload_max_size],
163
+ :archives => @options[:archivers].keys,
164
+ :extract => @options[:extractors].keys,
165
+ :url => @options[:url]
166
+ }
167
+ end
168
+
169
+ else
170
+ @response[:error] = "Directory does not exist"
171
+ _open(@root) if File.directory?(@root)
172
+ end
173
+
174
+ end # of open
175
+
176
+ #
177
+ def _mkdir
178
+ if perms_for(@current)[:write] == false
179
+ @response[:error] = 'Access Denied'
180
+ return
181
+ end
182
+
183
+ dir = @current + @params[:name]
184
+ if !dir.exist? && dir.mkdir
185
+ @params[:tree] = true
186
+ @response[:select] = [to_hash(dir)]
187
+ _open(@current)
188
+ else
189
+ @response[:error] = "Unable to create folder"
190
+ end
191
+ end # of mkdir
192
+
193
+ #
194
+ def _mkfile
195
+ if perms_for(@current)[:write] == false
196
+ @response[:error] = 'Access Denied'
197
+ return
198
+ end
199
+
200
+ file = @current + @params[:name]
201
+ if !file.exist? && file.touch
202
+ @response[:select] = [to_hash(file)]
203
+ _open(@current)
204
+ else
205
+ @response[:error] = "Unable to create file"
206
+ end
207
+ end # of mkfile
208
+
209
+ #
210
+ def _rename
211
+ to = @current + @params[:name]
212
+
213
+ perms_for_target = perms_for(@target)
214
+ if perms_for_target[:rm] == false
215
+ @response[:error] = 'Access Denied'
216
+ return
217
+ end
218
+
219
+ perms_for_current = perms_for(@current)
220
+ if perms_for_current[:write] == false
221
+ @response[:error] = 'Access Denied'
222
+ return
223
+ end
224
+
225
+ if to.exist?
226
+ @response[:error] = "Unable to rename #{@target.ftype}. '#{to.basename}' already exists"
227
+ elsif @target.rename(to)
228
+ @params[:tree] = to.directory?
229
+ @response[:select] = [to_hash(to)]
230
+ _open(@current)
231
+ else
232
+ @response[:error] = "Unable to rename #{@target.ftype}"
233
+ end
234
+ end # of rename
235
+
236
+ #
237
+ def _upload
238
+ if perms_for(@current)[:write] == false
239
+ @response[:error] = 'Access Denied'
240
+ return
241
+ end
242
+ select = []
243
+ @params[:upload].to_a.each do |file|
244
+ if file.respond_to?(:tempfile)
245
+ the_file = file.tempfile
246
+ else
247
+ the_file = file
248
+ end
249
+ if upload_max_size_in_bytes > 0 && File.size(the_file.path) > upload_max_size_in_bytes
250
+ @response[:error] ||= "Some files were not uploaded"
251
+ @response[:errorData][@options[:original_filename_method].call(file)] = 'File exceeds the maximum allowed filesize'
252
+ else
253
+ dst = @current + @options[:original_filename_method].call(file)
254
+ the_file.close
255
+ src = the_file.path
256
+ FileUtils.mv(src, dst.fullpath)
257
+ FileUtils.chmod @options[:upload_file_mode], dst
258
+ select << to_hash(dst)
259
+ end
260
+ end
261
+ @response[:select] = select unless select.empty?
262
+ _open(@current)
263
+ end # of upload
264
+
265
+ #
266
+ def _ping
267
+ @headers['Connection'] = 'Close'
268
+ end # of ping
269
+
270
+ #
271
+ def _paste
272
+ if perms_for(from_hash(@params[:dst]))[:write] == false
273
+ @response[:error] = 'Access Denied'
274
+ return
275
+ end
276
+
277
+ @targets.to_a.each do |src|
278
+ if perms_for(src)[:read] == false || (@params[:cut].to_i > 0 && perms_for(src)[:rm] == false)
279
+ @response[:error] ||= 'Some files were not copied.'
280
+ @response[:errorData][src.basename.to_s] = "Access Denied"
281
+ return
282
+ else
283
+ dst = from_hash(@params[:dst]) + src.basename
284
+ if dst.exist?
285
+ @response[:error] ||= 'Some files were unable to be copied'
286
+ @response[:errorData][src.basename.to_s] = "already exists in '#{dst.dirname}'"
287
+ else
288
+ if @params[:cut].to_i > 0
289
+ src.rename(dst)
290
+ else
291
+ if src.directory?
292
+ FileUtils.cp_r(src.fullpath, dst.fullpath)
293
+ else
294
+ FileUtils.cp(src.fullpath, dst.fullpath)
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end
300
+ @params[:tree] = true
301
+ _open(@current)
302
+ end # of paste
303
+
304
+ #
305
+ def _rm
306
+ if @targets.empty?
307
+ @response[:error] = "No files were selected for removal"
308
+ else
309
+ @targets.to_a.each do |target|
310
+ remove_target(target)
311
+ end
312
+ @params[:tree] = true
313
+ _open(@current)
314
+ end
315
+ end # of rm
316
+
317
+ #
318
+ def _duplicate
319
+ if perms_for(@target)[:read] == false
320
+ @response[:error] = 'Access Denied'
321
+ @response[:errorData][@target.basename.to_s] = 'Unable to read'
322
+ return
323
+ end
324
+ if perms_for(@target.dirname)[:write] == false
325
+ @response[:error] = 'Access Denied'
326
+ @response[:errorData][@target.dirname.to_s] = 'Unable to write'
327
+ return
328
+ end
329
+
330
+ duplicate = @target.duplicate
331
+ if @target.directory?
332
+ FileUtils.cp_r(@target, duplicate.fullpath)
333
+ else
334
+ FileUtils.copy(@target, duplicate.fullpath)
335
+ end
336
+ @response[:select] = [to_hash(duplicate)]
337
+ _open(@current)
338
+ end # of duplicate
339
+
340
+ #
341
+ def _read
342
+ if perms_for(@target)[:read] == true
343
+ @response[:content] = @target.read
344
+ else
345
+ @response[:error] = 'Access Denied'
346
+ end
347
+ end # of read
348
+
349
+ #
350
+ def _edit
351
+ perms = perms_for(@target)
352
+ if perms[:read] == true && perms[:write] == true
353
+ @target.open('w') { |f| f.write @params[:content] }
354
+ @response[:file] = cdc_for(@target)
355
+ else
356
+ @response[:error] = 'Access Denied'
357
+ end
358
+ end # of edit
359
+
360
+ #
361
+ def _extract
362
+ @response[:error] = 'Invalid Parameters' and return if @target.nil? || @current.nil? || !(@target.file? && @current.directory?)
363
+ @response[:error] = 'Access Denied' and return unless perms_for(@target)[:read] == true && perms_for(@current)[:write] == true
364
+ @response[:error] = 'No extractor available for this file type' and return if (extractor = @options[:extractors][mime_handler.for(@target)]).nil?
365
+ cmd = ['cd', @current.to_s.shellescape, '&&', extractor.map(&:shellescape), @target.basename.to_s.shellescape].flatten.join(' ')
366
+ if system(cmd)
367
+ @params[:tree] = true
368
+ _open(@current)
369
+ else
370
+ @response[:error] = 'Unable to extract files from archive'
371
+ end
372
+ end # of extract
373
+
374
+ #
375
+ def _archive
376
+ @response[:error] = 'Invalid Parameters' and return unless !@targets.nil? && @targets.all?{|e| e && e.exist?} && @current && @current.directory?
377
+ @response[:error] = 'Access Denied' and return unless !@targets.nil? && @targets.all?{|e| perms_for(e)[:read]} && perms_for(@current)[:write] == true
378
+ @response[:error] = 'No archiver available for this file type' and return if (archiver = @options[:archivers][@params[:type]]).nil?
379
+ extension = archiver.shift
380
+ basename = @params[:name] || @targets.first.basename_sans_extension
381
+ archive = (@root + "#{basename}#{extension}").unique
382
+ cmd = ['cd', @current.to_s.shellescape, '&&', archiver.map(&:shellescape), archive.to_s.shellescape, @targets.map{|t| t.basename.to_s.shellescape}].flatten.join(' ')
383
+ if system(cmd)
384
+ @response[:select] = [to_hash(archive)]
385
+ _open(@current)
386
+ else
387
+ @response[:error] = 'Unable to create archive'
388
+ end
389
+ end # of archive
390
+
391
+ #
392
+ def _tmb
393
+ if image_handler.nil?
394
+ command_not_implemented
395
+ else
396
+ @response[:current] = to_hash(@current)
397
+ @response[:images] = {}
398
+ idx = 0
399
+ @current.children.select{|e| mime_handler.for(e) =~ /image/}.each do |img|
400
+ if idx >= @options[:thumbs_at_once]
401
+ @response[:tmb] = true
402
+ break
403
+ end
404
+ thumbnail = thumbnail_for(img)
405
+ unless thumbnail.file?
406
+ mime = mime_handler.for(img)
407
+
408
+ # For animated Gifs (mime-type 'image/gif'), it doesn't create "#{thumbnail}" file, but it creates a series of "#{thumbnail}-x" files, depending
409
+ # on how many frames that src-gif contains
410
+ # same thing applies for photoshop files ('image/vnd.adobe.photoshop')
411
+ # So you need to add [0] to the src to get the first frame.
412
+ has_frames = true if ["image/gif", "image/vnd.adobe.photoshop"].include?(mime)
413
+ image_handler.thumbnail(img, thumbnail, :width => @options[:thumbs_size].to_i, :height => @options[:thumbs_size].to_i, has_frames: has_frames)
414
+
415
+ #Just-in-Case, if the file is not created don't send it
416
+ if thumbnail.file?
417
+ @response[:images][to_hash(img)] = @options[:url] + '/' + thumbnail.path.to_s
418
+ idx += 1
419
+ end
420
+ end
421
+ end
422
+ end
423
+
424
+ end # of tmb
425
+
426
+ #
427
+ def _resize
428
+ if image_handler.nil?
429
+ command_not_implemented
430
+ else
431
+ if @target.file?
432
+ perms = perms_for(@target)
433
+ if perms[:read] == true && perms[:write] == true
434
+ image_handler.resize(@target, :width => @params[:width].to_i, :height => @params[:height].to_i)
435
+ @response[:select] = [to_hash(@target)]
436
+ _open(@current)
437
+ else
438
+ @response[:error] = 'Access Denied'
439
+ end
440
+ else
441
+ @response[:error] = "Unable to resize file. It does not exist"
442
+ end
443
+ end
444
+ end # of resize
445
+
446
+ ################################################################################
447
+ private
448
+
449
+ #
450
+ def upload_max_size_in_bytes
451
+ bytes = @options[:upload_max_size]
452
+ if bytes.is_a?(String) && bytes.strip =~ /(\d+)([KMG]?)/
453
+ bytes = $1.to_i
454
+ unit = $2
455
+ case unit
456
+ when 'K'
457
+ bytes *= 1024
458
+ when 'M'
459
+ bytes *= 1024 * 1024
460
+ when 'G'
461
+ bytes *= 1024 * 1024 * 1024
462
+ end
463
+ end
464
+ bytes.to_i
465
+ end
466
+
467
+ #
468
+ def thumbnail_for(pathname)
469
+ @thumb_directory + "#{to_hash(pathname)}.png"
470
+ end
471
+
472
+ #
473
+ def remove_target(target)
474
+ if target.directory?
475
+ target.children.each do |child|
476
+ remove_target(child)
477
+ end
478
+ end
479
+ if perms_for(target)[:rm] == false
480
+ @response[:error] ||= 'Some files/directories were unable to be removed'
481
+ @response[:errorData][target.basename.to_s] = "Access Denied"
482
+ else
483
+ begin
484
+ target.unlink
485
+ if @options[:thumbs] && (thumbnail = thumbnail_for(target)).file?
486
+ thumbnail.unlink
487
+ end
488
+ rescue
489
+ @response[:error] ||= 'Some files/directories were unable to be removed'
490
+ @response[:errorData][target.basename.to_s] = "Remove failed"
491
+ end
492
+ end
493
+ end
494
+
495
+ def mime_handler
496
+ @options[:mime_handler]
497
+ end
498
+
499
+ #
500
+ def image_handler
501
+ @options[:image_handler]
502
+ end
503
+
504
+ #
505
+ def cwd_for(pathname)
506
+ {
507
+ :name => pathname.basename.to_s,
508
+ :hash => to_hash(pathname),
509
+ :mime => 'directory',
510
+ :rel => pathname.is_root? ? @options[:home] : (@options[:home] + '/' + pathname.path.to_s),
511
+ :size => 0,
512
+ :date => pathname.mtime.to_s,
513
+ }.merge(perms_for(pathname))
514
+ end
515
+
516
+ def cdc_for(pathname)
517
+ return nil if @options[:thumbs] && pathname.to_s == @thumb_directory.to_s
518
+ response = {
519
+ :name => pathname.basename.to_s,
520
+ :hash => to_hash(pathname),
521
+ :date => pathname.mtime.to_s,
522
+ }
523
+ response.merge! perms_for(pathname)
524
+
525
+ if pathname.directory?
526
+ response.merge!(
527
+ :size => 0,
528
+ :mime => 'directory'
529
+ )
530
+ elsif pathname.file?
531
+ response.merge!(
532
+ :size => pathname.size,
533
+ :mime => mime_handler.for(pathname),
534
+ :url => (@options[:url] + '/' + pathname.path.to_s)
535
+ )
536
+
537
+ if pathname.readable? && response[:mime] =~ /image/ && !image_handler.nil?
538
+ response.merge!(
539
+ :resize => true,
540
+ :dim => image_handler.size(pathname)
541
+ )
542
+ if @options[:thumbs]
543
+ if (thumbnail = thumbnail_for(pathname)).exist?
544
+ response.merge!( :tmb => (@options[:url] + '/' + thumbnail.path.to_s))
545
+ else
546
+ @response[:tmb] = true
547
+ end
548
+ end
549
+ end
550
+
551
+ end
552
+
553
+ if pathname.symlink?
554
+ response.merge!(
555
+ :link => to_hash(@root + pathname.readlink), # hash of file to which point link
556
+ :linkTo => (@root + pathname.readlink).relative_to(pathname.dirname.path).to_s, # relative path to
557
+ :parent => to_hash((@root + pathname.readlink).dirname) # hash of directory in which is linked file
558
+ )
559
+ end
560
+
561
+ return response
562
+ end
563
+
564
+ #
565
+ def tree_for(root)
566
+ root.child_directories(@options[:tree_sub_folders]).
567
+ reject{ |child|
568
+ ( @options[:thumbs] && child.to_s == @thumb_directory.to_s ) || perms_for(child)[:hidden]
569
+ }.
570
+ sort_by{|e| e.basename.to_s.downcase}.
571
+ map { |child|
572
+ {:name => child.basename.to_s,
573
+ :hash => to_hash(child),
574
+ :dirs => tree_for(child),
575
+ }.merge(perms_for(child))
576
+ }
577
+ end # of tree_for
578
+
579
+ #
580
+ def perms_for(pathname, options = {})
581
+ skip = [options[:skip]].flatten
582
+ response = {}
583
+
584
+ response[:read] = pathname.readable? if pathname.exist?
585
+ response[:read] &&= specific_perm_for(pathname, :read)
586
+ response[:read] &&= @options[:default_perms][:read]
587
+
588
+ response[:write] = pathname.writable? if pathname.exist?
589
+ response[:write] &&= specific_perm_for(pathname, :write)
590
+ response[:write] &&= @options[:default_perms][:write]
591
+
592
+ response[:rm] = !pathname.is_root?
593
+ response[:rm] &&= specific_perm_for(pathname, :rm)
594
+ response[:rm] &&= @options[:default_perms][:rm]
595
+
596
+ response[:hidden] = false
597
+ response[:hidden] ||= specific_perm_for(pathname, :hidden)
598
+ response[:hidden] ||= @options[:default_perms][:hidden]
599
+
600
+ response
601
+ end # of perms_for
602
+
603
+ #
604
+ def specific_perm_for(pathname, perm)
605
+ pathname = pathname.path if pathname.is_a?(ElFinder::Pathname)
606
+ matches = @options[:perms].select{ |k,v| pathname.to_s.send((k.is_a?(String) ? :== : :match), k) }
607
+ if perm == :hidden
608
+ matches.one?{|e| e.last[perm] }
609
+ else
610
+ matches.none?{|e| e.last[perm] == false}
611
+ end
612
+ end # of specific_perm_for
613
+
614
+ #
615
+ def invalid_request
616
+ @response[:error] = "Invalid command '#{@params[:cmd]}'"
617
+ end # of invalid_request
618
+
619
+ #
620
+ def command_not_implemented
621
+ @response[:error] = "Command '#{@params[:cmd]}' not yet implemented"
622
+ end # of command_not_implemented
623
+
624
+ end # of class Connector
625
+ end # of module ElFinder
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'shellwords'
3
+ require 'image_size'
4
+
5
+ module ElFinder
6
+
7
+ # Represents default image handler.
8
+ # It uses *mogrify* to resize images and *convert* to create thumbnails.
9
+ class Image
10
+
11
+ def self.size(pathname)
12
+ return nil unless File.exist?(pathname)
13
+ s = ::ImageSize.path(pathname).size.to_s
14
+ s = nil if s.empty?
15
+ return s
16
+ rescue
17
+ nil
18
+ end
19
+
20
+ def self.resize(pathname, options = {})
21
+ return nil unless File.exist?(pathname)
22
+ system( ::Shellwords.join(['mogrify', '-resize', "#{options[:width]}x#{options[:height]}!", pathname.to_s]) )
23
+ end # of self.resize
24
+
25
+ def self.thumbnail(src, dst, options = {})
26
+ return nil unless File.exist?(src)
27
+ src = "#{src.to_s}[0]" if options[:has_frames]
28
+ system( ::Shellwords.join(['convert', '-resize', "#{options[:width]}x#{options[:height]}", '-background', 'white', '-gravity', 'center', '-extent', "#{options[:width]}x#{options[:height]}", src.to_s, dst.to_s]) )
29
+ end # of self.resize
30
+
31
+ end # of class Image
32
+
33
+ end # of module ElFinder