carrierwave 3.0.7 → 3.1.0.rc
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +60 -12
- data/lib/carrierwave/downloader/base.rb +1 -1
- data/lib/carrierwave/mounter.rb +1 -0
- data/lib/carrierwave/processing/mini_magick.rb +30 -1
- data/lib/carrierwave/processing/rmagick.rb +36 -5
- data/lib/carrierwave/processing/vips.rb +31 -0
- data/lib/carrierwave/sanitized_file.rb +10 -1
- data/lib/carrierwave/storage/fog.rb +19 -6
- data/lib/carrierwave/uploader/cache.rb +1 -1
- data/lib/carrierwave/uploader/configuration.rb +8 -4
- data/lib/carrierwave/uploader/content_type_allowlist.rb +1 -1
- data/lib/carrierwave/uploader/content_type_denylist.rb +2 -2
- data/lib/carrierwave/uploader/extension_allowlist.rb +1 -1
- data/lib/carrierwave/uploader/extension_denylist.rb +2 -2
- data/lib/carrierwave/uploader/processing.rb +3 -0
- data/lib/carrierwave/uploader/store.rb +26 -0
- data/lib/carrierwave/uploader/versions.rb +6 -4
- data/lib/carrierwave/utilities/uri.rb +1 -1
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +9 -0
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5daf18958a06d91a53e10270049c75a1f93dcb8224e2dfb4511fc70d7bae5c2a
|
4
|
+
data.tar.gz: c60177f496f73f8fe949d89bc3cb39bb62aa81b384091eaf566c492a0d53f4dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c333ce7499ab4145df649e839ad40226d8338999b4ff624a884ffc07f253592000704b7f7cd090696602c29dcd1109e8a2aa1482c83dced511479d78cb0b650
|
7
|
+
data.tar.gz: dab32ccd98121831f2a1f4eee30e2540b3f15f73b8fc8680189df3e673457cea8f1e2f5bbe1555abf3a7fd25d8f1acdb16d13fa4c3a29b82d78aca76a838a0bd
|
data/README.md
CHANGED
@@ -659,14 +659,17 @@ end
|
|
659
659
|
## Testing with CarrierWave
|
660
660
|
|
661
661
|
It's a good idea to test your uploaders in isolation. In order to speed up your
|
662
|
-
tests, it's recommended to switch off processing in your tests, and to use the
|
663
|
-
|
662
|
+
tests, it's recommended to switch off processing in your tests, and to use the file storage.
|
663
|
+
Also, you can disable SSRF protection at your own risk using the `skip_ssrf_protection` configuration.
|
664
|
+
|
665
|
+
In Rails you could do that by adding an initializer with:
|
664
666
|
|
665
667
|
```ruby
|
666
668
|
if Rails.env.test? or Rails.env.cucumber?
|
667
669
|
CarrierWave.configure do |config|
|
668
670
|
config.storage = :file
|
669
671
|
config.enable_processing = false
|
672
|
+
config.skip_ssrf_protection = true
|
670
673
|
end
|
671
674
|
end
|
672
675
|
```
|
@@ -764,6 +767,10 @@ CarrierWave.configure do |config|
|
|
764
767
|
config.fog_directory = 'name_of_bucket' # required
|
765
768
|
config.fog_public = false # optional, defaults to true
|
766
769
|
config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" } # optional, defaults to {}
|
770
|
+
# Use this if you have AWS S3 ACLs disabled.
|
771
|
+
# config.fog_attributes = { 'x-amz-acl' => 'bucket-owner-full-control' }
|
772
|
+
# Use this if you have Google Cloud Storage uniform bucket-level access enabled.
|
773
|
+
# config.fog_attributes = { uniform: true }
|
767
774
|
# For an application which utilizes multiple servers but does not need caches persisted across requests,
|
768
775
|
# uncomment the line :file instead of the default :storage. Otherwise, it will use AWS as the temp cache store.
|
769
776
|
# config.cache_storage = :file
|
@@ -797,7 +804,7 @@ gem "fog"
|
|
797
804
|
```
|
798
805
|
|
799
806
|
You'll need to configure a directory (also known as a container), username and API key in the initializer.
|
800
|
-
For the sake of performance it is assumed that the directory already exists, so please create it if
|
807
|
+
For the sake of performance it is assumed that the directory already exists, so please create it if needs to be.
|
801
808
|
|
802
809
|
Using a US-based account:
|
803
810
|
|
@@ -856,7 +863,7 @@ gem "fog-google"
|
|
856
863
|
```
|
857
864
|
|
858
865
|
You'll need to configure a directory (also known as a bucket) and the credentials in the initializer.
|
859
|
-
For the sake of performance it is assumed that the directory already exists, so please create it if
|
866
|
+
For the sake of performance it is assumed that the directory already exists, so please create it if needs to be.
|
860
867
|
|
861
868
|
Please read the [fog-google README](https://github.com/fog/fog-google/blob/master/README.md) on how to get credentials.
|
862
869
|
|
@@ -970,14 +977,6 @@ class AvatarUploader < CarrierWave::Uploader::Base
|
|
970
977
|
end
|
971
978
|
```
|
972
979
|
|
973
|
-
#### List of available processing methods:
|
974
|
-
|
975
|
-
- `convert` - Changes the image encoding format to the given format(eg. jpg). This operation is treated specially to trigger the change of the file extension, so it matches with the format of the resulting file.
|
976
|
-
- `resize_to_limit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. Will only resize the image if it is larger than the specified dimensions. The resulting image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
|
977
|
-
- `resize_to_fit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. The image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
|
978
|
-
- `resize_to_fill` - Resize the image to fit within the specified dimensions while retaining the aspect ratio of the original image. If necessary, crop the image in the larger dimension. Optionally, a "gravity" may be specified, for example "Center", or "NorthEast".
|
979
|
-
- `resize_and_pad` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. If necessary, will pad the remaining area with the given color, which defaults to transparent (for gif and png, white for jpeg). Optionally, a "gravity" may be specified, as above.
|
980
|
-
|
981
980
|
See `carrierwave/processing/mini_magick.rb` for details.
|
982
981
|
|
983
982
|
### Using RMagick
|
@@ -1009,6 +1008,54 @@ end
|
|
1009
1008
|
Check out the manipulate! method, which makes it easy for you to write your own
|
1010
1009
|
manipulation methods.
|
1011
1010
|
|
1011
|
+
### Using Vips
|
1012
|
+
|
1013
|
+
CarrierWave version 2.2.0 added support for the `libvips` image processing library, through [ImageProcessing::Vips](https://github.com/janko/image_processing/blob/master/doc/vips.md). Its functionality matches that of the RMagick and MiniMagick processors, but it uses less memory and offers [faster processing](https://github.com/libvips/libvips/wiki/Speed-and-memory-use). To use the Vips processing module you must first install `libvips`, for example:
|
1014
|
+
|
1015
|
+
````bash
|
1016
|
+
$ sudo apt install libvips
|
1017
|
+
````
|
1018
|
+
|
1019
|
+
You also need to tell your uploader to use Vips:
|
1020
|
+
|
1021
|
+
````ruby
|
1022
|
+
class ImageFileUploader < CarrierWave::Uploader::Base
|
1023
|
+
include CarrierWave::Vips
|
1024
|
+
end
|
1025
|
+
````
|
1026
|
+
|
1027
|
+
### List of available processing methods:
|
1028
|
+
|
1029
|
+
> [!NOTE]
|
1030
|
+
> While the intention is to provide uniform interfaces to all three processing libraries the availability and implementation of processing methods can <a href="supported-processing-methods">vary slightly between them</a>.
|
1031
|
+
|
1032
|
+
- `convert` - Changes the image encoding format to the given format (eg. jpg). This operation is treated specially to trigger the change of the file extension, so it matches with the format of the resulting file.
|
1033
|
+
- `resize_to_limit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. Will only resize the image if it is larger than the specified dimensions. The resulting image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
|
1034
|
+
- `resize_to_fit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. The image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
|
1035
|
+
- `resize_to_fill` - Resize the image to fit within the specified dimensions while retaining the aspect ratio of the original image. If necessary, crop the image in the larger dimension. Optionally, a "gravity" may be specified, for example "Center", or "NorthEast".
|
1036
|
+
- `resize_and_pad` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. If necessary, will pad the remaining area with the given color, which defaults to transparent (for gif and png, white for jpeg). Optionally, a "gravity" may be specified, as above.
|
1037
|
+
- `crop` - Crop the image to the contents of a box with the specified height and width, positioned a given number of pixels from the top and left. The original image edge will be retained should the bottom and/or right edge of the box fall outside the image bounds.
|
1038
|
+
|
1039
|
+
#### Supported processing methods
|
1040
|
+
|
1041
|
+
The following table shows which processing methods are supported by each processing library, and which parameters they accept:
|
1042
|
+
|
1043
|
+
Method|RMagick|MiniMagick|Vips
|
1044
|
+
------|-----------------|-----------------|-----------------|
|
1045
|
+
`convert`|`format`|`format`, `page`<sup>1</sup>|`format`, `page`<sup>1</sup>
|
1046
|
+
`resize_to_limit`|`width`, `height`|`width`, `height`|`width`, `height`
|
1047
|
+
`resize_to_fit`|`width`, `height`|`width`, `height`|`width`, `height`
|
1048
|
+
`resize_to_fill`|`width`, `height`, `gravity`<sup>2</sup>|`width`, `height`, `gravity`<sup>2</sup>|`width`, `height`
|
1049
|
+
`resize_and_pad`|`width`, `height`, `background`, `gravity`<sup>2</sup>|`width`, `height`, `background`, `gravity`<sup>2</sup>|`width`, `height`, `background`, `gravity`<sup>2</sup>
|
1050
|
+
`resize_to_geometry_string`|`geometry_string`<sup>3</sup>|*not implemented*|*not implemented*
|
1051
|
+
`crop`|`left`, `top`, `width`, `height`|`left`, `top`, `width`, `height`|`left`, `top`, `width`, `height`
|
1052
|
+
|
1053
|
+
<sup>1</sup>`page` refers to the page number when converting from PDF, frame number when converting from GIF, and layer number when converting from PSD.
|
1054
|
+
|
1055
|
+
<sup>2</sup>`gravity` refers to an image position given as one of `Center`, `North`, `NorthWest`, `West`, `SouthWest`, `South`, `SouthEast`, `East`, or `NorthEast`.
|
1056
|
+
|
1057
|
+
<sup>3</sup>`geometry_string` is an [ImageMagick geometry string](https://rmagick.github.io/imusage.html#geometry).
|
1058
|
+
|
1012
1059
|
## Migrating from Paperclip
|
1013
1060
|
|
1014
1061
|
If you are using Paperclip, you can use the provided compatibility module:
|
@@ -1133,6 +1180,7 @@ cache
|
|
1133
1180
|
process
|
1134
1181
|
remove
|
1135
1182
|
retrieve_from_cache
|
1183
|
+
retrieve_from_store
|
1136
1184
|
store
|
1137
1185
|
```
|
1138
1186
|
|
data/lib/carrierwave/mounter.rb
CHANGED
@@ -79,6 +79,10 @@ module CarrierWave
|
|
79
79
|
def resize_and_pad(width, height, background=:transparent, gravity='Center')
|
80
80
|
process :resize_and_pad => [width, height, background, gravity]
|
81
81
|
end
|
82
|
+
|
83
|
+
def crop(left, top, width, height)
|
84
|
+
process :crop => [left, top, width, height]
|
85
|
+
end
|
82
86
|
end
|
83
87
|
|
84
88
|
##
|
@@ -210,6 +214,31 @@ module CarrierWave
|
|
210
214
|
end
|
211
215
|
end
|
212
216
|
|
217
|
+
##
|
218
|
+
# Crop the image to the contents of a box positioned at [left] and [top], with the dimensions given
|
219
|
+
# by [width] and [height]. The original image bottom/right edge is preserved if the cropping box falls
|
220
|
+
# outside the image bounds.
|
221
|
+
#
|
222
|
+
# === Parameters
|
223
|
+
#
|
224
|
+
# [left (integer)] left edge of area to extract
|
225
|
+
# [top (integer)] top edge of area to extract
|
226
|
+
# [width (Integer)] width of area to extract
|
227
|
+
# [height (Integer)] height of area to extract
|
228
|
+
#
|
229
|
+
# === Yields
|
230
|
+
#
|
231
|
+
# [MiniMagick::Image] additional manipulations to perform
|
232
|
+
#
|
233
|
+
def crop(left, top, width, height, combine_options: {}, &block)
|
234
|
+
width, height = resolve_dimensions(width, height)
|
235
|
+
|
236
|
+
minimagick!(block) do |builder|
|
237
|
+
builder.crop(left, top, width, height)
|
238
|
+
.apply(combine_options)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
213
242
|
##
|
214
243
|
# Returns the width of the image in pixels.
|
215
244
|
#
|
@@ -262,7 +291,7 @@ module CarrierWave
|
|
262
291
|
image = yield(image)
|
263
292
|
FileUtils.mv image.path, current_path
|
264
293
|
|
265
|
-
|
294
|
+
::MiniMagick::Image.new(current_path).identify
|
266
295
|
rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
|
267
296
|
raise e if e.message =~ /(You must have .+ installed|is not installed|executable not found)/
|
268
297
|
message = I18n.translate(:"errors.messages.processing_error")
|
@@ -22,7 +22,7 @@ module CarrierWave
|
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
# Or create your own helpers with the powerful manipulate! method. Check
|
25
|
-
# out the RMagick docs at
|
25
|
+
# out the RMagick docs at https://rmagick.github.io/ for more
|
26
26
|
# info
|
27
27
|
#
|
28
28
|
# class MyUploader < CarrierWave::Uploader::Base
|
@@ -102,12 +102,16 @@ module CarrierWave
|
|
102
102
|
def resize_to_geometry_string(geometry_string)
|
103
103
|
process :resize_to_geometry_string => [geometry_string]
|
104
104
|
end
|
105
|
+
|
106
|
+
def crop(left, top, width, height)
|
107
|
+
process :crop => [left, top, width, height]
|
108
|
+
end
|
105
109
|
end
|
106
110
|
|
107
111
|
##
|
108
112
|
# Changes the image encoding format to the given format
|
109
113
|
#
|
110
|
-
# See even
|
114
|
+
# See even https://rmagick.github.io/magick.html#formats
|
111
115
|
#
|
112
116
|
# === Parameters
|
113
117
|
#
|
@@ -161,7 +165,7 @@ module CarrierWave
|
|
161
165
|
# image may be shorter or narrower than specified in the smaller dimension
|
162
166
|
# but will not be larger than the specified values."
|
163
167
|
#
|
164
|
-
# See even
|
168
|
+
# See even https://rmagick.github.io/image3.html#resize_to_fit
|
165
169
|
#
|
166
170
|
# === Parameters
|
167
171
|
#
|
@@ -187,7 +191,7 @@ module CarrierWave
|
|
187
191
|
# specified dimensions while retaining the aspect ratio of the original
|
188
192
|
# image. If necessary, crop the image in the larger dimension."
|
189
193
|
#
|
190
|
-
# See even
|
194
|
+
# See even https://rmagick.github.io/image3.html#resize_to_fill
|
191
195
|
#
|
192
196
|
# === Parameters
|
193
197
|
#
|
@@ -260,6 +264,33 @@ module CarrierWave
|
|
260
264
|
end
|
261
265
|
end
|
262
266
|
|
267
|
+
##
|
268
|
+
# Crop the image to the contents of a box positioned at [left] and [top], with the dimensions given
|
269
|
+
# by [width] and [height]. The original image bottom/right edge is preserved if the cropping box falls
|
270
|
+
# outside the image bounds.
|
271
|
+
#
|
272
|
+
# === Parameters
|
273
|
+
#
|
274
|
+
# [left (integer)] left edge of area to extract
|
275
|
+
# [top (integer)] top edge of area to extract
|
276
|
+
# [width (Integer)] width of area to extract
|
277
|
+
# [height (Integer)] height of area to extract
|
278
|
+
#
|
279
|
+
# === Yields
|
280
|
+
#
|
281
|
+
# [Magick::Image] additional manipulations to perform
|
282
|
+
#
|
283
|
+
def crop(left, top, width, height, combine_options: {})
|
284
|
+
width = dimension_from width
|
285
|
+
height = dimension_from height
|
286
|
+
|
287
|
+
manipulate! do |img|
|
288
|
+
img.crop!(left, top, width, height)
|
289
|
+
img = yield(img) if block_given?
|
290
|
+
img
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
263
294
|
##
|
264
295
|
# Returns the width of the image.
|
265
296
|
#
|
@@ -377,7 +408,7 @@ module CarrierWave
|
|
377
408
|
proc do |img|
|
378
409
|
options.each do |k, v|
|
379
410
|
if v.is_a?(String) && (matches = v.match(/^["'](.+)["']/))
|
380
|
-
|
411
|
+
CarrierWave.deprecator.warn "Passing quoted strings like #{v} to #manipulate! is deprecated, pass them without quoting."
|
381
412
|
v = matches[1]
|
382
413
|
end
|
383
414
|
img.public_send(:"#{k}=", v)
|
@@ -78,6 +78,10 @@ module CarrierWave
|
|
78
78
|
def resize_and_pad(width, height, background=nil, gravity='centre', alpha=nil)
|
79
79
|
process :resize_and_pad => [width, height, background, gravity, alpha]
|
80
80
|
end
|
81
|
+
|
82
|
+
def crop(left, top, width, height)
|
83
|
+
process :crop => [left, top, width, height]
|
84
|
+
end
|
81
85
|
end
|
82
86
|
|
83
87
|
##
|
@@ -208,6 +212,33 @@ module CarrierWave
|
|
208
212
|
end
|
209
213
|
end
|
210
214
|
|
215
|
+
##
|
216
|
+
# Crop the image to the contents of a box positioned at [left] and [top], with the dimensions given
|
217
|
+
# by [width] and [height]. The original image bottom/right edge is preserved if the cropping box falls
|
218
|
+
# outside the image bounds.
|
219
|
+
#
|
220
|
+
# === Parameters
|
221
|
+
#
|
222
|
+
# [left (integer)] left edge of area to extract
|
223
|
+
# [top (integer)] top edge of area to extract
|
224
|
+
# [width (Integer)] width of area to extract
|
225
|
+
# [height (Integer)] height of area to extract
|
226
|
+
#
|
227
|
+
# === Yields
|
228
|
+
#
|
229
|
+
# [Vips::Image] additional manipulations to perform
|
230
|
+
#
|
231
|
+
def crop(left, top, width, height, combine_options: {})
|
232
|
+
width, height = resolve_dimensions(width, height)
|
233
|
+
width = vips_image.width - left if width + left > vips_image.width
|
234
|
+
height = vips_image.height - top if height + top > vips_image.height
|
235
|
+
|
236
|
+
vips! do |builder|
|
237
|
+
builder.crop(left, top, width, height)
|
238
|
+
.apply(combine_options)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
211
242
|
##
|
212
243
|
# Returns the width of the image in pixels.
|
213
244
|
#
|
@@ -321,7 +321,16 @@ module CarrierWave
|
|
321
321
|
|
322
322
|
def identified_content_type
|
323
323
|
with_io do |io|
|
324
|
-
Marcel::Magic.by_magic(io)
|
324
|
+
mimetype_by_magic = Marcel::Magic.by_magic(io)
|
325
|
+
mimetype_by_path = Marcel::Magic.by_path(path)
|
326
|
+
|
327
|
+
return nil if mimetype_by_magic.nil?
|
328
|
+
|
329
|
+
if mimetype_by_path&.child_of?(mimetype_by_magic.type)
|
330
|
+
mimetype_by_path.type
|
331
|
+
else
|
332
|
+
mimetype_by_magic.type
|
333
|
+
end
|
325
334
|
end
|
326
335
|
rescue Errno::ENOENT
|
327
336
|
nil
|
@@ -18,6 +18,8 @@ module CarrierWave
|
|
18
18
|
# [:fog_use_ssl_for_aws] (optional) #public_url will use https for the AWS generated URL]
|
19
19
|
# [:fog_aws_accelerate] (optional) #public_url will use s3-accelerate subdomain
|
20
20
|
# instead of s3, defaults to false
|
21
|
+
# [:fog_aws_fips] (optional) #public_url will use s3-fips subdomain
|
22
|
+
# instead of s3, defaults to false
|
21
23
|
#
|
22
24
|
#
|
23
25
|
# AWS credentials contain the following keys:
|
@@ -309,6 +311,15 @@ module CarrierWave
|
|
309
311
|
file.nil? ? 0 : file.content_length
|
310
312
|
end
|
311
313
|
|
314
|
+
##
|
315
|
+
# === Returns
|
316
|
+
#
|
317
|
+
# [Boolean] whether the file is non-existent or empty
|
318
|
+
#
|
319
|
+
def empty?
|
320
|
+
!exists? || size.zero?
|
321
|
+
end
|
322
|
+
|
312
323
|
##
|
313
324
|
# Check if the file exists on the remote service
|
314
325
|
#
|
@@ -365,6 +376,7 @@ module CarrierWave
|
|
365
376
|
when 'AWS'
|
366
377
|
# check if some endpoint is set in fog_credentials
|
367
378
|
if @uploader.fog_credentials.has_key?(:endpoint)
|
379
|
+
raise 'fog_aws_fips = true is incompatible with :endpoint, as FIPS endpoints do not support path-style URLs.' if @uploader.fog_aws_fips
|
368
380
|
"#{@uploader.fog_credentials[:endpoint]}/#{@uploader.fog_directory}/#{encoded_path}"
|
369
381
|
else
|
370
382
|
protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
|
@@ -374,17 +386,18 @@ module CarrierWave
|
|
374
386
|
use_virtual_hosted_style = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
|
375
387
|
|
376
388
|
region = @uploader.fog_credentials[:region].to_s
|
377
|
-
regional_host =
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
389
|
+
regional_host = 's3.amazonaws.com' # used for DEFAULT_S3_REGION or no region set
|
390
|
+
if @uploader.fog_aws_fips
|
391
|
+
regional_host = "s3-fips.#{region}.amazonaws.com" # https://aws.amazon.com/compliance/fips/
|
392
|
+
elsif ![DEFAULT_S3_REGION, ''].include?(region)
|
393
|
+
regional_host = "s3.#{region}.amazonaws.com"
|
394
|
+
end
|
383
395
|
|
384
396
|
if use_virtual_hosted_style
|
385
397
|
regional_host = 's3-accelerate.amazonaws.com' if @uploader.fog_aws_accelerate
|
386
398
|
"#{protocol}://#{@uploader.fog_directory}.#{regional_host}/#{encoded_path}"
|
387
399
|
else # directory is not a valid subdomain, so use path style for access
|
400
|
+
raise 'FIPS Endpoints can only be used with Virtual Hosted-Style addressing.' if @uploader.fog_aws_fips
|
388
401
|
"#{protocol}://#{regional_host}/#{@uploader.fog_directory}/#{encoded_path}"
|
389
402
|
end
|
390
403
|
end
|
@@ -91,9 +91,9 @@ module CarrierWave
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def sanitized_file
|
94
|
-
ActiveSupport::Deprecation.warn('#sanitized_file is deprecated, use #file instead.')
|
95
94
|
file
|
96
95
|
end
|
96
|
+
CarrierWave.deprecator.deprecate_methods(self, sanitized_file: :file)
|
97
97
|
|
98
98
|
##
|
99
99
|
# Returns a String which uniquely identifies the currently cached file for later retrieval
|
@@ -35,6 +35,7 @@ module CarrierWave
|
|
35
35
|
add_config :fog_authenticated_url_expiration
|
36
36
|
add_config :fog_use_ssl_for_aws
|
37
37
|
add_config :fog_aws_accelerate
|
38
|
+
add_config :fog_aws_fips
|
38
39
|
|
39
40
|
# Mounting
|
40
41
|
add_config :ignore_integrity_errors
|
@@ -47,6 +48,7 @@ module CarrierWave
|
|
47
48
|
add_config :cache_only
|
48
49
|
add_config :download_retry_count
|
49
50
|
add_config :download_retry_wait_time
|
51
|
+
add_config :skip_ssrf_protection
|
50
52
|
|
51
53
|
# set default values
|
52
54
|
reset_config
|
@@ -156,19 +158,19 @@ module CarrierWave
|
|
156
158
|
def add_deprecated_config(name)
|
157
159
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
158
160
|
def self.#{name}(value=nil)
|
159
|
-
|
161
|
+
CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
|
160
162
|
end
|
161
163
|
|
162
164
|
def self.#{name}=(value)
|
163
|
-
|
165
|
+
CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
|
164
166
|
end
|
165
167
|
|
166
168
|
def #{name}=(value)
|
167
|
-
|
169
|
+
CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
|
168
170
|
end
|
169
171
|
|
170
172
|
def #{name}
|
171
|
-
|
173
|
+
CarrierWave.deprecator.warn "##{name} is deprecated and has no effect"
|
172
174
|
end
|
173
175
|
RUBY
|
174
176
|
end
|
@@ -196,6 +198,7 @@ module CarrierWave
|
|
196
198
|
config.fog_authenticated_url_expiration = 600
|
197
199
|
config.fog_use_ssl_for_aws = true
|
198
200
|
config.fog_aws_accelerate = false
|
201
|
+
config.fog_aws_fips = false
|
199
202
|
config.store_dir = 'uploads'
|
200
203
|
config.cache_dir = 'uploads/tmp'
|
201
204
|
config.delete_tmp_file_after_storage = true
|
@@ -216,6 +219,7 @@ module CarrierWave
|
|
216
219
|
config.ensure_multipart_form = true
|
217
220
|
config.download_retry_count = 0
|
218
221
|
config.download_retry_wait_time = 5
|
222
|
+
config.skip_ssrf_protection = false
|
219
223
|
end
|
220
224
|
end
|
221
225
|
end
|
@@ -36,7 +36,7 @@ module CarrierWave
|
|
36
36
|
def check_content_type_allowlist!(new_file)
|
37
37
|
allowlist = content_type_allowlist
|
38
38
|
if !allowlist && respond_to?(:content_type_whitelist) && content_type_whitelist
|
39
|
-
|
39
|
+
CarrierWave.deprecator.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
|
40
40
|
@content_type_whitelist_warned = true
|
41
41
|
allowlist = content_type_whitelist
|
42
42
|
end
|
@@ -36,14 +36,14 @@ module CarrierWave
|
|
36
36
|
def check_content_type_denylist!(new_file)
|
37
37
|
denylist = content_type_denylist
|
38
38
|
if !denylist && respond_to?(:content_type_blacklist) && content_type_blacklist
|
39
|
-
|
39
|
+
CarrierWave.deprecator.warn "#content_type_blacklist is deprecated, use #content_type_denylist instead." unless instance_variable_defined?(:@content_type_blacklist_warned)
|
40
40
|
@content_type_blacklist_warned = true
|
41
41
|
denylist = content_type_blacklist
|
42
42
|
end
|
43
43
|
|
44
44
|
return unless denylist
|
45
45
|
|
46
|
-
|
46
|
+
CarrierWave.deprecator.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
47
|
@content_type_denylist_warned = true
|
48
48
|
|
49
49
|
content_type = new_file.content_type
|
@@ -39,7 +39,7 @@ module CarrierWave
|
|
39
39
|
def check_extension_allowlist!(new_file)
|
40
40
|
allowlist = extension_allowlist
|
41
41
|
if !allowlist && respond_to?(:extension_whitelist) && extension_whitelist
|
42
|
-
|
42
|
+
CarrierWave.deprecator.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
|
43
43
|
@extension_whitelist_warned = true
|
44
44
|
allowlist = extension_whitelist
|
45
45
|
end
|
@@ -39,14 +39,14 @@ module CarrierWave
|
|
39
39
|
def check_extension_denylist!(new_file)
|
40
40
|
denylist = extension_denylist
|
41
41
|
if !denylist && respond_to?(:extension_blacklist) && extension_blacklist
|
42
|
-
|
42
|
+
CarrierWave.deprecator.warn "#extension_blacklist is deprecated, use #extension_denylist instead." unless instance_variable_defined?(:@extension_blacklist_warned)
|
43
43
|
@extension_blacklist_warned = true
|
44
44
|
denylist = extension_blacklist
|
45
45
|
end
|
46
46
|
|
47
47
|
return unless denylist
|
48
48
|
|
49
|
-
|
49
|
+
CarrierWave.deprecator.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
50
|
@extension_denylist_warned = true
|
51
51
|
|
52
52
|
extension = new_file.extension.to_s
|
@@ -70,6 +70,9 @@ module CarrierWave
|
|
70
70
|
if processor == :convert
|
71
71
|
# Treat :convert specially, since it should trigger the file extension change
|
72
72
|
force_extension processor_args
|
73
|
+
if condition
|
74
|
+
warn "Use of 'process convert: format' with conditionals has an issue and doesn't work correctly. See https://github.com/carrierwaveuploader/carrierwave/issues/2723 for details. "
|
75
|
+
end
|
73
76
|
end
|
74
77
|
end
|
75
78
|
end
|
@@ -14,6 +14,20 @@ module CarrierWave
|
|
14
14
|
@file, @filename, @cache_id, @identifier, @deduplication_index = nil
|
15
15
|
end
|
16
16
|
}
|
17
|
+
|
18
|
+
after :store, :show_warning_when_filename_is_unavailable
|
19
|
+
|
20
|
+
class_attribute :filename_safeguard_checked
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
private
|
25
|
+
|
26
|
+
def inherited(subclass)
|
27
|
+
# To perform the filename safeguard check once per a class
|
28
|
+
self.filename_safeguard_checked = false
|
29
|
+
super
|
30
|
+
end
|
17
31
|
end
|
18
32
|
|
19
33
|
##
|
@@ -133,6 +147,18 @@ module CarrierWave
|
|
133
147
|
forcing_extension(for_file)
|
134
148
|
end
|
135
149
|
|
150
|
+
def show_warning_when_filename_is_unavailable(_)
|
151
|
+
return if self.class.filename_safeguard_checked
|
152
|
+
self.class.filename_safeguard_checked = true
|
153
|
+
return if filename
|
154
|
+
|
155
|
+
warn <<~MESSAGE
|
156
|
+
[WARNING] Your uploader's #filename method defined at #{method(:filename).source_location.join(':')} didn't return value after storing the file.
|
157
|
+
It's likely that the method is safeguarded with `if original_filename`, which were necessary for pre-3.x CarrierWave but is no longer needed.
|
158
|
+
Removing it is recommended, as it is known to cause issues depending on the use case: https://github.com/carrierwaveuploader/carrierwave/issues/2708
|
159
|
+
MESSAGE
|
160
|
+
end
|
161
|
+
|
136
162
|
def storage
|
137
163
|
@storage ||= self.class.storage.new(self)
|
138
164
|
end
|
@@ -20,7 +20,7 @@ module CarrierWave
|
|
20
20
|
def build(superclass)
|
21
21
|
return @klass if @klass
|
22
22
|
@klass = Class.new(superclass)
|
23
|
-
superclass.const_set("#{@name.to_s.camelize}
|
23
|
+
superclass.const_set("VersionUploader#{@name.to_s.camelize}", @klass)
|
24
24
|
|
25
25
|
@klass.version_names += [@name]
|
26
26
|
@klass.versions = {}
|
@@ -196,9 +196,9 @@ module CarrierWave
|
|
196
196
|
#
|
197
197
|
# === Returns
|
198
198
|
#
|
199
|
-
# [Boolean] True when the version
|
199
|
+
# [Boolean] True when the version satisfy its :if or :unless condition
|
200
200
|
#
|
201
|
-
def
|
201
|
+
def version_active?(name)
|
202
202
|
name = name.to_sym
|
203
203
|
|
204
204
|
return false unless versions.has_key?(name)
|
@@ -222,6 +222,8 @@ module CarrierWave
|
|
222
222
|
true
|
223
223
|
end
|
224
224
|
end
|
225
|
+
alias_method :version_exists?, :version_active?
|
226
|
+
CarrierWave.deprecator.deprecate_methods(self, version_exists?: :version_active?)
|
225
227
|
|
226
228
|
##
|
227
229
|
# Copies the parent's cache_id when caching a version file.
|
@@ -299,7 +301,7 @@ module CarrierWave
|
|
299
301
|
|
300
302
|
def active_versions
|
301
303
|
versions.select do |name, uploader|
|
302
|
-
|
304
|
+
version_active?(name)
|
303
305
|
end
|
304
306
|
end
|
305
307
|
|
@@ -4,7 +4,7 @@ module CarrierWave
|
|
4
4
|
module Utilities
|
5
5
|
module Uri
|
6
6
|
# based on Ruby < 2.0's URI.encode
|
7
|
-
PATH_SAFE = URI::
|
7
|
+
PATH_SAFE = URI::RFC2396_REGEXP::PATTERN::UNRESERVED + '\/'
|
8
8
|
PATH_UNSAFE = Regexp.new("[^#{PATH_SAFE}]", false)
|
9
9
|
NON_ASCII = /[^[:ascii:]]/.freeze
|
10
10
|
|
data/lib/carrierwave/version.rb
CHANGED
data/lib/carrierwave.rb
CHANGED
@@ -3,6 +3,7 @@ require 'active_support/core_ext/object/blank'
|
|
3
3
|
require 'active_support/core_ext/object/try'
|
4
4
|
require 'active_support/core_ext/class/attribute'
|
5
5
|
require 'active_support/concern'
|
6
|
+
require 'active_support/deprecation'
|
6
7
|
|
7
8
|
module CarrierWave
|
8
9
|
|
@@ -21,6 +22,10 @@ module CarrierWave
|
|
21
22
|
def tmp_path
|
22
23
|
@tmp_path ||= File.expand_path(File.join('..', 'tmp'), root)
|
23
24
|
end
|
25
|
+
|
26
|
+
def deprecator
|
27
|
+
@deprecator ||= ActiveSupport::Deprecation.new("#{CarrierWave::VERSION.split('.')[0].to_i + 1}.0", "CarrierWave")
|
28
|
+
end
|
24
29
|
end
|
25
30
|
|
26
31
|
end
|
@@ -64,6 +69,10 @@ elsif defined?(Rails)
|
|
64
69
|
end
|
65
70
|
end
|
66
71
|
|
72
|
+
initializer "carrierwave.deprecator" do |app|
|
73
|
+
app.deprecators[:carrierwave] = CarrierWave.deprecator if app.respond_to?(:deprecators)
|
74
|
+
end
|
75
|
+
|
67
76
|
config.before_eager_load do
|
68
77
|
CarrierWave::Storage::Fog.eager_load
|
69
78
|
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: 3.0.
|
4
|
+
version: 3.1.0.rc
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Nicklas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -226,20 +226,6 @@ dependencies:
|
|
226
226
|
- - ">="
|
227
227
|
- !ruby/object:Gem::Version
|
228
228
|
version: '0'
|
229
|
-
- !ruby/object:Gem::Dependency
|
230
|
-
name: fog-rackspace
|
231
|
-
requirement: !ruby/object:Gem::Requirement
|
232
|
-
requirements:
|
233
|
-
- - ">="
|
234
|
-
- !ruby/object:Gem::Version
|
235
|
-
version: '0'
|
236
|
-
type: :development
|
237
|
-
prerelease: false
|
238
|
-
version_requirements: !ruby/object:Gem::Requirement
|
239
|
-
requirements:
|
240
|
-
- - ">="
|
241
|
-
- !ruby/object:Gem::Version
|
242
|
-
version: '0'
|
243
229
|
- !ruby/object:Gem::Dependency
|
244
230
|
name: mini_magick
|
245
231
|
requirement: !ruby/object:Gem::Requirement
|
@@ -396,9 +382,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
396
382
|
version: 2.5.0
|
397
383
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
398
384
|
requirements:
|
399
|
-
- - "
|
385
|
+
- - ">"
|
400
386
|
- !ruby/object:Gem::Version
|
401
|
-
version:
|
387
|
+
version: 1.3.1
|
402
388
|
requirements: []
|
403
389
|
rubygems_version: 3.4.10
|
404
390
|
signing_key:
|