kt-paperclip 7.3.0 → 8.0.1

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.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +40 -61
  3. data/lib/generators/paperclip/paperclip_generator.rb +3 -1
  4. data/lib/kt-paperclip.rb +2 -0
  5. data/lib/paperclip/attachment.rb +2 -0
  6. data/lib/paperclip/attachment_registry.rb +2 -0
  7. data/lib/paperclip/callbacks.rb +7 -4
  8. data/lib/paperclip/commands/imagemagick/geometry_parser.rb +63 -0
  9. data/lib/paperclip/commands/imagemagick/version_detector.rb +41 -0
  10. data/lib/paperclip/commands/imagemagick.rb +44 -0
  11. data/lib/paperclip/commands/runner.rb +38 -0
  12. data/lib/paperclip/commands/unix_file.rb +28 -0
  13. data/lib/paperclip/content_type_detector.rb +31 -32
  14. data/lib/paperclip/errors.rb +2 -0
  15. data/lib/paperclip/file_command_content_type_detector.rb +11 -12
  16. data/lib/paperclip/filename_cleaner.rb +2 -0
  17. data/lib/paperclip/geometry.rb +22 -7
  18. data/lib/paperclip/geometry_detector_factory.rb +11 -31
  19. data/lib/paperclip/geometry_parser_factory.rb +13 -17
  20. data/lib/paperclip/glue.rb +2 -0
  21. data/lib/paperclip/has_attached_file.rb +2 -0
  22. data/lib/paperclip/helpers.rb +5 -25
  23. data/lib/paperclip/interpolations/plural_cache.rb +2 -0
  24. data/lib/paperclip/interpolations.rb +2 -0
  25. data/lib/paperclip/io_adapters/abstract_adapter.rb +2 -0
  26. data/lib/paperclip/io_adapters/attachment_adapter.rb +2 -0
  27. data/lib/paperclip/io_adapters/data_uri_adapter.rb +2 -0
  28. data/lib/paperclip/io_adapters/empty_string_adapter.rb +2 -0
  29. data/lib/paperclip/io_adapters/file_adapter.rb +2 -0
  30. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +2 -0
  31. data/lib/paperclip/io_adapters/identity_adapter.rb +2 -0
  32. data/lib/paperclip/io_adapters/nil_adapter.rb +2 -0
  33. data/lib/paperclip/io_adapters/registry.rb +2 -0
  34. data/lib/paperclip/io_adapters/stringio_adapter.rb +2 -0
  35. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +2 -0
  36. data/lib/paperclip/io_adapters/uri_adapter.rb +5 -13
  37. data/lib/paperclip/logger.rb +2 -0
  38. data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -0
  39. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +5 -3
  40. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -0
  41. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -0
  42. data/lib/paperclip/matchers.rb +2 -0
  43. data/lib/paperclip/media_type_spoof_detector.rb +42 -11
  44. data/lib/paperclip/missing_attachment_styles.rb +2 -0
  45. data/lib/paperclip/processor.rb +6 -19
  46. data/lib/paperclip/processor_helpers.rb +2 -0
  47. data/lib/paperclip/rails_environment.rb +2 -0
  48. data/lib/paperclip/railtie.rb +2 -0
  49. data/lib/paperclip/schema.rb +6 -4
  50. data/lib/paperclip/storage/filesystem.rb +2 -0
  51. data/lib/paperclip/storage/fog.rb +4 -3
  52. data/lib/paperclip/storage/s3.rb +3 -3
  53. data/lib/paperclip/storage.rb +2 -0
  54. data/lib/paperclip/style.rb +2 -0
  55. data/lib/paperclip/tempfile.rb +2 -0
  56. data/lib/paperclip/tempfile_factory.rb +2 -0
  57. data/lib/paperclip/thumbnail.rb +9 -10
  58. data/lib/paperclip/url_generator.rb +2 -0
  59. data/lib/paperclip/validators/attachment_content_type_validator.rb +2 -0
  60. data/lib/paperclip/validators/attachment_file_name_validator.rb +2 -0
  61. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +2 -0
  62. data/lib/paperclip/validators/attachment_presence_validator.rb +2 -0
  63. data/lib/paperclip/validators/attachment_size_validator.rb +2 -0
  64. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +2 -0
  65. data/lib/paperclip/validators.rb +2 -0
  66. data/lib/paperclip/version.rb +3 -1
  67. data/lib/paperclip.rb +25 -4
  68. data/lib/tasks/paperclip.rake +9 -4
  69. data/shoulda_macros/paperclip.rb +2 -0
  70. metadata +18 -538
  71. data/.codeclimate.yml +0 -17
  72. data/.github/FUNDING.yml +0 -3
  73. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  74. data/.github/ISSUE_TEMPLATE/custom.md +0 -10
  75. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  76. data/.gitignore +0 -19
  77. data/.hound.yml +0 -3
  78. data/.rubocop.yml +0 -1061
  79. data/.travis.yml +0 -45
  80. data/Appraisals +0 -30
  81. data/CONTRIBUTING.md +0 -85
  82. data/Gemfile +0 -19
  83. data/OLD_NEWS +0 -556
  84. data/RELEASING.md +0 -17
  85. data/Rakefile +0 -52
  86. data/UPGRADING +0 -17
  87. data/features/basic_integration.feature +0 -85
  88. data/features/migration.feature +0 -29
  89. data/features/rake_tasks.feature +0 -62
  90. data/features/step_definitions/attachment_steps.rb +0 -120
  91. data/features/step_definitions/html_steps.rb +0 -15
  92. data/features/step_definitions/rails_steps.rb +0 -257
  93. data/features/step_definitions/s3_steps.rb +0 -14
  94. data/features/step_definitions/web_steps.rb +0 -106
  95. data/features/support/env.rb +0 -12
  96. data/features/support/fakeweb.rb +0 -11
  97. data/features/support/file_helpers.rb +0 -34
  98. data/features/support/fixtures/boot_config.txt +0 -15
  99. data/features/support/fixtures/gemfile.txt +0 -5
  100. data/features/support/fixtures/preinitializer.txt +0 -20
  101. data/features/support/paths.rb +0 -28
  102. data/features/support/rails.rb +0 -39
  103. data/features/support/selectors.rb +0 -19
  104. data/gemfiles/4.2.gemfile +0 -20
  105. data/gemfiles/5.0.gemfile +0 -20
  106. data/gemfiles/5.1.gemfile +0 -20
  107. data/gemfiles/5.2.gemfile +0 -20
  108. data/gemfiles/6.0.gemfile +0 -20
  109. data/gemfiles/6.1.gemfile +0 -21
  110. data/gemfiles/7.0.gemfile +0 -21
  111. data/paperclip.gemspec +0 -50
  112. data/spec/database.yml +0 -4
  113. data/spec/paperclip/attachment_definitions_spec.rb +0 -13
  114. data/spec/paperclip/attachment_processing_spec.rb +0 -79
  115. data/spec/paperclip/attachment_registry_spec.rb +0 -158
  116. data/spec/paperclip/attachment_spec.rb +0 -1616
  117. data/spec/paperclip/content_type_detector_spec.rb +0 -54
  118. data/spec/paperclip/file_command_content_type_detector_spec.rb +0 -40
  119. data/spec/paperclip/filename_cleaner_spec.rb +0 -13
  120. data/spec/paperclip/geometry_detector_spec.rb +0 -47
  121. data/spec/paperclip/geometry_parser_spec.rb +0 -73
  122. data/spec/paperclip/geometry_spec.rb +0 -267
  123. data/spec/paperclip/glue_spec.rb +0 -63
  124. data/spec/paperclip/has_attached_file_spec.rb +0 -78
  125. data/spec/paperclip/integration_spec.rb +0 -702
  126. data/spec/paperclip/interpolations_spec.rb +0 -270
  127. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +0 -160
  128. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +0 -167
  129. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +0 -88
  130. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +0 -17
  131. data/spec/paperclip/io_adapters/file_adapter_spec.rb +0 -131
  132. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +0 -142
  133. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +0 -8
  134. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +0 -25
  135. data/spec/paperclip/io_adapters/registry_spec.rb +0 -35
  136. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +0 -64
  137. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +0 -146
  138. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +0 -231
  139. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +0 -19
  140. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +0 -108
  141. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +0 -69
  142. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +0 -88
  143. data/spec/paperclip/media_type_spoof_detector_spec.rb +0 -126
  144. data/spec/paperclip/meta_class_spec.rb +0 -30
  145. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +0 -88
  146. data/spec/paperclip/paperclip_spec.rb +0 -196
  147. data/spec/paperclip/plural_cache_spec.rb +0 -37
  148. data/spec/paperclip/processor_helpers_spec.rb +0 -57
  149. data/spec/paperclip/processor_spec.rb +0 -26
  150. data/spec/paperclip/rails_environment_spec.rb +0 -30
  151. data/spec/paperclip/rake_spec.rb +0 -103
  152. data/spec/paperclip/schema_spec.rb +0 -252
  153. data/spec/paperclip/storage/filesystem_spec.rb +0 -102
  154. data/spec/paperclip/storage/fog_spec.rb +0 -606
  155. data/spec/paperclip/storage/s3_live_spec.rb +0 -188
  156. data/spec/paperclip/storage/s3_spec.rb +0 -1961
  157. data/spec/paperclip/style_spec.rb +0 -251
  158. data/spec/paperclip/tempfile_factory_spec.rb +0 -33
  159. data/spec/paperclip/tempfile_spec.rb +0 -35
  160. data/spec/paperclip/thumbnail_spec.rb +0 -504
  161. data/spec/paperclip/url_generator_spec.rb +0 -231
  162. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +0 -410
  163. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +0 -249
  164. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +0 -85
  165. data/spec/paperclip/validators/attachment_size_validator_spec.rb +0 -325
  166. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +0 -48
  167. data/spec/paperclip/validators_spec.rb +0 -179
  168. data/spec/spec_helper.rb +0 -46
  169. data/spec/support/assertions.rb +0 -84
  170. data/spec/support/fake_model.rb +0 -24
  171. data/spec/support/fake_rails.rb +0 -12
  172. data/spec/support/fixtures/12k.png +0 -0
  173. data/spec/support/fixtures/50x50.png +0 -0
  174. data/spec/support/fixtures/5k.png +0 -0
  175. data/spec/support/fixtures/animated +0 -0
  176. data/spec/support/fixtures/animated.gif +0 -0
  177. data/spec/support/fixtures/animated.unknown +0 -0
  178. data/spec/support/fixtures/aws_s3.yml +0 -13
  179. data/spec/support/fixtures/bad.png +0 -1
  180. data/spec/support/fixtures/empty.html +0 -1
  181. data/spec/support/fixtures/empty.xlsx +0 -0
  182. data/spec/support/fixtures/fog.yml +0 -8
  183. data/spec/support/fixtures/rotated.jpg +0 -0
  184. data/spec/support/fixtures/s3.yml +0 -8
  185. data/spec/support/fixtures/sample.xlsm +0 -0
  186. data/spec/support/fixtures/spaced file.jpg +0 -0
  187. data/spec/support/fixtures/spaced file.png +0 -0
  188. data/spec/support/fixtures/text.txt +0 -1
  189. data/spec/support/fixtures/twopage.pdf +0 -0
  190. data/spec/support/fixtures/uppercase.PNG +0 -0
  191. data/spec/support/matchers/accept.rb +0 -5
  192. data/spec/support/matchers/exist.rb +0 -5
  193. data/spec/support/matchers/have_column.rb +0 -23
  194. data/spec/support/mock_attachment.rb +0 -24
  195. data/spec/support/mock_interpolator.rb +0 -24
  196. data/spec/support/mock_url_generator_builder.rb +0 -26
  197. data/spec/support/model_reconstruction.rb +0 -72
  198. data/spec/support/reporting.rb +0 -11
  199. data/spec/support/test_data.rb +0 -13
  200. data/spec/support/version_helper.rb +0 -9
