carrierwave 2.2.6 → 3.0.0.beta
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 +4 -4
- data/README.md +37 -7
- data/lib/carrierwave/downloader/base.rb +8 -1
- data/lib/carrierwave/downloader/remote_file.rb +7 -3
- data/lib/carrierwave/locale/en.yml +1 -3
- data/lib/carrierwave/mount.rb +40 -8
- data/lib/carrierwave/mounter.rb +1 -1
- data/lib/carrierwave/orm/activerecord.rb +5 -2
- data/lib/carrierwave/processing/mini_magick.rb +6 -6
- data/lib/carrierwave/processing/rmagick.rb +4 -4
- data/lib/carrierwave/processing/vips.rb +3 -3
- data/lib/carrierwave/sanitized_file.rb +18 -56
- data/lib/carrierwave/storage/file.rb +2 -2
- data/lib/carrierwave/storage/fog.rb +5 -16
- data/lib/carrierwave/uploader/cache.rb +1 -1
- data/lib/carrierwave/uploader/configuration.rb +2 -0
- data/lib/carrierwave/uploader/{content_type_whitelist.rb → content_type_allowlist.rb} +18 -16
- data/lib/carrierwave/uploader/{content_type_blacklist.rb → content_type_denylist.rb} +19 -14
- data/lib/carrierwave/uploader/{extension_whitelist.rb → extension_allowlist.rb} +17 -15
- data/lib/carrierwave/uploader/{extension_blacklist.rb → extension_denylist.rb} +18 -13
- data/lib/carrierwave/uploader/processing.rb +17 -6
- data/lib/carrierwave/uploader/versions.rb +18 -5
- data/lib/carrierwave/uploader.rb +8 -8
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities.rb +1 -0
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +1 -10
- metadata +17 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5777918bb6d5edc1006f2f0bfb10f47e1576bc9b4dcbabbc00d42a0cbd59a93f
|
4
|
+
data.tar.gz: 3f9a90b9c715e67c753909de2ee5a4c9ff5bd8c51ad5e7ed4730a128690c6a34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0ff141f52c94d57863789c6255629301317182991e5676394efde778122645da9e38fa9bcac926886e8e8d22d778250803dd8fdd2437d5f4ce3c97dedb2cd3a
|
7
|
+
data.tar.gz: 4130502d8c30bebf77189f9ca281f2b1cdf285bc6445a260ea3b49bd6597f0e7becad9983d33388eab0ca8f8fcb53e1ae0ebc1b7978c1cca62268e324cb42a2e
|
data/README.md
CHANGED
@@ -30,14 +30,11 @@ $ gem install carrierwave
|
|
30
30
|
In Rails, add it to your Gemfile:
|
31
31
|
|
32
32
|
```ruby
|
33
|
-
gem 'carrierwave', '
|
33
|
+
gem 'carrierwave', '>= 3.0.0.beta', '< 4.0'
|
34
34
|
```
|
35
35
|
|
36
36
|
Finally, restart the server to apply the changes.
|
37
37
|
|
38
|
-
As of version 2.0, CarrierWave requires Rails 5.0 or higher and Ruby 2.2
|
39
|
-
or higher. If you're on Rails 4, you should use 1.x.
|
40
|
-
|
41
38
|
## Getting Started
|
42
39
|
|
43
40
|
Start off by generating an uploader:
|
@@ -531,6 +528,16 @@ failures automatically with attribute validation errors. If you aren't, or you
|
|
531
528
|
disable CarrierWave's `validate_download` option, you'll need to handle those
|
532
529
|
errors yourself.
|
533
530
|
|
531
|
+
### Retry option for download from remote location
|
532
|
+
If you want to retry the download from the Remote URL, enable the download_retry_count option, an error occurs during download, it will try to execute the specified number of times every 5 second.
|
533
|
+
This option is effective when the remote destination is unstable.
|
534
|
+
|
535
|
+
```rb
|
536
|
+
CarrierWave.configure do |config|
|
537
|
+
config.download_retry_count = 3 # Default 0
|
538
|
+
end
|
539
|
+
```
|
540
|
+
|
534
541
|
## Providing a default URL
|
535
542
|
|
536
543
|
In many cases, especially when working with images, it might be a good idea to
|
@@ -951,7 +958,7 @@ See the MiniMagick site for more details:
|
|
951
958
|
|
952
959
|
https://github.com/minimagick/minimagick
|
953
960
|
|
954
|
-
And the ImageMagick command line options for more for
|
961
|
+
And the ImageMagick command line options for more for what's on offer:
|
955
962
|
|
956
963
|
http://www.imagemagick.org/script/command-line-options.php
|
957
964
|
|
@@ -1000,8 +1007,7 @@ errors:
|
|
1000
1007
|
extension_denylist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
|
1001
1008
|
content_type_allowlist_error: "You are not allowed to upload %{content_type} files, allowed types: %{allowed_types}"
|
1002
1009
|
content_type_denylist_error: "You are not allowed to upload %{content_type} files"
|
1003
|
-
|
1004
|
-
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
|
1010
|
+
processing_error: "Failed to manipulate, maybe it is not an image?"
|
1005
1011
|
min_size_error: "File size should be greater than %{min_size}"
|
1006
1012
|
max_size_error: "File size should be less than %{max_size}"
|
1007
1013
|
```
|
@@ -1066,6 +1072,30 @@ class User
|
|
1066
1072
|
end
|
1067
1073
|
```
|
1068
1074
|
|
1075
|
+
## Uploader Callbacks
|
1076
|
+
|
1077
|
+
In addition to the ActiveRecord callbacks described above, uploaders also have callbacks.
|
1078
|
+
|
1079
|
+
```ruby
|
1080
|
+
class MyUploader < ::CarrierWave::Uploader::Base
|
1081
|
+
before :remove, :log_removal
|
1082
|
+
private
|
1083
|
+
def log_removal
|
1084
|
+
::Rails.logger.info(format('Deleting file on S3: %s', @file))
|
1085
|
+
end
|
1086
|
+
end
|
1087
|
+
```
|
1088
|
+
|
1089
|
+
Uploader callbacks can be `before` or `after` the following events:
|
1090
|
+
|
1091
|
+
```
|
1092
|
+
cache
|
1093
|
+
process
|
1094
|
+
remove
|
1095
|
+
retrieve_from_cache
|
1096
|
+
store
|
1097
|
+
```
|
1098
|
+
|
1069
1099
|
## Contributing to CarrierWave
|
1070
1100
|
|
1071
1101
|
See [CONTRIBUTING.md](https://github.com/carrierwaveuploader/carrierwave/blob/master/CONTRIBUTING.md)
|
@@ -21,6 +21,7 @@ module CarrierWave
|
|
21
21
|
# [remote_headers (Hash)] Request headers
|
22
22
|
#
|
23
23
|
def download(url, remote_headers = {})
|
24
|
+
@current_download_retry_count = 0
|
24
25
|
headers = remote_headers.
|
25
26
|
reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
|
26
27
|
uri = process_uri(url.to_s)
|
@@ -42,7 +43,13 @@ module CarrierWave
|
|
42
43
|
response.value
|
43
44
|
end
|
44
45
|
rescue StandardError => e
|
45
|
-
|
46
|
+
if @current_download_retry_count < @uploader.download_retry_count
|
47
|
+
@current_download_retry_count += 1
|
48
|
+
sleep 5
|
49
|
+
retry
|
50
|
+
else
|
51
|
+
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
|
52
|
+
end
|
46
53
|
end
|
47
54
|
CarrierWave::Downloader::RemoteFile.new(response)
|
48
55
|
end
|
@@ -8,7 +8,10 @@ module CarrierWave
|
|
8
8
|
when String
|
9
9
|
@file = StringIO.new(file)
|
10
10
|
when Net::HTTPResponse
|
11
|
-
|
11
|
+
body = file.body
|
12
|
+
raise CarrierWave::DownloadError, 'could not download file: No Content' if body.nil?
|
13
|
+
|
14
|
+
@file = StringIO.new(body)
|
12
15
|
@content_type = file.content_type
|
13
16
|
@headers = file
|
14
17
|
@uri = file.uri
|
@@ -30,9 +33,10 @@ module CarrierWave
|
|
30
33
|
|
31
34
|
def original_filename
|
32
35
|
filename = filename_from_header || filename_from_uri
|
33
|
-
mime_type =
|
36
|
+
mime_type = Marcel::TYPES[content_type]
|
34
37
|
unless File.extname(filename).present? || mime_type.blank?
|
35
|
-
|
38
|
+
extension = mime_type[0].first
|
39
|
+
filename = "#{filename}.#{extension}"
|
36
40
|
end
|
37
41
|
filename
|
38
42
|
end
|
@@ -8,8 +8,6 @@ en:
|
|
8
8
|
extension_denylist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
|
9
9
|
content_type_allowlist_error: "You are not allowed to upload %{content_type} files, allowed types: %{allowed_types}"
|
10
10
|
content_type_denylist_error: "You are not allowed to upload %{content_type} files"
|
11
|
-
|
12
|
-
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
|
13
|
-
vips_processing_error: "Failed to manipulate with vips, maybe it is not an image? Original Error: %{e}"
|
11
|
+
processing_error: "Failed to manipulate, maybe it is not an image?"
|
14
12
|
min_size_error: "File size should be greater than %{min_size}"
|
15
13
|
max_size_error: "File size should be less than %{max_size}"
|
data/lib/carrierwave/mount.rb
CHANGED
@@ -174,8 +174,12 @@ module CarrierWave
|
|
174
174
|
return if frozen?
|
175
175
|
mounter = _mounter(:#{column})
|
176
176
|
|
177
|
-
|
178
|
-
|
177
|
+
if mounter.remove?
|
178
|
+
mounter.clear!
|
179
|
+
write_uploader(mounter.serialization_column, nil)
|
180
|
+
elsif mounter.identifiers.first
|
181
|
+
write_uploader(mounter.serialization_column, mounter.identifiers.first)
|
182
|
+
end
|
179
183
|
end
|
180
184
|
|
181
185
|
def #{column}_identifier
|
@@ -195,14 +199,25 @@ module CarrierWave
|
|
195
199
|
end
|
196
200
|
|
197
201
|
def store_previous_changes_for_#{column}
|
198
|
-
|
199
|
-
|
202
|
+
@_previous_changes_for_#{column} = saved_changes[_mounter(:#{column}).serialization_column]
|
203
|
+
end
|
204
|
+
|
205
|
+
def reset_previous_changes_for_#{column}
|
206
|
+
# We use this variable to pass information from save time to commit time.
|
207
|
+
# Make sure this doesn't persist across multiple transactions
|
208
|
+
@_previous_changes_for_#{column} = nil
|
200
209
|
end
|
201
210
|
|
202
211
|
def remove_previously_stored_#{column}
|
203
212
|
before, after = @_previous_changes_for_#{column}
|
204
213
|
_mounter(:#{column}).remove_previous([before], [after])
|
205
214
|
end
|
215
|
+
|
216
|
+
def remove_rolled_back_#{column}
|
217
|
+
before, after = @_previous_changes_for_#{column}
|
218
|
+
_mounter(:#{column}).remove_previous([after], [before])
|
219
|
+
@_previous_changes_for_#{column} = nil
|
220
|
+
end
|
206
221
|
RUBY
|
207
222
|
end
|
208
223
|
|
@@ -338,8 +353,12 @@ module CarrierWave
|
|
338
353
|
return if frozen?
|
339
354
|
mounter = _mounter(:#{column})
|
340
355
|
|
341
|
-
|
342
|
-
|
356
|
+
if mounter.remove?
|
357
|
+
mounter.clear!
|
358
|
+
write_uploader(mounter.serialization_column, nil)
|
359
|
+
elsif mounter.identifiers.any?
|
360
|
+
write_uploader(mounter.serialization_column, mounter.identifiers)
|
361
|
+
end
|
343
362
|
end
|
344
363
|
|
345
364
|
def #{column}_identifiers
|
@@ -347,13 +366,26 @@ module CarrierWave
|
|
347
366
|
end
|
348
367
|
|
349
368
|
def store_previous_changes_for_#{column}
|
350
|
-
|
351
|
-
|
369
|
+
@_previous_changes_for_#{column} = saved_changes[_mounter(:#{column}).serialization_column]
|
370
|
+
end
|
371
|
+
|
372
|
+
def reset_previous_changes_for_#{column}
|
373
|
+
# We use this variable to pass information from save time to commit time.
|
374
|
+
# Make sure this doesn't persist across multiple transactions
|
375
|
+
@_previous_changes_for_#{column} = nil
|
352
376
|
end
|
353
377
|
|
354
378
|
def remove_previously_stored_#{column}
|
379
|
+
return unless @_previous_changes_for_#{column}
|
355
380
|
_mounter(:#{column}).remove_previous(*@_previous_changes_for_#{column})
|
356
381
|
end
|
382
|
+
|
383
|
+
def remove_rolled_back_#{column}
|
384
|
+
return unless @_previous_changes_for_#{column}
|
385
|
+
before, after = @_previous_changes_for_#{column}
|
386
|
+
_mounter(:#{column}).remove_previous(after, before)
|
387
|
+
@_previous_changes_for_#{column} = nil
|
388
|
+
end
|
357
389
|
RUBY
|
358
390
|
end
|
359
391
|
|
data/lib/carrierwave/mounter.rb
CHANGED
@@ -92,7 +92,7 @@ module CarrierWave
|
|
92
92
|
@remote_urls = urls
|
93
93
|
|
94
94
|
clear_unstaged
|
95
|
-
urls.zip(remote_request_headers || [])
|
95
|
+
urls.zip(remote_request_headers || []) do |url, header|
|
96
96
|
handle_error do
|
97
97
|
uploader = blank_uploader
|
98
98
|
uploader.download!(url, header || {})
|
@@ -56,12 +56,15 @@ module CarrierWave
|
|
56
56
|
validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
|
57
57
|
validates_download_of column if uploader_option(column.to_sym, :validate_download)
|
58
58
|
|
59
|
+
after_save :"store_#{column}!"
|
59
60
|
before_save :"write_#{column}_identifier"
|
60
|
-
after_save :"store_previous_changes_for_#{column}"
|
61
61
|
after_commit :"remove_#{column}!", :on => :destroy
|
62
62
|
after_commit :"mark_remove_#{column}_false", :on => :update
|
63
|
+
|
64
|
+
after_save :"store_previous_changes_for_#{column}"
|
65
|
+
after_commit :"reset_previous_changes_for_#{column}"
|
63
66
|
after_commit :"remove_previously_stored_#{column}", :on => :update
|
64
|
-
|
67
|
+
after_rollback :"remove_rolled_back_#{column}"
|
65
68
|
|
66
69
|
mod = Module.new
|
67
70
|
prepend mod
|
@@ -88,7 +88,7 @@ module CarrierWave
|
|
88
88
|
#
|
89
89
|
# === Parameters
|
90
90
|
#
|
91
|
-
# [format (#to_s)] an
|
91
|
+
# [format (#to_s)] an abbreviation of the format
|
92
92
|
#
|
93
93
|
# === Yields
|
94
94
|
#
|
@@ -263,8 +263,8 @@ module CarrierWave
|
|
263
263
|
FileUtils.mv image.path, current_path
|
264
264
|
|
265
265
|
image.run_command("identify", current_path)
|
266
|
-
rescue ::MiniMagick::Error, ::MiniMagick::Invalid
|
267
|
-
message = I18n.translate(:"errors.messages.
|
266
|
+
rescue ::MiniMagick::Error, ::MiniMagick::Invalid
|
267
|
+
message = I18n.translate(:"errors.messages.processing_error")
|
268
268
|
raise CarrierWave::ProcessingError, message
|
269
269
|
ensure
|
270
270
|
image.destroy! if image
|
@@ -306,11 +306,11 @@ module CarrierWave
|
|
306
306
|
|
307
307
|
if File.extname(result.path) != File.extname(current_path)
|
308
308
|
move_to = current_path.chomp(File.extname(current_path)) + File.extname(result.path)
|
309
|
-
file.content_type = ::
|
309
|
+
file.content_type = Marcel::Magic.by_path(move_to).try(:type)
|
310
310
|
file.move_to(move_to, permissions, directory_permissions)
|
311
311
|
end
|
312
|
-
rescue ::MiniMagick::Error, ::MiniMagick::Invalid
|
313
|
-
message = I18n.translate(:"errors.messages.
|
312
|
+
rescue ::MiniMagick::Error, ::MiniMagick::Invalid
|
313
|
+
message = I18n.translate(:"errors.messages.processing_error")
|
314
314
|
raise CarrierWave::ProcessingError, message
|
315
315
|
end
|
316
316
|
|
@@ -109,7 +109,7 @@ module CarrierWave
|
|
109
109
|
#
|
110
110
|
# === Parameters
|
111
111
|
#
|
112
|
-
# [format (#to_s)] an
|
112
|
+
# [format (#to_s)] an abbreviation of the format
|
113
113
|
#
|
114
114
|
# === Yields
|
115
115
|
#
|
@@ -363,15 +363,15 @@ module CarrierWave
|
|
363
363
|
if options[:format] || @format
|
364
364
|
frames.write("#{options[:format] || @format}:#{current_path}", &write_block)
|
365
365
|
move_to = current_path.chomp(File.extname(current_path)) + ".#{options[:format] || @format}"
|
366
|
-
file.content_type = ::
|
366
|
+
file.content_type = Marcel::Magic.by_path(move_to).try(:type)
|
367
367
|
file.move_to(move_to, permissions, directory_permissions)
|
368
368
|
else
|
369
369
|
frames.write(current_path, &write_block)
|
370
370
|
end
|
371
371
|
|
372
372
|
destroy_image(frames)
|
373
|
-
rescue ::Magick::ImageMagickError
|
374
|
-
raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.
|
373
|
+
rescue ::Magick::ImageMagickError
|
374
|
+
raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.processing_error")
|
375
375
|
end
|
376
376
|
|
377
377
|
private
|
@@ -259,11 +259,11 @@ module CarrierWave
|
|
259
259
|
|
260
260
|
if File.extname(result.path) != File.extname(current_path)
|
261
261
|
move_to = current_path.chomp(File.extname(current_path)) + File.extname(result.path)
|
262
|
-
file.content_type = ::
|
262
|
+
file.content_type = Marcel::Magic.by_path(move_to).try(:type)
|
263
263
|
file.move_to(move_to, permissions, directory_permissions)
|
264
264
|
end
|
265
|
-
rescue ::Vips::Error
|
266
|
-
message = I18n.translate(:"errors.messages.
|
265
|
+
rescue ::Vips::Error
|
266
|
+
message = I18n.translate(:"errors.messages.processing_error")
|
267
267
|
raise CarrierWave::ProcessingError, message
|
268
268
|
end
|
269
269
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'active_support/core_ext/string/multibyte'
|
3
|
-
require 'mini_mime'
|
4
3
|
require 'marcel'
|
5
4
|
|
6
5
|
module CarrierWave
|
@@ -14,6 +13,7 @@ module CarrierWave
|
|
14
13
|
# It's probably needlessly comprehensive and complex. Help is appreciated.
|
15
14
|
#
|
16
15
|
class SanitizedFile
|
16
|
+
include CarrierWave::Utilities::FileName
|
17
17
|
|
18
18
|
attr_reader :file
|
19
19
|
|
@@ -59,29 +59,6 @@ module CarrierWave
|
|
59
59
|
|
60
60
|
alias_method :identifier, :filename
|
61
61
|
|
62
|
-
##
|
63
|
-
# Returns the part of the filename before the extension. So if a file is called 'test.jpeg'
|
64
|
-
# this would return 'test'
|
65
|
-
#
|
66
|
-
# === Returns
|
67
|
-
#
|
68
|
-
# [String] the first part of the filename
|
69
|
-
#
|
70
|
-
def basename
|
71
|
-
split_extension(filename)[0] if filename
|
72
|
-
end
|
73
|
-
|
74
|
-
##
|
75
|
-
# Returns the file extension
|
76
|
-
#
|
77
|
-
# === Returns
|
78
|
-
#
|
79
|
-
# [String] the extension
|
80
|
-
#
|
81
|
-
def extension
|
82
|
-
split_extension(filename)[1] if filename
|
83
|
-
end
|
84
|
-
|
85
62
|
##
|
86
63
|
# Returns the file's size.
|
87
64
|
#
|
@@ -159,7 +136,7 @@ module CarrierWave
|
|
159
136
|
else
|
160
137
|
@file.try(:rewind)
|
161
138
|
@content = @file.read
|
162
|
-
@file.try(:close) unless @file.try(:closed?)
|
139
|
+
@file.try(:close) unless @file.class.ancestors.include?(::StringIO) || @file.try(:closed?)
|
163
140
|
@content
|
164
141
|
end
|
165
142
|
end
|
@@ -261,8 +238,8 @@ module CarrierWave
|
|
261
238
|
def content_type
|
262
239
|
@content_type ||=
|
263
240
|
existing_content_type ||
|
264
|
-
|
265
|
-
|
241
|
+
marcel_magic_by_mime_type ||
|
242
|
+
marcel_magic_by_path
|
266
243
|
end
|
267
244
|
|
268
245
|
##
|
@@ -314,6 +291,7 @@ module CarrierWave
|
|
314
291
|
|
315
292
|
# Sanitize the filename, to prevent hacking
|
316
293
|
def sanitize(name)
|
294
|
+
name = name.scrub
|
317
295
|
name = name.tr("\\", "/") # work-around for IE
|
318
296
|
name = File.basename(name)
|
319
297
|
name = name.gsub(sanitize_regexp,"_")
|
@@ -324,47 +302,31 @@ module CarrierWave
|
|
324
302
|
|
325
303
|
def existing_content_type
|
326
304
|
if @file.respond_to?(:content_type) && @file.content_type
|
327
|
-
|
305
|
+
@file.content_type.to_s.chomp
|
328
306
|
end
|
329
307
|
end
|
330
308
|
|
331
|
-
def
|
332
|
-
|
333
|
-
type = File.open(path) do |file|
|
334
|
-
Marcel::Magic.by_magic(file).try(:type)
|
335
|
-
end
|
309
|
+
def marcel_magic_by_mime_type
|
310
|
+
return unless path
|
336
311
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
end
|
312
|
+
type = File.open(path) do |file|
|
313
|
+
Marcel::Magic.by_magic(file).try(:type)
|
314
|
+
end
|
341
315
|
|
342
|
-
|
316
|
+
if type.nil?
|
317
|
+
type = Marcel::Magic.by_path(path).try(:type)
|
318
|
+
type = 'invalid/invalid' unless type.nil? || type.start_with?('text/') || type.start_with?('application/json')
|
343
319
|
end
|
320
|
+
|
321
|
+
type
|
344
322
|
rescue Errno::ENOENT
|
345
323
|
nil
|
346
324
|
end
|
347
325
|
|
348
|
-
def
|
326
|
+
def marcel_magic_by_path
|
349
327
|
return unless path
|
350
|
-
mime_type = ::MiniMime.lookup_by_filename(path)
|
351
|
-
@content_type = (mime_type && mime_type.content_type).to_s
|
352
|
-
end
|
353
328
|
|
354
|
-
|
355
|
-
# regular expressions to try for identifying extensions
|
356
|
-
extension_matchers = [
|
357
|
-
/\A(.+)\.(tar\.([glx]?z|bz2))\z/, # matches "something.tar.gz"
|
358
|
-
/\A(.+)\.([^\.]+)\z/ # matches "something.jpg"
|
359
|
-
]
|
360
|
-
|
361
|
-
extension_matchers.each do |regexp|
|
362
|
-
if filename =~ regexp
|
363
|
-
return $1, $2
|
364
|
-
end
|
365
|
-
end
|
366
|
-
return filename, "" # In case we weren't able to split the extension
|
329
|
+
Marcel::Magic.by_path(path).to_s
|
367
330
|
end
|
368
|
-
|
369
331
|
end # SanitizedFile
|
370
332
|
end # CarrierWave
|
@@ -17,7 +17,7 @@ module CarrierWave
|
|
17
17
|
#
|
18
18
|
# By default, store!() uses copy_to(), which operates by copying the file
|
19
19
|
# from the cache to the store, then deleting the file from the cache.
|
20
|
-
# If move_to_store() is
|
20
|
+
# If move_to_store() is overridden to return true, then store!() uses move_to(),
|
21
21
|
# which simply moves the file from cache to store. Useful for large files.
|
22
22
|
#
|
23
23
|
# === Parameters
|
@@ -110,7 +110,7 @@ module CarrierWave
|
|
110
110
|
|
111
111
|
def clean_cache!(seconds)
|
112
112
|
Dir.glob(::File.expand_path(::File.join(uploader.cache_dir, '*'), CarrierWave.root)).each do |dir|
|
113
|
-
# generate_cache_id returns key
|
113
|
+
# generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
|
114
114
|
time = dir.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first.map(&:to_i)
|
115
115
|
time = Time.at(*time)
|
116
116
|
if time < (Time.now.utc - seconds)
|
@@ -146,7 +146,7 @@ module CarrierWave
|
|
146
146
|
:key => uploader.fog_directory,
|
147
147
|
:public => uploader.fog_public
|
148
148
|
).files.all(:prefix => uploader.cache_dir).each do |file|
|
149
|
-
# generate_cache_id returns key
|
149
|
+
# generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
|
150
150
|
matched = file.key.match(/(\d+)-\d+-\d+(?:-\d+)?/)
|
151
151
|
next unless matched
|
152
152
|
time = Time.at(matched[1].to_i)
|
@@ -165,6 +165,7 @@ module CarrierWave
|
|
165
165
|
DEFAULT_S3_REGION = 'us-east-1'
|
166
166
|
|
167
167
|
include CarrierWave::Utilities::Uri
|
168
|
+
include CarrierWave::Utilities::FileName
|
168
169
|
|
169
170
|
##
|
170
171
|
# Current local path to file
|
@@ -258,18 +259,6 @@ module CarrierWave
|
|
258
259
|
end
|
259
260
|
end
|
260
261
|
|
261
|
-
##
|
262
|
-
# Return extension of file
|
263
|
-
#
|
264
|
-
# === Returns
|
265
|
-
#
|
266
|
-
# [String] extension of file or nil if the file has no extension
|
267
|
-
#
|
268
|
-
def extension
|
269
|
-
path_elements = path.split('.')
|
270
|
-
path_elements.last if path_elements.size > 1
|
271
|
-
end
|
272
|
-
|
273
262
|
##
|
274
263
|
# deprecated: All attributes from file (includes headers)
|
275
264
|
#
|
@@ -409,7 +398,7 @@ module CarrierWave
|
|
409
398
|
end
|
410
399
|
|
411
400
|
##
|
412
|
-
# Return url to file, if
|
401
|
+
# Return url to file, if available
|
413
402
|
#
|
414
403
|
# === Returns
|
415
404
|
#
|
@@ -451,7 +440,7 @@ module CarrierWave
|
|
451
440
|
# @return [CarrierWave::Storage::Fog::File] the location where the file will be stored.
|
452
441
|
#
|
453
442
|
def copy_to(new_path)
|
454
|
-
|
443
|
+
file.copy(@uploader.fog_directory, new_path, copy_options)
|
455
444
|
CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
|
456
445
|
end
|
457
446
|
|
@@ -498,7 +487,7 @@ module CarrierWave
|
|
498
487
|
def copy_options
|
499
488
|
options = {}
|
500
489
|
options.merge!(acl_header) if acl_header.present?
|
501
|
-
options['Content-Type'] ||= content_type if content_type
|
490
|
+
options[fog_provider == "Google" ? :content_type : 'Content-Type'] ||= content_type if content_type
|
502
491
|
options.merge(@uploader.fog_attributes)
|
503
492
|
end
|
504
493
|
|
@@ -110,7 +110,7 @@ module CarrierWave
|
|
110
110
|
#
|
111
111
|
# By default, cache!() uses copy_to(), which operates by copying the file
|
112
112
|
# to the cache, then deleting the original file. If move_to_cache() is
|
113
|
-
#
|
113
|
+
# overridden to return true, then cache!() uses move_to(), which simply
|
114
114
|
# moves the file to the cache. Useful for large files.
|
115
115
|
#
|
116
116
|
# === Parameters
|
@@ -44,6 +44,7 @@ module CarrierWave
|
|
44
44
|
add_config :validate_download
|
45
45
|
add_config :mount_on
|
46
46
|
add_config :cache_only
|
47
|
+
add_config :download_retry_count
|
47
48
|
|
48
49
|
# set default values
|
49
50
|
reset_config
|
@@ -210,6 +211,7 @@ module CarrierWave
|
|
210
211
|
config.base_path = CarrierWave.base_path
|
211
212
|
config.enable_processing = true
|
212
213
|
config.ensure_multipart_form = true
|
214
|
+
config.download_retry_count = 0
|
213
215
|
end
|
214
216
|
end
|
215
217
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
|
-
module
|
3
|
+
module ContentTypeAllowlist
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_content_type_allowlist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -29,32 +29,34 @@ module CarrierWave
|
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
def content_type_allowlist
|
32
|
-
if respond_to?(:content_type_whitelist)
|
33
|
-
ActiveSupport::Deprecation.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
|
34
|
-
@content_type_whitelist_warned = true
|
35
|
-
content_type_whitelist
|
36
|
-
end
|
37
32
|
end
|
38
33
|
|
39
34
|
private
|
40
35
|
|
41
|
-
def
|
42
|
-
|
36
|
+
def check_content_type_allowlist!(new_file)
|
37
|
+
allowlist = content_type_allowlist
|
38
|
+
if !allowlist && respond_to?(:content_type_whitelist) && content_type_whitelist
|
39
|
+
ActiveSupport::Deprecation.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
|
40
|
+
@content_type_whitelist_warned = true
|
41
|
+
allowlist = content_type_whitelist
|
42
|
+
end
|
43
|
+
|
44
|
+
return unless allowlist
|
43
45
|
|
44
46
|
content_type = new_file.content_type
|
45
|
-
if !
|
46
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
47
|
-
allowed_types: Array(
|
47
|
+
if !allowlisted_content_type?(allowlist, content_type)
|
48
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_allowlist_error", content_type: content_type,
|
49
|
+
allowed_types: Array(allowlist).join(", "), default: :"errors.messages.content_type_whitelist_error")
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
51
|
-
def
|
52
|
-
Array(
|
53
|
+
def allowlisted_content_type?(allowlist, content_type)
|
54
|
+
Array(allowlist).any? do |item|
|
53
55
|
item = Regexp.quote(item) if item.class != Regexp
|
54
|
-
content_type =~
|
56
|
+
content_type =~ /#{item}/
|
55
57
|
end
|
56
58
|
end
|
57
59
|
|
58
|
-
end #
|
60
|
+
end # ContentTypeAllowlist
|
59
61
|
end # Uploader
|
60
62
|
end # CarrierWave
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
|
-
module
|
3
|
+
module ContentTypeDenylist
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_content_type_denylist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -29,29 +29,34 @@ module CarrierWave
|
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
def content_type_denylist
|
32
|
-
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def check_content_type_denylist!(new_file)
|
37
|
+
denylist = content_type_denylist
|
38
|
+
if !denylist && respond_to?(:content_type_blacklist) && content_type_blacklist
|
33
39
|
ActiveSupport::Deprecation.warn "#content_type_blacklist is deprecated, use #content_type_denylist instead." unless instance_variable_defined?(:@content_type_blacklist_warned)
|
34
40
|
@content_type_blacklist_warned = true
|
35
|
-
content_type_blacklist
|
41
|
+
denylist = content_type_blacklist
|
36
42
|
end
|
37
|
-
end
|
38
43
|
|
39
|
-
|
44
|
+
return unless denylist
|
40
45
|
|
41
|
-
|
42
|
-
|
46
|
+
ActiveSupport::Deprecation.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
|
+
@content_type_denylist_warned = true
|
43
48
|
|
44
49
|
content_type = new_file.content_type
|
45
|
-
if
|
46
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
47
|
-
content_type: content_type, default: :"errors.messages.
|
50
|
+
if denylisted_content_type?(denylist, content_type)
|
51
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_denylist_error",
|
52
|
+
content_type: content_type, default: :"errors.messages.content_type_blacklist_error")
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
51
|
-
def
|
52
|
-
Array(
|
56
|
+
def denylisted_content_type?(denylist, content_type)
|
57
|
+
Array(denylist).any? { |item| content_type =~ /#{item}/ }
|
53
58
|
end
|
54
59
|
|
55
|
-
end #
|
60
|
+
end # ContentTypeDenylist
|
56
61
|
end # Uploader
|
57
62
|
end # CarrierWave
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
|
-
module
|
3
|
+
module ExtensionAllowlist
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_extension_allowlist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -32,30 +32,32 @@ module CarrierWave
|
|
32
32
|
# end
|
33
33
|
#
|
34
34
|
def extension_allowlist
|
35
|
-
if respond_to?(:extension_whitelist)
|
36
|
-
ActiveSupport::Deprecation.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
|
37
|
-
@extension_whitelist_warned = true
|
38
|
-
extension_whitelist
|
39
|
-
end
|
40
35
|
end
|
41
36
|
|
42
37
|
private
|
43
38
|
|
44
|
-
def
|
45
|
-
|
39
|
+
def check_extension_allowlist!(new_file)
|
40
|
+
allowlist = extension_allowlist
|
41
|
+
if !allowlist && respond_to?(:extension_whitelist) && extension_whitelist
|
42
|
+
ActiveSupport::Deprecation.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
|
43
|
+
@extension_whitelist_warned = true
|
44
|
+
allowlist = extension_whitelist
|
45
|
+
end
|
46
|
+
|
47
|
+
return unless allowlist
|
46
48
|
|
47
49
|
extension = new_file.extension.to_s
|
48
|
-
if !
|
50
|
+
if !allowlisted_extension?(allowlist, extension)
|
49
51
|
# Look for whitelist first, then fallback to allowlist
|
50
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
51
|
-
allowed_types: Array(
|
52
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_allowlist_error", extension: new_file.extension.inspect,
|
53
|
+
allowed_types: Array(allowlist).join(", "), default: :"errors.messages.extension_whitelist_error")
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
|
-
def
|
57
|
+
def allowlisted_extension?(allowlist, extension)
|
56
58
|
downcase_extension = extension.downcase
|
57
|
-
Array(
|
59
|
+
Array(allowlist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
|
58
60
|
end
|
59
|
-
end #
|
61
|
+
end # ExtensionAllowlist
|
60
62
|
end # Uploader
|
61
63
|
end # CarrierWave
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
|
-
module
|
3
|
+
module ExtensionDenylist
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
before :cache, :
|
7
|
+
before :cache, :check_extension_denylist!
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
@@ -32,27 +32,32 @@ module CarrierWave
|
|
32
32
|
# end
|
33
33
|
#
|
34
34
|
def extension_denylist
|
35
|
-
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def check_extension_denylist!(new_file)
|
40
|
+
denylist = extension_denylist
|
41
|
+
if !denylist && respond_to?(:extension_blacklist) && extension_blacklist
|
36
42
|
ActiveSupport::Deprecation.warn "#extension_blacklist is deprecated, use #extension_denylist instead." unless instance_variable_defined?(:@extension_blacklist_warned)
|
37
43
|
@extension_blacklist_warned = true
|
38
|
-
extension_blacklist
|
44
|
+
denylist = extension_blacklist
|
39
45
|
end
|
40
|
-
end
|
41
46
|
|
42
|
-
|
47
|
+
return unless denylist
|
43
48
|
|
44
|
-
|
45
|
-
|
49
|
+
ActiveSupport::Deprecation.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
|
+
@extension_denylist_warned = true
|
46
51
|
|
47
52
|
extension = new_file.extension.to_s
|
48
|
-
if
|
49
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.
|
50
|
-
prohibited_types: Array(extension_denylist).join(", "), default: :"errors.messages.
|
53
|
+
if denylisted_extension?(denylist, extension)
|
54
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_denylist_error", extension: new_file.extension.inspect,
|
55
|
+
prohibited_types: Array(extension_denylist).join(", "), default: :"errors.messages.extension_blacklist_error")
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
54
|
-
def
|
55
|
-
Array(
|
59
|
+
def denylisted_extension?(denylist, extension)
|
60
|
+
Array(denylist).any? { |item| extension =~ /\A#{item}\z/i }
|
56
61
|
end
|
57
62
|
end
|
58
63
|
end
|
@@ -18,7 +18,7 @@ module CarrierWave
|
|
18
18
|
# Adds a processor callback which applies operations as a file is uploaded.
|
19
19
|
# The argument may be the name of any method of the uploader, expressed as a symbol,
|
20
20
|
# or a list of such methods, or a hash where the key is a method and the value is
|
21
|
-
# an array of arguments to call the method with
|
21
|
+
# an array of arguments to call the method with. Also accepts an :if or :unless condition
|
22
22
|
#
|
23
23
|
# === Parameters
|
24
24
|
#
|
@@ -31,6 +31,7 @@ module CarrierWave
|
|
31
31
|
# process :sepiatone, :vignette
|
32
32
|
# process :scale => [200, 200]
|
33
33
|
# process :scale => [200, 200], :if => :image?
|
34
|
+
# process :scale => [200, 200], :unless => :disallowed_image_type?
|
34
35
|
# process :sepiatone, :if => :image?
|
35
36
|
#
|
36
37
|
# def sepiatone
|
@@ -49,6 +50,10 @@ module CarrierWave
|
|
49
50
|
# ...
|
50
51
|
# end
|
51
52
|
#
|
53
|
+
# def disallowed_image_type?
|
54
|
+
# ...
|
55
|
+
# end
|
56
|
+
#
|
52
57
|
# end
|
53
58
|
#
|
54
59
|
def process(*args)
|
@@ -57,12 +62,12 @@ module CarrierWave
|
|
57
62
|
hash.merge!(arg)
|
58
63
|
end
|
59
64
|
|
60
|
-
|
65
|
+
condition_type = new_processors.keys.detect { |key| [:if, :unless].include?(key) }
|
66
|
+
condition = new_processors.delete(:if) || new_processors.delete(:unless)
|
61
67
|
new_processors.each do |processor, processor_args|
|
62
|
-
self.processors += [[processor, processor_args, condition]]
|
68
|
+
self.processors += [[processor, processor_args, condition, condition_type]]
|
63
69
|
end
|
64
70
|
end
|
65
|
-
|
66
71
|
end # ClassMethods
|
67
72
|
|
68
73
|
##
|
@@ -72,13 +77,19 @@ module CarrierWave
|
|
72
77
|
return unless enable_processing
|
73
78
|
|
74
79
|
with_callbacks(:process, new_file) do
|
75
|
-
self.class.processors.each do |method, args, condition|
|
76
|
-
if(condition)
|
80
|
+
self.class.processors.each do |method, args, condition, condition_type|
|
81
|
+
if(condition && condition_type == :if)
|
77
82
|
if condition.respond_to?(:call)
|
78
83
|
next unless condition.call(self, :args => args, :method => method, :file => new_file)
|
79
84
|
else
|
80
85
|
next unless self.send(condition, new_file)
|
81
86
|
end
|
87
|
+
elsif(condition && condition_type == :unless)
|
88
|
+
if condition.respond_to?(:call)
|
89
|
+
next if condition.call(self, :args => args, :method => method, :file => new_file)
|
90
|
+
else
|
91
|
+
next if self.send(condition, new_file)
|
92
|
+
end
|
82
93
|
end
|
83
94
|
|
84
95
|
if args.is_a? Array
|
@@ -51,6 +51,10 @@ module CarrierWave
|
|
51
51
|
# process :scale => [200, 200]
|
52
52
|
# end
|
53
53
|
#
|
54
|
+
# version :square, :unless => :invalid_image_type? do
|
55
|
+
# process :scale => [100, 100]
|
56
|
+
# end
|
57
|
+
#
|
54
58
|
# end
|
55
59
|
#
|
56
60
|
def version(name, options = {}, &block)
|
@@ -161,7 +165,7 @@ module CarrierWave
|
|
161
165
|
#
|
162
166
|
# === Returns
|
163
167
|
#
|
164
|
-
# [Boolean] True when the version exists according to its :if condition
|
168
|
+
# [Boolean] True when the version exists according to its :if or :unless condition
|
165
169
|
#
|
166
170
|
def version_exists?(name)
|
167
171
|
name = name.to_sym
|
@@ -169,11 +173,20 @@ module CarrierWave
|
|
169
173
|
return false unless self.class.versions.has_key?(name)
|
170
174
|
|
171
175
|
condition = self.class.versions[name].version_options[:if]
|
172
|
-
if
|
173
|
-
|
174
|
-
|
176
|
+
if_condition = self.class.versions[name].version_options[:if]
|
177
|
+
unless_condition = self.class.versions[name].version_options[:unless]
|
178
|
+
|
179
|
+
if(if_condition)
|
180
|
+
if(if_condition.respond_to?(:call))
|
181
|
+
if_condition.call(self, :version => name, :file => file)
|
175
182
|
else
|
176
|
-
send(
|
183
|
+
send(if_condition, file)
|
184
|
+
end
|
185
|
+
elsif(unless_condition)
|
186
|
+
if(unless_condition.respond_to?(:call))
|
187
|
+
!unless_condition.call(self, :version => name, :file => file)
|
188
|
+
else
|
189
|
+
!send(unless_condition, file)
|
177
190
|
end
|
178
191
|
else
|
179
192
|
true
|
data/lib/carrierwave/uploader.rb
CHANGED
@@ -7,10 +7,10 @@ require "carrierwave/uploader/cache"
|
|
7
7
|
require "carrierwave/uploader/store"
|
8
8
|
require "carrierwave/uploader/download"
|
9
9
|
require "carrierwave/uploader/remove"
|
10
|
-
require "carrierwave/uploader/
|
11
|
-
require "carrierwave/uploader/
|
12
|
-
require "carrierwave/uploader/
|
13
|
-
require "carrierwave/uploader/
|
10
|
+
require "carrierwave/uploader/extension_allowlist"
|
11
|
+
require "carrierwave/uploader/extension_denylist"
|
12
|
+
require "carrierwave/uploader/content_type_allowlist"
|
13
|
+
require "carrierwave/uploader/content_type_denylist"
|
14
14
|
require "carrierwave/uploader/file_size"
|
15
15
|
require "carrierwave/uploader/processing"
|
16
16
|
require "carrierwave/uploader/versions"
|
@@ -52,10 +52,10 @@ module CarrierWave
|
|
52
52
|
include CarrierWave::Uploader::Store
|
53
53
|
include CarrierWave::Uploader::Download
|
54
54
|
include CarrierWave::Uploader::Remove
|
55
|
-
include CarrierWave::Uploader::
|
56
|
-
include CarrierWave::Uploader::
|
57
|
-
include CarrierWave::Uploader::
|
58
|
-
include CarrierWave::Uploader::
|
55
|
+
include CarrierWave::Uploader::ExtensionAllowlist
|
56
|
+
include CarrierWave::Uploader::ExtensionDenylist
|
57
|
+
include CarrierWave::Uploader::ContentTypeAllowlist
|
58
|
+
include CarrierWave::Uploader::ContentTypeDenylist
|
59
59
|
include CarrierWave::Uploader::FileSize
|
60
60
|
include CarrierWave::Uploader::Processing
|
61
61
|
include CarrierWave::Uploader::Versions
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Utilities
|
3
|
+
module FileName
|
4
|
+
|
5
|
+
##
|
6
|
+
# Returns the part of the filename before the extension. So if a file is called 'test.jpeg'
|
7
|
+
# this would return 'test'
|
8
|
+
#
|
9
|
+
# === Returns
|
10
|
+
#
|
11
|
+
# [String] the first part of the filename
|
12
|
+
#
|
13
|
+
def basename
|
14
|
+
split_extension(filename)[0] if filename
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Returns the file extension
|
19
|
+
#
|
20
|
+
# === Returns
|
21
|
+
#
|
22
|
+
# [String] extension of file or "" if the file has no extension
|
23
|
+
#
|
24
|
+
def extension
|
25
|
+
split_extension(filename)[1] if filename
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def split_extension(filename)
|
31
|
+
# regular expressions to try for identifying extensions
|
32
|
+
extension_matchers = [
|
33
|
+
/\A(.+)\.(tar\.([glx]?z|bz2))\z/, # matches "something.tar.gz"
|
34
|
+
/\A(.+)\.([^\.]+)\z/ # matches "something.jpg"
|
35
|
+
]
|
36
|
+
|
37
|
+
extension_matchers.each do |regexp|
|
38
|
+
if filename =~ regexp
|
39
|
+
return $1, $2
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
return filename, "" # In case we weren't able to split the extension
|
44
|
+
end
|
45
|
+
end # FileName
|
46
|
+
end # Utilities
|
47
|
+
end # CarrierWave
|
data/lib/carrierwave/version.rb
CHANGED
data/lib/carrierwave.rb
CHANGED
@@ -25,16 +25,7 @@ module CarrierWave
|
|
25
25
|
|
26
26
|
end
|
27
27
|
|
28
|
-
if defined?(
|
29
|
-
|
30
|
-
CarrierWave.root = Merb.dir_for(:public)
|
31
|
-
Merb::BootLoader.before_app_loads do
|
32
|
-
# Setup path for uploaders and load all of them before classes are loaded
|
33
|
-
Merb.push_path(:uploaders, Merb.root / 'app' / 'uploaders', '*.rb')
|
34
|
-
Dir.glob(File.join(Merb.load_paths[:uploaders])).each {|f| require f }
|
35
|
-
end
|
36
|
-
|
37
|
-
elsif defined?(Jets)
|
28
|
+
if defined?(Jets)
|
38
29
|
|
39
30
|
module CarrierWave
|
40
31
|
class Turbine < Jets::Turbine
|
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:
|
4
|
+
version: 3.0.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Nicklas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,42 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 6.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 6.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 6.0.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: mini_mime
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1.3
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 0.1.3
|
40
|
+
version: 6.0.0
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: image_processing
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,34 +94,20 @@ dependencies:
|
|
108
94
|
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
96
|
version: '1.0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: pg
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
97
|
- !ruby/object:Gem::Dependency
|
126
98
|
name: rails
|
127
99
|
requirement: !ruby/object:Gem::Requirement
|
128
100
|
requirements:
|
129
101
|
- - ">="
|
130
102
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
103
|
+
version: 6.0.0
|
132
104
|
type: :development
|
133
105
|
prerelease: false
|
134
106
|
version_requirements: !ruby/object:Gem::Requirement
|
135
107
|
requirements:
|
136
108
|
- - ">="
|
137
109
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
110
|
+
version: 6.0.0
|
139
111
|
- !ruby/object:Gem::Dependency
|
140
112
|
name: cucumber
|
141
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -371,12 +343,12 @@ files:
|
|
371
343
|
- lib/carrierwave/uploader/cache.rb
|
372
344
|
- lib/carrierwave/uploader/callbacks.rb
|
373
345
|
- lib/carrierwave/uploader/configuration.rb
|
374
|
-
- lib/carrierwave/uploader/
|
375
|
-
- lib/carrierwave/uploader/
|
346
|
+
- lib/carrierwave/uploader/content_type_allowlist.rb
|
347
|
+
- lib/carrierwave/uploader/content_type_denylist.rb
|
376
348
|
- lib/carrierwave/uploader/default_url.rb
|
377
349
|
- lib/carrierwave/uploader/download.rb
|
378
|
-
- lib/carrierwave/uploader/
|
379
|
-
- lib/carrierwave/uploader/
|
350
|
+
- lib/carrierwave/uploader/extension_allowlist.rb
|
351
|
+
- lib/carrierwave/uploader/extension_denylist.rb
|
380
352
|
- lib/carrierwave/uploader/file_size.rb
|
381
353
|
- lib/carrierwave/uploader/mountable.rb
|
382
354
|
- lib/carrierwave/uploader/processing.rb
|
@@ -387,6 +359,7 @@ files:
|
|
387
359
|
- lib/carrierwave/uploader/url.rb
|
388
360
|
- lib/carrierwave/uploader/versions.rb
|
389
361
|
- lib/carrierwave/utilities.rb
|
362
|
+
- lib/carrierwave/utilities/file_name.rb
|
390
363
|
- lib/carrierwave/utilities/uri.rb
|
391
364
|
- lib/carrierwave/validations/active_model.rb
|
392
365
|
- lib/carrierwave/version.rb
|
@@ -405,14 +378,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
405
378
|
requirements:
|
406
379
|
- - ">="
|
407
380
|
- !ruby/object:Gem::Version
|
408
|
-
version: 2.
|
381
|
+
version: 2.5.0
|
409
382
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
410
383
|
requirements:
|
411
|
-
- - "
|
384
|
+
- - ">"
|
412
385
|
- !ruby/object:Gem::Version
|
413
|
-
version:
|
386
|
+
version: 1.3.1
|
414
387
|
requirements: []
|
415
|
-
rubygems_version: 3.
|
388
|
+
rubygems_version: 3.3.7
|
416
389
|
signing_key:
|
417
390
|
specification_version: 4
|
418
391
|
summary: Ruby file upload library
|