el_finder_s3 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,30 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'shellwords'
|
3
|
+
require 'image_size'
|
4
|
+
|
5
|
+
module ElFinderS3
|
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.new(File.open(pathname)).size.to_s
|
14
|
+
s = nil if s.empty?
|
15
|
+
return s
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.resize(pathname, options = {})
|
19
|
+
return nil unless File.exist?(pathname)
|
20
|
+
system( ::Shellwords.join(['mogrify', '-resize', "#{options[:width]}x#{options[:height]}!", pathname.to_s]) )
|
21
|
+
end # of self.resize
|
22
|
+
|
23
|
+
def self.thumbnail(src, dst, options = {})
|
24
|
+
return nil unless File.exist?(src)
|
25
|
+
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]) )
|
26
|
+
end # of self.resize
|
27
|
+
|
28
|
+
end # of class Image
|
29
|
+
|
30
|
+
end # of module ElFinderS3
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module ElFinderS3
|
2
|
+
|
3
|
+
# Represents default MIME types recognizer.
|
4
|
+
class MimeType
|
5
|
+
|
6
|
+
# File extension to mime type mapping.
|
7
|
+
TYPES = {
|
8
|
+
'ai' => 'application/postscript',
|
9
|
+
'eps' => 'application/postscript',
|
10
|
+
'exe' => 'application/octet-stream',
|
11
|
+
'doc' => 'application/vnd.ms-word',
|
12
|
+
'xls' => 'application/vnd.ms-excel',
|
13
|
+
'ppt' => 'application/vnd.ms-powerpoint',
|
14
|
+
'pps' => 'application/vnd.ms-powerpoint',
|
15
|
+
'pdf' => 'application/pdf',
|
16
|
+
'xml' => 'application/xml',
|
17
|
+
'odt' => 'application/vnd.oasis.opendocument.text',
|
18
|
+
'swf' => 'application/x-shockwave-flash',
|
19
|
+
# archives
|
20
|
+
'gz' => 'application/x-gzip',
|
21
|
+
'tgz' => 'application/x-gzip',
|
22
|
+
'bz' => 'application/x-bzip2',
|
23
|
+
'bz2' => 'application/x-bzip2',
|
24
|
+
'tbz' => 'application/x-bzip2',
|
25
|
+
'zip' => 'application/zip',
|
26
|
+
'rar' => 'application/x-rar',
|
27
|
+
'tar' => 'application/x-tar',
|
28
|
+
'7z' => 'application/x-7z-compressed',
|
29
|
+
# texts
|
30
|
+
'txt' => 'text/plain',
|
31
|
+
'php' => 'text/x-php',
|
32
|
+
'html' => 'text/html',
|
33
|
+
'htm' => 'text/html',
|
34
|
+
'js' => 'text/javascript',
|
35
|
+
'css' => 'text/css',
|
36
|
+
'rtf' => 'text/rtf',
|
37
|
+
'rtfd' => 'text/rtfd',
|
38
|
+
'py' => 'text/x-python',
|
39
|
+
'java' => 'text/x-java-source',
|
40
|
+
'rb' => 'text/x-ruby',
|
41
|
+
'sh' => 'text/x-shellscript',
|
42
|
+
'pl' => 'text/x-perl',
|
43
|
+
'sql' => 'text/x-sql',
|
44
|
+
# images
|
45
|
+
'bmp' => 'image/x-ms-bmp',
|
46
|
+
'jpg' => 'image/jpeg',
|
47
|
+
'jpeg' => 'image/jpeg',
|
48
|
+
'gif' => 'image/gif',
|
49
|
+
'png' => 'image/png',
|
50
|
+
'tif' => 'image/tiff',
|
51
|
+
'tiff' => 'image/tiff',
|
52
|
+
'tga' => 'image/x-targa',
|
53
|
+
'psd' => 'image/vnd.adobe.photoshop',
|
54
|
+
# audio
|
55
|
+
'mp3' => 'audio/mpeg',
|
56
|
+
'mid' => 'audio/midi',
|
57
|
+
'ogg' => 'audio/ogg',
|
58
|
+
'mp4a' => 'audio/mp4',
|
59
|
+
'wav' => 'audio/wav',
|
60
|
+
'wma' => 'audio/x-ms-wma',
|
61
|
+
# video
|
62
|
+
'avi' => 'video/x-msvideo',
|
63
|
+
'dv' => 'video/x-dv',
|
64
|
+
'mp4' => 'video/mp4',
|
65
|
+
'mpeg' => 'video/mpeg',
|
66
|
+
'mpg' => 'video/mpeg',
|
67
|
+
'mov' => 'video/quicktime',
|
68
|
+
'wm' => 'video/x-ms-wmv',
|
69
|
+
'flv' => 'video/x-flv',
|
70
|
+
'mkv' => 'video/x-matroska'
|
71
|
+
}
|
72
|
+
|
73
|
+
# Gets MIME type fort specified path.
|
74
|
+
# @param [::Pathname, String] pathname Path to recognize its MIME type.
|
75
|
+
# @return [String] MIME type if known; 'unknown/unknown' otherwise.
|
76
|
+
def self.for(pathname)
|
77
|
+
pathname = ::Pathname.new(pathname) if pathname.is_a?(String)
|
78
|
+
TYPES[pathname.extname.downcase[1..-1]] || 'application/octet-stream'
|
79
|
+
end # of for
|
80
|
+
|
81
|
+
end # of class MimeType
|
82
|
+
|
83
|
+
end # of module ElFinderS3
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module ElFinderS3
|
5
|
+
|
6
|
+
class Pathname
|
7
|
+
attr_reader :root, :path, :adapter
|
8
|
+
|
9
|
+
#
|
10
|
+
def initialize(adapter_or_root, path = '.')
|
11
|
+
@adapter = adapter_or_root.is_a?(ElFinderS3::Pathname) ? adapter_or_root.adapter : adapter_or_root
|
12
|
+
|
13
|
+
@root = path.is_a?(ElFinderS3::Pathname) ? path.root : S3Pathname.new(@adapter, '/')
|
14
|
+
|
15
|
+
if path.is_a?(ElFinderS3::Pathname)
|
16
|
+
@path = path.path
|
17
|
+
elsif path.is_a?(ElFinderS3::S3Pathname)
|
18
|
+
@path = path
|
19
|
+
else
|
20
|
+
@path = S3Pathname.new(@adapter, path)
|
21
|
+
end
|
22
|
+
if absolute?
|
23
|
+
if @path.cleanpath.to_s.start_with?(@root.to_s)
|
24
|
+
@path = S3Pathname.new(@adapter, @path.to_s.slice((@root.to_s.length)..-1), @path.attrs)
|
25
|
+
elsif @path.cleanpath.to_s.start_with?(@root.realpath.to_s)
|
26
|
+
@path = S3Pathname.new(@adapter, @path.to_s.slice((@root.realpath.to_s.length)..-1), @path.attrs)
|
27
|
+
else
|
28
|
+
raise SecurityError, "Absolute paths are not allowed"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
raise SecurityError, "Paths outside the root are not allowed" if outside_of_root?
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# of initialize
|
36
|
+
|
37
|
+
def type(type)
|
38
|
+
@type = type
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
def +(other)
|
43
|
+
if other.is_a? ::ElFinderS3::Pathname
|
44
|
+
other = other.path
|
45
|
+
end
|
46
|
+
self.class.new(@adapter, @path + other)
|
47
|
+
end
|
48
|
+
|
49
|
+
# of +
|
50
|
+
|
51
|
+
#
|
52
|
+
def is_root?
|
53
|
+
@path.to_s == '.'
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
def absolute?
|
58
|
+
@path.absolute?
|
59
|
+
end
|
60
|
+
|
61
|
+
# of absolute?
|
62
|
+
|
63
|
+
#
|
64
|
+
def relative?
|
65
|
+
@path.relative?
|
66
|
+
end
|
67
|
+
|
68
|
+
# of relative?
|
69
|
+
|
70
|
+
#
|
71
|
+
def outside_of_root?
|
72
|
+
!cleanpath.to_s.start_with?(@root.to_s)
|
73
|
+
end
|
74
|
+
|
75
|
+
# of outside_of_root?
|
76
|
+
|
77
|
+
#
|
78
|
+
def fullpath
|
79
|
+
@fullpath ||= (@path.nil? ? @root : @root + @path)
|
80
|
+
b = @path.nil? ? @root : @root + @path
|
81
|
+
return @fullpath
|
82
|
+
end
|
83
|
+
|
84
|
+
# of fullpath
|
85
|
+
|
86
|
+
#
|
87
|
+
def cleanpath
|
88
|
+
fullpath.cleanpath
|
89
|
+
end
|
90
|
+
|
91
|
+
# of cleanpath
|
92
|
+
|
93
|
+
#
|
94
|
+
def realpath
|
95
|
+
fullpath.realpath
|
96
|
+
end
|
97
|
+
|
98
|
+
# of realpath
|
99
|
+
|
100
|
+
#
|
101
|
+
def basename(*args)
|
102
|
+
@path.basename(*args)
|
103
|
+
end
|
104
|
+
|
105
|
+
# of basename
|
106
|
+
|
107
|
+
#
|
108
|
+
def basename_sans_extension
|
109
|
+
@path.basename(@path.extname)
|
110
|
+
end
|
111
|
+
|
112
|
+
# of basename
|
113
|
+
|
114
|
+
#
|
115
|
+
def basename(*args)
|
116
|
+
@path.basename(*args)
|
117
|
+
end
|
118
|
+
|
119
|
+
# of basename
|
120
|
+
|
121
|
+
#
|
122
|
+
def dirname
|
123
|
+
self.class.new(@adapter, @path.dirname)
|
124
|
+
end
|
125
|
+
|
126
|
+
# of basename
|
127
|
+
|
128
|
+
#
|
129
|
+
def extname
|
130
|
+
@path.nil? ? '' : @path.extname
|
131
|
+
end
|
132
|
+
|
133
|
+
# of extname
|
134
|
+
|
135
|
+
#
|
136
|
+
def to_s
|
137
|
+
cleanpath.to_s
|
138
|
+
end
|
139
|
+
|
140
|
+
def to_prefix_s
|
141
|
+
prefix_s = cleanpath.to_s
|
142
|
+
if prefix_s == '/'
|
143
|
+
return ''
|
144
|
+
elsif prefix_s[0] == '/'
|
145
|
+
prefix_s[0] = ''
|
146
|
+
end
|
147
|
+
|
148
|
+
if prefix_s[prefix_s.size-1] != '/'
|
149
|
+
prefix_s = prefix_s + '/'
|
150
|
+
end
|
151
|
+
return prefix_s
|
152
|
+
end
|
153
|
+
|
154
|
+
# of to_s
|
155
|
+
alias_method :to_str, :to_s
|
156
|
+
|
157
|
+
#
|
158
|
+
def child_directories(with_directory=true)
|
159
|
+
adapter.children(self, with_directory).select { |child| child.directory? }.map { |e| self.class.new(@adapter, e) }
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
def files(with_directory=true)
|
164
|
+
adapter.children(self, with_directory).select { |child| child.file? }.map { |e| self.class.new(@adapter, e) }
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
#
|
169
|
+
def children(with_directory=true)
|
170
|
+
adapter.children(self, with_directory).map { |e| self.class.new(@adapter, e) }
|
171
|
+
end
|
172
|
+
|
173
|
+
#
|
174
|
+
def touch(options = {})
|
175
|
+
adapter.touch(cleanpath, options)
|
176
|
+
end
|
177
|
+
|
178
|
+
#
|
179
|
+
def relative_to(other)
|
180
|
+
@path.relative_path_from(other)
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
def unique
|
185
|
+
return self.dup unless fullpath.file?
|
186
|
+
copy = 1
|
187
|
+
begin
|
188
|
+
new_file = self.class.new(@adapter, dirname + "#{basename_sans_extension} #{copy}#{extname}")
|
189
|
+
copy += 1
|
190
|
+
end while new_file.exist?
|
191
|
+
new_file
|
192
|
+
end
|
193
|
+
|
194
|
+
# of unique
|
195
|
+
|
196
|
+
#
|
197
|
+
def duplicate
|
198
|
+
_basename = basename_sans_extension
|
199
|
+
copy = 1
|
200
|
+
if _basename.to_s =~ /^(.*) copy (\d+)$/
|
201
|
+
_basename = $1
|
202
|
+
copy = $2.to_i
|
203
|
+
end
|
204
|
+
begin
|
205
|
+
new_file = self.class.new(@adapter, dirname + "#{_basename} copy #{copy}#{extname}")
|
206
|
+
copy += 1
|
207
|
+
end while new_file.exist?
|
208
|
+
new_file
|
209
|
+
end
|
210
|
+
|
211
|
+
# of duplicate
|
212
|
+
|
213
|
+
#
|
214
|
+
def rename(to)
|
215
|
+
to = self.class.new(@adapter, to)
|
216
|
+
realpath.rename(to.fullpath.to_s)
|
217
|
+
to
|
218
|
+
end
|
219
|
+
|
220
|
+
# of rename
|
221
|
+
|
222
|
+
{
|
223
|
+
'directory?' => {:path => 'realpath', :rescue => true},
|
224
|
+
'exist?' => {:path => 'realpath', :rescue => true},
|
225
|
+
'file?' => {:path => 'realpath', :rescue => true},
|
226
|
+
'ftype' => {:path => 'realpath', },
|
227
|
+
'mkdir' => {:path => 'fullpath', :args => '(*args)'},
|
228
|
+
'mtime' => {:path => 'realpath', },
|
229
|
+
'open' => {:path => 'fullpath', :args => '(*args, &block)'},
|
230
|
+
'read' => {:path => 'fullpath', :args => '(*args)'},
|
231
|
+
'write' => {:path => 'fullpath', :args => '(*args)'},
|
232
|
+
'readlink' => {:path => 'fullpath', },
|
233
|
+
'readable?' => {:path => 'realpath', :rescue => true},
|
234
|
+
'size' => {:path => 'realpath', },
|
235
|
+
'symlink?' => {:path => 'fullpath', },
|
236
|
+
'unlink' => {:path => 'realpath', },
|
237
|
+
'writable?' => {:path => 'realpath', :rescue => true},
|
238
|
+
}.each_pair do |meth, opts|
|
239
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
240
|
+
def #{meth}#{opts[:args]}
|
241
|
+
#{opts[:path]}.#{meth}#{opts[:args]}
|
242
|
+
#{"rescue Errno::ENOENT\nfalse" if opts[:rescue]}
|
243
|
+
end
|
244
|
+
METHOD
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
end # of class Pathname
|
249
|
+
|
250
|
+
end # of module ElFinderS3
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
module ElFinderS3
|
4
|
+
class S3Connector
|
5
|
+
:s3_client
|
6
|
+
:bucket_name
|
7
|
+
|
8
|
+
def initialize(server)
|
9
|
+
Aws.config.update(
|
10
|
+
{
|
11
|
+
region: server[:region],
|
12
|
+
credentials: Aws::Credentials.new(server[:access_key_id], server[:secret_access_key])
|
13
|
+
}
|
14
|
+
)
|
15
|
+
@bucket_name = server[:bucket_name]
|
16
|
+
@s3_client = Aws::S3::Client.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [ElFinderS3::Pathname] pathname
|
20
|
+
def ls_la(pathname, with_directory)
|
21
|
+
prefix = pathname.to_prefix_s
|
22
|
+
query = {
|
23
|
+
bucket: @bucket_name,
|
24
|
+
delimiter: '/',
|
25
|
+
encoding_type: 'url',
|
26
|
+
max_keys: 100,
|
27
|
+
prefix: prefix
|
28
|
+
}
|
29
|
+
|
30
|
+
response = @s3_client.list_objects(query)
|
31
|
+
result = []
|
32
|
+
#Files
|
33
|
+
response.contents.each { |e|
|
34
|
+
if e.key != prefix
|
35
|
+
e.key = e.key.gsub(prefix, '')
|
36
|
+
if with_directory
|
37
|
+
result.push(pathname.fullpath + ::ElFinderS3::S3Pathname.new(self, e))
|
38
|
+
else
|
39
|
+
result.push(::ElFinderS3::S3Pathname.new(self, e))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
}
|
43
|
+
#Folders
|
44
|
+
response.common_prefixes.each { |f|
|
45
|
+
if f.prefix != '' && f.prefix != prefix && f.prefix != '/'
|
46
|
+
f.prefix = f.prefix.split('/').last
|
47
|
+
result.push(pathname.fullpath + ::ElFinderS3::S3Pathname.new(self, f))
|
48
|
+
end
|
49
|
+
}
|
50
|
+
return result
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [ElFinderS3::Pathname] pathname
|
54
|
+
def exist?(pathname)
|
55
|
+
query = {
|
56
|
+
bucket: @bucket_name,
|
57
|
+
key: pathname.to_prefix_s
|
58
|
+
}
|
59
|
+
begin
|
60
|
+
@s3_client.head_object(query)
|
61
|
+
true
|
62
|
+
rescue Aws::S3::Errors::NotFound
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def mkdir(folder_name)
|
68
|
+
begin
|
69
|
+
@s3_client.put_object(bucket: @bucket_name, key: folder_name)
|
70
|
+
true
|
71
|
+
rescue
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def touch(filename)
|
77
|
+
begin
|
78
|
+
@s3_client.put_object(bucket: @bucket_name, key: filename)
|
79
|
+
true
|
80
|
+
rescue
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def store(filename, content)
|
86
|
+
@s3_client.put_object(bucket: @bucket_name, key: filename, body: content, acl: 'public-read')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|