attachment_saver 1.0.1 → 1.1.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: 5a22b412009475caf986f038cc3613ce59ff940c
4
- data.tar.gz: 072903d7678d8305718b416d62058623f4e7bc2d
3
+ metadata.gz: 6e98ac80c02ee411fd7ea5ad5b6c0ea691e9b4e8
4
+ data.tar.gz: 54a6365fa0959a3f273e7daf4b904ffa7b0fbff7
5
5
  SHA512:
6
- metadata.gz: b945b2d6f38082b9bd9befa2fb20f9f58ba150c63382d46d2860228b573a1851f6a0197ce43866052dd5f1a089d1226e88faeae706d81990b39a0a52ad71e19c
7
- data.tar.gz: cbabbc1710ec1bf2547104eb825baaa96939c73a8a4182dee0e4500fc067988292d562e52c923e8a81c5987ca11c0cd1cf821b33cab78a77aaf31581faf46261
6
+ metadata.gz: 81e68dc896fe18afa31e7e4573ccdbe9629f6d87f71a57e8a5ae4ac38a0f6c89fde78f38a3e60f3429908e8c685d4c9871cafc248cdfe6917b138b18c41e2a61
7
+ data.tar.gz: d2942a80062936f13e518a18dddf63e4a5514358fc677e43f7f2a2bcfd325e1c8581fa4b1774dce6bfabc98eece19843646c3a8f071891b947b1fd62b6e4a0bb
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ desc 'Test the columns_on_demand plugin.'
11
11
  Rake::TestTask.new(:test) do |t|
12
12
  t.libs << 'lib'
13
13
  t.libs << 'test'
14
- t.test_files = FileList['test/*_test.rb']
14
+ t.pattern = 'test/*_test.rb'
15
15
  t.verbose = true
16
+ t.warning = false
16
17
  end
@@ -14,18 +14,12 @@ of processing. Errors are carefully handled to minimize the possibility of
14
14
  broken uploads leaving incomplete or corrupt data.
15
15
 
16
16
  RMagick, MiniMagick, and ImageScience image processors are supported.
17
-
18
-
19
- Compatibility
20
- =============
21
-
22
- Currently tested against Rails 3.2.13 and 3.1.8, on Ruby 1.8.7 and 2.0.0p0.
23
- Was also tested compatible with 2.3.14 and 3.0.17.
24
17
  EOF
25
18
  gem.has_rdoc = false
26
19
  gem.author = "Will Bryant"
27
20
  gem.email = "will.bryant@gmail.com"
28
21
  gem.homepage = "http://github.com/willbryant/attachment_saver"
22
+ gem.license = 'MIT'
29
23
 
30
24
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
31
25
  gem.files = `git ls-files`.split("\n")
@@ -33,6 +27,7 @@ EOF
33
27
  gem.require_path = "lib"
34
28
 
35
29
  gem.add_dependency "activerecord"
30
+ gem.add_dependency "mimemagic"
36
31
  gem.add_development_dependency "rake"
37
32
  gem.add_development_dependency "image_science"
38
33
  gem.add_development_dependency "rmagick"
@@ -1,5 +1,4 @@
1
1
  require 'attachment_saver_errors'
2
- require 'misc/file_size'
3
2
  require 'tmpdir'
4
3
 
5
4
  module AttachmentSaver
@@ -1,3 +1,3 @@
1
1
  module AttachmentSaver
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -83,7 +83,7 @@ module AttachmentSaver
83
83
  end
84
84
 
85
85
  def in_storage?
86
- File.exists?(storage_filename)
86
+ File.exist?(storage_filename)
87
87
  end
88
88
 
89
89
  def public_path
@@ -1,4 +1,5 @@
1
1
  require 'attachment_saver_errors'
2
+ require 'mimemagic'
2
3
 
3
4
  class ImageProcessorError < AttachmentProcessorError; end
4
5
 
@@ -6,14 +7,40 @@ module AttachmentSaver
6
7
  module Processors
