paperclip 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/issue_template.md +3 -0
- data/MIGRATING-ES.md +317 -0
- data/MIGRATING.md +375 -0
- data/NEWS +17 -0
- data/README.md +26 -4
- data/UPGRADING +3 -3
- data/features/step_definitions/attachment_steps.rb +10 -10
- data/lib/paperclip.rb +1 -0
- data/lib/paperclip/attachment.rb +19 -6
- data/lib/paperclip/filename_cleaner.rb +0 -1
- data/lib/paperclip/geometry_detector_factory.rb +1 -1
- data/lib/paperclip/interpolations.rb +6 -1
- data/lib/paperclip/io_adapters/abstract_adapter.rb +11 -10
- data/lib/paperclip/io_adapters/attachment_adapter.rb +7 -1
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +2 -1
- data/lib/paperclip/io_adapters/uri_adapter.rb +8 -6
- data/lib/paperclip/logger.rb +1 -1
- data/lib/paperclip/media_type_spoof_detector.rb +8 -5
- data/lib/paperclip/processor.rb +10 -2
- data/lib/paperclip/schema.rb +1 -1
- data/lib/paperclip/storage/fog.rb +1 -1
- data/lib/paperclip/style.rb +0 -1
- data/lib/paperclip/thumbnail.rb +4 -1
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +4 -0
- data/lib/paperclip/version.rb +1 -1
- data/spec/paperclip/attachment_processing_spec.rb +0 -1
- data/spec/paperclip/attachment_spec.rb +17 -2
- data/spec/paperclip/filename_cleaner_spec.rb +0 -1
- data/spec/paperclip/integration_spec.rb +41 -5
- data/spec/paperclip/interpolations_spec.rb +9 -0
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +28 -0
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +33 -16
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +56 -8
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +1 -1
- data/spec/paperclip/media_type_spoof_detector_spec.rb +26 -0
- data/spec/paperclip/schema_spec.rb +46 -46
- data/spec/paperclip/style_spec.rb +0 -1
- data/spec/paperclip/thumbnail_spec.rb +5 -3
- data/spec/paperclip/url_generator_spec.rb +0 -1
- data/spec/support/model_reconstruction.rb +2 -2
- metadata +9 -6
data/NEWS
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
6.1.0 (2018-07-27):
|
2
|
+
|
3
|
+
* BUGFIX: Don't double-encode URLs (Roderick Monje).
|
4
|
+
* BUGFIX: Only use the content_type when it exists (Jean-Philippe Doyle).
|
5
|
+
* STABILITY: Better handling of the content-disposition header. Now supports
|
6
|
+
file name that is either enclosed or not in double quotes and is case
|
7
|
+
insensitive as per RC6266 grammar (Hasan Kumar, Yves Riel).
|
8
|
+
* STABILITY: Change database column type of attachment file size from unsigned 4-byte
|
9
|
+
`integer` to unsigned 8-byte `bigint`. The former type limits attachment size
|
10
|
+
to just over 2GB, which can easily be exceeded by a large video file (Laurent
|
11
|
+
Arnoud, Alen Zamanyan).
|
12
|
+
* STABILITY: Better error message when thumbnail processing errors (Hayden Ball).
|
13
|
+
* STABILITY: Fix file linking issues around Windows (Akihiko Odaki).
|
14
|
+
* STABILITY: Files without an extension will now be checked for spoofing attempts
|
15
|
+
(George Walters II).
|
16
|
+
* STABILITY: Manually close Tempfiles when we are done with them (Erkki Eilonen).
|
17
|
+
|
1
18
|
6.0.0 (2018-03-09):
|
2
19
|
|
3
20
|
* Improvement: Depend only on `aws-sdk-s3` instead of `aws-sdk` (https://github.com/thoughtbot/paperclip/pull/2481)
|
data/README.md
CHANGED
@@ -1,6 +1,28 @@
|
|
1
1
|
Paperclip
|
2
2
|
=========
|
3
3
|
|
4
|
+
# Deprecated
|
5
|
+
|
6
|
+
**[Paperclip is deprecated]**.
|
7
|
+
|
8
|
+
For new projects, we recommend Rails' own [ActiveStorage].
|
9
|
+
|
10
|
+
For existing projects, please consult and contribute to [the migration guide] ([en español]).
|
11
|
+
|
12
|
+
|
13
|
+
We will leave the Issues open as a discussion forum _only_. We do _not_
|
14
|
+
guarantee a response from us in the Issues.
|
15
|
+
|
16
|
+
We are no longer accepting pull requests _except_ pull requests against the
|
17
|
+
migration guide. All other pull requests will be closed without merging.
|
18
|
+
|
19
|
+
[Paperclip is deprecated]: https://robots.thoughtbot.com/closing-the-trombone
|
20
|
+
[ActiveStorage]: http://guides.rubyonrails.org/active_storage_overview.html
|
21
|
+
[the migration guide]: https://github.com/thoughtbot/paperclip/blob/master/MIGRATING.md
|
22
|
+
[en español]: https://github.com/thoughtbot/paperclip/blob/master/MIGRATING-ES.md
|
23
|
+
|
24
|
+
# Existing documentation
|
25
|
+
|
4
26
|
## Documentation valid for `master` branch
|
5
27
|
|
6
28
|
Please check the documentation for the paperclip version you are using:
|
@@ -167,7 +189,7 @@ Paperclip is distributed as a gem, which is how it should be used in your app.
|
|
167
189
|
Include the gem in your Gemfile:
|
168
190
|
|
169
191
|
```ruby
|
170
|
-
gem "paperclip", "~>
|
192
|
+
gem "paperclip", "~> 6.0.0"
|
171
193
|
```
|
172
194
|
|
173
195
|
Or, if you want to get the latest, you can get master from the main paperclip repository:
|
@@ -341,7 +363,7 @@ Lastly, you can also define multiple validations on a single attachment using `v
|
|
341
363
|
|
342
364
|
```ruby
|
343
365
|
validates_attachment :avatar, presence: true,
|
344
|
-
content_type:
|
366
|
+
content_type: "image/jpeg",
|
345
367
|
size: { in: 0..10.kilobytes }
|
346
368
|
```
|
347
369
|
|
@@ -368,7 +390,7 @@ afterwards, then assign manually:
|
|
368
390
|
```ruby
|
369
391
|
class Book < ActiveRecord::Base
|
370
392
|
has_attached_file :document, styles: { thumbnail: "60x60#" }
|
371
|
-
validates_attachment :document, content_type:
|
393
|
+
validates_attachment :document, content_type: "application/pdf"
|
372
394
|
validates_something_else # Other validations that conflict with Paperclip's
|
373
395
|
end
|
374
396
|
|
@@ -400,7 +422,7 @@ image-y ones:
|
|
400
422
|
|
401
423
|
```ruby
|
402
424
|
validates_attachment :avatar,
|
403
|
-
content_type:
|
425
|
+
content_type: ["image/jpeg", "image/gif", "image/png"]
|
404
426
|
```
|
405
427
|
|
406
428
|
`Paperclip::ContentTypeDetector` will attempt to match a file's extension to an
|
data/UPGRADING
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
# NOTE FOR UPGRADING FROM 4.3.0 OR EARLIER #
|
3
3
|
##################################################
|
4
4
|
|
5
|
-
Paperclip is now compatible with aws-sdk
|
5
|
+
Paperclip is now compatible with aws-sdk-s3.
|
6
6
|
|
7
|
-
If you are using S3 storage, aws-sdk
|
7
|
+
If you are using S3 storage, aws-sdk-s3 requires you to make a few small
|
8
8
|
changes:
|
9
9
|
|
10
10
|
* You must set the `s3_region`
|
@@ -13,5 +13,5 @@ changes:
|
|
13
13
|
using a hyphen. For example, `:public_read` needs to be changed to
|
14
14
|
`public-read`.
|
15
15
|
|
16
|
-
For a walkthrough of upgrading from 4 to 5 and aws-sdk >= 2.0 you can watch
|
16
|
+
For a walkthrough of upgrading from 4 to *5* (not 6) and aws-sdk >= 2.0 you can watch
|
17
17
|
http://rubythursday.com/episodes/ruby-snack-27-upgrade-paperclip-and-aws-sdk-in-prep-for-rails-5
|
@@ -84,12 +84,12 @@ end
|
|
84
84
|
|
85
85
|
Then /^I should have attachment columns for "([^"]*)"$/ do |attachment_name|
|
86
86
|
cd(".") do
|
87
|
-
columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.
|
87
|
+
columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.sql_type] }.inspect"`.strip)
|
88
88
|
expect_columns = [
|
89
|
-
["#{attachment_name}_file_name",
|
90
|
-
["#{attachment_name}_content_type",
|
91
|
-
["#{attachment_name}_file_size",
|
92
|
-
["#{attachment_name}_updated_at",
|
89
|
+
["#{attachment_name}_file_name", "varchar"],
|
90
|
+
["#{attachment_name}_content_type", "varchar"],
|
91
|
+
["#{attachment_name}_file_size", "bigint"],
|
92
|
+
["#{attachment_name}_updated_at", "datetime"]
|
93
93
|
]
|
94
94
|
expect(columns).to include(*expect_columns)
|
95
95
|
end
|
@@ -97,12 +97,12 @@ end
|
|
97
97
|
|
98
98
|
Then /^I should not have attachment columns for "([^"]*)"$/ do |attachment_name|
|
99
99
|
cd(".") do
|
100
|
-
columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.
|
100
|
+
columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.sql_type] }.inspect"`.strip)
|
101
101
|
expect_columns = [
|
102
|
-
["#{attachment_name}_file_name",
|
103
|
-
["#{attachment_name}_content_type",
|
104
|
-
["#{attachment_name}_file_size",
|
105
|
-
["#{attachment_name}_updated_at",
|
102
|
+
["#{attachment_name}_file_name", "varchar"],
|
103
|
+
["#{attachment_name}_content_type", "varchar"],
|
104
|
+
["#{attachment_name}_file_size", "bigint"],
|
105
|
+
["#{attachment_name}_updated_at", "datetime"]
|
106
106
|
]
|
107
107
|
|
108
108
|
expect(columns).not_to include(*expect_columns)
|
data/lib/paperclip.rb
CHANGED
data/lib/paperclip/attachment.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require 'uri'
|
3
2
|
require 'paperclip/url_generator'
|
4
3
|
require 'active_support/deprecation'
|
@@ -338,8 +337,15 @@ module Paperclip
|
|
338
337
|
# inconsistencies in timing of S3 commands. It's possible that calling
|
339
338
|
# #reprocess! will lose data if the files are not kept.
|
340
339
|
def reprocess!(*style_args)
|
341
|
-
|
342
|
-
|
340
|
+
saved_flags = @options.slice(
|
341
|
+
:only_process,
|
342
|
+
:preserve_files,
|
343
|
+
:check_validity_before_processing
|
344
|
+
)
|
345
|
+
@options[:only_process] = style_args
|
346
|
+
@options[:preserve_files] = true
|
347
|
+
@options[:check_validity_before_processing] = false
|
348
|
+
|
343
349
|
begin
|
344
350
|
assign(self)
|
345
351
|
save
|
@@ -348,8 +354,7 @@ module Paperclip
|
|
348
354
|
warn "#{e} - skipping file."
|
349
355
|
false
|
350
356
|
ensure
|
351
|
-
@options
|
352
|
-
@options[:preserve_files] = saved_preserve_files
|
357
|
+
@options.merge!(saved_flags)
|
353
358
|
end
|
354
359
|
end
|
355
360
|
|
@@ -532,6 +537,10 @@ module Paperclip
|
|
532
537
|
reduce(original) do |file, processor|
|
533
538
|
file = Paperclip.processor(processor).make(file, style.processor_options, self)
|
534
539
|
intermediate_files << file unless file == @queued_for_write[:original]
|
540
|
+
# if we're processing the original, close + unlink the source tempfile
|
541
|
+
if name == :original
|
542
|
+
@queued_for_write[:original].close(true)
|
543
|
+
end
|
535
544
|
file
|
536
545
|
end
|
537
546
|
|
@@ -591,7 +600,11 @@ module Paperclip
|
|
591
600
|
def unlink_files(files)
|
592
601
|
Array(files).each do |file|
|
593
602
|
file.close unless file.closed?
|
594
|
-
|
603
|
+
|
604
|
+
begin
|
605
|
+
file.unlink if file.respond_to?(:unlink)
|
606
|
+
rescue Errno::ENOENT
|
607
|
+
end
|
595
608
|
end
|
596
609
|
end
|
597
610
|
|
@@ -17,7 +17,7 @@ module Paperclip
|
|
17
17
|
orientation = Paperclip.options[:use_exif_orientation] ?
|
18
18
|
"%[exif:orientation]" : "1"
|
19
19
|
Paperclip.run(
|
20
|
-
"identify",
|
20
|
+
Paperclip.options[:is_windows] ? "magick identify" : "identify",
|
21
21
|
"-format '%wx%h,#{orientation}' :file", {
|
22
22
|
:file => "#{path}[0]"
|
23
23
|
}, {
|
@@ -5,6 +5,7 @@ module Paperclip
|
|
5
5
|
# Paperclip.interpolates method.
|
6
6
|
module Interpolations
|
7
7
|
extend self
|
8
|
+
ID_PARTITION_LIMIT = 1_000_000_000
|
8
9
|
|
9
10
|
# Hash assignment of interpolations. Included only for compatibility,
|
10
11
|
# and is not intended for normal use.
|
@@ -175,7 +176,11 @@ module Paperclip
|
|
175
176
|
def id_partition attachment, style_name
|
176
177
|
case id = attachment.instance.id
|
177
178
|
when Integer
|
178
|
-
|
179
|
+
if id < ID_PARTITION_LIMIT
|
180
|
+
("%09d".freeze % id).scan(/\d{3}/).join("/".freeze)
|
181
|
+
else
|
182
|
+
("%012d".freeze % id).scan(/\d{3}/).join("/".freeze)
|
183
|
+
end
|
179
184
|
when String
|
180
185
|
id.scan(/.{3}/).first(3).join("/".freeze)
|
181
186
|
else
|
@@ -4,7 +4,7 @@ module Paperclip
|
|
4
4
|
class AbstractAdapter
|
5
5
|
OS_RESTRICTED_CHARACTERS = %r{[/:]}
|
6
6
|
|
7
|
-
attr_reader :content_type, :original_filename, :size
|
7
|
+
attr_reader :content_type, :original_filename, :size, :tempfile
|
8
8
|
delegate :binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink, :to => :@tempfile
|
9
9
|
alias :length :size
|
10
10
|
|
@@ -57,15 +57,16 @@ module Paperclip
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def link_or_copy_file(src, dest)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
60
|
+
begin
|
61
|
+
Paperclip.log("Trying to link #{src} to #{dest}")
|
62
|
+
FileUtils.ln(src, dest, force: true) # overwrite existing
|
63
|
+
rescue Errno::EXDEV, Errno::EPERM, Errno::ENOENT, Errno::EEXIST => e
|
64
|
+
Paperclip.log(
|
65
|
+
"Link failed with #{e.message}; copying link #{src} to #{dest}"
|
66
|
+
)
|
67
|
+
FileUtils.cp(src, dest)
|
68
|
+
end
|
69
|
+
|
69
70
|
@destination.close
|
70
71
|
@destination.open.binmode
|
71
72
|
end
|
@@ -31,7 +31,13 @@ module Paperclip
|
|
31
31
|
if source.staged?
|
32
32
|
link_or_copy_file(source.staged_path(@style), destination.path)
|
33
33
|
else
|
34
|
-
|
34
|
+
begin
|
35
|
+
source.copy_to_local_file(@style, destination.path)
|
36
|
+
rescue Errno::EACCES
|
37
|
+
# clean up lingering tempfile if we cannot access source file
|
38
|
+
destination.close(true)
|
39
|
+
raise
|
40
|
+
end
|
35
41
|
end
|
36
42
|
destination
|
37
43
|
end
|
@@ -28,15 +28,17 @@ module Paperclip
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def content_type_from_content
|
31
|
-
|
32
|
-
@content.content_type
|
33
|
-
end
|
31
|
+
@content.meta["content-type"].presence
|
34
32
|
end
|
35
33
|
|
36
34
|
def filename_from_content_disposition
|
37
|
-
if @content.meta.key?("content-disposition")
|
38
|
-
|
39
|
-
|
35
|
+
if @content.meta.key?("content-disposition") && @content.meta["content-disposition"].match(/filename/i)
|
36
|
+
# can include both filename and filename* values according to RCF6266. filename should come first
|
37
|
+
_, filename = @content.meta["content-disposition"].split(/filename\*?\s*=\s*/i)
|
38
|
+
|
39
|
+
# filename can be enclosed in quotes or not
|
40
|
+
matches = filename.match(/"(.*)"/)
|
41
|
+
matches ? matches[1] : filename.split(';')[0]
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
data/lib/paperclip/logger.rb
CHANGED
@@ -11,7 +11,7 @@ module Paperclip
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def spoofed?
|
14
|
-
if has_name? &&
|
14
|
+
if has_name? && media_type_mismatch? && mapping_override_mismatch?
|
15
15
|
Paperclip.log("Content Type Spoof: Filename #{File.basename(@name)} (#{supplied_content_type} from Headers, #{content_types_from_name.map(&:to_s)} from Extension), content type discovered from file command: #{calculated_content_type}. See documentation to allow this combination.")
|
16
16
|
true
|
17
17
|
else
|
@@ -30,15 +30,18 @@ module Paperclip
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def media_type_mismatch?
|
33
|
-
|
33
|
+
extension_type_mismatch? || calculated_type_mismatch?
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
supplied_media_type.present? &&
|
36
|
+
def extension_type_mismatch?
|
37
|
+
supplied_media_type.present? &&
|
38
|
+
has_extension? &&
|
39
|
+
!media_types_from_name.include?(supplied_media_type)
|
38
40
|
end
|
39
41
|
|
40
42
|
def calculated_type_mismatch?
|
41
|
-
|
43
|
+
supplied_media_type.present? &&
|
44
|
+
!calculated_content_type.include?(supplied_media_type)
|
42
45
|
end
|
43
46
|
|
44
47
|
def mapping_override_mismatch?
|
data/lib/paperclip/processor.rb
CHANGED
@@ -37,13 +37,21 @@ module Paperclip
|
|
37
37
|
# The convert method runs the convert binary with the provided arguments.
|
38
38
|
# See Paperclip.run for the available options.
|
39
39
|
def convert(arguments = "", local_options = {})
|
40
|
-
Paperclip.run(
|
40
|
+
Paperclip.run(
|
41
|
+
Paperclip.options[:is_windows] ? "magick convert" : "convert",
|
42
|
+
arguments,
|
43
|
+
local_options,
|
44
|
+
)
|
41
45
|
end
|
42
46
|
|
43
47
|
# The identify method runs the identify binary with the provided arguments.
|
44
48
|
# See Paperclip.run for the available options.
|
45
49
|
def identify(arguments = "", local_options = {})
|
46
|
-
Paperclip.run(
|
50
|
+
Paperclip.run(
|
51
|
+
Paperclip.options[:is_windows] ? "magick identify" : "identify",
|
52
|
+
arguments,
|
53
|
+
local_options,
|
54
|
+
)
|
47
55
|
end
|
48
56
|
end
|
49
57
|
end
|
data/lib/paperclip/schema.rb
CHANGED
@@ -19,7 +19,7 @@ module Paperclip
|
|
19
19
|
# store your files. Remember that the bucket must be unique across
|
20
20
|
# all of Amazon S3. If the bucket does not exist, Paperclip will
|
21
21
|
# attempt to create it.
|
22
|
-
# * +fog_file
|
22
|
+
# * +fog_file+: This can be hash or lambda returning hash. The
|
23
23
|
# value is used as base properties for new uploaded file.
|
24
24
|
# * +path+: This is the key under the bucket in which the file will
|
25
25
|
# be stored. The URL will be constructed from the bucket and the
|
data/lib/paperclip/style.rb
CHANGED
data/lib/paperclip/thumbnail.rb
CHANGED
@@ -85,7 +85,10 @@ module Paperclip
|
|
85
85
|
dest: File.expand_path(dst.path),
|
86
86
|
)
|
87
87
|
rescue Terrapin::ExitStatusError => e
|
88
|
-
|
88
|
+
if @whiny
|
89
|
+
message = "There was an error processing the thumbnail for #{@basename}:\n" + e.message
|
90
|
+
raise Paperclip::Error, message
|
91
|
+
end
|
89
92
|
rescue Terrapin::CommandNotFoundError => e
|
90
93
|
raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `convert` command. Please install ImageMagick.")
|
91
94
|
end
|
@@ -8,6 +8,10 @@ module Paperclip
|
|
8
8
|
if Paperclip::MediaTypeSpoofDetector.using(adapter, value.original_filename, value.content_type).spoofed?
|
9
9
|
record.errors.add(attribute, :spoofed_media_type)
|
10
10
|
end
|
11
|
+
|
12
|
+
if adapter.tempfile
|
13
|
+
adapter.tempfile.close(true)
|
14
|
+
end
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
data/lib/paperclip/version.rb
CHANGED