carrierwave 2.2.6 → 3.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +180 -62
  3. data/lib/carrierwave/compatibility/paperclip.rb +4 -2
  4. data/lib/carrierwave/downloader/base.rb +20 -12
  5. data/lib/carrierwave/downloader/remote_file.rb +13 -10
  6. data/lib/carrierwave/locale/en.yml +5 -3
  7. data/lib/carrierwave/mount.rb +36 -50
  8. data/lib/carrierwave/mounter.rb +118 -50
  9. data/lib/carrierwave/orm/activerecord.rb +21 -62
  10. data/lib/carrierwave/processing/mini_magick.rb +45 -14
  11. data/lib/carrierwave/processing/rmagick.rb +47 -20
  12. data/lib/carrierwave/processing/vips.rb +43 -12
  13. data/lib/carrierwave/sanitized_file.rb +58 -77
  14. data/lib/carrierwave/storage/abstract.rb +5 -5
  15. data/lib/carrierwave/storage/file.rb +6 -5
  16. data/lib/carrierwave/storage/fog.rb +86 -65
  17. data/lib/carrierwave/test/matchers.rb +11 -7
  18. data/lib/carrierwave/uploader/cache.rb +19 -11
  19. data/lib/carrierwave/uploader/callbacks.rb +1 -1
  20. data/lib/carrierwave/uploader/configuration.rb +18 -8
  21. data/lib/carrierwave/uploader/{content_type_whitelist.rb → content_type_allowlist.rb} +17 -15
  22. data/lib/carrierwave/uploader/{content_type_blacklist.rb → content_type_denylist.rb} +20 -15
  23. data/lib/carrierwave/uploader/dimension.rb +66 -0
  24. data/lib/carrierwave/uploader/{extension_whitelist.rb → extension_allowlist.rb} +17 -15
  25. data/lib/carrierwave/uploader/{extension_blacklist.rb → extension_denylist.rb} +19 -14
  26. data/lib/carrierwave/uploader/file_size.rb +2 -2
  27. data/lib/carrierwave/uploader/processing.rb +34 -6
  28. data/lib/carrierwave/uploader/proxy.rb +16 -3
  29. data/lib/carrierwave/uploader/store.rb +70 -6
  30. data/lib/carrierwave/uploader/url.rb +1 -1
  31. data/lib/carrierwave/uploader/versions.rb +158 -138
  32. data/lib/carrierwave/uploader.rb +10 -8
  33. data/lib/carrierwave/utilities/file_name.rb +47 -0
  34. data/lib/carrierwave/utilities/uri.rb +14 -11
  35. data/lib/carrierwave/utilities.rb +1 -0
  36. data/lib/carrierwave/validations/active_model.rb +4 -6
  37. data/lib/carrierwave/version.rb +1 -1
  38. data/lib/carrierwave.rb +18 -17
  39. data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +1 -1
  40. data/lib/generators/uploader_generator.rb +3 -3
  41. metadata +33 -59
@@ -18,6 +18,8 @@ module CarrierWave
18
18
  # [:fog_use_ssl_for_aws] (optional) #public_url will use https for the AWS generated URL]
19
19
  # [:fog_aws_accelerate] (optional) #public_url will use s3-accelerate subdomain
20
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
21
23
  #
22
24
  #
23
25
  # AWS credentials contain the following keys:
@@ -146,7 +148,7 @@ module CarrierWave
146
148
  :key => uploader.fog_directory,
147
149
  :public => uploader.fog_public
148
150
  ).files.all(:prefix => uploader.cache_dir).each do |file|
149
- # generate_cache_id returns key formated TIMEINT-PID(-COUNTER)-RND
151
+ # generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
150
152
  matched = file.key.match(/(\d+)-\d+-\d+(?:-\d+)?/)
151
153
  next unless matched
152
154
  time = Time.at(matched[1].to_i)
@@ -162,9 +164,10 @@ module CarrierWave
162
164
  end
163
165
 
164
166
  class File
165
- DEFAULT_S3_REGION = 'us-east-1'
167
+ DEFAULT_S3_REGION = 'us-east-1'.freeze
166
168
 
167
169
  include CarrierWave::Utilities::Uri
