rack-bouncer 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +33 -7
- data/lib/rack/bouncer.rb +41 -38
- data/test/lib/rack/bouncer/aol_test.rb +15 -8
- data/test/lib/rack/bouncer/chrome_test.rb +93 -2
- data/test/lib/rack/bouncer/firefox_test.rb +15 -8
- data/test/lib/rack/bouncer/ie_test.rb +21 -35
- data/test/lib/rack/bouncer/safari_test.rb +105 -0
- data/test/lib/rack/bouncer_test.rb +49 -10
- data/test/user_agents.yml +66 -14
- metadata +4 -4
data/README.md
CHANGED
@@ -4,9 +4,11 @@ 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.0 |
|
8
|
-
| Firefox | < 4.0 |
|
9
7
|
| AOL | All |
|
8
|
+
| Chrome | < 7.0 |
|
9
|
+
| Firefox | < 4.0 |
|
10
|
+
| Internet Explorer | < 8.0 |
|
11
|
+
| Safari | < 4.0 |
|
10
12
|
|
11
13
|
## usage
|
12
14
|
|
@@ -19,19 +21,27 @@ The default redirects users to [Browse Happy](http://browsehappy.com/):
|
|
19
21
|
|
20
22
|
You can redirect users to a page in your website:
|
21
23
|
|
22
|
-
use Rack::Bouncer, :redirect => "/
|
24
|
+
use Rack::Bouncer, :redirect => "/requirements.html"
|
23
25
|
|
24
26
|
You can redirect users to a URL as well:
|
25
27
|
|
26
|
-
use Rack::Bouncer, :redirect => "
|
28
|
+
use Rack::Bouncer, :redirect => "https://www.google.com/chrome"
|
27
29
|
|
28
|
-
You can specify a minimum version of
|
30
|
+
You can specify a minimum version of Chrome like so:
|
29
31
|
|
30
|
-
use Rack::Bouncer, :
|
32
|
+
use Rack::Bouncer, :minimum_firefox => 6.0
|
31
33
|
|
32
34
|
You can specify a minimum version of Firefox like so:
|
33
35
|
|
34
|
-
use Rack::Bouncer, :
|
36
|
+
use Rack::Bouncer, :minimum_firefox => 3.6
|
37
|
+
|
38
|
+
You can specify a minimum version of IE like so:
|
39
|
+
|
40
|
+
use Rack::Bouncer, :minimum_ie => 6.0
|
41
|
+
|
42
|
+
You can specify a minimum version of Safari like so:
|
43
|
+
|
44
|
+
use Rack::Bouncer, :minimum_safari => 3.0
|
35
45
|
|
36
46
|
You can specify a set of safe paths:
|
37
47
|
|
@@ -39,6 +49,22 @@ You can specify a set of safe paths:
|
|
39
49
|
|
40
50
|
*NOTE:* By default, the above paths are safe already.
|
41
51
|
|
52
|
+
## warning
|
53
|
+
|
54
|
+
I use this gem in a production Rails app and it works great. But in development, my app throws the following error whenever the `Rack::Bouncer` middleware is triggered:
|
55
|
+
|
56
|
+
!! Unexpected error while processing request: thread 0x1001d5258 tried to join itself
|
57
|
+
|
58
|
+
I'm using the following versions of Ruby and Rails:
|
59
|
+
|
60
|
+
$ ruby -v
|
61
|
+
ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-darwin10.7.0], MBARI 0x6770, Ruby Enterprise Edition 2011.03
|
62
|
+
|
63
|
+
$ rails -v
|
64
|
+
Rails 2.3.14
|
65
|
+
|
66
|
+
If anyone has a suggestion, I'd appreciate your help.
|
67
|
+
|
42
68
|
## contributing
|
43
69
|
|
44
70
|
Pull requests are very welcome. You'd be doing me a favor if you could test cover your enhancement and ensure the test suite passes *before* initiating a pull request.
|
data/lib/rack/bouncer.rb
CHANGED
@@ -2,13 +2,15 @@
|
|
2
2
|
|
3
3
|
module Rack
|
4
4
|
class Bouncer
|
5
|
-
VERSION = "1.
|
5
|
+
VERSION = "1.4.0"
|
6
6
|
|
7
7
|
DEFAULT_OPTIONS = {
|
8
8
|
:safe_paths => ["/asset", "/images", "/stylesheets", "/javascripts", "/feedback"],
|
9
9
|
:redirect => "http://browsehappy.com/",
|
10
|
+
:minimum_chrome => 7.0,
|
11
|
+
:minimum_firefox => 4.0,
|
10
12
|
:minimum_ie => 8.0,
|
11
|
-
:
|
13
|
+
:minimum_safari => 4.0
|
12
14
|
}
|
13
15
|
|
14
16
|
def initialize(app, options = {})
|
@@ -17,16 +19,15 @@ module Rack
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def call(env)
|
20
|
-
return @app.call(env) if safe_path?(env)
|
21
|
-
return @app.call(env) if user_agent_blank?(env)
|
22
|
+
return @app.call(env) if safe_path?(env) || user_agent_blank?(env)
|
22
23
|
|
23
24
|
user_agent = env["HTTP_USER_AGENT"]
|
24
25
|
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
return expel if undesirable_ie?(user_agent) ||
|
27
|
+
undesirable_aol?(user_agent) ||
|
28
|
+
undesirable_firefox?(user_agent) ||
|
29
|
+
undesirable_safari?(user_agent) ||
|
30
|
+
undesirable_chrome?(user_agent)
|
30
31
|
|
31
32
|
@app.call(env)
|
32
33
|
end
|
@@ -42,51 +43,53 @@ module Rack
|
|
42
43
|
env["HTTP_USER_AGENT"].nil? || env["HTTP_USER_AGENT"].empty?
|
43
44
|
end
|
44
45
|
|
45
|
-
def
|
46
|
-
|
46
|
+
def expel
|
47
|
+
header = { "Location" => @options[:redirect], "Content-Type" => "text/html" }
|
48
|
+
[302, header, "User Agent not permitted"]
|
47
49
|
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
+
def undesirable_ie?(user_agent)
|
52
|
+
match = user_agent.match(/MSIE (\S+)/)
|
53
|
+
return false if match.nil?
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
+
version = match[1].to_f
|
56
|
+
return false if version == 0.0
|
55
57
|
|
56
|
-
|
57
|
-
# We need at least one digit to be able to get the version, hence the \d
|
58
|
-
user_agent.match(/MSIE \d/) ? true : false
|
58
|
+
version < @options[:minimum_ie]
|
59
59
|
end
|
60
60
|
|
61
|
-
def
|
62
|
-
user_agent.match(/
|
61
|
+
def undesirable_aol?(user_agent)
|
62
|
+
user_agent.match(/AOL \S+/) ? true : false
|
63
63
|
end
|
64
64
|
|
65
|
-
|
66
|
-
|
65
|
+
def undesirable_firefox?(user_agent)
|
66
|
+
match = user_agent.match(/Firefox\/(\S+)/)
|
67
|
+
return false if match.nil?
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
69
|
+
version = match[1].to_f
|
70
|
+
return false if version == 0.0
|
71
71
|
|
72
|
-
|
73
|
-
user_agent.match(/AOL \d/) ? true : false
|
72
|
+
version < @options[:minimum_firefox]
|
74
73
|
end
|
75
74
|
|
76
|
-
|
77
|
-
|
75
|
+
def undesirable_safari?(user_agent)
|
76
|
+
match = user_agent.match(/Version\/(\S+)\s+Safari\/\S+/)
|
77
|
+
return false if match.nil?
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
end
|
79
|
+
version = match[1].to_f
|
80
|
+
return false if version == 0.0
|
82
81
|
|
83
|
-
|
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
|
82
|
+
version < @options[:minimum_safari]
|
86
83
|
end
|
87
84
|
|
88
|
-
def
|
89
|
-
user_agent.match(/
|
85
|
+
def undesirable_chrome?(user_agent)
|
86
|
+
match = user_agent.match(/Chrome\/(\S+)\s+Safari\/\S+/)
|
87
|
+
return false if match.nil?
|
88
|
+
|
89
|
+
version = match[1].to_f
|
90
|
+
return false if version == 0.0
|
91
|
+
|
92
|
+
version < @options[:minimum_chrome]
|
90
93
|
end
|
91
94
|
end
|
92
95
|
end
|
@@ -1,30 +1,37 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class Rack::Bouncer::AOLTest < MiniTest::Unit::TestCase
|
4
|
-
def
|
4
|
+
def test_expels_aol_l4me
|
5
5
|
request = create_request
|
6
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
6
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:aol_l4me])
|
7
7
|
assert_equal 302, response.status
|
8
8
|
assert_equal response.location, "http://browsehappy.com/"
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def test_expels_aol_6_0
|
12
12
|
request = create_request
|
13
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
13
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:aol_6_0])
|
14
14
|
assert_equal 302, response.status
|
15
15
|
assert_equal response.location, "http://browsehappy.com/"
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def test_expels_aol_7_0
|
19
19
|
request = create_request
|
20
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
20
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:aol_7_0])
|
21
21
|
assert_equal 302, response.status
|
22
22
|
assert_equal response.location, "http://browsehappy.com/"
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def test_expels_aol_8_0
|
26
26
|
request = create_request
|
27
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
27
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:aol_8_0])
|
28
|
+
assert_equal 302, response.status
|
29
|
+
assert_equal response.location, "http://browsehappy.com/"
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_expels_aol_9_0
|
33
|
+
request = create_request
|
34
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:aol_9_0])
|
28
35
|
assert_equal 302, response.status
|
29
36
|
assert_equal response.location, "http://browsehappy.com/"
|
30
37
|
end
|
@@ -1,9 +1,100 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class Rack::Bouncer::ChromeTest < MiniTest::Unit::TestCase
|
4
|
-
def
|
4
|
+
def test_allows_chrome_l4me
|
5
5
|
request = create_request
|
6
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
6
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_l4me])
|
7
|
+
assert_equal 200, response.status
|
8
|
+
assert_equal "Hi Internets!", response.body
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_expels_chrome_6_0
|
12
|
+
request = create_request
|
13
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_6_0])
|
14
|
+
assert_equal 302, response.status
|
15
|
+
assert_equal response.location, "http://browsehappy.com/"
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_allows_chrome_6_0_when_minimum
|
19
|
+
request = create_request(:minimum_chrome => 6.0)
|
20
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_6_0])
|
21
|
+
assert_equal 200, response.status
|
22
|
+
assert_equal "Hi Internets!", response.body
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_allows_chrome_7_0
|
26
|
+
request = create_request
|
27
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_7_0])
|
28
|
+
assert_equal 200, response.status
|
29
|
+
assert_equal "Hi Internets!", response.body
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_allows_chrome_8_0
|
33
|
+
request = create_request
|
34
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_8_0])
|
35
|
+
assert_equal 200, response.status
|
36
|
+
assert_equal "Hi Internets!", response.body
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_allows_chrome_9_0
|
40
|
+
request = create_request
|
41
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_9_0])
|
42
|
+
assert_equal 200, response.status
|
43
|
+
assert_equal "Hi Internets!", response.body
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_allows_chrome_10_0
|
47
|
+
request = create_request
|
48
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_10_0])
|
49
|
+
assert_equal 200, response.status
|
50
|
+
assert_equal "Hi Internets!", response.body
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_allows_chrome_11_0
|
54
|
+
request = create_request
|
55
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_11_0])
|
56
|
+
assert_equal 200, response.status
|
57
|
+
assert_equal "Hi Internets!", response.body
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_allows_chrome_12_0
|
61
|
+
request = create_request
|
62
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_12_0])
|
63
|
+
assert_equal 200, response.status
|
64
|
+
assert_equal "Hi Internets!", response.body
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_allows_chrome_13_0
|
68
|
+
request = create_request
|
69
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_13_0])
|
70
|
+
assert_equal 200, response.status
|
71
|
+
assert_equal "Hi Internets!", response.body
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_allows_chrome_14_0
|
75
|
+
request = create_request
|
76
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_14_0])
|
77
|
+
assert_equal 200, response.status
|
78
|
+
assert_equal "Hi Internets!", response.body
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_allows_chrome_15_0
|
82
|
+
request = create_request
|
83
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_15_0])
|
84
|
+
assert_equal 200, response.status
|
85
|
+
assert_equal "Hi Internets!", response.body
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_allows_chrome_16_0
|
89
|
+
request = create_request
|
90
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_16_0])
|
91
|
+
assert_equal 200, response.status
|
92
|
+
assert_equal "Hi Internets!", response.body
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_allows_chrome_17_0
|
96
|
+
request = create_request
|
97
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:chrome_17_0])
|
7
98
|
assert_equal 200, response.status
|
8
99
|
assert_equal "Hi Internets!", response.body
|
9
100
|
end
|
@@ -1,6 +1,13 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class Rack::Bouncer::FirefoxTest < MiniTest::Unit::TestCase
|
4
|
+
def test_allows_firefox_l4me
|
5
|
+
request = create_request
|
6
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:firefox_l4me])
|
7
|
+
assert_equal 200, response.status
|
8
|
+
assert_equal "Hi Internets!", response.body
|
9
|
+
end
|
10
|
+
|
4
11
|
def test_expels_firefox_3_6
|
5
12
|
request = create_request
|
6
13
|
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:firefox_3_6])
|
@@ -43,9 +50,9 @@ class Rack::Bouncer::FirefoxTest < MiniTest::Unit::TestCase
|
|
43
50
|
assert_equal response.location, "http://browsehappy.com/"
|
44
51
|
end
|
45
52
|
|
46
|
-
def
|
53
|
+
def test_allows_firefox_4_0
|
47
54
|
request = create_request
|
48
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
55
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:firefox_4_0])
|
49
56
|
assert_equal 200, response.status
|
50
57
|
assert_equal "Hi Internets!", response.body
|
51
58
|
end
|
@@ -57,23 +64,23 @@ class Rack::Bouncer::FirefoxTest < MiniTest::Unit::TestCase
|
|
57
64
|
assert_equal "Hi Internets!", response.body
|
58
65
|
end
|
59
66
|
|
60
|
-
def
|
67
|
+
def test_allows_firefox_5_0
|
61
68
|
request = create_request
|
62
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
69
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:firefox_5_0])
|
63
70
|
assert_equal 200, response.status
|
64
71
|
assert_equal "Hi Internets!", response.body
|
65
72
|
end
|
66
73
|
|
67
|
-
def
|
74
|
+
def test_allows_firefox_6_0
|
68
75
|
request = create_request
|
69
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
76
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:firefox_6_0])
|
70
77
|
assert_equal 200, response.status
|
71
78
|
assert_equal "Hi Internets!", response.body
|
72
79
|
end
|
73
80
|
|
74
|
-
def
|
81
|
+
def test_allows_firefox_9_0
|
75
82
|
request = create_request
|
76
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
83
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:firefox_9_0])
|
77
84
|
assert_equal 200, response.status
|
78
85
|
assert_equal "Hi Internets!", response.body
|
79
86
|
end
|
@@ -1,72 +1,58 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class Rack::Bouncer::IETest < MiniTest::Unit::TestCase
|
4
|
-
def
|
4
|
+
def test_allows_ie_l4me
|
5
5
|
request = create_request
|
6
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
6
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_l4me])
|
7
7
|
assert_equal 200, response.status
|
8
8
|
assert_equal "Hi Internets!", response.body
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
request = create_request
|
13
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6])
|
14
|
-
assert_equal 302, response.status
|
15
|
-
assert_equal response.location, "http://browsehappy.com/"
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_expels_ie_6_and_redirects_to_internal_url
|
19
|
-
request = create_request(:redirect => "/foo")
|
20
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6])
|
21
|
-
assert_equal 302, response.status
|
22
|
-
assert_equal response.location, "/foo"
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_expels_ie_6_and_redirects_to_external_url
|
26
|
-
request = create_request(:redirect => "http://getfirefox.com")
|
27
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6])
|
28
|
-
assert_equal 302, response.status
|
29
|
-
assert_equal response.location, "http://getfirefox.com"
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_allows_ie_6_when_minimum
|
11
|
+
def test_allows_ie_6_0_when_minimum
|
33
12
|
request = create_request(:minimum_ie => 6.0)
|
34
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
13
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
35
14
|
assert_equal 200, response.status
|
36
15
|
assert_equal "Hi Internets!", response.body
|
37
16
|
end
|
38
17
|
|
39
|
-
def
|
18
|
+
def test_expels_ie_7_0
|
19
|
+
request = create_request
|
20
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_7_0])
|
21
|
+
assert_equal 302, response.status
|
22
|
+
assert_equal response.location, "http://browsehappy.com/"
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_expels_ie_7_0_b
|
40
26
|
request = create_request
|
41
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
27
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_7_0_b])
|
42
28
|
assert_equal 302, response.status
|
43
29
|
assert_equal response.location, "http://browsehappy.com/"
|
44
30
|
end
|
45
31
|
|
46
|
-
def
|
32
|
+
def test_allows_ie_7_0_when_minimum
|
47
33
|
request = create_request(:minimum_ie => 7.0)
|
48
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
34
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_7_0])
|
49
35
|
assert_equal 200, response.status
|
50
36
|
assert_equal "Hi Internets!", response.body
|
51
37
|
end
|
52
38
|
|
53
|
-
def
|
39
|
+
def test_allows_ie_8_0
|
54
40
|
request = create_request
|
55
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
41
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_8_0])
|
56
42
|
assert_equal 200, response.status
|
57
43
|
assert_equal "Hi Internets!", response.body
|
58
44
|
end
|
59
45
|
|
60
|
-
def
|
46
|
+
def test_allows_ie_8_0_when_minimum
|
61
47
|
request = create_request(:minimum_ie => 8.0)
|
62
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
48
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_8_0])
|
63
49
|
assert_equal 200, response.status
|
64
50
|
assert_equal "Hi Internets!", response.body
|
65
51
|
end
|
66
52
|
|
67
|
-
def
|
53
|
+
def test_allows_ie_9_0
|
68
54
|
request = create_request
|
69
|
-
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:
|
55
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_9_0])
|
70
56
|
assert_equal 200, response.status
|
71
57
|
assert_equal "Hi Internets!", response.body
|
72
58
|
end
|
@@ -1,6 +1,97 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class Rack::Bouncer::SafariTest < MiniTest::Unit::TestCase
|
4
|
+
def test_allows_safari_l4me
|
5
|
+
request = create_request
|
6
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_l4me])
|
7
|
+
assert_equal 200, response.status
|
8
|
+
assert_equal "Hi Internets!", response.body
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_expels_safari_3_0
|
12
|
+
request = create_request
|
13
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_0])
|
14
|
+
assert_equal 302, response.status
|
15
|
+
assert_equal response.location, "http://browsehappy.com/"
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_allows_safari_3_0_when_minimum
|
19
|
+
request = create_request(:minimum_safari => 3.0)
|
20
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_0])
|
21
|
+
assert_equal 200, response.status
|
22
|
+
assert_equal "Hi Internets!", response.body
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_expels_safari_3_0_1
|
26
|
+
request = create_request
|
27
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_0_1])
|
28
|
+
assert_equal 302, response.status
|
29
|
+
assert_equal response.location, "http://browsehappy.com/"
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_allows_safari_3_0_1_when_minimum
|
33
|
+
request = create_request(:minimum_safari => 3.0)
|
34
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_0_1])
|
35
|
+
assert_equal 200, response.status
|
36
|
+
assert_equal "Hi Internets!", response.body
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_expels_safari_3_1
|
40
|
+
request = create_request
|
41
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_1])
|
42
|
+
assert_equal 302, response.status
|
43
|
+
assert_equal response.location, "http://browsehappy.com/"
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_allows_safari_3_1_when_minimum
|
47
|
+
request = create_request(:minimum_safari => 3.1)
|
48
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_1])
|
49
|
+
assert_equal 200, response.status
|
50
|
+
assert_equal "Hi Internets!", response.body
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_expels_safari_3_1_2
|
54
|
+
request = create_request
|
55
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_1_2])
|
56
|
+
assert_equal 302, response.status
|
57
|
+
assert_equal response.location, "http://browsehappy.com/"
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_allows_safari_3_1_2_when_minimum
|
61
|
+
request = create_request(:minimum_safari => 3.1)
|
62
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_3_1_2])
|
63
|
+
assert_equal 200, response.status
|
64
|
+
assert_equal "Hi Internets!", response.body
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_allows_safari_4_0
|
68
|
+
request = create_request
|
69
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_4_0])
|
70
|
+
assert_equal 200, response.status
|
71
|
+
assert_equal "Hi Internets!", response.body
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_allows_safari_4_0_1
|
75
|
+
request = create_request
|
76
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_4_0_1])
|
77
|
+
assert_equal 200, response.status
|
78
|
+
assert_equal "Hi Internets!", response.body
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_allows_safari_4_0_dp1
|
82
|
+
request = create_request
|
83
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_4_0_dp1])
|
84
|
+
assert_equal 200, response.status
|
85
|
+
assert_equal "Hi Internets!", response.body
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_allows_safari_4_1
|
89
|
+
request = create_request
|
90
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_4_1])
|
91
|
+
assert_equal 200, response.status
|
92
|
+
assert_equal "Hi Internets!", response.body
|
93
|
+
end
|
94
|
+
|
4
95
|
def test_allows_safari_5_0
|
5
96
|
request = create_request
|
6
97
|
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_5_0])
|
@@ -8,10 +99,24 @@ class Rack::Bouncer::SafariTest < MiniTest::Unit::TestCase
|
|
8
99
|
assert_equal "Hi Internets!", response.body
|
9
100
|
end
|
10
101
|
|
102
|
+
def test_allows_safari_5_0_1
|
103
|
+
request = create_request
|
104
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_5_0_1])
|
105
|
+
assert_equal 200, response.status
|
106
|
+
assert_equal "Hi Internets!", response.body
|
107
|
+
end
|
108
|
+
|
11
109
|
def test_allows_safari_5_1
|
12
110
|
request = create_request
|
13
111
|
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_5_1])
|
14
112
|
assert_equal 200, response.status
|
15
113
|
assert_equal "Hi Internets!", response.body
|
16
114
|
end
|
115
|
+
|
116
|
+
def test_allows_safari_5_1_2
|
117
|
+
request = create_request
|
118
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:safari_5_1_2])
|
119
|
+
assert_equal 200, response.status
|
120
|
+
assert_equal "Hi Internets!", response.body
|
121
|
+
end
|
17
122
|
end
|
@@ -3,9 +3,12 @@ require "test_helper"
|
|
3
3
|
|
4
4
|
class Rack::BouncerTest < MiniTest::Unit::TestCase
|
5
5
|
def test_version
|
6
|
-
assert_equal "1.
|
6
|
+
assert_equal "1.4.0", Rack::Bouncer::VERSION
|
7
7
|
end
|
8
8
|
|
9
|
+
# Default Options
|
10
|
+
#################################################################################################
|
11
|
+
|
9
12
|
def test_default_safe_paths
|
10
13
|
expected = ["/asset", "/images", "/stylesheets", "/javascripts", "/feedback"]
|
11
14
|
assert_equal expected, Rack::Bouncer::DEFAULT_OPTIONS[:safe_paths]
|
@@ -15,14 +18,25 @@ class Rack::BouncerTest < MiniTest::Unit::TestCase
|
|
15
18
|
assert_equal "http://browsehappy.com/", Rack::Bouncer::DEFAULT_OPTIONS[:redirect]
|
16
19
|
end
|
17
20
|
|
18
|
-
def
|
19
|
-
assert_equal
|
21
|
+
def test_default_minimum_chrome
|
22
|
+
assert_equal 7.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_chrome]
|
20
23
|
end
|
21
24
|
|
22
25
|
def test_default_minimum_firefox
|
23
26
|
assert_equal 4.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_firefox]
|
24
27
|
end
|
25
28
|
|
29
|
+
def test_default_minimum_ie
|
30
|
+
assert_equal 8.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_ie]
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_default_minimum_safari
|
34
|
+
assert_equal 4.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_safari]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Edge Cases
|
38
|
+
#################################################################################################
|
39
|
+
|
26
40
|
def test_allows_if_no_user_agent_specified
|
27
41
|
request = create_request
|
28
42
|
response = request.get("/")
|
@@ -37,54 +51,79 @@ class Rack::BouncerTest < MiniTest::Unit::TestCase
|
|
37
51
|
assert_equal "Hi Internets!", response.body
|
38
52
|
end
|
39
53
|
|
54
|
+
# Redirects
|
55
|
+
#################################################################################################
|
56
|
+
|
57
|
+
def test_redirects_to_default
|
58
|
+
request = create_request
|
59
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
60
|
+
assert_equal 302, response.status
|
61
|
+
assert_equal response.location, "http://browsehappy.com/"
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_redirects_to_internal_url
|
65
|
+
request = create_request(:redirect => "/foo")
|
66
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
67
|
+
assert_equal 302, response.status
|
68
|
+
assert_equal response.location, "/foo"
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_redirects_to_external_url
|
72
|
+
request = create_request(:redirect => "https://www.google.com/chrome")
|
73
|
+
response = request.get("/", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
74
|
+
assert_equal 302, response.status
|
75
|
+
assert_equal response.location, "https://www.google.com/chrome"
|
76
|
+
end
|
77
|
+
|
78
|
+
|
40
79
|
# Safe Paths
|
41
80
|
#################################################################################################
|
42
81
|
|
43
82
|
def test_allows_redirect_path
|
44
83
|
request = create_request(:redirect => "/browser")
|
45
|
-
response = request.get("/browser", "HTTP_USER_AGENT" => USER_AGENTS[:
|
84
|
+
response = request.get("/browser", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
46
85
|
assert_equal 200, response.status
|
47
86
|
assert_equal "Hi Internets!", response.body
|
48
87
|
end
|
49
88
|
|
50
89
|
def test_expels_non_redirect_path
|
51
90
|
request = create_request(:redirect => "/browser")
|
52
|
-
response = request.get("/wrong", "HTTP_USER_AGENT" => USER_AGENTS[:
|
91
|
+
response = request.get("/wrong", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
53
92
|
assert_equal 302, response.status
|
54
93
|
assert_equal response.location, "/browser"
|
55
94
|
end
|
56
95
|
|
57
96
|
def test_allows_assets_path
|
58
97
|
request = create_request
|
59
|
-
response = request.get("/asset", "HTTP_USER_AGENT" => USER_AGENTS[:
|
98
|
+
response = request.get("/asset", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
60
99
|
assert_equal 200, response.status
|
61
100
|
assert_equal "Hi Internets!", response.body
|
62
101
|
end
|
63
102
|
|
64
103
|
def test_allows_images_path
|
65
104
|
request = create_request
|
66
|
-
response = request.get("/images", "HTTP_USER_AGENT" => USER_AGENTS[:
|
105
|
+
response = request.get("/images", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
67
106
|
assert_equal 200, response.status
|
68
107
|
assert_equal "Hi Internets!", response.body
|
69
108
|
end
|
70
109
|
|
71
110
|
def test_allows_stylesheets_path
|
72
111
|
request = create_request
|
73
|
-
response = request.get("/stylesheets", "HTTP_USER_AGENT" => USER_AGENTS[:
|
112
|
+
response = request.get("/stylesheets", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
74
113
|
assert_equal 200, response.status
|
75
114
|
assert_equal "Hi Internets!", response.body
|
76
115
|
end
|
77
116
|
|
78
117
|
def test_allows_javascripts_path
|
79
118
|
request = create_request
|
80
|
-
response = request.get("/javascripts", "HTTP_USER_AGENT" => USER_AGENTS[:
|
119
|
+
response = request.get("/javascripts", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
81
120
|
assert_equal 200, response.status
|
82
121
|
assert_equal "Hi Internets!", response.body
|
83
122
|
end
|
84
123
|
|
85
124
|
def test_allows_feedback_path
|
86
125
|
request = create_request
|
87
|
-
response = request.get("/feedback", "HTTP_USER_AGENT" => USER_AGENTS[:
|
126
|
+
response = request.get("/feedback", "HTTP_USER_AGENT" => USER_AGENTS[:ie_6_0])
|
88
127
|
assert_equal 200, response.status
|
89
128
|
assert_equal "Hi Internets!", response.body
|
90
129
|
end
|
data/test/user_agents.yml
CHANGED
@@ -3,13 +3,15 @@
|
|
3
3
|
# AOL
|
4
4
|
###################################################################################################
|
5
5
|
|
6
|
-
:
|
6
|
+
:aol_l4me:
|
7
|
+
Mozilla/4.0 (compatible; MSIE 5.5; AOL l4me; Windows 98)
|
8
|
+
:aol_6_0:
|
7
9
|
Mozilla/4.0 (compatible; MSIE 5.5; AOL 6.0; Windows 98)
|
8
|
-
:
|
10
|
+
:aol_7_0:
|
9
11
|
Mozilla/4.0 (compatible; MSIE 7.0; AOL 7.0; Windows NT 5.1)
|
10
|
-
:
|
12
|
+
:aol_8_0:
|
11
13
|
Mozilla/4.0 (compatible; MSIE 7.0; AOL 8.0; Windows NT 5.1)
|
12
|
-
:
|
14
|
+
:aol_9_0:
|
13
15
|
Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.0; Windows NT 5.1)
|
14
16
|
:aol_9_1:
|
15
17
|
Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.1; AOLBuild 4334.5000; Windows NT 5.1; Trident/4.0)
|
@@ -21,12 +23,38 @@
|
|
21
23
|
# Chrome
|
22
24
|
###################################################################################################
|
23
25
|
|
24
|
-
:
|
26
|
+
:chrome_l4me:
|
27
|
+
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/l4me Safari/535.7
|
28
|
+
:chrome_6_0:
|
29
|
+
Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.416.0 Safari/534.1
|
30
|
+
:chrome_7_0:
|
31
|
+
Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.24 Safari/534.7
|
32
|
+
:chrome_8_0:
|
33
|
+
Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.551.0 Safari/534.10
|
34
|
+
:chrome_9_0:
|
35
|
+
Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.44 Safari/534.13
|
36
|
+
:chrome_10_0:
|
37
|
+
Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Chrome/10.0.612.1 Safari/534.15
|
38
|
+
:chrome_11_0:
|
39
|
+
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.655.0 Safari/534.17
|
40
|
+
:chrome_12_0:
|
41
|
+
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.53 Safari/534.30
|
42
|
+
:chrome_13_0:
|
43
|
+
Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.215 Safari/535.1
|
44
|
+
:chrome_14_0:
|
45
|
+
Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.792.0 Safari/535.1
|
46
|
+
:chrome_15_0:
|
47
|
+
Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.872.0 Safari/535.2
|
48
|
+
:chrome_16_0:
|
25
49
|
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7
|
50
|
+
:chrome_17_0:
|
51
|
+
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.46 Safari/535.11
|
26
52
|
|
27
53
|
# Firefox
|
28
54
|
###################################################################################################
|
29
55
|
|
56
|
+
:firefox_l4me:
|
57
|
+
Mozilla/5.0(Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/l4me
|
30
58
|
:firefox_3_6:
|
31
59
|
Mozilla/5.0(Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/3.6
|
32
60
|
:firefox_3_6_2:
|
@@ -37,15 +65,15 @@
|
|
37
65
|
Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; en-US; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22
|
38
66
|
:firefox_3_8:
|
39
67
|
Mozilla/5.0 (X11; U; Linux i686; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8
|
40
|
-
:
|
68
|
+
:firefox_4_0:
|
41
69
|
Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0
|
42
70
|
:firefox_4_0_1:
|
43
71
|
Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20110518 Firefox/4.0.1
|
44
|
-
:
|
72
|
+
:firefox_5_0:
|
45
73
|
Mozilla/5.0 (Windows NT 5.1; U; rv:5.0) Gecko/20100101 Firefox/5.0
|
46
|
-
:
|
74
|
+
:firefox_6_0:
|
47
75
|
Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20110814 Firefox/6.0
|
48
|
-
:
|
76
|
+
:firefox_9_0:
|
49
77
|
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0
|
50
78
|
:firefox_9_0_a2:
|
51
79
|
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0a2) Gecko/20111101 Firefox/9.0a2
|
@@ -55,15 +83,17 @@
|
|
55
83
|
# Internet Explorer
|
56
84
|
###################################################################################################
|
57
85
|
|
58
|
-
:
|
86
|
+
:ie_l4me:
|
59
87
|
Mozilla/4.0 (compatible; MSIE l4me; Windows XP)
|
60
|
-
:
|
88
|
+
:ie_6_0:
|
61
89
|
Mozilla/4.0 (MSIE 6.0; Windows NT 5.1)
|
62
|
-
:
|
90
|
+
:ie_7_0:
|
63
91
|
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)
|
64
|
-
:
|
92
|
+
:ie_7_0_b:
|
93
|
+
Mozilla/4.0(compatible; MSIE 7.0b; Windows NT 6.0)
|
94
|
+
:ie_8_0:
|
65
95
|
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)
|
66
|
-
:
|
96
|
+
:ie_9_0:
|
67
97
|
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
|
68
98
|
|
69
99
|
# Mozilla
|
@@ -75,7 +105,29 @@
|
|
75
105
|
# Safari
|
76
106
|
###################################################################################################
|
77
107
|
|
108
|
+
:safari_l4me:
|
109
|
+
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/523.15 (KHTML, like Gecko) Version/l4me Safari/523.15
|
110
|
+
:safari_3_0:
|
111
|
+
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/523.15 (KHTML, like Gecko) Version/3.0 Safari/523.15
|
112
|
+
:safari_3_0_1:
|
113
|
+
Mozilla/5.0 (Windows; U; Windows NT 6.0; fi) AppleWebKit/522.12.1 (KHTML, like Gecko) Version/3.0.1 Safari/522.12.2
|
114
|
+
:safari_3_1:
|
115
|
+
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; en-us) AppleWebKit/526.1+ (KHTML, like Gecko) Version/3.1 Safari/525.13
|
116
|
+
:safari_3_1_2:
|
117
|
+
Mozilla/5.0 (Windows; U; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.1.2 Safari/525.21
|
118
|
+
:safari_4_0:
|
119
|
+
Mozilla/5.0 (Windows; U; Windows NT 6.0; ja-JP) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16
|
120
|
+
:safari_4_0_1:
|
121
|
+
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/4.0.1 Safari/530.18
|
122
|
+
:safari_4_0_dp1:
|
123
|
+
Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; en) AppleWebKit/528.4+ (KHTML, like Gecko) Version/4.0dp1 Safari/526.11.2
|
124
|
+
:safari_4_1:
|
125
|
+
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-en) AppleWebKit/533.16 (KHTML, like Gecko) Version/4.1 Safari/533.16
|
78
126
|
:safari_5_0:
|
79
127
|
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0 Safari/533.16
|
128
|
+
:safari_5_0_1:
|
129
|
+
Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8
|
80
130
|
:safari_5_1:
|
81
131
|
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1 Safari/534.52.7
|
132
|
+
:safari_5_1_2:
|
133
|
+
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1.2 Safari/534.52.7
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-bouncer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 1.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Julio Cesar Ody
|