carrierwave 1.3.2 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of carrierwave might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +117 -43
- data/lib/carrierwave.rb +4 -0
- data/lib/carrierwave/downloader/base.rb +87 -0
- data/lib/carrierwave/downloader/remote_file.rb +65 -0
- data/lib/carrierwave/locale/en.yml +5 -4
- data/lib/carrierwave/mount.rb +25 -19
- data/lib/carrierwave/mounter.rb +71 -48
- data/lib/carrierwave/orm/activerecord.rb +14 -8
- data/lib/carrierwave/processing.rb +1 -0
- data/lib/carrierwave/processing/mini_magick.rb +100 -117
- data/lib/carrierwave/processing/rmagick.rb +2 -2
- data/lib/carrierwave/processing/vips.rb +284 -0
- data/lib/carrierwave/sanitized_file.rb +38 -16
- data/lib/carrierwave/storage.rb +1 -0
- data/lib/carrierwave/storage/file.rb +2 -2
- data/lib/carrierwave/storage/fog.rb +44 -13
- data/lib/carrierwave/uploader.rb +0 -9
- data/lib/carrierwave/uploader/cache.rb +24 -16
- data/lib/carrierwave/uploader/configuration.rb +28 -15
- data/lib/carrierwave/uploader/content_type_blacklist.rb +17 -8
- data/lib/carrierwave/uploader/content_type_whitelist.rb +20 -8
- data/lib/carrierwave/uploader/download.rb +2 -123
- data/lib/carrierwave/uploader/extension_blacklist.rb +18 -10
- data/lib/carrierwave/uploader/extension_whitelist.rb +19 -10
- data/lib/carrierwave/uploader/mountable.rb +6 -0
- data/lib/carrierwave/uploader/proxy.rb +2 -2
- data/lib/carrierwave/uploader/serialization.rb +1 -1
- data/lib/carrierwave/uploader/store.rb +5 -3
- data/lib/carrierwave/uploader/url.rb +6 -3
- data/lib/carrierwave/uploader/versions.rb +43 -13
- data/lib/carrierwave/validations/active_model.rb +3 -3
- data/lib/carrierwave/version.rb +1 -1
- data/lib/generators/templates/uploader.rb +2 -2
- metadata +99 -20
data/lib/carrierwave/uploader.rb
CHANGED
@@ -43,15 +43,6 @@ module CarrierWave
|
|
43
43
|
class Base
|
44
44
|
attr_reader :file
|
45
45
|
|
46
|
-
##
|
47
|
-
# Workaround for class_attribute malfunction when used with Module#prepend
|
48
|
-
#
|
49
|
-
if RUBY_VERSION < '2.1.0'
|
50
|
-
def self.singleton_class?
|
51
|
-
!ancestors.include? self
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
46
|
include CarrierWave::Uploader::Configuration
|
56
47
|
include CarrierWave::Uploader::Callbacks
|
57
48
|
include CarrierWave::Uploader::Proxy
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
module CarrierWave
|
2
4
|
|
3
5
|
class FormNotMultipart < UploadError
|
@@ -23,9 +25,9 @@ module CarrierWave
|
|
23
25
|
#
|
24
26
|
def self.generate_cache_id
|
25
27
|
[Time.now.utc.to_i,
|
26
|
-
|
27
|
-
'%04d' % (CarrierWave::CacheCounter.increment %
|
28
|
-
'%04d' %
|
28
|
+
SecureRandom.random_number(1_000_000_000_000_000),
|
29
|
+
'%04d' % (CarrierWave::CacheCounter.increment % 10_000),
|
30
|
+
'%04d' % SecureRandom.random_number(10_000)
|
29
31
|
].map(&:to_s).join('-')
|
30
32
|
end
|
31
33
|
|
@@ -36,6 +38,16 @@ module CarrierWave
|
|
36
38
|
include CarrierWave::Uploader::Callbacks
|
37
39
|
include CarrierWave::Uploader::Configuration
|
38
40
|
|
41
|
+
included do
|
42
|
+
prepend Module.new {
|
43
|
+
def initialize(*)
|
44
|
+
super
|
45
|
+
@staged = false
|
46
|
+
end
|
47
|
+
}
|
48
|
+
attr_accessor :staged
|
49
|
+
end
|
50
|
+
|
39
51
|
module ClassMethods
|
40
52
|
|
41
53
|
##
|
@@ -52,7 +64,7 @@ module CarrierWave
|
|
52
64
|
# It's recommended that you keep cache files in one place only.
|
53
65
|
#
|
54
66
|
def clean_cached_files!(seconds=60*60*24)
|
55
|
-
cache_storage.new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
|
67
|
+
(cache_storage || storage).new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
|
56
68
|
end
|
57
69
|
end
|
58
70
|
|
@@ -64,7 +76,7 @@ module CarrierWave
|
|
64
76
|
# [Bool] whether the current file is cached
|
65
77
|
#
|
66
78
|
def cached?
|
67
|
-
|
79
|
+
!!@cache_id
|
68
80
|
end
|
69
81
|
|
70
82
|
##
|
@@ -78,14 +90,8 @@ module CarrierWave
|
|
78
90
|
end
|
79
91
|
|
80
92
|
def sanitized_file
|
81
|
-
|
82
|
-
|
83
|
-
sanitized = CarrierWave::Storage::Fog.new(self).retrieve!(File.basename(_content.path))
|
84
|
-
else
|
85
|
-
sanitized = SanitizedFile.new :tempfile => StringIO.new(_content),
|
86
|
-
:filename => File.basename(path), :content_type => file.content_type
|
87
|
-
end
|
88
|
-
sanitized
|
93
|
+
ActiveSupport::Deprecation.warn('#sanitized_file is deprecated, use #file instead.')
|
94
|
+
file
|
89
95
|
end
|
90
96
|
|
91
97
|
##
|
@@ -96,7 +102,7 @@ module CarrierWave
|
|
96
102
|
# [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
|
97
103
|
#
|
98
104
|
def cache_name
|
99
|
-
File.join(cache_id, full_original_filename) if cache_id
|
105
|
+
File.join(cache_id, full_original_filename) if cache_id && original_filename
|
100
106
|
end
|
101
107
|
|
102
108
|
##
|
@@ -115,7 +121,7 @@ module CarrierWave
|
|
115
121
|
#
|
116
122
|
# [CarrierWave::FormNotMultipart] if the assigned parameter is a string
|
117
123
|
#
|
118
|
-
def cache!(new_file =
|
124
|
+
def cache!(new_file = file)
|
119
125
|
new_file = CarrierWave::SanitizedFile.new(new_file)
|
120
126
|
return if new_file.empty?
|
121
127
|
|
@@ -123,6 +129,7 @@ module CarrierWave
|
|
123
129
|
|
124
130
|
self.cache_id = CarrierWave.generate_cache_id unless cache_id
|
125
131
|
|
132
|
+
@staged = true
|
126
133
|
@filename = new_file.filename
|
127
134
|
self.original_filename = new_file.filename
|
128
135
|
|
@@ -156,6 +163,7 @@ module CarrierWave
|
|
156
163
|
def retrieve_from_cache!(cache_name)
|
157
164
|
with_callbacks(:retrieve_from_cache, cache_name) do
|
158
165
|
self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
|
166
|
+
@staged = true
|
159
167
|
@filename = original_filename
|
160
168
|
@file = cache_storage.retrieve_from_cache!(full_filename(original_filename))
|
161
169
|
end
|
@@ -200,7 +208,7 @@ module CarrierWave
|
|
200
208
|
end
|
201
209
|
|
202
210
|
def cache_storage
|
203
|
-
@cache_storage ||= self.class.cache_storage.new(self)
|
211
|
+
@cache_storage ||= (self.class.cache_storage || self.class.storage).new(self)
|
204
212
|
end
|
205
213
|
end # Cache
|
206
214
|
end # Uploader
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'carrierwave/downloader/base'
|
2
|
+
|
1
3
|
module CarrierWave
|
2
4
|
|
3
5
|
module Uploader
|
@@ -21,9 +23,10 @@ module CarrierWave
|
|
21
23
|
add_config :move_to_cache
|
22
24
|
add_config :move_to_store
|
23
25
|
add_config :remove_previously_stored_files_after_update
|
26
|
+
add_config :downloader
|
24
27
|
|
25
28
|
# fog
|
26
|
-
|
29
|
+
add_deprecated_config :fog_provider
|
27
30
|
add_config :fog_attributes
|
28
31
|
add_config :fog_credentials
|
29
32
|
add_config :fog_directory
|
@@ -107,8 +110,8 @@ module CarrierWave
|
|
107
110
|
# cache_storage CarrierWave::Storage::File
|
108
111
|
# cache_storage MyCustomStorageEngine
|
109
112
|
#
|
110
|
-
def cache_storage(storage =
|
111
|
-
|
113
|
+
def cache_storage(storage = false)
|
114
|
+
unless storage == false
|
112
115
|
self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
|
113
116
|
end
|
114
117
|
_cache_storage
|
@@ -119,16 +122,8 @@ module CarrierWave
|
|
119
122
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
120
123
|
@#{name} = nil
|
121
124
|
|
122
|
-
def self.eager_load_fog(fog_credentials)
|
123
|
-
# see #1198. This will hopefully no longer be necessary after fog 2.0
|
124
|
-
require self.fog_provider
|
125
|
-
require 'carrierwave/storage/fog'
|
126
|
-
Fog::Storage.new(fog_credentials) if fog_credentials.present?
|
127
|
-
end unless defined? eager_load_fog
|
128
|
-
|
129
125
|
def self.#{name}(value=nil)
|
130
126
|
@#{name} = value if value
|
131
|
-
eager_load_fog(value) if value && '#{name}' == 'fog_credentials'
|
132
127
|
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
133
128
|
name = superclass.#{name}
|
134
129
|
return nil if name.nil? && !instance_variable_defined?(:@#{name})
|
@@ -136,12 +131,10 @@ module CarrierWave
|
|
136
131
|
end
|
137
132
|
|
138
133
|
def self.#{name}=(value)
|
139
|
-
eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
140
134
|
@#{name} = value
|
141
135
|
end
|
142
136
|
|
143
137
|
def #{name}=(value)
|
144
|
-
self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
145
138
|
@#{name} = value
|
146
139
|
end
|
147
140
|
|
@@ -157,6 +150,26 @@ module CarrierWave
|
|
157
150
|
RUBY
|
158
151
|
end
|
159
152
|
|
153
|
+
def add_deprecated_config(name)
|
154
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
155
|
+
def self.#{name}(value=nil)
|
156
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.#{name}=(value)
|
160
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
161
|
+
end
|
162
|
+
|
163
|
+
def #{name}=(value)
|
164
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
165
|
+
end
|
166
|
+
|
167
|
+
def #{name}
|
168
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
169
|
+
end
|
170
|
+
RUBY
|
171
|
+
end
|
172
|
+
|
160
173
|
def configure
|
161
174
|
yield self
|
162
175
|
end
|
@@ -173,8 +186,7 @@ module CarrierWave
|
|
173
186
|
:fog => "CarrierWave::Storage::Fog"
|
174
187
|
}
|
175
188
|
config.storage = :file
|
176
|
-
config.cache_storage =
|
177
|
-
config.fog_provider = 'fog'
|
189
|
+
config.cache_storage = nil
|
178
190
|
config.fog_attributes = {}
|
179
191
|
config.fog_credentials = {}
|
180
192
|
config.fog_public = true
|
@@ -187,6 +199,7 @@ module CarrierWave
|
|
187
199
|
config.move_to_cache = false
|
188
200
|
config.move_to_store = false
|
189
201
|
config.remove_previously_stored_files_after_update = true
|
202
|
+
config.downloader = CarrierWave::Downloader::Base
|
190
203
|
config.ignore_integrity_errors = true
|
191
204
|
config.ignore_processing_errors = true
|
192
205
|
config.ignore_download_errors = true
|
@@ -8,39 +8,48 @@ module CarrierWave
|
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
11
|
-
# Override this method in your uploader to provide a
|
11
|
+
# Override this method in your uploader to provide a denylist of files content types
|
12
12
|
# which are not allowed to be uploaded.
|
13
13
|
# Not only strings but Regexp are allowed as well.
|
14
14
|
#
|
15
15
|
# === Returns
|
16
16
|
#
|
17
|
-
# [NilClass, String, Regexp, Array[String, Regexp]] a
|
17
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] a denylist of content types which are not allowed to be uploaded
|
18
18
|
#
|
19
19
|
# === Examples
|
20
20
|
#
|
21
|
-
# def
|
21
|
+
# def content_type_denylist
|
22
22
|
# %w(text/json application/json)
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# Basically the same, but using a Regexp:
|
26
26
|
#
|
27
|
-
# def
|
27
|
+
# def content_type_denylist
|
28
28
|
# [/(text|application)\/json/]
|
29
29
|
# end
|
30
30
|
#
|
31
|
-
def
|
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
|
+
end
|
32
38
|
|
33
39
|
private
|
34
40
|
|
35
41
|
def check_content_type_blacklist!(new_file)
|
42
|
+
return unless content_type_denylist
|
43
|
+
|
36
44
|
content_type = new_file.content_type
|
37
|
-
if
|
38
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error",
|
45
|
+
if blacklisted_content_type?(content_type)
|
46
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error",
|
47
|
+
content_type: content_type, default: :"errors.messages.content_type_denylist_error")
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
42
51
|
def blacklisted_content_type?(content_type)
|
43
|
-
Array(
|
52
|
+
Array(content_type_denylist).any? { |item| content_type =~ /#{item}/ }
|
44
53
|
end
|
45
54
|
|
46
55
|
end # ContentTypeBlacklist
|
@@ -8,39 +8,51 @@ module CarrierWave
|
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
11
|
-
# Override this method in your uploader to provide
|
11
|
+
# Override this method in your uploader to provide an allowlist of files content types
|
12
12
|
# which are allowed to be uploaded.
|
13
13
|
# Not only strings but Regexp are allowed as well.
|
14
14
|
#
|
15
15
|
# === Returns
|
16
16
|
#
|
17
|
-
# [NilClass, String, Regexp, Array[String, Regexp]]
|
17
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of content types which are allowed to be uploaded
|
18
18
|
#
|
19
19
|
# === Examples
|
20
20
|
#
|
21
|
-
# def
|
21
|
+
# def content_type_allowlist
|
22
22
|
# %w(text/json application/json)
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# Basically the same, but using a Regexp:
|
26
26
|
#
|
27
|
-
# def
|
27
|
+
# def content_type_allowlist
|
28
28
|
# [/(text|application)\/json/]
|
29
29
|
# end
|
30
30
|
#
|
31
|
-
def
|
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
|
+
end
|
32
38
|
|
33
39
|
private
|
34
40
|
|
35
41
|
def check_content_type_whitelist!(new_file)
|
42
|
+
return unless content_type_allowlist
|
43
|
+
|
36
44
|
content_type = new_file.content_type
|
37
|
-
if
|
38
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: 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")
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
42
51
|
def whitelisted_content_type?(content_type)
|
43
|
-
Array(
|
52
|
+
Array(content_type_allowlist).any? do |item|
|
53
|
+
item = Regexp.quote(item) if item.class != Regexp
|
54
|
+
content_type =~ /#{item}/
|
55
|
+
end
|
44
56
|
end
|
45
57
|
|
46
58
|
end # ContentTypeWhitelist
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'ssrf_filter'
|
3
|
-
|
4
1
|
module CarrierWave
|
5
2
|
module Uploader
|
6
3
|
module Download
|
@@ -10,87 +7,8 @@ module CarrierWave
|
|
10
7
|
include CarrierWave::Uploader::Configuration
|
11
8
|
include CarrierWave::Uploader::Cache
|
12
9
|
|
13
|
-
class RemoteFile
|
14
|
-
attr_reader :uri
|
15
|
-
|
16
|
-
def initialize(uri, remote_headers = {}, skip_ssrf_protection: false)
|
17
|
-
@uri = uri
|
18
|
-
@remote_headers = remote_headers.reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
|
19
|
-
@file, @content_type, @headers = nil
|
20
|
-
@skip_ssrf_protection = skip_ssrf_protection
|
21
|
-
end
|
22
|
-
|
23
|
-
def original_filename
|
24
|
-
filename = filename_from_header || filename_from_uri
|
25
|
-
mime_type = MIME::Types[content_type].first
|
26
|
-
unless File.extname(filename).present? || mime_type.blank?
|
27
|
-
filename = "#{filename}.#{mime_type.extensions.first}"
|
28
|
-
end
|
29
|
-
filename
|
30
|
-
end
|
31
|
-
|
32
|
-
def respond_to?(*args)
|
33
|
-
super or file.respond_to?(*args)
|
34
|
-
end
|
35
|
-
|
36
|
-
def http?
|
37
|
-
@uri.scheme =~ /^https?$/
|
38
|
-
end
|
39
|
-
|
40
|
-
def content_type
|
41
|
-
@content_type || 'application/octet-stream'
|
42
|
-
end
|
43
|
-
|
44
|
-
def headers
|
45
|
-
@headers || {}
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def file
|
51
|
-
if @file.blank?
|
52
|
-
if @skip_ssrf_protection
|
53
|
-
@file = (URI.respond_to?(:open) ? URI : Kernel).open(@uri.to_s, @remote_headers)
|
54
|
-
@file = @file.is_a?(String) ? StringIO.new(@file) : @file
|
55
|
-
@content_type = @file.content_type
|
56
|
-
@headers = @file.meta
|
57
|
-
@uri = @file.base_uri
|
58
|
-
else
|
59
|
-
request = nil
|
60
|
-
response = SsrfFilter.get(@uri, headers: @remote_headers) do |req|
|
61
|
-
request = req
|
62
|
-
end
|
63
|
-
response.value
|
64
|
-
@file = StringIO.new(response.body)
|
65
|
-
@content_type = response.content_type
|
66
|
-
@headers = response
|
67
|
-
@uri = request.uri
|
68
|
-
end
|
69
|
-
end
|
70
|
-
@file
|
71
|
-
|
72
|
-
rescue StandardError => e
|
73
|
-
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
|
74
|
-
end
|
75
|
-
|
76
|
-
def filename_from_header
|
77
|
-
if headers['content-disposition']
|
78
|
-
match = headers['content-disposition'].match(/filename="?([^"]+)/)
|
79
|
-
return match[1] unless match.nil? || match[1].empty?
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def filename_from_uri
|
84
|
-
URI::DEFAULT_PARSER.unescape(File.basename(@uri.path))
|
85
|
-
end
|
86
|
-
|
87
|
-
def method_missing(*args, &block)
|
88
|
-
file.send(*args, &block)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
10
|
##
|
93
|
-
# Caches the file by downloading it from the given URL.
|
11
|
+
# Caches the file by downloading it from the given URL, using downloader.
|
94
12
|
#
|
95
13
|
# === Parameters
|
96
14
|
#
|
@@ -98,48 +16,9 @@ module CarrierWave
|
|
98
16
|
# [remote_headers (Hash)] Request headers
|
99
17
|
#
|
100
18
|
def download!(uri, remote_headers = {})
|
101
|
-
|
102
|
-
file = RemoteFile.new(processed_uri, remote_headers, skip_ssrf_protection: skip_ssrf_protection?(processed_uri))
|
103
|
-
raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
|
19
|
+
file = downloader.new(self).download(uri, remote_headers)
|
104
20
|
cache!(file)
|
105
21
|
end
|
106
|
-
|
107
|
-
##
|
108
|
-
# Processes the given URL by parsing and escaping it. Public to allow overriding.
|
109
|
-
#
|
110
|
-
# === Parameters
|
111
|
-
#
|
112
|
-
# [url (String)] The URL where the remote file is stored
|
113
|
-
#
|
114
|
-
def process_uri(uri)
|
115
|
-
URI.parse(uri)
|
116
|
-
rescue URI::InvalidURIError
|
117
|
-
uri_parts = uri.split('?')
|
118
|
-
# regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
|
119
|
-
encoded_uri = URI::DEFAULT_PARSER.escape(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
|
120
|
-
encoded_uri << '?' << URI::DEFAULT_PARSER.escape(uri_parts.join('?')) if uri_parts.any?
|
121
|
-
URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
|
122
|
-
end
|
123
|
-
|
124
|
-
##
|
125
|
-
# If this returns true, SSRF protection will be bypassed.
|
126
|
-
# You can override this if you want to allow accessing specific local URIs that are not SSRF exploitable.
|
127
|
-
#
|
128
|
-
# === Parameters
|
129
|
-
#
|
130
|
-
# [uri (URI)] The URI where the remote file is stored
|
131
|
-
#
|
132
|
-
# === Examples
|
133
|
-
#
|
134
|
-
# class MyUploader < CarrierWave::Uploader::Base
|
135
|
-
# def skip_ssrf_protection?(uri)
|
136
|
-
# uri.hostname == 'localhost' && uri.port == 80
|
137
|
-
# end
|
138
|
-
# end
|
139
|
-
#
|
140
|
-
def skip_ssrf_protection?(uri)
|
141
|
-
false
|
142
|
-
end
|
143
22
|
end # Download
|
144
23
|
end # Uploader
|
145
24
|
end # CarrierWave
|