170
+ include CarrierWave::Utilities::FileName
168
171
 
169
172
  ##
170
173
  # Current local path to file
@@ -197,27 +200,27 @@ module CarrierWave
197
200
  # [NilClass] no authenticated url available
198
201
  #
199
202
  def authenticated_url(options = {})
200
- if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(@uploader.fog_credentials[:provider])
203
+ if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(fog_provider)
201
204
  # avoid a get by using local references
202
205
  local_directory = connection.directories.new(:key => @uploader.fog_directory)
203
206
  local_file = local_directory.files.new(:key => path)
204
207
  expire_at = options[:expire_at] || ::Fog::Time.now.since(@uploader.fog_authenticated_url_expiration.to_i)
205
- case @uploader.fog_credentials[:provider]
206
- when 'AWS', 'Google'
207
- # Older versions of fog-google do not support options as a parameter
208
- if url_options_supported?(local_file)
209
- local_file.url(expire_at, options)
210
- else
211
- warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
212
- local_file.url(expire_at)
213
- end
214
- when 'Rackspace', 'OpenStack'
215
- connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
216
- when 'Aliyun'
217
- expire_at = expire_at - Time.now
218
- local_file.url(expire_at)
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)
219
213
  else
214
+ warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
220
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)
221
224
  end
222
225
  end
223
226
  end
@@ -258,18 +261,6 @@ module CarrierWave
258
261
  end
259
262
  end
260
263
 
261
- ##
262
- # Return extension of file
263
- #
264
- # === Returns
265
- #
266
- # [String] extension of file or nil if the file has no extension
267
- #
268
- def extension
269
- path_elements = path.split('.')
270
- path_elements.last if path_elements.size > 1
271
- end
272
-
273
264
  ##
274
265
  # deprecated: All attributes from file (includes headers)
275
266
  #
@@ -296,16 +287,16 @@ module CarrierWave
296
287
  #
297
288
  # [String] contents of file
298
289
  def read
299
- file_body = file.body
290
+ file_body = file&.body
300
291
 
301
292
  return if file_body.nil?
302
293
  return file_body unless file_body.is_a?(::File)
303
294
 
304
- # Fog::Storage::XXX::File#body could return the source file which was upoloaded to the remote server.
305
- read_source_file(file_body) if ::File.exist?(file_body.path)
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)
306
297
 
307
298
  # If the source file doesn't exist, the remote content is read
308
- @file = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
299
+ @file = nil
309
300
  file.body
310
301
  end
311
302
 
@@ -320,6 +311,15 @@ module CarrierWave
320
311
  file.nil? ? 0 : file.content_length
321
312
  end
322
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
323
  ##
324
324
  # Check if the file exists on the remote service
325
325
  #
@@ -343,7 +343,7 @@ module CarrierWave
343
343
  fog_file = new_file.to_file
344
344
  @content_type ||= new_file.content_type
345
345
  @file = directory.files.create({
346
- :body => fog_file ? fog_file : new_file.read,
346
+ :body => fog_file || new_file.read,
347
347
  :content_type => @content_type,
348
348
  :key => path,
349
349
  :public => @uploader.fog_public
@@ -364,7 +364,7 @@ module CarrierWave
364
364
  #
365
365
  def public_url
366
366
  encoded_path = encode_path(path)
367
- if host = @uploader.asset_host
367
+ if (host = @uploader.asset_host)
368
368
  if host.respond_to? :call
369
369
  "#{host.call(self)}/#{encoded_path}"
370
370
  else
@@ -376,26 +376,29 @@ module CarrierWave
376
376
  when 'AWS'
377
377
  # check if some endpoint is set in fog_credentials
378
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
379
380
  "#{@uploader.fog_credentials[:endpoint]}/#{@uploader.fog_directory}/#{encoded_path}"
380
381
  else
381
382
  protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
382
383
 
383
384
  subdomain_regex = /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
384
- valid_subdomain = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
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
385
395
 
386
- # if directory is a valid subdomain, use that style for access
387
- if valid_subdomain
388
- s3_subdomain = @uploader.fog_aws_accelerate ? "s3-accelerate" : "s3"
389
- "#{protocol}://#{@uploader.fog_directory}.#{s3_subdomain}.amazonaws.com/#{encoded_path}"
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}"
390
399
  else # directory is not a valid subdomain, so use path style for access
391
- region = @uploader.fog_credentials[:region].to_s
392
- host = case region
393
- when DEFAULT_S3_REGION, ''
394
- 's3.amazonaws.com'
395
- else
396
- "s3.#{region}.amazonaws.com"
397
- end
398
- "#{protocol}://#{host}/#{@uploader.fog_directory}/#{encoded_path}"
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}"
399
402
  end
