rack-bouncer 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  pkg/*
2
2
  .DS_Store
3
3
  *.gem
4
+ *.tmproj
data/README.md CHANGED
@@ -4,13 +4,14 @@ A Rack middleware that expels undesirable browsers out of your website. This pro
4
4
 
5
5
  | _Browser_ | _Undesirable Versions_ |
6
6
  |-------------------|------------------------|
7
- | Internet Explorer | < 8 |
7
+ | Internet Explorer | < 8.0 |
8
+ | Firefox | < 4.0 |
8
9
  | AOL | All |
9
10
 
10
11
  ## usage
11
12
 
12
13
  gem install rack-bouncer
13
- require "rack/bouncer"
14
+ require "rack-bouncer"
14
15
 
15
16
  The default redirects users to [Browse Happy](http://browsehappy.com/):
16
17
 
@@ -24,11 +25,15 @@ You can redirect users to a URL as well:
24
25
 
25
26
  use Rack::Bouncer, :redirect => "http://slashdot.org"
26
27
 
27
- You can even specify a minimum version of IE like so:
28
+ You can specify a minimum version of IE like so:
28
29
 
29
30
  use Rack::Bouncer, :redirect => "http://slashdot.org", :minimum_ie => 6.0
30
31
 
31
- You can even specify a set of safe paths:
32
+ You can specify a minimum version of Firefox like so:
33
+
34
+ use Rack::Bouncer, :redirect => "http://slashdot.org", :minimum_firefox => 3.6
35
+
36
+ You can specify a set of safe paths:
32
37
 
33
38
  use Rack::Bouncer, :safe_paths => ["/asset", "/images", "/stylesheets", "/javascripts", "/feedback"]
34
39
 
@@ -0,0 +1,2 @@
1
+ # encoding: UTF-8
2
+ require "rack/bouncer"
data/lib/rack/bouncer.rb CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  module Rack
4
4
  class Bouncer
5
- VERSION = "1.2.1"
5
+ VERSION = "1.3.0"
6
6
 
7
7
  DEFAULT_OPTIONS = {
8
- :safe_paths => ["/asset", "/images", "/stylesheets", "/javascripts", "/feedback"],
9
- :redirect => "http://browsehappy.com/",
10
- :minimum_ie => 8.0
8
+ :safe_paths => ["/asset", "/images", "/stylesheets", "/javascripts", "/feedback"],
9
+ :redirect => "http://browsehappy.com/",
10
+ :minimum_ie => 8.0,
11
+ :minimum_firefox => 4.0
11
12
  }
12
13
 
13
14
  def initialize(app, options = {})
@@ -16,49 +17,76 @@ module Rack
16
17
  end
17
18
 
18
19
  def call(env)
19
- if !safe_path(env) && (ie6_found_in?(env) || aol_found_in?(env))
20
- kick_it
21
- else
22
- @app.call(env)
20
+ return @app.call(env) if safe_path?(env)
21
+ return @app.call(env) if user_agent_blank?(env)
22
+
23
+ user_agent = env["HTTP_USER_AGENT"]
24
+
25
+ if undesirable_ie_present?(user_agent) ||
26
+ undesirable_aol_present?(user_agent) ||
27
+ undesirable_firefox_present?(user_agent)
28
+ return kick_it
23
29
  end
30
+
31
+ @app.call(env)
24
32
  end
25
33
 
26
34
  private
27
35
 
28
- def safe_path(env)
29
- path = env["PATH_INFO"]
30
- safe_paths = @options[:safe_paths].join("|")
36
+ def safe_path?(env)
37
+ return true if @options[:redirect] == env["PATH_INFO"]
38
+ return env["PATH_INFO"] =~ Regexp.new("^(#{@options[:safe_paths].join("|")})")
39
+ end
31
40
 
32
- path == @options[:redirect] || path =~ Regexp.new("^(#{safe_paths})")
41
+ def user_agent_blank?(env)
42
+ env["HTTP_USER_AGENT"].nil? || env["HTTP_USER_AGENT"].empty?
33
43
  end
34
44
 
35
- def ie6_found_in?(env)
36
- if env["HTTP_USER_AGENT"]
37
- is_ie?(env["HTTP_USER_AGENT"]) and ie_version(env["HTTP_USER_AGENT"]) < @options[:minimum_ie] and @options[:redirect] != env["PATH_INFO"]
38
- end
45
+ def kick_it
46
+ [302, {"Location" => @options[:redirect], "Content-Type" => "text/html"}, "Browser not supported"]
47
+ end
48
+
49
+ # Internet Explorer
50
+ ###############################################################################################
51
+
52
+ def undesirable_ie_present?(user_agent)
53
+ is_ie?(user_agent) && ie_version(user_agent) < @options[:minimum_ie]
39
54
  end
40
55
 
41
- def is_ie?(ua_string)
56
+ def is_ie?(user_agent)
42
57
  # We need at least one digit to be able to get the version, hence the \d
43
- ua_string.match(/MSIE \d/) ? true : false
58
+ user_agent.match(/MSIE \d/) ? true : false
44
59
  end
45
60
 
46
- def aol_found_in?(env)
47
- if env["HTTP_USER_AGENT"]
48
- is_aol?(env["HTTP_USER_AGENT"])
49
- end
61
+ def ie_version(user_agent)
62
+ user_agent.match(/MSIE (\S+)/)[1].to_f
50
63
  end
51
64
 
52
- def is_aol?(ua_string)
53
- ua_string.match(/AOL \d/) ? true : false
65
+ # AOL
66
+ ###############################################################################################
67
+
68
+ def undesirable_aol_present?(user_agent)
69
+ is_aol?(user_agent)
54
70
  end
55
71
 
56
- def ie_version(ua_string)
57
- ua_string.match(/MSIE (\S+)/)[1].to_f
72
+ def is_aol?(user_agent)
73
+ user_agent.match(/AOL \d/) ? true : false
58
74
  end
59
75
 
60
- def kick_it
61
- [302, {"Location" => @options[:redirect], "Content-Type" => "text/html"}, "Browser not supported"]
76
+ # Firefox
77
+ ###############################################################################################
78
+
79
+ def undesirable_firefox_present?(user_agent)
80
+ is_firefox?(user_agent) && firefox_version(user_agent) < @options[:minimum_firefox]
81
+ end
82
+
83
+ def is_firefox?(user_agent)
84
+ # We need at least one digit to be able to get the version, hence the \d
85
+ user_agent.match(/Firefox\/\d/) ? true : false
86
+ end
87
+
88
+ def firefox_version(user_agent)
89
+ user_agent.match(/Firefox\/(\S+)/)[1].to_f
62
90
  end
63
91
  end
64
92
  end
data/rack-bouncer.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
5
5
  s.name = "rack-bouncer"
6
6
  s.version = Rack::Bouncer::VERSION
7
7
  s.platform = Gem::Platform::RUBY
8
- s.authors = ["Jerod Santo", "Julio Cesar Ody", "Will Jessop", "Ryan Sobol"]
8
+ s.authors = ["Julio Cesar Ody", "Jerod Santo", "Will Jessop", "Ryan Sobol"]
9
9
  s.email = "contact@ryansobol.com"
10
10
  s.homepage = "https://github.com/ryansobol/rack-bouncer"
11
11
  s.summary = "A Rack middleware that expels undesirable browsers out of your website."
@@ -3,7 +3,7 @@ require "rubygems"
3
3
  require "minitest/autorun"
4
4
  require "rack/mock"
5
5
 
6
- require "rack/bouncer"
6
+ require "rack-bouncer"
7
7
 
8
8
  class TestApp
9
9
  def call(env)
@@ -18,7 +18,7 @@ end
18
18
  class Rack::Bouncer::Test < MiniTest::Unit::TestCase
19
19
 
20
20
  def test_version
21
- assert_equal "1.2.1", Rack::Bouncer::VERSION
21
+ assert_equal "1.3.0", Rack::Bouncer::VERSION
22
22
  end
23
23
 
24
24
  def test_default_safe_paths
@@ -34,6 +34,10 @@ class Rack::Bouncer::Test < MiniTest::Unit::TestCase
34
34
  assert_equal 8.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_ie]
35
35
  end
36
36
 
37
+ def test_default_minimum_firefox
38
+ assert_equal 4.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_firefox]
39
+ end
40
+
37
41
  def test_allows_if_no_user_agent_specified
38
42
  request = create_request
39
43
  response = request.get("/")
@@ -175,6 +179,48 @@ class Rack::Bouncer::Test < MiniTest::Unit::TestCase
175
179
  # Firefox
176
180
  #################################################################################################
177
181
 
182
+ def test_expels_firefox_3_6
183
+ request = create_request
184
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0(Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/3.6" })
185
+ assert_equal 302, response.status
186
+ assert_equal response.location, "http://browsehappy.com/"
187
+ end
188
+
189
+ def test_allows_firefox_3_6_when_minimum
190
+ request = create_request(:minimum_firefox => 3.6)
191
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0(Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/3.6" })
192
+ assert_equal 200, response.status
193
+ assert_equal "Hi Internets!", response.body
194
+ end
195
+
196
+ def test_expels_firefox_3_6_2
197
+ request = create_request
198
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2" })
199
+ assert_equal 302, response.status
200
+ assert_equal response.location, "http://browsehappy.com/"
201
+ end
202
+
203
+ def test_expels_firefox_3_6_b5
204
+ request = create_request
205
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2b5) Gecko/20091204 Firefox/3.6b5" })
206
+ assert_equal 302, response.status
207
+ assert_equal response.location, "http://browsehappy.com/"
208
+ end
209
+
210
+ def test_expels_firefox_3_6_22
211
+ request = create_request
212
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; en-US; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22" })
213
+ assert_equal 302, response.status
214
+ assert_equal response.location, "http://browsehappy.com/"
215
+ end
216
+
217
+ def test_expels_firefox_3_8
218
+ request = create_request
219
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8" })
220
+ assert_equal 302, response.status
221
+ assert_equal response.location, "http://browsehappy.com/"
222
+ end
223
+
178
224
  def test_allows_firefox_4
179
225
  request = create_request
180
226
  response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0" })
@@ -182,6 +228,48 @@ class Rack::Bouncer::Test < MiniTest::Unit::TestCase
182
228
  assert_equal "Hi Internets!", response.body
183
229
  end
184
230
 
231
+ def test_allows_firefox_4_0_1
232
+ request = create_request
233
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20110518 Firefox/4.0.1" })
234
+ assert_equal 200, response.status
235
+ assert_equal "Hi Internets!", response.body
236
+ end
237
+
238
+ def test_allows_firefox_5
239
+ request = create_request
240
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 5.1; U; rv:5.0) Gecko/20100101 Firefox/5.0" })
241
+ assert_equal 200, response.status
242
+ assert_equal "Hi Internets!", response.body
243
+ end
244
+
245
+ def test_allows_firefox_6
246
+ request = create_request
247
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20110814 Firefox/6.0" })
248
+ assert_equal 200, response.status
249
+ assert_equal "Hi Internets!", response.body
250
+ end
251
+
252
+ def test_allows_firefox_9
253
+ request = create_request
254
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0" })
255
+ assert_equal 200, response.status
256
+ assert_equal "Hi Internets!", response.body
257
+ end
258
+
259
+ def test_allows_firefox_9_0_a2
260
+ request = create_request
261
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0a2) Gecko/20111101 Firefox/9.0a2" })
262
+ assert_equal 200, response.status
263
+ assert_equal "Hi Internets!", response.body
264
+ end
265
+
266
+ def test_allows_firefox_10_0_a4
267
+ request = create_request
268
+ response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/6.0 (Macintosh; I; Intel Mac OS X 11_7_9; de-LI; rv:1.9b4) Gecko/2012010317 Firefox/10.0a4" })
269
+ assert_equal 200, response.status
270
+ assert_equal "Hi Internets!", response.body
271
+ end
272
+
185
273
  # Safari
186
274
  #################################################################################################
187
275
 
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-bouncer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 2
9
- - 1
10
- version: 1.2.1
8
+ - 3
9
+ - 0
10
+ version: 1.3.0
11
11
  platform: ruby
12
12
  authors:
13
- - Jerod Santo
14
13
  - Julio Cesar Ody
14
+ - Jerod Santo
15
15
  - Will Jessop
16
16
  - Ryan Sobol
17
17
  autorequire:
@@ -68,6 +68,7 @@ files:
68
68
  - Gemfile.lock
69
69
  - README.md
70
70
  - Rakefile
71
+ - lib/rack-bouncer.rb
71
72
  - lib/rack/bouncer.rb
72
73
  - rack-bouncer.gemspec
73
74
  - test/lib/rack/bouncer_test.rb