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.

Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -6
  3. data/.travis.yml +4 -13
  4. data/Appraisals +0 -10
  5. data/CONTRIBUTING.md +10 -5
  6. data/Gemfile +8 -4
  7. data/NEWS +1 -1
  8. data/README.md +51 -10
  9. data/Rakefile +6 -8
  10. data/features/basic_integration.feature +5 -5
  11. data/features/step_definitions/attachment_steps.rb +4 -4
  12. data/features/step_definitions/rails_steps.rb +4 -4
  13. data/features/step_definitions/web_steps.rb +2 -2
  14. data/features/support/env.rb +2 -2
  15. data/features/support/fixtures/gemfile.txt +1 -1
  16. data/features/support/rails.rb +2 -1
  17. data/gemfiles/3.2.gemfile +5 -3
  18. data/gemfiles/4.0.gemfile +5 -3
  19. data/gemfiles/4.1.gemfile +5 -3
  20. data/lib/generators/paperclip/paperclip_generator.rb +0 -2
  21. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
  22. data/lib/paperclip.rb +4 -1
  23. data/lib/paperclip/attachment.rb +90 -29
  24. data/lib/paperclip/content_type_detector.rb +1 -1
  25. data/lib/paperclip/geometry_detector_factory.rb +3 -1
  26. data/lib/paperclip/has_attached_file.rb +2 -1
  27. data/lib/paperclip/interpolations.rb +8 -0
  28. data/lib/paperclip/io_adapters/abstract_adapter.rb +1 -1
  29. data/lib/paperclip/io_adapters/data_uri_adapter.rb +1 -1
  30. data/lib/paperclip/io_adapters/stringio_adapter.rb +5 -11
  31. data/lib/paperclip/locales/de.yml +18 -0
  32. data/lib/paperclip/locales/es.yml +18 -0
  33. data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -1
  34. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -1
  35. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
  36. data/lib/paperclip/media_type_spoof_detector.rb +10 -2
  37. data/lib/paperclip/storage/filesystem.rb +1 -1
  38. data/lib/paperclip/storage/s3.rb +26 -4
  39. data/lib/paperclip/style.rb +1 -1
  40. data/lib/paperclip/thumbnail.rb +6 -6
  41. data/lib/paperclip/validators.rb +5 -3
  42. data/lib/paperclip/validators/attachment_size_validator.rb +7 -3
  43. data/lib/paperclip/version.rb +1 -1
  44. data/lib/tasks/paperclip.rake +1 -2
  45. data/paperclip.gemspec +5 -3
  46. data/shoulda_macros/paperclip.rb +0 -1
  47. data/{test → spec}/database.yml +0 -0
  48. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  49. data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +20 -21
  50. data/{test/attachment_registry_test.rb → spec/paperclip/attachment_registry_spec.rb} +10 -11
  51. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +367 -360
  52. data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +8 -8
  53. data/{test/file_command_content_type_detector_test.rb → spec/paperclip/file_command_content_type_detector_spec.rb} +5 -5
  54. data/spec/paperclip/filename_cleaner_spec.rb +14 -0
  55. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  56. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  57. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +49 -51
  58. data/{test/has_attached_file_test.rb → spec/paperclip/has_attached_file_spec.rb} +18 -27
  59. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +134 -126
  60. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +54 -40
  61. data/{test/io_adapters/abstract_adapter_test.rb → spec/paperclip/io_adapters/abstract_adapter_spec.rb} +21 -10
  62. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +27 -29
  63. data/{test/io_adapters/data_uri_adapter_test.rb → spec/paperclip/io_adapters/data_uri_adapter_spec.rb} +22 -18
  64. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  65. data/{test/io_adapters/file_adapter_test.rb → spec/paperclip/io_adapters/file_adapter_spec.rb} +32 -28
  66. data/{test/io_adapters/http_url_proxy_adapter_test.rb → spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb} +22 -22
  67. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  68. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  69. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +10 -7
  70. data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +16 -17
  71. data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +41 -41
  72. data/{test/io_adapters/uri_adapter_test.rb → spec/paperclip/io_adapters/uri_adapter_spec.rb} +22 -22
  73. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  74. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +99 -0
  75. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  76. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  77. data/{test/media_type_spoof_detector_test.rb → spec/paperclip/media_type_spoof_detector_spec.rb} +13 -8
  78. data/spec/paperclip/meta_class_spec.rb +30 -0
  79. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  80. data/{test/paperclip_test.rb → spec/paperclip/paperclip_spec.rb} +47 -47
  81. data/{test/plural_cache_test.rb → spec/paperclip/plural_cache_spec.rb} +6 -6
  82. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +5 -5
  83. data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
  84. data/spec/paperclip/schema_spec.rb +206 -0
  85. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  86. data/{test/storage/fog_test.rb → spec/paperclip/storage/fog_spec.rb} +145 -140
  87. data/spec/paperclip/storage/s3_live_spec.rb +182 -0
  88. data/spec/paperclip/storage/s3_spec.rb +1475 -0
  89. data/spec/paperclip/style_spec.rb +255 -0
  90. data/spec/paperclip/tempfile_factory_spec.rb +29 -0
  91. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +107 -107
  92. data/{test/url_generator_test.rb → spec/paperclip/url_generator_spec.rb} +55 -56
  93. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  94. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  95. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +19 -19
  96. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +65 -58
  97. data/{test/validators/media_type_spoof_detection_validator_test.rb → spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb} +8 -8
  98. data/spec/paperclip/validators_spec.rb +164 -0
  99. data/spec/spec_helper.rb +40 -0
  100. data/spec/support/assertions.rb +71 -0
  101. data/spec/support/fake_model.rb +21 -0
  102. data/spec/support/fake_rails.rb +12 -0
  103. data/{test → spec/support}/fixtures/12k.png +0 -0
  104. data/{test → spec/support}/fixtures/50x50.png +0 -0
  105. data/{test → spec/support}/fixtures/5k.png +0 -0
  106. data/{test → spec/support}/fixtures/animated +0 -0
  107. data/{test → spec/support}/fixtures/animated.gif +0 -0
  108. data/{test → spec/support}/fixtures/animated.unknown +0 -0
  109. data/{test → spec/support}/fixtures/bad.png +0 -0
  110. data/{test → spec/support}/fixtures/empty.html +0 -0
  111. data/{test → spec/support}/fixtures/fog.yml +0 -0
  112. data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  113. data/{test → spec/support}/fixtures/s3.yml +0 -0
  114. data/spec/support/fixtures/spaced file.jpg +0 -0
  115. data/test/fixtures/spaced file.png b/data/spec/support/fixtures/spaced → file.png +0 -0
  116. data/{test → spec/support}/fixtures/text.txt +0 -0
  117. data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  118. data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  119. data/spec/support/matchers/accept.rb +5 -0
  120. data/spec/support/matchers/exist.rb +5 -0
  121. data/{test → spec}/support/mock_attachment.rb +0 -0
  122. data/{test → spec}/support/mock_interpolator.rb +0 -0
  123. data/{test → spec}/support/mock_model.rb +0 -0
  124. data/{test → spec}/support/mock_url_generator_builder.rb +0 -0
  125. data/spec/support/model_reconstruction.rb +60 -0
  126. data/spec/support/rails_helpers.rb +7 -0
  127. data/spec/support/test_data.rb +13 -0
  128. data/spec/support/version_helper.rb +9 -0
  129. metadata +256 -210
  130. data/gemfiles/3.0.gemfile +0 -11
  131. data/gemfiles/3.1.gemfile +0 -11
  132. data/test/attachment_definitions_test.rb +0 -13
  133. data/test/filename_cleaner_test.rb +0 -14
  134. data/test/generator_test.rb +0 -84
  135. data/test/geometry_detector_test.rb +0 -24
  136. data/test/helper.rb +0 -239
  137. data/test/io_adapters/empty_string_adapter_test.rb +0 -18
  138. data/test/io_adapters/identity_adapter_test.rb +0 -8
  139. data/test/matchers/have_attached_file_matcher_test.rb +0 -25
  140. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -111
  141. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -70
  142. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -87
  143. data/test/meta_class_test.rb +0 -32
  144. data/test/paperclip_missing_attachment_styles_test.rb +0 -90
  145. data/test/schema_test.rb +0 -206
  146. data/test/storage/s3_live_test.rb +0 -179
  147. data/test/storage/s3_test.rb +0 -1357
  148. data/test/style_test.rb +0 -251
  149. data/test/tempfile_factory_test.rb +0 -29
  150. data/test/validators/attachment_content_type_validator_test.rb +0 -324
  151. data/test/validators/attachment_file_name_validator_test.rb +0 -162
  152. data/test/validators_test.rb +0 -101
