carrierwave 2.2.2 → 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.
- checksums.yaml +4 -4
- data/README.md +180 -62
- data/lib/carrierwave/compatibility/paperclip.rb +4 -2
- data/lib/carrierwave/downloader/base.rb +28 -14
- data/lib/carrierwave/downloader/remote_file.rb +13 -10
- data/lib/carrierwave/locale/en.yml +5 -3
- data/lib/carrierwave/mount.rb +36 -50
- data/lib/carrierwave/mounter.rb +118 -50
- data/lib/carrierwave/orm/activerecord.rb +21 -62
- data/lib/carrierwave/processing/mini_magick.rb +45 -14
- data/lib/carrierwave/processing/rmagick.rb +47 -20
- data/lib/carrierwave/processing/vips.rb +43 -12
- data/lib/carrierwave/sanitized_file.rb +58 -77
- data/lib/carrierwave/storage/abstract.rb +5 -5
- data/lib/carrierwave/storage/file.rb +6 -5
- data/lib/carrierwave/storage/fog.rb +86 -65
- data/lib/carrierwave/test/matchers.rb +11 -7
- data/lib/carrierwave/uploader/cache.rb +19 -11
- data/lib/carrierwave/uploader/callbacks.rb +1 -1
- data/lib/carrierwave/uploader/configuration.rb +18 -8
- data/lib/carrierwave/uploader/{content_type_whitelist.rb → content_type_allowlist.rb} +18 -16
- data/lib/carrierwave/uploader/{content_type_blacklist.rb → content_type_denylist.rb} +20 -15
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/{extension_whitelist.rb → extension_allowlist.rb} +17 -15
- data/lib/carrierwave/uploader/{extension_blacklist.rb → extension_denylist.rb} +19 -14
- data/lib/carrierwave/uploader/file_size.rb +2 -2
- data/lib/carrierwave/uploader/processing.rb +45 -7
- data/lib/carrierwave/uploader/proxy.rb +16 -3
- data/lib/carrierwave/uploader/store.rb +70 -6
- data/lib/carrierwave/uploader/url.rb +1 -1
- data/lib/carrierwave/uploader/versions.rb +158 -138
- data/lib/carrierwave/uploader.rb +10 -8
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities/uri.rb +14 -11
- data/lib/carrierwave/utilities.rb +1 -0
- data/lib/carrierwave/validations/active_model.rb +4 -6
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +18 -17
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +1 -1
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +37 -63
@@ -1,10 +1,10 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
|
-
module
|
3
|
+
module ContentTypeDenylist
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_content_type_denylist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -29,29 +29,34 @@ module CarrierWave
|
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
def content_type_denylist
|
32
|
-
if respond_to?(:content_type_blacklist)
|
33
|
-
ActiveSupport::Deprecation.warn "#content_type_blacklist is deprecated, use #content_type_denylist instead." unless instance_variable_defined?(:@content_type_blacklist_warned)
|
34
|
-
@content_type_blacklist_warned = true
|
35
|
-
content_type_blacklist
|
36
|
-
end
|
37
32
|
end
|
38
33
|
|
39
34
|
private
|
40
35
|
|
41
|
-
def
|
42
|
-
|
36
|
+
def check_content_type_denylist!(new_file)
|
37
|
+
denylist = content_type_denylist
|
38
|
+
if !denylist && respond_to?(:content_type_blacklist) && content_type_blacklist
|
39
|
+
CarrierWave.deprecator.warn "#content_type_blacklist is deprecated, use #content_type_denylist instead." unless instance_variable_defined?(:@content_type_blacklist_warned)
|
40
|
+
@content_type_blacklist_warned = true
|
41
|
+
denylist = content_type_blacklist
|
42
|
+
end
|
43
|
+
|
44
|
+
return unless denylist
|
45
|
+
|
46
|
+
CarrierWave.deprecator.warn "Use of #content_type_denylist is deprecated for the security reason, use #content_type_allowlist instead to explicitly state what are safe to accept" unless instance_variable_defined?(:@content_type_denylist_warned)
|
47
|
+
@content_type_denylist_warned = true
|
43
48
|
|
44
49
|
content_type = new_file.content_type
|
45
|
-
if
|
46
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
47
|
-
content_type: content_type, default: :"errors.messages.
|
50
|
+
if denylisted_content_type?(denylist, content_type)
|
51
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_denylist_error",
|
52
|
+
content_type: content_type, default: :"errors.messages.content_type_blacklist_error")
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
51
|
-
def
|
52
|
-
Array(
|
56
|
+
def denylisted_content_type?(denylist, content_type)
|
57
|
+
Array(denylist).any? { |item| content_type =~ /#{item}/ }
|
53
58
|
end
|
54
59
|
|
55
|
-
end #
|
60
|
+
end # ContentTypeDenylist
|
56
61
|
end # Uploader
|
57
62
|
end # CarrierWave
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module Dimension
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
before :cache, :check_dimensions!
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Override this method in your uploader to provide a Range of width which
|
14
|
+
# are allowed to be uploaded.
|
15
|
+
# === Returns
|
16
|
+
#
|
17
|
+
# [NilClass, Range] a width range which are permitted to be uploaded
|
18
|
+
#
|
19
|
+
# === Examples
|
20
|
+
#
|
21
|
+
# def width_range
|
22
|
+
# 1000..2000
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
def width_range; end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Override this method in your uploader to provide a Range of height which
|
29
|
+
# are allowed to be uploaded.
|
30
|
+
# === Returns
|
31
|
+
#
|
32
|
+
# [NilClass, Range] a height range which are permitted to be uploaded
|
33
|
+
#
|
34
|
+
# === Examples
|
35
|
+
#
|
36
|
+
# def height_range
|
37
|
+
# 1000..
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
def height_range; end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def check_dimensions!(new_file)
|
45
|
+
# NOTE: Skip the check for resized images
|
46
|
+
return if version_name.present?
|
47
|
+
return unless width_range || height_range
|
48
|
+
|
49
|
+
unless respond_to?(:width) || respond_to?(:height)
|
50
|
+
raise 'You need to include one of CarrierWave::MiniMagick, CarrierWave::RMagick, or CarrierWave::Vips to perform image dimension validation'
|
51
|
+
end
|
52
|
+
|
53
|
+
if width_range&.begin && width < width_range.begin
|
54
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_width_error", :min_width => ActiveSupport::NumberHelper.number_to_delimited(width_range.begin))
|
55
|
+
elsif width_range&.end && width > width_range.end
|
56
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_width_error", :max_width => ActiveSupport::NumberHelper.number_to_delimited(width_range.end))
|
57
|
+
elsif height_range&.begin && height < height_range.begin
|
58
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_height_error", :min_height => ActiveSupport::NumberHelper.number_to_delimited(height_range.begin))
|
59
|
+
elsif height_range&.end && height > height_range.end
|
60
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_height_error", :max_height => ActiveSupport::NumberHelper.number_to_delimited(height_range.end))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end # Dimension
|
65
|
+
end # Uploader
|
66
|
+
end # CarrierWave
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
|
-
module
|
3
|
+
module ExtensionAllowlist
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_extension_allowlist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -32,30 +32,32 @@ module CarrierWave
|
|
32
32
|
# end
|
33
33
|
#
|
34
34
|
def extension_allowlist
|
35
|
-
if respond_to?(:extension_whitelist)
|
36
|
-
ActiveSupport::Deprecation.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
|
37
|
-
@extension_whitelist_warned = true
|
38
|
-
extension_whitelist
|
39
|
-
end
|
40
35
|
end
|
41
36
|
|
42
37
|
private
|
43
38
|
|
44
|
-
def
|
45
|
-
|
39
|
+
def check_extension_allowlist!(new_file)
|
40
|
+
allowlist = extension_allowlist
|
41
|
+
if !allowlist && respond_to?(:extension_whitelist) && extension_whitelist
|
42
|
+
CarrierWave.deprecator.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
|
43
|
+
@extension_whitelist_warned = true
|
44
|
+
allowlist = extension_whitelist
|
45
|
+
end
|
46
|
+
|
47
|
+
return unless allowlist
|
46
48
|
|
47
49
|
extension = new_file.extension.to_s
|
48
|
-
if !
|
50
|
+
if !allowlisted_extension?(allowlist, extension)
|
49
51
|
# Look for whitelist first, then fallback to allowlist
|
50
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
51
|
-
allowed_types: Array(
|
52
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_allowlist_error", extension: new_file.extension.inspect,
|
53
|
+
allowed_types: Array(allowlist).join(", "), default: :"errors.messages.extension_whitelist_error")
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
|
-
def
|
57
|
+
def allowlisted_extension?(allowlist, extension)
|
56
58
|
downcase_extension = extension.downcase
|
57
|
-
Array(
|
59
|
+
Array(allowlist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
|
58
60
|
end
|
59
|
-
end #
|
61
|
+
end # ExtensionAllowlist
|
60
62
|
end # Uploader
|
61
63
|
end # CarrierWave
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
|
-
module
|
3
|
+
module ExtensionDenylist
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_extension_denylist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -32,27 +32,32 @@ module CarrierWave
|
|
32
32
|
# end
|
33
33
|
#
|
34
34
|
def extension_denylist
|
35
|
-
if respond_to?(:extension_blacklist)
|
36
|
-
ActiveSupport::Deprecation.warn "#extension_blacklist is deprecated, use #extension_denylist instead." unless instance_variable_defined?(:@extension_blacklist_warned)
|
37
|
-
@extension_blacklist_warned = true
|
38
|
-
extension_blacklist
|
39
|
-
end
|
40
35
|
end
|
41
36
|
|
42
37
|
private
|
43
38
|
|
44
|
-
def
|
45
|
-
|
39
|
+
def check_extension_denylist!(new_file)
|
40
|
+
denylist = extension_denylist
|
41
|
+
if !denylist && respond_to?(:extension_blacklist) && extension_blacklist
|
42
|
+
CarrierWave.deprecator.warn "#extension_blacklist is deprecated, use #extension_denylist instead." unless instance_variable_defined?(:@extension_blacklist_warned)
|
43
|
+
@extension_blacklist_warned = true
|
44
|
+
denylist = extension_blacklist
|
45
|
+
end
|
46
|
+
|
47
|
+
return unless denylist
|
48
|
+
|
49
|
+
CarrierWave.deprecator.warn "Use of #extension_denylist is deprecated for the security reason, use #extension_allowlist instead to explicitly state what are safe to accept" unless instance_variable_defined?(:@extension_denylist_warned)
|
50
|
+
@extension_denylist_warned = true
|
46
51
|
|
47
52
|
extension = new_file.extension.to_s
|
48
|
-
if
|
49
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
50
|
-
prohibited_types: Array(extension_denylist).join(", "), default: :"errors.messages.
|
53
|
+
if denylisted_extension?(denylist, extension)
|
54
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_denylist_error", extension: new_file.extension.inspect,
|
55
|
+
prohibited_types: Array(extension_denylist).join(", "), default: :"errors.messages.extension_blacklist_error")
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
54
|
-
def
|
55
|
-
Array(
|
59
|
+
def denylisted_extension?(denylist, extension)
|
60
|
+
Array(denylist).any? { |item| extension =~ /\A#{item}\z/i }
|
56
61
|
end
|
57
62
|
end
|
58
63
|
end
|
@@ -14,7 +14,7 @@ module CarrierWave
|
|
14
14
|
# are allowed to be uploaded.
|
15
15
|
# === Returns
|
16
16
|
#
|
17
|
-
# [NilClass, Range] a size range which are permitted to be uploaded
|
17
|
+
# [NilClass, Range] a size range (in bytes) which are permitted to be uploaded
|
18
18
|
#
|
19
19
|
# === Examples
|
20
20
|
#
|
@@ -24,7 +24,7 @@ module CarrierWave
|
|
24
24
|
#
|
25
25
|
def size_range; end
|
26
26
|
|
27
|
-
|
27
|
+
private
|
28
28
|
|
29
29
|
def check_size!(new_file)
|
30
30
|
size = new_file.size
|
@@ -18,7 +18,7 @@ module CarrierWave
|
|
18
18
|
# Adds a processor callback which applies operations as a file is uploaded.
|
19
19
|
# The argument may be the name of any method of the uploader, expressed as a symbol,
|
20
20
|
# or a list of such methods, or a hash where the key is a method and the value is
|
21
|
-
# an array of arguments to call the method with
|
21
|
+
# an array of arguments to call the method with. Also accepts an :if or :unless condition
|
22
22
|
#
|
23
23
|
# === Parameters
|
24
24
|
#
|
@@ -31,6 +31,7 @@ module CarrierWave
|
|
31
31
|
# process :sepiatone, :vignette
|
32
32
|
# process :scale => [200, 200]
|
33
33
|
# process :scale => [200, 200], :if => :image?
|
34
|
+
# process :scale => [200, 200], :unless => :disallowed_image_type?
|
34
35
|
# process :sepiatone, :if => :image?
|
35
36
|
#
|
36
37
|
# def sepiatone
|
@@ -49,6 +50,10 @@ module CarrierWave
|
|
49
50
|
# ...
|
50
51
|
# end
|
51
52
|
#
|
53
|
+
# def disallowed_image_type?
|
54
|
+
# ...
|
55
|
+
# end
|
56
|
+
#
|
52
57
|
# end
|
53
58
|
#
|
54
59
|
def process(*args)
|
@@ -57,12 +62,20 @@ module CarrierWave
|
|
57
62
|
hash.merge!(arg)
|
58
63
|
end
|
59
64
|
|
60
|
-
|
65
|
+
condition_type = new_processors.keys.detect { |key| [:if, :unless].include?(key) }
|
66
|
+
condition = new_processors.delete(:if) || new_processors.delete(:unless)
|
61
67
|
new_processors.each do |processor, processor_args|
|
62
|
-
self.processors += [[processor, processor_args, condition]]
|
68
|
+
self.processors += [[processor, processor_args, condition, condition_type]]
|
69
|
+
|
70
|
+
if processor == :convert
|
71
|
+
# Treat :convert specially, since it should trigger the file extension change
|
72
|
+
force_extension processor_args
|
73
|
+
if condition
|
74
|
+
warn "Use of 'process convert: format' with conditionals has an issue and doesn't work correctly. See https://github.com/carrierwaveuploader/carrierwave/issues/2723 for details. "
|
75
|
+
end
|
76
|
+
end
|
63
77
|
end
|
64
78
|
end
|
65
|
-
|
66
79
|
end # ClassMethods
|
67
80
|
|
68
81
|
##
|
@@ -72,19 +85,44 @@ module CarrierWave
|
|
72
85
|
return unless enable_processing
|
73
86
|
|
74
87
|
with_callbacks(:process, new_file) do
|
75
|
-
self.class.processors.each do |method, args, condition|
|
76
|
-
if
|
88
|
+
self.class.processors.each do |method, args, condition, condition_type|
|
89
|
+
if condition && condition_type == :if
|
77
90
|
if condition.respond_to?(:call)
|
78
91
|
next unless condition.call(self, :args => args, :method => method, :file => new_file)
|
79
92
|
else
|
80
93
|
next unless self.send(condition, new_file)
|
81
94
|
end
|
95
|
+
elsif condition && condition_type == :unless
|
96
|
+
if condition.respond_to?(:call)
|
97
|
+
next if condition.call(self, :args => args, :method => method, :file => new_file)
|
98
|
+
elsif self.send(condition, new_file)
|
99
|
+
next
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
if args.is_a? Array
|
104
|
+
kwargs, args = args.partition { |arg| arg.is_a? Hash }
|
105
|
+
end
|
106
|
+
|
107
|
+
if kwargs.present?
|
108
|
+
kwargs = kwargs.reduce(:merge)
|
109
|
+
self.send(method, *args, **kwargs)
|
110
|
+
else
|
111
|
+
self.send(method, *args)
|
82
112
|
end
|
83
|
-
self.send(method, *args)
|
84
113
|
end
|
85
114
|
end
|
86
115
|
end
|
87
116
|
|
117
|
+
private
|
118
|
+
|
119
|
+
def forcing_extension(filename)
|
120
|
+
if force_extension && filename
|
121
|
+
Pathname.new(filename).sub_ext(".#{force_extension.to_s.delete_prefix('.')}").to_s
|
122
|
+
else
|
123
|
+
filename
|
124
|
+
end
|
125
|
+
end
|
88
126
|
end # Processing
|
89
127
|
end # Uploader
|
90
128
|
end # CarrierWave
|
@@ -30,7 +30,20 @@ module CarrierWave
|
|
30
30
|
# [String] uniquely identifies a file
|
31
31
|
#
|
32
32
|
def identifier
|
33
|
-
@identifier || storage.try(:identifier)
|
33
|
+
@identifier || (file && storage.try(:identifier))
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Returns a String which is to be used as a temporary value which gets assigned to the column.
|
38
|
+
# The purpose is to mark the column that it will be updated. Finally before the save it will be
|
39
|
+
# overwritten by the #identifier value, which is usually #filename.
|
40
|
+
#
|
41
|
+
# === Returns
|
42
|
+
#
|
43
|
+
# [String] a temporary_identifier, by default the value of #cache_name is used
|
44
|
+
#
|
45
|
+
def temporary_identifier
|
46
|
+
cache_name || @identifier
|
34
47
|
end
|
35
48
|
|
36
49
|
##
|
@@ -40,8 +53,8 @@ module CarrierWave
|
|
40
53
|
#
|
41
54
|
# [String] contents of the file
|
42
55
|
#
|
43
|
-
def read
|
44
|
-
file.try(:read)
|
56
|
+
def read(*args)
|
57
|
+
file.try(:read, *args)
|
45
58
|
end
|
46
59
|
|
47
60
|
##
|
@@ -11,9 +11,23 @@ module CarrierWave
|
|
11
11
|
prepend Module.new {
|
12
12
|
def initialize(*)
|
13
13
|
super
|
14
|
-
@file, @filename, @cache_id, @identifier = nil
|
14
|
+
@file, @filename, @cache_id, @identifier, @deduplication_index = nil
|
15
15
|
end
|
16
16
|
}
|
17
|
+
|
18
|
+
after :store, :show_warning_when_filename_is_unavailable
|
19
|
+
|
20
|
+
class_attribute :filename_safeguard_checked
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
private
|
25
|
+
|
26
|
+
def inherited(subclass)
|
27
|
+
# To perform the filename safeguard check once per a class
|
28
|
+
self.filename_safeguard_checked = false
|
29
|
+
super
|
30
|
+
end
|
17
31
|
end
|
18
32
|
|
19
33
|
##
|
@@ -34,9 +48,26 @@ module CarrierWave
|
|
34
48
|
@filename
|
35
49
|
end
|
36
50
|
|
51
|
+
##
|
52
|
+
# Returns a filename which doesn't conflict with already-stored files.
|
53
|
+
#
|
54
|
+
# === Returns
|
55
|
+
#
|
56
|
+
# [String] the filename with suffix added for deduplication
|
57
|
+
#
|
58
|
+
def deduplicated_filename
|
59
|
+
return unless filename
|
60
|
+
return filename unless @deduplication_index
|
61
|
+
|
62
|
+
parts = filename.split('.')
|
63
|
+
basename = parts.shift
|
64
|
+
basename.sub!(/ ?\(\d+\)\z/, '')
|
65
|
+
([basename.to_s + (@deduplication_index > 1 ? "(#{@deduplication_index})" : '')] + parts).join('.')
|
66
|
+
end
|
67
|
+
|
37
68
|
##
|
38
69
|
# Calculates the path where the file should be stored. If +for_file+ is given, it will be
|
39
|
-
# used as the
|
70
|
+
# used as the identifier, otherwise +CarrierWave::Uploader#identifier+ is assumed.
|
40
71
|
#
|
41
72
|
# === Parameters
|
42
73
|
#
|
@@ -46,7 +77,7 @@ module CarrierWave
|
|
46
77
|
#
|
47
78
|
# [String] the store path
|
48
79
|
#
|
49
|
-
def store_path(for_file=
|
80
|
+
def store_path(for_file=identifier)
|
50
81
|
File.join([store_dir, full_filename(for_file)].compact)
|
51
82
|
end
|
52
83
|
|
@@ -60,7 +91,7 @@ module CarrierWave
|
|
60
91
|
# [new_file (File, IOString, Tempfile)] any kind of file object
|
61
92
|
#
|
62
93
|
def store!(new_file=nil)
|
63
|
-
cache!(new_file) if new_file &&
|
94
|
+
cache!(new_file) if new_file && !cached?
|
64
95
|
if !cache_only && @file && @cache_id
|
65
96
|
with_callbacks(:store, new_file) do
|
66
97
|
new_file = storage.store!(@file)
|
@@ -69,7 +100,8 @@ module CarrierWave
|
|
69
100
|
cache_storage.delete_dir!(cache_path(nil))
|
70
101
|
end
|
71
102
|
@file = new_file
|
72
|
-
@
|
103
|
+
@identifier = storage.identifier
|
104
|
+
@original_filename = @cache_id = @deduplication_index = nil
|
73
105
|
@staged = false
|
74
106
|
end
|
75
107
|
end
|
@@ -89,10 +121,42 @@ module CarrierWave
|
|
89
121
|
end
|
90
122
|
end
|
91
123
|
|
124
|
+
##
|
125
|
+
# Look for an identifier which doesn't collide with the given already-stored identifiers.
|
126
|
+
# It is done by adding a index number as the suffix.
|
127
|
+
# For example, if there's 'image.jpg' and the @deduplication_index is set to 2,
|
128
|
+
# The stored file will be named as 'image(2).jpg'.
|
129
|
+
#
|
130
|
+
# === Parameters
|
131
|
+
#
|
132
|
+
# [current_identifiers (Array[String])] List of identifiers for already-stored files
|
133
|
+
#
|
134
|
+
def deduplicate(current_identifiers)
|
135
|
+
@deduplication_index = nil
|
136
|
+
return unless current_identifiers.include?(identifier)
|
137
|
+
|
138
|
+
(1..current_identifiers.size + 1).each do |i|
|
139
|
+
@deduplication_index = i
|
140
|
+
break unless current_identifiers.include?(identifier)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
92
144
|
private
|
93
145
|
|
94
146
|
def full_filename(for_file)
|
95
|
-
for_file
|
147
|
+
forcing_extension(for_file)
|
148
|
+
end
|
149
|
+
|
150
|
+
def show_warning_when_filename_is_unavailable(_)
|
151
|
+
return if self.class.filename_safeguard_checked
|
152
|
+
self.class.filename_safeguard_checked = true
|
153
|
+
return if filename
|
154
|
+
|
155
|
+
warn <<~MESSAGE
|
156
|
+
[WARNING] Your uploader's #filename method defined at #{method(:filename).source_location.join(':')} didn't return value after storing the file.
|
157
|
+
It's likely that the method is safeguarded with `if original_filename`, which were necessary for pre-3.x CarrierWave but is no longer needed.
|
158
|
+
Removing it is recommended, as it is known to cause issues depending on the use case: https://github.com/carrierwaveuploader/carrierwave/issues/2708
|
159
|
+
MESSAGE
|
96
160
|
end
|
97
161
|
|
98
162
|
def storage
|