user_agent_parser 2.1.1 → 2.2.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.
Potentially problematic release.
This version of user_agent_parser might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Readme.md +19 -3
- data/bin/user_agent_parser +59 -0
- data/lib/user_agent_parser/cli.rb +58 -0
- data/lib/user_agent_parser/device.rb +7 -5
- data/lib/user_agent_parser/operating_system.rb +7 -5
- data/lib/user_agent_parser/parser.rb +6 -6
- data/lib/user_agent_parser/user_agent.rb +6 -7
- data/lib/user_agent_parser/version.rb +9 -4
- data/vendor/ua-parser/regexes.yaml +356 -94
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e6c42fb7a24030be52fa5c096b8af27e362bb02
|
4
|
+
data.tar.gz: 60cfeb6d90444739f7f81f0e035704e23b5597df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fe9aa53552e5fb33d04bdc412a4cfb684ef5e04cb75f0d3747a8036ae804891072f1114dba9729d243d7bb138e610f954ee108dc4d1dda025ac1155bf4e2445
|
7
|
+
data.tar.gz: 06ba11a996ca450f7db3a5fc5175c76d703e3cd2496013c0d09bc34a1f63cf8a145ee2a1fa1ee48b37152074ab6c12b98c0e4f62c9e305af59432f69d7fd10b3
|
data/Readme.md
CHANGED
@@ -2,9 +2,13 @@
|
|
2
2
|
|
3
3
|
UserAgentParser is a simple, comprehensive Ruby gem for parsing user agent strings. It uses [BrowserScope](http://www.browserscope.org/)'s [parsing patterns](https://github.com/tobie/ua-parser).
|
4
4
|
|
5
|
-
##
|
5
|
+
## Supported Rubies
|
6
6
|
|
7
|
-
* Ruby
|
7
|
+
* Ruby 2.1
|
8
|
+
* Ruby 2.0
|
9
|
+
* Ruby 1.9.3
|
10
|
+
* Ruby 1.9.2
|
11
|
+
* JRuby
|
8
12
|
|
9
13
|
## Installation
|
10
14
|
|
@@ -21,7 +25,7 @@ user_agent = UserAgentParser.parse 'Mozilla/5.0 (compatible; MSIE 9.0; Windows N
|
|
21
25
|
=> #<UserAgentParser::UserAgent IE 9.0 (Windows Vista)>
|
22
26
|
user_agent.to_s
|
23
27
|
=> "IE 9.0"
|
24
|
-
user_agent.
|
28
|
+
user_agent.family
|
25
29
|
=> "IE"
|
26
30
|
user_agent.version.to_s
|
27
31
|
=> "9.0"
|
@@ -74,6 +78,17 @@ or when instantiating a `UserAgentParser::Parser`:
|
|
74
78
|
UserAgentParser::Parser.new(patterns_path: '/some/path/to/regexes.yaml').parse(ua_string)
|
75
79
|
```
|
76
80
|
|
81
|
+
## Binary: user_agent_parser
|
82
|
+
|
83
|
+
There is a binary called `user_agent_parser` that will read from
|
84
|
+
standard input, parse each line and print the result, for example:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
$ cat SOME-FILE.json | user_agent_parser --format '%n %M' | distribution
|
88
|
+
```
|
89
|
+
|
90
|
+
See `user_agent_parser -h` for more information.
|
91
|
+
|
77
92
|
## Contributing
|
78
93
|
|
79
94
|
1. Fork
|
@@ -94,6 +109,7 @@ All accepted pull requests will earn you commit and release rights.
|
|
94
109
|
* Some new feature
|
95
110
|
* Some new bug fix
|
96
111
|
3. `rake release`
|
112
|
+
4. Create a [new Github release](https://github.com/toolmantim/user_agent_parser/releases/new)
|
97
113
|
|
98
114
|
## License
|
99
115
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
require 'user_agent_parser'
|
6
|
+
require 'user_agent_parser/cli'
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
|
10
|
+
optparse = OptionParser.new do|opts|
|
11
|
+
opts.on('--family', 'Print family only') do
|
12
|
+
options[:family] = true
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on('--name', 'Print name (alias for family) only') do
|
16
|
+
options[:family] = true
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on('--version', 'Print version only') do
|
20
|
+
options[:version] = true
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('--major', 'Print major version only') do
|
24
|
+
options[:major] = true
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on('--minor', 'Print minor version only') do
|
28
|
+
options[:minor] = true
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('--os', 'Print operating system only') do
|
32
|
+
options[:os] = true
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('--format format',
|
36
|
+
'Print output in specified format. The available formatters are:',
|
37
|
+
' - %f: family',
|
38
|
+
' - %n: name (alias for family)',
|
39
|
+
' - %v: version',
|
40
|
+
' - %M: major version',
|
41
|
+
' - %m: minor version',
|
42
|
+
' - %o: operating system'
|
43
|
+
) do |format|
|
44
|
+
options[:format] = format
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on('-h', '--help', 'Display this screen') do
|
48
|
+
puts opts
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
optparse.parse!
|
54
|
+
|
55
|
+
parser = UserAgentParser::Parser.new
|
56
|
+
|
57
|
+
ARGF.each do |line|
|
58
|
+
puts UserAgentParser::Cli.new(parser.parse(line), options).run!
|
59
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module UserAgentParser
|
2
|
+
class Cli
|
3
|
+
def initialize(user_agent, options = {})
|
4
|
+
@user_agent = user_agent
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def run!
|
9
|
+
if @options[:family]
|
10
|
+
@user_agent.family
|
11
|
+
elsif @options[:name]
|
12
|
+
@user_agent.name
|
13
|
+
elsif @options[:version]
|
14
|
+
with_version do |version|
|
15
|
+
version.to_s
|
16
|
+
end
|
17
|
+
elsif @options[:major]
|
18
|
+
major
|
19
|
+
elsif @options[:minor]
|
20
|
+
minor
|
21
|
+
elsif @options[:os]
|
22
|
+
@user_agent.os.to_s
|
23
|
+
elsif format = @options[:format]
|
24
|
+
format.
|
25
|
+
gsub('%f', @user_agent.family).
|
26
|
+
gsub('%n', @user_agent.name).
|
27
|
+
gsub('%v', version.to_s).
|
28
|
+
gsub('%M', major.to_s).
|
29
|
+
gsub('%m', minor.to_s).
|
30
|
+
gsub('%o', @user_agent.os.to_s)
|
31
|
+
else
|
32
|
+
@user_agent.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def major
|
39
|
+
with_version do |version|
|
40
|
+
version.major
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def minor
|
45
|
+
with_version do |version|
|
46
|
+
version.minor
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def version
|
51
|
+
@version ||= @user_agent.version
|
52
|
+
end
|
53
|
+
|
54
|
+
def with_version(&block)
|
55
|
+
block.call(version) if version
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
module UserAgentParser
|
2
2
|
class Device
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :family
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
alias_method :name, :family
|
6
|
+
|
7
|
+
def initialize(family = nil)
|
8
|
+
@family = family || 'Other'
|
7
9
|
end
|
8
10
|
|
9
11
|
def to_s
|
10
|
-
|
12
|
+
family
|
11
13
|
end
|
12
14
|
|
13
15
|
def inspect
|
@@ -15,7 +17,7 @@ module UserAgentParser
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def eql?(other)
|
18
|
-
self.class.eql?(other.class) &&
|
20
|
+
self.class.eql?(other.class) && family == other.family
|
19
21
|
end
|
20
22
|
|
21
23
|
alias_method :==, :eql?
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module UserAgentParser
|
2
2
|
class OperatingSystem
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :family, :version
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
alias_method :name, :family
|
6
|
+
|
7
|
+
def initialize(family = 'Other', version = nil)
|
8
|
+
@family = family
|
7
9
|
@version = version
|
8
10
|
end
|
9
11
|
|
10
12
|
def to_s
|
11
|
-
string =
|
13
|
+
string = family
|
12
14
|
unless version.nil?
|
13
15
|
string += " #{version}"
|
14
16
|
end
|
@@ -21,7 +23,7 @@ module UserAgentParser
|
|
21
23
|
|
22
24
|
def eql?(other)
|
23
25
|
self.class.eql?(other.class) &&
|
24
|
-
|
26
|
+
family == other.family &&
|
25
27
|
version == other.version
|
26
28
|
end
|
27
29
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
3
|
module UserAgentParser
|
4
|
-
|
4
|
+
|
5
5
|
class Parser
|
6
6
|
attr_reader :patterns_path
|
7
7
|
|
@@ -71,10 +71,10 @@ module UserAgentParser
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def user_agent_from_pattern_match(pattern, match, os = nil, device = nil)
|
74
|
-
|
74
|
+
family, v1, v2, v3, v4 = match[1], match[2], match[3], match[4], match[5]
|
75
75
|
|
76
76
|
if pattern["family_replacement"]
|
77
|
-
|
77
|
+
family = pattern["family_replacement"].sub('$1', family || '')
|
78
78
|
end
|
79
79
|
|
80
80
|
if pattern["v1_replacement"]
|
@@ -95,7 +95,7 @@ module UserAgentParser
|
|
95
95
|
|
96
96
|
version = version_from_segments(v1, v2, v3, v4)
|
97
97
|
|
98
|
-
UserAgent.new(
|
98
|
+
UserAgent.new(family, version, os, device)
|
99
99
|
end
|
100
100
|
|
101
101
|
def os_from_pattern_match(pattern, match)
|
@@ -137,8 +137,8 @@ module UserAgentParser
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def version_from_segments(*segments)
|
140
|
-
|
141
|
-
|
140
|
+
segments = segments.compact
|
141
|
+
segments.empty? ? nil : Version.new(*segments)
|
142
142
|
end
|
143
143
|
end
|
144
144
|
end
|
@@ -1,19 +1,18 @@
|
|
1
1
|
module UserAgentParser
|
2
2
|
class UserAgent
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :family, :version, :os, :device
|
4
4
|
|
5
|
-
|
6
|
-
alias_method :family, :name
|
5
|
+
alias_method :name, :family
|
7
6
|
|
8
|
-
def initialize(
|
9
|
-
@
|
7
|
+
def initialize(family = nil, version = nil, os = nil, device = nil)
|
8
|
+
@family = family || 'Other'
|
10
9
|
@version = version
|
11
10
|
@os = os
|
12
11
|
@device = device
|
13
12
|
end
|
14
13
|
|
15
14
|
def to_s
|
16
|
-
string =
|
15
|
+
string = family
|
17
16
|
string += " #{version}" if version
|
18
17
|
string
|
19
18
|
end
|
@@ -27,7 +26,7 @@ module UserAgentParser
|
|
27
26
|
|
28
27
|
def eql?(other)
|
29
28
|
self.class.eql?(other.class) &&
|
30
|
-
|
29
|
+
family == other.family &&
|
31
30
|
version == other.version &&
|
32
31
|
os == other.os
|
33
32
|
end
|
@@ -1,15 +1,20 @@
|
|
1
1
|
module UserAgentParser
|
2
2
|
class Version
|
3
3
|
|
4
|
-
# Private: Regex used to split version string into major, minor,
|
5
|
-
# and patch_minor.
|
4
|
+
# Private: Regex used to split string version string into major, minor,
|
5
|
+
# patch, and patch_minor.
|
6
6
|
SEGMENTS_REGEX = /\d+\-\d+|\d+[a-zA-Z]+$|\d+|[A-Za-z][0-9A-Za-z-]*$/
|
7
7
|
|
8
8
|
attr_reader :version
|
9
9
|
alias :to_s :version
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
|
11
|
+
def initialize(*args)
|
12
|
+
if args.length == 1 && args.first.is_a?(String)
|
13
|
+
@version = args.first.to_s.strip
|
14
|
+
else
|
15
|
+
@segments = args.map(&:to_s).map(&:strip)
|
16
|
+
@version = segments.join(".")
|
17
|
+
end
|
13
18
|
end
|
14
19
|
|
15
20
|
def major
|
@@ -6,8 +6,8 @@ user_agent_parsers:
|
|
6
6
|
# See os_parsers if you want to target a specific TV
|
7
7
|
- regex: '(HbbTV)/(\d+)\.(\d+)\.(\d+) \('
|
8
8
|
|
9
|
-
# must go before Firefox to catch SeaMonkey/Camino
|
10
|
-
- regex: '(SeaMonkey|Camino)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)'
|
9
|
+
# must go before Firefox to catch Chimera/SeaMonkey/Camino
|
10
|
+
- regex: '(Chimera|SeaMonkey|Camino)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)?'
|
11
11
|
|
12
12
|
# Firefox
|
13
13
|
- regex: '(Pale[Mm]oon)/(\d+)\.(\d+)\.?(\d+)?'
|
@@ -49,7 +49,7 @@ user_agent_parsers:
|
|
49
49
|
- regex: '(Navigator)/(\d+)\.(\d+)([ab]\d+)'
|
50
50
|
family_replacement: 'Netscape'
|
51
51
|
|
52
|
-
- regex: '(Netscape6)/(\d+)\.(\d+)
|
52
|
+
- regex: '(Netscape6)/(\d+)\.(\d+)\.?([ab]?\d+)?'
|
53
53
|
family_replacement: 'Netscape'
|
54
54
|
|
55
55
|
- regex: '(MyIBrow)/(\d+)\.(\d+)'
|
@@ -60,10 +60,13 @@ user_agent_parsers:
|
|
60
60
|
- regex: '(Opera Tablet).*Version/(\d+)\.(\d+)(?:\.(\d+))?'
|
61
61
|
- regex: '(Opera)/.+Opera Mobi.+Version/(\d+)\.(\d+)'
|
62
62
|
family_replacement: 'Opera Mobile'
|
63
|
+
- regex: '(Opera)/(\d+)\.(\d+).+Opera Mobi'
|
64
|
+
family_replacement: 'Opera Mobile'
|
65
|
+
- regex: 'Opera Mobi.+(Opera)(?:/|\s+)(\d+)\.(\d+)'
|
66
|
+
family_replacement: 'Opera Mobile'
|
63
67
|
- regex: 'Opera Mobi'
|
64
68
|
family_replacement: 'Opera Mobile'
|
65
|
-
- regex: '(Opera Mini)
|
66
|
-
- regex: '(Opera Mini)/att/(\d+)\.(\d+)'
|
69
|
+
- regex: '(Opera Mini)(?:/att)?/(\d+)\.(\d+)'
|
67
70
|
- regex: '(Opera)/9.80.*Version/(\d+)\.(\d+)(?:\.(\d+))?'
|
68
71
|
|
69
72
|
# Opera 14 for Android uses a WebKit render engine.
|
@@ -82,13 +85,13 @@ user_agent_parsers:
|
|
82
85
|
# http://luakit.org/projects/luakit/
|
83
86
|
- regex: '(luakit)'
|
84
87
|
family_replacement: 'LuaKit'
|
85
|
-
|
88
|
+
|
86
89
|
# Snowshoe
|
87
90
|
- regex: '(Snowshoe)/(\d+)\.(\d+).(\d+)'
|
88
91
|
|
89
92
|
# Lightning (for Thunderbird)
|
90
93
|
# http://www.mozilla.org/projects/calendar/lightning/
|
91
|
-
- regex: '(Lightning)/(\d+)\.(\d+)([ab]?\d+[a-z]*)'
|
94
|
+
- regex: '(Lightning)/(\d+)\.(\d+)\.?((?:[ab]?\d+[a-z]*)|(?:\d*))'
|
92
95
|
|
93
96
|
# Swiftfox
|
94
97
|
- regex: '(Firefox)/(\d+)\.(\d+)\.(\d+(?:pre)?) \(Swiftfox\)'
|
@@ -123,6 +126,28 @@ user_agent_parsers:
|
|
123
126
|
|
124
127
|
- regex: '(Minimo)'
|
125
128
|
|
129
|
+
- regex: 'PLAYSTATION 3.+WebKit'
|
130
|
+
family_replacement: 'NetFront NX'
|
131
|
+
- regex: 'PLAYSTATION 3'
|
132
|
+
family_replacement: 'NetFront'
|
133
|
+
- regex: '(PlayStation Portable)'
|
134
|
+
family_replacement: 'NetFront'
|
135
|
+
- regex: '(PlayStation Vita)'
|
136
|
+
family_replacement: 'NetFront NX'
|
137
|
+
|
138
|
+
- regex: 'AppleWebKit.+ (NX)/(\d+)\.(\d+)\.(\d+)'
|
139
|
+
family_replacement: 'NetFront NX'
|
140
|
+
- regex: '(Nintendo 3DS)'
|
141
|
+
family_replacement: 'NetFront NX'
|
142
|
+
|
143
|
+
# Amazon Silk, should go before Safari and Chrome Mobile
|
144
|
+
- regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?'
|
145
|
+
family_replacement: 'Amazon Silk'
|
146
|
+
|
147
|
+
|
148
|
+
# @ref: http://www.puffinbrowser.com
|
149
|
+
- regex: '(Puffin)/(\d+)\.(\d+)(?:\.(\d+))?'
|
150
|
+
|
126
151
|
# Chrome Mobile
|
127
152
|
- regex: '(CrMo)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
|
128
153
|
family_replacement: 'Chrome Mobile'
|
@@ -156,6 +181,14 @@ user_agent_parsers:
|
|
156
181
|
- regex: '(FlyFlow)/(\d+)\.(\d+)'
|
157
182
|
family_replacement: 'Baidu Explorer'
|
158
183
|
|
184
|
+
# QQ Browsers
|
185
|
+
- regex: '(MQQBrowser/Mini)(?:(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
|
186
|
+
family_replacement: 'QQ Browser Mini'
|
187
|
+
- regex: '(MQQBrowser)(?:/(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
|
188
|
+
family_replacement: 'QQ Browser Mobile'
|
189
|
+
- regex: '(QQBrowser)(?:/(\d+)(?:\.(\d+)\.(\d+)(?:\.(\d+))?)?)?'
|
190
|
+
family_replacement: 'QQ Browser'
|
191
|
+
|
159
192
|
# Pingdom
|
160
193
|
- regex: '(Pingdom.com_bot_version_)(\d+)\.(\d+)'
|
161
194
|
family_replacement: 'PingdomBot'
|
@@ -164,10 +197,18 @@ user_agent_parsers:
|
|
164
197
|
- regex: '(facebookexternalhit)/(\d+)\.(\d+)'
|
165
198
|
family_replacement: 'FacebookBot'
|
166
199
|
|
200
|
+
# LinkedIn
|
201
|
+
- regex: '(LinkedInBot)/(\d+)\.(\d+)'
|
202
|
+
family_replacement: 'LinkedInBot'
|
203
|
+
|
167
204
|
# Twitterbot
|
168
205
|
- regex: '(Twitterbot)/(\d+)\.(\d+)'
|
169
206
|
family_replacement: 'TwitterBot'
|
170
207
|
|
208
|
+
# Google Plus
|
209
|
+
- regex: 'Google.*/\+/web/snippet'
|
210
|
+
family_replacement: 'GooglePlusBot'
|
211
|
+
|
171
212
|
# Rackspace Monitoring
|
172
213
|
- regex: '(Rackspace Monitoring)/(\d+)\.(\d+)'
|
173
214
|
family_replacement: 'RackspaceBot'
|
@@ -191,25 +232,63 @@ user_agent_parsers:
|
|
191
232
|
#### MAIN CASES - this catches > 50% of all browsers ####
|
192
233
|
|
193
234
|
# Browser/major_version.minor_version.beta_version
|
194
|
-
- regex: '(AdobeAIR|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Epiphany|Shiira|Sunrise|Flock|Netscape|Lunascape|WebPilot|
|
235
|
+
- regex: '(AdobeAIR|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Epiphany|Shiira|Sunrise|Flock|Netscape|Lunascape|WebPilot|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iris|UP\.Browser|Bunjalloo|Google Earth|Raven for Mac|Openwave)/(\d+)\.(\d+)\.(\d+)'
|
236
|
+
|
237
|
+
# Outlook 2007
|
238
|
+
- regex: 'MSOffice 12'
|
239
|
+
family_replacement: 'Outlook'
|
240
|
+
v1_replacement: '2007'
|
241
|
+
|
242
|
+
# Outlook 2010
|
243
|
+
- regex: 'MSOffice 14'
|
244
|
+
family_replacement: 'Outlook'
|
245
|
+
v1_replacement: '2010'
|
246
|
+
|
247
|
+
# Outlook 2013
|
248
|
+
- regex: 'Microsoft Outlook 15\.\d+\.\d+'
|
249
|
+
family_replacement: 'Outlook'
|
250
|
+
v1_replacement: '2013'
|
251
|
+
|
252
|
+
# Apple Air Mail
|
253
|
+
- regex: '(Airmail) (\d+)\.(\d+)(?:\.(\d+))?'
|
254
|
+
|
255
|
+
# Thunderbird
|
256
|
+
- regex: '(Thunderbird)/(\d+)\.(\d+)\.(\d+(?:pre)?)'
|
257
|
+
family_replacement: 'Thunderbird'
|
195
258
|
|
196
259
|
# Chrome/Chromium/major_version.minor_version.beta_version
|
197
260
|
- regex: '(Chromium|Chrome)/(\d+)\.(\d+)\.(\d+)'
|
198
261
|
|
262
|
+
# Dolphin Browser
|
263
|
+
# @ref: http://www.dolphin.com
|
264
|
+
- regex: '\b(Dolphin)(?: |HDCN/|/INT\-)(\d+)\.(\d+)\.?(\d+)?'
|
265
|
+
|
199
266
|
# Browser/major_version.minor_version
|
200
|
-
- regex: '(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|
|
267
|
+
- regex: '(bingbot|Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Space Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen Browser|Polaris|Abrowser|Planetweb|ICE Browser|mDolphin)/(\d+)\.(\d+)\.?(\d+)?'
|
201
268
|
|
202
269
|
# Chrome/Chromium/major_version.minor_version
|
203
270
|
- regex: '(Chromium|Chrome)/(\d+)\.(\d+)'
|
204
271
|
|
272
|
+
##########
|
273
|
+
# IE Mobile needs to happen before Android to catch cases such as:
|
274
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920)...
|
275
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; ANZ821)...
|
276
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Orange)...
|
277
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Vodafone)...
|
278
|
+
##########
|
279
|
+
|
280
|
+
# IE Mobile
|
281
|
+
- regex: '(IEMobile)[ /](\d+)\.(\d+)'
|
282
|
+
family_replacement: 'IE Mobile'
|
283
|
+
|
205
284
|
# Browser major_version.minor_version.beta_version (space instead of slash)
|
206
285
|
- regex: '(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\d+)\.(\d+)\.(\d+)'
|
207
286
|
# Browser major_version.minor_version (space instead of slash)
|
208
287
|
- regex: '(iCab|Lunascape|Opera|Android|Jasmine|Polaris) (\d+)\.(\d+)\.?(\d+)?'
|
209
|
-
|
288
|
+
|
210
289
|
# Kindle WebKit
|
211
290
|
- regex: '(Kindle)/(\d+)\.(\d+)'
|
212
|
-
|
291
|
+
|
213
292
|
# weird android UAs
|
214
293
|
- regex: '(Android) Donut'
|
215
294
|
v1_replacement: '1'
|
@@ -230,18 +309,11 @@ user_agent_parsers:
|
|
230
309
|
- regex: '(Android) Honeycomb'
|
231
310
|
v1_replacement: '3'
|
232
311
|
|
233
|
-
# IE Mobile
|
234
|
-
- regex: '(IEMobile)[ /](\d+)\.(\d+)'
|
235
|
-
family_replacement: 'IE Mobile'
|
236
312
|
# desktop mode
|
237
313
|
# http://www.anandtech.com/show/3982/windows-phone-7-review
|
238
314
|
- regex: '(MSIE) (\d+)\.(\d+).*XBLWP7'
|
239
315
|
family_replacement: 'IE Large Screen'
|
240
316
|
|
241
|
-
# AFTER THE EDGE CASES ABOVE!
|
242
|
-
- regex: '(Firefox)/(\d+)\.(\d+)\.(\d+)'
|
243
|
-
- regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*)?'
|
244
|
-
|
245
317
|
#### END MAIN CASES ####
|
246
318
|
|
247
319
|
#### SPECIAL CASES ####
|
@@ -255,20 +327,6 @@ user_agent_parsers:
|
|
255
327
|
- regex: '(Maxthon|MyIE2|Uzbl|Shiira)'
|
256
328
|
v1_replacement: '0'
|
257
329
|
|
258
|
-
- regex: 'PLAYSTATION 3.+WebKit'
|
259
|
-
family_replacement: 'NetFront NX'
|
260
|
-
- regex: 'PLAYSTATION 3'
|
261
|
-
family_replacement: 'NetFront'
|
262
|
-
- regex: '(PlayStation Portable)'
|
263
|
-
family_replacement: 'NetFront'
|
264
|
-
- regex: '(PlayStation Vita)'
|
265
|
-
family_replacement: 'NetFront NX'
|
266
|
-
|
267
|
-
- regex: 'AppleWebKit.+ (NX)/(\d+)\.(\d+)\.(\d+)'
|
268
|
-
family_replacement: 'NetFront NX'
|
269
|
-
- regex: '(Nintendo 3DS)'
|
270
|
-
family_replacement: 'NetFront NX'
|
271
|
-
|
272
330
|
- regex: '(BrowseX) \((\d+)\.(\d+)\.(\d+)'
|
273
331
|
|
274
332
|
- regex: '(NCSA_Mosaic)/(\d+)\.(\d+)'
|
@@ -280,11 +338,12 @@ user_agent_parsers:
|
|
280
338
|
- regex: '(Embider)/(\d+)\.(\d+)'
|
281
339
|
family_replacement: 'Polaris'
|
282
340
|
|
283
|
-
- regex: '(BonEcho)/(\d+)\.(\d+)
|
341
|
+
- regex: '(BonEcho)/(\d+)\.(\d+)\.?([ab]?\d+)?'
|
284
342
|
family_replacement: 'Bon Echo'
|
285
343
|
|
286
|
-
|
287
|
-
|
344
|
+
# @note: iOS / OSX Applications
|
345
|
+
- regex: '(CFNetwork)(?:/(\d+)\.(\d+)\.?(\d+)?)?'
|
346
|
+
family_replacement: 'CFNetwork'
|
288
347
|
|
289
348
|
- regex: '(iPod).+Version/(\d+)\.(\d+)\.(\d+)'
|
290
349
|
family_replacement: 'Mobile Safari'
|
@@ -298,7 +357,7 @@ user_agent_parsers:
|
|
298
357
|
family_replacement: 'Mobile Safari'
|
299
358
|
- regex: '(iPad).*Version/(\d+)\.(\d+)'
|
300
359
|
family_replacement: 'Mobile Safari'
|
301
|
-
- regex: '(iPod|iPhone|iPad);.*CPU.*OS (\d+)(
|
360
|
+
- regex: '(iPod|iPhone|iPad);.*CPU.*OS (\d+)_(\d+)(?:_(\d+))?.*Mobile'
|
302
361
|
family_replacement: 'Mobile Safari'
|
303
362
|
- regex: '(iPod|iPhone|iPad)'
|
304
363
|
family_replacement: 'Mobile Safari'
|
@@ -315,8 +374,10 @@ user_agent_parsers:
|
|
315
374
|
- regex: '(QtCarBrowser)'
|
316
375
|
v1_replacement: '1'
|
317
376
|
|
318
|
-
- regex: '(iBrowser/Mini)(\d+).(\d+)'
|
377
|
+
- regex: '^(iBrowser/Mini)(\d+).(\d+)'
|
319
378
|
family_replacement: 'iBrowser Mini'
|
379
|
+
- regex: '^(iBrowser|iRAPP)/(\d+).(\d+)'
|
380
|
+
|
320
381
|
# nokia browsers
|
321
382
|
# based on: http://www.developer.nokia.com/Community/Wiki/User-Agent_headers_for_Nokia_devices
|
322
383
|
- regex: '^(Nokia)'
|
@@ -367,10 +428,6 @@ user_agent_parsers:
|
|
367
428
|
#- regex: '\(iPad;.+(Version)/(\d+)\.(\d+)(?:\.(\d+))?.*Safari/'
|
368
429
|
# family_replacement: 'iPad'
|
369
430
|
|
370
|
-
# Amazon Silk, should go before Safari
|
371
|
-
- regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?'
|
372
|
-
family_replacement: 'Amazon Silk'
|
373
|
-
|
374
431
|
# Phantomjs, should go before Safari
|
375
432
|
- regex: '(PhantomJS)/(\d+)\.(\d+)\.(\d+)'
|
376
433
|
|
@@ -397,10 +454,25 @@ user_agent_parsers:
|
|
397
454
|
- regex: '(Phantom)/V(\d+)\.(\d+)'
|
398
455
|
family_replacement: 'Phantom Browser'
|
399
456
|
|
400
|
-
- regex: '(
|
457
|
+
- regex: 'Trident(.*)rv.(\d+)\.(\d+)'
|
401
458
|
family_replacement: 'IE'
|
402
459
|
|
403
|
-
|
460
|
+
# Espial
|
461
|
+
- regex: '(Espial)/(\d+)(?:\.(\d+))?(?:\.(\d+))?'
|
462
|
+
|
463
|
+
# Apple Mail
|
464
|
+
|
465
|
+
# apple mail - not directly detectable, have it after Safari stuff
|
466
|
+
- regex: '(AppleWebKit)/(\d+)\.(\d+)\.(\d+)'
|
467
|
+
family_replacement: 'AppleMail'
|
468
|
+
|
469
|
+
# AFTER THE EDGE CASES ABOVE!
|
470
|
+
# AFTER IE11
|
471
|
+
# BEFORE all other IE
|
472
|
+
- regex: '(Firefox)/(\d+)\.(\d+)\.(\d+)'
|
473
|
+
- regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*)?'
|
474
|
+
|
475
|
+
- regex: '([MS]?IE) (\d+)\.(\d+)'
|
404
476
|
family_replacement: 'IE'
|
405
477
|
|
406
478
|
- regex: '(python-requests)/(\d+)\.(\d+)'
|
@@ -465,13 +537,22 @@ os_parsers:
|
|
465
537
|
# generic HbbTV, hoping to catch manufacturer name (always after 2nd comma) and the first string that looks like a 2011-2019 year
|
466
538
|
- regex: 'HbbTV/\d+\.\d+\.\d+ \(.*; ?([a-zA-Z]+) ?;.*(201[1-9]).*\)'
|
467
539
|
|
540
|
+
##########
|
541
|
+
# @note: Windows Phone needs to come before Windows NT 6.1 *and* before Android to catch cases such as:
|
542
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920)...
|
543
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; ANZ821)...
|
544
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Orange)...
|
545
|
+
# Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Vodafone)...
|
546
|
+
##########
|
547
|
+
|
548
|
+
- regex: '(Windows Phone) (?:OS[ /])?(\d+)\.(\d+)'
|
549
|
+
|
468
550
|
##########
|
469
551
|
# Android
|
470
552
|
# can actually detect rooted android os. do we care?
|
471
553
|
##########
|
472
|
-
- regex: '(Android) (\d+)\.(\d+)(?:[.\-]([a-z0-9]+))?'
|
473
|
-
|
474
|
-
|
554
|
+
- regex: '(Android)[ \-/](\d+)\.(\d+)(?:[.\-]([a-z0-9]+))?'
|
555
|
+
|
475
556
|
- regex: '(Android) Donut'
|
476
557
|
os_v1_replacement: '1'
|
477
558
|
os_v2_replacement: '2'
|
@@ -491,6 +572,17 @@ os_parsers:
|
|
491
572
|
- regex: '(Android) Honeycomb'
|
492
573
|
os_v1_replacement: '3'
|
493
574
|
|
575
|
+
# UCWEB
|
576
|
+
- regex: '^UCWEB.*; (Adr) (\d+)\.(\d+)(?:[.\-]([a-z0-9]+))?;'
|
577
|
+
os_replacement: 'Android'
|
578
|
+
- regex: '^UCWEB.*; (iPad OS|iPh OS) (\d+)_(\d+)(?:_(\d+))?;'
|
579
|
+
os_replacement: 'iOS'
|
580
|
+
- regex: '^UCWEB.*; (wds) (\d+)\.(\d+)(?:\.(\d+))?;'
|
581
|
+
os_replacement: 'Windows Phone'
|
582
|
+
# JUC
|
583
|
+
- regex: '^(JUC).*; ?U; ?(?:Android)?(\d+)\.(\d+)(?:[\.\-]([a-z0-9]+))?'
|
584
|
+
os_replacement: 'Android'
|
585
|
+
|
494
586
|
##########
|
495
587
|
# Kindle Android
|
496
588
|
##########
|
@@ -506,14 +598,18 @@ os_parsers:
|
|
506
598
|
# (very) roughly ordered in terms of frequency of occurence of regex (win xp currently most frequent, etc)
|
507
599
|
##########
|
508
600
|
|
509
|
-
|
510
|
-
os_replacement: 'Windows XP'
|
511
|
-
|
512
|
-
# ie mobile des ktop mode
|
601
|
+
# ie mobile desktop mode
|
513
602
|
# spoofs nt 6.1. must come before windows 7
|
514
603
|
- regex: '(XBLWP7)'
|
515
604
|
os_replacement: 'Windows Phone'
|
516
605
|
|
606
|
+
# @note: This needs to come before Windows NT 6.1
|
607
|
+
- regex: '(Windows ?Mobile)'
|
608
|
+
os_replacement: 'Windows Mobile'
|
609
|
+
|
610
|
+
- regex: '(Windows (?:NT 5\.2|NT 5\.1))'
|
611
|
+
os_replacement: 'Windows XP'
|
612
|
+
|
517
613
|
- regex: '(Windows NT 6\.1)'
|
518
614
|
os_replacement: 'Windows 7'
|
519
615
|
|
@@ -521,30 +617,37 @@ os_parsers:
|
|
521
617
|
os_replacement: 'Windows Vista'
|
522
618
|
|
523
619
|
- regex: '(Win 9x 4\.90)'
|
524
|
-
os_replacement: 'Windows
|
620
|
+
os_replacement: 'Windows ME'
|
525
621
|
|
526
622
|
- regex: '(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\.0|Windows Vista|Windows 2000|Windows 3.1)'
|
527
623
|
|
528
624
|
- regex: '(Windows NT 6\.2; ARM;)'
|
529
625
|
os_replacement: 'Windows RT'
|
530
|
-
|
531
|
-
# is this a spoof or is nt 6.2 out and about in some capacity?
|
532
626
|
- regex: '(Windows NT 6\.2)'
|
533
627
|
os_replacement: 'Windows 8'
|
534
628
|
|
629
|
+
- regex: '(Windows NT 6\.3; ARM;)'
|
630
|
+
os_replacement: 'Windows RT 8.1'
|
631
|
+
- regex: '(Windows NT 6\.3)'
|
632
|
+
os_replacement: 'Windows 8.1'
|
633
|
+
|
535
634
|
- regex: '(Windows NT 5\.0)'
|
536
635
|
os_replacement: 'Windows 2000'
|
537
636
|
|
538
|
-
- regex: '(Windows Phone) (\d+)\.(\d+)'
|
539
|
-
- regex: '(Windows Phone) OS (\d+)\.(\d+)'
|
540
|
-
- regex: '(Windows ?Mobile)'
|
541
|
-
os_replacement: 'Windows Mobile'
|
542
|
-
|
543
637
|
- regex: '(WinNT4.0)'
|
544
638
|
os_replacement: 'Windows NT 4.0'
|
545
639
|
|
546
|
-
- regex: '(
|
547
|
-
os_replacement: 'Windows
|
640
|
+
- regex: '(Windows ?CE)'
|
641
|
+
os_replacement: 'Windows CE'
|
642
|
+
|
643
|
+
- regex: 'Win ?(95|98|3.1|NT|ME|2000)'
|
644
|
+
os_replacement: 'Windows $1'
|
645
|
+
|
646
|
+
- regex: 'Win16'
|
647
|
+
os_replacement: 'Windows 3.1'
|
648
|
+
|
649
|
+
- regex: 'Win32'
|
650
|
+
os_replacement: 'Windows 95'
|
548
651
|
|
549
652
|
##########
|
550
653
|
# Tizen OS from Samsung
|
@@ -554,10 +657,36 @@ os_parsers:
|
|
554
657
|
|
555
658
|
##########
|
556
659
|
# Mac OS
|
557
|
-
# http://en.wikipedia.org/wiki/Mac_OS_X#Versions
|
660
|
+
# @ref: http://en.wikipedia.org/wiki/Mac_OS_X#Versions
|
661
|
+
# @ref: http://www.puredarwin.org/curious/versions
|
558
662
|
##########
|
559
663
|
- regex: '(Mac OS X) (\d+)[_.](\d+)(?:[_.](\d+))?'
|
560
|
-
|
664
|
+
# Leopard
|
665
|
+
- regex: ' (Dar)(win)/(9).(\d+).*\((?:i386|x86_64|Power Macintosh)\)'
|
666
|
+
os_replacement: 'Mac OS X'
|
667
|
+
os_v1_replacement: '10'
|
668
|
+
os_v2_replacement: '5'
|
669
|
+
# Snow Leopard
|
670
|
+
- regex: ' (Dar)(win)/(10).(\d+).*\((?:i386|x86_64)\)'
|
671
|
+
os_replacement: 'Mac OS X'
|
672
|
+
os_v1_replacement: '10'
|
673
|
+
os_v2_replacement: '6'
|
674
|
+
# Lion
|
675
|
+
- regex: ' (Dar)(win)/(11).(\d+).*\((?:i386|x86_64)\)'
|
676
|
+
os_replacement: 'Mac OS X'
|
677
|
+
os_v1_replacement: '10'
|
678
|
+
os_v2_replacement: '7'
|
679
|
+
# Mountain Lion
|
680
|
+
- regex: ' (Dar)(win)/(12).(\d+).*\((?:i386|x86_64)\)'
|
681
|
+
os_replacement: 'Mac OS X'
|
682
|
+
os_v1_replacement: '10'
|
683
|
+
os_v2_replacement: '8'
|
684
|
+
# Mavericks
|
685
|
+
- regex: ' (Dar)(win)/(13).(\d+).*\((?:i386|x86_64)\)'
|
686
|
+
os_replacement: 'Mac OS X'
|
687
|
+
os_v1_replacement: '10'
|
688
|
+
os_v2_replacement: '9'
|
689
|
+
|
561
690
|
# IE on Mac doesn't specify version number
|
562
691
|
- regex: 'Mac_PowerPC'
|
563
692
|
os_replacement: 'Mac OS'
|
@@ -571,7 +700,7 @@ os_parsers:
|
|
571
700
|
# iOS
|
572
701
|
# http://en.wikipedia.org/wiki/IOS_version_history
|
573
702
|
##########
|
574
|
-
- regex: '(CPU OS|iPhone OS) (\d+)_(\d+)(?:_(\d+))?'
|
703
|
+
- regex: '(CPU OS|iPhone OS|CPU iPhone) +(\d+)[_\.](\d+)(?:[_\.](\d+))?'
|
575
704
|
os_replacement: 'iOS'
|
576
705
|
|
577
706
|
# remaining cases are mostly only opera uas, so catch opera as to not catch iphone spoofs
|
@@ -585,6 +714,63 @@ os_parsers:
|
|
585
714
|
- regex: '(AppleTV)/(\d+)\.(\d+)'
|
586
715
|
os_replacement: 'ATV OS X'
|
587
716
|
|
717
|
+
# CFNetwork/Darwin - The specific CFNetwork or Darwin version determines
|
718
|
+
# whether the os maps to Mac OS, or iOS, or just Darwin.
|
719
|
+
# See: http://user-agents.me/cfnetwork-version-list
|
720
|
+
- regex: '(CFNetwork)/(5)48\.0\.3.* Darwin/11\.0\.0'
|
721
|
+
os_replacement: 'iOS'
|
722
|
+
- regex: '(CFNetwork)/(5)48\.(0)\.4.* Darwin/(1)1\.0\.0'
|
723
|
+
os_replacement: 'iOS'
|
724
|
+
- regex: '(CFNetwork)/(5)48\.(1)\.4'
|
725
|
+
os_replacement: 'iOS'
|
726
|
+
- regex: '(CFNetwork)/(4)85\.1(3)\.9'
|
727
|
+
os_replacement: 'iOS'
|
728
|
+
- regex: '(CFNetwork)/(6)09\.(1)\.4'
|
729
|
+
os_replacement: 'iOS'
|
730
|
+
- regex: '(CFNetwork)/(6)(0)9'
|
731
|
+
os_replacement: 'iOS'
|
732
|
+
- regex: '(CFNetwork)/6(7)2\.(1)\.13'
|
733
|
+
os_replacement: 'iOS'
|
734
|
+
- regex: '(CFNetwork)/6(7)2\.(1)\.(1)4'
|
735
|
+
os_replacement: 'iOS'
|
736
|
+
- regex: '(CF)(Network)/6(7)(2)\.1\.15'
|
737
|
+
os_replacement: 'iOS'
|
738
|
+
os_v1_replacement: '7'
|
739
|
+
os_v2_replacement: '1'
|
740
|
+
- regex: '(CFNetwork)/6(7)2\.(0)\.(?:2|8)'
|
741
|
+
os_replacement: 'iOS'
|
742
|
+
- regex: '(CFNetwork)/709\.1'
|
743
|
+
os_replacement: 'iOS'
|
744
|
+
os_v1_replacement: '8'
|
745
|
+
os_v2_replacement: '0.b5'
|
746
|
+
|
747
|
+
##########
|
748
|
+
# CFNetwork iOS Apps
|
749
|
+
# @ref: https://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
|
750
|
+
##########
|
751
|
+
- regex: 'CFNetwork/.* Darwin/(9)\.\d+'
|
752
|
+
os_replacement: 'iOS'
|
753
|
+
os_v1_replacement: '1'
|
754
|
+
- regex: 'CFNetwork/.* Darwin/(10)\.\d+'
|
755
|
+
os_replacement: 'iOS'
|
756
|
+
os_v1_replacement: '4'
|
757
|
+
- regex: 'CFNetwork/.* Darwin/(11)\.\d+'
|
758
|
+
os_replacement: 'iOS'
|
759
|
+
os_v1_replacement: '5'
|
760
|
+
- regex: 'CFNetwork/.* Darwin/(13)\.\d+'
|
761
|
+
os_replacement: 'iOS'
|
762
|
+
os_v1_replacement: '6'
|
763
|
+
- regex: 'CFNetwork/6.* Darwin/(14)\.\d+'
|
764
|
+
os_replacement: 'iOS'
|
765
|
+
os_v1_replacement: '7'
|
766
|
+
- regex: 'CFNetwork/7.* Darwin/(14)\.\d+'
|
767
|
+
os_replacement: 'iOS'
|
768
|
+
os_v1_replacement: '8'
|
769
|
+
os_v2_replacement: '0'
|
770
|
+
# iOS Apps
|
771
|
+
- regex: '\b(iOS[ /]|iPhone(?:/| v|[ _]OS[/,]|; | OS : |\d,\d/|\d,\d; )|iPad/)(\d{1,2})[_\.](\d{1,2})(?:[_\.](\d+))?'
|
772
|
+
os_replacement: 'iOS'
|
773
|
+
|
588
774
|
##########
|
589
775
|
# Chrome OS
|
590
776
|
# if version 0.0.0, probably this stuff:
|
@@ -606,7 +792,7 @@ os_parsers:
|
|
606
792
|
# Symbian + Symbian OS
|
607
793
|
# http://en.wikipedia.org/wiki/History_of_Symbian
|
608
794
|
##########
|
609
|
-
- regex: '(Symbian[Oo][Ss])/(\d+)\.(\d+)'
|
795
|
+
- regex: '(Symbian[Oo][Ss])[/ ](\d+)\.(\d+)'
|
610
796
|
os_replacement: 'Symbian OS'
|
611
797
|
- regex: '(Symbian/3).+NokiaBrowser/7\.3'
|
612
798
|
os_replacement: 'Symbian^3 Anna'
|
@@ -614,13 +800,15 @@ os_parsers:
|
|
614
800
|
os_replacement: 'Symbian^3 Belle'
|
615
801
|
- regex: '(Symbian/3)'
|
616
802
|
os_replacement: 'Symbian^3'
|
617
|
-
- regex: '(Series 60|SymbOS|S60)'
|
803
|
+
- regex: '\b(Series 60|SymbOS|S60Version|S60V\d|S60\b)'
|
618
804
|
os_replacement: 'Symbian OS'
|
619
805
|
- regex: '(MeeGo)'
|
620
806
|
- regex: 'Symbian [Oo][Ss]'
|
621
807
|
os_replacement: 'Symbian OS'
|
622
808
|
- regex: 'Series40;'
|
623
809
|
os_replacement: 'Nokia Series 40'
|
810
|
+
- regex: 'Series30Plus;'
|
811
|
+
os_replacement: 'Nokia Series 30 Plus'
|
624
812
|
|
625
813
|
##########
|
626
814
|
# BlackBerry devices
|
@@ -641,7 +829,7 @@ os_parsers:
|
|
641
829
|
##########
|
642
830
|
# Firefox OS
|
643
831
|
##########
|
644
|
-
- regex: '\(Mobile;.+Firefox/\d+\.\d+'
|
832
|
+
- regex: '\((?:Mobile|Tablet);.+Firefox/\d+\.\d+'
|
645
833
|
os_replacement: 'Firefox OS'
|
646
834
|
|
647
835
|
##########
|
@@ -658,12 +846,10 @@ os_parsers:
|
|
658
846
|
##########
|
659
847
|
# Google TV
|
660
848
|
##########
|
661
|
-
- regex: '(GoogleTV) (\d+)\.(\d+)
|
662
|
-
# Old style
|
663
|
-
- regex: '(GoogleTV)/[\da-z]+'
|
849
|
+
- regex: '(GoogleTV)(?: (\d+)\.(\d+)(?:\.(\d+))?|/[\da-z]+)'
|
664
850
|
|
665
851
|
- regex: '(WebTV)/(\d+).(\d+)'
|
666
|
-
|
852
|
+
|
667
853
|
##########
|
668
854
|
# Misc mobile
|
669
855
|
##########
|
@@ -675,20 +861,20 @@ os_parsers:
|
|
675
861
|
# Generic patterns
|
676
862
|
# since the majority of os cases are very specific, these go last
|
677
863
|
##########
|
678
|
-
|
679
|
-
- regex: '(Fedora|Red Hat|PCLinuxOS)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
|
864
|
+
- regex: '(Fedora|Red Hat|PCLinuxOS|Puppy|Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Slackware|(?:Free|Open|Net|\b)BSD)[/ ](\d+)\.(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
|
680
865
|
|
681
|
-
#
|
682
|
-
- regex: '(
|
866
|
+
# Gentoo Linux + Kernel Version
|
867
|
+
- regex: '(Linux)[ /](\d+)\.(\d+)(?:\.(\d+))?.*gentoo'
|
868
|
+
os_replacement: 'Gentoo'
|
683
869
|
|
684
|
-
#
|
685
|
-
- regex: '(
|
870
|
+
# Opera Mini Bada
|
871
|
+
- regex: '\((Bada);'
|
686
872
|
|
687
873
|
# just os
|
688
|
-
- regex: '(Windows|
|
689
|
-
- regex: '(Ubuntu|Kubuntu|Arch Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red Hat|Fedora|PCLinuxOS|Gentoo|Mageia)'
|
690
|
-
|
691
|
-
- regex: '(Linux
|
874
|
+
- regex: '(Windows|Android|WeTab|Maemo)'
|
875
|
+
- regex: '(Ubuntu|Kubuntu|Arch Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red Hat|Fedora|PCLinuxOS|Gentoo|Mageia|(?:Free|Open|Net|\b)BSD)'
|
876
|
+
# Linux + Kernel Version
|
877
|
+
- regex: '(Linux)(?:[ /](\d+)\.(\d+)(?:\.(\d+))?)?'
|
692
878
|
- regex: 'SunOS'
|
693
879
|
os_replacement: 'Solaris'
|
694
880
|
|
@@ -734,7 +920,29 @@ device_parsers:
|
|
734
920
|
# Samsung
|
735
921
|
- regex: '(SamsungSGHi560)'
|
736
922
|
device_replacement: 'Samsung SGHi560'
|
923
|
+
|
924
|
+
- regex: '(SCH-[A-Za-z0-9_-]+)'
|
925
|
+
device_replacement: 'Samsung $1'
|
926
|
+
|
927
|
+
- regex: '(SGH-[A-Za-z0-9_-]+)'
|
928
|
+
device_replacement: 'Samsung $1'
|
929
|
+
|
930
|
+
- regex: '(GT-[A-Za-z0-9_-]+)'
|
931
|
+
device_replacement: 'Samsung $1'
|
932
|
+
|
933
|
+
- regex: '(SM-[A-Za-z0-9_-]+)'
|
934
|
+
device_replacement: 'Samsung $1'
|
935
|
+
|
936
|
+
- regex: '(SPH-[A-Za-z0-9_-]+)'
|
937
|
+
device_replacement: 'Samsung $1'
|
737
938
|
|
939
|
+
- regex: 'SAMSUNG-([A-Za-z0-9_-]+)'
|
940
|
+
device_replacement: 'Samsung $1'
|
941
|
+
|
942
|
+
- regex: 'SAMSUNG ([A-Za-z0-9_-]+)'
|
943
|
+
device_replacement: 'Samsung $1'
|
944
|
+
|
945
|
+
|
738
946
|
#########
|
739
947
|
# Ericsson - must come before nokia since they also use symbian
|
740
948
|
#########
|
@@ -747,8 +955,8 @@ device_parsers:
|
|
747
955
|
##########
|
748
956
|
- regex: 'PLAYSTATION 3'
|
749
957
|
device_replacement: 'PlayStation 3'
|
750
|
-
- regex: '(PlayStation Portable)'
|
751
|
-
- regex: '(PlayStation
|
958
|
+
- regex: '(PlayStation (:?Portable|Vita))'
|
959
|
+
- regex: '(PlayStation (:?\d+))'
|
752
960
|
|
753
961
|
##########
|
754
962
|
# incomplete!
|
@@ -763,21 +971,22 @@ device_parsers:
|
|
763
971
|
device_replacement: 'Kindle Fire HD 8.9" WiFi'
|
764
972
|
- regex: '(KFJWA Build)'
|
765
973
|
device_replacement: 'Kindle Fire HD 8.9" 4G'
|
974
|
+
- regex: '(KFSOWI Build)'
|
975
|
+
device_replacement: 'Kindle Fire HD 7" WiFi'
|
976
|
+
- regex: '(KFTHWI Build)'
|
977
|
+
device_replacement: 'Kindle Fire HDX 7" WiFi'
|
978
|
+
- regex: '(KFTHWA Build)'
|
979
|
+
device_replacement: 'Kindle Fire HDX 7" 4G'
|
980
|
+
- regex: '(KFAPWI Build)'
|
981
|
+
device_replacement: 'Kindle Fire HDX 8.9" WiFi'
|
982
|
+
- regex: '(KFAPWA Build)'
|
983
|
+
device_replacement: 'Kindle Fire HDX 8.9" 4G'
|
766
984
|
- regex: '(Kindle Fire)'
|
767
985
|
- regex: '(Kindle)'
|
768
986
|
- regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?'
|
769
987
|
device_replacement: 'Kindle Fire'
|
770
988
|
|
771
|
-
|
772
|
-
# Android General Device Matching (far from perfect)
|
773
|
-
#########
|
774
|
-
- regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; WOWMobile (.+) Build'
|
775
|
-
- regex: 'Android[\- ][\d]+\.[\d]+\-update1; [A-Za-z]{2}\-[A-Za-z]{0,2}; (.+) Build'
|
776
|
-
- regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; (.+) Build'
|
777
|
-
- regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+;[A-Za-z]{2}\-[A-Za-z]{0,2};(.+) Build'
|
778
|
-
- regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; (.+) Build'
|
779
|
-
- regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; (.+) Build'
|
780
|
-
- regex: 'Android[\- ][\d]+\.[\d]+; (.+) Build'
|
989
|
+
|
781
990
|
|
782
991
|
##########
|
783
992
|
# NOKIA
|
@@ -849,7 +1058,16 @@ device_parsers:
|
|
849
1058
|
|
850
1059
|
- regex: 'Googlebot-Mobile/(\d+).(\d+)'
|
851
1060
|
device_replacement: 'Spider'
|
1061
|
+
|
1062
|
+
- regex: 'Googlebot/\d+.\d+'
|
1063
|
+
device_replacement: 'Spider'
|
1064
|
+
|
1065
|
+
- regex: 'NING/(\d+).(\d+)'
|
1066
|
+
device_replacement: 'Spider'
|
852
1067
|
|
1068
|
+
- regex: 'MsnBot-Media /(\d+).(\d+)'
|
1069
|
+
device_replacement: 'Spider'
|
1070
|
+
|
853
1071
|
##########
|
854
1072
|
# complete but probably catches spoofs
|
855
1073
|
# iSTUFF
|
@@ -878,7 +1096,14 @@ device_parsers:
|
|
878
1096
|
device_replacement: 'Alcatel $1'
|
879
1097
|
- regex: 'Alcatel-([A-Za-z0-9]+)'
|
880
1098
|
device_replacement: 'Alcatel $1'
|
881
|
-
|
1099
|
+
- regex: 'ALCATEL_ONE_TOUCH_([A-Za-z0-9]+)'
|
1100
|
+
device_replacement: 'Alcatel ONE TOUCH $1'
|
1101
|
+
- regex: 'ALCATEL (ONE TOUCH [A-Za-z0-9]+)'
|
1102
|
+
device_replacement: 'Alcatel $1'
|
1103
|
+
- regex: 'ALCATEL (one touch [A-Za-z0-9]+)'
|
1104
|
+
device_replacement: 'Alcatel $1'
|
1105
|
+
- regex: 'ALCATEL ([A-Za-z0-9]+)'
|
1106
|
+
device_replacement: 'Alcatel $1'
|
882
1107
|
##########
|
883
1108
|
# Amoi
|
884
1109
|
##########
|
@@ -997,6 +1222,14 @@ device_parsers:
|
|
997
1222
|
device_replacement: 'Motorola $1'
|
998
1223
|
- regex: 'MOT\-([A-Za-z0-9]+)'
|
999
1224
|
device_replacement: 'Motorola $1'
|
1225
|
+
- regex: ' (DROID RAZR [A-Za-z0-9 ]+) '
|
1226
|
+
device_replacement: 'Motorola $1'
|
1227
|
+
- regex: ' (DROID[2 ][A-Za-z0-9 ]+) '
|
1228
|
+
device_replacement: 'Motorola $1'
|
1229
|
+
- regex: ' (Droid2| )'
|
1230
|
+
device_replacement: 'Motorola $1'
|
1231
|
+
- regex: ' (DROID2| )'
|
1232
|
+
device_replacement: 'Motorola $1'
|
1000
1233
|
|
1001
1234
|
##########
|
1002
1235
|
# nintendo
|
@@ -1027,6 +1260,16 @@ device_parsers:
|
|
1027
1260
|
device_replacement: 'Samsung $1'
|
1028
1261
|
- regex: 'SAMSUNG\; ([A-Za-z0-9\-]+)'
|
1029
1262
|
device_replacement: 'Samsung $1'
|
1263
|
+
|
1264
|
+
##########
|
1265
|
+
# ZTE
|
1266
|
+
##########
|
1267
|
+
- regex: 'ZTE-([A-Za-z0-9\-]+)'
|
1268
|
+
device_replacement: 'ZTE $1'
|
1269
|
+
- regex: 'ZTE ([A-Za-z0-9\-]+)'
|
1270
|
+
device_replacement: 'ZTE $1'
|
1271
|
+
- regex: 'ZTE_([A-Za-z0-9\-]+)'
|
1272
|
+
device_replacement: 'ZTE $1'
|
1030
1273
|
|
1031
1274
|
##########
|
1032
1275
|
# Sega
|
@@ -1042,11 +1285,30 @@ device_parsers:
|
|
1042
1285
|
- regex: 'Softbank/2\.0/([A-Za-z0-9]+)'
|
1043
1286
|
device_replacement: 'Softbank $1'
|
1044
1287
|
|
1288
|
+
##########
|
1289
|
+
# SONY #
|
1290
|
+
##########
|
1291
|
+
- regex: 'Sony([^ ]+) '
|
1292
|
+
device_replacement: 'Sony $1'
|
1293
|
+
|
1045
1294
|
##########
|
1046
1295
|
# WebTV
|
1047
1296
|
##########
|
1048
1297
|
- regex: '(WebTV)/(\d+).(\d+)'
|
1049
1298
|
|
1299
|
+
#########
|
1300
|
+
# Android General Device Matching (far from perfect)
|
1301
|
+
#########
|
1302
|
+
- regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; [^;]+; ([A-Za-z0-9 _-]+) '
|
1303
|
+
- regex: 'Android[\- ][\d]+\.[\d]+; [^;]+; ([A-Za-z0-9 _-]+) '
|
1304
|
+
- regex: 'Android[\- ][\d]+\.[\d]+; [^;]+; WOWMobile ([A-Za-z0-9 _-]+) '
|
1305
|
+
- regex: 'Android[\- ][\d]+\.[\d]+\-update1; [^;]+; ([A-Za-z0-9 _-]+) '
|
1306
|
+
- regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+;[^;]+;([A-Za-z0-9 _-]+) '
|
1307
|
+
- regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; ([A-Za-z0-9 _-]+) '
|
1308
|
+
- regex: 'Android[\- ][\d]+\.[\d]+; ([A-Za-z0-9 _-]+) '
|
1309
|
+
- regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; [^;]+; ([A-Za-z0-9\.\/_-]+) '
|
1310
|
+
- regex: 'Android[\- ][\d]+\.[\d]+; [^;]+; ([A-Za-z0-9\.\/_-]+) '
|
1311
|
+
|
1050
1312
|
##########
|
1051
1313
|
# Generic Smart Phone
|
1052
1314
|
##########
|
@@ -1068,6 +1330,6 @@ device_parsers:
|
|
1068
1330
|
##########
|
1069
1331
|
# Spiders (this is hack...)
|
1070
1332
|
##########
|
1071
|
-
- regex: '(bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\-webcrawler|converacrawler|dataparksearch|findlinks|crawler)'
|
1333
|
+
- regex: '(bingbot|bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\-webcrawler|converacrawler|dataparksearch|findlinks|crawler|Netvibes|Sogou Pic Spider|ICC\-Crawler|Innovazion Crawler|Daumoa|EtaoSpider|A6\-Indexer|YisouSpider|Riddler|DBot|wsr\-agent|Xenu|SeznamBot|PaperLiBot|SputnikBot|CCBot|ProoXiBot|Scrapy|Genieo|Screaming Frog|YahooCacheSystem|CiBra|Nutch)'
|
1072
1334
|
device_replacement: 'Spider'
|
1073
1335
|
|
metadata
CHANGED
@@ -1,25 +1,28 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: user_agent_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Lucas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A simple, comprehensive Ruby gem for parsing user agent strings with
|
14
14
|
the help of BrowserScope's UA database
|
15
15
|
email: t@toolmantim.com
|
16
|
-
executables:
|
16
|
+
executables:
|
17
|
+
- user_agent_parser
|
17
18
|
extensions: []
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
20
21
|
- MIT-LICENSE
|
21
22
|
- Readme.md
|
23
|
+
- bin/user_agent_parser
|
22
24
|
- lib/user_agent_parser.rb
|
25
|
+
- lib/user_agent_parser/cli.rb
|
23
26
|
- lib/user_agent_parser/device.rb
|
24
27
|
- lib/user_agent_parser/operating_system.rb
|
25
28
|
- lib/user_agent_parser/parser.rb
|
@@ -46,7 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
49
|
version: '0'
|
47
50
|
requirements: []
|
48
51
|
rubyforge_project:
|
49
|
-
rubygems_version: 2.
|
52
|
+
rubygems_version: 2.2.2
|
50
53
|
signing_key:
|
51
54
|
specification_version: 4
|
52
55
|
summary: A simple, comprehensive Ruby gem for parsing user agent strings with the
|