@@ -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
- ENV['BUNDLE_GEMFILE'] = File.join(Dir.pwd, ENV['BUNDLE_GEMFILE']) unless ENV['BUNDLE_GEMFILE'].start_with?(Dir.pwd)
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
 
@@ -2,9 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "jruby-openssl", :platform=>:jruby
6
- gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
7
- gem "pry", :platform=>:ruby
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
 
@@ -2,9 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "jruby-openssl", :platform=>:jruby
6
- gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
7
- gem "pry", :platform=>:ruby
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
 
@@ -2,9 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "jruby-openssl", :platform=>:jruby
6
- gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
7
- gem "sqlite3", :platform=>:ruby
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
- drop_attached_file :<%= table_name %>, :<%= attachment %>
12
+ remove_attachment :<%= table_name %>, :<%= attachment %>
13
13
  <% end -%>
14
14
  end
15
15
  end
@@ -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
 
@@ -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
- # also queues up the previous file for deletion, to be flushed away on
92
- # #save of its host. In addition to form uploads, you can also assign
93
- # another Paperclip attachment:
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 uploaded_file
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
- return nil if not file.assignment?
101
- self.clear(*only_process)
102
- return nil if file.nil?
100
+ if @file.assignment?
101
+ clear(*only_process)
103
102
 
