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.
@@ -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,7 @@
1
+ module ElFinderS3
2
+ class Railties < ::Rails::Railtie
3
+ initializer 'Rails logger' do
4
+ ElFinderS3::Connector.logger = Rails.logger
5
+ end
6
+ end
7
+ end
@@ -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