carrierwave 0.9.0 → 2.1.1

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.

Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +362 -116
  3. data/lib/carrierwave/compatibility/paperclip.rb +29 -21
  4. data/lib/carrierwave/downloader/base.rb +83 -0
  5. data/lib/carrierwave/downloader/remote_file.rb +65 -0
  6. data/lib/carrierwave/error.rb +1 -0
  7. data/lib/carrierwave/locale/en.yml +7 -4
  8. data/lib/carrierwave/mount.rb +238 -186
  9. data/lib/carrierwave/mounter.rb +188 -0
  10. data/lib/carrierwave/orm/activerecord.rb +60 -24
  11. data/lib/carrierwave/processing/mini_magick.rb +139 -78
  12. data/lib/carrierwave/processing/rmagick.rb +68 -23
  13. data/lib/carrierwave/processing.rb +0 -1
  14. data/lib/carrierwave/sanitized_file.rb +67 -27
  15. data/lib/carrierwave/storage/abstract.rb +15 -2
  16. data/lib/carrierwave/storage/file.rb +69 -2
  17. data/lib/carrierwave/storage/fog.rb +180 -41
  18. data/lib/carrierwave/storage.rb +1 -7
  19. data/lib/carrierwave/test/matchers.rb +77 -12
  20. data/lib/carrierwave/uploader/cache.rb +74 -38
  21. data/lib/carrierwave/uploader/callbacks.rb +0 -2
  22. data/lib/carrierwave/uploader/configuration.rb +72 -6
  23. data/lib/carrierwave/uploader/content_type_blacklist.rb +48 -0
  24. data/lib/carrierwave/uploader/content_type_whitelist.rb +48 -0
  25. data/lib/carrierwave/uploader/default_url.rb +3 -5
  26. data/lib/carrierwave/uploader/download.rb +5 -69
  27. data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
  28. data/lib/carrierwave/uploader/extension_whitelist.rb +13 -10
  29. data/lib/carrierwave/uploader/file_size.rb +43 -0
  30. data/lib/carrierwave/uploader/mountable.rb +13 -8
  31. data/lib/carrierwave/uploader/processing.rb +15 -17
  32. data/lib/carrierwave/uploader/proxy.rb +16 -7
  33. data/lib/carrierwave/uploader/remove.rb +0 -2
  34. data/lib/carrierwave/uploader/serialization.rb +3 -5
  35. data/lib/carrierwave/uploader/store.rb +17 -24
  36. data/lib/carrierwave/uploader/url.rb +3 -5
  37. data/lib/carrierwave/uploader/versions.rb +117 -86
  38. data/lib/carrierwave/uploader.rb +6 -2
  39. data/lib/carrierwave/utilities/uri.rb +5 -6
  40. data/lib/carrierwave/utilities.rb +1 -3
  41. data/lib/carrierwave/validations/active_model.rb +3 -7
  42. data/lib/carrierwave/version.rb +1 -1
  43. data/lib/carrierwave.rb +36 -3
  44. data/lib/generators/templates/uploader.rb +4 -8
  45. data/lib/generators/uploader_generator.rb +1 -1
  46. metadata +195 -94
  47. data/lib/carrierwave/locale/cs.yml +0 -11
  48. data/lib/carrierwave/locale/de.yml +0 -11
  49. data/lib/carrierwave/locale/nl.yml +0 -11
  50. data/lib/carrierwave/locale/sk.yml +0 -11
  51. data/lib/carrierwave/processing/mime_types.rb +0 -73
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ require 'securerandom'
2
2
 
3
3
  module CarrierWave
4
4
 
@@ -8,15 +8,27 @@ module CarrierWave
8
8
  end
9
9
  end
10
10
 
11
+ class CacheCounter
12
+ @@counter = 0
13
+
14
+ def self.increment
15
+ @@counter += 1
16
+ end
17
+ end
18
+
11
19
  ##
12
20
  # Generates a unique cache id for use in the caching system
13
21
  #
14
22
  # === Returns
15
23
  #
16
- # [String] a cache id in the format TIMEINT-PID-RND
24
+ # [String] a cache id in the format TIMEINT-PID-COUNTER-RND
17
25
  #
18
26
  def self.generate_cache_id
19
- Time.now.utc.to_i.to_s + '-' + Process.pid.to_s + '-' + ("%04d" % rand(9999))
27
+ [Time.now.utc.to_i,
28
+ SecureRandom.random_number(1_000_000_000_000_000),
29
+ '%04d' % (CarrierWave::CacheCounter.increment % 10_000),
30
+ '%04d' % SecureRandom.random_number(10_000)
31
+ ].map(&:to_s).join('-')
20
32
  end
21
33
 
22
34
  module Uploader
@@ -26,6 +38,16 @@ module CarrierWave
26
38
  include CarrierWave::Uploader::Callbacks
