paperclip 4.1.1 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +0 -6
- data/.travis.yml +4 -13
- data/Appraisals +0 -10
- data/CONTRIBUTING.md +10 -5
- data/Gemfile +8 -4
- data/NEWS +1 -1
- data/README.md +51 -10
- data/Rakefile +6 -8
- data/features/basic_integration.feature +5 -5
- data/features/step_definitions/attachment_steps.rb +4 -4
- data/features/step_definitions/rails_steps.rb +4 -4
- data/features/step_definitions/web_steps.rb +2 -2
- data/features/support/env.rb +2 -2
- data/features/support/fixtures/gemfile.txt +1 -1
- data/features/support/rails.rb +2 -1
- data/gemfiles/3.2.gemfile +5 -3
- data/gemfiles/4.0.gemfile +5 -3
- data/gemfiles/4.1.gemfile +5 -3
- data/lib/generators/paperclip/paperclip_generator.rb +0 -2
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
- data/lib/paperclip.rb +4 -1
- data/lib/paperclip/attachment.rb +90 -29
- data/lib/paperclip/content_type_detector.rb +1 -1
- data/lib/paperclip/geometry_detector_factory.rb +3 -1
- data/lib/paperclip/has_attached_file.rb +2 -1
- data/lib/paperclip/interpolations.rb +8 -0
- data/lib/paperclip/io_adapters/abstract_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/stringio_adapter.rb +5 -11
- data/lib/paperclip/locales/de.yml +18 -0
- data/lib/paperclip/locales/es.yml +18 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -1
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -1
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
- data/lib/paperclip/media_type_spoof_detector.rb +10 -2
- data/lib/paperclip/storage/filesystem.rb +1 -1
- data/lib/paperclip/storage/s3.rb +26 -4
- data/lib/paperclip/style.rb +1 -1
- data/lib/paperclip/thumbnail.rb +6 -6
- data/lib/paperclip/validators.rb +5 -3
- data/lib/paperclip/validators/attachment_size_validator.rb +7 -3
- data/lib/paperclip/version.rb +1 -1
- data/lib/tasks/paperclip.rake +1 -2
- data/paperclip.gemspec +5 -3
- data/shoulda_macros/paperclip.rb +0 -1
- data/{test → spec}/database.yml +0 -0
- data/spec/paperclip/attachment_definitions_spec.rb +13 -0
- data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +20 -21
- data/{test/attachment_registry_test.rb → spec/paperclip/attachment_registry_spec.rb} +10 -11
- data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +367 -360
- data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +8 -8
- data/{test/file_command_content_type_detector_test.rb → spec/paperclip/file_command_content_type_detector_spec.rb} +5 -5
- data/spec/paperclip/filename_cleaner_spec.rb +14 -0
- data/spec/paperclip/geometry_detector_spec.rb +39 -0
- data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
- data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +49 -51
- data/{test/has_attached_file_test.rb → spec/paperclip/has_attached_file_spec.rb} +18 -27
- data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +134 -126
- data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +54 -40
- data/{test/io_adapters/abstract_adapter_test.rb → spec/paperclip/io_adapters/abstract_adapter_spec.rb} +21 -10
- data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +27 -29
- data/{test/io_adapters/data_uri_adapter_test.rb → spec/paperclip/io_adapters/data_uri_adapter_spec.rb} +22 -18
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
- data/{test/io_adapters/file_adapter_test.rb → spec/paperclip/io_adapters/file_adapter_spec.rb} +32 -28
- data/{test/io_adapters/http_url_proxy_adapter_test.rb → spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb} +22 -22
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
- data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
- data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +10 -7
- data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +16 -17
- data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +41 -41
- data/{test/io_adapters/uri_adapter_test.rb → spec/paperclip/io_adapters/uri_adapter_spec.rb} +22 -22
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +99 -0
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
- data/{test/media_type_spoof_detector_test.rb → spec/paperclip/media_type_spoof_detector_spec.rb} +13 -8
- data/spec/paperclip/meta_class_spec.rb +30 -0
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
- data/{test/paperclip_test.rb → spec/paperclip/paperclip_spec.rb} +47 -47
- data/{test/plural_cache_test.rb → spec/paperclip/plural_cache_spec.rb} +6 -6
- data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +5 -5
- data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
- data/spec/paperclip/schema_spec.rb +206 -0
- data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
- data/{test/storage/fog_test.rb → spec/paperclip/storage/fog_spec.rb} +145 -140
- data/spec/paperclip/storage/s3_live_spec.rb +182 -0
- data/spec/paperclip/storage/s3_spec.rb +1475 -0
- data/spec/paperclip/style_spec.rb +255 -0
- data/spec/paperclip/tempfile_factory_spec.rb +29 -0
- data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +107 -107
- data/{test/url_generator_test.rb → spec/paperclip/url_generator_spec.rb} +55 -56
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
- data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +19 -19
- data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +65 -58
- data/{test/validators/media_type_spoof_detection_validator_test.rb → spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb} +8 -8
- data/spec/paperclip/validators_spec.rb +164 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/support/assertions.rb +71 -0
- data/spec/support/fake_model.rb +21 -0
- data/spec/support/fake_rails.rb +12 -0
- data/{test → spec/support}/fixtures/12k.png +0 -0
- data/{test → spec/support}/fixtures/50x50.png +0 -0
- data/{test → spec/support}/fixtures/5k.png +0 -0
- data/{test → spec/support}/fixtures/animated +0 -0
- data/{test → spec/support}/fixtures/animated.gif +0 -0
- data/{test → spec/support}/fixtures/animated.unknown +0 -0
- data/{test → spec/support}/fixtures/bad.png +0 -0
- data/{test → spec/support}/fixtures/empty.html +0 -0
- data/{test → spec/support}/fixtures/fog.yml +0 -0
- data/{test → spec/support}/fixtures/rotated.jpg +0 -0
- data/{test → spec/support}/fixtures/s3.yml +0 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/test/fixtures/spaced file.png b/data/spec/support/fixtures/spaced → file.png +0 -0
- data/{test → spec/support}/fixtures/text.txt +0 -0
- data/{test → spec/support}/fixtures/twopage.pdf +0 -0
- data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
- data/spec/support/matchers/accept.rb +5 -0
- data/spec/support/matchers/exist.rb +5 -0
- data/{test → spec}/support/mock_attachment.rb +0 -0
- data/{test → spec}/support/mock_interpolator.rb +0 -0
- data/{test → spec}/support/mock_model.rb +0 -0
- data/{test → spec}/support/mock_url_generator_builder.rb +0 -0
- data/spec/support/model_reconstruction.rb +60 -0
- data/spec/support/rails_helpers.rb +7 -0
- data/spec/support/test_data.rb +13 -0
- data/spec/support/version_helper.rb +9 -0
- metadata +256 -210
- data/gemfiles/3.0.gemfile +0 -11
- data/gemfiles/3.1.gemfile +0 -11
- data/test/attachment_definitions_test.rb +0 -13
- data/test/filename_cleaner_test.rb +0 -14
- data/test/generator_test.rb +0 -84
- data/test/geometry_detector_test.rb +0 -24
- data/test/helper.rb +0 -239
- data/test/io_adapters/empty_string_adapter_test.rb +0 -18
- data/test/io_adapters/identity_adapter_test.rb +0 -8
- data/test/matchers/have_attached_file_matcher_test.rb +0 -25
- data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -111
- data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -70
- data/test/matchers/validate_attachment_size_matcher_test.rb +0 -87
- data/test/meta_class_test.rb +0 -32
- data/test/paperclip_missing_attachment_styles_test.rb +0 -90
- data/test/schema_test.rb +0 -206
- data/test/storage/s3_live_test.rb +0 -179
- data/test/storage/s3_test.rb +0 -1357
- data/test/style_test.rb +0 -251
- data/test/tempfile_factory_test.rb +0 -29
- data/test/validators/attachment_content_type_validator_test.rb +0 -324
- data/test/validators/attachment_file_name_validator_test.rb +0 -162
- data/test/validators_test.rb +0 -101
data/features/support/rails.rb
CHANGED
@@ -6,7 +6,8 @@ ORIGINAL_BUNDLE_VARS = Hash[ENV.select{ |key,value| BUNDLE_ENV_VARS.include?(key
|
|
6
6
|
ENV['RAILS_ENV'] = 'test'
|
7
7
|
|
8
8
|
Before do
|
9
|
-
|
9
|
+
gemfile = ENV['BUNDLE_GEMFILE'].to_s
|
10
|
+
ENV['BUNDLE_GEMFILE'] = File.join(Dir.pwd, gemfile) unless gemfile.start_with?(Dir.pwd)
|
10
11
|
@framework_version = nil
|
11
12
|
end
|
12
13
|
|
data/gemfiles/3.2.gemfile
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem "
|
6
|
-
gem "
|
7
|
-
gem "
|
5
|
+
gem "sqlite3", "1.3.8", :platforms=>:ruby
|
6
|
+
gem "jruby-openssl", :platforms=>:jruby
|
7
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms=>:jruby
|
8
|
+
gem "rubysl", :platforms=>:rbx
|
9
|
+
gem "racc", :platforms=>:rbx
|
8
10
|
gem "rails", "~> 3.2.15"
|
9
11
|
gem "paperclip", :path=>"../"
|
10
12
|
|
data/gemfiles/4.0.gemfile
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem "
|
6
|
-
gem "
|
7
|
-
gem "
|
5
|
+
gem "sqlite3", "1.3.8", :platforms=>:ruby
|
6
|
+
gem "jruby-openssl", :platforms=>:jruby
|
7
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms=>:jruby
|
8
|
+
gem "rubysl", :platforms=>:rbx
|
9
|
+
gem "racc", :platforms=>:rbx
|
8
10
|
gem "rails", "~> 4.0.0"
|
9
11
|
gem "paperclip", :path=>"../"
|
10
12
|
|
data/gemfiles/4.1.gemfile
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem "
|
6
|
-
gem "
|
7
|
-
gem "
|
5
|
+
gem "sqlite3", "1.3.8", :platforms=>:ruby
|
6
|
+
gem "jruby-openssl", :platforms=>:jruby
|
7
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms=>:jruby
|
8
|
+
gem "rubysl", :platforms=>:rbx
|
9
|
+
gem "racc", :platforms=>:rbx
|
8
10
|
gem "rails", "~> 4.1.0.beta"
|
9
11
|
gem "paperclip", :path=>"../"
|
10
12
|
|
@@ -16,8 +16,6 @@ class PaperclipGenerator < ActiveRecord::Generators::Base
|
|
16
16
|
migration_template "paperclip_migration.rb.erb", "db/migrate/#{migration_file_name}"
|
17
17
|
end
|
18
18
|
|
19
|
-
protected
|
20
|
-
|
21
19
|
def migration_name
|
22
20
|
"add_attachment_#{attachment_names.join("_")}_to_#{name.underscore.pluralize}"
|
23
21
|
end
|
@@ -9,7 +9,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration
|
|
9
9
|
|
10
10
|
def self.down
|
11
11
|
<% attachment_names.each do |attachment| -%>
|
12
|
-
|
12
|
+
remove_attachment :<%= table_name %>, :<%= attachment %>
|
13
13
|
<% end -%>
|
14
14
|
end
|
15
15
|
end
|
data/lib/paperclip.rb
CHANGED
@@ -75,6 +75,8 @@ module Paperclip
|
|
75
75
|
# * command_path: Defines the path at which to find the command line
|
76
76
|
# programs if they are not visible to Rails the system's search path. Defaults to
|
77
77
|
# nil, which uses the first executable found in the user's search path.
|
78
|
+
# * use_exif_orientation: Whether to inspect EXIF data to determine an
|
79
|
+
# image's orientation. Defaults to true.
|
78
80
|
def self.options
|
79
81
|
@options ||= {
|
80
82
|
:whiny => true,
|
@@ -83,7 +85,8 @@ module Paperclip
|
|
83
85
|
:log => true,
|
84
86
|
:log_command => true,
|
85
87
|
:swallow_stderr => true,
|
86
|
-
:content_type_mappings => {}
|
88
|
+
:content_type_mappings => {},
|
89
|
+
:use_exif_orientation => true
|
87
90
|
}
|
88
91
|
end
|
89
92
|
|
data/lib/paperclip/attachment.rb
CHANGED
@@ -87,37 +87,29 @@ module Paperclip
|
|
87
87
|
end
|
88
88
|
|
89
89
|
# What gets called when you call instance.attachment = File. It clears
|
90
|
-
# errors, assigns attributes, and processes the file. It
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
90
|
+
# errors, assigns attributes, and processes the file. It also queues up the
|
91
|
+
# previous file for deletion, to be flushed away on #save of its host. In
|
92
|
+
# addition to form uploads, you can also assign another Paperclip
|
93
|
+
# attachment:
|
94
94
|
# new_user.avatar = old_user.avatar
|
95
|
-
def assign
|
95
|
+
def assign(uploaded_file)
|
96
|
+
@file = Paperclip.io_adapters.for(uploaded_file)
|
96
97
|
ensure_required_accessors!
|
97
98
|
ensure_required_validations!
|
98
|
-
file = Paperclip.io_adapters.for(uploaded_file)
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
return nil if file.nil?
|
100
|
+
if @file.assignment?
|
101
|
+
clear(*only_process)
|
103
102
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
post_process(*only_process) if post_processing
|
115
|
-
|
116
|
-
# Reset the file size if the original file was reprocessed.
|
117
|
-
instance_write(:file_size, @queued_for_write[:original].size)
|
118
|
-
instance_write(:fingerprint, @queued_for_write[:original].fingerprint) if instance_respond_to?(:fingerprint)
|
119
|
-
updater = :"#{name}_file_name_will_change!"
|
120
|
-
instance.send updater if instance.respond_to? updater
|
103
|
+
if @file.nil?
|
104
|
+
nil
|
105
|
+
else
|
106
|
+
assign_attributes
|
107
|
+
post_process_file
|
108
|
+
reset_file_if_original_reprocessed
|
109
|
+
end
|
110
|
+
else
|
111
|
+
nil
|
112
|
+
end
|
121
113
|
end
|
122
114
|
|
123
115
|
# Returns the public URL of the attachment with a given style. This does
|
@@ -142,9 +134,8 @@ module Paperclip
|
|
142
134
|
#
|
143
135
|
# +#new(Paperclip::Attachment, options_hash)+
|
144
136
|
# +#for(style_name, options_hash)+
|
145
|
-
def url(style_name = default_style, options = {})
|
146
|
-
default_options = {:timestamp => @options[:use_timestamp], :escape => @options[:escape_url]}
|
147
137
|
|
138
|
+
def url(style_name = default_style, options = {})
|
148
139
|
if options == true || options == false # Backwards compatibility.
|
149
140
|
@url_generator.for(style_name, default_options.merge(:timestamp => options))
|
150
141
|
else
|
@@ -152,6 +143,13 @@ module Paperclip
|
|
152
143
|
end
|
153
144
|
end
|
154
145
|
|
146
|
+
def default_options
|
147
|
+
{
|
148
|
+
:timestamp => @options[:use_timestamp],
|
149
|
+
:escape => @options[:escape_url]
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
155
153
|
# Alias to +url+ that allows using the expiring_url method provided by the cloud
|
156
154
|
# storage implementations, but keep using filesystem storage for development and
|
157
155
|
# testing.
|
@@ -391,8 +389,16 @@ module Paperclip
|
|
391
389
|
@instance.class.validators.map(&:class)
|
392
390
|
end
|
393
391
|
|
392
|
+
def required_validator_classes
|
393
|
+
Paperclip::REQUIRED_VALIDATORS + Paperclip::REQUIRED_VALIDATORS.flat_map(&:descendants)
|
394
|
+
end
|
395
|
+
|
396
|
+
def missing_required_validator?
|
397
|
+
(active_validator_classes & required_validator_classes).empty?
|
398
|
+
end
|
399
|
+
|
394
400
|
def ensure_required_validations!
|
395
|
-
if
|
401
|
+
if missing_required_validator?
|
396
402
|
raise Paperclip::Errors::MissingRequiredValidatorError
|
397
403
|
end
|
398
404
|
end
|
@@ -419,6 +425,61 @@ module Paperclip
|
|
419
425
|
self.extend(storage_module)
|
420
426
|
end
|
421
427
|
|
428
|
+
def assign_attributes
|
429
|
+
@queued_for_write[:original] = @file
|
430
|
+
assign_file_information
|
431
|
+
assign_fingerprint(@file.fingerprint)
|
432
|
+
assign_timestamps
|
433
|
+
end
|
434
|
+
|
435
|
+
def assign_file_information
|
436
|
+
instance_write(:file_name, cleanup_filename(@file.original_filename))
|
437
|
+
instance_write(:content_type, @file.content_type.to_s.strip)
|
438
|
+
instance_write(:file_size, @file.size)
|
439
|
+
end
|
440
|
+
|
441
|
+
def assign_fingerprint(fingerprint)
|
442
|
+
if instance_respond_to?(:fingerprint)
|
443
|
+
instance_write(:fingerprint, fingerprint)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
def assign_timestamps
|
448
|
+
if has_enabled_but_unset_created_at?
|
449
|
+
instance_write(:created_at, Time.now)
|
450
|
+
end
|
451
|
+
|
452
|
+
instance_write(:updated_at, Time.now)
|
453
|
+
end
|
454
|
+
|
455
|
+
def post_process_file
|
456
|
+
dirty!
|
457
|
+
|
458
|
+
if post_processing
|
459
|
+
post_process(*only_process)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
def dirty!
|
464
|
+
@dirty = true
|
465
|
+
end
|
466
|
+
|
467
|
+
def reset_file_if_original_reprocessed
|
468
|
+
instance_write(:file_size, @queued_for_write[:original].size)
|
469
|
+
assign_fingerprint(@queued_for_write[:original].fingerprint)
|
470
|
+
reset_updater
|
471
|
+
end
|
472
|
+
|
473
|
+
def reset_updater
|
474
|
+
if instance.respond_to?(updater)
|
475
|
+
instance.send(updater)
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
def updater
|
480
|
+
:"#{name}_file_name_will_change!"
|
481
|
+
end
|
482
|
+
|
422
483
|
def extra_options_for(style) #:nodoc:
|
423
484
|
process_options(:convert_options, style)
|
424
485
|
end
|
@@ -14,9 +14,11 @@ module Paperclip
|
|
14
14
|
|
15
15
|
def geometry_string
|
16
16
|
begin
|
17
|
+
orientation = Paperclip.options[:use_exif_orientation] ?
|
18
|
+
"%[exif:orientation]" : "1"
|
17
19
|
Paperclip.run(
|
18
20
|
"identify",
|
19
|
-
"-format '%wx%h
|
21
|
+
"-format '%wx%h,#{orientation}' :file", {
|
20
22
|
:file => "#{path}[0]"
|
21
23
|
}, {
|
22
24
|
:swallow_stderr => true
|
@@ -80,7 +80,8 @@ module Paperclip
|
|
80
80
|
|
81
81
|
def add_required_validations
|
82
82
|
name = @name
|
83
|
-
@klass.validates_media_type_spoof_detection name,
|
83
|
+
@klass.validates_media_type_spoof_detection name,
|
84
|
+
:if => ->(instance){ instance.send(name).dirty? }
|
84
85
|
end
|
85
86
|
|
86
87
|
def add_active_record_callbacks
|
@@ -101,6 +101,14 @@ module Paperclip
|
|
101
101
|
File.extname(attachment.original_filename).gsub(/\A\.+/, "")
|
102
102
|
end
|
103
103
|
|
104
|
+
# Returns the dot+extension of the file. e.g. ".jpg" for "file.jpg"
|
105
|
+
# If the style has a format defined, it will return the format instead
|
106
|
+
# of the actual extension. If the extension is empty, no dot is added.
|
107
|
+
def dotextension attachment, style_name
|
108
|
+
ext = extension(attachment, style_name)
|
109
|
+
ext.empty? ? "" : ".#{ext}"
|
110
|
+
end
|
111
|
+
|
104
112
|
# Returns an extension based on the content type. e.g. "jpeg" for
|
105
113
|
# "image/jpeg". If the style has a specified format, it will override the
|
106
114
|
# content-type detection.
|
@@ -2,7 +2,6 @@ module Paperclip
|
|
2
2
|
class StringioAdapter < AbstractAdapter
|
3
3
|
def initialize(target)
|
4
4
|
@target = target
|
5
|
-
@tempfile = copy_to_tempfile
|
6
5
|
cache_current_values
|
7
6
|
end
|
8
7
|
|
@@ -11,26 +10,21 @@ module Paperclip
|
|
11
10
|
private
|
12
11
|
|
13
12
|
def cache_current_values
|
13
|
+
self.original_filename = @target.original_filename if @target.respond_to?(:original_filename)
|
14
|
+
self.original_filename ||= "data"
|
15
|
+
@tempfile = copy_to_tempfile(@target)
|
14
16
|
@content_type = ContentTypeDetector.new(@tempfile.path).detect
|
15
|
-
original_filename = @target.original_filename if @target.respond_to?(:original_filename)
|
16
|
-
original_filename ||= "data.#{extension_for(@content_type)}"
|
17
|
-
self.original_filename = original_filename.strip
|
18
17
|
@size = @target.size
|
19
18
|
end
|
20
19
|
|
21
|
-
def copy_to_tempfile
|
22
|
-
while data =
|
20
|
+
def copy_to_tempfile(source)
|
21
|
+
while data = source.read(16*1024)
|
23
22
|
destination.write(data)
|
24
23
|
end
|
25
24
|
destination.rewind
|
26
25
|
destination
|
27
26
|
end
|
28
27
|
|
29
|
-
def extension_for(content_type)
|
30
|
-
type = MIME::Types[content_type].first
|
31
|
-
type && type.extensions.first
|
32
|
-
end
|
33
|
-
|
34
28
|
end
|
35
29
|
end
|
36
30
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
de:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
in_between: "muss zwischen %{min} und %{max} sein"
|
5
|
+
spoofed_media_type: "trägt eine Dateiendung, die nicht mit dem Inhalt der Datei übereinstimmt"
|
6
|
+
|
7
|
+
number:
|
8
|
+
human:
|
9
|
+
storage_units:
|
10
|
+
format: "%n %u"
|
11
|
+
units:
|
12
|
+
byte:
|
13
|
+
one: "Byte"
|
14
|
+
other: "Bytes"
|
15
|
+
kb: "KB"
|
16
|
+
mb: "MB"
|
17
|
+
gb: "GB"
|
18
|
+
tb: "TB"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
es:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
in_between: "debe estar entre %{min} y %{max}"
|
5
|
+
spoofed_media_type: "tiene una extensión que no coincide con su contenido"
|
6
|
+
|
7
|
+
number:
|
8
|
+
human:
|
9
|
+
storage_units:
|
10
|
+
format: "%n %u"
|
11
|
+
units:
|
12
|
+
byte:
|
13
|
+
one: "Byte"
|
14
|
+
other: "Bytes"
|
15
|
+
kb: "KB"
|
16
|
+
mb: "MB"
|
17
|
+
gb: "GB"
|
18
|
+
tb: "TB"
|
@@ -27,9 +27,10 @@ module Paperclip
|
|
27
27
|
"Should have an attachment named #{@attachment_name}"
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def failure_message_when_negated
|
31
31
|
"Should not have an attachment named #{@attachment_name}"
|
32
32
|
end
|
33
|
+
alias negative_failure_message failure_message_when_negated
|
33
34
|
|
34
35
|
def description
|
35
36
|
"have an attachment named #{@attachment_name}"
|
@@ -26,9 +26,10 @@ module Paperclip
|
|
26
26
|
"Attachment #{@attachment_name} should be required"
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def failure_message_when_negated
|
30
30
|
"Attachment #{@attachment_name} should not be required"
|
31
31
|
end
|
32
|
+
alias negative_failure_message failure_message_when_negated
|
32
33
|
|
33
34
|
def description
|
34
35
|
"require presence of attachment #{@attachment_name}"
|
@@ -45,9 +45,10 @@ module Paperclip
|
|
45
45
|
"Attachment #{@attachment_name} must be between #{@low} and #{@high} bytes"
|
46
46
|
end
|
47
47
|
|
48
|
-
def
|
48
|
+
def failure_message_when_negated
|
49
49
|
"Attachment #{@attachment_name} cannot be between #{@low} and #{@high} bytes"
|
50
50
|
end
|
51
|
+
alias negative_failure_message failure_message_when_negated
|
51
52
|
|
52
53
|
def description
|
53
54
|
"validate the size of attachment #{@attachment_name}"
|
@@ -10,7 +10,7 @@ module Paperclip
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def spoofed?
|
13
|
-
if
|
13
|
+
if has_name? && has_extension? && media_type_mismatch? && mapping_override_mismatch?
|
14
14
|
Paperclip.log("Content Type Spoof: Filename #{File.basename(@name)} (#{supplied_file_content_types}), content type discovered from file command: #{calculated_content_type}. See documentation to allow this combination.")
|
15
15
|
true
|
16
16
|
end
|
@@ -18,6 +18,14 @@ module Paperclip
|
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
+
def has_name?
|
22
|
+
@name.present?
|
23
|
+
end
|
24
|
+
|
25
|
+
def has_extension?
|
26
|
+
File.extname(@name).present?
|
27
|
+
end
|
28
|
+
|
21
29
|
def media_type_mismatch?
|
22
30
|
! supplied_file_media_types.include?(calculated_media_type)
|
23
31
|
end
|
@@ -52,7 +60,7 @@ module Paperclip
|
|
52
60
|
|
53
61
|
def type_from_file_command
|
54
62
|
begin
|
55
|
-
Paperclip.run("file", "-b --mime
|
63
|
+
Paperclip.run("file", "-b --mime :file", :file => @file.path).split(/[:;]\s+/).first
|
56
64
|
rescue Cocaine::CommandLineError
|
57
65
|
""
|
58
66
|
end
|