paperclip 5.2.1 → 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 +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
|