400
403
  end
401
404
  when 'Google'
@@ -409,7 +412,7 @@ module CarrierWave
409
412
  end
410
413
 
411
414
  ##
412
- # Return url to file, if avaliable
415
+ # Return url to file, if available
413
416
  #
414
417
  # === Returns
415
418
  #
@@ -435,7 +438,7 @@ module CarrierWave
435
438
  # [NilClass] no file name available
436
439
  #
437
440
  def filename(options = {})
438
- return unless file_url = url(options)
441
+ return unless (file_url = url(options))
439
442
  CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
440
443
  end
441
444
 
@@ -451,10 +454,29 @@ module CarrierWave
451
454
  # @return [CarrierWave::Storage::Fog::File] the location where the file will be stored.
452
455
  #
453
456
  def copy_to(new_path)
454
- connection.copy_object(@uploader.fog_directory, file.key, @uploader.fog_directory, new_path, copy_options)
457
+ file.copy(@uploader.fog_directory, new_path, copy_options)
455
458
  CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
456
459
  end
457
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
+
458
480
  private
459
481
 
460
482
  ##
@@ -476,12 +498,10 @@ module CarrierWave
476
498
  # [Fog::#{provider}::Directory] containing directory
477
499
  #
478
500
  def directory
479
- @directory ||= begin
480
- connection.directories.new(
481
- :key => @uploader.fog_directory,
482
- :public => @uploader.fog_public
483
- )
484
- end
501
+ @directory ||= connection.directories.new(
502
+ :key => @uploader.fog_directory,
503
+ :public => @uploader.fog_public
504
+ )
485
505
  end
486
506
 
487
507
  ##
@@ -498,14 +518,15 @@ module CarrierWave
498
518
  def copy_options
499
519
  options = {}
500
520
  options.merge!(acl_header) if acl_header.present?
501
- options['Content-Type'] ||= content_type if content_type
521
+ options[fog_provider == "Google" ? :content_type : 'Content-Type'] ||= content_type if content_type
502
522
  options.merge(@uploader.fog_attributes)
503
523
  end
504
524
 
505
525
  def acl_header
506
- if fog_provider == 'AWS'
526
+ case fog_provider
527
+ when 'AWS'
507
528
  { 'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private' }
508
- elsif fog_provider == "Google"
529
+ when "Google"
509
530
  @uploader.fog_public ? { destination_predefined_acl: "publicRead" } : {}
510
531
  else
511
532
  {}
@@ -516,14 +537,14 @@ module CarrierWave
516
537
  @uploader.fog_credentials[:provider].to_s
517
538
  end
518
539
 
519
- def read_source_file(file_body)
520
- return unless ::File.exist?(file_body.path)
540
+ def read_source_file
541
+ source_file = to_file
542
+ return unless source_file
521
543
 
522
544
  begin
523
- file_body = ::File.open(file_body.path) if file_body.closed? # Reopen if it's already closed
524
- file_body.read
545
+ source_file.read
525
546
  ensure
526
- file_body.close
547
+ source_file.close
527
548
  end
528
549
  end
529
550
 
@@ -45,11 +45,11 @@ module CarrierWave
45
45
  def matches?(actual)
46
46
  @actual = actual
47
47
  # Satisfy expectation here. Return false or raise an error if it's not met.
48
- (File.stat(@actual.path).mode & 0777) == @expected
48
+ (File.stat(@actual.path).mode & 0o777) == @expected
49
49
  end
50
50
 
51
51
  def failure_message
52
- "expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
52
+ "expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0o777).to_s(8)}"
53
53
  end
54
54
 
55
55
  def failure_message_when_negated