7
8
  # shared code for all image processors
8
9
  module Image
10
+ DEFAULT_VALID_IMAGE_TYPES = %w(image/jpeg image/png image/gif).freeze
11
+
9
12
  def image?
10
13
  return false if content_type.blank?
11
14
  parts = content_type.split(/\//)
12
15
  parts.size == 2 && parts.first.strip == 'image'
13
16
  end
17
+
18
+ def valid_image_type
19
+ valid_image_types = self.class.attachment_options[:valid_image_types] || DEFAULT_VALID_IMAGE_TYPES
20
+
21
+ uploaded_file.rewind
22
+ magic = MimeMagic.by_magic(uploaded_file)
23
+
24
+ if magic.nil?
25
+ # if it doesn't look like an image, make sure it's not labelled as an image
26
+ self.content_type = 'application/octet-stream' if image? || content_type.nil?
27
+ elsif !valid_image_types.include?(magic.type)
28
+ # overwrite the content type given by the untrusted client with the real content type; it may get refined later by the image processor
29
+ self.content_type = magic.type
30
+ else
31
+ # seems legit
32
+ return true
33
+ end
34
+
35
+ errors.add(:content_type, "is invalid") if respond_to?(:errors)
36
+ false
37
+ end
14
38
 
15
39
  def before_validate_attachment
16
- examine_attachment unless uploaded_file.nil? || derived_image?
40
+ unless uploaded_file.nil? || derived_image?
41
+ return false unless valid_image_type
42
+ examine_image
43
+ end
17
44
  rescue ImageProcessorError
18
45
  # we examine all files, regardless of whether the client browser labelled them an
19
46
  # image, because they may be an image with the wrong extension or content type.
@@ -19,7 +19,7 @@ module AttachmentSaver
19
19
  ::ImageScience.with_image_attributes(filename) {|image| block.call(image)}
20
20
  end
21
21
 
22
- def examine_attachment
22
+ def examine_image
23
23
  with_image_attributes(uploaded_file_path) do |original_image|
24
24
  self.width = original_image.width if respond_to?(:width)
25
25
  self.height = original_image.height if respond_to?(:height)
@@ -28,7 +28,7 @@ module AttachmentSaver
28
28
  with_image(filename, &block)
29
29
  end
30
30
 
31
- def examine_attachment
31
+ def examine_image
32
32
  with_image_attributes(uploaded_file_path) do |original_image|
33
33
  self.content_type = original_image.mime_type unless self.class.attachment_options[:keep_content_type] || original_image.mime_type.blank?
34
34
  self.file_extension = original_image.file_type_extension unless self.class.attachment_options[:keep_file_extension] || original_image.file_type_extension.blank?
@@ -93,7 +93,7 @@ module AttachmentSaver
93
93
  left = (width - new_width)/2
94
94
  right = (height - new_height)/2
95
95
  image = dup
96
- image << "-crop #{new_width}x#{new_height}+#{left}+#{right} +repage" # mini_magick's #crop doesn't support the repage flag
96
+ image.crop("#{new_width}x#{new_height}+#{left}+#{right}", "+repage")
97
97
  image.extend Operations
98
98
  block.call(image)
99
99
  end
@@ -23,7 +23,7 @@ module AttachmentSaver
23
23
  block.call(image.extend(Operations))
24
24
  end
25
25
 
26
- def examine_attachment
26
+ def examine_image
27
27
  with_image_attributes(uploaded_file_path) do |original_image|
28
28
  self.width = original_image.width if respond_to?(:width)
29
29
  self.height = original_image.height if respond_to?(:height)
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
2
  require 'attachment_saver'
3
3
 
4
- class AttachmentSaverTest < Test::Unit::TestCase
4
+ class AttachmentSaverTest < ActiveSupport::TestCase
5
5
  def test_split_filename
6
6
  assert_equal ['a', nil], AttachmentSaver::split_filename('a')
7
7
  assert_equal ['a', ''], AttachmentSaver::split_filename('a.')
@@ -1,8 +1,8 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
- require 'mocha'
2
+ require 'mocha/test_unit'
3
3
  require 'datastores/file_system'
4
4
 
5
- class FileSystemDatastoreTest < Test::Unit::TestCase
5
+ class FileSystemDatastoreTest < ActiveSupport::TestCase
6
6
  attr_accessor :storage_key, :original_filename, :content_type
7
7
 
8
8
  DEFAULT_ATTACHMENT_OPTIONS = {:storage_directory => File.join(TEST_TEMP_DIR, 'fs_store_test'),
@@ -151,6 +151,8 @@ class FileSystemDatastoreTest < Test::Unit::TestCase
151
151
  save_attachment_to_test(data)
152
152
  save_test_independent_files(file, data)
153
153
  end
154
+ ensure
155
+ FileUtils.unstub(:ln)
154
156
  end
155
157
 
156
158
 
@@ -60,6 +60,14 @@ class ImageFixtures
60
60
  :expected_extension => 'js' }
61
61
  end
62
62
 
63
+ def self.exploit_file
64
+ { :path => fixture_path('ssrf.png'), # actually a .mvg file
65
+ :content_type => 'image/png',
66
+ :original_filename => 'ssrf.png',
67
+ :expected_content_type => 'application/octet-stream',
68
+ :expected_extension => 'mvg' }
69
+ end
70
+
63
71
  def self.all_readable
64
72
  [valid, wrong_extension, no_extension, empty_extension]
65
73
  end
@@ -1,9 +1,9 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
- require 'mocha'
2
+ require 'mocha/test_unit'
3
3
  require 'processors/image'
4
4
  require File.expand_path(File.join(File.dirname(__FILE__), 'image_operations'))
5
5
 
6
- class ImageProcessorTest < Test::Unit::TestCase
6
+ class ImageProcessorTest < ActiveSupport::TestCase
7
7
  class SomeModel
8
8
  include AttachmentSaver::Processors::Image
9
9
 
@@ -16,6 +16,7 @@ class ImageProcessorTest < Test::Unit::TestCase
16
16
  end
17
17
 
18
18
  def test_image?
19
+ SomeModel.attachment_options = {}
19
20
  [nil, '', '/', 'foo', 'foo/' '/bar', 'text/plain', 'x-image/invalid', 'image-x/invalid'].each do |mime|
20
21
  assert_equal false, SomeModel.new(mime).image?
21
22
  end
@@ -36,30 +37,32 @@ class ImageProcessorTest < Test::Unit::TestCase
36
37
  end
37
38
 
38
39
  def test_before_validate_attachment
39
- model_without_upload = SomeModel.new('application/octet-stream') # note the content type doesn't have to be an image for examine_attachment to be called, since examine_attachment is supposed to fix up incorrect client-supplied content-types
40
+ SomeModel.attachment_options = {}
41
+ model_without_upload = SomeModel.new('application/octet-stream') # note the content type doesn't have to be an image for examine_image to be called, since examine_image is supposed to fix up incorrect client-supplied content-types
40
42
  model_without_upload.expects(:uploaded_file).times(1).returns(nil)
41
- model_without_upload.expects(:examine_attachment).times(0)
43
+ model_without_upload.expects(:examine_image).times(0)
42
44
  model_without_upload.before_validate_attachment
43
45
 
44
46
  model_with_upload = SomeModel.new('application/octet-stream')
45
- model_with_upload.expects(:uploaded_file).times(1).returns('dummy')
46
- model_with_upload.expects(:examine_attachment).times(1)
47
+ model_with_upload.expects(:uploaded_file).at_least(:once).returns(StringIO.new('dummy'))
48
+ model_with_upload.expects(:examine_image).times(1)
47
49
  model_with_upload.before_validate_attachment
48
50
 
49
51
  model_with_non_image_upload = SomeModel.new('text/plain')
50
- model_with_non_image_upload.expects(:uploaded_file).times(1).returns('dummy')
51
- model_with_non_image_upload.expects(:examine_attachment).times(1).raises(ImageProcessorError)
52
+ model_with_non_image_upload.expects(:uploaded_file).at_least(:once).returns(StringIO.new('dummy'))
53
+ model_with_non_image_upload.expects(:examine_image).times(1).raises(ImageProcessorError)
52
54
  model_with_non_image_upload.before_validate_attachment
53
55
  assert_equal 'text/plain', model_with_non_image_upload.content_type
54
56
 
55
57
  model_with_mislabelled_non_image_upload = SomeModel.new('image/png')
56
- model_with_mislabelled_non_image_upload.expects(:uploaded_file).times(1).returns('dummy')
57
- model_with_mislabelled_non_image_upload.expects(:examine_attachment).times(1).raises(ImageProcessorError)
58
+ model_with_mislabelled_non_image_upload.expects(:uploaded_file).at_least(:once).returns(StringIO.new('dummy'))
59
+ model_with_mislabelled_non_image_upload.expects(:examine_image).times(1).raises(ImageProcessorError)
58
60
  model_with_mislabelled_non_image_upload.before_validate_attachment
59
61
  assert_equal 'application/octet-stream', model_with_mislabelled_non_image_upload.content_type
60
62
  end
61
63
 
62
64
  def test_from_geometry_string
65
+ SomeModel.attachment_options = {}
63
66
  ImageOperations::geometry_strings.each do |geometry, expected_result|
64
67
  assert_equal expected_result, AttachmentSaver::Processors::Image.from_geometry_string(geometry), "geometry parse of #{geometry} produced incorrect results"
65
68
  end
@@ -8,6 +8,7 @@ module ImageProcessorTestModel
8
8
 
9
9
  def self.included(base)
10
10
  base.cattr_accessor :attachment_options
11
+ base.attachment_options = {}
11
12
  end
12
13
 
13
14
  def initialize(uploaded_data)
@@ -36,7 +37,7 @@ module ImageProcessorTests
36
37
  model = processor_model.new(File.open(fixture[:path], 'rb'))
37
38
  model.content_type = fixture[:content_type]
38
39
  model.original_filename = fixture[:original_filename]
39
- model.examine_attachment
40
+ model.examine_image
40
41
  assert_equal fixture[:expected_content_type], model.content_type
41
42
  assert_equal fixture[:width], model.width
42
43
  assert_equal fixture[:height], model.height
@@ -50,7 +51,7 @@ module ImageProcessorTests
50
51
  ImageFixtures.all_unreadable.each do |fixture|
51
52
  model = processor_model.new(File.open(fixture[:path], 'rb'))
52
53
  model.content_type = fixture[:content_type]
53
- assert_raises(processor_exception) { model.examine_attachment }
54
+ assert_raises(processor_exception) { model.examine_image }
54
55
  assert_equal fixture[:expected_content_type], model.content_type
55
56
  assert_equal nil, model.width
56
57
  assert_equal nil, model.height
@@ -61,6 +62,15 @@ module ImageProcessorTests
61
62
  end
62
63
  end
63
64
 
65
+ def test_image_exploits
66
+ processor_model.attachment_options = {:valid_image_types => %w(image/png image/jpeg)}
67
+
68
+ model = processor_model.new(File.open(ImageFixtures.fixture_path('ssrf.png'), 'rb')) # actually a .mvg file
69
+ model.expects(:examine_attachment).times(0) # don't invoke the potentially vulnerable image processor code
70
+ model.before_validate_attachment
71
+ assert_not_equal 'image/png', model.content_type
72
+ end
73
+
64
74
  def test_derived_attributes_from_valid
65
75
  processor_model.attachment_options = {:formats => ImageOperations.resize_operations}
66
76
 
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'image_processor_test_common'))
2
2
  require 'processors/image_science'
