README.md in file_validators-1.1.0 vs README.md in file_validators-1.2.0

- old
+ new

@@ -1,20 +1,25 @@ # File Validators -[![Gem Version](http://img.shields.io/gem/v/file_validators.svg)](https://rubygems.org/gems/file_validators) +[![Gem Version](https://badge.fury.io/rb/file_validators.svg)](http://badge.fury.io/rb/file_validators) [![Build Status](https://travis-ci.org/musaffa/file_validators.svg)](https://travis-ci.org/musaffa/file_validators) -[![Dependency Status](http://img.shields.io/gemnasium/musaffa/file_validators.svg)](https://gemnasium.com/musaffa/file_validators) -[![Coverage Status](http://img.shields.io/coveralls/musaffa/file_validators.svg)](https://coveralls.io/r/musaffa/file_validators) -[![Code Climate](http://img.shields.io/codeclimate/github/musaffa/file_validators.svg)](https://codeclimate.com/github/musaffa/file_validators) +[![Dependency Status](https://gemnasium.com/musaffa/file_validators.svg)](https://gemnasium.com/musaffa/file_validators) +[![Coverage Status](https://coveralls.io/repos/musaffa/file_validators/badge.png)](https://coveralls.io/r/musaffa/file_validators) +[![Code Climate](https://codeclimate.com/github/musaffa/file_validators/badges/gpa.svg)](https://codeclimate.com/github/musaffa/file_validators) +[![Inline docs](http://inch-ci.org/github/musaffa/file_validators.svg)](http://inch-ci.org/github/musaffa/file_validators) -File Validators gem adds file size and content type validations to ActiveModel. Any module that uses ActiveModel, for example ActiveRecord, can use these file validators. +File Validators gem adds file size and content type validations to ActiveModel. +Any module that uses ActiveModel, for example ActiveRecord, can use these file validators. ## Support * ActiveModel versions: 3 and 4. * Rails versions: 3 and 4. +It has been tested to work with Carrierwave, Paperclip, Dragonfly etc file uploading solutions. +Validations works both before and after uploads. + ## Installation Add the following to your Gemfile: ```ruby @@ -29,22 +34,24 @@ class Profile include ActiveModel::Validations attr_accessor :avatar validates :avatar, file_size: { less_than_or_equal_to: 100.kilobytes }, - file_content_type: { allow: ['image/jpeg', 'image/png', 'image/gif'] } + file_content_type: { allow: ['image/jpeg', 'image/png'] } end ``` ActiveRecord example: ```ruby class Profile < ActiveRecord::Base validates :avatar, file_size: { less_than_or_equal_to: 100.kilobytes }, - file_content_type: { allow: ['image/jpeg', 'image/png', 'image/gif'] } + file_content_type: { allow: ['image/jpeg', 'image/png'] } end ``` +You can also use `:validates_file_size` and `:validates_file_content_type` idioms. + ## API ### File Size Validator: * `in`: A range of bytes or a proc that returns a range @@ -71,15 +78,15 @@ With `:in` you will get `min` and `max` as replacements. `count`, `min` and `max` each will have its value and unit together. You can write error messages without using any replacement. ```ruby validates :avatar, file_size: { less_than: 100.kilobytes, - message: 'avatar file size should be less than %{count}' } + message: 'avatar should be less than %{count}' } ``` ```ruby validates :document, file_size: { in: 1.kilobyte..1.megabyte, - message: 'document should be within %{min} and %{max}' } + message: 'must be within %{min} and %{max}' } ``` * `if`: A lambda or name of an instance method. Validation will only be run if this lambda or method returns true. * `unless`: Same as `if` but validates if lambda or method returns false. You can combine different options. @@ -101,18 +108,18 @@ validates :avatar, file_size: { less_than: lambda { |record| record.size_in_bytes } } ``` ### File Content Type Validator -* `allow`: Allowed content types. Can be a single content type or an array. Each type can be a String or a Regexp. It also accepts proc. Allows all by default. +* `allow`: Allowed content types. Can be a single content type or an array. Each type can be a String or a Regexp. It also accepts `proc`. Allows all by default. ```ruby # string validates :avatar, file_content_type: { allow: 'image/jpeg' } ``` ```ruby # array of strings -validates :attachment, file_content_type: { allow: ['image/jpeg', 'image/png', 'text/plain'] } +validates :attachment, file_content_type: { allow: ['image/jpeg', 'text/plain'] } ``` ```ruby # regexp validates :avatar, file_content_type: { allow: /^image\/.*/ } ``` @@ -131,34 +138,48 @@ * `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. * `message`: The message to display when the uploaded file has an invalid content type. You will get `types` as a replacement. You can write error messages without using any replacement. ```ruby validates :avatar, file_content_type: { allow: ['image/jpeg', 'image/gif'], - message: 'should have content type %{types}' } + message: 'only %{types} are allowed' } ``` ```ruby validates :avatar, file_content_type: { allow: ['image/jpeg', 'image/gif'], - message: 'Avatar only allows jpeg and gif image files' } + message: 'Avatar only allows jpeg and gif' } ``` * `if`: A lambda or name of an instance method. Validation will only be run is this lambda or method returns true. * `unless`: Same as `if` but validates if lambda or method returns false. You can combine `:allow` and `:exclude`: ```ruby # this will allow all the image types except png and gif validates :avatar, file_content_type: { allow: /^image\/.*/, exclude: ['image/png', 'image/gif'] } ``` +## Security + +This gem uses file command to get the content type based on the content of the file rather +than the extension. This prevents fake content types inserted in the request header. + +It also prevents file media type spoofing. For example, user may upload a .html document as +a part of the EXIF header of a valid JPEG file. Content type validator will identify its content type +as `image/jpeg` and, without spoof detection, it may pass the validation and be saved as .html document +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. + +**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. + ## i18n Translations File Size Errors * `file_size_is_in`: takes `min` and `max` as replacements * `file_size_is_less_than`: takes `count` as replacement * `file_size_is_less_than_or_equal_to`: takes `count` as replacement * `file_size_is_greater_than`: takes `count` as replacement * `file_size_is_greater_than_or_equal_to`: takes `count` as replacement Content Type Errors +* `spoofed_file_media_type`: generated when file media type from its extension doesn't match the media type of its +content. learn more from [security](#Security). * `allowed_file_content_types`: generated when you have specified allowed types but the content type of the file doesn't match. takes `types` as replacement. * `excluded_file_content_types`: generated when you have specified excluded types and the content type of the file matches anyone of them. takes `types` as replacement.