@@ -76,11 +76,11 @@ module CarrierWave
76
76
  def matches?(actual)
77
77
  @actual = actual
78
78
  # Satisfy expectation here. Return false or raise an error if it's not met.
79
- (File.stat(File.dirname @actual.path).mode & 0777) == @expected
79
+ (File.stat(File.dirname(@actual.path)).mode & 0o777) == @expected
80
80
  end
81
81
 
82
82
  def failure_message
83
- "expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
83
+ "expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0o777).to_s(8)}"
84
84
  end
85
85
 
86
86
  def failure_message_when_negated
@@ -341,9 +341,11 @@ module CarrierWave
341
341
  begin
342
342
  require 'rmagick'
343
343
  rescue LoadError
344
- require 'RMagick'
345
- rescue LoadError
346
- puts "WARNING: Failed to require rmagick, image processing may fail!"
344
+ begin
345
+ require 'RMagick'
346
+ rescue LoadError
347
+ puts "WARNING: Failed to require rmagick, image processing may fail!"
348
+ end
347
349
  end
348
350
  end
349
351
  MagickWrapper.new(filename)
@@ -353,6 +355,7 @@ module CarrierWave
353
355
 
354
356
  class MagickWrapper # :nodoc:
355
357
  attr_reader :image
358
+
356
359
  def width
357
360
  image.columns
358
361
  end
@@ -372,6 +375,7 @@ module CarrierWave
372
375
 
373
376
  class MiniMagickWrapper # :nodoc:
374
377
  attr_reader :image
378
+
375
379
  def width
376
380
  image[:width]
377
381
  end
@@ -24,7 +24,8 @@ module CarrierWave
24
24
  # [String] a cache id in the format TIMEINT-PID-COUNTER-RND
25
25
  #
26
26
  def self.generate_cache_id
