carrierwave 1.3.1 → 1.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13d4923726d7eb20e4ce86366a5c538621fcf7041f508c91a49d18110836e1b8
4
- data.tar.gz: b28de2ffce2e7febf02bab5366d30e2cb5b9a0bd2d1399d05aebddddcdd8192f
3
+ metadata.gz: 2ef69bd6c6815eeb01f996a2506ac01cc6f366a566217fc366dde5a0653f92a1
4
+ data.tar.gz: 396d34e7c58d946ada4ede908f672c1abec0e4d59031dfca7455ee0d77d7d2db
5
5
  SHA512:
6
- metadata.gz: 70d982a8de3b08806f7a059033cec1df699005a9817435ea0b7f05fd284139578f73c80909ba97e9534a44978862298ac6fde43870856b73d9da0db28fb4be99
7
- data.tar.gz: bcbae13bc47d3b03a521c136b0b5d2183e022eb4750720df9618933de56bf7b2cce89eec80c9584fd88b00caba992432bc6d7c47f2cab324667a7bb7fd1851ee
6
+ metadata.gz: a2ed581457edf26ff5c60922f98bed68b3f539196f15ff38f780be5619cc5aec21481be0dd78f6c16e8ab3fa1a83b6e2d859030c723bc357dd78a3d0352a410b
7
+ data.tar.gz: 897d714945716a4bdcf48036c194212d9724863392931bde86bc2a44a2743c3088962ef1b633417262239e2ef8c374694afc634ac8e5074c2ff7d767a313bcbe
data/README.md CHANGED
@@ -163,6 +163,9 @@ class User < ActiveRecord::Base
163
163
  end
