carrierwave 0.10.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 (61) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +307 -121
  3. data/lib/carrierwave/compatibility/paperclip.rb +0 -2
  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 +229 -180
  9. data/lib/carrierwave/mounter.rb +188 -0
  10. data/lib/carrierwave/orm/activerecord.rb +59 -24
  11. data/lib/carrierwave/processing/mini_magick.rb +137 -83
  12. data/lib/carrierwave/processing/rmagick.rb +65 -8
  13. data/lib/carrierwave/processing.rb +0 -1
  14. data/lib/carrierwave/sanitized_file.rb +67 -32
  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 +177 -39
  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 +71 -13
  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 +4 -74
  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 +10 -10
  32. data/lib/carrierwave/uploader/proxy.rb +6 -8
  33. data/lib/carrierwave/uploader/remove.rb +0 -2
  34. data/lib/carrierwave/uploader/serialization.rb +2 -4
  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 +123 -93
  38. data/lib/carrierwave/uploader.rb +6 -2
  39. data/lib/carrierwave/utilities/uri.rb +5 -6
  40. data/lib/carrierwave/utilities.rb +0 -3
  41. data/lib/carrierwave/validations/active_model.rb +3 -5
  42. data/lib/carrierwave/version.rb +1 -1
  43. data/lib/carrierwave.rb +34 -8
  44. data/lib/generators/templates/uploader.rb +4 -8
  45. metadata +130 -57
  46. data/lib/carrierwave/locale/cs.yml +0 -11
  47. data/lib/carrierwave/locale/de.yml +0 -11
  48. data/lib/carrierwave/locale/el.yml +0 -11
  49. data/lib/carrierwave/locale/es.yml +0 -11
  50. data/lib/carrierwave/locale/fr.yml +0 -11
  51. data/lib/carrierwave/locale/ja.yml +0 -11
  52. data/lib/carrierwave/locale/nb.yml +0 -11
  53. data/lib/carrierwave/locale/nl.yml +0 -11
  54. data/lib/carrierwave/locale/pl.yml +0 -11
  55. data/lib/carrierwave/locale/pt-BR.yml +0 -11
  56. data/lib/carrierwave/locale/pt-PT.yml +0 -11
  57. data/lib/carrierwave/locale/ru.yml +0 -11
  58. data/lib/carrierwave/locale/sk.yml +0 -11
  59. data/lib/carrierwave/locale/tr.yml +0 -11
  60. data/lib/carrierwave/processing/mime_types.rb +0 -74
  61. data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -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,36 +75,66 @@ 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
81
- def self.eager_load_fog(fog_credentials)
82
- # see #1198. This will hopefully no longer be necessary after fog 2.0
83
- Fog::Storage.new(fog_credentials) if fog_credentials.present?
84
- end
123
+ @#{name} = nil
85
124
 
86
125
  def self.#{name}(value=nil)
87
126
  @#{name} = value if value
88
- eager_load_fog(value) if value && '#{name}' == 'fog_credentials'
89
127
  return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
90
128
  name = superclass.#{name}
91
- return nil if name.nil? && !instance_variable_defined?("@#{name}")
129
+ return nil if name.nil? && !instance_variable_defined?(:@#{name})
92
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
93
131
  end
94
132
 
95
133
  def self.#{name}=(value)
96
- eager_load_fog(value) if '#{name}' == 'fog_credentials'
97
134
  @#{name} = value
98
135
  end
99
136
 
100
137
  def #{name}=(value)
101
- self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials'
102
138
  @#{name} = value
103
139
  end
104
140
 
@@ -107,13 +143,33 @@ module CarrierWave
107
143
  value = self.class.#{name} unless instance_variable_defined?(:@#{name})
108
144
  if value.instance_of?(Proc)
109
145
  value.arity >= 1 ? value.call(self) : value.call
110
- else
146
+ else
111
147
  value
112
148
  end
113
149
  end
114
150
  RUBY
115
151
  end
116
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
+
117
173
  def configure
118
174
  yield self
119
175
  end
@@ -130,17 +186,20 @@ module CarrierWave
130
186
  :fog => "CarrierWave::Storage::Fog"
131
187
  }
132
188
  config.storage = :file
189
+ config.cache_storage = nil
133
190
  config.fog_attributes = {}
134
191
  config.fog_credentials = {}
135
192
  config.fog_public = true
136
193
  config.fog_authenticated_url_expiration = 600
137
194
  config.fog_use_ssl_for_aws = true
195
+ config.fog_aws_accelerate = false
138
196
  config.store_dir = 'uploads'
139
197
  config.cache_dir = 'uploads/tmp'
140
198
  config.delete_tmp_file_after_storage = true
141
199
  config.move_to_cache = false
142
200
  config.move_to_store = false
143
201
  config.remove_previously_stored_files_after_update = true
202
+ config.downloader = CarrierWave::Downloader::Base
144
203
  config.ignore_integrity_errors = true
145
204
  config.ignore_processing_errors = true
146
205
  config.ignore_download_errors = true
@@ -158,4 +217,3 @@ module CarrierWave
158
217
  end
159
218
  end
160
219
  end
161
-
@@ -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,84 +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
- filename = filename_from_header || File.basename(file.base_uri.path)
21
- mime_type = MIME::Types[file.content_type].first
22
- unless File.extname(filename).present? || mime_type.blank?
23
- filename = "#{filename}.#{mime_type.extensions.first}"
24
- end
25
- filename
26
- end
27
-
28
- def respond_to?(*args)
29
- super or file.respond_to?(*args)
30
- end
31
-
32
- def http?
33
- @uri.scheme =~ /^https?$/
34
- end
35
-
36
- private
37
-
38
- def file
39
- if @file.blank?
40
- @file = Kernel.open(@uri.to_s)
41
- @file = @file.is_a?(String) ? StringIO.new(@file) : @file
42
- end
43
- @file
44
-
45
- rescue Exception => e
46
- raise CarrierWave::DownloadError, "could not download file: #{e.message}"
47
- end
48
-
49
- def filename_from_header
50
- if file.meta.include? 'content-disposition'
51
- match = file.meta['content-disposition'].match(/filename="?([^"]+)/)
52
- return match[1] unless match.nil? || match[1].empty?
53
- end
54
- end
55
-
56
- def method_missing(*args, &block)
57
- file.send(*args, &block)
58
- end
59
- end
60
-
61
10
  ##
62
- # Caches the file by downloading it from the given URL.
11
+ # Caches the file by downloading it from the given URL, using downloader.
63
12
  #
64
13
  # === Parameters
65
14
  #
66
15
  # [url (String)] The URL where the remote file is stored
16
+ # [remote_headers (Hash)] Request headers
67
17
  #
68
- def download!(uri)
69
- processed_uri = process_uri(uri)
70
- file = RemoteFile.new(processed_uri)
71
- raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
18
+ def download!(uri, remote_headers = {})
19
+ file = downloader.new(self).download(uri, remote_headers)
72
20
  cache!(file)
73
21
  end
74
-
75
- ##
76
- # Processes the given URL by parsing and escaping it. Public to allow overriding.
77
- #
78
- # === Parameters
79
- #
80
- # [url (String)] The URL where the remote file is stored
81
- #
82
- def process_uri(uri)
83
- URI.parse(uri)
84
- rescue URI::InvalidURIError
85
- uri_parts = uri.split('?')
86
- # regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
87
- encoded_uri = URI.encode(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
88
- encoded_uri << '?' << URI.encode(uri_parts.join('?')) if uri_parts.any?
89
- URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
90
- end
91
-
92
22
  end # Download
93
23
  end # Uploader
94
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