mini-smart-pkg 0.0.1

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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/carrierwave-3.1.3/README.md +1214 -0
  3. data/carrierwave-3.1.3/lib/carrierwave/compatibility/paperclip.rb +105 -0
  4. data/carrierwave-3.1.3/lib/carrierwave/downloader/base.rb +101 -0
  5. data/carrierwave-3.1.3/lib/carrierwave/downloader/remote_file.rb +68 -0
  6. data/carrierwave-3.1.3/lib/carrierwave/error.rb +8 -0
  7. data/carrierwave-3.1.3/lib/carrierwave/locale/en.yml +17 -0
  8. data/carrierwave-3.1.3/lib/carrierwave/mount.rb +446 -0
  9. data/carrierwave-3.1.3/lib/carrierwave/mounter.rb +257 -0
  10. data/carrierwave-3.1.3/lib/carrierwave/orm/activerecord.rb +68 -0
  11. data/carrierwave-3.1.3/lib/carrierwave/processing/mini_magick.rb +362 -0
  12. data/carrierwave-3.1.3/lib/carrierwave/processing/rmagick.rb +433 -0
  13. data/carrierwave-3.1.3/lib/carrierwave/processing/vips.rb +315 -0
  14. data/carrierwave-3.1.3/lib/carrierwave/processing.rb +3 -0
  15. data/carrierwave-3.1.3/lib/carrierwave/sanitized_file.rb +361 -0
  16. data/carrierwave-3.1.3/lib/carrierwave/storage/abstract.rb +43 -0
  17. data/carrierwave-3.1.3/lib/carrierwave/storage/file.rb +124 -0
  18. data/carrierwave-3.1.3/lib/carrierwave/storage/fog.rb +560 -0
  19. data/carrierwave-3.1.3/lib/carrierwave/storage.rb +3 -0
  20. data/carrierwave-3.1.3/lib/carrierwave/test/matchers.rb +398 -0
  21. data/carrierwave-3.1.3/lib/carrierwave/uploader/cache.rb +223 -0
  22. data/carrierwave-3.1.3/lib/carrierwave/uploader/callbacks.rb +33 -0
  23. data/carrierwave-3.1.3/lib/carrierwave/uploader/configuration.rb +229 -0
  24. data/carrierwave-3.1.3/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
  25. data/carrierwave-3.1.3/lib/carrierwave/uploader/content_type_denylist.rb +65 -0
  26. data/carrierwave-3.1.3/lib/carrierwave/uploader/default_url.rb +17 -0
  27. data/carrierwave-3.1.3/lib/carrierwave/uploader/dimension.rb +66 -0
  28. data/carrierwave-3.1.3/lib/carrierwave/uploader/download.rb +24 -0
  29. data/carrierwave-3.1.3/lib/carrierwave/uploader/extension_allowlist.rb +63 -0
  30. data/carrierwave-3.1.3/lib/carrierwave/uploader/extension_denylist.rb +64 -0
  31. data/carrierwave-3.1.3/lib/carrierwave/uploader/file_size.rb +43 -0
  32. data/carrierwave-3.1.3/lib/carrierwave/uploader/mountable.rb +44 -0
  33. data/carrierwave-3.1.3/lib/carrierwave/uploader/processing.rb +128 -0
  34. data/carrierwave-3.1.3/lib/carrierwave/uploader/proxy.rb +99 -0
  35. data/carrierwave-3.1.3/lib/carrierwave/uploader/remove.rb +21 -0
  36. data/carrierwave-3.1.3/lib/carrierwave/uploader/serialization.rb +28 -0
  37. data/carrierwave-3.1.3/lib/carrierwave/uploader/store.rb +168 -0
  38. data/carrierwave-3.1.3/lib/carrierwave/uploader/url.rb +44 -0
  39. data/carrierwave-3.1.3/lib/carrierwave/uploader/versions.rb +352 -0
  40. data/carrierwave-3.1.3/lib/carrierwave/uploader.rb +69 -0
  41. data/carrierwave-3.1.3/lib/carrierwave/utilities/file_name.rb +47 -0
  42. data/carrierwave-3.1.3/lib/carrierwave/utilities/uri.rb +26 -0
  43. data/carrierwave-3.1.3/lib/carrierwave/utilities.rb +7 -0
  44. data/carrierwave-3.1.3/lib/carrierwave/validations/active_model.rb +76 -0
  45. data/carrierwave-3.1.3/lib/carrierwave/version.rb +3 -0
  46. data/carrierwave-3.1.3/lib/carrierwave.rb +108 -0
  47. data/carrierwave-3.1.3/lib/generators/templates/uploader.rb.erb +56 -0
  48. data/carrierwave-3.1.3/lib/generators/uploader_generator.rb +7 -0
  49. data/mini-smart-pkg.gemspec +12 -0
  50. metadata +89 -0