27
39
  include CarrierWave::Uploader::Configuration
28
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
+
29
51
  module ClassMethods
30
52
 
31
53
  ##
@@ -42,13 +64,7 @@ module CarrierWave
42
64
  # It's recommended that you keep cache files in one place only.
43
65
  #
44
66
  def clean_cached_files!(seconds=60*60*24)
45
- Dir.glob(File.expand_path(File.join(cache_dir, '*'), CarrierWave.root)).each do |dir|
46
- time = dir.scan(/(\d+)-\d+-\d+/).first.map { |t| t.to_i }
47
- time = Time.at(*time)
48
- if time < (Time.now.utc - seconds)
49
- FileUtils.rm_rf(dir)
50
- end
51
- end
67
+ (cache_storage || storage).new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
52
68
  end
53
69
  end
54
70
 
@@ -74,16 +90,8 @@ module CarrierWave
74
90
  end
75
91
 
76
92
  def sanitized_file
77
- _content = file.read
78
- if _content.is_a?(File) # could be if storage is Fog
79
- sanitized = CarrierWave::Storage::Fog.new(self).retrieve!(File.basename(_content.path))
80
- sanitized.read if sanitized.exists?
81
-
82
- else
83
- sanitized = SanitizedFile.new :tempfile => StringIO.new(file.read),
84
- :filename => File.basename(path), :content_type => file.content_type
85
- end
86
- sanitized
93
+ ActiveSupport::Deprecation.warn('#sanitized_file is deprecated, use #file instead.')
94
+ file
87
95
  end
88
96
 
89
97
  ##
@@ -91,10 +99,10 @@ module CarrierWave
91
99
  #
92
100
  # === Returns
93
101
  #
94
- # [String] a cache name, in the format YYYYMMDD-HHMM-PID-RND/filename.txt
102
+ # [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
95
103
  #
96
104
  def cache_name
97
- File.join(cache_id, full_original_filename) if cache_id and original_filename
105
+ File.join(cache_id, full_original_filename) if cache_id && original_filename
98
106
  end
99
107
 
100
108
  ##
@@ -113,24 +121,31 @@ module CarrierWave
113
121
  #
114
122
  # [CarrierWave::FormNotMultipart] if the assigned parameter is a string
115
123
  #
116
- def cache!(new_file = sanitized_file)
124
+ def cache!(new_file = file)
117
125
  new_file = CarrierWave::SanitizedFile.new(new_file)
126
+ return if new_file.empty?
118
127
 
119
- unless new_file.empty?
120
- raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
128
+ raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
121
129
 
122
- with_callbacks(:cache, new_file) do
123
- self.cache_id = CarrierWave.generate_cache_id unless cache_id
130
+ self.cache_id = CarrierWave.generate_cache_id unless cache_id
124
131
 
125
- @filename = new_file.filename
126
- self.original_filename = new_file.filename
132
+ @staged = true
133
+ @filename = new_file.filename
134
+ self.original_filename = new_file.filename
135
+
136
+ begin
137
+ # first, create a workfile on which we perform processings
138
+ if move_to_cache
139
+ @file = new_file.move_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
140
+ else
141
+ @file = new_file.copy_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
142
+ end
127
143
 
128
- if move_to_cache
129
- @file = new_file.move_to(cache_path, permissions, directory_permissions)
130
- else
131
- @file = new_file.copy_to(cache_path, permissions, directory_permissions)
132
- end
144
+ with_callbacks(:cache, @file) do
145
+ @file = cache_storage.cache!(@file)
133
146
  end
147
+ ensure
148
+ FileUtils.rm_rf(workfile_path(''))
134
149
  end
135
150
  end
136
151
 
@@ -148,15 +163,31 @@ module CarrierWave
148
163
  def retrieve_from_cache!(cache_name)
149
164
  with_callbacks(:retrieve_from_cache, cache_name) do
150
165
  self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
166
+ @staged = true
151
167
  @filename = original_filename
152
- @file = CarrierWave::SanitizedFile.new(cache_path)
168
+ @file = cache_storage.retrieve_from_cache!(full_filename(original_filename))
153
169
  end
154
170
  end
155
171
 
172
+ ##
173
+ # Calculates the path where the cache file should be stored.
174
+ #
175
+ # === Parameters
176
+ #
177
+ # [for_file (String)] name of the file <optional>
178
+ #
179
+ # === Returns
180
+ #
181
+ # [String] the cache path
182
+ #
183
+ def cache_path(for_file=full_filename(original_filename))
184
+ File.join(*[cache_dir, @cache_id, for_file].compact)
185
+ end
186
+
156
187
  private
157
188
 