104
- @queued_for_write[:original] = file
105
- instance_write(:file_name, cleanup_filename(file.original_filename))
106
- instance_write(:content_type, file.content_type.to_s.strip)
107
- instance_write(:file_size, file.size)
108
- instance_write(:fingerprint, file.fingerprint) if instance_respond_to?(:fingerprint)
109
- instance_write(:created_at, Time.now) if has_enabled_but_unset_created_at?
110
- instance_write(:updated_at, Time.now)
111
-
112
- @dirty = true
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 (active_validator_classes & Paperclip::REQUIRED_VALIDATORS).empty?
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
@@ -40,7 +40,7 @@ module Paperclip
40
40
  private
41
41
 
42
42
  def empty_file?
43
- File.exists?(@filename) && File.size(@filename) == 0
43
+ File.exist?(@filename) && File.size(@filename) == 0
44
44
  end
45
45
 
46
46
  alias :empty? :empty_file?
@@ -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,%[exif:orientation]' :file", {
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, :if => ->{ send(name).dirty? }
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.
@@ -34,7 +34,7 @@ module Paperclip
34
34
  private
35
35
 
36
36
  def destination
37
- @destination ||= TempfileFactory.new.generate
37
+ @destination ||= TempfileFactory.new.generate(@original_filename.to_s)
38
38
  end
39
39
 
40
40
  def copy_to_tempfile(src)
@@ -1,7 +1,7 @@
1
1
  module Paperclip
2
2
  class DataUriAdapter < StringioAdapter
3
3
 
4
- REGEXP = /\Adata:([-\w]+\/[-\w\+]+)?;base64,(.*)/m
4
+ REGEXP = /\Adata:([-\w]+\/[-\w\+\.]+)?;base64,(.*)/m
5
5
 
6
6
  def initialize(target_uri)
7
7
  super(extract_target(target_uri))
@@ -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 = @target.read(16*1024)
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 negative_failure_message
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 negative_failure_message
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 negative_failure_message
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 @name.present? && media_type_mismatch? && mapping_override_mismatch?
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-type :file", :file => @file.path)
63
+ Paperclip.run("file", "-b --mime :file", :file => @file.path).split(/[:;]\s+/).first
56
64
  rescue Cocaine::CommandLineError
57
65
  ""
58
66
  end