3
3
 
4
- class ImageScienceProcessorTest < Test::Unit::TestCase
4
+ class ImageScienceProcessorTest < ActiveSupport::TestCase
5
5
  class ImageScienceTestModel
6
6
  include AttachmentSaver::InstanceMethods
7
7
  include AttachmentSaver::Processors::ImageScience
@@ -1,8 +1,8 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
- require 'mocha'
2
+ require 'mocha/test_unit'
3
3
  require 'datastores/in_column'
4
4
 
5
- class InColumnDatastoreTest < Test::Unit::TestCase
5
+ class InColumnDatastoreTest < ActiveSupport::TestCase
6
6
  attr_accessor :data, :original_filename, :content_type
7
7
 
8
8
  DEFAULT_ATTACHMENT_OPTIONS = {}
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'image_processor_test_common'))
2
2
  require 'processors/mini_magick'
3
3
 
4
- class MiniMagickProcessorTest < Test::Unit::TestCase
4
+ class MiniMagickProcessorTest < ActiveSupport::TestCase
5
5
  class MiniMagickTestModel
6
6
  include AttachmentSaver::InstanceMethods
7
7
  include AttachmentSaver::Processors::MiniMagick
data/test/model_test.rb CHANGED
@@ -28,7 +28,7 @@ class Unprocessed < ActiveRecord::Base
28
28
  end
