attachment_saver 1.3.0 → 1.4.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: c35a16fce5a99e7ed88cc052759edcfbe3888202
4
- data.tar.gz: 79cb33e50d35f9dd4828a42e07cb11781637e3eb
3
+ metadata.gz: 1ab301b6cb41a742a469e6570ee68098947546bf
4
+ data.tar.gz: b2b922db15fc14b957f9fe6c3ef3ad7493ab4f3a
5
5
  SHA512:
6
- metadata.gz: '0911d907f27e14f6f75c1e3c80dc70f492e465868de2f38c6f7325d52eb7fa79dbaef9007070be838da7ddf76d4302b64e59b41fa268f8c176ac32191cb7612d'
7
- data.tar.gz: 649583ca6636e12a6f3f4e03ea1a8ea71124c09f5c728f116b1765e4457cdbe8ef874800b5acdc4c3c08bdbdb346fc8f954b42ee1b8d6bb6a4802b9d43f5fe78
6
+ metadata.gz: 73d1c02e925c5855493f40c313cd5320d169cfc55da1a613cdf15c15484c74e1406db90c18fed8dcb9d728dd4e89b0938fbe2cf3da2e08b092001e383684366f
7
+ data.tar.gz: c7a870a119aca14f8fb6696841f13dc8fe6300eea0db95e317eb88cc6a0d226d5771d50d1ddd649b7198b9e8466dfeeaeb55e0aedf13cde0dd40cac9895b6e5f
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  test/log/*
2
2
  test/tmp/*
3
3
  test/attachment_saver_test_sqlite.db
4
+ samples.html
5
+ samples/
data/Gemfile CHANGED
@@ -9,3 +9,5 @@ gemspec
9
9
  # your gemspec. These might include edge Rails or gems from your path or
10
10
  # Git. Remember to move these dependencies to your gemspec before releasing
11
11
  # your gem to rubygems.org.
12
+
13
+ gem 'activerecord', ENV['RAILS_VERSION']
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- attachment_saver (1.2.0)
4
+ attachment_saver (1.4.0)
5
5
  activerecord
6
6
  mimemagic
7
7
 
@@ -11,19 +11,23 @@ GEM
11
11
  RubyInline (3.12.4)
12
12
  ZenTest (~> 4.3)
13
13
  ZenTest (4.11.1)
14
- activemodel (5.1.4)
15
- activesupport (= 5.1.4)
16
- activerecord (5.1.4)
17
- activemodel (= 5.1.4)
18
- activesupport (= 5.1.4)
19
- arel (~> 8.0)
20
- activesupport (5.1.4)
14
+ activemodel (5.2.0.beta2)
15
+ activesupport (= 5.2.0.beta2)
16
+ activerecord (5.2.0.beta2)
17
+ activemodel (= 5.2.0.beta2)
18
+ activesupport (= 5.2.0.beta2)
19
+ arel (>= 9.0)
20
+ activesupport (5.2.0.beta2)
21
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
22
22
  i18n (~> 0.7)
23
23
  minitest (~> 5.1)
24
24
  tzinfo (~> 1.1)
25
- arel (8.0.0)
25
+ arel (9.0.0)
26
26
  concurrent-ruby (1.0.5)
27
+ gdk_pixbuf2 (2.2.5)
28
+ glib2 (= 2.2.5)
29
+ glib2 (2.2.5)
30
+ pkg-config
27
31
  i18n (0.9.1)
28
32
  concurrent-ruby (~> 1.0)
29
33
  image_science (1.3.0)
@@ -32,9 +36,10 @@ GEM
32
36
  metaclass (0.0.4)
33
37
  mimemagic (0.3.2)
34
38
  mini_magick (4.8.0)
35
- minitest (5.10.3)
39
+ minitest (5.11.0)
36
40
  mocha (1.3.0)
37
41
  metaclass (~> 0.0.1)
42
+ pkg-config (1.2.8)
38
43
  rake (12.3.0)
39
44
  rmagick (2.16.0)
40
45
  sqlite3 (1.3.13)
@@ -46,7 +51,9 @@ PLATFORMS
46
51
  ruby
47
52
 
48
53
  DEPENDENCIES
54
+ activerecord
49
55
  attachment_saver!
56
+ gdk_pixbuf2
50
57
  image_science
51
58
  image_size
52
59
  mini_magick
@@ -56,4 +63,4 @@ DEPENDENCIES
56
63
  sqlite3
57
64
 
58
65
  BUNDLED WITH
59
- 1.15.3
66
+ 1.16.1
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 Will Bryant, Sekuda Ltd
1
+ Copyright (c) 2007-2018 Will Bryant, Sekuda Ltd
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README CHANGED
@@ -8,14 +8,16 @@ provided, and the architecture simplifies clean implementation of other types
8
8
  of processing. Errors are carefully handled to minimize the possibility of
9
9
  broken uploads leaving incomplete or corrupt data.
10
10
 
11
- RMagick, MiniMagick, and ImageScience image processors are supported.
11
+ RMagick, MiniMagick, ImageScience, and GdkPixbuf image processors are supported.
12
+
13
+ The pure-ruby ImageSize image processor is also supported (for inspecting images but not resizing them).
12
14
 
13
15
 
14
16
  Compatibility
15
17
  =============
16
18
 
17
- Currently tested against Rails 3.2.13 and 3.1.8, on Ruby 1.8.7 and 2.0.0p0.
18
- Was also tested compatible with 2.3.14 and 3.0.17.
19
+ Currently tested against Rails 5.2 (up to 5.2.0.beta2), 5.1 (up to 5.1.4), 5.0 (up to 5.0.6), and 4.2 (up to 4.2.10), on Ruby 2.3.6, 2.4.3, and 2.5.0.
20
+ Was also tested compatible with 2.3.14, 3.0.17, 3.1.8, 3.2.13, 4.2, and 5.0.
19
21
 
20
22
 
21
23
  Examples
@@ -116,7 +118,7 @@ A custom image-processing format using your image-processor's features
116
118
  ----------------------------------------------------------------------
117
119
 
118
120
  # in a file in your lib/ directory that's required in somewhere:
119
- module AttachmentSaver::Processors::RMagick::Operations # or MiniMagick::Operations or ImageScience::Operations - see lib/processors
121
+ module AttachmentSaver::Processors::RMagick::Operations # or MiniMagick::Operations or ImageScience::Operations or GdkPixbuf::Operations - see lib/processors
120
122
  # this module is mixed in to the actual image objects built by the processor, so you can call its' methods directly
121
123
  def wavy_black_and_white(wave_height, wave_length, &block)
122
124
  # RMagick returns the new object; MiniMagick acts on the same object (so you must dup); ImageScience yields; so, look at the existing lib/processors to see the appropriate pattern
@@ -33,6 +33,7 @@ EOF
33
33
  gem.add_development_dependency "rmagick"
34
34
  gem.add_development_dependency "mini_magick"
35
35
  gem.add_development_dependency "image_size"
36
+ gem.add_development_dependency "gdk_pixbuf2"
36
37
  gem.add_development_dependency "sqlite3"
37
38
  gem.add_development_dependency "mocha"
38
39
  end
@@ -1,3 +1,3 @@
1
1
  module AttachmentSaver
2
- VERSION = '1.3.0'
2
+ VERSION = '1.4.0'
3
3
  end
@@ -0,0 +1,106 @@
1
+ require 'gdk_pixbuf2'
2
+ require 'misc/extended_tempfile'
3
+ require 'processors/image'
4
+
5
+ class GdkPixbufProcessorError < ImageProcessorError; end
6
+
7
+ module AttachmentSaver
8
+ module Processors
9
+ module GdkPixbuf
10
+ include Image
11
+
12
+ def with_image(filename, &block)
13
+ # we use Gdk::PixbufLoader rather than Gdk::Pixbuf.new(filename) so that we can learn the format of the
14
+ # image, which process_image wants to know so that it can save the derived images in the same format.
15
+ loader = Gdk::PixbufLoader.new
16
+ File.open(filename, "rb") do |file|
17
+ while buf = file.read(65536)
18
+ loader.write(buf)
19
+ end
20
+ end
21
+ loader.close
22
+ image = loader.pixbuf
23
+ image.extend(Operations)
24
+ image.format = loader.format.name
25
+ block.call(image)
26
+ end
27
+
28
+ def examine_image
29
+ fileinfo, width, height = Gdk::Pixbuf.get_file_info(uploaded_file_path)
30
+ raise GdkPixbufProcessorError, "Not an image" if fileinfo.nil?
31
+
32
+ self.width = width if respond_to?(:width)
33
+ self.height = height if respond_to?(:height)
34
+ self.content_type = fileinfo.mime_types.first unless self.class.attachment_options[:keep_content_type] || fileinfo.mime_types.empty?
35
+ self.file_extension = normalize_extension(fileinfo.extensions.first) unless self.class.attachment_options[:keep_file_extension] || fileinfo.extensions.empty?
36
+ rescue AttachmentSaverError
37
+ raise
38
+ rescue Exception => ex
39
+ raise GdkPixbufProcessorError, "#{ex.class}: #{ex.message}", ex.backtrace
40
+ end
41
+
42
+ def normalize_extension(extension)
43
+ case extension
44
+ when 'jpeg' then 'jpg'
45
+ else extension
46
+ end
47
+ end
48
+
49
+ def process_image(original_image, derived_format_name, resize_format)
50
+ resize_format = Image.from_geometry_string(resize_format) if resize_format.is_a?(String)
51
+
52
+ result = original_image.send(*resize_format) do |derived_image|
53
+ return nil unless want_format?(derived_format_name, derived_image.width, derived_image.height)
54
+
55
+ # both original_filename and content_type must be defined for parents when using image processing
56
+ # - but apps can just define them using attr_accessor if they don't want them persisted to db
57
+ derived_content_type = content_type
58
+ derived_extension = derived_image.file_type_extension
59
+
60
+ # we leverage tempfiles as discussed in the uploaded_file method
61
+ temp = ExtendedTempfile.new("asgtemp", tempfile_directory, derived_extension)
62
+ temp.binmode
63
+ temp.close
64
+ derived_image.save(temp.path, original_image.format)
65
+ temp.open # we close & reopen so we see the file the processor wrote to, even if it created a new file rather than writing into our tempfile
66
+
67
+ { :format_name => derived_format_name.to_s,
68
+ :width => derived_image.width,
69
+ :height => derived_image.height,
70
+ :content_type => derived_content_type,
71
+ :file_extension => derived_extension,
72
+ :uploaded_data => temp }
73
+ end
74
+
75
+ result
76
+ end
77
+
78
+ module Operations
79
+ include AttachmentSaver::Processors::Image::Operations
80
+
81
+ attr_accessor :format
82
+
83
+ def file_type_extension
84
+ case format
85
+ when 'jpeg' then 'jpg'
86
+ else format.downcase
87
+ end
88
+ end
89
+
90
+ def resize_to(new_width, new_height, &block)
91
+ image = scale(new_width, new_height)
92
+ image.extend Operations
93
+ image.format = format
94
+ block.call(image)
95
+ end
96
+
97
+ def crop_to(new_width, new_height, &block) # crops to the center
98
+ image = Gdk::Pixbuf.new(self, (width - new_width)/2, (height - new_height)/2, new_width, new_height)
99
+ image.extend Operations
100
+ image.format = format
101
+ block.call(image)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -132,7 +132,7 @@ module AttachmentSaver
132
132
  module Operations
133
133
  # if they choose to use this module to implement the resize operations, the processor
134
134
  # module just needs to implement width, height, resize_to(new_width, new_height, &block),
135
- # and crop_to(new_width, new_height, &block)
135
+ # and crop_to(new_width, new_height, &block). they also need with_image for process_attachment.
136
136
 
137
137
  # squishes the image to the given width and height, without preserving the aspect ratio.
138
138
  # yields this image itself if it is already the given size.
@@ -0,0 +1,42 @@
1
+ require 'image_size'
2
+ require 'misc/extended_tempfile'
3
+ require 'processors/image'
4
+
5
+ class ImageSizeProcessorError < ImageProcessorError; end
6
+
7
+ module AttachmentSaver
8
+ module Processors
9
+ module ImageSize
10
+ include Image
11
+
12
+ def examine_image
13
+ image_size = ::ImageSize.path(uploaded_file_path)
14
+ raise ImageSizeProcessorError, "Not an image" if image_size.format.nil?
15
+
16
+ self.width = image_size.width if respond_to?(:width)
17
+ self.height = image_size.height if respond_to?(:height)
18
+ self.file_extension = extension_for_image_format(image_size.format) unless self.class.attachment_options[:keep_file_extension]
19
+ self.content_type = mime_type_for_image_format(image_size.format) unless self.class.attachment_options[:keep_content_type]
20
+ rescue AttachmentSaverError
21
+ raise
22
+ rescue Exception => ex
23
+ raise ImageSizeProcessorError, "#{ex.class}: #{ex.message}", ex.backtrace
24
+ end
25
+
26
+ def extension_for_image_format(format)
27
+ case format
28
+ when :jpeg then 'jpg'
29
+ else format.to_s
30
+ end
31
+ end
32
+
33
+ def mime_type_for_image_format(format)
34
+ "image/#{format}"
35
+ end
36
+
37
+ def with_image(*args)
38
+ raise NotImplementedError, "the image_size processor can only be used to check image types and dimensions, not produce resized images"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fileutils'
3
+ require 'active_record'
4
+ require 'active_support/inflector'
5
+ require 'attachment_saver'
6
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test', 'image_operations'))
7
+
8
+ sample_dir = File.expand_path(File.join(File.dirname(__FILE__), 'samples'))
9
+ FileUtils.rm_r(sample_dir)
10
+ FileUtils.mkdir(sample_dir)
11
+
12
+ original_filenames = %w(test/fixtures/test.jpg test/fixtures/pd.png)
13
+
14
+ processors = %w(ImageScience RMagick MiniMagick GdkPixbuf).each.with_object({}) do |processor, results|
15
+ require "processors/#{processor.underscore}"
16
+
17
+ instance = Object.new
18
+ instance.class_eval { attr_accessor :content_type }
19
+ instance.extend(AttachmentSaver::InstanceMethods)
20
+ instance.extend(AttachmentSaver::Processors.const_get(processor))
21
+
22
+ results[processor] = instance
23
+ end
24
+
25
+ File.open("samples.html", "w") do |html|
26
+ html.write "<html><body>"
27
+
28
+ original_filenames.each do |original_filename|
29
+ html.write "<h1>#{original_filename}</h1><table border='2'><tr><th></th>"
30
+ processors.each do |processor, instance|
31
+ html.write "<th>#{processor}</th>"
32
+ end
33
+ html.write "</tr>"
34
+
35
+ ImageOperations.resize_operations.each do |derived_format_name, format_definition|
36
+ html.write "<tr><th>#{derived_format_name}<br/><pre>#{format_definition.inspect}</pre></th>"
37
+ processors.each do |processor, instance|
38
+ instance.with_image(original_filename) do |original_image|
39
+ result = instance.process_image(original_image, derived_format_name, format_definition)
40
+
41
+ filename = "#{sample_dir}/#{processor.underscore}-#{File.basename original_filename}-#{result[:format_name]}.#{result[:file_extension]}"
42
+ File.open(filename, "wb") do |f|
43
+ result[:uploaded_data].rewind
44
+ IO.copy_stream(result[:uploaded_data], f)
45
+ end
46
+ size = result[:uploaded_data].size < 1024 ? "#{result[:uploaded_data].size} bytes" : "%0.1fkb" % (result[:uploaded_data].size/1024.0)
47
+ html.write "<td><img src='#{filename}' width='#{result[:width]}' height='#{result[:height]}'><br/>#{size}</td>"
48
+ end
49
+ end
50
+ html.write "</tr>"
51
+ end
52
+
53
+ html.write "</table>"
54
+ end
55
+
56
+ html.write "</html></body>"
57
+ end
Binary file
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'image_processor_test_common'))
2
+ require 'processors/gdk_pixbuf'
3
+
4
+ class GdkPixbufProcessorTest < ActiveSupport::TestCase
5
+ class GdkPixbufTestModel
6
+ include AttachmentSaver::InstanceMethods
7
+ include AttachmentSaver::Processors::GdkPixbuf
8
+ include ImageProcessorTestModel
9
+ end
10
+
11
+ def processor_model
12
+ GdkPixbufTestModel
13
+ end
14
+
15
+ def processor_exception
16
+ GdkPixbufProcessorError
17
+ end
18
+
19
+ include ImageProcessorTests
20
+ end
@@ -40,7 +40,8 @@ class ImageOperations
40
40
  :scaletocover2 => [:scale_to_cover, 720, 900],
41
41
 
42
42
  :coverandcrop1 => [:cover_and_crop, 200, 300],
43
- :coverandcrop2 => [:cover_and_crop, 720, 900],
43
+ :coverandcrop2 => [:cover_and_crop, 300, 200],
44
+ :coverandcrop3 => [:cover_and_crop, 720, 900],
44
45
  }
45
46
  end
46
47
 
@@ -75,7 +76,8 @@ class ImageOperations
75
76
  :scaletocover2 => [720, 720*600/448],
76
77
 
77
78
  :coverandcrop1 => [200, 300],
78
- :coverandcrop2 => [720, 900],
79
+ :coverandcrop2 => [300, 200],
80
+ :coverandcrop3 => [720, 900],
79
81
  }
80
82
  end
81
83
 
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'image_processor_test_common'))
2
+ require 'processors/image_size'
3
+
4
+ class ImageSizeProcessorTest < ActiveSupport::TestCase
5
+ class ImageSizeTestModel
6
+ include AttachmentSaver::InstanceMethods
7
+ include AttachmentSaver::Processors::ImageSize
8
+ include ImageProcessorTestModel
9
+ end
10
+
11
+ def processor_model
12
+ ImageSizeTestModel
13
+ end
14
+
15
+ def processor_exception
16
+ ImageSizeProcessorError
17
+ end
18
+
19
+ include ImageProcessorTests
20
+
21
+ def processes_images?
22
+ false
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ for version in 4.2.10 5.0.6 5.1.4 5.2.0.beta2
6
+ do
7
+ RAILS_VERSION=$version bundle update activerecord
8
+ bundle exec rake
9
+ done
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attachment_saver
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.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: 2017-12-20 00:00:00.000000000 Z
11
+ date: 2018-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: gdk_pixbuf2
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: sqlite3
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -166,25 +180,31 @@ files:
166
180
  - lib/misc/extended_tempfile.rb
167
181
  - lib/misc/image_science_extensions.rb
168
182
  - lib/misc/mini_magick_extensions.rb
183
+ - lib/processors/gdk_pixbuf.rb
169
184
  - lib/processors/image.rb
170
185
  - lib/processors/image_science.rb
186
+ - lib/processors/image_size.rb
171
187
  - lib/processors/mini_magick.rb
172
188
  - lib/processors/r_magick.rb
189
+ - samples.rb
173
190
  - test/attachment_saver_test.rb
174
191
  - test/database.yml
175
192
  - test/file_system_datastore_test.rb
176
193
  - test/fixtures/broken.jpg
177
194
  - test/fixtures/emptyextension.
178
195
  - test/fixtures/noextension
196
+ - test/fixtures/pd.png
179
197
  - test/fixtures/ssrf.png
180
198
  - test/fixtures/test.jpg
181
199
  - test/fixtures/test.js
182
200
  - test/fixtures/wrongextension.png
201
+ - test/gdk_pixbuf_processor_test.rb
183
202
  - test/image_fixtures.rb
184
203
  - test/image_operations.rb
185
204
  - test/image_processor_test.rb
186
205
  - test/image_processor_test_common.rb
187
206
  - test/image_science_processor_test.rb
207
+ - test/image_size_processor_test.rb
188
208
  - test/in_column_datastore_test.rb
189
209
  - test/mini_magick_processor_test.rb
190
210
  - test/model_test.rb
@@ -192,6 +212,7 @@ files:
192
212
  - test/rmagick_processor_test.rb
193
213
  - test/schema.rb
194
214
  - test/test_helper.rb
215
+ - test_all.sh
195
216
  homepage: http://github.com/willbryant/attachment_saver
196
217
  licenses:
197
218
  - MIT
@@ -223,15 +244,18 @@ test_files:
223
244
  - test/fixtures/broken.jpg
224
245
  - test/fixtures/emptyextension.
225
246
  - test/fixtures/noextension
247
+ - test/fixtures/pd.png
226
248
  - test/fixtures/ssrf.png
227
249
  - test/fixtures/test.jpg
228
250
  - test/fixtures/test.js
229
251
  - test/fixtures/wrongextension.png
252
+ - test/gdk_pixbuf_processor_test.rb
230
253
  - test/image_fixtures.rb
231
254
  - test/image_operations.rb
232
255
  - test/image_processor_test.rb
233
256
  - test/image_processor_test_common.rb
234
257
  - test/image_science_processor_test.rb
258
+ - test/image_size_processor_test.rb
235
259
  - test/in_column_datastore_test.rb
236
260
  - test/mini_magick_processor_test.rb
237
261
  - test/model_test.rb