file_validators 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b2c81af7c7d23418b0c6e37eea387759dda91a48
4
- data.tar.gz: a50cac956a66ac32de2c01b15ffe3be6b5acfbfe
3
+ metadata.gz: b2a185e059287eb886b2f0aca6f8654d0860f97d
4
+ data.tar.gz: 087b21a3812ec49de9dd0df345521792631b2925
5
5
  SHA512:
6
- metadata.gz: 6f6a8749bea73140878064b29e78a79b938076d28b42dcec160f955867d297d8d79cb01e3ec533cdef3571678f85f887071e267734f830fb095038f97b9eadb6
7
- data.tar.gz: f1e3491b792d054b3e515944b64b0fe2fdb1bce5f1a62c2d1ad3b54494a8787e9536e8d5b0870a165f477a4b0d67d09c8d105bb376ca04e03eae387c4673731c
6
+ metadata.gz: ba536373220e03c3e4da79095baad18015dfec6f152cca7fca98f8ba0b1c9b64488b6f447497153e959d3eb1980f07015b32f2c1717638fda8002bb99232d1c7
7
+ data.tar.gz: cf6d97528247cae02d8c42824c42938e37e57b2ff73045cd429ecb601c23784ce058afe3ef8969994ef83f7366482132818b724b2c00c0a28390d52650a5fb4a
data/.travis.yml CHANGED
@@ -1,9 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.2
4
- - 2.0.0
3
+ - 2.2.2
5
4
  - 1.9.3
6
5
  gemfile:
6
+ - gemfiles/activemodel_4.2.gemfile
7
7
  - gemfiles/activemodel_4.1.gemfile
8
8
  - gemfiles/activemodel_4.0.gemfile
9
9
  - gemfiles/activemodel_3.2.gemfile
data/Appraisals CHANGED
@@ -16,4 +16,8 @@ end
16
16
 
17
17
  appraise 'activemodel-4.1' do
18
18
  gem 'activemodel', '4.1.6'
19
- end
19
+ end
20
+
21
+ appraise 'activemodel-4.2' do
22
+ gem 'activemodel', '4.2.3'
23
+ end
data/README.md CHANGED
@@ -15,7 +15,7 @@ Any module that uses ActiveModel, for example ActiveRecord, can use these file v
15
15
  * ActiveModel versions: 3 and 4.
16
16
  * Rails versions: 3 and 4.
17
17
 
18
- It has been tested to work with Carrierwave, Paperclip, Dragonfly etc file uploading solutions.
18
+ It has been tested to work with Carrierwave, Paperclip, Dragonfly, Refile etc file uploading solutions.
19
19
  Validations works both before and after uploads.
20
20
 
21
21
  ## Installation
@@ -135,7 +135,17 @@ validates :attachment, file_content_type: { allow: [/^image\/.*/, 'video/mp4'] }
135
135
  # proc/lambda example
136
136
  validates :video, file_content_type: { allow: lambda { |record| record.content_types } }
137
137
  ```
138
- * `exclude`: Forbidden content types. Can be a single content type or an array. Each type can be a String or a Regexp. It also accepts `proc`. See `:allow` options examples.
138
+ * `exclude`: Forbidden content types. Can be a single content type or an array. Each type
139
+ can be a String or a Regexp. It also accepts `proc`. See `:allow` options examples.
140
+ * `mode`: `:strict` or `:relaxed`. `:strict` mode can detect content type based on the contents
141
+ of the files. It also detects media type spoofing (see more in [security](#security)).
142
+ `:relaxed` mode uses file name to detect the content type using `mime-types` gem.
143
+ If mode option is not set then the validator uses form supplied content type.
144
+ ```ruby
145
+ # string
146
+ validates :avatar, file_content_type: { allow: 'image/jpeg', mode: :strict }
147
+ validates :avatar, file_content_type: { allow: 'image/jpeg', mode: :relaxed }
148
+ ```
139
149
  * `message`: The message to display when the uploaded file has an invalid content type.
140
150
  You will get `types` as a replacement. You can write error messages without using any replacement.
141
151
  ```ruby
