browser_sniffer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gemspec.rb +51 -0
- data/.gitignore +17 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +47 -0
- data/README.md +49 -0
- data/Rakefile +12 -0
- data/browser_sniffer.gemspec +23 -0
- data/init.rb +1 -0
- data/lib/browser_sniffer.rb +152 -0
- data/lib/browser_sniffer/patterns.rb +240 -0
- data/lib/browser_sniffer/version.rb +3 -0
- data/test/browser_sniffer_test.rb +405 -0
- data/test/test_helper.rb +6 -0
- metadata +97 -0
data/.gemspec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
class Readme < String
|
2
|
+
attr_reader :path
|
3
|
+
|
4
|
+
def initialize(path)
|
5
|
+
@path = path
|
6
|
+
super(File.read(self.path))
|
7
|
+
end
|
8
|
+
|
9
|
+
def summary
|
10
|
+
if self =~ /^# (?:\S+)\s+(.+?)\s{2,}/m
|
11
|
+
scrub $1
|
12
|
+
else
|
13
|
+
raise "could not find summary in #{path}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
if self =~ /^## Description\s+(.+?)\s{2,}/m
|
19
|
+
scrub $1
|
20
|
+
else
|
21
|
+
raise "could not find description in #{path}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def scrub(string)
|
27
|
+
string.delete("\\`").gsub(/\[([^\]]+)\]\([^)]*\)/, "\\1").tr("\n", " ").to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Files < Array
|
32
|
+
def executables
|
33
|
+
grep(%r{^bin/}) { |f| File.basename(f) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def requires
|
37
|
+
["lib"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def tests
|
41
|
+
grep(%r{^(test|spec|features)/})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def files
|
46
|
+
@files ||= Files.new(`git ls-files`.split($/))
|
47
|
+
end
|
48
|
+
|
49
|
+
def readme(path = File.expand_path("./README.md"))
|
50
|
+
(@readmes ||= {})[path] ||= Readme.new(path)
|
51
|
+
end
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
Based off UAParser.js
|
2
|
+
https://github.com/faisalman/ua-parser-js
|
3
|
+
|
4
|
+
Copyright (c) 2013 Shopify
|
5
|
+
Copyright (c) 2012-2013 Faisalman <fyzlman@gmail.com>
|
6
|
+
Dual licensed under GPLv2 & MIT
|
7
|
+
|
8
|
+
---------------------------------------------------
|
9
|
+
|
10
|
+
GPLv2
|
11
|
+
|
12
|
+
This program is free software; you can redistribute it and/or
|
13
|
+
modify it under the terms of the GNU General Public License
|
14
|
+
as published by the Free Software Foundation; either version 2
|
15
|
+
of the License, or (at your option) any later version.
|
16
|
+
|
17
|
+
This program is distributed in the hope that it will be useful,
|
18
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20
|
+
GNU General Public License for more details.
|
21
|
+
|
22
|
+
You should have received a copy of the GNU General Public License
|
23
|
+
along with this program; if not, write to the Free Software
|
24
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
25
|
+
|
26
|
+
---------------------------------------------------
|
27
|
+
|
28
|
+
MIT License
|
29
|
+
|
30
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
31
|
+
a copy of this software and associated documentation files (the
|
32
|
+
"Software"), to deal in the Software without restriction, including
|
33
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
34
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
35
|
+
permit persons to whom the Software is furnished to do so, subject to
|
36
|
+
the following conditions:
|
37
|
+
|
38
|
+
The above copyright notice and this permission notice shall be
|
39
|
+
included in all copies or substantial portions of the Software.
|
40
|
+
|
41
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
42
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
43
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
44
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
45
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
46
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
47
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
[](http://travis-ci.org/Shopify/browser_sniffer)
|
2
|
+
[](http://badge.fury.io/rb/browser_sniffer)
|
3
|
+
|
4
|
+
# BrowserSniffer
|
5
|
+
|
6
|
+
## Description
|
7
|
+
|
8
|
+
Parses user agent strings and boils it all down to a few simple classifications.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem "browser_sniffer"
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle install
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ git clone https://github.com/Shopify/browser_sniffer && cd browser_sniffer && bundle install && rake install
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require "browser_sniffer"
|
28
|
+
|
29
|
+
client_info = BrowserSniffer.new(request.user_agent)
|
30
|
+
client_info.form_factor # => :tablet
|
31
|
+
client_info.browser # => :safari
|
32
|
+
client_info.major_browser_version # => 4
|
33
|
+
client_info.engine # => :webkit
|
34
|
+
client_info.major_engine_version # => 531
|
35
|
+
client_info.os # => :ios
|
36
|
+
client_info.os_version # => 3.2
|
37
|
+
```
|
38
|
+
|
39
|
+
## Contributing
|
40
|
+
|
41
|
+
Fork, branch & pull request.
|
42
|
+
|
43
|
+
## Licensing
|
44
|
+
|
45
|
+
Based off [UAParser.js](https://github.com/faisalman/ua-parser-js)
|
46
|
+
|
47
|
+
Copyright (c) 2013 Shopify
|
48
|
+
Copyright (c) 2012-2013 Faisalman <fyzlman@gmail.com>
|
49
|
+
Dual licensed under GPLv2 & MIT
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path("../.gemspec", __FILE__)
|
2
|
+
require File.expand_path("../lib/browser_sniffer/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "browser_sniffer"
|
6
|
+
spec.version = BrowserSniffer::VERSION
|
7
|
+
spec.authors = ["Shopify"]
|
8
|
+
spec.email = ["gems@shopify.com"]
|
9
|
+
spec.description = readme.description
|
10
|
+
spec.summary = readme.summary
|
11
|
+
spec.homepage = "https://github.com/Shopify/browser_sniffer"
|
12
|
+
spec.license = "GPLv2 & MIT"
|
13
|
+
|
14
|
+
spec.files = files
|
15
|
+
spec.executables = files.executables
|
16
|
+
spec.test_files = files.tests
|
17
|
+
spec.require_paths = files.requires
|
18
|
+
|
19
|
+
spec.required_ruby_version = ">= 1.9.3"
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'browser_sniffer'
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require "browser_sniffer/version"
|
2
|
+
require "browser_sniffer/patterns"
|
3
|
+
|
4
|
+
class BrowserSniffer
|
5
|
+
attr_reader :user_agent
|
6
|
+
|
7
|
+
def initialize(user_agent)
|
8
|
+
@user_agent = user_agent
|
9
|
+
end
|
10
|
+
|
11
|
+
def ios?
|
12
|
+
os == :ios
|
13
|
+
end
|
14
|
+
|
15
|
+
def android?
|
16
|
+
os == :android
|
17
|
+
end
|
18
|
+
|
19
|
+
def ie8?
|
20
|
+
browser == :ie && major_browser_version == 8
|
21
|
+
end
|
22
|
+
|
23
|
+
def handheld?
|
24
|
+
form_factor == :handheld
|
25
|
+
end
|
26
|
+
|
27
|
+
def tablet?
|
28
|
+
form_factor == :tablet
|
29
|
+
end
|
30
|
+
|
31
|
+
def desktop?
|
32
|
+
form_factor == :desktop
|
33
|
+
end
|
34
|
+
|
35
|
+
def form_factor
|
36
|
+
device_info[:type] || :desktop
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
def engine
|
42
|
+
engine_info[:type]
|
43
|
+
end
|
44
|
+
|
45
|
+
def engine_name
|
46
|
+
engine_info[:name]
|
47
|
+
end
|
48
|
+
|
49
|
+
def major_engine_version
|
50
|
+
str = engine_info[:major]
|
51
|
+
str && str.to_i
|
52
|
+
end
|
53
|
+
|
54
|
+
def engine_version
|
55
|
+
engine_info[:version]
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def browser
|
61
|
+
browser_info[:type]
|
62
|
+
end
|
63
|
+
|
64
|
+
def browser_name
|
65
|
+
browser_info[:name]
|
66
|
+
end
|
67
|
+
|
68
|
+
def major_browser_version
|
69
|
+
str = browser_info[:major]
|
70
|
+
str && str.to_i
|
71
|
+
end
|
72
|
+
|
73
|
+
def browser_version
|
74
|
+
browser_info[:version]
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
def device
|
80
|
+
device_info[:name]
|
81
|
+
end
|
82
|
+
|
83
|
+
def device_name
|
84
|
+
device_info[:model]
|
85
|
+
end
|
86
|
+
|
87
|
+
def device_vendor
|
88
|
+
device_info[:vendor]
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
def os
|
94
|
+
os_info[:type]
|
95
|
+
end
|
96
|
+
|
97
|
+
def os_name
|
98
|
+
os_info[:name]
|
99
|
+
end
|
100
|
+
|
101
|
+
def os_version
|
102
|
+
os_info[:version]
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
def browser_info
|
108
|
+
@browser_info ||= parse_user_agent_for(BrowserSniffer::REGEX_MAP[:browser])
|
109
|
+
end
|
110
|
+
|
111
|
+
def engine_info
|
112
|
+
@engine_info ||= parse_user_agent_for(BrowserSniffer::REGEX_MAP[:engine])
|
113
|
+
end
|
114
|
+
|
115
|
+
def device_info
|
116
|
+
@device_info ||= parse_user_agent_for(BrowserSniffer::REGEX_MAP[:device])
|
117
|
+
end
|
118
|
+
|
119
|
+
def os_info
|
120
|
+
@os_info ||= parse_user_agent_for(BrowserSniffer::REGEX_MAP[:os])
|
121
|
+
end
|
122
|
+
|
123
|
+
def parse_user_agent_for(type)
|
124
|
+
result = {}
|
125
|
+
type.each_slice(2) do |slice|
|
126
|
+
format = slice[1]
|
127
|
+
slice[0].each do |regex|
|
128
|
+
regex.match(user_agent) do |match|
|
129
|
+
format.each_with_index do |field, index|
|
130
|
+
if field.class == Symbol
|
131
|
+
result[field] = match[index + 1]
|
132
|
+
elsif field.class == Array
|
133
|
+
if field[1].class == String || field[1].class == Symbol
|
134
|
+
result[field[0]] = field[1]
|
135
|
+
elsif field[1].class == Hash
|
136
|
+
if field[1][match[index + 1]]
|
137
|
+
result[field[0]] = field[1][match[index + 1]]
|
138
|
+
else
|
139
|
+
result[field[0]] = match[index + 1]
|
140
|
+
end
|
141
|
+
elsif field[1].class == Proc
|
142
|
+
result[field[0]] = field[1].call(match[index + 1])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
return result
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
result
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
class BrowserSniffer
|
2
|
+
STRING_MAP = {
|
3
|
+
:browser => {
|
4
|
+
:oldsafari => {
|
5
|
+
:major => {
|
6
|
+
'/85' => '1',
|
7
|
+
'/125' => '1',
|
8
|
+
'/312' => '1',
|
9
|
+
'/412' => '2',
|
10
|
+
'/416' => '2',
|
11
|
+
'/417' => '2',
|
12
|
+
'/419' => '2'
|
13
|
+
},
|
14
|
+
:version => {
|
15
|
+
'/85' => '1.0',
|
16
|
+
'/125' => '1.2',
|
17
|
+
'/312' => '1.3',
|
18
|
+
'/412' => '2.0',
|
19
|
+
'/416' => '2.0.2',
|
20
|
+
'/417' => '2.0.3',
|
21
|
+
'/419' => '2.0.4'
|
22
|
+
}
|
23
|
+
}
|
24
|
+
},
|
25
|
+
:os => {
|
26
|
+
:windows => {
|
27
|
+
:version => {
|
28
|
+
'4.90' => 'ME',
|
29
|
+
'NT3.51' => 'NT 3.11',
|
30
|
+
'NT4.0' => 'NT 4.0',
|
31
|
+
'NT 5.0' => '2000',
|
32
|
+
'NT 5.1' => 'XP',
|
33
|
+
'NT 5.2' => 'XP',
|
34
|
+
'NT 6.0' => 'Vista',
|
35
|
+
'NT 6.1' => '7',
|
36
|
+
'NT 6.2' => '8',
|
37
|
+
'ARM' => 'RT'
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
REGEX_MAP = {
|
44
|
+
:browser => [
|
45
|
+
[
|
46
|
+
# Presto based
|
47
|
+
/(opera\smini)\/((\d+)?[\w\.-]+)/i, # Opera Mini
|
48
|
+
/(opera\s[mobiletab]+).+:version\/((\d+)?[\w\.-]+)/i, # Opera Mobi/Tablet
|
49
|
+
/(opera).+:version\/((\d+)?[\w\.]+)/i, # Opera > 9.80
|
50
|
+
/(opera)[\/\s]+((\d+)?[\w\.]+)/i # Opera < 9.80
|
51
|
+
], [:name, :version, :major, [:type, :opera]], [
|
52
|
+
/\s(opr)\/((\d+)?[\w\.]+)/i # Opera Webkit
|
53
|
+
], [[:name, 'Opera'], :version, :major, [:type, :opera]], [
|
54
|
+
# Mixed
|
55
|
+
/(kindle)\/((\d+)?[\w\.]+)/i, # Kindle
|
56
|
+
/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i, # Lunascape/Maxthon/Netfront/Jasmine/Blazer
|
57
|
+
# Trident based
|
58
|
+
/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i # Avant/IEMobile/SlimBrowser/Baidu
|
59
|
+
], [:name, :version, :major], [
|
60
|
+
/(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i # Internet Explorer
|
61
|
+
], [:name, :version, :major, [:type, :ie]], [
|
62
|
+
# Webkit/KHTML based
|
63
|
+
/(rekonq)\/?((\d+)[\w\.]+)*/i, # Rekonq
|
64
|
+
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt)\/((\d+)?[\w\.-]+)/i # Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt
|
65
|
+
], [:name, :version, :major], [
|
66
|
+
/(yabrowser)\/((\d+)?[\w\.]+)/i # Yandex
|
67
|
+
], [[:name, 'Yandex'], :version, :major], [
|
68
|
+
/(comodo_dragon)\/((\d+)?[\w\.]+)/i # Comodo Dragon
|
69
|
+
], [[:name, 'Comodo Dragon'], :version, :major], [
|
70
|
+
/(chromium)\/((\d+)?[\w\.-]+)/i, # Chromium
|
71
|
+
/(chrome)\/v?((\d+)?[\w\.]+)/i # Chrome
|
72
|
+
], [:name, :version, :major, [:type, :chrome]], [
|
73
|
+
/(omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i # Chrome/OmniWeb/Arora/Tizen/Nokia
|
74
|
+
], [:name, :version, :major], [
|
75
|
+
/(dolfin)\/((\d+)?[\w\.]+)/i # Dolphin
|
76
|
+
], [[:name, 'Dolphin'], :version, :major], [
|
77
|
+
/((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i # Chrome for Android/iOS
|
78
|
+
], [[:name, 'Chrome'], :version, :major, [:type, :chrome]], [
|
79
|
+
/version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i # Mobile Safari
|
80
|
+
], [:version, :major, [:name, 'Mobile Safari'], [:type, :safari]], [
|
81
|
+
/version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i # Safari & Safari Mobile
|
82
|
+
], [:version, :major, :name, [:type, :safari]], [
|
83
|
+
/webkit.+?(mobile\s?safari|safari)((\/[\w]+))/i # Safari < 3.0
|
84
|
+
], [:name, [:major, STRING_MAP[:browser][:oldsafari][:major]], [:version, STRING_MAP[:browser][:oldsafari][:version]], [:type, :safari]], [
|
85
|
+
/(konqueror)\/((\d+)?[\w\.]+)/i, # Konqueror
|
86
|
+
/(webkit|khtml)\/((\d+)?[\w\.]+)/i
|
87
|
+
], [:name, :version, :major], [
|
88
|
+
# Gecko based
|
89
|
+
/(navigator|netscape)\/((\d+)?[\w\.-]+)/i # Netscape
|
90
|
+
], [[:name, 'Netscape'], :version, :major], [
|
91
|
+
/(swiftfox)/i, # Swiftfox
|
92
|
+
/(iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i, # Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
|
93
|
+
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i # Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
94
|
+
], [:name, :version, :major], [
|
95
|
+
/(firefox)\/((\d+)?[\w\.-]+)/i, # Firefox
|
96
|
+
/(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i, # Mozilla
|
97
|
+
], [:name, :version, :major, [:type, :firefox]], [
|
98
|
+
# Other
|
99
|
+
/(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?((\d+)?[\w\.]+)/i, # UCBrowser/Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf
|
100
|
+
/(links)\s\(((\d+)?[\w\.]+)/i, # Links
|
101
|
+
/(gobrowser)\/?((\d+)?[\w\.]+)*/i, # GoBrowser
|
102
|
+
/(ice\s?browser)\/v?((\d+)?[\w\._]+)/i, # ICE Browser
|
103
|
+
/(mosaic)[\/\s]((\d+)?[\w\.]+)/i # Mosaic
|
104
|
+
], [:name, :version, :major]
|
105
|
+
],
|
106
|
+
:device => [
|
107
|
+
[
|
108
|
+
/\((playbook);[\w\s\);-]+(rim)/i # PlayBook
|
109
|
+
], [:model, :vendor, [:type, :tablet]], [
|
110
|
+
/\((ipad);[\w\s\);-]+(apple)/i # iPad
|
111
|
+
], [:model, :vendor, [:name, :ipad], [:type, :tablet]], [
|
112
|
+
/(hp).+(touchpad)/i, # HP TouchPad
|
113
|
+
/(kindle)\/([\w\.]+)/i, # Kindle
|
114
|
+
/\s(nook)[\w\s]+build\/(\w+)/i, # Nook
|
115
|
+
/(dell)\s(strea[kpr\s\d]*[\dko])/i # Dell Streak
|
116
|
+
], [:vendor, :model, [:type, :tablet]], [
|
117
|
+
/\((ip[honed]+);.+(apple)/i # iPod/iPhone
|
118
|
+
], [:model, :vendor, [:name, :iphone], [:type, :handheld]], [
|
119
|
+
/(blackberry)[\s-]?(\w+)/i, # BlackBerry
|
120
|
+
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|huawei|meizu|motorola)[\s_-]?([\w-]+)*/i, # BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Huawei/Meizu/Motorola
|
121
|
+
/(hp)\s([\w\s]+\w)/i, # HP iPAQ
|
122
|
+
/(asus)-?(\w+)/i # Asus
|
123
|
+
], [:vendor, :model, [:type, :handheld]], [
|
124
|
+
/\((bb10);\s(\w+)/i # BlackBerry 10
|
125
|
+
], [[:vendor, 'BlackBerry'], :model, [:type, :handheld]], [
|
126
|
+
/android.+((transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+))/i # Asus Tablets
|
127
|
+
], [[:vendor, 'Asus'], :model, [:type, :tablet]], [
|
128
|
+
/(sony)\s(tablet\s[ps])/i # Sony Tablets
|
129
|
+
], [:vendor, :model, [:type, :tablet]], [
|
130
|
+
/(nintendo)\s([wids3u]+)/i # Nintendo
|
131
|
+
], [:vendor, :model, [:type, :console]], [
|
132
|
+
/((playstation)\s[3portablevi]+)/i # Playstation
|
133
|
+
], [[:vendor, 'Sony'], :model, [:type, :console]], [
|
134
|
+
/(sprint\s(\w+))/i # Sprint Phones
|
135
|
+
], [:vendor, :model, [:type, :handheld]], [
|
136
|
+
/(htc)[;_\s-]+([\w\s_]+(?=\))|\w+)*/i, # HTC
|
137
|
+
/(zte)-(\w+)*/i, # ZTE
|
138
|
+
/(alcatel|geeksphone|huawei|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]+)*/i # Alcatel/GeeksPhone/Huawei/Lenovo/Nexian/Panasonic/Sony
|
139
|
+
], [:vendor, [:model, lambda {|str| str.gsub(/_/, ' ') }], [:type, :handheld]], [
|
140
|
+
/\s((milestone|droid[2x]?))[globa\s]*\sbuild\//i, # Motorola
|
141
|
+
/(mot)[\s-]?(\w+)*/i
|
142
|
+
], [[:vendor, 'Motorola'], :model, [:type, :handheld]], [
|
143
|
+
/android.+\s((mz60\d|xoom[\s2]{0,2}))\sbuild\//i
|
144
|
+
], [[:vendor, 'Motorola'], :model, [:type, :tablet]], [
|
145
|
+
/android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n8000|sgh-t8[56]9))/i
|
146
|
+
], [[:vendor, 'Samsung'], :model, [:type, :tablet]], [
|
147
|
+
# Samsung
|
148
|
+
/((s[cgp]h-\w+|gt-\w+|galaxy\snexus))/i,
|
149
|
+
/(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i,
|
150
|
+
/sec-((sgh\w+))/i
|
151
|
+
], [[:vendor, 'Samsung'], :model, [:type, :handheld]], [
|
152
|
+
/(sie)-(\w+)*/i # Siemens
|
153
|
+
], [[:vendor, 'Siemens'], :model, [:type, :handheld]], [
|
154
|
+
/(maemo|nokia).*(n900|lumia\s\d+)/i, # Nokia
|
155
|
+
/(nokia)[\s_-]?([\w-]+)*/i
|
156
|
+
], [[:vendor, 'Nokia'], :model, [:type, :handheld]], [
|
157
|
+
/android\s3\.[-\s\w;]{10}((a\d{3}))/i # Acer
|
158
|
+
], [[:vendor, 'Acer'], :model, [:type, :tablet]], [
|
159
|
+
/android\s3\.[-\s\w;]{10}(lg?)-([06cv9]{3,4})/i # LG
|
160
|
+
], [[:vendor, 'LG'], :model, [:type, :tablet]], [
|
161
|
+
/((nexus\s4))/i,
|
162
|
+
/(lg)[-e;\s\/]+(\w+)*/i
|
163
|
+
], [[:vendor, 'LG'], :model, [:type, :handheld]], [
|
164
|
+
/opera\smobi/i,
|
165
|
+
/android/i
|
166
|
+
], [[:type, :handheld]], [
|
167
|
+
/nitro/i # Nintendo DS
|
168
|
+
], [[:type, :console]], [
|
169
|
+
/(mobile|tablet);.+rv\:.+gecko\//i # Unidentifiable
|
170
|
+
], [:type, :vendor, :model]
|
171
|
+
],
|
172
|
+
:engine => [
|
173
|
+
[
|
174
|
+
/(presto)\/((\d+)[\w\.]+)/i # Presto
|
175
|
+
], [:name, :version, :major, [:type, :presto]], [
|
176
|
+
/(webkit)\/((\d+)[\w\.]+)/i # WebKit
|
177
|
+
], [:name, :version, :major, [:type, :webkit]], [
|
178
|
+
/(trident)\/((\d+)[\w\.]+)/i # Trident
|
179
|
+
], [:name, :version, :major, [:type, :trident]], [
|
180
|
+
/(netfront|netsurf|amaya|lynx|w3m)\/((\d+)[\w\.]+)/i, # NetFront/NetSurf/Amaya/Lynx/w3m
|
181
|
+
/(khtml|tasman|links)[\/\s]\(?((\d+)[\w\.]+)/i, # KHTML/Tasman/Links
|
182
|
+
/(icab)[\/\s]([23]\.(\d+)[\d\.]+)/i # iCab
|
183
|
+
], [:name, :version, :major], [
|
184
|
+
/rv\:((\d+)[\w\.]+).*(gecko)/i # Gecko
|
185
|
+
], [:version, :major, :name, [:type, :gecko]]
|
186
|
+
],
|
187
|
+
:os => [
|
188
|
+
[
|
189
|
+
# Windows based
|
190
|
+
/(windows)\snt\s6\.2;\s(arm)/i, # Windows RT
|
191
|
+
/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i,
|
192
|
+
/(microsoft windows)/i
|
193
|
+
], [:name, [:version, STRING_MAP[:os][:windows][:version]], [:type, :windows]], [
|
194
|
+
/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
|
195
|
+
], [[:name, 'Windows'], [:version, STRING_MAP[:os][:windows][:version]], [:type, :windows]], [
|
196
|
+
# Mobile/Embedded OS
|
197
|
+
/\((bb)(10);/i # BlackBerry 10
|
198
|
+
], [[:name, 'BlackBerry'], :version, [:type, :blackberry]], [
|
199
|
+
/(blackberry)\w*\/?([\w\.]+)*/i, # Blackberry
|
200
|
+
/(rim\stablet\sos)[\/\s-]?([\w\.]+)*/i # RIM
|
201
|
+
], [:name, :version, [:type, :blackberry]], [
|
202
|
+
/(android)[\/\s-]?([\w\.]+)*/i # Android
|
203
|
+
], [:name, :version, [:type, :android]], [
|
204
|
+
/(tizen)\/([\w\.]+)/i, # Tizen
|
205
|
+
/(webos|palm\os|qnx|bada|meego)[\/\s-]?([\w\.]+)*/i # WebOS/Palm/QNX/Bada/MeeGo
|
206
|
+
], [:name, :version], [
|
207
|
+
/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i # Symbian
|
208
|
+
], [[:name, 'Symbian'], :version],[
|
209
|
+
/mozilla.+\(mobile;.+gecko.+firefox/i # Firefox OS
|
210
|
+
], [[:name, 'Firefox OS'], :version], [
|
211
|
+
# Console
|
212
|
+
/(nintendo|playstation)\s([wids3portablevu]+)/i, # Nintendo/Playstation
|
213
|
+
], [:name, :version], [
|
214
|
+
# GNU/Linux based
|
215
|
+
/(mint)[\/\s\(]?(\w+)*/i, # Mint
|
216
|
+
/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i, # Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk
|
217
|
+
/(hurd|linux)\s?([\w\.]+)*/i, # Hurd/Linux
|
218
|
+
/(gnu)\s?([\w\.]+)*/i # GNU
|
219
|
+
], [:name, :version, [:type, :linux]], [
|
220
|
+
/(cros)\s[\w]+\s([\w\.]+\w)/i # Chromium OS
|
221
|
+
], [[:name, 'Chromium OS'], :version],[
|
222
|
+
# Solaris
|
223
|
+
/(sunos)\s?([\w\.]+\d)*/i # Solaris
|
224
|
+
], [[:name, 'Solaris'], :version], [
|
225
|
+
# BSD based
|
226
|
+
/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i # FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
|
227
|
+
], [:name, :version],[
|
228
|
+
/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i # iOS
|
229
|
+
], [[:name, 'iOS'], [:version, lambda {|str| str.gsub(/_/, '.') }], [:type, :ios]], [
|
230
|
+
/(mac\sos\sx)\s?([\w\s\.]+\w)*/i # Mac OS
|
231
|
+
], [:name, [:version, lambda {|str| str.gsub(/_/, '.') }], [:type, :mac]], [
|
232
|
+
# Other
|
233
|
+
/(haiku)\s(\w+)/i, # Haiku
|
234
|
+
/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, # AIX
|
235
|
+
/(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i, # Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS
|
236
|
+
/(unix)\s?([\w\.]+)*/i # UNIX
|
237
|
+
], [:name, :version]
|
238
|
+
]
|
239
|
+
}
|
240
|
+
end
|
@@ -0,0 +1,405 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BrowserSnifferTest < ActiveSupport::TestCase
|
4
|
+
AGENTS = {
|
5
|
+
:ipad_old => {
|
6
|
+
:user_agent => "Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10",
|
7
|
+
:form_factor => :tablet,
|
8
|
+
:ios? => true,
|
9
|
+
:android? => false,
|
10
|
+
:desktop? => false,
|
11
|
+
:engine => :webkit,
|
12
|
+
:major_engine_version => 531,
|
13
|
+
:os => :ios,
|
14
|
+
:os_version => '3.2',
|
15
|
+
:browser => :safari,
|
16
|
+
:major_browser_version => 4
|
17
|
+
},
|
18
|
+
:ipad_new => {
|
19
|
+
:user_agent => "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10",
|
20
|
+
:form_factor => :tablet,
|
21
|
+
:ios? => true,
|
22
|
+
:android? => false,
|
23
|
+
:desktop? => false,
|
24
|
+
:engine => :webkit,
|
25
|
+
:major_engine_version => 531,
|
26
|
+
:os => :ios,
|
27
|
+
:os_version => '3.2',
|
28
|
+
:browser => :safari,
|
29
|
+
:major_browser_version => 4
|
30
|
+
},
|
31
|
+
:ipad_chrome => {
|
32
|
+
:user_agent => "Mozilla/5.0 (iPad; CPU OS 6_0_1 like Mac OS X; en-us) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/21.0.1180.82 Mobile/10A523 Safari/7534.48.3",
|
33
|
+
:form_factor => :tablet,
|
34
|
+
:ios? => true,
|
35
|
+
:android? => false,
|
36
|
+
:desktop? => false,
|
37
|
+
:engine => :webkit,
|
38
|
+
:major_engine_version => 534,
|
39
|
+
:os => :ios,
|
40
|
+
:os_version => '6.0.1',
|
41
|
+
:browser => :chrome,
|
42
|
+
:major_browser_version => 21
|
43
|
+
},
|
44
|
+
:iphone => {
|
45
|
+
:user_agent => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16",
|
46
|
+
:form_factor => :handheld,
|
47
|
+
:ios? => true,
|
48
|
+
:android? => false,
|
49
|
+
:desktop? => false,
|
50
|
+
:engine => :webkit,
|
51
|
+
:major_engine_version => 528,
|
52
|
+
:os => :ios,
|
53
|
+
:os_version => '3.1.2',
|
54
|
+
:browser => :safari,
|
55
|
+
:major_browser_version => 4
|
56
|
+
},
|
57
|
+
:ipod_touch => {
|
58
|
+
:user_agent => "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20",
|
59
|
+
:form_factor => :handheld,
|
60
|
+
:ios? => true,
|
61
|
+
:android? => false,
|
62
|
+
:desktop? => false,
|
63
|
+
:engine => :webkit,
|
64
|
+
:major_engine_version => 525,
|
65
|
+
:os => :ios,
|
66
|
+
:os_version => '2.2.1',
|
67
|
+
:browser => :safari,
|
68
|
+
:major_browser_version => 3
|
69
|
+
},
|
70
|
+
:nexus_one => {
|
71
|
+
:user_agent => "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
|
72
|
+
:form_factor => :handheld,
|
73
|
+
:ios? => false,
|
74
|
+
:android? => true,
|
75
|
+
:desktop? => false,
|
76
|
+
:engine => :webkit,
|
77
|
+
:major_engine_version => 533,
|
78
|
+
:os => :android,
|
79
|
+
:os_version => '2.2',
|
80
|
+
:browser => :safari,
|
81
|
+
:major_browser_version => 4
|
82
|
+
},
|
83
|
+
:htc_droid => {
|
84
|
+
:user_agent => "Mozilla/5.0 (Linux; U; Android 2.2; nl-nl; Desire_A8181 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
|
85
|
+
:form_factor => :handheld,
|
86
|
+
:ios? => false,
|
87
|
+
:android? => true,
|
88
|
+
:desktop? => false,
|
89
|
+
:engine => :webkit,
|
90
|
+
:major_engine_version => 533,
|
91
|
+
:os => :android,
|
92
|
+
:os_version => '2.2',
|
93
|
+
:browser => :safari,
|
94
|
+
:major_browser_version => 4
|
95
|
+
},
|
96
|
+
:bb_torch => {
|
97
|
+
:user_agent => "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1+",
|
98
|
+
:form_factor => :handheld,
|
99
|
+
:ios? => false,
|
100
|
+
:android? => false,
|
101
|
+
:desktop? => false,
|
102
|
+
:engine => :webkit,
|
103
|
+
:major_engine_version => 534,
|
104
|
+
:os => :blackberry,
|
105
|
+
:os_version => nil,
|
106
|
+
:browser => :safari,
|
107
|
+
:major_browser_version => 6
|
108
|
+
},
|
109
|
+
:bb_8830 => {
|
110
|
+
:user_agent => "BlackBerry8330/4.3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/105",
|
111
|
+
:form_factor => :handheld,
|
112
|
+
:ios? => false,
|
113
|
+
:android? => false,
|
114
|
+
:desktop? => false,
|
115
|
+
:engine => nil,
|
116
|
+
:major_engine_version => nil,
|
117
|
+
:os => :blackberry,
|
118
|
+
:os_version => '4.3.0',
|
119
|
+
:browser => nil,
|
120
|
+
:major_browser_version => nil
|
121
|
+
},
|
122
|
+
:kindle => {
|
123
|
+
:user_agent => "Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 600x800)",
|
124
|
+
:form_factor => :tablet,
|
125
|
+
:ios? => false,
|
126
|
+
:android? => false,
|
127
|
+
:desktop? => false,
|
128
|
+
:engine => nil,
|
129
|
+
:major_engine_version => 3,
|
130
|
+
:os => :linux,
|
131
|
+
:os_version => '2.6.22',
|
132
|
+
:browser => nil,
|
133
|
+
:major_browser_version => 2
|
134
|
+
},
|
135
|
+
:nokia_classic => {
|
136
|
+
:user_agent => "Nokia3120Classic/2.0 (06.20) Profile/MIDP-2.1 Configuration/CLDC-1.1",
|
137
|
+
:form_factor => :handheld,
|
138
|
+
:ios? => false,
|
139
|
+
:android? => false,
|
140
|
+
:desktop? => false,
|
141
|
+
:engine => nil,
|
142
|
+
:major_engine_version => nil,
|
143
|
+
:os => nil,
|
144
|
+
:os_version => nil,
|
145
|
+
:browser => nil,
|
146
|
+
:major_browser_version => nil
|
147
|
+
},
|
148
|
+
:nokia_3200 => {
|
149
|
+
:user_agent => "Nokia3200/1.0 (5.29) Profile/MIDP-1.0 Configuration/CLDC-1.0\nUP.Link/6.3.1.13.0",
|
150
|
+
:form_factor => :handheld,
|
151
|
+
:ios? => false,
|
152
|
+
:android? => false,
|
153
|
+
:desktop? => false,
|
154
|
+
:engine => nil,
|
155
|
+
:major_engine_version => nil,
|
156
|
+
:os => nil,
|
157
|
+
:os_version => nil,
|
158
|
+
:browser => nil,
|
159
|
+
:major_browser_version => nil
|
160
|
+
},
|
161
|
+
:att => {
|
162
|
+
:user_agent => "Opera/9.51 Beta (Microsoft Windows; PPC; Opera Mobi/1718; U; en)",
|
163
|
+
:form_factor => :handheld,
|
164
|
+
:ios? => false,
|
165
|
+
:android? => false,
|
166
|
+
:desktop? => false,
|
167
|
+
:engine => nil,
|
168
|
+
:major_engine_version => nil,
|
169
|
+
:os => :windows,
|
170
|
+
:os_version => nil,
|
171
|
+
:browser => :opera,
|
172
|
+
:major_browser_version => 9
|
173
|
+
},
|
174
|
+
:benq => {
|
175
|
+
:user_agent => "BenQ-CF61/1.00/WAP2.0/MIDP2.0/CLDC1.0 UP.Browser/6.3.0.4.c.1.102 (GUI) MMP/2.0",
|
176
|
+
:form_factor => :handheld,
|
177
|
+
:ios? => false,
|
178
|
+
:android? => false,
|
179
|
+
:desktop? => false,
|
180
|
+
:engine => nil,
|
181
|
+
:major_engine_version => nil,
|
182
|
+
:os => nil,
|
183
|
+
:os_version => nil,
|
184
|
+
:browser => nil,
|
185
|
+
:major_browser_version => nil
|
186
|
+
},
|
187
|
+
:dell_streak => {
|
188
|
+
:user_agent => "Mozilla/5.0 (Linux; U; Android 1.6; en-gb; Dell Streak Build/Donut AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/ 525.20.1",
|
189
|
+
:form_factor => :tablet,
|
190
|
+
:ios? => false,
|
191
|
+
:android? => true,
|
192
|
+
:desktop? => false,
|
193
|
+
:engine => :webkit,
|
194
|
+
:major_engine_version => 528,
|
195
|
+
:os => :android,
|
196
|
+
:os_version => '1.6',
|
197
|
+
:os => :android,
|
198
|
+
:major_browser_version => 3
|
199
|
+
},
|
200
|
+
:hp_ipaq => {
|
201
|
+
:user_agent => "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320; HP iPAQ h6300)",
|
202
|
+
:form_factor => :handheld,
|
203
|
+
:ios? => false,
|
204
|
+
:android? => false,
|
205
|
+
:desktop? => false,
|
206
|
+
:engine => nil,
|
207
|
+
:major_engine_version => nil,
|
208
|
+
:os => :windows,
|
209
|
+
:os_version => 'CE',
|
210
|
+
:browser => :ie,
|
211
|
+
:major_browser_version => 4
|
212
|
+
},
|
213
|
+
:nintendo_ds => {
|
214
|
+
:user_agent => "Mozilla/4.0 (compatible; MSIE 6.0; Nitro) Opera 8.50 [en Mozilla/4.0 (compatible; MSIE 6.0; Nitro) Opera 8.50 [ja]",
|
215
|
+
:form_factor => :console,
|
216
|
+
:ios? => false,
|
217
|
+
:android? => false,
|
218
|
+
:desktop? => false,
|
219
|
+
:engine => nil,
|
220
|
+
:major_engine_version => nil,
|
221
|
+
:os => nil,
|
222
|
+
:os_version => nil,
|
223
|
+
:browser => :opera,
|
224
|
+
:major_browser_version => 8
|
225
|
+
},
|
226
|
+
:firefox_linux => {
|
227
|
+
:user_agent => "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8",
|
228
|
+
:form_factor => :desktop,
|
229
|
+
:ios? => false,
|
230
|
+
:android? => false,
|
231
|
+
:desktop? => true,
|
232
|
+
:engine => :gecko,
|
233
|
+
:major_engine_version => 1,
|
234
|
+
:os => :linux,
|
235
|
+
:os_version => '10.04',
|
236
|
+
:browser => :firefox,
|
237
|
+
:major_browser_version => 3
|
238
|
+
},
|
239
|
+
:safari_mac => {
|
240
|
+
:user_agent => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-ca) AppleWebKit/534.6+ (KHTML, like Gecko) Version/5.0 Safari/533.16",
|
241
|
+
:form_factor => :desktop,
|
242
|
+
:ios? => false,
|
243
|
+
:android? => false,
|
244
|
+
:desktop? => true,
|
245
|
+
:engine => :webkit,
|
246
|
+
:major_engine_version => 534,
|
247
|
+
:os => :mac,
|
248
|
+
:os_version => '10.6.3',
|
249
|
+
:browser => :safari,
|
250
|
+
:major_browser_version => 5
|
251
|
+
},
|
252
|
+
:chrome_mac => {
|
253
|
+
:user_agent => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-US) AppleWebKit/534.6 (KHTML, like Gecko) Chrome/6.0.495.0 Safari/534.6",
|
254
|
+
:form_factor => :desktop,
|
255
|
+
:ios? => false,
|
256
|
+
:android? => false,
|
257
|
+
:desktop? => true,
|
258
|
+
:engine => :webkit,
|
259
|
+
:major_engine_version => 534,
|
260
|
+
:os => :mac,
|
261
|
+
:os_version => '10.6.3',
|
262
|
+
:browser => :chrome,
|
263
|
+
:major_browser_version => 6
|
264
|
+
},
|
265
|
+
:chrome_win => {
|
266
|
+
:user_agent => "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.125 Safari/533.4",
|
267
|
+
:form_factor => :desktop,
|
268
|
+
:ios? => false,
|
269
|
+
:android? => false,
|
270
|
+
:desktop? => true,
|
271
|
+
:engine => :webkit,
|
272
|
+
:major_engine_version => 533,
|
273
|
+
:os => :windows,
|
274
|
+
:os_version => 'Vista',
|
275
|
+
:browser => :chrome,
|
276
|
+
:major_browser_version => 5
|
277
|
+
},
|
278
|
+
:ie9 => {
|
279
|
+
:user_agent => "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)",
|
280
|
+
:form_factor => :desktop,
|
281
|
+
:ios? => false,
|
282
|
+
:android? => false,
|
283
|
+
:desktop? => true,
|
284
|
+
:engine => :trident,
|
285
|
+
:major_engine_version => 5,
|
286
|
+
:os => :windows,
|
287
|
+
:os_version => '7',
|
288
|
+
:browser => :ie,
|
289
|
+
:major_browser_version => 9
|
290
|
+
},
|
291
|
+
:ie8 => {
|
292
|
+
:user_agent => "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MDDC)",
|
293
|
+
:form_factor => :desktop,
|
294
|
+
:ios? => false,
|
295
|
+
:android? => false,
|
296
|
+
:desktop? => true,
|
297
|
+
:engine => :trident,
|
298
|
+
:major_engine_version => 4,
|
299
|
+
:os => :windows,
|
300
|
+
:os_version => '7',
|
301
|
+
:browser => :ie,
|
302
|
+
:major_browser_version => 8
|
303
|
+
},
|
304
|
+
:ie7 => {
|
305
|
+
:user_agent => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6.4; .NET CLR 1.1.4322; FDM; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)",
|
306
|
+
:form_factor => :desktop,
|
307
|
+
:ios? => false,
|
308
|
+
:android? => false,
|
309
|
+
:desktop? => true,
|
310
|
+
:engine => nil,
|
311
|
+
:major_engine_version => nil,
|
312
|
+
:os => :windows,
|
313
|
+
:os_version => 'XP',
|
314
|
+
:browser => :ie,
|
315
|
+
:major_browser_version => 7
|
316
|
+
},
|
317
|
+
:opera_win => {
|
318
|
+
:user_agent => "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.5.24 Version/10.54",
|
319
|
+
:form_factor => :desktop,
|
320
|
+
:ios? => false,
|
321
|
+
:android? => false,
|
322
|
+
:desktop? => true,
|
323
|
+
:engine => :presto,
|
324
|
+
:major_engine_version => 2,
|
325
|
+
:os => :windows,
|
326
|
+
:os_version => '7',
|
327
|
+
:browser => :opera,
|
328
|
+
:major_browser_version => 9
|
329
|
+
},
|
330
|
+
:wii => {
|
331
|
+
:user_agent => "Opera/9.00 (Nintendo Wii; U; ; 1038-58; Wii Shop Channel/1.0; en)",
|
332
|
+
:form_factor => :console,
|
333
|
+
:ios? => false,
|
334
|
+
:android? => false,
|
335
|
+
:desktop? => false,
|
336
|
+
:engine => nil,
|
337
|
+
:major_engine_version => nil,
|
338
|
+
:os => nil,
|
339
|
+
:os_version => 'Wii',
|
340
|
+
:browser => :opera,
|
341
|
+
:major_browser_version => 9
|
342
|
+
},
|
343
|
+
:springboard_launched_ipod_browser => {
|
344
|
+
:user_agent => "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8J2",
|
345
|
+
:form_factor => :handheld,
|
346
|
+
:ios? => true,
|
347
|
+
:android? => false,
|
348
|
+
:desktop? => false,
|
349
|
+
:engine => :webkit,
|
350
|
+
:major_engine_version => 533,
|
351
|
+
:os => :ios,
|
352
|
+
:os_version => '4.3.3',
|
353
|
+
:browser => nil,
|
354
|
+
:major_browser_version => 533
|
355
|
+
},
|
356
|
+
:ipod_os_4_3_3 => {
|
357
|
+
:user_agent => "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
|
358
|
+
:form_factor => :handheld,
|
359
|
+
:ios? => true,
|
360
|
+
:android? => false,
|
361
|
+
:desktop? => false,
|
362
|
+
:engine => :webkit,
|
363
|
+
:major_engine_version => 533,
|
364
|
+
:os => :ios,
|
365
|
+
:os_version => '4.3.3',
|
366
|
+
:browser => :safari,
|
367
|
+
:major_browser_version => 5
|
368
|
+
},
|
369
|
+
:iphone_4S => {
|
370
|
+
:user_agent => "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
|
371
|
+
:form_factor => :handheld,
|
372
|
+
:ios? => true,
|
373
|
+
:android? => false,
|
374
|
+
:desktop? => false,
|
375
|
+
:engine => :webkit,
|
376
|
+
:major_engine_version => 534,
|
377
|
+
:os => :ios,
|
378
|
+
:os_version => '5.0',
|
379
|
+
:browser => :safari,
|
380
|
+
:major_browser_version => 5
|
381
|
+
},
|
382
|
+
:ipad_ios5 => {
|
383
|
+
:user_agent => "Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
|
384
|
+
:form_factor => :tablet,
|
385
|
+
:ios? => true,
|
386
|
+
:android? => false,
|
387
|
+
:desktop? => false,
|
388
|
+
:engine => :webkit,
|
389
|
+
:major_engine_version => 534,
|
390
|
+
:os => :ios,
|
391
|
+
:os_version => '5.0',
|
392
|
+
:browser => :safari,
|
393
|
+
:major_browser_version => 5
|
394
|
+
}
|
395
|
+
}
|
396
|
+
|
397
|
+
AGENTS.each do |agent, attributes|
|
398
|
+
test "sniff #{agent} correctly" do
|
399
|
+
sniffer = BrowserSniffer.new(attributes[:user_agent])
|
400
|
+
attributes.except(:user_agent).each do |attribute, value|
|
401
|
+
assert_equal value, sniffer.send(attribute), "#{attribute.to_s} did not match"
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: browser_sniffer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Shopify
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Parses user agent strings and boils it all down to a few simple classifications.
|
47
|
+
email:
|
48
|
+
- gems@shopify.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gemspec.rb
|
54
|
+
- .gitignore
|
55
|
+
- .travis.yml
|
56
|
+
- Gemfile
|
57
|
+
- LICENSE.txt
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- browser_sniffer.gemspec
|
61
|
+
- init.rb
|
62
|
+
- lib/browser_sniffer.rb
|
63
|
+
- lib/browser_sniffer/patterns.rb
|
64
|
+
- lib/browser_sniffer/version.rb
|
65
|
+
- test/browser_sniffer_test.rb
|
66
|
+
- test/test_helper.rb
|
67
|
+
homepage: https://github.com/Shopify/browser_sniffer
|
68
|
+
licenses:
|
69
|
+
- GPLv2 & MIT
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.9.3
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
hash: -639204093017043880
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.8.25
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: ! '## Description'
|
95
|
+
test_files:
|
96
|
+
- test/browser_sniffer_test.rb
|
97
|
+
- test/test_helper.rb
|