27
- [Time.now.utc.to_i,
27
+ [
28
+ Time.now.utc.to_i,
28
29
  SecureRandom.random_number(1_000_000_000_000_000),
29
30
  '%04d' % (CarrierWave::CacheCounter.increment % 10_000),
30
31
  '%04d' % SecureRandom.random_number(10_000)
@@ -64,7 +65,7 @@ module CarrierWave
64
65
  # It's recommended that you keep cache files in one place only.
65
66
  #
66
67
  def clean_cached_files!(seconds=60*60*24)
67
- (cache_storage || storage).new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
68
+ (cache_storage || storage).new(new).clean_cache!(seconds)
68
69
  end
69
70
  end
70
71
 
@@ -90,9 +91,9 @@ module CarrierWave
90
91
  end
91
92
 
92
93
  def sanitized_file
93
- ActiveSupport::Deprecation.warn('#sanitized_file is deprecated, use #file instead.')
94
94
  file
95
95
  end
96
+ CarrierWave.deprecator.deprecate_methods(self, sanitized_file: :file)
96
97
 
97
98
  ##
98
99
  # Returns a String which uniquely identifies the currently cached file for later retrieval
@@ -102,7 +103,7 @@ module CarrierWave
102
103
  # [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
103
104
  #
104
105
  def cache_name
105
- File.join(cache_id, full_original_filename) if cache_id && original_filename
106
+ File.join(cache_id, original_filename) if cache_id && original_filename
106
107
  end
107
108
 
108
109
  ##
@@ -110,7 +111,7 @@ module CarrierWave
110
111
  #
111
112
  # By default, cache!() uses copy_to(), which operates by copying the file
112
113
  # to the cache, then deleting the original file. If move_to_cache() is
113
- # overriden to return true, then cache!() uses move_to(), which simply
114
+ # overridden to return true, then cache!() uses move_to(), which simply
114
115
  # moves the file to the cache. Useful for large files.
115
116
  #
116
117
  # === Parameters
@@ -129,6 +130,7 @@ module CarrierWave
129
130
 
130
131
  self.cache_id = CarrierWave.generate_cache_id unless cache_id
131
132
 
133
+ @identifier = nil
132
134
  @staged = true
133
135
  @filename = new_file.filename
134
136
  self.original_filename = new_file.filename
@@ -165,7 +167,7 @@ module CarrierWave
165
167
  self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
166
168
  @staged = true
167
169
  @filename = original_filename
168
- @file = cache_storage.retrieve_from_cache!(full_filename(original_filename))
170
+ @file = cache_storage.retrieve_from_cache!(full_original_filename)
169
171
  end
170
172
  end
171
173
 
@@ -180,20 +182,21 @@ module CarrierWave
180
182
  #
181
183
  # [String] the cache path
182
184
  #
183
- def cache_path(for_file=full_filename(original_filename))
185
+ def cache_path(for_file=full_original_filename)
184
186
  File.join(*[cache_dir, @cache_id, for_file].compact)
185
187
  end
186
188
 
189
+ protected
190
+
191
+ attr_reader :cache_id
192
+
187
193
  private
188
194
 
189
195
  def workfile_path(for_file=original_filename)
190
196
  File.join(CarrierWave.tmp_path, @cache_id, version_name.to_s, for_file)
191
197
  end
192
198
 
193
- attr_reader :cache_id, :original_filename
194
-
195
- # We can override the full_original_filename method in other modules
196
- alias_method :full_original_filename, :original_filename
199
+ attr_reader :original_filename
197
200
 
198
201
  def cache_id=(cache_id)
199
202
  # Earlier version used 3 part cache_id. Thus we should allow for
@@ -210,6 +213,11 @@ module CarrierWave
210
213
  def cache_storage
211
214
  @cache_storage ||= (self.class.cache_storage || self.class.storage).new(self)
212
215
  end
216
+
217
+ # We can override the full_original_filename method in other modules
218
+ def full_original_filename
219
+ forcing_extension(original_filename)
220
+ end
213
221
  end # Cache
214
222
  end # Uploader
215
223
  end # CarrierWave
@@ -5,7 +5,7 @@ module CarrierWave
5
5
 
6
6
  included do
7
7
  class_attribute :_before_callbacks, :_after_callbacks,
8
- :instance_writer => false
8
+ :instance_writer => false
9
9
  self._before_callbacks = Hash.new []
10
10
  self._after_callbacks = Hash.new []
11
11
  end
@@ -24,6 +24,7 @@ module CarrierWave
24
24
  add_config :move_to_store
25
25
  add_config :remove_previously_stored_files_after_update
26
26
  add_config :downloader
27
+ add_config :force_extension
27
28
 
28
29
  # fog
29
30
  add_deprecated_config :fog_provider
@@ -34,6 +35,7 @@ module CarrierWave
34
35
  add_config :fog_authenticated_url_expiration
35
36
  add_config :fog_use_ssl_for_aws
36
37
  add_config :fog_aws_accelerate
38
+ add_config :fog_aws_fips
37
39
 
38
40
  # Mounting
39
41
  add_config :ignore_integrity_errors
@@ -44,6 +46,9 @@ module CarrierWave
44
46
  add_config :validate_download
45
47
  add_config :mount_on
46
48
  add_config :cache_only
49
+ add_config :download_retry_count
50
+ add_config :download_retry_wait_time
51
+ add_config :skip_ssrf_protection
47
52
 
48
53
  # set default values
49
54
  reset_config
@@ -77,7 +82,7 @@ module CarrierWave
77
82
  def storage(storage = nil)
78
83
  case storage
79
84
  when Symbol
80
- if storage_engine = storage_engines[storage]
85
+ if (storage_engine = storage_engines[storage])
81
86
  self._storage = eval storage_engine
82
87
  else
83
88
  raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
@@ -123,7 +128,7 @@ module CarrierWave
123
128
  @#{name} = nil
124
129
 
125
130
  def self.#{name}(value=nil)
126
- @#{name} = value if value
131
+ @#{name} = value unless value.nil?
127
132
  return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
128
133
  name = superclass.#{name}
129
134
  return nil if name.nil? && !instance_variable_defined?(:@#{name})
@@ -153,19 +158,19 @@ module CarrierWave
153
158
  def add_deprecated_config(name)
154
159
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
155
160
  def self.#{name}(value=nil)
156
- ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
161
+ CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
157
162
  end
158
163
 
159
164
  def self.#{name}=(value)
160
- ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
165
+ CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
161
166
  end
162
167
 
163
168
  def #{name}=(value)
164
- ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
169
+ CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
165
170
  end
166
171
 
167
172
  def #{name}
168
- ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
173
+ CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
169
174
  end
170
175
  RUBY
171
176
  end
@@ -179,8 +184,8 @@ module CarrierWave
179
184
  #
180
185
  def reset_config
181
186
  configure do |config|
182
- config.permissions = 0644
183
- config.directory_permissions = 0755
187
+ config.permissions = 0o644
188
+ config.directory_permissions = 0o755
184
189
  config.storage_engines = {
185
190
  :file => "CarrierWave::Storage::File",
186
191
  :fog => "CarrierWave::Storage::Fog"
@@ -193,6 +198,7 @@ module CarrierWave
193
198
  config.fog_authenticated_url_expiration = 600
194
199
  config.fog_use_ssl_for_aws = true
195
200
  config.fog_aws_accelerate = false
201
+ config.fog_aws_fips = false
196
202
  config.store_dir = 'uploads'
197
203
  config.cache_dir = 'uploads/tmp'
198
204
  config.delete_tmp_file_after_storage = true
@@ -200,6 +206,7 @@ module CarrierWave
200
206
  config.move_to_store = false
201
207
  config.remove_previously_stored_files_after_update = true
202
208
  config.downloader = CarrierWave::Downloader::Base
209
+ config.force_extension = false
203
210
  config.ignore_integrity_errors = true
204
211
  config.ignore_processing_errors = true
205
212
  config.ignore_download_errors = true
@@ -210,6 +217,9 @@ module CarrierWave
210
217
  config.base_path = CarrierWave.base_path
211
218
  config.enable_processing = true
212
219
  config.ensure_multipart_form = true
220
+ config.download_retry_count = 0
221
+ config.download_retry_wait_time = 5
222
+ config.skip_ssrf_protection = false
213
223
  end
214
224
  end
215
225
  end
@@ -1,10 +1,10 @@
1
1
  module CarrierWave
2
2
  module Uploader
3
- module ContentTypeWhitelist
3
+ module ContentTypeAllowlist
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- before :cache, :check_content_type_whitelist!
7
+ before :cache, :check_content_type_allowlist!
8
8
  end
9
9
 
10
10
  ##
@@ -29,32 +29,34 @@ module CarrierWave
29
29
  # end
30
30
  #
31
31
  def content_type_allowlist
32
- if respond_to?(:content_type_whitelist)
33
- ActiveSupport::Deprecation.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
34
- @content_type_whitelist_warned = true
35
- content_type_whitelist
36
- end
37
32
  end
38
33
 
39
34
  private
40
35
 
41
- def check_content_type_whitelist!(new_file)
42
- return unless content_type_allowlist
36
+ def check_content_type_allowlist!(new_file)
37
+ allowlist = content_type_allowlist
38
+ if !allowlist && respond_to?(:content_type_whitelist) && content_type_whitelist
39
+ CarrierWave.deprecator.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
40
+ @content_type_whitelist_warned = true
41
+ allowlist = content_type_whitelist
42
+ end
43
+
44
+ return unless allowlist
43
45
 
44
46
  content_type = new_file.content_type
45
- if !whitelisted_content_type?(content_type)
46
- raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type,
47
- allowed_types: Array(content_type_allowlist).join(", "), default: :"errors.messages.content_type_allowlist_error")
47
+ if !allowlisted_content_type?(allowlist, content_type)
48
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_allowlist_error", content_type: content_type,
49
+ allowed_types: Array(allowlist).join(", "), default: :"errors.messages.content_type_whitelist_error")
48
50
  end
49
51
  end
50
52
 
51
- def whitelisted_content_type?(content_type)
52
- Array(content_type_allowlist).any? do |item|
53
+ def allowlisted_content_type?(allowlist, content_type)
54
+ Array(allowlist).any? do |item|
53
55
  item = Regexp.quote(item) if item.class != Regexp
54
56
  content_type =~ /\A#{item}/
55
57
  end
56
58
  end
57
59
 
58
- end # ContentTypeWhitelist
60
+ end # ContentTypeAllowlist
59
61
  end # Uploader
60
62
  end # CarrierWave