29
29
 
30
30
  class LoadedImage < ActiveRecord::Base
31
- set_table_name 'images'
31
+ self.table_name = 'images'
32
32
  saves_attachment :processor => 'image_science' # don't create any derived images, but still process the image to get the attributes
33
33
  end
34
34
 
@@ -38,21 +38,21 @@ class AllInOneTableImages < ActiveRecord::Base
38
38
  end
39
39
 
40
40
  class ImageScienceImage < ActiveRecord::Base
41
- set_table_name 'images'
41
+ self.table_name = 'images'
42
42
  saves_attachment :processor => 'ImageScience', :formats => {:small => '200x200'}
43
43
  end
44
44
 
45
45
  class RMagickImage < ActiveRecord::Base
46
- set_table_name 'images'
46
+ self.table_name = 'images'
47
47
  saves_attachment :processor => 'RMagick', :formats => {:small => '200x200'}
48
48
  end
49
49
 
50
50
  class MiniMagickImage < ActiveRecord::Base
51
- set_table_name 'images'
51
+ self.table_name = 'images'
52
52
  saves_attachment :processor => 'RMagick', :formats => {:small => '200x200'}
53
53
  end
54
54
 
55
- class ModelTest < Test::Unit::TestCase
55
+ class ModelTest < ActiveSupport::TestCase
56
56
  module ValidUploadedFileAttributes