158
- def cache_path
159
- File.expand_path(File.join(cache_dir, cache_name), root)
189
+ def workfile_path(for_file=original_filename)
190
+ File.join(CarrierWave.tmp_path, @cache_id, version_name.to_s, for_file)
160
191
  end
161
192
 
162
193
  attr_reader :cache_id, :original_filename
@@ -165,7 +196,9 @@ module CarrierWave
165
196
  alias_method :full_original_filename, :original_filename
166
197
 
167
198
  def cache_id=(cache_id)
168
- raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A[\d]+\-[\d]+\-[\d]{4}\z/
199
+ # Earlier version used 3 part cache_id. Thus we should allow for
200
+ # the cache_id to have both 3 part and 4 part formats.
201
+ raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A(-)?[\d]+\-[\d]+(\-[\d]{4})?\-[\d]{4}\z/
169
202
  @cache_id = cache_id
170
203
  end
171
204
 
@@ -174,6 +207,9 @@ module CarrierWave
174
207
  @original_filename = filename
175
208
  end
176
209
 
210
+ def cache_storage
211
+ @cache_storage ||= (self.class.cache_storage || self.class.storage).new(self)
212
+ end
177
213
  end # Cache
178
214
  end # Uploader
179
215
  end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Callbacks
@@ -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,17 @@ 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
29
+ add_deprecated_config :fog_provider
26
30
  add_config :fog_attributes
27
31
  add_config :fog_credentials
28
32
  add_config :fog_directory
29
33
  add_config :fog_public
30
34
  add_config :fog_authenticated_url_expiration
31
35
  add_config :fog_use_ssl_for_aws
36
+ add_config :fog_aws_accelerate
32
37
 
33
38
  # Mounting
34
39
  add_config :ignore_integrity_errors
@@ -38,6 +43,7 @@ module CarrierWave
38
43
  add_config :validate_processing
39
44
  add_config :validate_download
40
45
  add_config :mount_on
46
+ add_config :cache_only
41
47
 
42
48
  # set default values
43
49
  reset_config
@@ -69,20 +75,58 @@ module CarrierWave
69
75
  # storage MyCustomStorageEngine
70
76
  #
71
77
  def storage(storage = nil)
72
- if storage
73
- self._storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
78
+ case storage
79
+ when Symbol
80
+ if storage_engine = storage_engines[storage]
81
+ self._storage = eval storage_engine
82
+ else
83
+ raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
84
+ end
85
+ when nil
86
+ storage
87
+ else
88
+ self._storage = storage
74
89
  end
75
90
  _storage
76
91
  end
77
92
  alias_method :storage=, :storage
78
93
 
94
+ ##
95
+ # Sets the cache storage engine to be used when storing cache files with this uploader.
96
+ # Same as .storage except for required methods being #cache!(CarrierWave::SanitizedFile),
97
+ # #retrieve_from_cache! and #delete_dir!.
98
+ #
99
+ # === Parameters
100
+ #
101
+ # [storage (Symbol, Class)] The cache storage engine to use for this uploader
102
+ #
103
+ # === Returns
104
+ #
105
+ # [Class] the cache storage engine to be used with this uploader
106
+ #
107
+ # === Examples
108
+ #
109
+ # cache_storage :file
110
+ # cache_storage CarrierWave::Storage::File
111
+ # cache_storage MyCustomStorageEngine
112
+ #
113
+ def cache_storage(storage = false)
114
+ unless storage == false
115
+ self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
116
+ end
117
+ _cache_storage
118
+ end
119
+ alias_method :cache_storage=, :cache_storage
120
+
79
121
  def add_config(name)
80
122
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
123
+ @#{name} = nil
124
+
81
125
  def self.#{name}(value=nil)
82
126
  @#{name} = value if value
83
127
  return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
84
128
  name = superclass.#{name}
85
- return nil if name.nil? && !instance_variable_defined?("@#{name}")
129
+ return nil if name.nil? && !instance_variable_defined?(:@#{name})
86
130
  @#{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
131
  end
88
132
 
@@ -99,13 +143,33 @@ module CarrierWave
99
143
  value = self.class.#{name} unless instance_variable_defined?(:@#{name})
100
144
  if value.instance_of?(Proc)
101
145
  value.arity >= 1 ? value.call(self) : value.call
102
- else
146
+ else
103
147
  value
104
148
  end
105
149
  end
106
150
  RUBY
107
151
  end
108
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
+
109
173
  def configure
110
174
  yield self
111
175
  end
@@ -122,17 +186,20 @@ module CarrierWave
122
186
  :fog => "CarrierWave::Storage::Fog"
123
187
  }
124
188
  config.storage = :file
189
+ config.cache_storage = nil
125
190
  config.fog_attributes = {}
126
191
  config.fog_credentials = {}
127
192
  config.fog_public = true
128
193
  config.fog_authenticated_url_expiration = 600
