kt-paperclip 7.2.2 → 8.0.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 +4 -4
- data/LICENSE +1 -1
- data/README.md +24 -56
- data/lib/generators/paperclip/paperclip_generator.rb +3 -1
- data/lib/kt-paperclip.rb +2 -0
- data/lib/paperclip/attachment.rb +49 -30
- data/lib/paperclip/attachment_registry.rb +2 -0
- data/lib/paperclip/callbacks.rb +7 -4
- data/lib/paperclip/commands/imagemagick/geometry_parser.rb +63 -0
- data/lib/paperclip/commands/imagemagick/version_detector.rb +41 -0
- data/lib/paperclip/commands/imagemagick.rb +44 -0
- data/lib/paperclip/commands/runner.rb +38 -0
- data/lib/paperclip/commands/unix_file.rb +28 -0
- data/lib/paperclip/content_type_detector.rb +31 -32
- data/lib/paperclip/errors.rb +2 -0
- data/lib/paperclip/file_command_content_type_detector.rb +11 -12
- data/lib/paperclip/filename_cleaner.rb +2 -0
- data/lib/paperclip/geometry.rb +22 -7
- data/lib/paperclip/geometry_detector_factory.rb +11 -31
- data/lib/paperclip/geometry_parser_factory.rb +13 -17
- data/lib/paperclip/glue.rb +2 -0
- data/lib/paperclip/has_attached_file.rb +2 -0
- data/lib/paperclip/helpers.rb +5 -25
- data/lib/paperclip/interpolations/plural_cache.rb +2 -0
- data/lib/paperclip/interpolations.rb +2 -0
- data/lib/paperclip/io_adapters/abstract_adapter.rb +3 -1
- data/lib/paperclip/io_adapters/attachment_adapter.rb +11 -0
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/registry.rb +2 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +2 -0
- data/lib/paperclip/io_adapters/uri_adapter.rb +5 -13
- data/lib/paperclip/locales/fr.yml +18 -0
- data/lib/paperclip/locales/gd.yml +1 -1
- data/lib/paperclip/logger.rb +2 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +5 -3
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -0
- data/lib/paperclip/matchers.rb +2 -0
- data/lib/paperclip/media_type_spoof_detector.rb +3 -10
- data/lib/paperclip/missing_attachment_styles.rb +2 -0
- data/lib/paperclip/processor.rb +6 -19
- data/lib/paperclip/processor_helpers.rb +2 -0
- data/lib/paperclip/rails_environment.rb +2 -0
- data/lib/paperclip/railtie.rb +2 -0
- data/lib/paperclip/schema.rb +6 -4
- data/lib/paperclip/storage/filesystem.rb +2 -0
- data/lib/paperclip/storage/fog.rb +13 -4
- data/lib/paperclip/storage/s3.rb +27 -5
- data/lib/paperclip/storage.rb +2 -0
- data/lib/paperclip/style.rb +2 -0
- data/lib/paperclip/tempfile.rb +2 -0
- data/lib/paperclip/tempfile_factory.rb +2 -0
- data/lib/paperclip/thumbnail.rb +9 -10
- data/lib/paperclip/url_generator.rb +2 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +2 -0
- data/lib/paperclip/validators/attachment_file_name_validator.rb +2 -0
- data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +2 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +2 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +2 -0
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +2 -0
- data/lib/paperclip/validators.rb +2 -0
- data/lib/paperclip/version.rb +3 -1
- data/lib/paperclip.rb +25 -4
- data/lib/tasks/paperclip.rake +9 -4
- data/shoulda_macros/paperclip.rb +2 -0
- metadata +19 -538
- data/.codeclimate.yml +0 -17
- data/.github/FUNDING.yml +0 -3
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- data/.github/ISSUE_TEMPLATE/custom.md +0 -10
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- data/.gitignore +0 -19
- data/.hound.yml +0 -3
- data/.rubocop.yml +0 -1061
- data/.travis.yml +0 -45
- data/Appraisals +0 -30
- data/CONTRIBUTING.md +0 -85
- data/Gemfile +0 -19
- data/NEWS +0 -554
- data/RELEASING.md +0 -17
- data/Rakefile +0 -52
- data/UPGRADING +0 -17
- data/features/basic_integration.feature +0 -85
- data/features/migration.feature +0 -29
- data/features/rake_tasks.feature +0 -62
- data/features/step_definitions/attachment_steps.rb +0 -120
- data/features/step_definitions/html_steps.rb +0 -15
- data/features/step_definitions/rails_steps.rb +0 -257
- data/features/step_definitions/s3_steps.rb +0 -14
- data/features/step_definitions/web_steps.rb +0 -106
- data/features/support/env.rb +0 -12
- data/features/support/fakeweb.rb +0 -11
- data/features/support/file_helpers.rb +0 -34
- data/features/support/fixtures/boot_config.txt +0 -15
- data/features/support/fixtures/gemfile.txt +0 -5
- data/features/support/fixtures/preinitializer.txt +0 -20
- data/features/support/paths.rb +0 -28
- data/features/support/rails.rb +0 -39
- data/features/support/selectors.rb +0 -19
- data/gemfiles/4.2.gemfile +0 -20
- data/gemfiles/5.0.gemfile +0 -20
- data/gemfiles/5.1.gemfile +0 -20
- data/gemfiles/5.2.gemfile +0 -20
- data/gemfiles/6.0.gemfile +0 -20
- data/gemfiles/6.1.gemfile +0 -21
- data/gemfiles/7.0.gemfile +0 -21
- data/paperclip.gemspec +0 -50
- data/spec/database.yml +0 -4
- data/spec/paperclip/attachment_definitions_spec.rb +0 -13
- data/spec/paperclip/attachment_processing_spec.rb +0 -79
- data/spec/paperclip/attachment_registry_spec.rb +0 -158
- data/spec/paperclip/attachment_spec.rb +0 -1590
- data/spec/paperclip/content_type_detector_spec.rb +0 -54
- data/spec/paperclip/file_command_content_type_detector_spec.rb +0 -40
- data/spec/paperclip/filename_cleaner_spec.rb +0 -13
- data/spec/paperclip/geometry_detector_spec.rb +0 -47
- data/spec/paperclip/geometry_parser_spec.rb +0 -73
- data/spec/paperclip/geometry_spec.rb +0 -267
- data/spec/paperclip/glue_spec.rb +0 -63
- data/spec/paperclip/has_attached_file_spec.rb +0 -78
- data/spec/paperclip/integration_spec.rb +0 -702
- data/spec/paperclip/interpolations_spec.rb +0 -270
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +0 -160
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +0 -140
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +0 -88
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +0 -17
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +0 -131
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +0 -142
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +0 -8
- data/spec/paperclip/io_adapters/nil_adapter_spec.rb +0 -25
- data/spec/paperclip/io_adapters/registry_spec.rb +0 -35
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +0 -64
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +0 -146
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +0 -231
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +0 -19
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +0 -108
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +0 -69
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +0 -88
- data/spec/paperclip/media_type_spoof_detector_spec.rb +0 -126
- data/spec/paperclip/meta_class_spec.rb +0 -30
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +0 -88
- data/spec/paperclip/paperclip_spec.rb +0 -196
- data/spec/paperclip/plural_cache_spec.rb +0 -37
- data/spec/paperclip/processor_helpers_spec.rb +0 -57
- data/spec/paperclip/processor_spec.rb +0 -26
- data/spec/paperclip/rails_environment_spec.rb +0 -30
- data/spec/paperclip/rake_spec.rb +0 -103
- data/spec/paperclip/schema_spec.rb +0 -252
- data/spec/paperclip/storage/filesystem_spec.rb +0 -102
- data/spec/paperclip/storage/fog_spec.rb +0 -606
- data/spec/paperclip/storage/s3_live_spec.rb +0 -188
- data/spec/paperclip/storage/s3_spec.rb +0 -1878
- data/spec/paperclip/style_spec.rb +0 -251
- data/spec/paperclip/tempfile_factory_spec.rb +0 -33
- data/spec/paperclip/tempfile_spec.rb +0 -35
- data/spec/paperclip/thumbnail_spec.rb +0 -504
- data/spec/paperclip/url_generator_spec.rb +0 -231
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +0 -410
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +0 -249
- data/spec/paperclip/validators/attachment_presence_validator_spec.rb +0 -85
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +0 -325
- data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +0 -48
- data/spec/paperclip/validators_spec.rb +0 -179
- data/spec/spec_helper.rb +0 -46
- data/spec/support/assertions.rb +0 -84
- data/spec/support/fake_model.rb +0 -24
- data/spec/support/fake_rails.rb +0 -12
- data/spec/support/fixtures/12k.png +0 -0
- data/spec/support/fixtures/50x50.png +0 -0
- data/spec/support/fixtures/5k.png +0 -0
- data/spec/support/fixtures/animated +0 -0
- data/spec/support/fixtures/animated.gif +0 -0
- data/spec/support/fixtures/animated.unknown +0 -0
- data/spec/support/fixtures/aws_s3.yml +0 -13
- data/spec/support/fixtures/bad.png +0 -1
- data/spec/support/fixtures/empty.html +0 -1
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/fixtures/fog.yml +0 -8
- data/spec/support/fixtures/rotated.jpg +0 -0
- data/spec/support/fixtures/s3.yml +0 -8
- data/spec/support/fixtures/sample.xlsm +0 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/spec/support/fixtures/spaced file.png +0 -0
- data/spec/support/fixtures/text.txt +0 -1
- data/spec/support/fixtures/twopage.pdf +0 -0
- data/spec/support/fixtures/uppercase.PNG +0 -0
- data/spec/support/matchers/accept.rb +0 -5
- data/spec/support/matchers/exist.rb +0 -5
- data/spec/support/matchers/have_column.rb +0 -23
- data/spec/support/mock_attachment.rb +0 -24
- data/spec/support/mock_interpolator.rb +0 -24
- data/spec/support/mock_url_generator_builder.rb +0 -26
- data/spec/support/model_reconstruction.rb +0 -72
- data/spec/support/reporting.rb +0 -11
- data/spec/support/test_data.rb +0 -13
- data/spec/support/version_helper.rb +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 57acb40c010d089179840fb06116bb36527035ce5e6ddaa25531d2d24067456f
|
|
4
|
+
data.tar.gz: f49b37dbd63550be17c59b47ce930981dae6f7d88461cf90721925051e579efa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f92b7453a259e25763375ba727dc262910ec647e54017182befa98e0330e6ac5890cd76ab27476a3be6725de35aeb8b85f73db463ad75007370d0076ed3220bb
|
|
7
|
+
data.tar.gz: dae535db1d37087c4505aaa0db691c2e300377755c9345ef412a28dfde1bf55f64f169d6f438d0285672db9bc8681629708c1c366e719cfcb2773d89f6ad5906
|
data/LICENSE
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
1
|
LICENSE
|
|
3
2
|
|
|
4
3
|
The MIT License
|
|
5
4
|
|
|
6
5
|
Copyright (c) 2008-2016 Jon Yurek and thoughtbot, inc.
|
|
6
|
+
Copyright (c) 2019-2025 Kreeti Technologies Pvt Ltd.
|
|
7
7
|
|
|
8
8
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
9
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
|
@@ -93,73 +93,41 @@ Requirements
|
|
|
93
93
|
Paperclip now requires Ruby version **>= 2.3** and Rails version **>= 4.2**
|
|
94
94
|
(only if you're going to use Paperclip with Ruby on Rails).
|
|
95
95
|
|
|
96
|
-
### Image Processor
|
|
96
|
+
### ImageMagick Image Processor
|
|
97
97
|
|
|
98
|
-
[ImageMagick](http://www.imagemagick.org) must be installed and Paperclip must have access to it.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
[ImageMagick](http://www.imagemagick.org) must be installed and Paperclip must have access to it.
|
|
99
|
+
Refer to ImageMagick's [installations instructions](https://imagemagick.org/download/).
|
|
100
|
+
ImageMagick 7 is the latest version. As of April 2026, some package managers such as `apt`
|
|
101
|
+
still install ImageMagick 6.
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
In development mode, you might add this line to `config/environments/development.rb)`:
|
|
103
|
+
Paperclip supports both ImageMagick versions 6 and 7, and will auto-detect your version.
|
|
104
|
+
You may enforce a specific version in an initializer such as `config/initializers/paperclip.rb`:
|
|
107
105
|
|
|
108
106
|
```ruby
|
|
109
|
-
Paperclip.options[:
|
|
107
|
+
Paperclip.options[:imagemagick_version] = "7"
|
|
110
108
|
```
|
|
111
109
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
brew install imagemagick
|
|
115
|
-
|
|
116
|
-
If you are dealing with pdf uploads or running the test suite, you'll also need
|
|
117
|
-
to install GhostScript. On Mac OS X, you can also install that using Homebrew:
|
|
118
|
-
|
|
119
|
-
brew install gs
|
|
120
|
-
|
|
121
|
-
If you are on Ubuntu (or any Debian base Linux distribution), you'll want to run
|
|
122
|
-
the following with apt-get:
|
|
123
|
-
|
|
124
|
-
sudo apt-get install imagemagick -y
|
|
125
|
-
|
|
126
|
-
### `file`
|
|
127
|
-
|
|
128
|
-
The Unix [`file` command](https://en.wikipedia.org/wiki/File_(command)) is required for content-type checking.
|
|
129
|
-
This utility isn't available in Windows, but comes bundled with Ruby [Devkit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit),
|
|
130
|
-
so Windows users must make sure that the devkit is installed and added to the system `PATH`.
|
|
131
|
-
|
|
132
|
-
**Manual Installation**
|
|
133
|
-
|
|
134
|
-
If you're using Windows 7+ as a development environment, you may need to install the `file.exe` application manually. The `file spoofing` system in Paperclip 4+ relies on this; if you don't have it working, you'll receive `Validation failed: Upload file has an extension that does not match its contents.` errors.
|
|
110
|
+
Please ensure ImageMagick is in your environment path, or alternatively set
|
|
111
|
+
the path manually in an initializer:
|
|
135
112
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
To test, you can use the image below:
|
|
141
|
-

|
|
142
|
-
|
|
143
|
-
Next, you need to integrate with your environment - preferably through the `PATH` variable, or by changing your `config/environments/development.rb` file
|
|
144
|
-
|
|
145
|
-
**PATH**
|
|
146
|
-
|
|
147
|
-
1. Click "Start"
|
|
148
|
-
2. On "Computer", right-click and select "Properties"
|
|
149
|
-
3. In Properties, select "Advanced System Settings"
|
|
150
|
-
4. Click the "Environment Variables" button
|
|
151
|
-
5. Locate the "PATH" var - at the end, add the path to your newly installed `file.exe` (typically `C:\Program Files (x86)\GnuWin32\bin`)
|
|
152
|
-
6. Restart any CMD shells you have open & see if it works
|
|
113
|
+
```ruby
|
|
114
|
+
Paperclip.options[:imagemagick_path] = "/usr/local/bin/"
|
|
115
|
+
```
|
|
153
116
|
|
|
154
|
-
|
|
117
|
+
### Optional: Unix `file` Command
|
|
155
118
|
|
|
156
|
-
|
|
119
|
+
Paperclip uses the [Marcel gem](https://github.com/rails/marcel) to detect file content types.
|
|
120
|
+
If Marcel cannot detect the type, the [Unix `file` command](https://en.wikipedia.org/wiki/File_(command))
|
|
121
|
+
is used as an optional fallback. To use it, ensure `file` is in your environment path,
|
|
122
|
+
or alternatively set its path manually in an initializer:
|
|
157
123
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
124
|
+
```ruby
|
|
125
|
+
Paperclip.options[:file_command_path] = "/usr/local/bin/"
|
|
126
|
+
```
|
|
161
127
|
|
|
162
|
-
|
|
128
|
+
Windows users should install the `file` utility via the Ruby Installer for Windows'
|
|
129
|
+
[DevKit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit), or alternatively,
|
|
130
|
+
by installing [MSYS2](https://www.msys2.org/) which provides Unix utilities for Windows.
|
|
163
131
|
|
|
164
132
|
---
|
|
165
133
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "rails/generators/active_record"
|
|
2
4
|
|
|
3
5
|
class PaperclipGenerator < ActiveRecord::Generators::Base
|
|
@@ -31,6 +33,6 @@ class PaperclipGenerator < ActiveRecord::Generators::Base
|
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
def migration_version
|
|
34
|
-
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
|
36
|
+
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
|
35
37
|
end
|
|
36
38
|
end
|
data/lib/kt-paperclip.rb
CHANGED
data/lib/paperclip/attachment.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "uri"
|
|
2
4
|
require "paperclip/url_generator"
|
|
3
5
|
require "active_support/deprecation"
|
|
@@ -10,30 +12,31 @@ module Paperclip
|
|
|
10
12
|
class Attachment
|
|
11
13
|
def self.default_options
|
|
12
14
|
@default_options ||= {
|
|
13
|
-
convert_options:
|
|
14
|
-
default_style:
|
|
15
|
-
default_url:
|
|
16
|
-
escape_url:
|
|
17
|
-
restricted_characters:
|
|
18
|
-
filename_cleaner:
|
|
19
|
-
hash_data:
|
|
20
|
-
hash_digest:
|
|
21
|
-
interpolator:
|
|
22
|
-
only_process:
|
|
23
|
-
path:
|
|
24
|
-
preserve_files:
|
|
25
|
-
processors:
|
|
26
|
-
source_file_options:
|
|
27
|
-
storage:
|
|
28
|
-
styles:
|
|
29
|
-
url:
|
|
30
|
-
url_generator:
|
|
31
|
-
use_default_time_zone:
|
|
32
|
-
use_timestamp:
|
|
33
|
-
whiny:
|
|
34
|
-
validate_media_type:
|
|
35
|
-
adapter_options:
|
|
36
|
-
check_validity_before_processing:
|
|
15
|
+
convert_options: {},
|
|
16
|
+
default_style: :original,
|
|
17
|
+
default_url: "/:attachment/:style/missing.png",
|
|
18
|
+
escape_url: true,
|
|
19
|
+
restricted_characters: /[&$+,\/:;=?@<>\[\]\{\}\|\\\^~%# ]/,
|
|
20
|
+
filename_cleaner: nil,
|
|
21
|
+
hash_data: ":class/:attachment/:id/:style/:updated_at",
|
|
22
|
+
hash_digest: "SHA1",
|
|
23
|
+
interpolator: Paperclip::Interpolations,
|
|
24
|
+
only_process: [],
|
|
25
|
+
path: ":rails_root/public:url",
|
|
26
|
+
preserve_files: false,
|
|
27
|
+
processors: [:thumbnail],
|
|
28
|
+
source_file_options: {},
|
|
29
|
+
storage: :filesystem,
|
|
30
|
+
styles: {},
|
|
31
|
+
url: "/system/:class/:attachment/:id_partition/:style/:filename",
|
|
32
|
+
url_generator: Paperclip::UrlGenerator,
|
|
33
|
+
use_default_time_zone: true,
|
|
34
|
+
use_timestamp: true,
|
|
35
|
+
whiny: Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails],
|
|
36
|
+
validate_media_type: true,
|
|
37
|
+
adapter_options: { hash_digest: Digest::MD5 },
|
|
38
|
+
check_validity_before_processing: true,
|
|
39
|
+
return_file_attributes_on_destroy: false
|
|
37
40
|
}
|
|
38
41
|
end
|
|
39
42
|
|
|
@@ -69,6 +72,8 @@ module Paperclip
|
|
|
69
72
|
# +interpolator+ - the object used to interpolate filenames and URLs. Defaults to Paperclip::Interpolations
|
|
70
73
|
# +url_generator+ - the object used to generate URLs, using the interpolator. Defaults to Paperclip::UrlGenerator
|
|
71
74
|
# +escape_url+ - Perform URI escaping to URLs. Defaults to true
|
|
75
|
+
# +return_file_attributes_on_destroy+ - whether attachment-related attributes should be displayed when
|
|
76
|
+
# destroying a record. Defaults to false.
|
|
72
77
|
def initialize(name, instance, options = {})
|
|
73
78
|
@name = name.to_sym
|
|
74
79
|
@name_string = name.to_s
|
|
@@ -563,12 +568,10 @@ module Paperclip
|
|
|
563
568
|
path(style) if exists?(style)
|
|
564
569
|
end.compact
|
|
565
570
|
end
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
instance_write(:created_at, nil) if has_enabled_but_unset_created_at?
|
|
571
|
-
instance_write(:updated_at, nil)
|
|
571
|
+
|
|
572
|
+
return if show_attrs_and_destroy_callback_triggered?
|
|
573
|
+
|
|
574
|
+
clear_all_attachment_attributes
|
|
572
575
|
end
|
|
573
576
|
|
|
574
577
|
def flush_errors #:nodoc:
|
|
@@ -613,5 +616,21 @@ module Paperclip
|
|
|
613
616
|
def has_enabled_but_unset_created_at?
|
|
614
617
|
able_to_store_created_at? && !instance_read(:created_at)
|
|
615
618
|
end
|
|
619
|
+
|
|
620
|
+
# Checks whether the option to show attributes to be destroyed is enabled and whether a destroy callback has been
|
|
621
|
+
# invoked when deleting the entire record.
|
|
622
|
+
def show_attrs_and_destroy_callback_triggered?
|
|
623
|
+
@options[:return_file_attributes_on_destroy] && instance.instance_variable_get(:@_destroy_callback_already_called)
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
# Sets attachment-related attributes to `nil`.
|
|
627
|
+
def clear_all_attachment_attributes
|
|
628
|
+
instance_write(:file_name, nil)
|
|
629
|
+
instance_write(:content_type, nil)
|
|
630
|
+
instance_write(:file_size, nil)
|
|
631
|
+
instance_write(:fingerprint, nil)
|
|
632
|
+
instance_write(:created_at, nil) if has_enabled_but_unset_created_at?
|
|
633
|
+
instance_write(:updated_at, nil)
|
|
634
|
+
end
|
|
616
635
|
end
|
|
617
636
|
end
|
data/lib/paperclip/callbacks.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Paperclip
|
|
2
4
|
module Callbacks
|
|
3
5
|
def self.included(base)
|
|
@@ -9,14 +11,15 @@ module Paperclip
|
|
|
9
11
|
def define_paperclip_callbacks(*callbacks)
|
|
10
12
|
define_callbacks(*[callbacks, { terminator: hasta_la_vista_baby }].flatten)
|
|
11
13
|
callbacks.each do |callback|
|
|
12
|
-
|
|
13
|
-
def before_#{callback}(*args, &blk)
|
|
14
|
+
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
|
15
|
+
def self.before_#{callback}(*args, &blk)
|
|
14
16
|
set_callback(:#{callback}, :before, *args, &blk)
|
|
15
17
|
end
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
def self.after_#{callback}(*args, &blk)
|
|
17
20
|
set_callback(:#{callback}, :after, *args, &blk)
|
|
18
21
|
end
|
|
19
|
-
|
|
22
|
+
RUBY
|
|
20
23
|
end
|
|
21
24
|
end
|
|
22
25
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paperclip
|
|
4
|
+
module Commands
|
|
5
|
+
module ImageMagick
|
|
6
|
+
module GeometryParser
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
FORMAT = /\b(\d*)x?(\d*)\b(?:,(\d?))?(@>|>@|[><#@%^!])?/i.freeze
|
|
10
|
+
|
|
11
|
+
# Runs `magick identify` and returns a Paperclip::Geometry
|
|
12
|
+
def detect(file)
|
|
13
|
+
parse(fetch(file))
|
|
14
|
+
end
|
|
15
|
+
alias_method :from_file, :detect
|
|
16
|
+
|
|
17
|
+
# Parses a "WxH,O" string into a Paperclip::Geometry
|
|
18
|
+
def parse(string)
|
|
19
|
+
return unless (match = string&.strip&.match(FORMAT))
|
|
20
|
+
|
|
21
|
+
Paperclip::Geometry.new(
|
|
22
|
+
width: match[1],
|
|
23
|
+
height: match[2],
|
|
24
|
+
orientation: match[3],
|
|
25
|
+
modifier: match[4]
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def fetch(file)
|
|
32
|
+
filepath = path(file)
|
|
33
|
+
raise_error("Cannot find the geometry of a file with a blank name") if filepath.blank?
|
|
34
|
+
|
|
35
|
+
str = Paperclip::Commands::ImageMagick.identify(
|
|
36
|
+
"-format '%wx%h,#{orientation}' :file",
|
|
37
|
+
{ file: "#{filepath}[0]" },
|
|
38
|
+
{ swallow_stderr: true }
|
|
39
|
+
).presence
|
|
40
|
+
|
|
41
|
+
raise_error unless str
|
|
42
|
+
|
|
43
|
+
str
|
|
44
|
+
rescue Terrapin::ExitStatusError
|
|
45
|
+
raise_error
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def path(file)
|
|
49
|
+
file.respond_to?(:path) ? file.path : file
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def orientation
|
|
53
|
+
Paperclip.options[:use_exif_orientation] ? "%[exif:orientation]" : "1"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def raise_error(message = nil)
|
|
57
|
+
message ||= "Could not identify image size"
|
|
58
|
+
raise Errors::NotIdentifiedByImageMagickError.new(message)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paperclip
|
|
4
|
+
module Commands
|
|
5
|
+
module ImageMagick
|
|
6
|
+
module VersionDetector
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
# Returns 6, 7, or nil (not installed)
|
|
10
|
+
def detected_version
|
|
11
|
+
return @detected_version if defined?(@detected_version)
|
|
12
|
+
|
|
13
|
+
@detected_version = detect
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def detect
|
|
19
|
+
return 7 if valid?("magick")
|
|
20
|
+
return 6 if valid?("convert")
|
|
21
|
+
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def valid?(command)
|
|
26
|
+
run(command).to_s.include?("ImageMagick")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def run(command)
|
|
30
|
+
Paperclip::Commands::Runner.run(command, path, "-version", {}, swallow_stderr: true)
|
|
31
|
+
rescue Terrapin::CommandLineError
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def path
|
|
36
|
+
Paperclip::Commands::ImageMagick.imagemagick_path
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paperclip
|
|
4
|
+
module Commands
|
|
5
|
+
module ImageMagick
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
def convert(arguments = nil, interpolation_values = {}, local_options = {})
|
|
9
|
+
run(convert_command, imagemagick_path, arguments, interpolation_values, local_options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def identify(arguments = nil, interpolation_values = {}, local_options = {})
|
|
13
|
+
run(identify_command, imagemagick_path, arguments, interpolation_values, local_options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def imagemagick_path
|
|
17
|
+
Paperclip.options[:imagemagick_path]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def run(command, path = nil, arguments = nil, interpolation_values = {}, local_options = {})
|
|
23
|
+
Runner.run(command, path || imagemagick_path, arguments, interpolation_values, local_options)
|
|
24
|
+
rescue Terrapin::CommandNotFoundError
|
|
25
|
+
raise Errors::CommandNotFoundError.new("Could not run the `#{command}` command. Please install ImageMagick.")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Returns true if ImageMagick 7 is in use (either detected or forced via config)
|
|
29
|
+
def magick_command?
|
|
30
|
+
version = Paperclip.options[:imagemagick_version]&.to_i ||
|
|
31
|
+
VersionDetector.detected_version
|
|
32
|
+
!version.nil? && version >= 7
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def convert_command
|
|
36
|
+
magick_command? ? "magick" : "convert"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def identify_command
|
|
40
|
+
magick_command? ? "magick identify" : "identify"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paperclip
|
|
4
|
+
module Commands
|
|
5
|
+
module Runner
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
def run(command, path = nil, arguments = nil, interpolation_values = {}, local_options = {})
|
|
9
|
+
if Paperclip.logging? && (Paperclip.options[:log_command] || local_options[:log_command])
|
|
10
|
+
local_options = local_options.merge(logger: Paperclip.logger)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
binary = resolve_binary(command, path)
|
|
14
|
+
|
|
15
|
+
Terrapin::CommandLine.new(binary, arguments, local_options)
|
|
16
|
+
.run(interpolation_values)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def resolve_binary(command, path)
|
|
22
|
+
# @deprecated +Paperclip.options[:command_path]+ will be removed in Paperclip 8.0
|
|
23
|
+
path ||= Paperclip.options[:command_path]
|
|
24
|
+
return command unless path
|
|
25
|
+
|
|
26
|
+
# command may be multi-word (e.g. "magick identify")
|
|
27
|
+
words = command.split(" ", 2)
|
|
28
|
+
candidate = File.join(path, words[0])
|
|
29
|
+
if File.executable?(candidate)
|
|
30
|
+
words[0] = candidate
|
|
31
|
+
words.join(" ")
|
|
32
|
+
else
|
|
33
|
+
command
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paperclip
|
|
4
|
+
module Commands
|
|
5
|
+
module UnixFile
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
# Returns a normalized content type value, otherwise nil.
|
|
9
|
+
def detect_content_type(file)
|
|
10
|
+
type = run_file_command(file)
|
|
11
|
+
return if type.blank? || type.match(/\(.*?\)/)
|
|
12
|
+
|
|
13
|
+
type.split(/[:;\s]+/)[0].strip
|
|
14
|
+
rescue Terrapin::CommandLineError => e
|
|
15
|
+
Paperclip.log("Error while determining content type: #{e}")
|
|
16
|
+
nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def run_file_command(file)
|
|
22
|
+
Runner.run("file", Paperclip.options[:file_command_path], "-b --mime :file", { file: file })
|
|
23
|
+
rescue Terrapin::CommandLineError
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,22 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Paperclip
|
|
4
|
+
# The content-type detection strategy is as follows:
|
|
5
|
+
#
|
|
6
|
+
# 1. Blank/Empty files: If there's no filepath or the file is empty,
|
|
7
|
+
# provide a sensible default (application/octet-stream or inode/x-empty)
|
|
8
|
+
#
|
|
9
|
+
# 2. Calculated match: Return the first result that is found by both the
|
|
10
|
+
# Marcel gem (or `file` command) and MIME::Types.
|
|
11
|
+
#
|
|
12
|
+
# 3. Standard types: Return the first standard (without an x- prefix) entry
|
|
13
|
+
# in MIME::Types
|
|
14
|
+
#
|
|
15
|
+
# 4. Experimental types: If there were no standard types in MIME::Types
|
|
16
|
+
# list, try to return the first experimental one
|
|
17
|
+
#
|
|
18
|
+
# 5. Raw `file` command: Just use the output of Marcel (or `file` command),
|
|
19
|
+
# cached from step 2.
|
|
20
|
+
#
|
|
21
|
+
# 6. If nothing found, return a sensible default.
|
|
2
22
|
class ContentTypeDetector
|
|
3
|
-
# The content-type detection strategy is as follows:
|
|
4
|
-
#
|
|
5
|
-
# 1. Blank/Empty files: If there's no filepath or the file is empty,
|
|
6
|
-
# provide a sensible default (application/octet-stream or inode/x-empty)
|
|
7
|
-
#
|
|
8
|
-
# 2. Calculated match: Return the first result that is found by both the
|
|
9
|
-
# `file` command and MIME::Types.
|
|
10
|
-
#
|
|
11
|
-
# 3. Standard types: Return the first standard (without an x- prefix) entry
|
|
12
|
-
# in MIME::Types
|
|
13
|
-
#
|
|
14
|
-
# 4. Experimental types: If there were no standard types in MIME::Types
|
|
15
|
-
# list, try to return the first experimental one
|
|
16
|
-
#
|
|
17
|
-
# 5. Raw `file` command: Just use the output of the `file` command raw, or
|
|
18
|
-
# a sensible default. This is cached from Step 2.
|
|
19
|
-
|
|
20
23
|
EMPTY_TYPE = "inode/x-empty"
|
|
21
24
|
SENSIBLE_DEFAULT = "application/octet-stream"
|
|
22
25
|
|
|
@@ -25,15 +28,15 @@ module Paperclip
|
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
# Returns a String describing the file's content type
|
|
28
|
-
def detect
|
|
31
|
+
def detect(default = SENSIBLE_DEFAULT)
|
|
29
32
|
if blank_name?
|
|
30
|
-
|
|
33
|
+
default
|
|
31
34
|
elsif empty_file?
|
|
32
35
|
EMPTY_TYPE
|
|
33
36
|
elsif calculated_type_matches.any?
|
|
34
37
|
calculated_type_matches.first
|
|
35
38
|
else
|
|
36
|
-
type_from_file_contents ||
|
|
39
|
+
type_from_file_contents || default
|
|
37
40
|
end.to_s
|
|
38
41
|
end
|
|
39
42
|
|
|
@@ -60,26 +63,22 @@ module Paperclip
|
|
|
60
63
|
end
|
|
61
64
|
|
|
62
65
|
def type_from_file_contents
|
|
63
|
-
|
|
66
|
+
return @type_from_file_contents if defined?(@type_from_file_contents)
|
|
67
|
+
|
|
68
|
+
@type_from_file_contents = type_from_marcel || type_from_file_command
|
|
64
69
|
rescue Errno::ENOENT => e
|
|
65
70
|
Paperclip.log("Error while determining content type: #{e}")
|
|
66
|
-
|
|
71
|
+
@type_from_file_contents = nil
|
|
67
72
|
end
|
|
68
73
|
|
|
69
74
|
def type_from_marcel
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
name: @filepath
|
|
74
|
-
# Marcel::MineType returns 'application/octet-stream' if it can't find
|
|
75
|
-
# a valid type.
|
|
76
|
-
@type_from_marcel = nil if @type_from_marcel == SENSIBLE_DEFAULT
|
|
77
|
-
@type_from_marcel
|
|
75
|
+
type = Marcel::MimeType.for(Pathname.new(@filepath), name: @filepath)
|
|
76
|
+
# Marcel::MineType returns 'application/octet-stream' if it can't find a valid type.
|
|
77
|
+
type == SENSIBLE_DEFAULT ? nil : type
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def type_from_file_command
|
|
81
|
-
@
|
|
82
|
-
FileCommandContentTypeDetector.new(@filepath).detect
|
|
81
|
+
Commands::UnixFile.detect_content_type(@filepath)
|
|
83
82
|
end
|
|
84
83
|
end
|
|
85
84
|
end
|
data/lib/paperclip/errors.rb
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Paperclip
|
|
4
|
+
# @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::ContentTypeDetector+ instead.
|
|
2
5
|
class FileCommandContentTypeDetector
|
|
6
|
+
# @deprecated Will be removed in Paperclip 8.0.
|
|
3
7
|
SENSIBLE_DEFAULT = "application/octet-stream"
|
|
4
8
|
|
|
9
|
+
# @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::ContentTypeDetector+ instead.
|
|
5
10
|
def initialize(filename)
|
|
11
|
+
warn_deprecation
|
|
6
12
|
@filename = filename
|
|
7
13
|
end
|
|
8
14
|
|
|
15
|
+
# @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::ContentTypeDetector+ instead.
|
|
9
16
|
def detect
|
|
10
|
-
|
|
17
|
+
warn_deprecation
|
|
18
|
+
Paperclip::Commands::UnixFile.detect_content_type(@filename) || SENSIBLE_DEFAULT
|
|
11
19
|
end
|
|
12
20
|
|
|
13
21
|
private
|
|
14
22
|
|
|
15
|
-
def
|
|
16
|
-
|
|
17
|
-
type = begin
|
|
18
|
-
Paperclip.run("file", "-b --mime :file", file: @filename)
|
|
19
|
-
rescue Terrapin::CommandLineError => e
|
|
20
|
-
Paperclip.log("Error while determining content type: #{e}")
|
|
21
|
-
SENSIBLE_DEFAULT
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
type = SENSIBLE_DEFAULT if type.nil? || type.match(/\(.*?\)/)
|
|
25
|
-
type.split(/[:;\s]+/)[0]
|
|
23
|
+
def warn_deprecation
|
|
24
|
+
Paperclip.deprecator.warn("Paperclip::FileCommandContentTypeDetector has been replaced by Paperclip::ContentTypeDetector.")
|
|
26
25
|
end
|
|
27
26
|
end
|
|
28
27
|
end
|