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
    
        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] | 
| 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", "~>  | 
| 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( | 
| 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:  | 
| 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:  | 
| 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:  | 
| 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' | 
| 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  | 
| 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  | 
| 1037 | 
            +
            **Example of test configuration with Factory Bot**
         | 
| 1004 1038 |  | 
| 1005 1039 |  | 
| 1006 1040 | 
             
            ```ruby
         | 
| 1007 | 
            -
             | 
| 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 | 
| 5 | 
            +
            Paperclip is now compatible with aws-sdk-s3.
         | 
| 6 6 |  | 
| 7 | 
            -
            If you are using S3 storage, aws-sdk  | 
| 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. | 
| 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",  | 
| 90 | 
            -
                  ["#{attachment_name}_content_type",  | 
| 91 | 
            -
                  ["#{attachment_name}_file_size",  | 
| 92 | 
            -
                  ["#{attachment_name}_updated_at",  | 
| 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. | 
| 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",  | 
| 103 | 
            -
                  ["#{attachment_name}_content_type",  | 
| 104 | 
            -
                  ["#{attachment_name}_file_size",  | 
| 105 | 
            -
                  ["#{attachment_name}_updated_at",  | 
| 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)
         | 
| @@ -13,7 +13,9 @@ class PaperclipGenerator < ActiveRecord::Generators::Base | |
| 13 13 | 
             
              end
         | 
| 14 14 |  | 
| 15 15 | 
             
              def generate_migration
         | 
| 16 | 
            -
                migration_template | 
| 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
         | 
    
        data/lib/paperclip/attachment.rb
    CHANGED
    
    | @@ -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 | 
            -
                   | 
| 342 | 
            -
             | 
| 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 | 
| 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 | 
            -
             | 
| 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  | 
| 19 | 
            +
                         rescue Terrapin::CommandLineError => e
         | 
| 20 20 | 
             
                           Paperclip.log("Error while determining content type: #{e}")
         | 
| 21 21 | 
             
                           SENSIBLE_DEFAULT
         | 
| 22 22 | 
             
                         end
         | 
| @@ -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  | 
| 27 | 
            +
                  rescue Terrapin::ExitStatusError
         | 
| 28 28 | 
             
                    ""
         | 
| 29 | 
            -
                  rescue  | 
| 29 | 
            +
                  rescue Terrapin::CommandNotFoundError => e
         | 
| 30 30 | 
             
                    raise_because_imagemagick_missing
         | 
| 31 31 | 
             
                  end
         | 
| 32 32 | 
             
                end
         | 
    
        data/lib/paperclip/helpers.rb
    CHANGED
    
    | @@ -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 | 
            -
                   | 
| 31 | 
            -
                   | 
| 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 | 
            -
                   | 
| 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 | 
            -
                     | 
| 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 | 
            -
                   | 
| 61 | 
            -
             | 
| 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 | 
            -
                     | 
| 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
         | 
| @@ -28,15 +28,17 @@ module Paperclip | |
| 28 28 | 
             
                end
         | 
| 29 29 |  | 
| 30 30 | 
             
                def content_type_from_content
         | 
| 31 | 
            -
                   | 
| 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 | 
            -
                     | 
| 39 | 
            -
                     | 
| 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 |  | 
    
        data/lib/paperclip/logger.rb
    CHANGED
    
    
| @@ -11,7 +11,7 @@ module Paperclip | |
| 11 11 | 
             
                end
         | 
| 12 12 |  | 
| 13 13 | 
             
                def spoofed?
         | 
| 14 | 
            -
                  if has_name? &&  | 
| 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 | 
            -
                   | 
| 33 | 
            +
                  extension_type_mismatch? || calculated_type_mismatch?
         | 
| 34 34 | 
             
                end
         | 
| 35 35 |  | 
| 36 | 
            -
                def  | 
| 37 | 
            -
                  supplied_media_type.present? && | 
| 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 | 
            -
                   | 
| 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", : | 
| 76 | 
            -
             | 
| 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
         | 
    
        data/lib/paperclip/processor.rb
    CHANGED
    
    | @@ -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( | 
| 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( | 
| 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
         |