carrierwave 0.11.2 → 1.3.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 +5 -5
- data/README.md +255 -125
- data/lib/carrierwave/compatibility/paperclip.rb +0 -2
- data/lib/carrierwave/error.rb +1 -0
- data/lib/carrierwave/locale/en.yml +7 -4
- data/lib/carrierwave/mount.rb +219 -176
- data/lib/carrierwave/mounter.rb +165 -0
- data/lib/carrierwave/orm/activerecord.rb +50 -21
- data/lib/carrierwave/processing/mini_magick.rb +86 -15
- data/lib/carrierwave/processing/rmagick.rb +63 -8
- data/lib/carrierwave/processing.rb +0 -1
- data/lib/carrierwave/sanitized_file.rb +51 -46
- data/lib/carrierwave/storage/abstract.rb +15 -2
- data/lib/carrierwave/storage/file.rb +69 -2
- data/lib/carrierwave/storage/fog.rb +152 -33
- data/lib/carrierwave/storage.rb +0 -9
- data/lib/carrierwave/test/matchers.rb +77 -12
- data/lib/carrierwave/uploader/cache.rb +41 -27
- data/lib/carrierwave/uploader/callbacks.rb +0 -2
- data/lib/carrierwave/uploader/configuration.rb +54 -9
- data/lib/carrierwave/uploader/content_type_whitelist.rb +1 -1
- data/lib/carrierwave/uploader/default_url.rb +3 -5
- data/lib/carrierwave/uploader/download.rb +66 -15
- data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
- data/lib/carrierwave/uploader/extension_whitelist.rb +13 -10
- data/lib/carrierwave/uploader/file_size.rb +43 -0
- data/lib/carrierwave/uploader/mountable.rb +7 -8
- data/lib/carrierwave/uploader/processing.rb +10 -10
- data/lib/carrierwave/uploader/proxy.rb +5 -7
- data/lib/carrierwave/uploader/remove.rb +0 -2
- data/lib/carrierwave/uploader/serialization.rb +1 -3
- data/lib/carrierwave/uploader/store.rb +14 -23
- data/lib/carrierwave/uploader/url.rb +3 -5
- data/lib/carrierwave/uploader/versions.rb +82 -82
- data/lib/carrierwave/uploader.rb +11 -2
- data/lib/carrierwave/utilities/uri.rb +5 -6
- data/lib/carrierwave/utilities.rb +0 -3
- data/lib/carrierwave/validations/active_model.rb +3 -5
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +32 -10
- data/lib/generators/templates/uploader.rb +4 -8
- metadata +64 -79
- data/lib/carrierwave/locale/cs.yml +0 -11
- data/lib/carrierwave/locale/de.yml +0 -11
- data/lib/carrierwave/locale/el.yml +0 -11
- data/lib/carrierwave/locale/es.yml +0 -11
- data/lib/carrierwave/locale/fr.yml +0 -11
- data/lib/carrierwave/locale/ja.yml +0 -11
- data/lib/carrierwave/locale/nb.yml +0 -11
- data/lib/carrierwave/locale/nl.yml +0 -11
- data/lib/carrierwave/locale/pl.yml +0 -11
- data/lib/carrierwave/locale/pt-BR.yml +0 -11
- data/lib/carrierwave/locale/pt-PT.yml +0 -11
- data/lib/carrierwave/locale/ru.yml +0 -11
- data/lib/carrierwave/locale/sk.yml +0 -11
- data/lib/carrierwave/locale/tr.yml +0 -11
- data/lib/carrierwave/processing/mime_types.rb +0 -74
- data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
|
5
3
|
class FormNotMultipart < UploadError
|
@@ -54,13 +52,7 @@ module CarrierWave
|
|
54
52
|
# It's recommended that you keep cache files in one place only.
|
55
53
|
#
|
56
54
|
def clean_cached_files!(seconds=60*60*24)
|
57
|
-
|
58
|
-
time = dir.scan(/(\d+)-\d+-\d+/).first.map { |t| t.to_i }
|
59
|
-
time = Time.at(*time)
|
60
|
-
if time < (Time.now.utc - seconds)
|
61
|
-
FileUtils.rm_rf(dir)
|
62
|
-
end
|
63
|
-
end
|
55
|
+
cache_storage.new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
|
64
56
|
end
|
65
57
|
end
|
66
58
|
|
@@ -89,10 +81,8 @@ module CarrierWave
|
|
89
81
|
_content = file.read
|
90
82
|
if _content.is_a?(File) # could be if storage is Fog
|
91
83
|
sanitized = CarrierWave::Storage::Fog.new(self).retrieve!(File.basename(_content.path))
|
92
|
-
sanitized.read if sanitized.exists?
|
93
|
-
|
94
84
|
else
|
95
|
-
sanitized = SanitizedFile.new :tempfile => StringIO.new(
|
85
|
+
sanitized = SanitizedFile.new :tempfile => StringIO.new(_content),
|
96
86
|
:filename => File.basename(path), :content_type => file.content_type
|
97
87
|
end
|
98
88
|
sanitized
|
@@ -127,22 +117,28 @@ module CarrierWave
|
|
127
117
|
#
|
128
118
|
def cache!(new_file = sanitized_file)
|
129
119
|
new_file = CarrierWave::SanitizedFile.new(new_file)
|
120
|
+
return if new_file.empty?
|
121
|
+
|
122
|
+
raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
|
130
123
|
|
131
|
-
unless
|
132
|
-
raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
|
124
|
+
self.cache_id = CarrierWave.generate_cache_id unless cache_id
|
133
125
|
|
134
|
-
|
135
|
-
|
126
|
+
@filename = new_file.filename
|
127
|
+
self.original_filename = new_file.filename
|
136
128
|
|
137
|
-
|
138
|
-
|
129
|
+
begin
|
130
|
+
# first, create a workfile on which we perform processings
|
131
|
+
if move_to_cache
|
132
|
+
@file = new_file.move_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
|
133
|
+
else
|
134
|
+
@file = new_file.copy_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
|
135
|
+
end
|
139
136
|
|
140
|
-
|
141
|
-
|
142
|
-
else
|
143
|
-
@file = new_file.copy_to(cache_path, permissions, directory_permissions)
|
144
|
-
end
|
137
|
+
with_callbacks(:cache, @file) do
|
138
|
+
@file = cache_storage.cache!(@file)
|
145
139
|
end
|
140
|
+
ensure
|
141
|
+
FileUtils.rm_rf(workfile_path(''))
|
146
142
|
end
|
147
143
|
end
|
148
144
|
|
@@ -161,14 +157,29 @@ module CarrierWave
|
|
161
157
|
with_callbacks(:retrieve_from_cache, cache_name) do
|
162
158
|
self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
|
163
159
|
@filename = original_filename
|
164
|
-
@file =
|
160
|
+
@file = cache_storage.retrieve_from_cache!(full_filename(original_filename))
|
165
161
|
end
|
166
162
|
end
|
167
163
|
|
164
|
+
##
|
165
|
+
# Calculates the path where the cache file should be stored.
|
166
|
+
#
|
167
|
+
# === Parameters
|
168
|
+
#
|
169
|
+
# [for_file (String)] name of the file <optional>
|
170
|
+
#
|
171
|
+
# === Returns
|
172
|
+
#
|
173
|
+
# [String] the cache path
|
174
|
+
#
|
175
|
+
def cache_path(for_file=full_filename(original_filename))
|
176
|
+
File.join(*[cache_dir, @cache_id, for_file].compact)
|
177
|
+
end
|
178
|
+
|
168
179
|
private
|
169
180
|
|
170
|
-
def
|
171
|
-
File.
|
181
|
+
def workfile_path(for_file=original_filename)
|
182
|
+
File.join(CarrierWave.tmp_path, @cache_id, version_name.to_s, for_file)
|
172
183
|
end
|
173
184
|
|
174
185
|
attr_reader :cache_id, :original_filename
|
@@ -179,7 +190,7 @@ module CarrierWave
|
|
179
190
|
def cache_id=(cache_id)
|
180
191
|
# Earlier version used 3 part cache_id. Thus we should allow for
|
181
192
|
# the cache_id to have both 3 part and 4 part formats.
|
182
|
-
raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A[\d]+\-[\d]+(\-[\d]{4})?\-[\d]{4}\z/
|
193
|
+
raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A(-)?[\d]+\-[\d]+(\-[\d]{4})?\-[\d]{4}\z/
|
183
194
|
@cache_id = cache_id
|
184
195
|
end
|
185
196
|
|
@@ -188,6 +199,9 @@ module CarrierWave
|
|
188
199
|
@original_filename = filename
|
189
200
|
end
|
190
201
|
|
202
|
+
def cache_storage
|
203
|
+
@cache_storage ||= self.class.cache_storage.new(self)
|
204
|
+
end
|
191
205
|
end # Cache
|
192
206
|
end # Uploader
|
193
207
|
end # CarrierWave
|
@@ -5,7 +5,7 @@ module CarrierWave
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
class_attribute :_storage, :instance_writer => false
|
8
|
+
class_attribute :_storage, :_cache_storage, :instance_writer => false
|
9
9
|
|
10
10
|
add_config :root
|
11
11
|
add_config :base_path
|
@@ -23,12 +23,14 @@ module CarrierWave
|
|
23
23
|
add_config :remove_previously_stored_files_after_update
|
24
24
|
|
25
25
|
# fog
|
26
|
+
add_config :fog_provider
|
26
27
|
add_config :fog_attributes
|
27
28
|
add_config :fog_credentials
|
28
29
|
add_config :fog_directory
|
29
30
|
add_config :fog_public
|
30
31
|
add_config :fog_authenticated_url_expiration
|
31
32
|
add_config :fog_use_ssl_for_aws
|
33
|
+
add_config :fog_aws_accelerate
|
32
34
|
|
33
35
|
# Mounting
|
34
36
|
add_config :ignore_integrity_errors
|
@@ -38,6 +40,7 @@ module CarrierWave
|
|
38
40
|
add_config :validate_processing
|
39
41
|
add_config :validate_download
|
40
42
|
add_config :mount_on
|
43
|
+
add_config :cache_only
|
41
44
|
|
42
45
|
# set default values
|
43
46
|
reset_config
|
@@ -69,36 +72,76 @@ module CarrierWave
|
|
69
72
|
# storage MyCustomStorageEngine
|
70
73
|
#
|
71
74
|
def storage(storage = nil)
|
72
|
-
|
73
|
-
|
75
|
+
case storage
|
76
|
+
when Symbol
|
77
|
+
if storage_engine = storage_engines[storage]
|
78
|
+
self._storage = eval storage_engine
|
79
|
+
else
|
80
|
+
raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
|
81
|
+
end
|
82
|
+
when nil
|
83
|
+
storage
|
84
|
+
else
|
85
|
+
self._storage = storage
|
74
86
|
end
|
75
87
|
_storage
|
76
88
|
end
|
77
89
|
alias_method :storage=, :storage
|
78
90
|
|
91
|
+
##
|
92
|
+
# Sets the cache storage engine to be used when storing cache files with this uploader.
|
93
|
+
# Same as .storage except for required methods being #cache!(CarrierWave::SanitizedFile),
|
94
|
+
# #retrieve_from_cache! and #delete_dir!.
|
95
|
+
#
|
96
|
+
# === Parameters
|
97
|
+
#
|
98
|
+
# [storage (Symbol, Class)] The cache storage engine to use for this uploader
|
99
|
+
#
|
100
|
+
# === Returns
|
101
|
+
#
|
102
|
+
# [Class] the cache storage engine to be used with this uploader
|
103
|
+
#
|
104
|
+
# === Examples
|
105
|
+
#
|
106
|
+
# cache_storage :file
|
107
|
+
# cache_storage CarrierWave::Storage::File
|
108
|
+
# cache_storage MyCustomStorageEngine
|
109
|
+
#
|
110
|
+
def cache_storage(storage = nil)
|
111
|
+
if storage
|
112
|
+
self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
|
113
|
+
end
|
114
|
+
_cache_storage
|
115
|
+
end
|
116
|
+
alias_method :cache_storage=, :cache_storage
|
117
|
+
|
79
118
|
def add_config(name)
|
80
119
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
120
|
+
@#{name} = nil
|
121
|
+
|
81
122
|
def self.eager_load_fog(fog_credentials)
|
82
123
|
# see #1198. This will hopefully no longer be necessary after fog 2.0
|
124
|
+
require self.fog_provider
|
125
|
+
require 'carrierwave/storage/fog'
|
83
126
|
Fog::Storage.new(fog_credentials) if fog_credentials.present?
|
84
|
-
end
|
127
|
+
end unless defined? eager_load_fog
|
85
128
|
|
86
129
|
def self.#{name}(value=nil)
|
87
130
|
@#{name} = value if value
|
88
131
|
eager_load_fog(value) if value && '#{name}' == 'fog_credentials'
|
89
132
|
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
90
133
|
name = superclass.#{name}
|
91
|
-
return nil if name.nil? && !instance_variable_defined?(
|
134
|
+
return nil if name.nil? && !instance_variable_defined?(:@#{name})
|
92
135
|
@#{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
|
93
136
|
end
|
94
137
|
|
95
138
|
def self.#{name}=(value)
|
96
|
-
eager_load_fog(value) if '#{name}' == 'fog_credentials'
|
139
|
+
eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
97
140
|
@#{name} = value
|
98
141
|
end
|
99
142
|
|
100
143
|
def #{name}=(value)
|
101
|
-
self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials'
|
144
|
+
self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
102
145
|
@#{name} = value
|
103
146
|
end
|
104
147
|
|
@@ -107,7 +150,7 @@ module CarrierWave
|
|
107
150
|
value = self.class.#{name} unless instance_variable_defined?(:@#{name})
|
108
151
|
if value.instance_of?(Proc)
|
109
152
|
value.arity >= 1 ? value.call(self) : value.call
|
110
|
-
else
|
153
|
+
else
|
111
154
|
value
|
112
155
|
end
|
113
156
|
end
|
@@ -130,11 +173,14 @@ module CarrierWave
|
|
130
173
|
:fog => "CarrierWave::Storage::Fog"
|
131
174
|
}
|
132
175
|
config.storage = :file
|
176
|
+
config.cache_storage = :file
|
177
|
+
config.fog_provider = 'fog'
|
133
178
|
config.fog_attributes = {}
|
134
179
|
config.fog_credentials = {}
|
135
180
|
config.fog_public = true
|
136
181
|
config.fog_authenticated_url_expiration = 600
|
137
182
|
config.fog_use_ssl_for_aws = true
|
183
|
+
config.fog_aws_accelerate = false
|
138
184
|
config.store_dir = 'uploads'
|
139
185
|
config.cache_dir = 'uploads/tmp'
|
140
186
|
config.delete_tmp_file_after_storage = true
|
@@ -158,4 +204,3 @@ module CarrierWave
|
|
158
204
|
end
|
159
205
|
end
|
160
206
|
end
|
161
|
-
|
@@ -35,7 +35,7 @@ module CarrierWave
|
|
35
35
|
def check_content_type_whitelist!(new_file)
|
36
36
|
content_type = new_file.content_type
|
37
37
|
if content_type_whitelist && !whitelisted_content_type?(content_type)
|
38
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type)
|
38
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type, allowed_types: Array(content_type_whitelist).join(", "))
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -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
|
@@ -1,6 +1,5 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require 'open-uri'
|
2
|
+
require 'ssrf_filter'
|
4
3
|
|
5
4
|
module CarrierWave
|
6
5
|
module Uploader
|
@@ -12,13 +11,18 @@ module CarrierWave
|
|
12
11
|
include CarrierWave::Uploader::Cache
|
13
12
|
|
14
13
|
class RemoteFile
|
15
|
-
|
14
|
+
attr_reader :uri
|
15
|
+
|
16
|
+
def initialize(uri, remote_headers = {}, skip_ssrf_protection: false)
|
16
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
|
17
21
|
end
|
18
22
|
|
19
23
|
def original_filename
|
20
|
-
filename = filename_from_header ||
|
21
|
-
mime_type = MIME::Types[
|
24
|
+
filename = filename_from_header || filename_from_uri
|
25
|
+
mime_type = MIME::Types[content_type].first
|
22
26
|
unless File.extname(filename).present? || mime_type.blank?
|
23
27
|
filename = "#{filename}.#{mime_type.extensions.first}"
|
24
28
|
end
|
@@ -33,26 +37,53 @@ module CarrierWave
|
|
33
37
|
@uri.scheme =~ /^https?$/
|
34
38
|
end
|
35
39
|
|
36
|
-
|
40
|
+
def content_type
|
41
|
+
@content_type || 'application/octet-stream'
|
42
|
+
end
|
43
|
+
|
44
|
+
def headers
|
45
|
+
@headers || {}
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
37
49
|
|
38
50
|
def file
|
39
51
|
if @file.blank?
|
40
|
-
|
41
|
-
|
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
|
42
69
|
end
|
43
70
|
@file
|
44
71
|
|
45
|
-
rescue
|
72
|
+
rescue StandardError => e
|
46
73
|
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
|
47
74
|
end
|
48
75
|
|
49
76
|
def filename_from_header
|
50
|
-
if
|
51
|
-
match =
|
77
|
+
if headers['content-disposition']
|
78
|
+
match = headers['content-disposition'].match(/filename="?([^"]+)/)
|
52
79
|
return match[1] unless match.nil? || match[1].empty?
|
53
80
|
end
|
54
81
|
end
|
55
82
|
|
83
|
+
def filename_from_uri
|
84
|
+
URI::DEFAULT_PARSER.unescape(File.basename(@uri.path))
|
85
|
+
end
|
86
|
+
|
56
87
|
def method_missing(*args, &block)
|
57
88
|
file.send(*args, &block)
|
58
89
|
end
|
@@ -64,10 +95,11 @@ module CarrierWave
|
|
64
95
|
# === Parameters
|
65
96
|
#
|
66
97
|
# [url (String)] The URL where the remote file is stored
|
98
|
+
# [remote_headers (Hash)] Request headers
|
67
99
|
#
|
68
|
-
def download!(uri)
|
100
|
+
def download!(uri, remote_headers = {})
|
69
101
|
processed_uri = process_uri(uri)
|
70
|
-
file = RemoteFile.new(processed_uri)
|
102
|
+
file = RemoteFile.new(processed_uri, remote_headers, skip_ssrf_protection: skip_ssrf_protection?(processed_uri))
|
71
103
|
raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
|
72
104
|
cache!(file)
|
73
105
|
end
|
@@ -84,11 +116,30 @@ module CarrierWave
|
|
84
116
|
rescue URI::InvalidURIError
|
85
117
|
uri_parts = uri.split('?')
|
86
118
|
# regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
|
87
|
-
encoded_uri = URI.
|
88
|
-
encoded_uri << '?' << URI.
|
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?
|
89
121
|
URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
|
90
122
|
end
|
91
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
|
92
143
|
end # Download
|
93
144
|
end # Uploader
|
94
145
|
end # CarrierWave
|
@@ -4,7 +4,7 @@ module CarrierWave
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_extension_blacklist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -16,32 +16,36 @@ module CarrierWave
|
|
16
16
|
# the Regexp expression, also case insensitive.
|
17
17
|
#
|
18
18
|
# === Returns
|
19
|
-
|
20
|
-
# [NilClass, Array[String,Regexp]] a black list of extensions which are prohibited to be uploaded
|
19
|
+
|
20
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] a black list of extensions which are prohibited to be uploaded
|
21
21
|
#
|
22
22
|
# === Examples
|
23
23
|
#
|
24
|
-
# def
|
24
|
+
# def extension_blacklist
|
25
25
|
# %w(swf tiff)
|
26
26
|
# end
|
27
27
|
#
|
28
28
|
# Basically the same, but using a Regexp:
|
29
29
|
#
|
30
|
-
# def
|
30
|
+
# def extension_blacklist
|
31
31
|
# [/swf/, 'tiff']
|
32
32
|
# end
|
33
33
|
#
|
34
|
-
|
35
|
-
def
|
34
|
+
|
35
|
+
def extension_blacklist; end
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
|
-
def
|
39
|
+
def check_extension_blacklist!(new_file)
|
40
40
|
extension = new_file.extension.to_s
|
41
|
-
if
|
42
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
41
|
+
if extension_blacklist && blacklisted_extension?(extension)
|
42
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_blacklist_error", extension: new_file.extension.inspect, prohibited_types: Array(extension_blacklist).join(", "))
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
def blacklisted_extension?(extension)
|
47
|
+
Array(extension_blacklist).any? { |item| extension =~ /\A#{item}\z/i }
|
48
|
+
end
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
@@ -1,12 +1,10 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Uploader
|
5
3
|
module ExtensionWhitelist
|
6
4
|
extend ActiveSupport::Concern
|
7
5
|
|
8
6
|
included do
|
9
|
-
before :cache, :
|
7
|
+
before :cache, :check_extension_whitelist!
|
10
8
|
end
|
11
9
|
|
12
10
|
##
|
@@ -19,31 +17,36 @@ module CarrierWave
|
|
19
17
|
#
|
20
18
|
# === Returns
|
21
19
|
#
|
22
|
-
# [NilClass, Array[String,Regexp]] a white list of extensions which are allowed to be uploaded
|
20
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] a white list of extensions which are allowed to be uploaded
|
23
21
|
#
|
24
22
|
# === Examples
|
25
23
|
#
|
26
|
-
# def
|
24
|
+
# def extension_whitelist
|
27
25
|
# %w(jpg jpeg gif png)
|
28
26
|
# end
|
29
27
|
#
|
30
28
|
# Basically the same, but using a Regexp:
|
31
29
|
#
|
32
|
-
# def
|
30
|
+
# def extension_whitelist
|
33
31
|
# [/jpe?g/, 'gif', 'png']
|
34
32
|
# end
|
35
33
|
#
|
36
|
-
def
|
34
|
+
def extension_whitelist; end
|
37
35
|
|
38
36
|
private
|
39
37
|
|
40
|
-
def
|
38
|
+
def check_extension_whitelist!(new_file)
|
41
39
|
extension = new_file.extension.to_s
|
42
|
-
if
|
43
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
40
|
+
if extension_whitelist && !whitelisted_extension?(extension)
|
41
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_whitelist_error", extension: new_file.extension.inspect, allowed_types: Array(extension_whitelist).join(", "))
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
45
|
+
def whitelisted_extension?(extension)
|
46
|
+
downcase_extension = extension.downcase
|
47
|
+
Array(extension_whitelist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
|
48
|
+
end
|
49
|
+
|
47
50
|
end # ExtensionWhitelist
|
48
51
|
end # Uploader
|
49
52
|
end # CarrierWave
|
@@ -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 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
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Uploader
|
5
3
|
module Mountable
|
@@ -7,13 +5,14 @@ module CarrierWave
|
|
7
5
|
attr_reader :model, :mounted_as
|
8
6
|
|
9
7
|
##
|
10
|
-
# If a model is given as the first parameter, it will be stored in the
|
11
|
-
# available
|
12
|
-
# where this instance of the uploader is mounted.
|
13
|
-
# your uploader.
|
8
|
+
# If a model is given as the first parameter, it will be stored in the
|
9
|
+
# uploader, and available through +#model+. Likewise, mounted_as stores
|
10
|
+
# the name of the column where this instance of the uploader is mounted.
|
11
|
+
# These values can then be used inside your uploader.
|
14
12
|
#
|
15
|
-
# If you do not wish to mount your uploaders with the ORM extensions in
|
16
|
-
# can override this method inside your uploader. Just be
|
13
|
+
# If you do not wish to mount your uploaders with the ORM extensions in
|
14
|
+
# -more then you can override this method inside your uploader. Just be
|
15
|
+
# sure to call +super+
|
17
16
|
#
|
18
17
|
# === Parameters
|
19
18
|
#
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Uploader
|
5
3
|
module Processing
|
@@ -11,7 +9,7 @@ module CarrierWave
|
|
11
9
|
class_attribute :processors, :instance_writer => false
|
12
10
|
self.processors = []
|
13
11
|
|
14
|
-
|
12
|
+
before :cache, :process!
|
15
13
|
end
|
16
14
|
|
17
15
|
module ClassMethods
|
@@ -73,15 +71,17 @@ module CarrierWave
|
|
73
71
|
def process!(new_file=nil)
|
74
72
|
return unless enable_processing
|
75
73
|
|
76
|
-
|
77
|
-
|
78
|
-
if
|
79
|
-
|
80
|
-
|
81
|
-
|
74
|
+
with_callbacks(:process, new_file) do
|
75
|
+
self.class.processors.each do |method, args, condition|
|
76
|
+
if(condition)
|
77
|
+
if condition.respond_to?(:call)
|
78
|
+
next unless condition.call(self, :args => args, :method => method, :file => new_file)
|
79
|
+
else
|
80
|
+
next unless self.send(condition, new_file)
|
81
|
+
end
|
82
82
|
end
|
83
|
+
self.send(method, *args)
|
83
84
|
end
|
84
|
-
self.send(method, *args)
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|