paperclip 5.2.1 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.github/issue_template.md +3 -0
  3. data/MIGRATING-ES.md +317 -0
  4. data/MIGRATING.md +375 -0
  5. data/NEWS +36 -0
  6. data/README.md +52 -18
  7. data/UPGRADING +3 -3
  8. data/features/step_definitions/attachment_steps.rb +10 -10
  9. data/features/step_definitions/rails_steps.rb +1 -1
  10. data/lib/generators/paperclip/paperclip_generator.rb +9 -1
  11. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
  12. data/lib/paperclip/attachment.rb +19 -6
  13. data/lib/paperclip/file_command_content_type_detector.rb +1 -1
  14. data/lib/paperclip/filename_cleaner.rb +0 -1
  15. data/lib/paperclip/geometry_detector_factory.rb +3 -3
  16. data/lib/paperclip/helpers.rb +3 -3
  17. data/lib/paperclip/interpolations.rb +6 -1
  18. data/lib/paperclip/io_adapters/abstract_adapter.rb +11 -6
  19. data/lib/paperclip/io_adapters/attachment_adapter.rb +7 -1
  20. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +2 -1
  21. data/lib/paperclip/io_adapters/uri_adapter.rb +8 -6
  22. data/lib/paperclip/logger.rb +1 -1
  23. data/lib/paperclip/media_type_spoof_detector.rb +11 -7
  24. data/lib/paperclip/processor.rb +10 -2
  25. data/lib/paperclip/schema.rb +1 -1
  26. data/lib/paperclip/storage/fog.rb +3 -2
  27. data/lib/paperclip/storage/s3.rb +8 -16
  28. data/lib/paperclip/style.rb +0 -1
  29. data/lib/paperclip/thumbnail.rb +8 -5
  30. data/lib/paperclip/url_generator.rb +1 -0
  31. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +4 -0
  32. data/lib/paperclip/version.rb +1 -1
  33. data/lib/paperclip.rb +2 -1
  34. data/paperclip.gemspec +2 -2
  35. data/spec/paperclip/attachment_processing_spec.rb +0 -1
  36. data/spec/paperclip/attachment_spec.rb +17 -2
  37. data/spec/paperclip/content_type_detector_spec.rb +1 -1
  38. data/spec/paperclip/file_command_content_type_detector_spec.rb +15 -1
  39. data/spec/paperclip/filename_cleaner_spec.rb +0 -1
  40. data/spec/paperclip/integration_spec.rb +41 -5
  41. data/spec/paperclip/interpolations_spec.rb +9 -0
  42. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +59 -0
  43. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +33 -16
  44. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +56 -8
  45. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +1 -1
  46. data/spec/paperclip/media_type_spoof_detector_spec.rb +41 -0
  47. data/spec/paperclip/paperclip_spec.rb +13 -13
  48. data/spec/paperclip/processor_spec.rb +4 -4
  49. data/spec/paperclip/schema_spec.rb +46 -46
  50. data/spec/paperclip/storage/fog_spec.rb +5 -0
  51. data/spec/paperclip/storage/s3_spec.rb +6 -6
  52. data/spec/paperclip/style_spec.rb +0 -1
  53. data/spec/paperclip/thumbnail_spec.rb +8 -6
  54. data/spec/paperclip/url_generator_spec.rb +0 -1
  55. data/spec/spec_helper.rb +0 -1
  56. data/spec/support/model_reconstruction.rb +2 -2
  57. metadata +120 -20
  58. data/spec/support/conditional_filter_helper.rb +0 -5
