kt-paperclip 6.2.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.
Files changed (191) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +3 -0
  4. data/.gitignore +19 -0
  5. data/.hound.yml +1050 -0
  6. data/.rubocop.yml +1 -0
  7. data/.travis.yml +47 -0
  8. data/Appraisals +24 -0
  9. data/CONTRIBUTING.md +86 -0
  10. data/Gemfile +18 -0
  11. data/LICENSE +24 -0
  12. data/NEWS +515 -0
  13. data/README.md +1053 -0
  14. data/RELEASING.md +17 -0
  15. data/Rakefile +52 -0
  16. data/UPGRADING +17 -0
  17. data/features/basic_integration.feature +85 -0
  18. data/features/migration.feature +29 -0
  19. data/features/rake_tasks.feature +62 -0
  20. data/features/step_definitions/attachment_steps.rb +110 -0
  21. data/features/step_definitions/html_steps.rb +15 -0
  22. data/features/step_definitions/rails_steps.rb +257 -0
  23. data/features/step_definitions/s3_steps.rb +14 -0
  24. data/features/step_definitions/web_steps.rb +106 -0
  25. data/features/support/env.rb +12 -0
  26. data/features/support/fakeweb.rb +11 -0
  27. data/features/support/file_helpers.rb +34 -0
  28. data/features/support/fixtures/boot_config.txt +15 -0
  29. data/features/support/fixtures/gemfile.txt +5 -0
  30. data/features/support/fixtures/preinitializer.txt +20 -0
  31. data/features/support/paths.rb +28 -0
  32. data/features/support/rails.rb +39 -0
  33. data/features/support/selectors.rb +19 -0
  34. data/gemfiles/4.2.gemfile +20 -0
  35. data/gemfiles/5.0.gemfile +20 -0
  36. data/gemfiles/5.1.gemfile +20 -0
  37. data/gemfiles/5.2.gemfile +20 -0
  38. data/gemfiles/6.0.gemfile +20 -0
  39. data/lib/generators/paperclip/USAGE +8 -0
  40. data/lib/generators/paperclip/paperclip_generator.rb +36 -0
  41. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
  42. data/lib/paperclip.rb +215 -0
  43. data/lib/paperclip/attachment.rb +617 -0
  44. data/lib/paperclip/attachment_registry.rb +60 -0
  45. data/lib/paperclip/callbacks.rb +42 -0
  46. data/lib/paperclip/content_type_detector.rb +80 -0
  47. data/lib/paperclip/errors.rb +34 -0
  48. data/lib/paperclip/file_command_content_type_detector.rb +28 -0
  49. data/lib/paperclip/filename_cleaner.rb +15 -0
  50. data/lib/paperclip/geometry.rb +157 -0
  51. data/lib/paperclip/geometry_detector_factory.rb +45 -0
  52. data/lib/paperclip/geometry_parser_factory.rb +31 -0
  53. data/lib/paperclip/glue.rb +17 -0
  54. data/lib/paperclip/has_attached_file.rb +116 -0
  55. data/lib/paperclip/helpers.rb +60 -0
  56. data/lib/paperclip/interpolations.rb +201 -0
  57. data/lib/paperclip/interpolations/plural_cache.rb +18 -0
  58. data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
  59. data/lib/paperclip/io_adapters/attachment_adapter.rb +47 -0
  60. data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
  61. data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
  62. data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
  63. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
  64. data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
  65. data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
  66. data/lib/paperclip/io_adapters/registry.rb +36 -0
  67. data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
  68. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
  69. data/lib/paperclip/io_adapters/uri_adapter.rb +68 -0
  70. data/lib/paperclip/locales/en.yml +18 -0
  71. data/lib/paperclip/logger.rb +21 -0
  72. data/lib/paperclip/matchers.rb +64 -0
  73. data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
  74. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
  75. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
  76. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
  77. data/lib/paperclip/media_type_spoof_detector.rb +90 -0
  78. data/lib/paperclip/missing_attachment_styles.rb +84 -0
  79. data/lib/paperclip/processor.rb +56 -0
  80. data/lib/paperclip/processor_helpers.rb +52 -0
  81. data/lib/paperclip/rails_environment.rb +21 -0
  82. data/lib/paperclip/railtie.rb +31 -0
  83. data/lib/paperclip/schema.rb +81 -0
  84. data/lib/paperclip/storage.rb +3 -0
  85. data/lib/paperclip/storage/filesystem.rb +99 -0
  86. data/lib/paperclip/storage/fog.rb +252 -0
  87. data/lib/paperclip/storage/s3.rb +461 -0
  88. data/lib/paperclip/style.rb +106 -0
  89. data/lib/paperclip/tempfile.rb +42 -0
  90. data/lib/paperclip/tempfile_factory.rb +22 -0
  91. data/lib/paperclip/thumbnail.rb +131 -0
  92. data/lib/paperclip/url_generator.rb +76 -0
  93. data/lib/paperclip/validators.rb +73 -0
  94. data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
  95. data/lib/paperclip/validators/attachment_file_name_validator.rb +75 -0
  96. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
  97. data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
  98. data/lib/paperclip/validators/attachment_size_validator.rb +109 -0
  99. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
  100. data/lib/paperclip/version.rb +3 -0
  101. data/lib/tasks/paperclip.rake +140 -0
  102. data/paperclip.gemspec +50 -0
  103. data/shoulda_macros/paperclip.rb +134 -0
  104. data/spec/database.yml +4 -0
  105. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  106. data/spec/paperclip/attachment_processing_spec.rb +79 -0
  107. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  108. data/spec/paperclip/attachment_spec.rb +1590 -0
  109. data/spec/paperclip/content_type_detector_spec.rb +47 -0
  110. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  111. data/spec/paperclip/filename_cleaner_spec.rb +13 -0
  112. data/spec/paperclip/geometry_detector_spec.rb +38 -0
  113. data/spec/paperclip/geometry_parser_spec.rb +73 -0
  114. data/spec/paperclip/geometry_spec.rb +255 -0
  115. data/spec/paperclip/glue_spec.rb +42 -0
  116. data/spec/paperclip/has_attached_file_spec.rb +78 -0
  117. data/spec/paperclip/integration_spec.rb +702 -0
  118. data/spec/paperclip/interpolations_spec.rb +270 -0
  119. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
  120. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +140 -0
  121. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
  122. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  123. data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
  124. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +137 -0
  125. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  126. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
  127. data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
  128. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
  129. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
  130. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +221 -0
  131. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  132. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
  133. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  134. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  135. data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
  136. data/spec/paperclip/meta_class_spec.rb +30 -0
  137. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
  138. data/spec/paperclip/paperclip_spec.rb +196 -0
  139. data/spec/paperclip/plural_cache_spec.rb +37 -0
  140. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  141. data/spec/paperclip/processor_spec.rb +26 -0
  142. data/spec/paperclip/rails_environment_spec.rb +30 -0
  143. data/spec/paperclip/rake_spec.rb +103 -0
  144. data/spec/paperclip/schema_spec.rb +252 -0
  145. data/spec/paperclip/storage/filesystem_spec.rb +79 -0
  146. data/spec/paperclip/storage/fog_spec.rb +560 -0
  147. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  148. data/spec/paperclip/storage/s3_spec.rb +1695 -0
  149. data/spec/paperclip/style_spec.rb +251 -0
  150. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  151. data/spec/paperclip/tempfile_spec.rb +35 -0
  152. data/spec/paperclip/thumbnail_spec.rb +504 -0
  153. data/spec/paperclip/url_generator_spec.rb +221 -0
  154. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  155. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +159 -0
  156. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
  157. data/spec/paperclip/validators/attachment_size_validator_spec.rb +235 -0
  158. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
  159. data/spec/paperclip/validators_spec.rb +164 -0
  160. data/spec/spec_helper.rb +45 -0
  161. data/spec/support/assertions.rb +84 -0
  162. data/spec/support/fake_model.rb +24 -0
  163. data/spec/support/fake_rails.rb +12 -0
  164. data/spec/support/fixtures/12k.png +0 -0
  165. data/spec/support/fixtures/50x50.png +0 -0
  166. data/spec/support/fixtures/5k.png +0 -0
  167. data/spec/support/fixtures/animated +0 -0
  168. data/spec/support/fixtures/animated.gif +0 -0
  169. data/spec/support/fixtures/animated.unknown +0 -0
  170. data/spec/support/fixtures/bad.png +1 -0
  171. data/spec/support/fixtures/empty.html +1 -0
  172. data/spec/support/fixtures/empty.xlsx +0 -0
  173. data/spec/support/fixtures/fog.yml +8 -0
  174. data/spec/support/fixtures/rotated.jpg +0 -0
  175. data/spec/support/fixtures/s3.yml +8 -0
  176. data/spec/support/fixtures/spaced file.jpg +0 -0
  177. data/spec/support/fixtures/spaced file.png +0 -0
  178. data/spec/support/fixtures/text.txt +1 -0
  179. data/spec/support/fixtures/twopage.pdf +0 -0
  180. data/spec/support/fixtures/uppercase.PNG +0 -0
  181. data/spec/support/matchers/accept.rb +5 -0
  182. data/spec/support/matchers/exist.rb +5 -0
  183. data/spec/support/matchers/have_column.rb +23 -0
  184. data/spec/support/mock_attachment.rb +24 -0
  185. data/spec/support/mock_interpolator.rb +24 -0
  186. data/spec/support/mock_url_generator_builder.rb +26 -0
  187. data/spec/support/model_reconstruction.rb +72 -0
  188. data/spec/support/reporting.rb +11 -0
  189. data/spec/support/test_data.rb +13 -0
  190. data/spec/support/version_helper.rb +9 -0
  191. metadata +586 -0
