user_agent_info 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,189 @@
1
+ #
2
+ # = UserAgentInfo
3
+ #
4
+ # == simplify user-agent detection in Rails
5
+ #
6
+ # Author:: Mehmet Celik
7
+ #
8
+ # == Usage
9
+ #
10
+ # It extends ActionController::Request and parses the requests HTTP_USER_AGENT header so it can be queried.
11
+ # The supported browsers are IE, Firefox, Chrome, Opera this translates into the methods isIE?, isFirefox?, isChrome, isOpera?
12
+ # You can also supply a version like isIE?('6.0') and you can query if it is worse or/and better then a version isIE_or_worse?('6.0')
13
+ #
14
+ # === Example
15
+ #
16
+ # class UpgradeBrowserController < ApplicationController
17
+ # def index
18
+ # @upgrade = request.user_agent_info.isIE_or_worse?('6.0')
19
+ # end
20
+ # end
21
+
22
+
23
+ module UserAgentInfo
24
+ class UserAgent
25
+ attr_reader :browser_info
26
+
27
+ def initialize(r) #:nodoc:
28
+ parse_browser_info(r)
29
+ end
30
+
31
+ # query user_agent_info
32
+ #
33
+ # request.user_agent_info['header'] ==> Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4
34
+ # request.user_agent_info['platform'] ==> Macintosh
35
+ # request.user_agent_info['name'] ==> Firefox
36
+ # request.user_agent_info['name_display'] ==> Mozilla Firefox
37
+ # request.user_agent_info['cpuos'] ==> Intel Mac OS X 10.5
38
+ # request.user_agent_info['language'] ==> en-US
39
+ # request.user_agent_info['version'] ==> 3.5
40
+ # request.user_agent_info['engine'] ==> Gecko/20091016
41
+ def [](lookup)
42
+ @browser_info[lookup]
43
+ end
44
+
45
+ # check if browser is Internet Explorer
46
+ # request.user_agent_info.isIE? ==> true if browser is Internet Explorer <br />
47
+ # request.user_agent_info.isIE?('6.0') ==> true if browser is Internet Explorer version 6.0 '=='
48
+ # request.user_agent_info.isIE_or_worse?('6.0') ==> true if browser is Internet Explorer version worse or equal to 6.0 '<='
49
+ # request.user_agent_info.isIE_and_worse?('6.0') ==> true if browser is Internet Explorer version worse then 6.0 '<'
50
+ # request.user_agent_info.isIE_or_better?('6.0') ==> true if browser is Internet Explorer version better or equal to 6.0 '>='
51
+ # request.user_agent_info.isIE_and_better?('6.0') ==> true if browser is Internet Explorer version better then 6.0 '>'
52
+ def isIE?(version = nil)
53
+ browser_query('MSIE', version)
54
+ end
55
+
56
+ def isFirefox?(version = nil)
57
+ browser_query('Firefox', version)
58
+ end
59
+
60
+ def isChrome?(version = nil)
61
+ browser_query('Chrome', version)
62
+ end
63
+
64
+ def isOpera?(version = nil)
65
+ browser_query('Opera', version)
66
+ end
67
+
68
+ def method_missing(method_id, *arguments, &block) #:nodoc:
69
+ actions = ['better', 'worse']
70
+ operators = ['or', 'and']
71
+
72
+ method = method_id.to_s
73
+ method_name = "#{method.split('_')[0]}?"
74
+
75
+ operator = method.split('_')[1]
76
+ action = method.split('_')[2].chop
77
+
78
+ return false if !operators.include?(operator)
79
+ return false if !action.include?(action)
80
+
81
+ if self.send method_name.to_sym
82
+ if arguments.size != 1
83
+ raise RuntimeError, "Missing 'version' argument."
84
+ end
85
+
86
+ version = arguments[0].to_f
87
+ case
88
+ when action.eql?("better") && operator.eql?('or')
89
+ return @browser_info['version'] >= version
90
+ when action.eql?("better") && operator.eql?('and')
91
+ return @browser_info['version'] > version
92
+ when action.eql?("worse") && operator.eql?('or')
93
+ return @browser_info['version'] <= version
94
+ when action.eql?("worse") && operator.eql?('and')
95
+ return @browser_info['version'] < version
96
+ end
97
+ end
98
+
99
+ return false
100
+ end
101
+
102
+ private
103
+ def parse_browser_info(r)
104
+ supported_browser = %w(MSIE Firefox Chrome Opera)
105
+ browser_labels = {"MSIE" => 'Microsoft Internet Explorer',
106
+ "Firefox" => "Mozilla Firefox",
107
+ "Chrome" => "Google Chrome",
108
+ "Opera" => "Opera",
109
+ "unknown" => "unknown"}
110
+
111
+ header = platform = name = cpuos = language = engine = ''
112
+ version = 0.0
113
+
114
+ if r.nil?
115
+ raise "Couldn't determine request"
116
+ end
117
+ header = r.headers['HTTP_USER_AGENT']
118
+
119
+ case
120
+ when header.match('MSIE')
121
+ string_match = header.match('.*? \((.*?)?\)( .*)?')
122
+ browser = string_match[1].split(';').map {|e| e.strip}
123
+
124
+ platform = browser[0]
125
+ cpuos = browser[2]
126
+ name_version = browser[1].split(' ')
127
+ version = name_version[1].to_f
128
+ name = name_version[0]
129
+ language = ''
130
+ when header.match('Firefox') || header.match('Chrome') || header.match('Safari')
131
+ string_match = header.match('.*? \((.*?)?\)( .*)?')
132
+ browser = string_match[1].split(';').map {|e| e.strip}
133
+ platform = browser[0]
134
+ name = browser[1]
135
+ cpuos = browser[2]
136
+ language = browser[3]
137
+
138
+ name_version_engine = string_match[2].gsub(/\(.*?\)/,'').split(' ')
139
+ name_version = name_version_engine[1].split('/')
140
+ name = name_version[0]
141
+ version = name_version[1].to_f
142
+ engine = name_version_engine[0]
143
+ when header.match('Opera')
144
+ string_match = header.match('(.*?) \((.*?)?\)( .*)?')
145
+ browser = string_match[1].split('/').map { |e| e.strip }
146
+ name = browser[0]
147
+ version = browser[1].to_f
148
+ browser = string_match[2].split(';').map {|e| e.strip}
149
+ platform = browser[0]
150
+ cpuos = browser[1]
151
+ language = browser[3]
152
+ engine = string_match[3].strip
153
+ else
154
+ platform = name = cpuos = language = engine = 'unknown'
155
+ end
156
+
157
+ @browser_info = {'header' => header, 'platform' => platform, 'name' => name, 'name_display' => browser_labels[name],
158
+ 'cpuos' => cpuos, 'language' => language, 'version' => version, 'engine' => engine}
159
+
160
+ @browser_info
161
+ end
162
+
163
+ def browser_query(browser_name, version)
164
+ response = false
165
+ if @browser_info.nil?
166
+ parse_browser_info
167
+ end
168
+
169
+ unless @browser_info.nil?
170
+ if @browser_info['name'].eql?(browser_name)
171
+ if version.nil? || version.empty?
172
+ response = true
173
+ else
174
+ response = true if (@browser_info['version'] == version.to_f)
175
+ end
176
+ end
177
+
178
+ end
179
+ response
180
+ end
181
+
182
+ end
183
+ end
184
+
185
+ class ActionController::Request #:nodoc: all
186
+ def user_agent_info
187
+ UserAgentInfo::UserAgent.new(self)
188
+ end
189
+ end
@@ -0,0 +1,52 @@
1
+ $LOAD_PATH << '../lib'
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+ require 'shoulda'
5
+
6
+ require 'action_controller'
7
+ require 'user_agent_info'
8
+
9
+
10
+ class Request
11
+ attr_accessor :headers
12
+
13
+ def initialize(header)
14
+ @headers = {'HTTP_USER_AGENT' => header}
15
+ end
16
+
17
+ def user_agent_info
18
+ UserAgentInfo::UserAgent.new(self)
19
+ end
20
+
21
+ def headers
22
+ @headers
23
+ end
24
+
25
+ end
26
+
27
+ FIREFOX_OSX_HEADER ='Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4'
28
+ CHROME_OSX_HEADER ='Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.3 (KHTML, like Gecko) Chrome/4.0.223.11 Safari/532.3'
29
+ OPERA_OSX_HEADER ='Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.2.15 Version/10.00'
30
+ IE_80_WIN_HEADER ='Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)'
31
+ IE_70_WIN_HEADER ='Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)'
32
+ FIREFOX_WIN_HEADER ='Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.14) Gecko/2009082707 Firefox/3.0.14 (.NET CLR 3.5.30729)'
33
+
34
+ class TestBrowsers < Test::Unit::TestCase
35
+
36
+ context "All browsers user agent info" do
37
+ context "MS Internet Explorer" do
38
+ setup do
39
+ @request = Request.new(IE_80_WIN_HEADER)
40
+ @browser = "This is #{@request.user_agent_info['name_display']} #{@request.user_agent_info['version']}"
41
+ end
42
+
43
+ should 'be Internet Explorer 8.0' do
44
+ assert(@request.user_agent_info.isIE?('8.0'), @browser)
45
+ end
46
+
47
+ should 'be Internet Explorer 6.0 or better' do
48
+ assert(@request.user_agent_info.isIE_or_better?('6.0'), @browser)
49
+ end
50
+ end
51
+ end
52
+ end