@@ -1,45 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
4
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::ImageMagick::GeometryParser+ instead.
2
5
  class GeometryDetector
6
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::ImageMagick::GeometryParser+ instead.
3
7
  def initialize(file)
8
+ warn_deprecation
4
9
  @file = file
5
- raise_if_blank_file
10
+ raise Errors::NotIdentifiedByImageMagickError.new("Cannot find the geometry of a file with a blank name") if @file.blank?
6
11
  end
7
12
 
13
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::ImageMagick::GeometryParser+ instead.
8
14
  def make
9
- geometry = GeometryParser.new(geometry_string.strip).make
10
- geometry || raise(Errors::NotIdentifiedByImageMagickError.new("Could not identify image size"))
15
+ warn_deprecation
16
+ Paperclip::Commands::ImageMagick::GeometryParser.from_file(@file)
11
17
  end
12
18
 
13
19
  private
14
20
 
15
- def geometry_string
16
- orientation = Paperclip.options[:use_exif_orientation] ?
17
- "%[exif:orientation]" : "1"
18
- Paperclip.run(
19
- Paperclip.options[:is_windows] ? "magick identify" : "identify",
20
- "-format '%wx%h,#{orientation}' :file", {
21
- file: "#{path}[0]"
22
- },
23
- swallow_stderr: true
24
- )
25
- rescue Terrapin::ExitStatusError
26
- ""
27
- rescue Terrapin::CommandNotFoundError => e
28
- raise_because_imagemagick_missing
29
- end
30
-
31
- def path
32
- @file.respond_to?(:path) ? @file.path : @file
33
- end
34
-
35
- def raise_if_blank_file
36
- if path.blank?
37
- raise Errors::NotIdentifiedByImageMagickError.new("Cannot find the geometry of a file with a blank name")
38
- end
39
- end
40
-
41
- def raise_because_imagemagick_missing
42
- raise Errors::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
21
+ def warn_deprecation
22
+ Paperclip.deprecator.warn("Paperclip::GeometryDetector has been replaced by Paperclip::Commands::ImageMagick::GeometryParser")
43
23
  end