@@ -0,0 +1,124 @@
1
+ module CarrierWave
2
+ module Storage
3
+
4
+ ##
5
+ # File storage stores file to the Filesystem (surprising, no?). There's really not much
6
+ # to it, it uses the store_dir defined on the uploader as the storage location. That's
7
+ # pretty much it.
8
+ #
9
+ class File < Abstract
10
+ def initialize(*)
11
+ super
12
+ @cache_called = nil
13
+ end
14
+
15
+ ##
16
+ # Move the file to the uploader's store path.
17
+ #
18
+ # By default, store!() uses copy_to(), which operates by copying the file
19
+ # from the cache to the store, then deleting the file from the cache.
20
+ # If move_to_store() is overridden to return true, then store!() uses move_to(),
21
+ # which simply moves the file from cache to store. Useful for large files.
22
+ #
23
+ # === Parameters
24
+ #
25
+ # [file (CarrierWave::SanitizedFile)] the file to store
26
+ #
27
+ # === Returns
28
+ #
29
+ # [CarrierWave::SanitizedFile] a sanitized file
30
+ #
31
+ def store!(file)
32
+ path = ::File.expand_path(uploader.store_path, uploader.root)
33
+ if uploader.move_to_store
34
+ file.move_to(path, uploader.permissions, uploader.directory_permissions)
35
+ else
36
+ file.copy_to(path, uploader.permissions, uploader.directory_permissions)
37
+ end
38
+ end
39
+
40
+ ##
41
+ # Retrieve the file from its store path
42
+ #
43
+ # === Parameters
44
+ #
45
+ # [identifier (String)] the filename of the file
46
+ #
47
+ # === Returns
48
+ #
49
+ # [CarrierWave::SanitizedFile] a sanitized file
50
+ #
51
+ def retrieve!(identifier)
52
+ path = ::File.expand_path(uploader.store_path(identifier), uploader.root)
53
+ CarrierWave::SanitizedFile.new(path)
54
+ end
55
+
56
+ ##
57
+ # Stores given file to cache directory.
58
+ #
59
+ # === Parameters
60
+ #
61
+ # [new_file (File, IOString, Tempfile)] any kind of file object
62
+ #
63
+ # === Returns
64
+ #
65
+ # [CarrierWave::SanitizedFile] a sanitized file
66
+ #
67
+ def cache!(new_file)
68
+ new_file.move_to(::File.expand_path(uploader.cache_path, uploader.root), uploader.permissions, uploader.directory_permissions, true)
69
+ rescue Errno::EMLINK, Errno::ENOSPC => e
70
+ raise(e) if @cache_called
71
+ @cache_called = true
72
+
73
+ # NOTE: Remove cached files older than 10 minutes
74
+ clean_cache!(600)
75
+
76
+ cache!(new_file)
77
+ end
78
+
79
+ ##
80
+ # Retrieves the file with the given cache_name from the cache.
81
+ #
82
+ # === Parameters
83
+ #
84
+ # [cache_name (String)] uniquely identifies a cache file
85
+ #
86
+ # === Raises
87
+ #
88
+ # [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
89
+ #
90
+ def retrieve_from_cache!(identifier)
91
+ CarrierWave::SanitizedFile.new(::File.expand_path(uploader.cache_path(identifier), uploader.root))
92
+ end
93
+
94
+ ##
95
+ # Deletes a cache dir
96
+ #
97
+ def delete_dir!(path)
98
+ if path
99
+ begin
100
+ Dir.rmdir(::File.expand_path(path, uploader.root))
101
+ rescue Errno::ENOENT
102
+ # Ignore: path does not exist
103
+ rescue Errno::ENOTDIR
104
+ # Ignore: path is not a dir
105
+ rescue Errno::ENOTEMPTY, Errno::EEXIST
106
+ # Ignore: dir is not empty
107
+ end
108
+ end
109
+ end
110
+
111
+ def clean_cache!(seconds)
112
+ Dir.glob(::File.expand_path(::File.join(uploader.cache_dir, '*'), uploader.root)).each do |dir|
113
+ # generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
114
+ matched = dir.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first
115
+ next unless matched
116
+ time = Time.at(matched[0].to_i)
117
+ if time < (Time.now.utc - seconds)
118
+ FileUtils.rm_rf(dir)
119
+ end
120
+ end
121
+ end
122
+ end # File
123
+ end # Storage
124
+ end # CarrierWave
@@ -0,0 +1,560 @@
1
+ module CarrierWave
2
+ module Storage
3
+
4
+ ##
5
+ # Stores things using the "fog" gem.
6
+ #
7
+ # fog supports storing files with AWS, Google, Local and Rackspace
8
+ #
9
+ # You need to setup some options to configure your usage:
10
+ #
11
+ # [:fog_credentials] host info and credentials for service
12
+ # [:fog_directory] specifies name of directory to store data in, assumed to already exist
13
+ #
14
+ # [:fog_attributes] (optional) additional attributes to set on files
15
+ # [:fog_public] (optional) public readability, defaults to true
16
+ # [:fog_authenticated_url_expiration] (optional) time (in seconds) that authenticated urls
17
+ # will be valid, when fog_public is false and provider is AWS or Google, defaults to 600
18
+ # [:fog_use_ssl_for_aws] (optional) #public_url will use https for the AWS generated URL]
19
+ # [:fog_aws_accelerate] (optional) #public_url will use s3-accelerate subdomain
20
+ # instead of s3, defaults to false
21
+ # [:fog_aws_fips] (optional) #public_url will use s3-fips subdomain
22
+ # instead of s3, defaults to false
23
+ #
24
+ #
25
+ # AWS credentials contain the following keys:
26
+ #
27
+ # [:aws_access_key_id]
28
+ # [:aws_secret_access_key]
29
+ # [:region] (optional) defaults to 'us-east-1'
30
+ # :region should be one of ['eu-west-1', 'us-east-1', 'ap-southeast-1', 'us-west-1', 'ap-northeast-1', 'eu-central-1']
31
+ #
32
+ #
33
+ # Google credentials contain the following keys:
34
+ # [:google_storage_access_key_id]
35
+ # [:google_storage_secret_access_key]
36
+ #
37
+ #
38
+ # Local credentials contain the following keys:
39
+ #
40
+ # [:local_root] local path to files
41
+ #
42
+ #
43
+ # Rackspace credentials contain the following keys:
44
+ #
45
+ # [:rackspace_username]
46
+ # [:rackspace_api_key]
47
+ #
48
+ #
49
+ # A full example with AWS credentials:
50
+ # CarrierWave.configure do |config|
51
+ # config.fog_credentials = {
52
+ # :aws_access_key_id => 'xxxxxx',
53
+ # :aws_secret_access_key => 'yyyyyy',
54
+ # :provider => 'AWS'
55
+ # }
56
+ # config.fog_directory = 'directoryname'
57
+ # config.fog_public = true
58
+ # end
59
+ #
60
+ class Fog < Abstract
61
+ class << self
62
+ def connection_cache
63
+ @connection_cache ||= {}
64
+ end
65
+
66
+ def eager_load
67
+ # see #1198. This will hopefully no longer be necessary in future release of fog
68
+ fog_credentials = CarrierWave::Uploader::Base.fog_credentials
69
+ if fog_credentials.present?
70
+ CarrierWave::Storage::Fog.connection_cache[fog_credentials] ||= ::Fog::Storage.new(fog_credentials)
71
+ end
72
+ end
73
+ end
74
+
75
+ ##
76
+ # Store a file
77
+ #
78
+ # === Parameters
79
+ #
80
+ # [file (CarrierWave::SanitizedFile)] the file to store
81
+ #
82
+ # === Returns
83
+ #
84
+ # [CarrierWave::Storage::Fog::File] the stored file
85
+ #
86
+ def store!(file)
87
+ f = CarrierWave::Storage::Fog::File.new(uploader, self, uploader.store_path)
88
+ f.store(file)
89
+ f
90
+ end
91
+
92
+ ##
93
+ # Retrieve a file
94
+ #
95
+ # === Parameters
96
+ #
97
+ # [identifier (String)] unique identifier for file
98
+ #
99
+ # === Returns
100
+ #
101
+ # [CarrierWave::Storage::Fog::File] the stored file
102
+ #
103
+ def retrieve!(identifier)
104
+ CarrierWave::Storage::Fog::File.new(uploader, self, uploader.store_path(identifier))
105
+ end
106
+
107
+ ##
108
+ # Stores given file to cache directory.
109
+ #
110
+ # === Parameters
111
+ #
112
+ # [new_file (File, IOString, Tempfile)] any kind of file object
113
+ #
114
+ # === Returns
115
+ #
116
+ # [CarrierWave::SanitizedFile] a sanitized file
117
+ #
118
+ def cache!(new_file)
119
+ f = CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path)
120
+ f.store(new_file)
121
+ f
122
+ end
123
+
124
+ ##
125
+ # Retrieves the file with the given cache_name from the cache.
126
+ #
127
+ # === Parameters
128
+ #
129
+ # [cache_name (String)] uniquely identifies a cache file
130
+ #
131
+ # === Raises
132
+ #
133
+ # [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
134
+ #
135
+ def retrieve_from_cache!(identifier)
136
+ CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path(identifier))
137
+ end
138
+
139
+ ##
140
+ # Deletes a cache dir
141
+ #
142
+ def delete_dir!(path)
143
+ # do nothing, because there's no such things as 'empty directory'
144
+ end
145
+
146
+ def clean_cache!(seconds)
147
+ connection.directories.new(
148
+ :key => uploader.fog_directory,
149
+ :public => uploader.fog_public
150
+ ).files.all(:prefix => uploader.cache_dir).each do |file|
151
+ # generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
152
+ matched = file.key.match(/(\d+)-\d+-\d+(?:-\d+)?/)
153
+ next unless matched
154
+ time = Time.at(matched[1].to_i)
155
+ file.destroy if time < (Time.now.utc - seconds)
156
+ end
157
+ end
158
+
159
+ def connection
160
+ @connection ||= begin
161
+ options = credentials = uploader.fog_credentials
162
+ self.class.connection_cache[credentials] ||= ::Fog::Storage.new(options)
163
+ end
164
+ end
165
+
166
+ class File
167
+ DEFAULT_S3_REGION = 'us-east-1'.freeze
168
+
169
+ include CarrierWave::Utilities::Uri
170
+ include CarrierWave::Utilities::FileName
171
+
172
+ ##
173
+ # Current local path to file
174
+ #
175
+ # === Returns
176
+ #
177
+ # [String] a path to file
178
+ #
179
+ attr_reader :path
180
+
181
+ ##
182
+ # Return all attributes from file
183
+ #
184
+ # === Returns
185
+ #
186
+ # [Hash] attributes from file
187
+ #
188
+ def attributes
189
+ file.attributes
190
+ end
191
+
192
+ ##
193
+ # Return a temporary authenticated url to a private file, if available
194
+ # Only supported for AWS, Rackspace, Google, AzureRM and Aliyun providers
195
+ #
196
+ # === Returns
197
+ #
198
+ # [String] temporary authenticated url
199
+ # or
200
+ # [NilClass] no authenticated url available
201
+ #
202
+ def authenticated_url(options = {})
203
+ if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(fog_provider)
204
+ # avoid a get by using local references
205
+ local_directory = connection.directories.new(:key => @uploader.fog_directory)
206
+ local_file = local_directory.files.new(:key => path)
207
+ expire_at = options[:expire_at] || ::Fog::Time.now.since(@uploader.fog_authenticated_url_expiration.to_i)
208
+ case fog_provider
209
+ when 'AWS', 'Google'
210
+ # Older versions of fog-google do not support options as a parameter
211
+ if url_options_supported?(local_file)
212
+ local_file.url(expire_at, options)
213
+ else
214
+ warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
215
+ local_file.url(expire_at)
216
+ end
217
+ when 'Rackspace', 'OpenStack'
218
+ connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
219
+ when 'Aliyun'
220
+ expire_at -= Time.now
221
+ local_file.url(expire_at)
222
+ else
223
+ local_file.url(expire_at)
224
+ end
225
+ end
226
+ end
227
+
228
+ ##
229
+ # Lookup value for file content-type header
230
+ #
231
+ # === Returns
232
+ #
233
+ # [String] value of content-type
234
+ #
235
+ def content_type
236
+ @content_type || file.try(:content_type)
237
+ end
238
+
239
+ ##
240
+ # Set non-default content-type header (default is file.content_type)
241
+ #
242
+ # === Returns
243
+ #
244
+ # [String] returns new content type value
245
+ #
246
+ def content_type=(new_content_type)
247
+ @content_type = new_content_type
248
+ end
249
+
250
+ ##
251
+ # Remove the file from service
252
+ #
253
+ # === Returns
254
+ #
255
+ # [Boolean] true for success or raises error
256
+ #
257
+ def delete
258
+ # avoid a get by just using local reference
259
+ directory.files.new(:key => path).destroy.tap do |result|
260
+ @file = nil if result
261
+ end
262
+ end
263
+
264
+ ##
265
+ # deprecated: All attributes from file (includes headers)
266
+ #
267
+ # === Returns
268
+ #
269
+ # [Hash] attributes from file
270
+ #
271
+ def headers
272
+ location = caller.first
273
+ warning = "[yellow][WARN] headers is deprecated, use attributes instead[/]"
274
+ warning << " [light_black](#{location})[/]"
275
+ Formatador.display_line(warning)
276
+ attributes
277
+ end
278
+
279
+ def initialize(uploader, base, path)
280
+ @uploader, @base, @path, @content_type = uploader, base, path, nil
281
+ end
282
+
283
+ ##
284
+ # Read content of file from service
285
+ #
286
+ # === Returns
287
+ #
288
+ # [String] contents of file
289
+ def read
290
+ file_body = file&.body
291
+
292
+ return if file_body.nil?
293
+ return file_body unless file_body.is_a?(::File)
294
+
295
+ # Fog::Storage::XXX::File#body could return the source file which was uploaded to the remote server.
296
+ return read_source_file if ::File.exist?(file_body.path)
297
+
298
+ # If the source file doesn't exist, the remote content is read
299
+ @file = nil
300
+ file.body
301
+ end
302
+
303
+ ##
304
+ # Return size of file body
305
+ #
306
+ # === Returns
307
+ #
308
+ # [Integer] size of file body
309
+ #
310
+ def size
311
+ file.nil? ? 0 : file.content_length
312
+ end
313
+
314
+ ##
315
+ # === Returns
316
+ #
317
+ # [Boolean] whether the file is non-existent or empty
318
+ #
319
+ def empty?
320
+ !exists? || size.zero?
321
+ end
322
+
323
+ ##
324
+ # Check if the file exists on the remote service
325
+ #
326
+ # === Returns
327
+ #
328
+ # [Boolean] true if file exists or false
329
+ def exists?
330
+ !!file
331
+ end
332
+
333
+ ##
334
+ # Write file to service
335
+ #
336
+ # === Returns
337
+ #
338
+ # [Boolean] true on success or raises error
339
+ def store(new_file)
340
+ if new_file.is_a?(self.class)
341
+ new_file.copy_to(path)
342
+ else
343
+ fog_file = new_file.to_file
344
+ @content_type ||= new_file.content_type
345
+ @file = directory.files.create({
346
+ :body => fog_file || new_file.read,
347
+ :content_type => @content_type,
348
+ :key => path,
349
+ :public => @uploader.fog_public
350
+ }.merge(@uploader.fog_attributes))
351
+ fog_file.close if fog_file && !fog_file.closed?
352
+ end
353
+ true
354
+ end
355
+
356
+ ##
357
+ # Return a url to a public file, if available
358
+ #
359
+ # === Returns
360
+ #
361
+ # [String] public url
362
+ # or
363
+ # [NilClass] no public url available
364
+ #
365
+ def public_url
366
+ encoded_path = encode_path(path)
367
+ if (host = @uploader.asset_host)
368
+ if host.respond_to? :call
369
+ "#{host.call(self)}/#{encoded_path}"
370
+ else
371
+ "#{host}/#{encoded_path}"
372
+ end
373
+ else
374
+ # AWS/Google optimized for speed over correctness
375
+ case fog_provider
376
+ when 'AWS'
377
+ # check if some endpoint is set in fog_credentials
378
+ if @uploader.fog_credentials.has_key?(:endpoint)
379
+ raise 'fog_aws_fips = true is incompatible with :endpoint, as FIPS endpoints do not support path-style URLs.' if @uploader.fog_aws_fips
380
+ "#{@uploader.fog_credentials[:endpoint]}/#{@uploader.fog_directory}/#{encoded_path}"
381
+ else
382
+ protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
383
+
384
+ subdomain_regex = /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
385
+ # To use the virtual-hosted style, the bucket name needs to be representable as a subdomain
386
+ use_virtual_hosted_style = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
387
+
388
+ region = @uploader.fog_credentials[:region].to_s
389
+ regional_host = 's3.amazonaws.com' # used for DEFAULT_S3_REGION or no region set
390
+ if @uploader.fog_aws_fips
391
+ regional_host = "s3-fips.#{region}.amazonaws.com" # https://aws.amazon.com/compliance/fips/
392
+ elsif ![DEFAULT_S3_REGION, ''].include?(region)
393
+ regional_host = "s3.#{region}.amazonaws.com"
394
+ end
395
+
396
+ if use_virtual_hosted_style
397
+ regional_host = 's3-accelerate.amazonaws.com' if @uploader.fog_aws_accelerate
398
+ "#{protocol}://#{@uploader.fog_directory}.#{regional_host}/#{encoded_path}"
399
+ else # directory is not a valid subdomain, so use path style for access
400
+ raise 'FIPS Endpoints can only be used with Virtual Hosted-Style addressing.' if @uploader.fog_aws_fips
401
+ "#{protocol}://#{regional_host}/#{@uploader.fog_directory}/#{encoded_path}"
402
+ end
403
+ end
404
+ when 'Google'
405
+ # https://cloud.google.com/storage/docs/access-public-data
406
+ "https://storage.googleapis.com/#{@uploader.fog_directory}/#{encoded_path}"
407
+ else
408
+ # avoid a get by just using local reference
409
+ directory.files.new(:key => path).public_url
410
+ end
411
+ end
412
+ end
413
+
414
+ ##
415
+ # Return url to file, if available
416
+ #
417
+ # === Returns
418
+ #
419
+ # [String] url
420
+ # or
421
+ # [NilClass] no url available
422
+ #
423
+ def url(options = {})
424
+ if !@uploader.fog_public
425
+ authenticated_url(options)
426
+ else
427
+ public_url
428
+ end
429
+ end
430
+
431
+ ##
432
+ # Return file name, if available
433
+ #
434
+ # === Returns
435
+ #
436
+ # [String] file name
437
+ # or
438
+ # [NilClass] no file name available
439
+ #
440
+ def filename(options = {})
441
+ return unless (file_url = url(options))
442
+ CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
443
+ end
444
+
445
+ ##
446
+ # Creates a copy of this file and returns it.
447
+ #
448
+ # === Parameters
449
+ #
450
+ # [new_path (String)] The path where the file should be copied to.
451
+ #
452
+ # === Returns
453
+ #
454
+ # @return [CarrierWave::Storage::Fog::File] the location where the file will be stored.
455
+ #
456
+ def copy_to(new_path)
457
+ file.copy(@uploader.fog_directory, new_path, copy_options)
458
+ CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
459
+ end
460
+
461
+ ##
462
+ # Return the local file
463
+ #
464
+ # === Returns
465
+ #
466
+ # [File] The local file as Ruby's File class
467
+ # or
468
+ # [NilClass] When there's no file, or the file is remotely stored
469
+ #
470
+ def to_file
471
+ return nil unless file.body.is_a? ::File
472
+
473
+ if file.body.closed?
474
+ ::File.open(file.body.path) # Reopen if it's already closed
475
+ else
476
+ file.body
477
+ end
478
+ end
479
+
480
+ private
481
+
482
+ ##
483
+ # connection to service
484
+ #
485
+ # === Returns
486
+ #
487
+ # [Fog::#{provider}::Storage] connection to service
488
+ #
489
+ def connection
490
+ @base.connection
491
+ end
492
+
493
+ ##
494
+ # local reference to directory containing file
495
+ #
496
+ # === Returns
497
+ #
498
+ # [Fog::#{provider}::Directory] containing directory
499
+ #
500
+ def directory
501
+ @directory ||= connection.directories.new(
502
+ :key => @uploader.fog_directory,
503
+ :public => @uploader.fog_public
504
+ )
505
+ end
506
+
507
+ ##
508
+ # lookup file
509
+ #
510
+ # === Returns
511
+ #
512
+ # [Fog::#{provider}::File] file data from remote service
513
+ #
514
+ def file
515
+ @file ||= directory.files.head(path)
516
+ end
517
+
518
+ def copy_options
519
+ options = {}
520
+ options.merge!(acl_header) if acl_header.present?
521
+ options[fog_provider == "Google" ? :content_type : 'Content-Type'] ||= content_type if content_type
522
+ options.merge(@uploader.fog_attributes)
523
+ end
524
+
525
+ def acl_header
526
+ case fog_provider
527
+ when 'AWS'
528
+ { 'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private' }
529
+ when "Google"
530
+ @uploader.fog_public ? { destination_predefined_acl: "publicRead" } : {}
531
+ else
532
+ {}
533
+ end
534
+ end
535
+
536
+ def fog_provider
537
+ @uploader.fog_credentials[:provider].to_s
538
+ end
539
+
540
+ def read_source_file
541
+ source_file = to_file
542
+ return unless source_file
543
+
544
+ begin
545
+ source_file.read
546
+ ensure
547
+ source_file.close
548
+ end
549
+ end
550
+
551
+ def url_options_supported?(local_file)
552
+ parameters = local_file.method(:url).parameters
553
+ parameters.count == 2 && parameters[1].include?(:options)
554
+ end
555
+ end
556
+
557
+ end # Fog
558
+
559
+ end # Storage
560
+ end # CarrierWave
@@ -0,0 +1,3 @@
1
+ require "carrierwave/storage/abstract"
2
+ require "carrierwave/storage/file"
3
+ require "carrierwave/storage/fog"