57
57
  def fixture=(value)
58
58
  @fixture = value
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'image_processor_test_common'))
2
2
  require 'processors/r_magick'
3
3
 
4
- class RMagickProcessorTest < Test::Unit::TestCase
4
+ class RMagickProcessorTest < ActiveSupport::TestCase
5
5
  class RMagickTestModel
6
6
  include AttachmentSaver::InstanceMethods
7
7
  include AttachmentSaver::Processors::RMagick
data/test/test_helper.rb CHANGED
@@ -7,17 +7,16 @@ end
7
7
  gem 'activesupport', ENV['RAILS_VERSION']
8
8
  gem 'activerecord', ENV['RAILS_VERSION']
9
9
 
10
- require 'test/unit'
10
+ require 'minitest/autorun'
11
11
  require 'active_support'
12
12
  require 'active_support/test_case'
13
13
  require 'active_record'
14
14
  require 'active_record/fixtures'
15
15
 
16
16
  begin
17
- require 'ruby-debug'
18
- Debugger.start
17
+ require 'byebug'
19
18
  rescue LoadError
20
- # ruby-debug not installed, no debugging for you
19
+ # no debugging for you
21
20
  end
22
21
 
23
22
  RAILS_ROOT = File.dirname(__FILE__)
@@ -42,8 +41,6 @@ load(File.join(File.dirname(__FILE__), "/schema.rb"))
42
41
 
