paperclip 5.2.1 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/issue_template.md +3 -0
- data/MIGRATING-ES.md +317 -0
- data/MIGRATING.md +375 -0
- data/NEWS +36 -0
- data/README.md +52 -18
- data/UPGRADING +3 -3
- data/features/step_definitions/attachment_steps.rb +10 -10
- data/features/step_definitions/rails_steps.rb +1 -1
- data/lib/generators/paperclip/paperclip_generator.rb +9 -1
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
- data/lib/paperclip/attachment.rb +19 -6
- data/lib/paperclip/file_command_content_type_detector.rb +1 -1
- data/lib/paperclip/filename_cleaner.rb +0 -1
- data/lib/paperclip/geometry_detector_factory.rb +3 -3
- data/lib/paperclip/helpers.rb +3 -3
- data/lib/paperclip/interpolations.rb +6 -1
- data/lib/paperclip/io_adapters/abstract_adapter.rb +11 -6
- 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 +11 -7
- data/lib/paperclip/processor.rb +10 -2
- data/lib/paperclip/schema.rb +1 -1
- data/lib/paperclip/storage/fog.rb +3 -2
- data/lib/paperclip/storage/s3.rb +8 -16
- data/lib/paperclip/style.rb +0 -1
- data/lib/paperclip/thumbnail.rb +8 -5
- data/lib/paperclip/url_generator.rb +1 -0
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +4 -0
- data/lib/paperclip/version.rb +1 -1
- data/lib/paperclip.rb +2 -1
- data/paperclip.gemspec +2 -2
- data/spec/paperclip/attachment_processing_spec.rb +0 -1
- data/spec/paperclip/attachment_spec.rb +17 -2
- data/spec/paperclip/content_type_detector_spec.rb +1 -1
- data/spec/paperclip/file_command_content_type_detector_spec.rb +15 -1
- 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 +59 -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 +41 -0
- data/spec/paperclip/paperclip_spec.rb +13 -13
- data/spec/paperclip/processor_spec.rb +4 -4
- data/spec/paperclip/schema_spec.rb +46 -46
- data/spec/paperclip/storage/fog_spec.rb +5 -0
- data/spec/paperclip/storage/s3_spec.rb +6 -6
- data/spec/paperclip/style_spec.rb +0 -1
- data/spec/paperclip/thumbnail_spec.rb +8 -6
- data/spec/paperclip/url_generator_spec.rb +0 -1
- data/spec/spec_helper.rb +0 -1
- data/spec/support/model_reconstruction.rb +2 -2
- metadata +120 -20
- data/spec/support/conditional_filter_helper.rb +0 -5
@@ -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
|
@@ -117,6 +117,7 @@ module Paperclip
|
|
117
117
|
raise if retried
|
118
118
|
retried = true
|
119
119
|
directory.save
|
120
|
+
file.rewind
|
120
121
|
retry
|
121
122
|
ensure
|
122
123
|
file.rewind
|
@@ -184,7 +185,7 @@ module Paperclip
|
|
184
185
|
private
|
185
186
|
|
186
187
|
def convert_time(time)
|
187
|
-
if time.is_a?(
|
188
|
+
if time.is_a?(Integer)
|
188
189
|
time = Time.now + time
|
189
190
|
end
|
190
191
|
time
|
data/lib/paperclip/storage/s3.rb
CHANGED
@@ -3,8 +3,8 @@ module Paperclip
|
|
3
3
|
# Amazon's S3 file hosting service is a scalable, easy place to store files for
|
4
4
|
# distribution. You can find out more about it at http://aws.amazon.com/s3
|
5
5
|
#
|
6
|
-
# To use Paperclip with S3, include the +aws-sdk+ gem in your Gemfile:
|
7
|
-
# gem 'aws-sdk'
|
6
|
+
# To use Paperclip with S3, include the +aws-sdk-s3+ gem in your Gemfile:
|
7
|
+
# gem 'aws-sdk-s3'
|
8
8
|
# There are a few S3-specific options for has_attached_file:
|
9
9
|
# * +s3_credentials+: Takes a path, a File, a Hash or a Proc. The path (or File) must point
|
10
10
|
# to a YAML file containing the +access_key_id+ and +secret_access_key+ that Amazon
|
@@ -94,8 +94,9 @@ module Paperclip
|
|
94
94
|
# to interpolate. Keys should be unique, like filenames, and despite the fact that
|
95
95
|
# S3 (strictly speaking) does not support directories, you can still use a / to
|
96
96
|
# separate parts of your file name.
|
97
|
-
# * +s3_host_name+: If you are using your bucket in Tokyo region
|
98
|
-
#
|
97
|
+
# * +s3_host_name+: If you are using your bucket in Tokyo region
|
98
|
+
# etc, write host_name (e.g., 's3-ap-northeast-1.amazonaws.com').
|
99
|
+
# * +s3_region+: For aws-sdk-s3, s3_region is required.
|
99
100
|
# * +s3_metadata+: These key/value pairs will be stored with the
|
100
101
|
# object. This option works by prefixing each key with
|
101
102
|
# "x-amz-meta-" before sending it as a header on the object
|
@@ -117,20 +118,16 @@ module Paperclip
|
|
117
118
|
# :s3_storage_class => :REDUCED_REDUNDANCY
|
118
119
|
#
|
119
120
|
# Other storage classes, such as <tt>:STANDARD_IA</tt>, are also available—see the
|
120
|
-
# documentation for the <tt>aws-sdk</tt> gem for the full list.
|
121
|
+
# documentation for the <tt>aws-sdk-s3</tt> gem for the full list.
|
121
122
|
|
122
123
|
module S3
|
123
124
|
def self.extended base
|
124
125
|
begin
|
125
|
-
require
|
126
|
+
require "aws-sdk-s3"
|
126
127
|
rescue LoadError => e
|
127
|
-
e.message << " (You may need to install the aws-sdk gem)"
|
128
|
+
e.message << " (You may need to install the aws-sdk-s3 gem)"
|
128
129
|
raise e
|
129
130
|
end
|
130
|
-
if Gem::Version.new(Aws::VERSION) >= Gem::Version.new(2) &&
|
131
|
-
Gem::Version.new(Aws::VERSION) <= Gem::Version.new("2.0.33")
|
132
|
-
raise LoadError, "paperclip does not support aws-sdk versions 2.0.0 - 2.0.33. Please upgrade aws-sdk to a newer version."
|
133
|
-
end
|
134
131
|
|
135
132
|
base.instance_eval do
|
136
133
|
@s3_options = @options[:s3_options] || {}
|
@@ -158,11 +155,6 @@ module Paperclip
|
|
158
155
|
|
159
156
|
@http_proxy = @options[:http_proxy] || nil
|
160
157
|
|
161
|
-
if @options.has_key?(:use_accelerate_endpoint) &&
|
162
|
-
Gem::Version.new(Aws::VERSION) < Gem::Version.new("2.3.0")
|
163
|
-
raise LoadError, ":use_accelerate_endpoint is only available from aws-sdk version 2.3.0. Please upgrade aws-sdk to a newer version."
|
164
|
-
end
|
165
|
-
|
166
158
|
@use_accelerate_endpoint = @options[:use_accelerate_endpoint]
|
167
159
|
end
|
168
160
|
|
data/lib/paperclip/style.rb
CHANGED
data/lib/paperclip/thumbnail.rb
CHANGED
@@ -84,9 +84,12 @@ module Paperclip
|
|
84
84
|
source: "#{File.expand_path(src.path)}#{frame}",
|
85
85
|
dest: File.expand_path(dst.path),
|
86
86
|
)
|
87
|
-
rescue
|
88
|
-
|
89
|
-
|
87
|
+
rescue Terrapin::ExitStatusError => e
|
88
|
+
if @whiny
|
89
|
+
message = "There was an error processing the thumbnail for #{@basename}:\n" + e.message
|
90
|
+
raise Paperclip::Error, message
|
91
|
+
end
|
92
|
+
rescue Terrapin::CommandNotFoundError => e
|
90
93
|
raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `convert` command. Please install ImageMagick.")
|
91
94
|
end
|
92
95
|
|
@@ -122,9 +125,9 @@ module Paperclip
|
|
122
125
|
@identified_as_animated = ANIMATED_FORMATS.include? identify("-format %m :file", :file => "#{@file.path}[0]").to_s.downcase.strip
|
123
126
|
end
|
124
127
|
@identified_as_animated
|
125
|
-
rescue
|
128
|
+
rescue Terrapin::ExitStatusError => e
|
126
129
|
raise Paperclip::Error, "There was an error running `identify` for #{@basename}" if @whiny
|
127
|
-
rescue
|
130
|
+
rescue Terrapin::CommandNotFoundError => e
|
128
131
|
raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
|
129
132
|
end
|
130
133
|
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
data/lib/paperclip.rb
CHANGED
@@ -67,7 +67,7 @@ end
|
|
67
67
|
require 'mimemagic'
|
68
68
|
require 'mimemagic/overlay'
|
69
69
|
require 'logger'
|
70
|
-
require '
|
70
|
+
require 'terrapin'
|
71
71
|
|
72
72
|
require 'paperclip/railtie' if defined?(Rails::Railtie)
|
73
73
|
|
@@ -98,6 +98,7 @@ module Paperclip
|
|
98
98
|
swallow_stderr: true,
|
99
99
|
use_exif_orientation: true,
|
100
100
|
whiny: true,
|
101
|
+
is_windows: Gem.win_platform?
|
101
102
|
}
|
102
103
|
end
|
103
104
|
|
data/paperclip.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
|
27
27
|
s.add_dependency('activemodel', '>= 4.2.0')
|
28
28
|
s.add_dependency('activesupport', '>= 4.2.0')
|
29
|
-
s.add_dependency('
|
29
|
+
s.add_dependency('terrapin', '~> 0.6.0')
|
30
30
|
s.add_dependency('mime-types')
|
31
31
|
s.add_dependency('mimemagic', '~> 0.3.0')
|
32
32
|
|
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.add_development_dependency('rspec', '~> 3.0')
|
36
36
|
s.add_development_dependency('appraisal')
|
37
37
|
s.add_development_dependency('mocha')
|
38
|
-
s.add_development_dependency('aws-sdk'
|
38
|
+
s.add_development_dependency('aws-sdk-s3')
|
39
39
|
s.add_development_dependency('bourne')
|
40
40
|
s.add_development_dependency('cucumber-rails')
|
41
41
|
s.add_development_dependency('cucumber-expressions', '4.0.3') # TODO: investigate failures on 4.0.4
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require 'spec_helper'
|
3
2
|
|
4
3
|
describe Paperclip::Attachment do
|
@@ -54,6 +53,22 @@ describe Paperclip::Attachment do
|
|
54
53
|
expect(dummy.avatar.path(:original)).to exist
|
55
54
|
end
|
56
55
|
|
56
|
+
it "reprocess works with virtual content_type attribute" do
|
57
|
+
rebuild_class styles: { small: "100x>" }
|
58
|
+
modify_table { |t| t.remove :avatar_content_type }
|
59
|
+
Dummy.send :attr_accessor, :avatar_content_type
|
60
|
+
Dummy.validates_attachment_content_type(
|
61
|
+
:avatar,
|
62
|
+
content_type: %w(image/jpeg image/png)
|
63
|
+
)
|
64
|
+
Dummy.create!(avatar: File.new(fixture_file("50x50.png"), "rb"))
|
65
|
+
|
66
|
+
dummy = Dummy.first
|
67
|
+
dummy.avatar.reprocess!(:small)
|
68
|
+
|
69
|
+
expect(dummy.avatar.path(:small)).to exist
|
70
|
+
end
|
71
|
+
|
57
72
|
context "having a not empty hash as a default option" do
|
58
73
|
before do
|
59
74
|
@old_default_options = Paperclip::Attachment.default_options.dup
|
@@ -1401,7 +1416,7 @@ describe Paperclip::Attachment do
|
|
1401
1416
|
|
1402
1417
|
context "and avatar_file_size column" do
|
1403
1418
|
before do
|
1404
|
-
ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :
|
1419
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :bigint
|
1405
1420
|
rebuild_class
|
1406
1421
|
@dummy = Dummy.new
|
1407
1422
|
end
|
@@ -41,7 +41,7 @@ describe Paperclip::ContentTypeDetector do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'returns a sensible default when the file command is missing' do
|
44
|
-
Paperclip.stubs(:run).raises(
|
44
|
+
Paperclip.stubs(:run).raises(Terrapin::CommandLineError.new)
|
45
45
|
@filename = "/path/to/something"
|
46
46
|
assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new(@filename).detect
|
47
47
|
end
|
@@ -12,7 +12,7 @@ describe Paperclip::FileCommandContentTypeDetector do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'returns a sensible default when the file command is missing' do
|
15
|
-
Paperclip.stubs(:run).raises(
|
15
|
+
Paperclip.stubs(:run).raises(Terrapin::CommandLineError.new)
|
16
16
|
@filename = "/path/to/something"
|
17
17
|
assert_equal "application/octet-stream",
|
18
18
|
Paperclip::FileCommandContentTypeDetector.new(@filename).detect
|
@@ -23,4 +23,18 @@ describe Paperclip::FileCommandContentTypeDetector do
|
|
23
23
|
assert_equal "application/octet-stream",
|
24
24
|
Paperclip::FileCommandContentTypeDetector.new("windows").detect
|
25
25
|
end
|
26
|
+
|
27
|
+
context "#type_from_file_command" do
|
28
|
+
let(:detector) { Paperclip::FileCommandContentTypeDetector.new("html") }
|
29
|
+
|
30
|
+
it "does work with the output of old versions of file" do
|
31
|
+
Paperclip.stubs(:run).returns("text/html charset=us-ascii")
|
32
|
+
expect(detector.detect).to eq("text/html")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "does work with the output of new versions of file" do
|
36
|
+
Paperclip.stubs(:run).returns("text/html; charset=us-ascii")
|
37
|
+
expect(detector.detect).to eq("text/html")
|
38
|
+
end
|
39
|
+
end
|
26
40
|
end
|
@@ -1,16 +1,33 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require 'spec_helper'
|
3
2
|
require 'open-uri'
|
4
3
|
|
5
4
|
describe 'Paperclip' do
|
5
|
+
around do |example|
|
6
|
+
files_before = ObjectSpace.each_object(Tempfile).select do |file|
|
7
|
+
file.path && File.file?(file.path)
|
8
|
+
end
|
9
|
+
|
10
|
+
example.run
|
11
|
+
|
12
|
+
files_after = ObjectSpace.each_object(Tempfile).select do |file|
|
13
|
+
file.path && File.file?(file.path)
|
14
|
+
end
|
15
|
+
|
16
|
+
diff = files_after - files_before
|
17
|
+
expect(diff).to eq([]), "Leaked tempfiles: #{diff.inspect}"
|
18
|
+
end
|
19
|
+
|
6
20
|
context "Many models at once" do
|
7
21
|
before do
|
8
22
|
rebuild_model
|
9
23
|
@file = File.new(fixture_file("5k.png"), 'rb')
|
10
24
|
# Deals with `Too many open files` error
|
11
|
-
|
12
|
-
Dummy.import
|
13
|
-
|
25
|
+
dummies = Array.new(300) { Dummy.new avatar: @file }
|
26
|
+
Dummy.import dummies
|
27
|
+
# save attachment instances to run after hooks including tempfile cleanup
|
28
|
+
# since activerecord-import does not use our usually hooked-in hooks
|
29
|
+
# (such as after_save)
|
30
|
+
dummies.each { |dummy| dummy.avatar.save }
|
14
31
|
end
|
15
32
|
|
16
33
|
after { @file.close }
|
@@ -135,6 +152,14 @@ describe 'Paperclip' do
|
|
135
152
|
end
|
136
153
|
|
137
154
|
it "allows us to selectively create each thumbnail" do
|
155
|
+
skip <<-EXPLANATION
|
156
|
+
#reprocess! calls #assign which calls Paperclip.io_adapters.for
|
157
|
+
which creates the tempfile. #assign then calls #post_process_file which
|
158
|
+
calls MediaTypeSpoofDetectionValidator#validate_each which calls
|
159
|
+
Paperclip.io_adapters.for, which creates another tempfile. That first
|
160
|
+
tempfile is the one that leaks.
|
161
|
+
EXPLANATION
|
162
|
+
|
138
163
|
assert_file_not_exists(@thumb_small_path)
|
139
164
|
assert_file_not_exists(@thumb_large_path)
|
140
165
|
|
@@ -159,7 +184,11 @@ describe 'Paperclip' do
|
|
159
184
|
assert_not_equal File.size(@file.path), @dummy.avatar.size
|
160
185
|
end
|
161
186
|
|
162
|
-
after
|
187
|
+
after do
|
188
|
+
@file.close
|
189
|
+
# save attachment instance to run after hooks (including tempfile cleanup)
|
190
|
+
@dummy.avatar.save
|
191
|
+
end
|
163
192
|
end
|
164
193
|
|
165
194
|
context "A model with attachments scoped under an id" do
|
@@ -347,6 +376,8 @@ describe 'Paperclip' do
|
|
347
376
|
it "is not ok with bad files" do
|
348
377
|
@dummy.avatar = @bad_file
|
349
378
|
assert ! @dummy.valid?
|
379
|
+
# save attachment instance to run after hooks (including tempfile cleanup)
|
380
|
+
@dummy.avatar.save
|
350
381
|
end
|
351
382
|
|
352
383
|
it "knows the difference between good files, bad files, and not files when validating" do
|
@@ -354,8 +385,13 @@ describe 'Paperclip' do
|
|
354
385
|
@d2 = Dummy.find(@dummy.id)
|
355
386
|
@d2.avatar = @file
|
356
387
|
assert @d2.valid?, @d2.errors.full_messages.inspect
|
388
|
+
# save attachment instance to run after hooks (including tempfile cleanup)
|
389
|
+
@d2.avatar.save
|
390
|
+
|
357
391
|
@d2.avatar = @bad_file
|
358
392
|
assert ! @d2.valid?
|
393
|
+
# save attachment instance to run after hooks (including tempfile cleanup)
|
394
|
+
@d2.avatar.save
|
359
395
|
end
|
360
396
|
|
361
397
|
it "is able to reload without saving and not have the file disappear" do
|
@@ -139,6 +139,15 @@ describe Paperclip::Interpolations do
|
|
139
139
|
assert_equal "000/000/023", Paperclip::Interpolations.id_partition(attachment, :style)
|
140
140
|
end
|
141
141
|
|
142
|
+
it "returns the partitioned id when the id is above 999_999_999" do
|
143
|
+
attachment = mock
|
144
|
+
attachment.expects(:id).
|
145
|
+
returns(Paperclip::Interpolations::ID_PARTITION_LIMIT)
|
146
|
+
attachment.expects(:instance).returns(attachment)
|
147
|
+
assert_equal "001/000/000/000",
|
148
|
+
Paperclip::Interpolations.id_partition(attachment, :style)
|
149
|
+
end
|
150
|
+
|
142
151
|
it "returns the partitioned id of the attachment when the id is a string" do
|
143
152
|
attachment = mock
|
144
153
|
attachment.expects(:id).returns("32fnj23oio2f")
|
@@ -93,9 +93,68 @@ describe Paperclip::AbstractAdapter do
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
+
context "#copy_to_tempfile" do
|
97
|
+
around do |example|
|
98
|
+
FileUtils.module_eval do
|
99
|
+
class << self
|
100
|
+
alias paperclip_ln ln
|
101
|
+
|
102
|
+
def ln(*)
|
103
|
+
raise Errno::EXDEV
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
example.run
|
109
|
+
|
110
|
+
FileUtils.module_eval do
|
111
|
+
class << self
|
112
|
+
alias ln paperclip_ln
|
113
|
+
undef paperclip_ln
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should return a readable file even when linking fails" do
|
119
|
+
src = open(fixture_file("5k.png"), "rb")
|
120
|
+
expect(subject.send(:copy_to_tempfile, src).read).to eq src.read
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
96
124
|
context "#original_filename=" do
|
97
125
|
it "should not fail with a nil original filename" do
|
98
126
|
expect { subject.original_filename = nil }.not_to raise_error
|
99
127
|
end
|
100
128
|
end
|
129
|
+
|
130
|
+
context "#link_or_copy_file" do
|
131
|
+
class TestLinkOrCopyAdapter < Paperclip::AbstractAdapter
|
132
|
+
public :copy_to_tempfile, :destination
|
133
|
+
end
|
134
|
+
|
135
|
+
subject { TestLinkOrCopyAdapter.new(nil) }
|
136
|
+
let(:body) { "body" }
|
137
|
+
|
138
|
+
let(:file) do
|
139
|
+
t = Tempfile.new("destination")
|
140
|
+
t.print(body)
|
141
|
+
t.rewind
|
142
|
+
t
|
143
|
+
end
|
144
|
+
|
145
|
+
after do
|
146
|
+
file.close
|
147
|
+
file.unlink
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should be able to read the file" do
|
151
|
+
expect(subject.copy_to_tempfile(file).read).to eq(body)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should be able to reopen the file after symlink has failed" do
|
155
|
+
FileUtils.expects(:ln).raises(Errno::EXDEV)
|
156
|
+
|
157
|
+
expect(subject.copy_to_tempfile(file).read).to eq(body)
|
158
|
+
end
|
159
|
+
end
|
101
160
|
end
|
@@ -3,10 +3,9 @@ require 'spec_helper'
|
|
3
3
|
describe Paperclip::HttpUrlProxyAdapter do
|
4
4
|
before do
|
5
5
|
@open_return = StringIO.new("xxx")
|
6
|
-
@open_return.stubs(:
|
7
|
-
|
8
|
-
|
9
|
-
stubs(:download_content).returns(@open_return)
|
6
|
+
@open_return.stubs(:meta).returns("content-type" => "image/png")
|
7
|
+
Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).
|
8
|
+
returns(@open_return)
|
10
9
|
Paperclip::HttpUrlProxyAdapter.register
|
11
10
|
end
|
12
11
|
|
@@ -69,17 +68,18 @@ describe Paperclip::HttpUrlProxyAdapter do
|
|
69
68
|
end
|
70
69
|
|
71
70
|
context "a url with query params" do
|
72
|
-
|
73
|
-
@url = "https://github.com/thoughtbot/paperclip?file=test"
|
74
|
-
@subject = Paperclip.io_adapters.for(@url)
|
75
|
-
end
|
71
|
+
subject { Paperclip.io_adapters.for(url) }
|
76
72
|
|
77
|
-
after
|
78
|
-
|
79
|
-
|
73
|
+
after { subject.close }
|
74
|
+
|
75
|
+
let(:url) { "https://github.com/thoughtbot/paperclip?file=test" }
|
80
76
|
|
81
77
|
it "returns a file name" do
|
82
|
-
assert_equal "paperclip",
|
78
|
+
assert_equal "paperclip", subject.original_filename
|
79
|
+
end
|
80
|
+
|
81
|
+
it "preserves params" do
|
82
|
+
assert_equal url, subject.instance_variable_get(:@target).to_s
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -107,15 +107,32 @@ describe Paperclip::HttpUrlProxyAdapter do
|
|
107
107
|
end
|
108
108
|
|
109
109
|
context "a url with special characters in the filename" do
|
110
|
-
|
110
|
+
before do
|
111
111
|
Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).
|
112
112
|
returns(@open_return)
|
113
|
-
|
114
|
-
|
115
|
-
|
113
|
+
end
|
114
|
+
|
115
|
+
let(:filename) do
|
116
|
+
"paperclip-%C3%B6%C3%A4%C3%BC%E5%AD%97%C2%B4%C2%BD%E2%99%A5"\
|
116
117
|
"%C3%98%C2%B2%C3%88.png"
|
118
|
+
end
|
119
|
+
let(:url) { "https://github.com/thoughtbot/paperclip-öäü字´½♥زÈ.png" }
|
117
120
|
|
121
|
+
subject { Paperclip.io_adapters.for(url) }
|
122
|
+
|
123
|
+
it "returns a encoded filename" do
|
118
124
|
assert_equal filename, subject.original_filename
|
119
125
|
end
|
126
|
+
|
127
|
+
context "when already URI encoded" do
|
128
|
+
let(:url) do
|
129
|
+
"https://github.com/thoughtbot/paperclip-%C3%B6%C3%A4%C3%BC%E5%AD%97"\
|
130
|
+
"%C2%B4%C2%BD%E2%99%A5%C3%98%C2%B2%C3%88.png"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "returns a encoded filename" do
|
134
|
+
assert_equal filename, subject.original_filename
|
135
|
+
end
|
136
|
+
end
|
120
137
|
end
|
121
138
|
end
|
@@ -16,6 +16,8 @@ describe Paperclip::UriAdapter do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
context "a new instance" do
|
19
|
+
let(:meta) { { "content-type" => "image/png" } }
|
20
|
+
|
19
21
|
before do
|
20
22
|
Paperclip::UriAdapter.any_instance.
|
21
23
|
stubs(:download_content).returns(@open_return)
|
@@ -62,7 +64,7 @@ describe Paperclip::UriAdapter do
|
|
62
64
|
assert_equal 'image/png', @subject.content_type
|
63
65
|
end
|
64
66
|
|
65
|
-
it
|
67
|
+
it "accepts an original_filename" do
|
66
68
|
@subject.original_filename = 'image.png'
|
67
69
|
assert_equal 'image.png', @subject.original_filename
|
68
70
|
end
|
@@ -71,6 +73,7 @@ describe Paperclip::UriAdapter do
|
|
71
73
|
|
72
74
|
context "a directory index url" do
|
73
75
|
let(:content_type) { "text/html" }
|
76
|
+
let(:meta) { { "content-type" => "text/html" } }
|
74
77
|
|
75
78
|
before do
|
76
79
|
Paperclip::UriAdapter.any_instance.
|
@@ -105,23 +108,68 @@ describe Paperclip::UriAdapter do
|
|
105
108
|
|
106
109
|
context "a url with content disposition headers" do
|
107
110
|
let(:file_name) { "test_document.pdf" }
|
108
|
-
let(:
|
109
|
-
{
|
110
|
-
"content-disposition" => "attachment; filename=\"#{file_name}\";",
|
111
|
-
}
|
112
|
-
end
|
111
|
+
let(:filename_from_path) { "paperclip" }
|
113
112
|
|
114
113
|
before do
|
115
114
|
Paperclip::UriAdapter.any_instance.
|
116
115
|
stubs(:download_content).returns(@open_return)
|
117
116
|
|
118
|
-
@uri = URI.parse(
|
117
|
+
@uri = URI.parse(
|
118
|
+
"https://github.com/thoughtbot/#{filename_from_path}?file=test")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "returns file name from path" do
|
122
|
+
meta["content-disposition"] = "inline;"
|
123
|
+
|
119
124
|
@subject = Paperclip.io_adapters.for(@uri)
|
125
|
+
|
126
|
+
assert_equal filename_from_path, @subject.original_filename
|
120
127
|
end
|
121
128
|
|
122
|
-
it "returns a file name" do
|
129
|
+
it "returns a file name enclosed in double quotes" do
|
130
|
+
file_name = "john's test document.pdf"
|
131
|
+
meta["content-disposition"] = "attachment; filename=\"#{file_name}\";"
|
132
|
+
|
133
|
+
@subject = Paperclip.io_adapters.for(@uri)
|
134
|
+
|
135
|
+
assert_equal file_name, @subject.original_filename
|
136
|
+
end
|
137
|
+
|
138
|
+
it "returns a file name not enclosed in double quotes" do
|
139
|
+
meta["content-disposition"] = "ATTACHMENT; FILENAME=#{file_name};"
|
140
|
+
|
141
|
+
@subject = Paperclip.io_adapters.for(@uri)
|
142
|
+
|
143
|
+
assert_equal file_name, @subject.original_filename
|
144
|
+
end
|
145
|
+
|
146
|
+
it "does not crash when an empty filename is given" do
|
147
|
+
meta["content-disposition"] = "ATTACHMENT; FILENAME=\"\";"
|
148
|
+
|
149
|
+
@subject = Paperclip.io_adapters.for(@uri)
|
150
|
+
|
151
|
+
assert_equal "", @subject.original_filename
|
152
|
+
end
|
153
|
+
|
154
|
+
it "returns a file name ignoring RFC 5987 encoding" do
|
155
|
+
meta["content-disposition"] =
|
156
|
+
"attachment; filename=#{file_name}; filename* = utf-8''%e2%82%ac%20rates"
|
157
|
+
|
158
|
+
@subject = Paperclip.io_adapters.for(@uri)
|
159
|
+
|
123
160
|
assert_equal file_name, @subject.original_filename
|
124
161
|
end
|
162
|
+
|
163
|
+
context "when file name has consecutive periods" do
|
164
|
+
let(:file_name) { "test_document..pdf" }
|
165
|
+
|
166
|
+
it "returns a file name" do
|
167
|
+
@uri = URI.parse(
|
168
|
+
"https://github.com/thoughtbot/#{file_name}?file=test")
|
169
|
+
@subject = Paperclip.io_adapters.for(@uri)
|
170
|
+
assert_equal file_name, @subject.original_filename
|
171
|
+
end
|
172
|
+
end
|
125
173
|
end
|
126
174
|
|
127
175
|
context "a url with restricted characters in the filename" do
|
@@ -7,7 +7,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentSizeMatcher do
|
|
7
7
|
before do
|
8
8
|
reset_table("dummies") do |d|
|
9
9
|
d.string :avatar_file_name
|
10
|
-
d.
|
10
|
+
d.bigint :avatar_file_size
|
11
11
|
end
|
12
12
|
reset_class "Dummy"
|
13
13
|
Dummy.do_not_validate_attachment_file_type :avatar
|