carrierwave 0.9.0 → 3.0.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 +7 -0
- data/README.md +508 -158
- data/lib/carrierwave/compatibility/paperclip.rb +31 -21
- data/lib/carrierwave/downloader/base.rb +101 -0
- data/lib/carrierwave/downloader/remote_file.rb +68 -0
- data/lib/carrierwave/error.rb +1 -0
- data/lib/carrierwave/locale/en.yml +11 -5
- data/lib/carrierwave/mount.rb +220 -187
- data/lib/carrierwave/mounter.rb +255 -0
- data/lib/carrierwave/orm/activerecord.rb +24 -34
- data/lib/carrierwave/processing/mini_magick.rb +142 -79
- data/lib/carrierwave/processing/rmagick.rb +76 -35
- data/lib/carrierwave/processing/vips.rb +284 -0
- data/lib/carrierwave/processing.rb +1 -1
- data/lib/carrierwave/sanitized_file.rb +89 -70
- data/lib/carrierwave/storage/abstract.rb +16 -3
- data/lib/carrierwave/storage/file.rb +71 -3
- data/lib/carrierwave/storage/fog.rb +215 -58
- data/lib/carrierwave/storage.rb +1 -7
- data/lib/carrierwave/test/matchers.rb +88 -19
- data/lib/carrierwave/uploader/cache.rb +88 -44
- data/lib/carrierwave/uploader/callbacks.rb +1 -3
- data/lib/carrierwave/uploader/configuration.rb +81 -9
- data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
- data/lib/carrierwave/uploader/content_type_denylist.rb +62 -0
- data/lib/carrierwave/uploader/default_url.rb +3 -5
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/download.rb +5 -69
- data/lib/carrierwave/uploader/extension_allowlist.rb +63 -0
- data/lib/carrierwave/uploader/extension_denylist.rb +64 -0
- data/lib/carrierwave/uploader/file_size.rb +43 -0
- data/lib/carrierwave/uploader/mountable.rb +13 -8
- data/lib/carrierwave/uploader/processing.rb +54 -21
- data/lib/carrierwave/uploader/proxy.rb +30 -8
- data/lib/carrierwave/uploader/remove.rb +0 -2
- data/lib/carrierwave/uploader/serialization.rb +3 -5
- data/lib/carrierwave/uploader/store.rb +59 -28
- data/lib/carrierwave/uploader/url.rb +8 -7
- data/lib/carrierwave/uploader/versions.rb +173 -124
- data/lib/carrierwave/uploader.rb +12 -6
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities/uri.rb +14 -12
- data/lib/carrierwave/utilities.rb +2 -3
- data/lib/carrierwave/validations/active_model.rb +7 -13
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +41 -16
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +5 -9
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +224 -100
- data/lib/carrierwave/locale/cs.yml +0 -11
- data/lib/carrierwave/locale/de.yml +0 -11
- data/lib/carrierwave/locale/nl.yml +0 -11
- data/lib/carrierwave/locale/sk.yml +0 -11
- data/lib/carrierwave/processing/mime_types.rb +0 -73
- data/lib/carrierwave/uploader/extension_blacklist.rb +0 -47
- data/lib/carrierwave/uploader/extension_whitelist.rb +0 -49
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'carrierwave/downloader/base'
|
2
|
+
|
1
3
|
module CarrierWave
|
2
4
|
|
3
5
|
module Uploader
|
@@ -5,7 +7,7 @@ module CarrierWave
|
|
5
7
|
extend ActiveSupport::Concern
|
6
8
|
|
7
9
|
included do
|
8
|
-
class_attribute :_storage, :instance_writer => false
|
10
|
+
class_attribute :_storage, :_cache_storage, :instance_writer => false
|
9
11
|
|
10
12
|
add_config :root
|
11
13
|
add_config :base_path
|
@@ -21,14 +23,18 @@ 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
|
27
|
+
add_config :force_extension
|
24
28
|
|
25
29
|
# fog
|
30
|
+
add_deprecated_config :fog_provider
|
26
31
|
add_config :fog_attributes
|
27
32
|
add_config :fog_credentials
|
28
33
|
add_config :fog_directory
|
29
34
|
add_config :fog_public
|
30
35
|
add_config :fog_authenticated_url_expiration
|
31
36
|
add_config :fog_use_ssl_for_aws
|
37
|
+
add_config :fog_aws_accelerate
|
32
38
|
|
33
39
|
# Mounting
|
34
40
|
add_config :ignore_integrity_errors
|
@@ -38,6 +44,9 @@ module CarrierWave
|
|
38
44
|
add_config :validate_processing
|
39
45
|
add_config :validate_download
|
40
46
|
add_config :mount_on
|
47
|
+
add_config :cache_only
|
48
|
+
add_config :download_retry_count
|
49
|
+
add_config :download_retry_wait_time
|
41
50
|
|
42
51
|
# set default values
|
43
52
|
reset_config
|
@@ -69,20 +78,58 @@ module CarrierWave
|
|
69
78
|
# storage MyCustomStorageEngine
|
70
79
|
#
|
71
80
|
def storage(storage = nil)
|
72
|
-
|
73
|
-
|
81
|
+
case storage
|
82
|
+
when Symbol
|
83
|
+
if (storage_engine = storage_engines[storage])
|
84
|
+
self._storage = eval storage_engine
|
85
|
+
else
|
86
|
+
raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
|
87
|
+
end
|
88
|
+
when nil
|
89
|
+
storage
|
90
|
+
else
|
91
|
+
self._storage = storage
|
74
92
|
end
|
75
93
|
_storage
|
76
94
|
end
|
77
95
|
alias_method :storage=, :storage
|
78
96
|
|
97
|
+
##
|
98
|
+
# Sets the cache storage engine to be used when storing cache files with this uploader.
|
99
|
+
# Same as .storage except for required methods being #cache!(CarrierWave::SanitizedFile),
|
100
|
+
# #retrieve_from_cache! and #delete_dir!.
|
101
|
+
#
|
102
|
+
# === Parameters
|
103
|
+
#
|
104
|
+
# [storage (Symbol, Class)] The cache storage engine to use for this uploader
|
105
|
+
#
|
106
|
+
# === Returns
|
107
|
+
#
|
108
|
+
# [Class] the cache storage engine to be used with this uploader
|
109
|
+
#
|
110
|
+
# === Examples
|
111
|
+
#
|
112
|
+
# cache_storage :file
|
113
|
+
# cache_storage CarrierWave::Storage::File
|
114
|
+
# cache_storage MyCustomStorageEngine
|
115
|
+
#
|
116
|
+
def cache_storage(storage = false)
|
117
|
+
unless storage == false
|
118
|
+
self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
|
119
|
+
end
|
120
|
+
_cache_storage
|
121
|
+
end
|
122
|
+
alias_method :cache_storage=, :cache_storage
|
123
|
+
|
79
124
|
def add_config(name)
|
80
125
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
126
|
+
@#{name} = nil
|
127
|
+
|
81
128
|
def self.#{name}(value=nil)
|
82
|
-
@#{name} = value
|
129
|
+
@#{name} = value unless value.nil?
|
83
130
|
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
84
131
|
name = superclass.#{name}
|
85
|
-
return nil if name.nil? && !instance_variable_defined?(
|
132
|
+
return nil if name.nil? && !instance_variable_defined?(:@#{name})
|
86
133
|
@#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
|
87
134
|
end
|
88
135
|
|
@@ -99,13 +146,33 @@ module CarrierWave
|
|
99
146
|
value = self.class.#{name} unless instance_variable_defined?(:@#{name})
|
100
147
|
if value.instance_of?(Proc)
|
101
148
|
value.arity >= 1 ? value.call(self) : value.call
|
102
|
-
else
|
149
|
+
else
|
103
150
|
value
|
104
151
|
end
|
105
152
|
end
|
106
153
|
RUBY
|
107
154
|
end
|
108
155
|
|
156
|
+
def add_deprecated_config(name)
|
157
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
158
|
+
def self.#{name}(value=nil)
|
159
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.#{name}=(value)
|
163
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
164
|
+
end
|
165
|
+
|
166
|
+
def #{name}=(value)
|
167
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
168
|
+
end
|
169
|
+
|
170
|
+
def #{name}
|
171
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
172
|
+
end
|
173
|
+
RUBY
|
174
|
+
end
|
175
|
+
|
109
176
|
def configure
|
110
177
|
yield self
|
111
178
|
end
|
@@ -115,24 +182,28 @@ module CarrierWave
|
|
115
182
|
#
|
116
183
|
def reset_config
|
117
184
|
configure do |config|
|
118
|
-
config.permissions =
|
119
|
-
config.directory_permissions =
|
185
|
+
config.permissions = 0o644
|
186
|
+
config.directory_permissions = 0o755
|
120
187
|
config.storage_engines = {
|
121
188
|
:file => "CarrierWave::Storage::File",
|
122
189
|
:fog => "CarrierWave::Storage::Fog"
|
123
190
|
}
|
124
191
|
config.storage = :file
|
192
|
+
config.cache_storage = nil
|
125
193
|
config.fog_attributes = {}
|
126
194
|
config.fog_credentials = {}
|
127
195
|
config.fog_public = true
|
128
196
|
config.fog_authenticated_url_expiration = 600
|
129
197
|
config.fog_use_ssl_for_aws = true
|
198
|
+
config.fog_aws_accelerate = false
|
130
199
|
config.store_dir = 'uploads'
|
131
200
|
config.cache_dir = 'uploads/tmp'
|
132
201
|
config.delete_tmp_file_after_storage = true
|
133
202
|
config.move_to_cache = false
|
134
203
|
config.move_to_store = false
|
135
204
|
config.remove_previously_stored_files_after_update = true
|
205
|
+
config.downloader = CarrierWave::Downloader::Base
|
206
|
+
config.force_extension = false
|
136
207
|
config.ignore_integrity_errors = true
|
137
208
|
config.ignore_processing_errors = true
|
138
209
|
config.ignore_download_errors = true
|
@@ -143,6 +214,8 @@ module CarrierWave
|
|
143
214
|
config.base_path = CarrierWave.base_path
|
144
215
|
config.enable_processing = true
|
145
216
|
config.ensure_multipart_form = true
|
217
|
+
config.download_retry_count = 0
|
218
|
+
config.download_retry_wait_time = 5
|
146
219
|
end
|
147
220
|
end
|
148
221
|
end
|
@@ -150,4 +223,3 @@ module CarrierWave
|
|
150
223
|
end
|
151
224
|
end
|
152
225
|
end
|
153
|
-
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Uploader
|
3
|
+
module ContentTypeAllowlist
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before :cache, :check_content_type_allowlist!
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Override this method in your uploader to provide an allowlist of files content types
|
12
|
+
# which are allowed to be uploaded.
|
13
|
+
# Not only strings but Regexp are allowed as well.
|
14
|
+
#
|
15
|
+
# === Returns
|
16
|
+
#
|
17
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of content types which are allowed to be uploaded
|
18
|
+
#
|
19
|
+
# === Examples
|
20
|
+
#
|
21
|
+
# def content_type_allowlist
|
22
|
+
# %w(text/json application/json)
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Basically the same, but using a Regexp:
|
26
|
+
#
|
27
|
+
# def content_type_allowlist
|
28
|
+
# [/(text|application)\/json/]
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
def content_type_allowlist
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
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
|
+
ActiveSupport::Deprecation.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
|
45
|
+
|
46
|
+
content_type = new_file.content_type
|
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")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def allowlisted_content_type?(allowlist, content_type)
|
54
|
+
Array(allowlist).any? do |item|
|
55
|
+
item = Regexp.quote(item) if item.class != Regexp
|
56
|
+
content_type =~ /#{item}/
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end # ContentTypeAllowlist
|
61
|
+
end # Uploader
|
62
|
+
end # CarrierWave
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Uploader
|
3
|
+
module ContentTypeDenylist
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before :cache, :check_content_type_denylist!
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Override this method in your uploader to provide a denylist of files content types
|
12
|
+
# which are not allowed to be uploaded.
|
13
|
+
# Not only strings but Regexp are allowed as well.
|
14
|
+
#
|
15
|
+
# === Returns
|
16
|
+
#
|
17
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] a denylist of content types which are not allowed to be uploaded
|
18
|
+
#
|
19
|
+
# === Examples
|
20
|
+
#
|
21
|
+
# def content_type_denylist
|
22
|
+
# %w(text/json application/json)
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Basically the same, but using a Regexp:
|
26
|
+
#
|
27
|
+
# def content_type_denylist
|
28
|
+
# [/(text|application)\/json/]
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
def content_type_denylist
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
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
|
+
ActiveSupport::Deprecation.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
|
+
ActiveSupport::Deprecation.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
|
48
|
+
|
49
|
+
content_type = new_file.content_type
|
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")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def denylisted_content_type?(denylist, content_type)
|
57
|
+
Array(denylist).any? { |item| content_type =~ /#{item}/ }
|
58
|
+
end
|
59
|
+
|
60
|
+
end # ContentTypeDenylist
|
61
|
+
end # Uploader
|
62
|
+
end # CarrierWave
|
@@ -1,19 +1,17 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Uploader
|
5
3
|
module DefaultUrl
|
6
4
|
|
7
5
|
def url(*args)
|
8
|
-
super || default_url
|
6
|
+
super || default_url(*args)
|
9
7
|
end
|
10
8
|
|
11
9
|
##
|
12
10
|
# Override this method in your uploader to provide a default url
|
13
11
|
# in case no file has been cached/stored yet.
|
14
12
|
#
|
15
|
-
def default_url; end
|
13
|
+
def default_url(*args); end
|
16
14
|
|
17
15
|
end # DefaultPath
|
18
16
|
end # Uploader
|
19
|
-
end # CarrierWave
|
17
|
+
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,7 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'open-uri'
|
4
|
-
|
5
1
|
module CarrierWave
|
6
2
|
module Uploader
|
7
3
|
module Download
|
@@ -11,78 +7,18 @@ module CarrierWave
|
|
11
7
|
include CarrierWave::Uploader::Configuration
|
12
8
|
include CarrierWave::Uploader::Cache
|
13
9
|
|
14
|
-
class RemoteFile
|
15
|
-
def initialize(uri)
|
16
|
-
@uri = uri
|
17
|
-
end
|
18
|
-
|
19
|
-
def original_filename
|
20
|
-
if file.meta.include? 'content-disposition'
|
21
|
-
match = file.meta['content-disposition'].match(/filename=(\"?)(.+)\1/)
|
22
|
-
return match[2] unless match.nil?
|
23
|
-
end
|
24
|
-
File.basename(file.base_uri.path)
|
25
|
-
end
|
26
|
-
|
27
|
-
def respond_to?(*args)
|
28
|
-
super or file.respond_to?(*args)
|
29
|
-
end
|
30
|
-
|
31
|
-
def http?
|
32
|
-
@uri.scheme =~ /^https?$/
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def file
|
38
|
-
if @file.blank?
|
39
|
-
@file = Kernel.open(@uri.to_s)
|
40
|
-
@file = @file.is_a?(String) ? StringIO.new(@file) : @file
|
41
|
-
end
|
42
|
-
@file
|
43
|
-
|
44
|
-
rescue Exception => e
|
45
|
-
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
|
46
|
-
end
|
47
|
-
|
48
|
-
def method_missing(*args, &block)
|
49
|
-
file.send(*args, &block)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
##
|
54
|
-
# Caches the file by downloading it from the given URL.
|
55
|
-
#
|
56
|
-
# === Parameters
|
57
|
-
#
|
58
|
-
# [url (String)] The URL where the remote file is stored
|
59
|
-
#
|
60
|
-
def download!(uri)
|
61
|
-
unless uri.blank?
|
62
|
-
processed_uri = process_uri(uri)
|
63
|
-
file = RemoteFile.new(processed_uri)
|
64
|
-
raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
|
65
|
-
cache!(file)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
10
|
##
|
70
|
-
#
|
11
|
+
# Caches the file by downloading it from the given URL, using downloader.
|
71
12
|
#
|
72
13
|
# === Parameters
|
73
14
|
#
|
74
15
|
# [url (String)] The URL where the remote file is stored
|
16
|
+
# [remote_headers (Hash)] Request headers
|
75
17
|
#
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
uri_parts = uri.split('?')
|
80
|
-
# regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
|
81
|
-
encoded_uri = URI.encode(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
|
82
|
-
encoded_uri << '?' << URI.encode(uri_parts.join('?')) if uri_parts.any?
|
83
|
-
URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
|
18
|
+
def download!(uri, remote_headers = {})
|
19
|
+
file = downloader.new(self).download(uri, remote_headers)
|
20
|
+
cache!(file)
|
84
21
|
end
|
85
|
-
|
86
22
|
end # Download
|
87
23
|
end # Uploader
|
88
24
|
end # CarrierWave
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Uploader
|
3
|
+
module ExtensionAllowlist
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before :cache, :check_extension_allowlist!
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Override this method in your uploader to provide an allowlist of extensions which
|
12
|
+
# are allowed to be uploaded. Compares the file's extension case insensitive.
|
13
|
+
# Furthermore, not only strings but Regexp are allowed as well.
|
14
|
+
#
|
15
|
+
# When using a Regexp in the allowlist, `\A` and `\z` are automatically added to
|
16
|
+
# the Regexp expression, also case insensitive.
|
17
|
+
#
|
18
|
+
# === Returns
|
19
|
+
#
|
20
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of extensions which are allowed to be uploaded
|
21
|
+
#
|
22
|
+
# === Examples
|
23
|
+
#
|
24
|
+
# def extension_allowlist
|
25
|
+
# %w(jpg jpeg gif png)
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Basically the same, but using a Regexp:
|
29
|
+
#
|
30
|
+
# def extension_allowlist
|
31
|
+
# [/jpe?g/, 'gif', 'png']
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
def extension_allowlist
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def check_extension_allowlist!(new_file)
|
40
|
+
allowlist = extension_allowlist
|
41
|
+
if !allowlist && respond_to?(:extension_whitelist) && extension_whitelist
|
42
|
+
ActiveSupport::Deprecation.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
|
48
|
+
|
49
|
+
extension = new_file.extension.to_s
|
50
|
+
if !allowlisted_extension?(allowlist, extension)
|
51
|
+
# Look for whitelist first, then fallback to allowlist
|
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")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def allowlisted_extension?(allowlist, extension)
|
58
|
+
downcase_extension = extension.downcase
|
59
|
+
Array(allowlist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
|
60
|
+
end
|
61
|
+
end # ExtensionAllowlist
|
62
|
+
end # Uploader
|
63
|
+
end # CarrierWave
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Uploader
|
3
|
+
module ExtensionDenylist
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before :cache, :check_extension_denylist!
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Override this method in your uploader to provide a denylist of extensions which
|
12
|
+
# are prohibited to be uploaded. Compares the file's extension case insensitive.
|
13
|
+
# Furthermore, not only strings but Regexp are allowed as well.
|
14
|
+
#
|
15
|
+
# When using a Regexp in the denylist, `\A` and `\z` are automatically added to
|
16
|
+
# the Regexp expression, also case insensitive.
|
17
|
+
#
|
18
|
+
# === Returns
|
19
|
+
|
20
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] a deny list of extensions which are prohibited to be uploaded
|
21
|
+
#
|
22
|
+
# === Examples
|
23
|
+
#
|
24
|
+
# def extension_denylist
|
25
|
+
# %w(swf tiff)
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Basically the same, but using a Regexp:
|
29
|
+
#
|
30
|
+
# def extension_denylist
|
31
|
+
# [/swf/, 'tiff']
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
def extension_denylist
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def check_extension_denylist!(new_file)
|
40
|
+
denylist = extension_denylist
|
41
|
+
if !denylist && respond_to?(:extension_blacklist) && extension_blacklist
|
42
|
+
ActiveSupport::Deprecation.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
|
+
ActiveSupport::Deprecation.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
|
51
|
+
|
52
|
+
extension = new_file.extension.to_s
|
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")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def denylisted_extension?(denylist, extension)
|
60
|
+
Array(denylist).any? { |item| extension =~ /\A#{item}\z/i }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module FileSize
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
before :cache, :check_size!
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Override this method in your uploader to provide a Range of Size which
|
14
|
+
# are allowed to be uploaded.
|
15
|
+
# === Returns
|
16
|
+
#
|
17
|
+
# [NilClass, Range] a size range (in bytes) which are permitted to be uploaded
|
18
|
+
#
|
19
|
+
# === Examples
|
20
|
+
#
|
21
|
+
# def size_range
|
22
|
+
# 3256...5748
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
def size_range; end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def check_size!(new_file)
|
30
|
+
size = new_file.size
|
31
|
+
expected_size_range = size_range
|
32
|
+
if expected_size_range.is_a?(::Range)
|
33
|
+
if size < expected_size_range.min
|
34
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_size_error", :min_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.min))
|
35
|
+
elsif size > expected_size_range.max
|
36
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_size_error", :max_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.max))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # FileSize
|
42
|
+
end # Uploader
|
43
|
+
end # CarrierWave
|