data/NEWS CHANGED
@@ -1,3 +1,38 @@
1
+ 6.1.0 (2018-07-27):
2
+
3
+ * BUGFIX: Don't double-encode URLs (Roderick Monje).
4
+ * BUGFIX: Only use the content_type when it exists (Jean-Philippe Doyle).
5
+ * STABILITY: Better handling of the content-disposition header. Now supports
6
+ file name that is either enclosed or not in double quotes and is case
7
+ insensitive as per RC6266 grammar (Hasan Kumar, Yves Riel).
8
+ * STABILITY: Change database column type of attachment file size from unsigned 4-byte
9
+ `integer` to unsigned 8-byte `bigint`. The former type limits attachment size
10
+ to just over 2GB, which can easily be exceeded by a large video file (Laurent
11
+ Arnoud, Alen Zamanyan).
12
+ * STABILITY: Better error message when thumbnail processing errors (Hayden Ball).
13
+ * STABILITY: Fix file linking issues around Windows (Akihiko Odaki).
14
+ * STABILITY: Files without an extension will now be checked for spoofing attempts
15
+ (George Walters II).
16
+ * STABILITY: Manually close Tempfiles when we are done with them (Erkki Eilonen).
17
+
18
+ 6.0.0 (2018-03-09):
19
+
20
+ * Improvement: Depend only on `aws-sdk-s3` instead of `aws-sdk` (https://github.com/thoughtbot/paperclip/pull/2481)
21
+
22
+ 5.3.0 (2018-03-09):
23
+
24
+ * Improvement: Use `FactoryBot` instead of `FactoryGirl` (https://github.com/thoughtbot/paperclip/pull/2501)
25
+ * Improvement: README updates (https://github.com/thoughtbot/paperclip/pull/2411, https://github.com/thoughtbot/paperclip/pull/2433, https://github.com/thoughtbot/paperclip/pull/2374, https://github.com/thoughtbot/paperclip/pull/2417, https://github.com/thoughtbot/paperclip/pull/2536)
26
+ * Improvement: Remove Ruby 2.4 deprecation warning (https://github.com/thoughtbot/paperclip/pull/2401)
27
+ * Improvement: Rails 5 migration compatibility (https://github.com/thoughtbot/paperclip/pull/2470)
28
+ * Improvement: Documentation around post processing (https://github.com/thoughtbot/paperclip/pull/2381)
29
+ * Improvement: S3 hostname example documentation (https://github.com/thoughtbot/paperclip/pull/2379)
30
+ * Bugfix: Allow paperclip to load in IRB (https://github.com/thoughtbot/paperclip/pull/2369)
31
+ * Bugfix: MIME type detection (https://github.com/thoughtbot/paperclip/issues/2527)
32
+ * Bugfix: Bad tempfile state after symlink failure (https://github.com/thoughtbot/paperclip/pull/2540)
33
+ * Bugfix: Rewind file after Fog bucket creation (https://github.com/thoughtbot/paperclip/pull/2572)
34
+ * Improvement: Use `Terrapin` instead of `Cocaine` (https://github.com/thoughtbot/paperclip/pull/2553)
35
+
1
36
  5.2.1 (2018-01-25):
2
37
 
3
38
  * Bugfix: Fix copying files on Windows. (#2532)
@@ -36,6 +71,7 @@
36
71
  * Improvement: S3 storage option `:s3_prefixes_in_alias`. (#2287)
37
72
  * Improvement: Fog option `:fog_public` can be a lambda. (#2302)
38
73
  * Improvement: One fewer warning on JRuby. (#2352)
74
+ * Ruby 2.4.0 compatibility (doesn't use Fixnum anymore)
39
75
 
40
76
  5.1.0 (2016-08-19):
41
77
 
data/README.md CHANGED
@@ -1,6 +1,28 @@
1
1
  Paperclip
2
2
  =========
3
3
 
4
+ # Deprecated
5
+
6
+ **[Paperclip is deprecated]**.
7
+
8
+ For new projects, we recommend Rails' own [ActiveStorage].
9
+
10
+ For existing projects, please consult and contribute to [the migration guide] ([en español]).
11
+
12
+
13
+ We will leave the Issues open as a discussion forum _only_. We do _not_
14
+ guarantee a response from us in the Issues.
15
+
16
+ We are no longer accepting pull requests _except_ pull requests against the
17
+ migration guide. All other pull requests will be closed without merging.
18
+
19
+ [Paperclip is deprecated]: https://robots.thoughtbot.com/closing-the-trombone
20
+ [ActiveStorage]: http://guides.rubyonrails.org/active_storage_overview.html
21
+ [the migration guide]: https://github.com/thoughtbot/paperclip/blob/master/MIGRATING.md
22
+ [en español]: https://github.com/thoughtbot/paperclip/blob/master/MIGRATING-ES.md
23
+
24
+ # Existing documentation
25
+
4
26
  ## Documentation valid for `master` branch
5
27
 
6
28
  Please check the documentation for the paperclip version you are using:
@@ -87,7 +109,7 @@ Requirements
87
109
  ### Ruby and Rails
88
110
 
89
111
  Paperclip now requires Ruby version **>= 2.1** and Rails version **>= 4.2**
90
- (only if you're going to use Paperclip with Ruby on Rails.)
112
+ (only if you're going to use Paperclip with Ruby on Rails).
91
113
 
92
114
  ### Image Processor
93
115
 
@@ -105,7 +127,7 @@ In development mode, you might add this line to `config/environments/development
105
127
  Paperclip.options[:command_path] = "/usr/local/bin/"
106
128
  ```
107
129
 
108
- If you're on Mac OS X, you'll want to run the following with [Homebrew] (http://www.brew.sh):
130
+ If you're on Mac OS X, you'll want to run the following with [Homebrew](http://www.brew.sh):
109
131
 
110
132
  brew install imagemagick
111
133
 
@@ -167,7 +189,7 @@ Paperclip is distributed as a gem, which is how it should be used in your app.
167
189
  Include the gem in your Gemfile:
168
190
 
169
191
  ```ruby
170
- gem "paperclip", "~> 5.0.0"
192
+ gem "paperclip", "~> 6.0.0"
171
193
  ```
172
194
 
173
195
  Or, if you want to get the latest, you can get master from the main paperclip repository:
@@ -206,6 +228,8 @@ end
206
228
 
207
229
  ### Migrations
208
230
 
231
+
232
+ Assuming you have a `users` table, add an `avatar` column to the `users` table:
209
233
  ```ruby
210
234
  class AddAvatarColumnsToUsers < ActiveRecord::Migration
211
235
  def up
@@ -221,10 +245,11 @@ end
221
245
  (Or you can use the Rails migration generator: `rails generate paperclip user avatar`)
222
246
 
223
247
  ### Edit and New Views
224
-
248
+ Make sure you have corresponding methods in your controller:
225
249
  ```erb
226
250
  <%= form_for @user, url: users_path, html: { multipart: true } do |form| %>
227
251
  <%= form.file_field :avatar %>
252
+ <%= form.submit %>
228
253
  <% end %>
229
254
  ```
230
255
 
@@ -233,6 +258,7 @@ end
233
258
  ```erb
234
259
  <%= simple_form_for @user, url: users_path do |form| %>
235
260
  <%= form.input :avatar, as: :file %>
261
+ <%= form.submit %>
236
262
  <% end %>
237
263
  ```
238
264
 
@@ -240,7 +266,7 @@ end
240
266
 
241
267
  ```ruby
242
268
  def create
243
- @user = User.create( user_params )
269
+ @user = User.create(user_params)
244
270
  end
245
271
 
246
272
  private
@@ -254,7 +280,7 @@ end
254
280
  ```
255
281
 
256
282
  ### View Helpers
257
-
283
+ Add these to the view where you want your images displayed:
258
284
  ```erb
259
285
  <%= image_tag @user.avatar.url %>
260
286
  <%= image_tag @user.avatar.url(:medium) %>
@@ -337,7 +363,7 @@ Lastly, you can also define multiple validations on a single attachment using `v
337
363
 
338
364
  ```ruby
339
365
  validates_attachment :avatar, presence: true,
340
- content_type: { content_type: "image/jpeg" },
366
+ content_type: "image/jpeg",
341
367
  size: { in: 0..10.kilobytes }
342
368
  ```
343
369
 
@@ -347,7 +373,7 @@ called with valid attachments._
347
373
 
348
374
  ```ruby
349
375
  class Message < ActiveRecord::Base
350
- has_attached_file :asset, styles: {thumb: "100x100#"}
376
+ has_attached_file :asset, styles: { thumb: "100x100#" }
351
377
 
352
378
  before_post_process :skip_for_audio
353
379
 
@@ -363,8 +389,8 @@ afterwards, then assign manually:
363
389
 
364
390
  ```ruby
365
391
  class Book < ActiveRecord::Base
366
- has_attached_file :document, styles: {thumbnail: "60x60#"}
367
- validates_attachment :document, content_type: { content_type: "application/pdf" }
392
+ has_attached_file :document, styles: { thumbnail: "60x60#" }
393
+ validates_attachment :document, content_type: "application/pdf"
368
394
  validates_something_else # Other validations that conflict with Paperclip's
369
395
  end
370
396
 
@@ -396,7 +422,7 @@ image-y ones:
396
422
 
397
423
  ```ruby
398
424
  validates_attachment :avatar,
399
- content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
425
+ content_type: ["image/jpeg", "image/gif", "image/png"]
400
426
  ```
401
427
 
402
428
  `Paperclip::ContentTypeDetector` will attempt to match a file's extension to an
@@ -563,7 +589,7 @@ Storage
563
589
  Paperclip ships with 3 storage adapters:
564
590
 
565
591
  * File Storage
566
- * S3 Storage (via `aws-sdk`)
592
+ * S3 Storage (via `aws-sdk-s3`)
567
593
  * Fog Storage
568
594
 
569
595
  If you would like to use Paperclip with another storage, you can install these
@@ -589,10 +615,10 @@ _**NOTE**: This is a change from previous versions of Paperclip, but is overall
589
615
  safer choice for the default file store._
590
616
 
591
617
  You may also choose to store your files using Amazon's S3 service. To do so, include
592
- the `aws-sdk` gem in your Gemfile:
618
+ the `aws-sdk-s3` gem in your Gemfile:
593
619
 
594
620
  ```ruby
595
- gem 'aws-sdk', '~> 2.3.0'
621
+ gem 'aws-sdk-s3'
596
622
  ```
597
623
 
598
624
  And then you can specify using S3 from `has_attached_file`.
@@ -656,6 +682,14 @@ JPGs will remain JPGs). `Paperclip::Thumbnail` uses ImageMagick to process
656
682
  images; [ImageMagick's geometry documentation](http://www.imagemagick.org/script/command-line-processing.php#geometry)
657
683
  has more information on the accepted style formats.
658
684
 
685
+ For more fine-grained control of the conversion process, `source_file_options` and `convert_options` can be used to pass flags and settings directly to ImageMagick's powerful Convert tool, [documented here](https://www.imagemagick.org/script/convert.php). For example:
686
+
687
+ ```ruby
688
+ has_attached_file :image, styles: { regular: ['800x800>', :png]},
689
+ source_file_options: { regular: "-density 96 -depth 8 -quality 85" },
690
+ convert_options: { regular: "-posterize 3"}
691
+ ```
692
+
659
693
  ImageMagick supports a number of environment variables for controlling its resource limits. For example, you can enforce memory or execution time limits by setting the following variables in your application's process environment:
660
694
 
661
695
  * `MAGICK_MEMORY_LIMIT=128MiB`
@@ -738,7 +772,7 @@ called with valid attachments._
738
772
 
739
773
  ```ruby
740
774
  class Message < ActiveRecord::Base
741
- has_attached_file :asset, styles: {thumb: "100x100#"}
775
+ has_attached_file :asset, styles: { thumb: "100x100#" }
742
776
 
743
777
  before_post_process :skip_for_audio
744
778
 
@@ -983,7 +1017,7 @@ similar mechanism for whichever parallel testing library you use.
983
1017
 
984
1018
  **Integration Tests**
985
1019
 
986
- Using integration tests with FactoryGirl may save multiple copies of
1020
+ Using integration tests with FactoryBot may save multiple copies of
987
1021
  your test files within the app. To avoid this, specify a custom path in
988
1022
  the `config/environments/test.rb` like so:
989
1023
 
@@ -1000,11 +1034,11 @@ config.after(:suite) do
1000
1034
  end
1001
1035
  ```
1002
1036
 
1003
- **Example of test configuration with Factory Girl**
1037
+ **Example of test configuration with Factory Bot**
1004
1038
 
1005
1039
 
1006
1040
  ```ruby
1007
- FactoryGirl.define do
1041
+ FactoryBot.define do
1008
1042
  factory :user do
1009
1043
  avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") }
1010
1044
  end
data/UPGRADING CHANGED
@@ -2,9 +2,9 @@
2
2
  # NOTE FOR UPGRADING FROM 4.3.0 OR EARLIER #
3
3
  ##################################################
4
4
 
5
- Paperclip is now compatible with aws-sdk >= 2.0.0.
5
+ Paperclip is now compatible with aws-sdk-s3.
6
6
 
7
- If you are using S3 storage, aws-sdk >= 2.0.0 requires you to make a few small
7
+ If you are using S3 storage, aws-sdk-s3 requires you to make a few small
8
8
  changes:
9
9
 
10
10
  * You must set the `s3_region`
@@ -13,5 +13,5 @@ changes:
13
13
  using a hyphen. For example, `:public_read` needs to be changed to
14
14
  `public-read`.
15
15
 
16
- For a walkthrough of upgrading from 4 to 5 and aws-sdk >= 2.0 you can watch
16
+ For a walkthrough of upgrading from 4 to *5* (not 6) and aws-sdk >= 2.0 you can watch
17
17
  http://rubythursday.com/episodes/ruby-snack-27-upgrade-paperclip-and-aws-sdk-in-prep-for-rails-5
@@ -84,12 +84,12 @@ end
84
84
 
85
85
  Then /^I should have attachment columns for "([^"]*)"$/ do |attachment_name|
86
86
  cd(".") do
87
- columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.type] }.inspect"`.strip)
87
+ columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.sql_type] }.inspect"`.strip)
88
88
  expect_columns = [
89
- ["#{attachment_name}_file_name", :string],
90
- ["#{attachment_name}_content_type", :string],
91
- ["#{attachment_name}_file_size", :integer],
92
- ["#{attachment_name}_updated_at", :datetime]
89
+ ["#{attachment_name}_file_name", "varchar"],
90
+ ["#{attachment_name}_content_type", "varchar"],
91
+ ["#{attachment_name}_file_size", "bigint"],
92
+ ["#{attachment_name}_updated_at", "datetime"]
93
93
  ]
94
94
  expect(columns).to include(*expect_columns)
95
95
  end
@@ -97,12 +97,12 @@ end
97
97
 
98
98
  Then /^I should not have attachment columns for "([^"]*)"$/ do |attachment_name|
99
99
  cd(".") do
100
- columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.type] }.inspect"`.strip)
100
+ columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.sql_type] }.inspect"`.strip)
101
101
  expect_columns = [
102
- ["#{attachment_name}_file_name", :string],
103
- ["#{attachment_name}_content_type", :string],
104
- ["#{attachment_name}_file_size", :integer],
105
- ["#{attachment_name}_updated_at", :datetime]
102
+ ["#{attachment_name}_file_name", "varchar"],
103
+ ["#{attachment_name}_content_type", "varchar"],
104
+ ["#{attachment_name}_file_size", "bigint"],
105
+ ["#{attachment_name}_updated_at", "datetime"]
106
106
  ]
107
107
 
108
108
  expect(columns).not_to include(*expect_columns)
@@ -17,7 +17,7 @@ Given /^I generate a new rails application$/ do
17
17
  gem "jruby-openssl", :platform => :jruby
18
18
  gem "capybara"
19
19
  gem "gherkin"
20
- gem "aws-sdk", "~> 2.0.0"
20
+ gem "aws-sdk-s3"
21
21
  gem "racc", :platform => :rbx
22
22
  gem "rubysl", :platform => :rbx
23
23
  """
@@ -13,7 +13,9 @@ class PaperclipGenerator < ActiveRecord::Generators::Base
13
13
  end
14
14
 
15
15
  def generate_migration
16
- migration_template "paperclip_migration.rb.erb", "db/migrate/#{migration_file_name}"
16
+ migration_template("paperclip_migration.rb.erb",
17
+ "db/migrate/#{migration_file_name}",
18
+ migration_version: migration_version)
17
19
  end
18
20
 
19
21
  def migration_name
@@ -27,4 +29,10 @@ class PaperclipGenerator < ActiveRecord::Generators::Base
27
29
  def migration_class_name
28
30
  migration_name.camelize
29
31
  end
32
+
33
+ def migration_version
34
+ if Rails.version.start_with? "5"
35
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
36
+ end
37
+ end
30
38
  end
@@ -1,4 +1,4 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration
1
+ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
3
  change_table :<%= table_name %> do |t|
4
4
  <% attachment_names.each do |attachment| -%>
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  require 'uri'
3
2
  require 'paperclip/url_generator'
4
3
  require 'active_support/deprecation'
@@ -338,8 +337,15 @@ module Paperclip
338
337
  # inconsistencies in timing of S3 commands. It's possible that calling
339
338
  # #reprocess! will lose data if the files are not kept.
340
339
  def reprocess!(*style_args)
341
- saved_only_process, @options[:only_process] = @options[:only_process], style_args
342
- saved_preserve_files, @options[:preserve_files] = @options[:preserve_files], true
340
+ saved_flags = @options.slice(
341
+ :only_process,
342
+ :preserve_files,
343
+ :check_validity_before_processing
344
+ )
345
+ @options[:only_process] = style_args
346
+ @options[:preserve_files] = true
347
+ @options[:check_validity_before_processing] = false
348
+
343
349
  begin
344
350
  assign(self)
345
351
  save
@@ -348,8 +354,7 @@ module Paperclip
348
354
  warn "#{e} - skipping file."
349
355
  false
350
356
  ensure
351
- @options[:only_process] = saved_only_process
352
- @options[:preserve_files] = saved_preserve_files
357
+ @options.merge!(saved_flags)
353
358
  end
354
359
  end
355
360
 
@@ -532,6 +537,10 @@ module Paperclip
532
537
  reduce(original) do |file, processor|
533
538
  file = Paperclip.processor(processor).make(file, style.processor_options, self)
534
539
  intermediate_files << file unless file == @queued_for_write[:original]
540
+ # if we're processing the original, close + unlink the source tempfile
541
+ if name == :original
542
+ @queued_for_write[:original].close(true)
543
+ end
535
544
  file
536
545
  end
537
546
 
@@ -591,7 +600,11 @@ module Paperclip
591
600
  def unlink_files(files)
592
601
  Array(files).each do |file|
593
602
  file.close unless file.closed?
594
- file.unlink if file.respond_to?(:unlink) && file.path.present? && File.exist?(file.path)
603
+
604
+ begin
605
+ file.unlink if file.respond_to?(:unlink)
606
+ rescue Errno::ENOENT
607
+ end
595
608
  end
596
609
  end
597
610
 
@@ -16,7 +16,7 @@ module Paperclip
16
16
  # On BSDs, `file` doesn't give a result code of 1 if the file doesn't exist.
17
17
  type = begin
18
18
  Paperclip.run("file", "-b --mime :file", file: @filename)
19
- rescue Cocaine::CommandLineError => e
19
+ rescue Terrapin::CommandLineError => e
20
20
  Paperclip.log("Error while determining content type: #{e}")
21
21
  SENSIBLE_DEFAULT
22
22
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  module Paperclip
3
2
  class FilenameCleaner
4
3
  def initialize(invalid_character_regex)
@@ -17,16 +17,16 @@ module Paperclip
17
17
  orientation = Paperclip.options[:use_exif_orientation] ?
18
18
  "%[exif:orientation]" : "1"
19
19
  Paperclip.run(
20
- "identify",
20
+ Paperclip.options[:is_windows] ? "magick identify" : "identify",
21
21
  "-format '%wx%h,#{orientation}' :file", {
22
22
  :file => "#{path}[0]"
23
23
  }, {
24
24
  :swallow_stderr => true
25
25
  }
26
26
  )
27
- rescue Cocaine::ExitStatusError
27
+ rescue Terrapin::ExitStatusError
28
28
  ""
29
- rescue Cocaine::CommandNotFoundError => e
29
+ rescue Terrapin::CommandNotFoundError => e
30
30
  raise_because_imagemagick_missing
31
31
  end
32
32
  end
@@ -27,12 +27,12 @@ module Paperclip
27
27
  #
28
28
  def run(cmd, arguments = "", interpolation_values = {}, local_options = {})
29
29
  command_path = options[:command_path]
30
- cocaine_path_array = Cocaine::CommandLine.path.try(:split, Cocaine::OS.path_separator)
31
- Cocaine::CommandLine.path = [cocaine_path_array, command_path].flatten.compact.uniq
30
+ terrapin_path_array = Terrapin::CommandLine.path.try(:split, Terrapin::OS.path_separator)
31
+ Terrapin::CommandLine.path = [terrapin_path_array, command_path].flatten.compact.uniq
32
32
  if logging? && (options[:log_command] || local_options[:log_command])
33
33
  local_options = local_options.merge(:logger => logger)
34
34
  end
35
- Cocaine::CommandLine.new(cmd, arguments, local_options).run(interpolation_values)
35
+ Terrapin::CommandLine.new(cmd, arguments, local_options).run(interpolation_values)
36
36
  end
37
37
 
38
38
  # Find all instances of the given Active Record model +klass+ with attachment +name+.
@@ -5,6 +5,7 @@ module Paperclip
5
5
  # Paperclip.interpolates method.
6
6
  module Interpolations
7
7
  extend self
8
+ ID_PARTITION_LIMIT = 1_000_000_000
8
9
 
9
10
  # Hash assignment of interpolations. Included only for compatibility,
10
11
  # and is not intended for normal use.
@@ -175,7 +176,11 @@ module Paperclip
175
176
  def id_partition attachment, style_name
176
177
  case id = attachment.instance.id
177
178
  when Integer
178
- ("%09d".freeze % id).scan(/\d{3}/).join("/".freeze)
179
+ if id < ID_PARTITION_LIMIT
180
+ ("%09d".freeze % id).scan(/\d{3}/).join("/".freeze)
181
+ else
182
+ ("%012d".freeze % id).scan(/\d{3}/).join("/".freeze)
183
+ end
179
184
  when String
180
185
  id.scan(/.{3}/).first(3).join("/".freeze)
181
186
  else
@@ -4,7 +4,7 @@ module Paperclip
4
4
  class AbstractAdapter
5
5
  OS_RESTRICTED_CHARACTERS = %r{[/:]}
6
6
 
7
- attr_reader :content_type, :original_filename, :size
7
+ attr_reader :content_type, :original_filename, :size, :tempfile
8
8
  delegate :binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink, :to => :@tempfile
9
9
  alias :length :size
10
10
 
@@ -57,13 +57,18 @@ module Paperclip
57
57
  end
58
58
 
59
59
  def link_or_copy_file(src, dest)
60
- Paperclip.log("Trying to link #{src} to #{dest}")
61
- FileUtils.ln(src, dest, force: true) # overwrite existing
60
+ begin
61
+ Paperclip.log("Trying to link #{src} to #{dest}")
62
+ FileUtils.ln(src, dest, force: true) # overwrite existing
63
+ rescue Errno::EXDEV, Errno::EPERM, Errno::ENOENT, Errno::EEXIST => e
64
+ Paperclip.log(
65
+ "Link failed with #{e.message}; copying link #{src} to #{dest}"
66
+ )
67
+ FileUtils.cp(src, dest)
68
+ end
69
+
62
70
  @destination.close
63
71
  @destination.open.binmode
64
- rescue Errno::EXDEV, Errno::EPERM, Errno::ENOENT, Errno::EEXIST => e
65
- Paperclip.log("Link failed with #{e.message}; copying link #{src} to #{dest}")
66
- FileUtils.cp(src, dest)
67
72
  end
68
73
  end
69
74
  end
@@ -31,7 +31,13 @@ module Paperclip
31
31
  if source.staged?
32
32
  link_or_copy_file(source.staged_path(@style), destination.path)
33
33
  else
34
- source.copy_to_local_file(@style, destination.path)
34
+ begin
35
+ source.copy_to_local_file(@style, destination.path)
36
+ rescue Errno::EACCES
37
+ # clean up lingering tempfile if we cannot access source file
38
+ destination.close(true)
39
+ raise
40
+ end
35
41
  end
36
42
  destination
37
43
  end
@@ -9,7 +9,8 @@ module Paperclip
9
9
  REGEXP = /\Ahttps?:\/\//
10
10
 
11
11
  def initialize(target, options = {})
12
- super(URI(URI.escape(target)), options)
12
+ escaped = URI.escape(target)
13
+ super(URI(target == URI.unescape(target) ? escaped : target), options)
13
14
  end
14
15
  end
15
16
  end
@@ -28,15 +28,17 @@ module Paperclip
28
28
  end
29
29
 
30
30
  def content_type_from_content
31
- if @content.respond_to?(:content_type)
32
- @content.content_type
33
- end
31
+ @content.meta["content-type"].presence
34
32
  end
35
33
 
36
34
  def filename_from_content_disposition
37
- if @content.meta.key?("content-disposition")
38
- matches = @content.meta["content-disposition"].match(/filename="([^"]*)"/)
39
- matches[1] if matches
35
+ if @content.meta.key?("content-disposition") && @content.meta["content-disposition"].match(/filename/i)
36
+ # can include both filename and filename* values according to RCF6266. filename should come first
37
+ _, filename = @content.meta["content-disposition"].split(/filename\*?\s*=\s*/i)
38
+
39
+ # filename can be enclosed in quotes or not
40
+ matches = filename.match(/"(.*)"/)
41
+ matches ? matches[1] : filename.split(';')[0]
40
42
  end
41
43
  end
42
44
 
@@ -2,7 +2,7 @@ module Paperclip
2
2
  module Logger
3
3
  # Log a paperclip-specific line. This will log to STDOUT
4
4
  # by default. Set Paperclip.options[:log] to false to turn off.
5
- def log message
5
+ def log(message)
6
6
  logger.info("[paperclip] #{message}") if logging?
7
7
  end
8
8
 
@@ -11,7 +11,7 @@ module Paperclip
11
11
  end
12
12
 
13
13
  def spoofed?
14
- if has_name? && has_extension? && media_type_mismatch? && mapping_override_mismatch?
14
+ if has_name? && media_type_mismatch? && mapping_override_mismatch?
15
15
  Paperclip.log("Content Type Spoof: Filename #{File.basename(@name)} (#{supplied_content_type} from Headers, #{content_types_from_name.map(&:to_s)} from Extension), content type discovered from file command: #{calculated_content_type}. See documentation to allow this combination.")
16
16
  true
17
17
  else
@@ -30,15 +30,18 @@ module Paperclip
30
30
  end
31
31
 
32
32
  def media_type_mismatch?
33
- supplied_type_mismatch? || calculated_type_mismatch?
33
+ extension_type_mismatch? || calculated_type_mismatch?
34
34
  end
35
35
 
36
- def supplied_type_mismatch?
37
- supplied_media_type.present? && !media_types_from_name.include?(supplied_media_type)
36
+ def extension_type_mismatch?
37
+ supplied_media_type.present? &&
38
+ has_extension? &&
39
+ !media_types_from_name.include?(supplied_media_type)
38
40
  end
39
41
 
40
42
  def calculated_type_mismatch?
41
- !media_types_from_name.include?(calculated_media_type)
43
+ supplied_media_type.present? &&
44
+ !calculated_content_type.include?(supplied_media_type)
42
45
  end
43
46
 
44
47
  def mapping_override_mismatch?
@@ -72,8 +75,9 @@ module Paperclip
72
75
 
73
76
  def type_from_file_command
74
77
  begin
75
- Paperclip.run("file", "-b --mime :file", :file => @file.path).split(/[:;]\s+/).first
76
- rescue Cocaine::CommandLineError
78
+ Paperclip.run("file", "-b --mime :file", file: @file.path).
79
+ split(/[:;\s]+/).first
80
+ rescue Terrapin::CommandLineError
77
81
  ""
78
82
  end
79
83
  end
@@ -37,13 +37,21 @@ module Paperclip
37
37
  # The convert method runs the convert binary with the provided arguments.
38
38
  # See Paperclip.run for the available options.
39
39
  def convert(arguments = "", local_options = {})
40
- Paperclip.run('convert', arguments, local_options)
40
+ Paperclip.run(
41
+ Paperclip.options[:is_windows] ? "magick convert" : "convert",
42
+ arguments,
43
+ local_options,
44
+ )
41
45
  end
42
46
 
43
47
  # The identify method runs the identify binary with the provided arguments.
44
48
  # See Paperclip.run for the available options.
45
49
  def identify(arguments = "", local_options = {})
46
- Paperclip.run('identify', arguments, local_options)
50
+ Paperclip.run(
51
+ Paperclip.options[:is_windows] ? "magick identify" : "identify",
52
+ arguments,
53
+ local_options,
54
+ )
47
55
  end
48
56
  end
49
57
  end
@@ -5,7 +5,7 @@ module Paperclip
5
5
  module Schema
6
6
  COLUMNS = {:file_name => :string,
7
7
  :content_type => :string,
8
- :file_size => :integer,
8
+ :file_size => :bigint,
9
9
  :updated_at => :datetime}
10
10
 
11
11
  def self.included(base)