@@ -157,15 +167,20 @@ validates :avatar, file_content_type: { allow: /^image\/.*/, exclude: ['image/pn
157
167
 
158
168
  ## Security
159
169
 
160
- This gem uses file command to get the content type based on the content of the file rather
170
+ This gem can use Unix file command to get the content type based on the content of the file rather
161
171
  than the extension. This prevents fake content types inserted in the request header.
162
172
 
163
173
  It also prevents file media type spoofing. For example, user may upload a .html document as
164
174
  a part of the EXIF header of a valid JPEG file. Content type validator will identify its content type
165
175
  as `image/jpeg` and, without spoof detection, it may pass the validation and be saved as .html document
166
- thus exposing your application to a security vulnerability. Media type spoof detector wont let that happen. It will not allow a file having `image/jpeg` content type to be saved as `text/plain`. It checks only media type mismatch, for example `text` of `text/plain` and `image` of `image/jpeg`. So it will not prevent `image/jpeg` from saving as `image/png` as both have the same `image` media type.
176
+ thus exposing your application to a security vulnerability. Media type spoof detector wont let that happen.
177
+ It will not allow a file having `image/jpeg` content type to be saved as `text/plain`. It checks only media
178
+ type mismatch, for example `text` of `text/plain` and `image` of `image/jpeg`. So it will not prevent
179
+ `image/jpeg` from saving as `image/png` as both have the same `image` media type.
167
180
 
168
- **note**: Media type spoof detection is integrated in the [content type validator](#file-content-type-validator). This means without content type validation spoof detection wont be enabled.
181
+ **note**: This security feature is disabled by default. To enable it, first add `cocaine` gem in
182
+ your Gemfile and then add `mode: :strict` option in [content type validations](#file-content-type-validator).
183
+ `:strict` mode may not work in direct file uploading systems as the file is not passed along with the form.
169
184
 
170
185
  ## i18n Translations
171
186
 
@@ -211,6 +226,28 @@ en:
211
226
  tb: "TB"
212
227
  ```
213
228
 
229
+ ## Further Instructions
230
+
231
+ If you are using `:strict` or `:relaxed` mode, for content types which are not supported
232
+ by mime-types gem, you need to register those content types. For example, you can register
233
+ `.docx` in the initializer:
234
+ ```Ruby
235
+ # config/initializers/mime_types.rb
236
+ Mime::Type.register "application/vnd.openxmlformats-officedocument.wordprocessingml.document", :docx
237
+ ```
238
+
239
+ If you want to see what content type `:strict` mode returns, run this command in the shell:
240
+ ```Shell
241
+ $ file -b --mime-type your-file.xxx
242
+ ```
243
+
244
+ ## Issues
245
+
246
+ **Carrierwave** - You are adding file validators to a model, then you are recommended to keep extension_white_list &/
247
+ extension_black_list in the uploaders (in case you don't have, add that method).
248
+ As of this writing (see [issue](https://github.com/carrierwaveuploader/carrierwave/issues/361)), Carrierwave
249
+ uploaders start processing a file immediately after its assignment (even before the validators are called).
250
+
214
251
  ## Tests
215
252
 
216
253
  ```ruby
@@ -19,8 +19,8 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.add_dependency 'activemodel', '>= 3.0'
21
21
  s.add_dependency 'mime-types', '>= 1.0'
22
- s.add_dependency 'cocaine', '~> 0.5.4'
23
22
 
23
+ s.add_development_dependency 'cocaine', '~> 0.5.4'
24
24
  s.add_development_dependency 'rake'
25
25
  s.add_development_dependency 'rspec', '~> 3.1.0'
26
26
  s.add_development_dependency 'coveralls'
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "activemodel", "4.2.3"
7
+
8
+ gemspec :path => "../"
@@ -1,4 +1,7 @@
1
- require 'cocaine'
1
+ begin
2
+ require 'cocaine'
3
+ rescue LoadError
4
+ end
2
5
 
3
6
  module FileValidators
4
7
  module Utils
@@ -30,6 +33,8 @@ module FileValidators
30
33
  def content_type_from_file_command
31
34
  type = begin
32
35
  Cocaine::CommandLine.new('file', '-b --mime-type :file').run(file: @file_path)
36
+ rescue NameError => e
37
+ puts "file_validators: Add 'cocaine' gem as you are using file content type validations in strict mode"
33
38
  rescue Cocaine::CommandLineError => e
34
39
  # TODO: log command failure
35
40
  DEFAULT_CONTENT_TYPE
@@ -25,7 +25,7 @@ module FileValidators
25
25
 
26
26
  def has_extension?
27
27
  # the following code replaced File.extname(@file_name).present? because it cannot
28
- # return the extension of a file named '.html', '.jpg' etc
28
+ # return the extension of a extension-only file names, e.g. '.html', '.jpg' etc
29
29
  @file_name.split('.').length > 1
30
30
  end
31
31
 
@@ -13,13 +13,12 @@ module ActiveModel
13
13
 
14
14
  def validate_each(record, attribute, value)
15
15
  unless value.blank?
16
- file_path = get_file_path(value)
17
- file_name = get_file_name(value)
18
- content_type = detect_content_type(file_path)
16
+ mode = option_value(record, :mode)
17
+ content_type = get_content_type(value, mode)
19
18
  allowed_types = option_content_types(record, :allow)
20
19
  forbidden_types = option_content_types(record, :exclude)
21
20
 
22
- validate_media_type(record, attribute, content_type, file_name)
21
+ validate_media_type(record, attribute, content_type, get_file_name(value)) if mode == :strict
23
22
  validate_whitelist(record, attribute, content_type, allowed_types)
24
23
  validate_blacklist(record, attribute, content_type, forbidden_types)
25
24
  end
@@ -55,8 +54,19 @@ module ActiveModel
55
54
  end
56
55
  end
57
56
 
58
- def detect_content_type(file_path)
59
- FileValidators::Utils::ContentTypeDetector.new(file_path).detect
57
+ def get_content_type(value, mode)
58
+ case mode
59
+ when :strict
60
+ file_path = get_file_path(value)
61
+ FileValidators::Utils::ContentTypeDetector.new(file_path).detect
62
+ when :relaxed
63
+ file_name = get_file_name(value)
64
+ MIME::Types.type_for(file_name).first
65
+ else
66
+ value = JSON.parse(value) if value.is_a?(String)
67
+ value = OpenStruct.new(value) if value.is_a?(Hash)
68
+ value.content_type
69
+ end
60
70
  end
61
71
 
62
72
  def option_content_types(record, key)
@@ -103,6 +113,12 @@ module ActiveModel
103
113
  # * +exclude+: Forbidden content types.
104
114
  # * +message+: The message to display when the uploaded file has an invalid
105
115
  # content type.
116
+ # * +mode+: :strict or :relaxed.
117
+ # :strict mode validates the content type based on the actual contents
118
+ # of the files. Thus it can detect media type spoofing.
119
+ # :relaxed validates the content type based on the file name using
120
+ # the mime-types gem. It's only for sanity check.
121
+ # If mode is not set then it uses form supplied content type.
106
122
  # * +if+: A lambda or name of an instance method. Validation will only
107
123
  # be run is this lambda or method returns true.
108
124
  # * +unless+: Same as +if+ but validates if lambda or method returns false.
@@ -15,6 +15,8 @@ module ActiveModel
15
15
  def validate_each(record, attribute, value)
16
16
  unless value.blank?
17
17
  options.slice(*CHECKS.keys).each do |option, option_value|
18
+ value = JSON.parse(value) if value.is_a?(String)
19
+ value = OpenStruct.new(value) if value.is_a?(Hash)
18
20
  option_value = option_value.call(record) if option_value.is_a?(Proc)
19
21
  unless valid_size?(value.size, option, option_value)
20
22
  record.errors.add(attribute,
@@ -1,3 +1,3 @@
1
1
  module FileValidators
2
- VERSION = '1.2.0'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -0,0 +1 @@
1
+ a sample text
@@ -12,6 +12,7 @@ describe 'File Content Type integration with ActiveModel' do
12
12
  @chubby_bubble_path = File.join(File.dirname(__FILE__), '../fixtures/chubby_bubble.jpg')
13
13
  @chubby_cute_path = File.join(File.dirname(__FILE__), '../fixtures/chubby_cute.png')
14
14
  @sample_text_path = File.join(File.dirname(__FILE__), '../fixtures/sample.txt')
15
+ @spoofed_file_path = File.join(File.dirname(__FILE__), '../fixtures/spoofed.jpg')
15
16
  end
16
17
 
17
18
  context ':allow option' do
@@ -40,7 +41,7 @@ describe 'File Content Type integration with ActiveModel' do
40
41
  before :all do
41
42
  Person.class_eval do
42
43
  Person.reset_callbacks(:validate)
43
- validates :avatar, file_content_type: { allow: /^image\/.*/ }
44
+ validates :avatar, file_content_type: { allow: /^image\/.*/, mode: :strict }
44
45
  end
45
46
  end
46
47
 
@@ -68,7 +69,7 @@ describe 'File Content Type integration with ActiveModel' do
68
69
  before :all do
69
70
  Person.class_eval do
70
71
  Person.reset_callbacks(:validate)
71
- validates :avatar, file_content_type: { allow: ['image/jpeg', 'text/plain'] }
72
+ validates :avatar, file_content_type: { allow: ['image/jpeg', 'text/plain'], mode: :strict }
72
73
  end
73
74
  end
74
75
 
@@ -96,7 +97,8 @@ describe 'File Content Type integration with ActiveModel' do
96
97
  before :all do
97
98
  Person.class_eval do
98
99
  Person.reset_callbacks(:validate)
99
- validates :avatar, file_content_type: { allow: lambda { |record| ['image/jpeg', 'text/plain'] } }
100
+ validates :avatar, file_content_type: { allow: lambda { |record| ['image/jpeg', 'text/plain'] },
101
+ mode: :strict }
100
102
  end
101
103
  end
102
104
 
@@ -126,7 +128,7 @@ describe 'File Content Type integration with ActiveModel' do
126
128
  before :all do
127
129
  Person.class_eval do
128
130
  Person.reset_callbacks(:validate)
129
- validates :avatar, file_content_type: { exclude: 'image/jpeg' }
131
+ validates :avatar, file_content_type: { exclude: 'image/jpeg', mode: :strict }
130
132
  end
131
133
  end
132
134
 
@@ -147,7 +149,7 @@ describe 'File Content Type integration with ActiveModel' do
147
149
  before :all do
148
150
  Person.class_eval do
149
151
  Person.reset_callbacks(:validate)
150
- validates :avatar, file_content_type: { exclude: /^image\/.*/ }
152
+ validates :avatar, file_content_type: { exclude: /^image\/.*/, mode: :strict }
151
153
  end
152
154
  end
153
155
 
@@ -175,7 +177,7 @@ describe 'File Content Type integration with ActiveModel' do
175
177
  before :all do
176
178
  Person.class_eval do
177
179
  Person.reset_callbacks(:validate)
178
- validates :avatar, file_content_type: { exclude: ['image/jpeg', 'text/plain'] }
180
+ validates :avatar, file_content_type: { exclude: ['image/jpeg', 'text/plain'], mode: :strict }
179
181
  end
180
182
  end
181
183
 
@@ -203,7 +205,7 @@ describe 'File Content Type integration with ActiveModel' do
203
205
  before :all do
204
206
  Person.class_eval do
205
207
  Person.reset_callbacks(:validate)
206
- validates :avatar, file_content_type: { exclude: lambda { |record| /^image\/.*/ } }
208
+ validates :avatar, file_content_type: { exclude: lambda { |record| /^image\/.*/ }, mode: :strict }
207
209
  end
208
210
  end
209
211
 
@@ -227,7 +229,7 @@ describe 'File Content Type integration with ActiveModel' do
227
229
  before :all do
228
230
  Person.class_eval do
229
231
  Person.reset_callbacks(:validate)
230
- validates :avatar, file_content_type: { allow: /^image\/.*/, exclude: 'image/png' }
232
+ validates :avatar, file_content_type: { allow: /^image\/.*/, exclude: 'image/png', mode: :strict }
231
233
  end
232
234
  end
233
235
 
@@ -243,4 +245,123 @@ describe 'File Content Type integration with ActiveModel' do
243
245
  it { is_expected.not_to be_valid }
244
246
  end
245
247
  end
248
+
249
+ context ':mode option' do
250
+ context 'strict mode' do
251
+ before :all do
252
+ Person.class_eval do
253
+ Person.reset_callbacks(:validate)
254
+ validates :avatar, file_content_type: { allow: 'image/jpeg', mode: :strict }
255
+ end
256
+ end
257
+
258
+ subject { Person.new }
259
+
260
+ context 'with valid file' do
261
+ it 'validates the file' do
262
+ subject.avatar = Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
263
+ expect(subject).to be_valid
264
+ end
265
+ end
266
+
267
+ context 'with spoofed file' do
268
+ it 'invalidates the file' do
269
+ subject.avatar = Rack::Test::UploadedFile.new(@spoofed_file_path, 'image/jpeg')
270
+ expect(subject).not_to be_valid
271
+ end
272
+ end
273
+ end
274
+
275
+ context 'relaxed mode' do
276
+ before :all do
277
+ Person.class_eval do
278
+ Person.reset_callbacks(:validate)
279
+ validates :avatar, file_content_type: { allow: 'image/jpeg', mode: :relaxed }
280
+ end
281
+ end
282
+
283
+ subject { Person.new }
284
+
285
+ context 'with valid file' do
286
+ it 'validates the file' do
287
+ subject.avatar = Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
288
+ expect(subject).to be_valid
289
+ end
290
+ end
291
+
292
+ context 'with spoofed file' do
293
+ it 'validates the file' do
294
+ subject.avatar = Rack::Test::UploadedFile.new(@spoofed_file_path, 'image/jpeg')
295
+ expect(subject).to be_valid
296
+ end
297
+ end
298
+ end
299
+
300
+ context 'default mode' do
301
+ before :all do
302
+ Person.class_eval do
303
+ Person.reset_callbacks(:validate)
304
+ validates :avatar, file_content_type: { allow: 'image/jpeg' }
305
+ end
306
+ end
307
+
308
+ subject { Person.new }
309
+
310
+ context 'with valid file' do
311
+ it 'validates the file' do
312
+ subject.avatar = Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
313
+ expect(subject).to be_valid
314
+ end
315
+ end
316
+
317
+ context 'with spoofed file' do
318
+ it 'invalidates the file' do
319
+ subject.avatar = Rack::Test::UploadedFile.new(@spoofed_file_path, 'image/jpeg')
320
+ expect(subject).to be_valid
321
+ end
322
+ end
323
+ end
324
+ end
325
+
326
+ context 'image data as json string' do
327
+ before :all do
328
+ Person.class_eval do
329
+ Person.reset_callbacks(:validate)
330
+ validates :avatar, file_content_type: { allow: 'image/jpeg' }
331
+ end
332
+ end
333
+
334
+ subject { Person.new }
335
+
336
+ context 'for invalid content type' do
337
+ before { subject.avatar = "{\"filename\":\"img140910_88338.GIF\",\"content_type\":\"image/gif\",\"size\":13150}" }
338
+ it { is_expected.not_to be_valid }
339
+ end
340
+
341
+ context 'for valid content type' do
342
+ before { subject.avatar = "{\"filename\":\"img140910_88338.jpg\",\"content_type\":\"image/jpeg\",\"size\":13150}" }
343
+ it { is_expected.to be_valid }
344
+ end
345
+ end
346
+
347
+ context 'image data as hash' do
348
+ before :all do
349
+ Person.class_eval do
350
+ Person.reset_callbacks(:validate)
351
+ validates :avatar, file_content_type: { allow: 'image/jpeg' }
352
+ end
353
+ end
354
+
355
+ subject { Person.new }
356
+
357
+ context 'for invalid content type' do
358
+ before { subject.avatar = { "filename":"img140910_88338.GIF", "content_type":"image/gif", "size":13150 } }
359
+ it { is_expected.not_to be_valid }
360
+ end
361
+
362
+ context 'for valid content type' do
363
+ before { subject.avatar = { "filename":"img140910_88338.jpg", "content_type":"image/jpeg", "size":13150 } }
364
+ it { is_expected.to be_valid }
365
+ end
366
+ end
246
367
  end
@@ -206,4 +206,46 @@ describe 'File Size Validator integration with ActiveModel' do
206
206
  it { is_expected.to be_valid }
207
207
  end
208
208
  end
209
+
210
+ context 'image data as json string' do
211
+ before :all do
212
+ Person.class_eval do
213
+ Person.reset_callbacks(:validate)
214
+ validates :avatar, file_size: { greater_than: 20.kilobytes }
215
+ end
216
+ end
217
+
218
+ subject { Person.new }
219
+
220
+ context 'when file size is less than the specified size' do
221
+ before { subject.avatar = "{\"filename\":\"img140910_88338.GIF\",\"content_type\":\"image/gif\",\"size\":13150}" }
222
+ it { is_expected.not_to be_valid }
223
+ end
224
+
225
+ context 'when file size within the specified size' do
226
+ before { subject.avatar = "{\"filename\":\"img140910_88338.GIF\",\"content_type\":\"image/gif\",\"size\":33150}" }
227
+ it { is_expected.to be_valid }
228
+ end
229
+ end
230
+
231
+ context 'image data as hash' do
232
+ before :all do
233
+ Person.class_eval do
234
+ Person.reset_callbacks(:validate)
235
+ validates :avatar, file_size: { greater_than: 20.kilobytes }
236
+ end
237
+ end
238
+
239
+ subject { Person.new }
240
+
241
+ context 'when file size is less than the specified size' do
242
+ before { subject.avatar = { "filename":"img140910_88338.GIF", "content_type":"image/gif", "size":13150 } }
243
+ it { is_expected.not_to be_valid }
244
+ end
245
+
246
+ context 'when file size within the specified size' do
247
+ before { subject.avatar = { "filename":"img140910_88338.GIF", "content_type":"image/gif", "size":33150 } }
248
+ it { is_expected.to be_valid }
249
+ end
250
+ end
209
251
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  ENV['RAILS_ENV'] ||= 'test'
2
2
 
3
+ require 'active_support'
3
4
  require 'active_support/core_ext'
4
5
  require_relative '../lib/file_validators'
5
6
  require 'rspec'
@@ -1,8 +1,8 @@
1
1
  RSpec::Matchers.define :allow_file_content_type do |content_type, validator, message|
2
2
  match do |model|
3
3
  value = double('file', path: content_type, original_filename: content_type)
4
- model.any_instance.stub(:read_attribute_for_validation).and_return(value)
5
- validator.stub(:detect_content_type).and_return(content_type)
4
+ allow_any_instance_of(model).to receive(:read_attribute_for_validation).and_return(value)
5
+ allow(validator).to receive(:get_content_type).and_return(content_type)
6
6
  dummy = model.new
7
7
  validator.validate(dummy)
8
8
  if message.present?
@@ -1,7 +1,7 @@
1
1
  RSpec::Matchers.define :allow_file_size do |size, validator, message|
2
2
  match do |model|
3
3
  value = double('file', size: size)
4
- model.any_instance.stub(:read_attribute_for_validation).and_return(value)
4
+ allow_any_instance_of(model).to receive(:read_attribute_for_validation).and_return(value)
5
5
  dummy = model.new
6
6
  validator.validate(dummy)
7
7
  if message.present?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file_validators
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ahmad Musaffa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-28 00:00:00.000000000 Z
11
+ date: 2015-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -45,7 +45,7 @@ dependencies:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.5.4
48
- type: :runtime
48
+ type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
@@ -130,6 +130,7 @@ files:
130
130
  - gemfiles/activemodel_3.2.gemfile
131
131
  - gemfiles/activemodel_4.0.gemfile
132
132
  - gemfiles/activemodel_4.1.gemfile
133
+ - gemfiles/activemodel_4.2.gemfile
133
134
  - lib/file_validators.rb
134
135
  - lib/file_validators/locale/en.yml
135
136
  - lib/file_validators/utils/content_type_detector.rb
@@ -141,6 +142,7 @@ files:
141
142
  - spec/fixtures/chubby_cute.png
142
143
  - spec/fixtures/cute.jpg
143
144
  - spec/fixtures/sample.txt
145
+ - spec/fixtures/spoofed.jpg
144
146
  - spec/integration/combined_validators_integration_spec.rb
145
147
  - spec/integration/file_content_type_validation_integration_spec.rb
146
148
  - spec/integration/file_size_validator_integration_spec.rb
@@ -172,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
174
  version: '0'
173
175
  requirements: []
174
176
  rubyforge_project:
175
- rubygems_version: 2.2.2
177
+ rubygems_version: 2.4.5
176
178
  signing_key:
177
179
  specification_version: 4
178
180
  summary: ActiveModel file validators
@@ -181,6 +183,7 @@ test_files:
181
183
  - spec/fixtures/chubby_cute.png
182
184
  - spec/fixtures/cute.jpg
183
185
  - spec/fixtures/sample.txt
186
+ - spec/fixtures/spoofed.jpg
184
187
  - spec/integration/combined_validators_integration_spec.rb
185
188
  - spec/integration/file_content_type_validation_integration_spec.rb
186
189
  - spec/integration/file_size_validator_integration_spec.rb