129
194
  config.fog_use_ssl_for_aws = true
195
+ config.fog_aws_accelerate = false
130
196
  config.store_dir = 'uploads'
131
197
  config.cache_dir = 'uploads/tmp'
132
198
  config.delete_tmp_file_after_storage = true
133
199
  config.move_to_cache = false
134
200
  config.move_to_store = false
135
201
  config.remove_previously_stored_files_after_update = true
202
+ config.downloader = CarrierWave::Downloader::Base
136
203
  config.ignore_integrity_errors = true
137
204
  config.ignore_processing_errors = true
138
205
  config.ignore_download_errors = true
@@ -150,4 +217,3 @@ module CarrierWave
150
217
  end
151
218
  end
152
219
  end
153
-
@@ -0,0 +1,48 @@
1
+ module CarrierWave
2
+ module Uploader
3
+ module ContentTypeBlacklist
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before :cache, :check_content_type_blacklist!
8
+ end
9
+
10
+ ##
11
+ # Override this method in your uploader to provide a blacklist 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 blacklist of content types which are not allowed to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def content_type_blacklist
22
+ # %w(text/json application/json)
23
+ # end
24
+ #
25
+ # Basically the same, but using a Regexp:
26
+ #
27
+ # def content_type_blacklist
28
+ # [/(text|application)\/json/]
29
+ # end
30
+ #
31
+ def content_type_blacklist; end
32
+
33
+ private
34
+
35
+ def check_content_type_blacklist!(new_file)
36
+ content_type = new_file.content_type
37
+ if content_type_blacklist && blacklisted_content_type?(content_type)
38
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error", content_type: content_type)
39
+ end
40
+ end
41
+
42
+ def blacklisted_content_type?(content_type)
43
+ Array(content_type_blacklist).any? { |item| content_type =~ /#{item}/ }
44
+ end
45
+
46
+ end # ContentTypeBlacklist
47
+ end # Uploader
48
+ end # CarrierWave
@@ -0,0 +1,48 @@
1
+ module CarrierWave
2
+ module Uploader
3
+ module ContentTypeWhitelist
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before :cache, :check_content_type_whitelist!
8
+ end
9
+
10
+ ##
11
+ # Override this method in your uploader to provide a whitelist 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]] a whitelist of content types which are allowed to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def content_type_whitelist
22
+ # %w(text/json application/json)
23
+ # end
24
+ #
25
+ # Basically the same, but using a Regexp:
26
+ #
27
+ # def content_type_whitelist
28
+ # [/(text|application)\/json/]
29
+ # end
30
+ #
31
+ def content_type_whitelist; end
32
+
33
+ private
34
+
35
+ def check_content_type_whitelist!(new_file)
36
+ content_type = new_file.content_type
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, allowed_types: Array(content_type_whitelist).join(", "))
39
+ end
40
+ end
41
+
42
+ def whitelisted_content_type?(content_type)
43
+ Array(content_type_whitelist).any? { |item| content_type =~ /#{item}/ }
44
+ end
45
+
46
+ end # ContentTypeWhitelist
47
+ end # Uploader
48
+ 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
@@ -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
- # Processes the given URL by parsing and escaping it. Public to allow overriding.
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 process_uri(uri)
77
- URI.parse(uri)
78
- rescue URI::InvalidURIError
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
@@ -4,7 +4,7 @@ module CarrierWave
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- before :cache, :check_blacklist!
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 extension_black_list
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 extension_black_list
30
+ # def extension_blacklist
31
31
  # [/swf/, 'tiff']
32
32
  # end
33
33
  #
34
-
35
- def extension_black_list; end
34
+
35
+ def extension_blacklist; end
36
36
 
37
37
  private
38
38
 
39
- def check_blacklist!(new_file)
39
+ def check_extension_blacklist!(new_file)
40
40
  extension = new_file.extension.to_s
41
- if extension_black_list and extension_black_list.detect { |item| extension =~ /\A#{item}\z/i }
42
- raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_black_list_error", :extension => new_file.extension.inspect, :prohibited_types => extension_black_list.join(", "))
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, :check_whitelist!
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 extension_white_list
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 extension_white_list
30
+ # def extension_whitelist
33
31
  # [/jpe?g/, 'gif', 'png']
34
32
  # end
35
33
  #
36
- def extension_white_list; end
34
+ def extension_whitelist; end
37
35
 
38
36
  private
39
37
 
40
- def check_whitelist!(new_file)
38
+ def check_extension_whitelist!(new_file)
41
39
  extension = new_file.extension.to_s
42
- if extension_white_list and not extension_white_list.detect { |item| extension =~ /\A#{item}\z/i }
43
- raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_white_list_error", :extension => new_file.extension.inspect, :allowed_types => extension_white_list.join(", "))
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