scale_down 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.rdoc +7 -1
- data/config_sample.ru +5 -0
- data/lib/scale_down/configuration.rb +40 -0
- data/lib/scale_down/controller.rb +18 -4
- data/lib/scale_down/image.rb +24 -6
- data/lib/scale_down/version.rb +1 -1
- data/lib/scale_down.rb +4 -4
- data/test/scale_down/configuration_test.rb +13 -0
- data/test/scale_down/controller_test.rb +1 -0
- data/test/scale_down/image_test.rb +34 -1
- metadata +7 -5
- data/gen_tags +0 -2
data/README.rdoc
CHANGED
@@ -47,6 +47,10 @@ Create a rackup file (config.ru)
|
|
47
47
|
|
48
48
|
# The root path to the images. Use a symlink if it is helpful
|
49
49
|
config.root_path = File.expand_path(File.dirname(__FILE__))+"/public"
|
50
|
+
|
51
|
+
# The public path for serving static(scaled) images, probably identical to the above.
|
52
|
+
config.public_path = File.expand_path(File.dirname(__FILE__))+"/public"
|
53
|
+
|
50
54
|
end
|
51
55
|
|
52
56
|
run ScaleDown::Controller
|
@@ -65,9 +69,11 @@ In your application with the images you will need to generate the URL for the im
|
|
65
69
|
# ie scaled_image_src('/images/picture.png/400x300-cropped')
|
66
70
|
def scaled_image_src(url)
|
67
71
|
hmac = HMAC::SHA1.new("secret").update(url).to_s[0...8]
|
68
|
-
"http://images.myserver.com#{url}/#{hmac}"
|
72
|
+
"http://images.myserver.com#{URI.encode(url)}/#{hmac}"
|
69
73
|
end
|
70
74
|
|
75
|
+
Files names might require URI encoding. This should be done after generating the HMAC.
|
76
|
+
|
71
77
|
Of course this could be done in PHP, Python, or whatever language your application is running.
|
72
78
|
|
73
79
|
== TODO
|
data/config_sample.ru
CHANGED
@@ -14,6 +14,11 @@ ScaleDown.tap do |config|
|
|
14
14
|
|
15
15
|
# The root path to the images
|
16
16
|
config.root_path = File.expand_path(File.dirname(__FILE__))+"/public"
|
17
|
+
|
18
|
+
# The location of the public directory for serving static files
|
19
|
+
# This might be redudant since it will always, maybe, maybe not, be the same as root_path
|
20
|
+
config.public_path = "#{File.expand_path(File.dirname(__FILE__))}/public"
|
21
|
+
|
17
22
|
end
|
18
23
|
|
19
24
|
run ScaleDown::Controller
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ScaleDown
|
2
|
+
class << self
|
3
|
+
|
4
|
+
# Defines the method to use for generating an HMAC
|
5
|
+
# For example
|
6
|
+
# ScaleDown.hmac_method = HMAC::SHA2
|
7
|
+
attr_accessor :hmac_method
|
8
|
+
|
9
|
+
# The shared secret for generating the hmac
|
10
|
+
attr_accessor :hmac_key
|
11
|
+
|
12
|
+
# How many characters of the HMAC are used for validation
|
13
|
+
attr_accessor :hmac_length
|
14
|
+
|
15
|
+
# An array of the max width and height an image can be scaled, in pixels.
|
16
|
+
# [800,600] would limit scaling operations to 800px wide by 600px tall
|
17
|
+
# Default [1200,1200]
|
18
|
+
attr_accessor :max_dimensions
|
19
|
+
|
20
|
+
# The max file size allowed for the file to be scaled, in bytes
|
21
|
+
# Defaults to 10 * 1_048_576
|
22
|
+
attr_accessor :max_file_size
|
23
|
+
|
24
|
+
# The location of the public path for you application
|
25
|
+
# +Must be set+
|
26
|
+
attr_accessor :public_path
|
27
|
+
def public_path=(str)
|
28
|
+
@public_path = str
|
29
|
+
ScaleDown::Controller.public = str
|
30
|
+
end
|
31
|
+
|
32
|
+
# The path the root of the images directory
|
33
|
+
attr_accessor :root_path
|
34
|
+
|
35
|
+
# Defaults
|
36
|
+
ScaleDown.max_file_size = 10 * 1_048_576
|
37
|
+
ScaleDown.max_dimensions = [1200,1200]
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -3,17 +3,31 @@ class ScaleDown::Controller < Sinatra::Application
|
|
3
3
|
set :raise_errors, true
|
4
4
|
set :show_exceptions, false
|
5
5
|
set :static, true
|
6
|
-
set :public, "/Users/johnweir/Sites/famedriver/site/public"
|
7
6
|
|
8
7
|
get '/' do
|
9
8
|
"<b>ScaleDown version #{ScaleDown::VERSION}<b/>"
|
10
9
|
end
|
11
10
|
|
12
|
-
get '/*/:filename/:geometry/:hmac'
|
11
|
+
# get '/*/:filename/:geometry/:hmac'
|
12
|
+
# is what I want, but
|
13
|
+
# this fails when the URL includes things like %23 (an encoded hash tag)
|
14
|
+
get '/*' do
|
15
|
+
parts = params[:splat].join("/").split("/")
|
16
|
+
|
17
|
+
params = {
|
18
|
+
:hmac => parts.pop,
|
19
|
+
:geometry => parts.pop,
|
20
|
+
:filename => parts.pop,
|
21
|
+
:splat => parts
|
22
|
+
}
|
23
|
+
|
13
24
|
path, status = scaler(params)
|
25
|
+
|
26
|
+
# TODO Eh? Shouldn't it be if 301
|
14
27
|
unless status == 403
|
15
|
-
redirect path, status
|
28
|
+
redirect URI.encode(path), status
|
16
29
|
else
|
30
|
+
# TODO error messages which explain what went wrong
|
17
31
|
[status, "Error: this image could not be processed"]
|
18
32
|
end
|
19
33
|
end
|
@@ -22,7 +36,7 @@ class ScaleDown::Controller < Sinatra::Application
|
|
22
36
|
def scaler(params)
|
23
37
|
ScaleDown::Scaler.process \
|
24
38
|
:path => params[:splat].join("/"),
|
25
|
-
:filename => params[:filename],
|
39
|
+
:filename => URI.decode(params[:filename]),
|
26
40
|
:geometry => params[:geometry],
|
27
41
|
:hmac => params[:hmac]
|
28
42
|
end
|
data/lib/scale_down/image.rb
CHANGED
@@ -1,15 +1,32 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
|
3
3
|
class ScaleDown::Image
|
4
|
+
|
4
5
|
include Magick
|
5
6
|
|
6
7
|
class << self
|
8
|
+
|
7
9
|
def scale(properties)
|
8
10
|
new(properties).valid?
|
9
11
|
end
|
10
|
-
|
12
|
+
|
11
13
|
def geometry(properties)
|
12
|
-
Magick::Geometry.new(properties[:width], properties[:height], nil, nil, ">")
|
14
|
+
validate_geometry Magick::Geometry.new(properties[:width], properties[:height], nil, nil, ">")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Ensures that the dimensions are not both 'auto' and within the max dimensions
|
18
|
+
def validate_geometry(geometry)
|
19
|
+
geometry.tap do |g|
|
20
|
+
total = g.width + g.height
|
21
|
+
raise ScaleDown::InvalidGeometry if total == 0
|
22
|
+
raise ScaleDown::InvalidGeometry if g.width > ScaleDown.max_dimensions[0] || g.height > ScaleDown.max_dimensions[1]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate_file_size(file_path)
|
27
|
+
unless File.size(file_path) < ScaleDown.max_file_size
|
28
|
+
raise ScaleDown::FileSizeTooLarge
|
29
|
+
end
|
13
30
|
end
|
14
31
|
end
|
15
32
|
|
@@ -23,13 +40,14 @@ class ScaleDown::Image
|
|
23
40
|
save if @file
|
24
41
|
end
|
25
42
|
|
26
|
-
def load_file(
|
43
|
+
def load_file(file_path)
|
44
|
+
self.class.validate_file_size(file_path)
|
27
45
|
begin
|
28
|
-
Magick::Image.read(
|
46
|
+
Magick::Image.read(file_path).first
|
29
47
|
rescue Magick::ImageMagickError => e
|
30
48
|
return nil
|
31
49
|
end
|
32
|
-
end
|
50
|
+
end
|
33
51
|
|
34
52
|
def geometry(properties)
|
35
53
|
self.class.geometry properties
|
@@ -41,7 +59,7 @@ class ScaleDown::Image
|
|
41
59
|
|
42
60
|
protected
|
43
61
|
|
44
|
-
def save
|
62
|
+
def save
|
45
63
|
path = Pathname.new(@out).dirname.to_s
|
46
64
|
FileUtils.mkdir_p path unless FileTest.directory? path
|
47
65
|
resize
|
data/lib/scale_down/version.rb
CHANGED
data/lib/scale_down.rb
CHANGED
@@ -7,15 +7,15 @@ require 'RMagick'
|
|
7
7
|
require 'hmac-sha1'
|
8
8
|
|
9
9
|
module ScaleDown
|
10
|
+
require 'scale_down/configuration'
|
10
11
|
require 'scale_down/version'
|
11
12
|
require 'scale_down/controller'
|
12
13
|
require 'scale_down/scaler'
|
13
14
|
require 'scale_down/image'
|
14
15
|
|
15
|
-
class
|
16
|
-
|
17
|
-
|
18
|
-
end
|
16
|
+
class InvalidGeometry < Exception; end
|
17
|
+
class FileSizeTooLarge < Exception; end
|
18
|
+
|
19
19
|
|
20
20
|
def self.valid_hmac?(params)
|
21
21
|
str = ["/",params[:path], "/", params[:filename], "/", params[:geometry]].join
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__))+'/../test_helper'
|
2
|
+
|
3
|
+
class ScaleDown::Test < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Configuration" do
|
6
|
+
context "public_path" do
|
7
|
+
should "set the controller's public setting" do
|
8
|
+
ScaleDown.public_path = "/tmp/directory"
|
9
|
+
assert_equal "/tmp/directory", ScaleDown::Controller.public
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -43,7 +43,7 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
43
43
|
assert_equal 400, geo.height
|
44
44
|
end
|
45
45
|
|
46
|
-
should "auto scale" do
|
46
|
+
should "auto scale any one dimensions" do
|
47
47
|
assert create \
|
48
48
|
tests_path("files/graphic.png"),
|
49
49
|
tests_path("scaled_test/graphic_scaled.png"),
|
@@ -53,6 +53,24 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
53
53
|
assert_equal 150, image.rows
|
54
54
|
assert_equal 75, image.columns
|
55
55
|
end
|
56
|
+
|
57
|
+
should "return nil if both dimensions are 'auto'" do
|
58
|
+
assert_raises ScaleDown::InvalidGeometry do
|
59
|
+
ScaleDown::Image.geometry :width => "auto", :height => "auto"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
should "raise an error if either dimension is outside of the ScaleDown.max_dimensions" do
|
64
|
+
ScaleDown.max_dimensions = [1200,1200]
|
65
|
+
|
66
|
+
assert_raises ScaleDown::InvalidGeometry do
|
67
|
+
ScaleDown::Image.geometry :width => 1300, :height => 900
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_raises ScaleDown::InvalidGeometry do
|
71
|
+
ScaleDown::Image.geometry :width => 900, :height => 1300
|
72
|
+
end
|
73
|
+
end
|
56
74
|
end
|
57
75
|
|
58
76
|
context "an invalid file" do
|
@@ -72,6 +90,21 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
72
90
|
end
|
73
91
|
end
|
74
92
|
|
93
|
+
context "a file larger than the MAX_SIZE" do
|
94
|
+
setup do
|
95
|
+
File.expects(:size).with(tests_path("files/graphic.png")).at_least_once.returns(50 * 1_048_576)
|
96
|
+
end
|
97
|
+
|
98
|
+
should "raise an exception" do
|
99
|
+
assert_raises ScaleDown::FileSizeTooLarge do
|
100
|
+
@subject = create \
|
101
|
+
tests_path("files/graphic.png"),
|
102
|
+
tests_path("scaled_test/graphic_scaled.png"),
|
103
|
+
{ :width => 100, :height => 105 }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
75
108
|
context "cropping" do
|
76
109
|
setup do
|
77
110
|
@subject = create \
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scale_down
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- John Weir
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-23 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -130,8 +130,8 @@ files:
|
|
130
130
|
- Rakefile
|
131
131
|
- color_profiles/sRGB.icm
|
132
132
|
- config_sample.ru
|
133
|
-
- gen_tags
|
134
133
|
- lib/scale_down.rb
|
134
|
+
- lib/scale_down/configuration.rb
|
135
135
|
- lib/scale_down/controller.rb
|
136
136
|
- lib/scale_down/image.rb
|
137
137
|
- lib/scale_down/scaler.rb
|
@@ -141,6 +141,7 @@ files:
|
|
141
141
|
- test/files/graphic.png
|
142
142
|
- test/files/invalid_jpeg.jpg
|
143
143
|
- test/files/orient.jpg
|
144
|
+
- test/scale_down/configuration_test.rb
|
144
145
|
- test/scale_down/controller_test.rb
|
145
146
|
- test/scale_down/image_test.rb
|
146
147
|
- test/scale_down/scaler_test.rb
|
@@ -186,6 +187,7 @@ test_files:
|
|
186
187
|
- test/files/graphic.png
|
187
188
|
- test/files/invalid_jpeg.jpg
|
188
189
|
- test/files/orient.jpg
|
190
|
+
- test/scale_down/configuration_test.rb
|
189
191
|
- test/scale_down/controller_test.rb
|
190
192
|
- test/scale_down/image_test.rb
|
191
193
|
- test/scale_down/scaler_test.rb
|
data/gen_tags
DELETED