@@ -0,0 +1,108 @@
1
+ require "spec_helper"
2
+ require "paperclip/matchers"
3
+
4
+ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
5
+ extend Paperclip::Shoulda::Matchers
6
+
7
+ before do
8
+ reset_table("dummies") do |d|
9
+ d.string :title
10
+ d.string :avatar_file_name
11
+ d.string :avatar_content_type
12
+ end
13
+ reset_class "Dummy"
14
+ Dummy.do_not_validate_attachment_file_type :avatar
15
+ Dummy.has_attached_file :avatar
16
+ end
17
+
18
+ it "rejects a class with no validation" do
19
+ expect(matcher).to_not accept(Dummy)
20
+ expect { matcher.failure_message }.to_not raise_error
21
+ end
22
+
23
+ it "rejects a class when the validation fails" do
24
+ Dummy.validates_attachment_content_type :avatar, content_type: %r{audio/.*}
25
+ expect(matcher).to_not accept(Dummy)
26
+ expect { matcher.failure_message }.to_not raise_error
27
+ end
28
+
29
+ it "accepts a class with a matching validation" do
30
+ Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
31
+ expect(matcher).to accept(Dummy)
32
+ expect { matcher.failure_message }.to_not raise_error
33
+ end
34
+
35
+ it "accepts a class with other validations but matching types" do
36
+ Dummy.validates_presence_of :title
37
+ Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
38
+ expect(matcher).to accept(Dummy)
39
+ expect { matcher.failure_message }.to_not raise_error
40
+ end
41
+
42
+ it "accepts a class that matches and a matcher that only specifies 'allowing'" do
43
+ Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
44
+ matcher = plain_matcher.allowing(%w(image/png image/jpeg))
45
+
46
+ expect(matcher).to accept(Dummy)
47
+ expect { matcher.failure_message }.to_not raise_error
48
+ end
49
+
50
+ it "rejects a class that does not match and a matcher that only specifies 'allowing'" do
51
+ Dummy.validates_attachment_content_type :avatar, content_type: %r{audio/.*}
52
+ matcher = plain_matcher.allowing(%w(image/png image/jpeg))
53
+
54
+ expect(matcher).to_not accept(Dummy)
55
+ expect { matcher.failure_message }.to_not raise_error
56
+ end
57
+
58
+ it "accepts a class that matches and a matcher that only specifies 'rejecting'" do
59
+ Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
60
+ matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
61
+
62
+ expect(matcher).to accept(Dummy)
63
+ expect { matcher.failure_message }.to_not raise_error
64
+ end
65
+
66
+ it "rejects a class that does not match and a matcher that only specifies 'rejecting'" do
67
+ Dummy.validates_attachment_content_type :avatar, content_type: %r{audio/.*}
68
+ matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
69
+
70
+ expect(matcher).to_not accept(Dummy)
71
+ expect { matcher.failure_message }.to_not raise_error
72
+ end
73
+
74
+ context "using an :if to control the validation" do
75
+ before do
76
+ Dummy.class_eval do
77
+ validates_attachment_content_type :avatar, content_type: %r{image/*}, if: :go
78
+ attr_accessor :go
79
+ end
80
+ end
81
+
82
+ it "runs the validation if the control is true" do
83
+ dummy = Dummy.new
84
+ dummy.go = true
85
+ expect(matcher).to accept(dummy)
86
+ expect { matcher.failure_message }.to_not raise_error
87
+ end
88
+
89
+ it "does not run the validation if the control is false" do
90
+ dummy = Dummy.new
91
+ dummy.go = false
92
+ expect(matcher).to_not accept(dummy)
93
+ expect { matcher.failure_message }.to_not raise_error
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ def plain_matcher
100
+ self.class.validate_attachment_content_type(:avatar)
101
+ end
102
+
103
+ def matcher
104
+ plain_matcher.
105
+ allowing(%w(image/png image/jpeg)).
106
+ rejecting(%w(audio/mp3 application/octet-stream))
107
+ end
108
+ end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+ require "paperclip/matchers"
3
+
4
+ describe Paperclip::Shoulda::Matchers::ValidateAttachmentPresenceMatcher do
5
+ extend Paperclip::Shoulda::Matchers
6
+
7
+ before do
8
+ reset_table("dummies") do |d|
9
+ d.string :avatar_file_name
10
+ end
11
+ reset_class "Dummy"
12
+ Dummy.has_attached_file :avatar
13
+ Dummy.do_not_validate_attachment_file_type :avatar
14
+ end
15
+
16
+ it "rejects a class with no validation" do
17
+ expect(matcher).to_not accept(Dummy)
18
+ end
19
+
20
+ it "accepts a class with a matching validation" do
21
+ Dummy.validates_attachment_presence :avatar
22
+ expect(matcher).to accept(Dummy)
23
+ end
24
+
25
+ it "accepts an instance with other attachment validations" do
26
+ reset_table("dummies") do |d|
27
+ d.string :avatar_file_name
28
+ d.string :avatar_content_type
29
+ end
30
+ Dummy.class_eval do
31
+ validates_attachment_presence :avatar
32
+ validates_attachment_content_type :avatar, content_type: "image/gif"
33
+ end
34
+ dummy = Dummy.new
35
+
36
+ dummy.avatar = File.new fixture_file("5k.png")
37
+
38
+ expect(matcher).to accept(dummy)
39
+ end
40
+
41
+ context "using an :if to control the validation" do
42
+ before do
43
+ Dummy.class_eval do
44
+ validates_attachment_presence :avatar, if: :go
45
+ attr_accessor :go
46
+ end
47
+ end
48
+
49
+ it "runs the validation if the control is true" do
50
+ dummy = Dummy.new
51
+ dummy.avatar = nil
52
+ dummy.go = true
53
+ expect(matcher).to accept(dummy)
54
+ end
55
+
56
+ it "does not run the validation if the control is false" do
57
+ dummy = Dummy.new
58
+ dummy.avatar = nil
59
+ dummy.go = false
60
+ expect(matcher).to_not accept(dummy)
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def matcher
67
+ self.class.validate_attachment_presence(:avatar)
68
+ end
69
+ end
@@ -0,0 +1,88 @@
1
+ require "spec_helper"
2
+ require "paperclip/matchers"
3
+
4
+ describe Paperclip::Shoulda::Matchers::ValidateAttachmentSizeMatcher do
5
+ extend Paperclip::Shoulda::Matchers
6
+
7
+ before do
8
+ reset_table("dummies") do |d|
9
+ d.string :avatar_file_name
10
+ d.bigint :avatar_file_size
11
+ end
12
+ reset_class "Dummy"
13
+ Dummy.do_not_validate_attachment_file_type :avatar
14
+ Dummy.has_attached_file :avatar
15
+ end
16
+
17
+ context "Limiting size" do
18
+ it "rejects a class with no validation" do
19
+ expect(matcher.in(256..1024)).to_not accept(Dummy)
20
+ end
21
+
22
+ it "rejects a class with a validation that's too high" do
23
+ Dummy.validates_attachment_size :avatar, in: 256..2048
24
+ expect(matcher.in(256..1024)).to_not accept(Dummy)
25
+ end
26
+
27
+ it "accepts a class with a validation that's too low" do
28
+ Dummy.validates_attachment_size :avatar, in: 0..1024
29
+ expect(matcher.in(256..1024)).to_not accept(Dummy)
30
+ end
31
+
32
+ it "accepts a class with a validation that matches" do
33
+ Dummy.validates_attachment_size :avatar, in: 256..1024
34
+ expect(matcher.in(256..1024)).to accept(Dummy)
35
+ end
36
+ end
37
+
38
+ context "allowing anything" do
39
+ it "given a class with an upper limit" do
40
+ Dummy.validates_attachment_size :avatar, less_than: 1
41
+ expect(matcher).to accept(Dummy)
42
+ end
43
+
44
+ it "given a class with a lower limit" do
45
+ Dummy.validates_attachment_size :avatar, greater_than: 1
46
+ expect(matcher).to accept(Dummy)
47
+ end
48
+ end
49
+
50
+ context "using an :if to control the validation" do
51
+ before do
52
+ Dummy.class_eval do
53
+ validates_attachment_size :avatar, greater_than: 1024, if: :go
54
+ attr_accessor :go
55
+ end
56
+ end
57
+
58
+ it "run the validation if the control is true" do
59
+ dummy = Dummy.new
60
+ dummy.go = true
61
+ expect(matcher.greater_than(1024)).to accept(dummy)
62
+ end
63
+
64
+ it "not run the validation if the control is false" do
65
+ dummy = Dummy.new
66
+ dummy.go = false
67
+ expect(matcher.greater_than(1024)).to_not accept(dummy)
68
+ end
69
+ end
70
+
71
+ context "post processing" do
72
+ before do
73
+ Dummy.validates_attachment_size :avatar, greater_than: 1024
74
+ end
75
+
76
+ it "be skipped" do
77
+ dummy = Dummy.new
78
+ expect(dummy.avatar).to_not receive(:post_process)
79
+ expect(matcher.greater_than(1024)).to accept(dummy)
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def matcher
86
+ self.class.validate_attachment_size(:avatar)
87
+ end
88
+ end
@@ -0,0 +1,120 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::MediaTypeSpoofDetector do
4
+ it "rejects a file that is named .html and identifies as PNG" do
5
+ file = File.open(fixture_file("5k.png"))
6
+ assert Paperclip::MediaTypeSpoofDetector.using(file, "5k.html", "image/png").spoofed?
7
+ end
8
+
9
+ it "does not reject a file that is named .jpg and identifies as PNG" do
10
+ file = File.open(fixture_file("5k.png"))
11
+ assert !Paperclip::MediaTypeSpoofDetector.using(file, "5k.jpg", "image/png").spoofed?
12
+ end
13
+
14
+ it "does not reject a file that is named .html and identifies as HTML" do
15
+ file = File.open(fixture_file("empty.html"))
16
+ assert !Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "text/html").spoofed?
17
+ end
18
+
19
+ it "does not reject a file that does not have a name" do
20
+ file = File.open(fixture_file("empty.html"))
21
+ assert !Paperclip::MediaTypeSpoofDetector.using(file, "", "text/html").spoofed?
22
+ end
23
+
24
+ it "does not reject a file that does have an extension" do
25
+ file = File.open(fixture_file("empty.html"))
26
+ assert !Paperclip::MediaTypeSpoofDetector.using(file, "data", "text/html").spoofed?
27
+ end
28
+
29
+ it "does not reject when the supplied file is an IOAdapter" do
30
+ adapter = Paperclip.io_adapters.for(File.new(fixture_file("5k.png")))
31
+ assert !Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename, adapter.content_type).spoofed?
32
+ end
33
+
34
+ it "does not reject when the extension => content_type is in :content_type_mappings" do
35
+ begin
36
+ Paperclip.options[:content_type_mappings] = { pem: "text/plain" }
37
+ file = Tempfile.open(["test", ".PEM"])
38
+ file.puts "Certificate!"
39
+ file.close
40
+ adapter = Paperclip.io_adapters.for(File.new(file.path))
41
+ assert !Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename, adapter.content_type).spoofed?
42
+ ensure
43
+ Paperclip.options[:content_type_mappings] = {}
44
+ end
45
+ end
46
+
47
+ context "file named .html and is as HTML, but we're told JPG" do
48
+ let(:file) { File.open(fixture_file("empty.html")) }
49
+ let(:spoofed?) { Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "image/jpg").spoofed? }
50
+
51
+ it "rejects the file" do
52
+ assert spoofed?
53
+ end
54
+
55
+ it "logs info about the detected spoof" do
56
+ expect(Paperclip).to receive(:log).with('Content Type Spoof: Filename empty.html (image/jpg from Headers, ["text/html"] from Extension), content type discovered from file command: text/html. See documentation to allow this combination.')
57
+ spoofed?
58
+ end
59
+ end
60
+
61
+ context "GIF file named without extension, but we're told GIF" do
62
+ let(:file) { File.open(fixture_file("animated")) }
63
+ let(:spoofed?) do
64
+ Paperclip::MediaTypeSpoofDetector.
65
+ using(file, "animated", "image/gif").
66
+ spoofed?
67
+ end
68
+
69
+ it "accepts the file" do
70
+ assert !spoofed?
71
+ end
72
+ end
73
+
74
+ context "GIF file named without extension, but we're told HTML" do
75
+ let(:file) { File.open(fixture_file("animated")) }
76
+ let(:spoofed?) do
77
+ Paperclip::MediaTypeSpoofDetector.
78
+ using(file, "animated", "text/html").
79
+ spoofed?
80
+ end
81
+
82
+ it "rejects the file" do
83
+ assert spoofed?
84
+ end
85
+ end
86
+
87
+ it "does not reject if content_type is empty but otherwise checks out" do
88
+ file = File.open(fixture_file("empty.html"))
89
+ assert !Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "").spoofed?
90
+ end
91
+
92
+ it "does allow array as :content_type_mappings" do
93
+ begin
94
+ Paperclip.options[:content_type_mappings] = {
95
+ html: ["binary", "text/html"]
96
+ }
97
+ file = File.open(fixture_file("empty.html"))
98
+ spoofed = Paperclip::MediaTypeSpoofDetector.
99
+ using(file, "empty.html", "text/html").spoofed?
100
+ assert !spoofed
101
+ ensure
102
+ Paperclip.options[:content_type_mappings] = {}
103
+ end
104
+ end
105
+
106
+ context "#type_from_file_command" do
107
+ let(:file) { File.new(fixture_file("empty.html")) }
108
+ let(:detector) { Paperclip::MediaTypeSpoofDetector.new(file, "html", "") }
109
+
110
+ it "does work with the output of old versions of file" do
111
+ allow(Paperclip).to receive(:run).and_return("text/html charset=us-ascii")
112
+ expect(detector.send(:type_from_file_command)).to eq("text/html")
113
+ end
114
+
115
+ it "does work with the output of new versions of file" do
116
+ allow(Paperclip).to receive(:run).and_return("text/html; charset=us-ascii")
117
+ expect(detector.send(:type_from_file_command)).to eq("text/html")
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,30 @@
1
+ require "spec_helper"
2
+
3
+ describe "Metaclasses" do
4
+ context "A meta-class of dummy" do
5
+ if active_support_version >= "4.1" || ruby_version < "2.1"
6
+ before do
7
+ rebuild_model
8
+ reset_class("Dummy")
9
+ end
10
+
11
+ it "is able to use Paperclip like a normal class" do
12
+ @dummy = Dummy.new
13
+
14
+ assert_nothing_raised do
15
+ rebuild_meta_class_of(@dummy)
16
+ end
17
+ end
18
+
19
+ it "works like any other instance" do
20
+ @dummy = Dummy.new
21
+ rebuild_meta_class_of(@dummy)
22
+
23
+ assert_nothing_raised do
24
+ @dummy.avatar = File.new(fixture_file("5k.png"), "rb")
25
+ end
26
+ assert @dummy.save
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,88 @@
1
+ require "spec_helper"
2
+
3
+ describe "Missing Attachment Styles" do
4
+ before do
5
+ Paperclip::AttachmentRegistry.clear
6
+ end
7
+
8
+ after do
9
+ begin
10
+ File.unlink(Paperclip.registered_attachments_styles_path)
11
+ rescue StandardError
12
+ nil
13
+ end
14
+ end
15
+
16
+ it "enables to get and set path to registered styles file" do
17
+ assert_equal ROOT.join("tmp/public/system/paperclip_attachments.yml").to_s, Paperclip.registered_attachments_styles_path
18
+ Paperclip.registered_attachments_styles_path = "/tmp/config/paperclip_attachments.yml"
19
+ assert_equal "/tmp/config/paperclip_attachments.yml", Paperclip.registered_attachments_styles_path
20
+ Paperclip.registered_attachments_styles_path = nil
21
+ assert_equal ROOT.join("tmp/public/system/paperclip_attachments.yml").to_s, Paperclip.registered_attachments_styles_path
22
+ end
23
+
24
+ it "is able to get current attachment styles" do
25
+ assert_equal Hash.new, Paperclip.send(:current_attachments_styles)
26
+ rebuild_model styles: { croppable: "600x600>", big: "1000x1000>" }
27
+ expected_hash = { Dummy: { avatar: [:big, :croppable] } }
28
+ assert_equal expected_hash, Paperclip.send(:current_attachments_styles)
29
+ end
30
+
31
+ it "is able to save current attachment styles for further comparison" do
32
+ rebuild_model styles: { croppable: "600x600>", big: "1000x1000>" }
33
+ Paperclip.save_current_attachments_styles!
34
+ expected_hash = { Dummy: { avatar: [:big, :croppable] } }
35
+ assert_equal expected_hash, YAML.load_file(Paperclip.registered_attachments_styles_path)
36
+ end
37
+
38
+ it "is able to read registered attachment styles from file" do
39
+ rebuild_model styles: { croppable: "600x600>", big: "1000x1000>" }
40
+ Paperclip.save_current_attachments_styles!
41
+ expected_hash = { Dummy: { avatar: [:big, :croppable] } }
42
+ assert_equal expected_hash, Paperclip.send(:get_registered_attachments_styles)
43
+ end
44
+
45
+ it "is able to calculate differences between registered styles and current styles" do
46
+ rebuild_model styles: { croppable: "600x600>", big: "1000x1000>" }
47
+ Paperclip.save_current_attachments_styles!
48
+ rebuild_model styles: { thumb: "x100", export: "x400>", croppable: "600x600>", big: "1000x1000>" }
49
+ expected_hash = { Dummy: { avatar: [:export, :thumb] } }
50
+ assert_equal expected_hash, Paperclip.missing_attachments_styles
51
+
52
+ ActiveRecord::Base.connection.create_table :books, force: true
53
+ class ::Book < ActiveRecord::Base
54
+ has_attached_file :cover, styles: { small: "x100", large: "1000x1000>" }
55
+ has_attached_file :sample, styles: { thumb: "x100" }
56
+ end
57
+
58
+ expected_hash = {
59
+ Dummy: { avatar: [:export, :thumb] },
60
+ Book: { sample: [:thumb], cover: [:large, :small] }
61
+ }
62
+ assert_equal expected_hash, Paperclip.missing_attachments_styles
63
+ Paperclip.save_current_attachments_styles!
64
+ assert_equal Hash.new, Paperclip.missing_attachments_styles
65
+ end
66
+
67
+ it "is able to calculate differences when a new attachment is added to a model" do
68
+ rebuild_model styles: { croppable: "600x600>", big: "1000x1000>" }
69
+ Paperclip.save_current_attachments_styles!
70
+
71
+ class ::Dummy
72
+ has_attached_file :photo, styles: { small: "x100", large: "1000x1000>" }
73
+ end
74
+
75
+ expected_hash = {
76
+ Dummy: { photo: [:large, :small] }
77
+ }
78
+ assert_equal expected_hash, Paperclip.missing_attachments_styles
79
+ Paperclip.save_current_attachments_styles!
80
+ assert_equal Hash.new, Paperclip.missing_attachments_styles
81
+ end
82
+
83
+ # It's impossible to build styles hash without loading from database whole bunch of records
84
+ it "skips lambda-styles" do
85
+ rebuild_model styles: lambda { |attachment| attachment.instance.other == "a" ? { thumb: "50x50#" } : { large: "400x400" } }
86
+ assert_equal Hash.new, Paperclip.send(:current_attachments_styles)
87
+ end
88
+ end