44
24
  end
45
25
  end
@@ -1,31 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
4
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::ImageMagick::GeometryParser+ instead.
2
5
  class GeometryParser
3
- FORMAT = /\b(\d*)x?(\d*)\b(?:,(\d?))?(\@\>|\>\@|[\>\<\#\@\%^!])?/i.freeze
6
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::ImageMagick::GeometryParser::FORMAT+ instead.
7
+ FORMAT = Paperclip::Commands::ImageMagick::GeometryParser::FORMAT
8
+
9
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::ImageMagick::GeometryParser+ instead.
4
10
  def initialize(string)
11
+ warn_deprecation
5
12
  @string = string
6
13
  end
7
14
 
15
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::ImageMagick::GeometryParser+ instead.
8
16
  def make
9
- if match
10
- Geometry.new(
11
- height: @height,
12
- width: @width,
13
- modifier: @modifier,
14
- orientation: @orientation
15
- )
16
- end
17
+ warn_deprecation
18
+ Paperclip::Commands::ImageMagick::GeometryParser.parse(@string)
17
19
  end
18
20
 
19
21
  private
20
22
 
21
- def match
22
- if actual_match = @string && @string.match(FORMAT)
23
- @width = actual_match[1]
24
- @height = actual_match[2]
25
- @orientation = actual_match[3]
26
- @modifier = actual_match[4]
27
- end
28
- actual_match
23
+ def warn_deprecation
24
+ Paperclip.deprecator.warn("Paperclip::GeometryParser has been replaced by Paperclip::Commands::ImageMagick::GeometryParser")
29
25
  end
30
26
  end
31
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "paperclip/callbacks"
2
4
  require "paperclip/validators"
3
5
  require "paperclip/schema"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class HasAttachedFile
3
5
  def self.define_on(klass, name, options)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Helpers
3
5
  def configure
@@ -8,31 +10,9 @@ module Paperclip
8
10
  Paperclip::Interpolations[key] = block
9
11
  end
10
12
 
11
- # The run method takes the name of a binary to run, the arguments
12
- # to that binary, the values to interpolate and some local options.
13
- #
14
- # :cmd -> The name of a binary to run.
15
- #
16
- # :arguments -> The command line arguments to that binary.
17
- #
18
- # :interpolation_values -> Values to be interpolated into the arguments.
19
- #
20
- # :local_options -> The options to be used by Cocain::CommandLine.
21
- # These could be: runner
22
- # logger
23
- # swallow_stderr
24
- # expected_outcodes
25
- # environment
26
- # runner_options
27
- #
28
- def run(cmd, arguments = "", interpolation_values = {}, local_options = {})
29
- command_path = options[:command_path]
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
- if logging? && (options[:log_command] || local_options[:log_command])
33
- local_options = local_options.merge(logger: logger)
34
- end
35
- Terrapin::CommandLine.new(cmd, arguments, local_options).run(interpolation_values)
13
+ # @deprecated Will be removed in Paperclip 8.0. Use +Paperclip::Commands::Runner.run+ instead.
14
+ def run(command, arguments = nil, interpolation_values = {}, local_options = {})
15
+ Commands::Runner.run(command, nil, arguments, interpolation_values, local_options)
36
16
  end
37
17
 
38
18
  # Find all instances of the given Active Record model +klass+ with attachment +name+.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Interpolations
3
5
  class PluralCache
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  # This module contains all the methods that are available for interpolation
3
5
  # in paths and urls. To add your own (or override an existing one), you
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/delegation"
2
4
 
3
5
  module Paperclip
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class AttachmentAdapter < AbstractAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class DataUriAdapter < StringioAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class EmptyStringAdapter < AbstractAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class FileAdapter < AbstractAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class HttpUrlProxyAdapter < UriAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class IdentityAdapter < AbstractAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class NilAdapter < AbstractAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class AdapterRegistry
3
5
  class NoHandlerError < Paperclip::Error; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class StringioAdapter < AbstractAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class UploadedFileAdapter < AbstractAdapter
3
5
  def self.register
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "open-uri"
2
4
 
3
5
  module Paperclip
@@ -50,20 +52,10 @@ module Paperclip
50
52
  "index.html"
51
53
  end
52
54
 
53
- if RUBY_VERSION < '2.5'
54
- def download_content
55
- options = { read_timeout: Paperclip.options[:read_timeout] }.compact
56
-
57
- # rubocop:disable Security/Open
58
- open(@target, options)
59
- # rubocop:enable Security/Open
60
- end
61
- else
62
- def download_content
63
- options = { read_timeout: Paperclip.options[:read_timeout] }.compact
55
+ def download_content
56
+ options = { read_timeout: Paperclip.options[:read_timeout] }.compact
64
57
 
65
- URI.open(@target, options)
66
- end
58
+ URI.open(@target, options)
67
59
  end
68
60
 
69
61
  def copy_to_tempfile(src)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Logger
3
5
  # Log a paperclip-specific line. This will log to STDOUT
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Shoulda
3
5
  module Matchers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Shoulda
3
5
  module Matchers
@@ -39,7 +41,7 @@ module Paperclip
39
41
  end
40
42
 
41
43
  def failure_message
42
- "#{expected_attachment}\n".tap do |message|
44
+ (+"#{expected_attachment}\n").tap do |message|
43
45
  message << accepted_types_and_failures.to_s
44
46
  message << "\n\n" if @allowed_types.present? && @rejected_types.present?
45
47
  message << rejected_types_and_failures.to_s
@@ -54,7 +56,7 @@ module Paperclip
54
56
 
55
57
  def accepted_types_and_failures
56
58
  if @allowed_types.present?
57
- "Accept content types: #{@allowed_types.join(', ')}\n".tap do |message|
59
+ (+"Accept content types: #{@allowed_types.join(', ')}\n").tap do |message|
58
60
  message << if @missing_allowed_types.present?
59
61
  " #{@missing_allowed_types.join(', ')} were rejected."
60
62
  else
@@ -66,7 +68,7 @@ module Paperclip
66
68
 
67
69
  def rejected_types_and_failures
68
70
  if @rejected_types.present?
69
- "Reject content types: #{@rejected_types.join(', ')}\n".tap do |message|
71
+ (+"Reject content types: #{@rejected_types.join(', ')}\n").tap do |message|
70
72
  message << if @missing_rejected_types.present?
71
73
  " #{@missing_rejected_types.join(', ')} were accepted."
72
74
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Shoulda
3
5
  module Matchers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Shoulda
3
5
  module Matchers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "paperclip/matchers/have_attached_file_matcher"
2
4
  require "paperclip/matchers/validate_attachment_presence_matcher"
3
5
  require "paperclip/matchers/validate_attachment_content_type_matcher"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class MediaTypeSpoofDetector
3
5
  def self.using(file, name, content_type)
@@ -40,12 +42,27 @@ module Paperclip
40
42
  end
41
43
 
42
44
  def calculated_type_mismatch?
43
- supplied_media_type.present? &&
44
- !calculated_content_type.include?(supplied_media_type)
45
+ return false if supplied_media_type.blank?
46
+ # Fast path: the magic number already supports the supplied type, no shell out needed.
47
+ return false if supplied_type_consistent_with?(type_from_magic)
48
+ # The bytes told us nothing at all, so there is nothing to contradict the supplied type.
49
+ return false if calculated_content_types.empty?
50
+
51
+ !supplied_type_consistent_with?(type_from_file_command)
52
+ end
53
+
54
+ # The supplied type is supported by the bytes if it shares their media type, or if it is a
55
+ # specialization of what the bytes resolved to: image/svg+xml is a child of application/xml,
56
+ # which is all the magic number of an SVG with an XML declaration can tell us.
57
+ def supplied_type_consistent_with?(type)
58
+ return false if type.blank?
59
+
60
+ type.include?(supplied_media_type) ||
61
+ !!Marcel::Magic.child?(supplied_content_type, type)
45
62
  end
46
63
 
47
64
  def mapping_override_mismatch?
48
- !Array(mapped_content_type).include?(calculated_content_type)
65
+ (Array(mapped_content_type) & calculated_content_types).empty?
49
66
  end
50
67
 
51
68
  def supplied_content_type
@@ -64,21 +81,35 @@ module Paperclip
64
81
  @media_types_from_name ||= content_types_from_name.collect(&:media_type)
65
82
  end
66
83
 
84
+ # Every type the file's *contents* resolve to. The filename is deliberately never consulted
85
+ # here -- trusting it is what let a renamed file pass this check (kreeti/kt-paperclip#173).
86
+ def calculated_content_types
87
+ @calculated_content_types ||=
88
+ # Both sources return nil, never a blank string, when they come up empty.
89
+ [type_from_magic, type_from_file_command].compact.uniq
90
+ end
91
+
67
92
  def calculated_content_type
68
- @calculated_content_type ||= type_from_file_command.chomp
93
+ @calculated_content_type ||= calculated_content_types.first.to_s
69
94
  end
70
95
 
71
- def calculated_media_type
72
- @calculated_media_type ||= calculated_content_type.split("/").first
96
+ # Note the absence of a `name:` argument. Marcel lets the filename decide when the bytes carry
97
+ # no magic number of their own, which is exactly what spoof detection must not allow.
98
+ def type_from_magic
99
+ return @type_from_magic if defined?(@type_from_magic)
100
+
101
+ type = Marcel::MimeType.for(Pathname.new(@file.path))
102
+ # Marcel::MimeType returns 'application/octet-stream' if it can't find a valid type.
103
+ @type_from_magic = type == ContentTypeDetector::SENSIBLE_DEFAULT ? nil : type
104
+ rescue Errno::ENOENT => e
105
+ Paperclip.log("Error while determining content type: #{e}")
106
+ @type_from_magic = nil
73
107
  end
74
108
 
75
109
  def type_from_file_command
76
- Paperclip.run("file", "-b --mime :file", file: @file.path).
77
- split(/[:;\s]+/).first
78
- rescue Terrapin::CommandLineError
79
- Paperclip.log("Problem getting type from `file` command. Possible that `file` doesn't exist on this system. Content Type validations don't work without this.")
110
+ return @type_from_file_command if defined?(@type_from_file_command)
80
111
 
81
- ""
112
+ @type_from_file_command = Commands::UnixFile.detect_content_type(@file.path)
82
113
  end
83
114
 
84
115
  def mapped_content_type
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "paperclip/attachment_registry"
2
4
  require "set"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  # Paperclip processors allow you to modify attached files when they are
3
5
  # attached in any way you are able. Paperclip itself uses command-line
@@ -15,9 +17,6 @@ module Paperclip
15
17
  #
16
18
  # #make must return an instance of File (Tempfile is acceptable) which
17
19
  # contains the results of the processing.
18
- #
19
- # See Paperclip.run for more information about using command-line
20
- # utilities from within Processors.
21
20
  class Processor
22
21
  attr_accessor :file, :options, :attachment
23
22
 
@@ -33,24 +32,12 @@ module Paperclip
33
32
  new(file, options, attachment).make
34
33
  end
35
34
 
36
- # The convert method runs the convert binary with the provided arguments.
37
- # See Paperclip.run for the available options.
38
- def convert(arguments = "", local_options = {})
39
- Paperclip.run(
40
- Paperclip.options[:is_windows] ? "magick convert" : "convert",
41
- arguments,
42
- local_options
43
- )
35
+ def convert(arguments = nil, interpolation_values = {})
36
+ Paperclip::Commands::ImageMagick.convert(arguments, interpolation_values)
44
37
  end
45
38
 
46
- # The identify method runs the identify binary with the provided arguments.
47
- # See Paperclip.run for the available options.
48
- def identify(arguments = "", local_options = {})
49
- Paperclip.run(
50
- Paperclip.options[:is_windows] ? "magick identify" : "identify",
51
- arguments,
52
- local_options
53
- )
39
+ def identify(arguments = nil, interpolation_values = {})
40
+ Paperclip::Commands::ImageMagick.identify(arguments, interpolation_values)
54
41
  end
55
42
  end
56
43
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module ProcessorHelpers
3
5
  class NoSuchProcessor < StandardError; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class RailsEnvironment
3
5
  def self.get
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "paperclip"
2
4
  require "paperclip/schema"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/deprecation"
2
4
 
3
5
  module Paperclip
@@ -25,7 +27,7 @@ module Paperclip
25
27
 
26
28
  attachment_names.each do |attachment_name|
27
29
  COLUMNS.each_pair do |column_name, column_type|
28
- column_options = options.merge(options[column_name.to_sym] || {})
30
+ column_options = options.merge(options[column_name.to_sym] || {}).except(*COLUMNS.keys)
29
31
  add_column(table_name, "#{attachment_name}_#{column_name}", column_type, **column_options)
30
32
  end
31
33
  end
@@ -44,7 +46,7 @@ module Paperclip
44
46
  end
45
47
 
46
48
  def drop_attached_file(*args)
47
- ActiveSupport::Deprecation.warn "Method `drop_attached_file` in the migration has been deprecated and will be replaced by `remove_attachment`."
49
+ Paperclip.deprecator.warn "Method `drop_attached_file` in the migration has been deprecated and will be replaced by `remove_attachment`."
48
50
  remove_attachment(*args)
49
51
  end
50
52
  end
@@ -54,14 +56,14 @@ module Paperclip
54
56
  options = attachment_names.extract_options!
55
57
  attachment_names.each do |attachment_name|
56
58
  COLUMNS.each_pair do |column_name, column_type|
57
- column_options = options.merge(options[column_name.to_sym] || {})
59
+ column_options = options.merge(options[column_name.to_sym] || {}).except(*COLUMNS.keys)
58
60
  column("#{attachment_name}_#{column_name}", column_type, **column_options)
59
61
  end
60
62
  end
61
63
  end
62
64
 
63
65
  def has_attached_file(*attachment_names)
64
- ActiveSupport::Deprecation.warn "Method `t.has_attached_file` in the migration has been deprecated and will be replaced by `t.attachment`."
66
+ Paperclip.deprecator.warn "Method `t.has_attached_file` in the migration has been deprecated and will be replaced by `t.attachment`."
65
67
  attachment(*attachment_names)
66
68
  end
67
69
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Storage
3
5
  # The default place to store attachments is in the filesystem. Files on the local
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  module Storage
3
5
  # fog is a modern and versatile cloud computing library for Ruby.
@@ -44,8 +46,7 @@ module Paperclip
44
46
  begin
45
47
  require "fog"
46
48
  rescue LoadError => e
47
- e.message << " (You may need to install the fog gem)"
48
- raise e
49
+ raise("#{e.message} (You may need to install the fog gem)")
49
50
  end
50
51
  end
51
52
 
@@ -216,7 +217,7 @@ module Paperclip
216
217
  when File
217
218
  load_credentials_from_file(creds.path)
218
219
  when String, Pathname
219
- load_credentials_from_file(creds.path)
220
+ load_credentials_from_file(creds)
220
221
  when Hash
221
222
  creds
222
223
  else
@@ -1,4 +1,5 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module Paperclip
3
4
  module Storage
4
5
  # Amazon's S3 file hosting service is a scalable, easy place to store files for
@@ -126,8 +127,7 @@ module Paperclip
126
127
  begin
127
128
  require "aws-sdk-s3"
128
129
  rescue LoadError => e
129
- e.message << " (You may need to install the aws-sdk-s3 gem)"
130
- raise e
130
+ raise("#{e.message} (You may need to install the aws-sdk-s3 gem)")
131
131
  end
132
132
 
133
133
  base.instance_eval do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "paperclip/storage/filesystem"
2
4
  require "paperclip/storage/fog"
3
5
  require "paperclip/storage/s3"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  # The Style class holds the definition of a thumbnail style, applying
3
5
  # whatever processing is required to normalize the definition and delaying
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  # Overriding some implementation of Tempfile
3
5
  class Tempfile < ::Tempfile
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Paperclip
2
4
  class TempfileFactory
3
5
  def generate(name = random_name)