43
42
  require File.expand_path(File.join(File.dirname(__FILE__), '../init')) # load the plugin
44
43
 
45
- at_exit do # at_exits are run in reverse of declaration order, and Test::Unit runs from an at_exit, so we must declare ours before that require below
44
+ at_exit do
46
45
  FileUtils.rm_rf(File.join(File.dirname(__FILE__), 'tmp'))
47
46
  end
48
-
49
- require 'test/unit'
metadata CHANGED
@@ -1,97 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attachment_saver
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Will Bryant
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-21 00:00:00.000000000 Z
11
+ date: 2016-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mimemagic
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - '>='
45
+ - - ">="
32
46
  - !ruby/object:Gem::Version
33
47
  version: '0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - '>='
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: image_science
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - '>='
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
61
  version: '0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - '>='
66
+ - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rmagick
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - '>='
73
+ - - ">="
60
74
  - !ruby/object:Gem::Version
61
75
  version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - '>='
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: mini_magick
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - '>='
87
+ - - ">="
74
88
  - !ruby/object:Gem::Version
75
89
  version: '0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - '>='
94
+ - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: sqlite3
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - '>='
101
+ - - ">="
88
102
  - !ruby/object:Gem::Version
89
103
  version: '0'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - '>='
108
+ - - ">="
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  description: |
@@ -103,19 +117,12 @@ description: |
103
117
  broken uploads leaving incomplete or corrupt data.
104
118
 
105
119
  RMagick, MiniMagick, and ImageScience image processors are supported.
106
-
107
-
108
- Compatibility
109
- =============
110
-
111
- Currently tested against Rails 3.2.13 and 3.1.8, on Ruby 1.8.7 and 2.0.0p0.
112
- Was also tested compatible with 2.3.14 and 3.0.17.
113
120
  email: will.bryant@gmail.com
114
121
  executables: []
115
122
  extensions: []
116
123
  extra_rdoc_files: []
117
124
  files:
118
- - .gitignore
125
+ - ".gitignore"
119
126
  - MIT-LICENSE
120
127
  - README
121
128
  - Rakefile
@@ -127,7 +134,6 @@ files:
127
134
  - lib/datastores/file_system.rb
128
135
  - lib/datastores/in_column.rb
129
136
  - lib/misc/extended_tempfile.rb
130
- - lib/misc/file_size.rb
131
137
  - lib/misc/image_science_extensions.rb
132
138
  - lib/misc/mini_magick_extensions.rb
133
139
  - lib/processors/image.rb
@@ -156,7 +162,8 @@ files:
156
162
  - test/schema.rb
157
163
  - test/test_helper.rb
158
164
  homepage: http://github.com/willbryant/attachment_saver
159
- licenses: []
165
+ licenses:
166
+ - MIT
160
167
  metadata: {}
161
168
  post_install_message:
162
169
  rdoc_options: []
@@ -164,17 +171,17 @@ require_paths:
164
171
  - lib
165
172
  required_ruby_version: !ruby/object:Gem::Requirement
166
173
  requirements:
167
- - - '>='
174
+ - - ">="
168
175
  - !ruby/object:Gem::Version
169
176
  version: '0'
170
177
  required_rubygems_version: !ruby/object:Gem::Requirement
171
178
  requirements:
172
- - - '>='
179
+ - - ">="
173
180
  - !ruby/object:Gem::Version
174
181
  version: '0'
175
182
  requirements: []
176
183
  rubyforge_project:
177
- rubygems_version: 2.0.2
184
+ rubygems_version: 2.2.5
178
185
  signing_key:
179
186
  specification_version: 4
180
187
  summary: Saves attachments in files, models, or columns.
@@ -1,5 +0,0 @@
1
- class File
2
- def size # for compatibility with StringIO & Tempfile
3
- stat.size
4
- end
5
- end