164
164
  ```
165
165
 
166
+ Make sure that you mount the uploader with write (mount_uploaders) with `s` not (mount_uploader)
167
+ in order to avoid errors when uploading multiple files
168
+
166
169
  Make sure your file input fields are set up as multiple file fields. For
167
170
  example in Rails you'll want to do something like this:
168
171
 
@@ -110,7 +110,7 @@ module CarrierWave
110
110
  end
111
111
 
112
112
  def remove?
113
- remove.present? && remove !~ /\A0|false$\z/
113
+ remove.present? && (remove == true || remove !~ /\A0|false$\z/)
114
114
  end
115
115
 
116
116
  def remove!
@@ -378,9 +378,15 @@ module CarrierWave
378
378
 
379
379
  def create_info_block(options)
380
380
  return nil unless options
381
- assignments = options.map { |k, v| "self.#{k} = #{v}" }
382
- code = "lambda { |img| " + assignments.join(";") + "}"
383
- eval code
381
+ proc do |img|
382
+ options.each do |k, v|
383
+ if v.is_a?(String) && (matches = v.match(/^["'](.+)["']/))
384
+ ActiveSupport::Deprecation.warn "Passing quoted strings like #{v} to #manipulate! is deprecated, pass them without quoting."
385
+ v = matches[1]
386
+ end
387
+ img.public_send(:"#{k}=", v)
388
+ end
389
+ end
384
390
  end
385
391
 
386
392
  def destroy_image(image)
@@ -114,12 +114,11 @@ module CarrierWave
114
114
  # [String, nil] the path where the file is located.
115
115
  #
116
116
  def path
117
- unless @file.blank?
118
- if is_path?
119
- File.expand_path(@file)
120
- elsif @file.respond_to?(:path) and not @file.path.blank?
121
- File.expand_path(@file.path)
122
- end
117
+ return if @file.blank?
118
+ if is_path?
119
+ File.expand_path(@file)
120
+ elsif @file.respond_to?(:path) && !@file.path.blank?
121
+ File.expand_path(@file.path)
123
122
  end
124
123
  end
125
124
 
@@ -313,7 +312,7 @@ module CarrierWave
313
312
  def mkdir!(path, directory_permissions)
314
313
  options = {}
315
314
  options[:mode] = directory_permissions if directory_permissions
316
- FileUtils.mkdir_p(File.dirname(path), options) unless File.exist?(File.dirname(path))
315
+ FileUtils.mkdir_p(File.dirname(path), **options) unless File.exist?(File.dirname(path))
317
316
  end
318
317
 
319
318
  def chmod!(path, permissions)
@@ -177,7 +177,7 @@ module CarrierWave
177
177
 
178
178
  ##
179
179
  # Return a temporary authenticated url to a private file, if available
180
- # Only supported for AWS, Rackspace and Google providers
180
+ # Only supported for AWS, Rackspace, Google and AzureRM providers
181
181
  #
182
182
  # === Returns
183
183
  #
@@ -186,7 +186,7 @@ module CarrierWave
186
186
  # [NilClass] no authenticated url available
187
187
  #
188
188
  def authenticated_url(options = {})
189
- if ['AWS', 'Google', 'Rackspace', 'OpenStack'].include?(@uploader.fog_credentials[:provider])
189
+ if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM'].include?(@uploader.fog_credentials[:provider])
190
190
  # avoid a get by using local references
191
191
  local_directory = connection.directories.new(:key => @uploader.fog_directory)
192
192
  local_file = local_directory.files.new(:key => path)
@@ -200,10 +200,8 @@ module CarrierWave
200
200
  warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
201
201
  local_file.url(expire_at)
202
202
  end
203
- when 'Rackspace'
203
+ when 'Rackspace', 'OpenStack'
204
204
  connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
205
- when 'OpenStack'
206
- connection.get_object_https_url(@uploader.fog_directory, path, expire_at)
207
205
  else
208
206
  local_file.url(expire_at)
209
207
  end
@@ -1,4 +1,5 @@
1
1
  require 'open-uri'
2
+ require 'ssrf_filter'
2
3
 
3
4
  module CarrierWave
4
5
  module Uploader
@@ -10,15 +11,18 @@ module CarrierWave
10
11
  include CarrierWave::Uploader::Cache
11
12
 
12
13
  class RemoteFile
13
- def initialize(uri, remote_headers = {})
14
+ attr_reader :uri
15
+
16
+ def initialize(uri, remote_headers = {}, skip_ssrf_protection: false)
14
17
  @uri = uri
15
- @remote_headers = remote_headers
16
- @file = nil
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
24
  filename = filename_from_header || filename_from_uri
21
- mime_type = MIME::Types[file.content_type].first
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,15 +37,35 @@ module CarrierWave
33
37
  @uri.scheme =~ /^https?$/
34
38
  end
35
39
 
36
- private
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
- headers = @remote_headers.
41
- reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
42
-
43
- @file = Kernel.open(@uri.to_s, headers)
44
- @file = @file.is_a?(String) ? StringIO.new(@file) : @file
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
45
69
  end
46
70
  @file
47
71
 
@@ -50,14 +74,14 @@ module CarrierWave
50
74
  end
51
75
 
52
76
  def filename_from_header
53
- if file.meta.include? 'content-disposition'
54
- match = file.meta['content-disposition'].match(/filename="?([^"]+)/)
77
+ if headers['content-disposition']
78
+ match = headers['content-disposition'].match(/filename="?([^"]+)/)
55
79
  return match[1] unless match.nil? || match[1].empty?
56
80
  end
57
81
  end
58
82
 
59
83
  def filename_from_uri
60
- URI.decode(File.basename(file.base_uri.path))
84
+ URI::DEFAULT_PARSER.unescape(File.basename(@uri.path))
61
85
  end
62
86
 
63
87
  def method_missing(*args, &block)
@@ -75,7 +99,7 @@ module CarrierWave
75
99
  #
76
100
  def download!(uri, remote_headers = {})
77
101
  processed_uri = process_uri(uri)
78
- file = RemoteFile.new(processed_uri, remote_headers)
102
+ file = RemoteFile.new(processed_uri, remote_headers, skip_ssrf_protection: skip_ssrf_protection?(processed_uri))
79
103
  raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
80
104
  cache!(file)
81
105
  end
@@ -92,11 +116,30 @@ module CarrierWave
92
116
  rescue URI::InvalidURIError
93
117
  uri_parts = uri.split('?')
94
118
  # regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
95
- encoded_uri = URI.encode(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
96
- encoded_uri << '?' << URI.encode(uri_parts.join('?')) if uri_parts.any?
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?
97
121
  URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
98
122
  end
99
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
100
143
  end # Download
101
144
  end # Uploader
102
145
  end # CarrierWave
@@ -1,3 +1,3 @@
1
1
  module CarrierWave
2
- VERSION = "1.3.1"
2
+ VERSION = "1.3.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carrierwave
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Nicklas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-29 00:00:00.000000000 Z
11
+ date: 2023-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -53,33 +53,39 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.16'
55
55
  - !ruby/object:Gem::Dependency
56
- name: pg
56
+ name: ssrf_filter
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "<"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
61
+ version: 1.1.0
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '1.0'
65
+ type: :runtime
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
66
- - - ">="
69
+ - - "<"
67
70
  - !ruby/object:Gem::Version
68
- version: '0'
71
+ version: 1.1.0
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.0'
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: rails
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
79
  - - ">="
74
80
  - !ruby/object:Gem::Version
75
- version: 4.0.0
81
+ version: 5.0.0
76
82
  type: :development
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - ">="
81
87
  - !ruby/object:Gem::Version
82
- version: 4.0.0
88
+ version: 5.0.0
83
89
  - !ruby/object:Gem::Dependency
84
90
  name: cucumber
85
91
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +128,20 @@ dependencies:
122
128
  - - ">="
123
129
  - !ruby/object:Gem::Version
124
130
  version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: fog-core
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 2.1.0
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 2.1.0
125
145
  - !ruby/object:Gem::Dependency
126
146
  name: fog-aws
127
147
  requirement: !ruby/object:Gem::Requirement
@@ -140,16 +160,16 @@ dependencies:
140
160
  name: fog-google
141
161
  requirement: !ruby/object:Gem::Requirement
142
162
  requirements:
143
- - - "~>"
163
+ - - ">="
144
164
  - !ruby/object:Gem::Version
145
- version: 1.7.1
165
+ version: '0'
146
166
  type: :development
147
167
  prerelease: false
148
168
  version_requirements: !ruby/object:Gem::Requirement
149
169
  requirements:
150
- - - "~>"
170
+ - - ">="
151
171
  - !ruby/object:Gem::Version
152
- version: 1.7.1
172
+ version: '0'
153
173
  - !ruby/object:Gem::Dependency
154
174
  name: fog-local
155
175
  requirement: !ruby/object:Gem::Requirement
@@ -196,16 +216,16 @@ dependencies:
196
216
  name: rmagick
197
217
  requirement: !ruby/object:Gem::Requirement
198
218
  requirements:
199
- - - ">="
219
+ - - "~>"
200
220
  - !ruby/object:Gem::Version
201
- version: '0'
221
+ version: '2.16'
202
222
  type: :development
203
223
  prerelease: false
204
224
  version_requirements: !ruby/object:Gem::Requirement
205
225
  requirements:
206
- - - ">="
226
+ - - "~>"
207
227
  - !ruby/object:Gem::Version
208
- version: '0'
228
+ version: '2.16'
209
229
  - !ruby/object:Gem::Dependency
210
230
  name: timecop
211
231
  requirement: !ruby/object:Gem::Requirement
@@ -319,8 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
319
339
  - !ruby/object:Gem::Version
320
340
  version: '0'
321
341
  requirements: []
322
- rubyforge_project:
323
- rubygems_version: 2.7.8
342
+ rubygems_version: 3.1.6
324
343
  signing_key:
325
344
  specification_version: 4
326
345
  summary: Ruby file upload library