user_agent_parser 2.0.0 → 2.1.4

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.

@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 63fba72411cd6f5a6abb1a1fc066479f60b50d14
4
+ data.tar.gz: a169357b37a9dbe604c73cd1e10414324c139b4a
5
+ SHA512:
6
+ metadata.gz: c4de6f103556c10c73080d12f6fda1db551a7a0b487a5ba0812fd11bac9db7b6c9773e57458843d2ce151c1717377eea1567bde79143f6f146b673eda29ef8da
7
+ data.tar.gz: dac63ba14206459b3ed336586c9b1a7a330b54b6be76297704f0313c240a699c591ed1f6ba854c2cd0db613b6479d8435f7c0c2d22b54fc5d6138cde2e6d3a8e
data/Readme.md CHANGED
@@ -43,6 +43,21 @@ parser.parse 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.5.24 Version/10.53'
43
43
  => #<UserAgentParser::UserAgent Opera 10.53 (Windows XP)>
44
44
  ```
45
45
 
46
+ In a larger application, you could store a parser in a global to avoid repeat pattern loading:
47
+
48
+ ```ruby
49
+ module MyApplication
50
+
51
+ # Instantiate the parser on load as it's quite expensive
52
+ USER_AGENT_PARSER = UserAgentParser::Parser.new
53
+
54
+ def self.user_agent_parser
55
+ USER_AGENT_PARSER
56
+ end
57
+
58
+ end
59
+ ```
60
+
46
61
  ## The pattern database
47
62
 
48
63
  The [ua-parser database](https://github.com/tobie/ua-parser/blob/master/regexes.yaml) is included via a [git submodule](http://help.github.com/submodules/). To update the database the submodule needs to be updated and the gem re-released (pull requests for this are very welcome!).
@@ -59,6 +74,17 @@ or when instantiating a `UserAgentParser::Parser`:
59
74
  UserAgentParser::Parser.new(patterns_path: '/some/path/to/regexes.yaml').parse(ua_string)
60
75
  ```
61
76
 
77
+ ## Binary: user_agent_parser
78
+
79
+ There is a binary called `user_agent_parser` that will read from
80
+ standard input, parse each line and print the result, for example:
81
+
82
+ ```ruby
83
+ $ cat SOME-FILE.json | user_agent_parser --format '%n %M' | distribution
84
+ ```
85
+
86
+ See `user_agent_parser -h` for more information.
87
+
62
88
  ## Contributing
63
89
 
64
90
  1. Fork
@@ -68,6 +94,19 @@ UserAgentParser::Parser.new(patterns_path: '/some/path/to/regexes.yaml').parse(u
68
94
 
69
95
  All accepted pull requests will earn you commit and release rights.
70
96
 
97
+ ## Releasing a new version
98
+
99
+ 1. Update the version in `user_agent_parser.gemspec`
100
+ 2. `git commit user_agent_parser.gemspec` with the following message format:
101
+
102
+ Version x.x.x
103
+
104
+ Changelog:
105
+ * Some new feature
106
+ * Some new bug fix
107
+ 3. `rake release`
108
+ 4. Create a [new Github release](https://github.com/toolmantim/user_agent_parser/releases/new)
109
+
71
110
  ## License
72
111
 
73
112
  MIT
@@ -0,0 +1,54 @@
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('--name', 'Print name only') do
12
+ options[:name] = true
13
+ end
14
+
15
+ opts.on('--version', 'Print version only') do
16
+ options[:version] = true
17
+ end
18
+
19
+ opts.on('--major', 'Print major version only') do
20
+ options[:major] = true
21
+ end
22
+
23
+ opts.on('--minor', 'Print minor version only') do
24
+ options[:minor] = true
25
+ end
26
+
27
+ opts.on('--os', 'Print operating system only') do
28
+ options[:os] = true
29
+ end
30
+
31
+ opts.on('--format format',
32
+ 'Print output in specified format. The available formatters are:',
33
+ ' - %n: name',
34
+ ' - %v: version',
35
+ ' - %M: major version',
36
+ ' - %m: minor version',
37
+ ' - %o: operating system'
38
+ ) do |format|
39
+ options[:format] = format
40
+ end
41
+
42
+ opts.on('-h', '--help', 'Display this screen') do
43
+ puts opts
44
+ exit
45
+ end
46
+ end
47
+
48
+ optparse.parse!
49
+
50
+ parser = UserAgentParser::Parser.new
51
+
52
+ ARGF.each do |line|
53
+ puts UserAgentParser::Cli.new(parser.parse(line), options).run!
54
+ end
@@ -0,0 +1,54 @@
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[:name]
10
+ @user_agent.name
11
+ elsif @options[:version]
12
+ with_version do |version|
13
+ version.to_s
14
+ end
15
+ elsif @options[:major]
16
+ major
17
+ elsif @options[:minor]
18
+ minor
19
+ elsif @options[:os]
20
+ @user_agent.os.to_s
21
+ elsif format = @options[:format]
22
+ format.gsub('%n', @user_agent.name).
23
+ gsub('%v', version.to_s).
24
+ gsub('%M', major.to_s).
25
+ gsub('%m', minor.to_s).
26
+ gsub('%o', @user_agent.os.to_s)
27
+ else
28
+ @user_agent.to_s
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def major
35
+ with_version do |version|
36
+ version.major
37
+ end
38
+ end
39
+
40
+ def minor
41
+ with_version do |version|
42
+ version.minor
43
+ end
44
+ end
45
+
46
+ def version
47
+ @version ||= @user_agent.version
48
+ end
49
+
50
+ def with_version(&block)
51
+ block.call(version) if version
52
+ end
53
+ end
54
+ end
@@ -71,7 +71,7 @@ module UserAgentParser
71
71
  end
72
72
 
73
73
  def user_agent_from_pattern_match(pattern, match, os = nil, device = nil)
74
- name, v1, v2, v3 = match[1], match[2], match[3], match[4]
74
+ name, v1, v2, v3, v4 = match[1], match[2], match[3], match[4], match[5]
75
75
 
76
76
  if pattern["family_replacement"]
77
77
  name = pattern["family_replacement"].sub('$1', name || '')
@@ -89,7 +89,11 @@ module UserAgentParser
89
89
  v3 = pattern["v3_replacement"].sub('$1', v3 || '')
90
90
  end
91
91
 
92
- version = version_from_segments(v1, v2, v3)
92
+ if pattern["v4_replacement"]
93
+ v4 = pattern["v4_replacement"].sub('$1', v4 || '')
94
+ end
95
+
96
+ version = version_from_segments(v1, v2, v3, v4)
93
97
 
94
98
  UserAgent.new(name, version, os, device)
95
99
  end
@@ -1,6 +1,11 @@
1
1
  user_agent_parsers:
2
2
  #### SPECIAL CASES TOP ####
3
3
 
4
+ # HbbTV standard defines what features the browser should understand.
5
+ # but it's like targeting "HTML5 browsers", effective browser support depends on the model
6
+ # See os_parsers if you want to target a specific TV
7
+ - regex: '(HbbTV)/(\d+)\.(\d+)\.(\d+) \('
8
+
4
9
  # must go before Firefox to catch SeaMonkey/Camino
5
10
  - regex: '(SeaMonkey|Camino)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)'
6
11
 
@@ -61,6 +66,14 @@ user_agent_parsers:
61
66
  - regex: '(Opera Mini)/att/(\d+)\.(\d+)'
62
67
  - regex: '(Opera)/9.80.*Version/(\d+)\.(\d+)(?:\.(\d+))?'
63
68
 
69
+ # Opera 14 for Android uses a WebKit render engine.
70
+ - regex: '(?:Mobile Safari).*(OPR)/(\d+)\.(\d+)\.(\d+)'
71
+ family_replacement: 'Opera Mobile'
72
+
73
+ # Opera 15 for Desktop is similar to Chrome but includes an "OPR" Version string.
74
+ - regex: '(?:Chrome).*(OPR)/(\d+)\.(\d+)\.(\d+)'
75
+ family_replacement: 'Opera'
76
+
64
77
  # Palm WebOS looks a lot like Safari.
65
78
  - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+))?'
66
79
  family_replacement: 'webOS Browser'
@@ -75,7 +88,7 @@ user_agent_parsers:
75
88
 
76
89
  # Lightning (for Thunderbird)
77
90
  # http://www.mozilla.org/projects/calendar/lightning/
78
- - regex: '(Lightning)/(\d+)\.(\d+)([ab]?\d+[a-z]*)'
91
+ - regex: '(Lightning)/(\d+)\.(\d+)\.?((?:[ab]?\d+[a-z]*)|(?:\d*))'
79
92
 
80
93
  # Swiftfox
81
94
  - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+(?:pre)?) \(Swiftfox\)'
@@ -84,7 +97,7 @@ user_agent_parsers:
84
97
  family_replacement: 'Swiftfox'
85
98
 
86
99
  # Rekonq
87
- - regex: '(rekonq)/(\d+)\.(\d+) Safari'
100
+ - regex: '(rekonq)/(\d+)\.(\d+)\.?(\d+)? Safari'
88
101
  family_replacement: 'Rekonq'
89
102
  - regex: 'rekonq'
90
103
  family_replacement: 'Rekonq'
@@ -133,9 +146,6 @@ user_agent_parsers:
133
146
  - regex: '(SLP Browser)/(\d+)\.(\d+)'
134
147
  family_replacement: 'Tizen Browser'
135
148
 
136
- # Epiphany browser (identifies as Chromium)
137
- - regex: '(Epiphany)/(\d+)\.(\d+).(\d+)'
138
-
139
149
  # Sogou Explorer 2.X
140
150
  - regex: '(SE 2\.X) MetaSr (\d+)\.(\d+)'
141
151
  family_replacement: 'Sogou Explorer'
@@ -154,6 +164,10 @@ user_agent_parsers:
154
164
  - regex: '(facebookexternalhit)/(\d+)\.(\d+)'
155
165
  family_replacement: 'FacebookBot'
156
166
 
167
+ # LinkedIn
168
+ - regex: '(LinkedInBot)/(\d+)\.(\d+)'
169
+ family_replacement: 'LinkedInBot'
170
+
157
171
  # Twitterbot
158
172
  - regex: '(Twitterbot)/(\d+)\.(\d+)'
159
173
  family_replacement: 'TwitterBot'
@@ -173,15 +187,49 @@ user_agent_parsers:
173
187
  - regex: '(Chrome)/(\d+)\.(\d+)\.(\d+).* MRCHROME'
174
188
  family_replacement: 'Mail.ru Chromium Browser'
175
189
 
190
+ # AOL Browser (IE-based)
191
+ - regex: '(AOL) (\d+)\.(\d+); AOLBuild (\d+)'
192
+
193
+
194
+
195
+
176
196
  #### END SPECIAL CASES TOP ####
177
197
 
178
198
  #### MAIN CASES - this catches > 50% of all browsers ####
179
199
 
180
200
  # Browser/major_version.minor_version.beta_version
181
- - regex: '(AdobeAIR|Chromium|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Shiira|Sunrise|Chrome|Flock|Netscape|Lunascape|WebPilot|Vodafone|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+)'
201
+ - regex: '(AdobeAIR|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Epiphany|Shiira|Sunrise|Flock|Netscape|Lunascape|WebPilot|Vodafone|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+)'
202
+
203
+ # Outlook 2007
204
+ - regex: 'MSOffice 12'
205
+ family_replacement: 'Outlook'
206
+ v1_replacement: '2007'
207
+
208
+ # Outlook 2010
209
+ - regex: 'MSOffice 14'
210
+ family_replacement: 'Outlook'
211
+ v1_replacement: '2010'
212
+
213
+ # Outlook 2013
214
+ - regex: 'Microsoft Outlook 15\.\d+\.\d+'
215
+ family_replacement: 'Outlook'
216
+ v1_replacement: '2013'
217
+
218
+ # Apple Air Mail
219
+ - regex: '(Airmail) (\d+)\.(\d+)(?:\.(\d+))?'
220
+
221
+ # Thunderbird
222
+ - regex: '(Thunderbird)/(\d+)\.(\d+)\.(\d+(?:pre)?)'
223
+ family_replacement: 'Thunderbird'
224
+
225
+ # Chrome/Chromium/major_version.minor_version.beta_version
226
+ - regex: '(Chromium|Chrome)/(\d+)\.(\d+)\.(\d+)'
182
227
 
183
228
  # Browser/major_version.minor_version
184
- - regex: '(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|Vodafone|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)/(\d+)\.(\d+)'
229
+ - 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|Vodafone|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)/(\d+)\.(\d+)'
230
+
231
+ # Chrome/Chromium/major_version.minor_version
232
+ - regex: '(Chromium|Chrome)/(\d+)\.(\d+)'
185
233
 
186
234
  # Browser major_version.minor_version.beta_version (space instead of slash)
187
235
  - regex: '(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\d+)\.(\d+)\.(\d+)'
@@ -219,10 +267,6 @@ user_agent_parsers:
219
267
  - regex: '(MSIE) (\d+)\.(\d+).*XBLWP7'
220
268
  family_replacement: 'IE Large Screen'
221
269
 
222
- # AFTER THE EDGE CASES ABOVE!
223
- - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+)'
224
- - regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*)?'
225
-
226
270
  #### END MAIN CASES ####
227
271
 
228
272
  #### SPECIAL CASES ####
@@ -338,6 +382,9 @@ user_agent_parsers:
338
382
  - regex: '(Pre)/(\d+)\.(\d+)'
339
383
  family_replacement: 'Palm Pre'
340
384
 
385
+ # fork of Links
386
+ - regex: '(ELinks)/(\d+)\.(\d+)'
387
+ - regex: '(ELinks) \((\d+)\.(\d+)'
341
388
  - regex: '(Links) \((\d+)\.(\d+)'
342
389
 
343
390
  - regex: '(QtWeb) Internet Browser/(\d+)\.(\d+)'
@@ -349,6 +396,9 @@ user_agent_parsers:
349
396
  - regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?'
350
397
  family_replacement: 'Amazon Silk'
351
398
 
399
+ # Phantomjs, should go before Safari
400
+ - regex: '(PhantomJS)/(\d+)\.(\d+)\.(\d+)'
401
+
352
402
  # WebKit Nightly
353
403
  - regex: '(AppleWebKit)/(\d+)\.?(\d+)?\+ .* Safari'
354
404
  family_replacement: 'WebKit Nightly'
@@ -372,13 +422,85 @@ user_agent_parsers:
372
422
  - regex: '(Phantom)/V(\d+)\.(\d+)'
373
423
  family_replacement: 'Phantom Browser'
374
424
 
375
- - regex: '(MSIE) (\d+)\.(\d+)'
425
+ - regex: 'Trident(.*)rv.(\d+)\.(\d+)'
426
+ family_replacement: 'IE'
427
+
428
+ # Apple Mail
429
+
430
+ # apple mail - not directly detectable, have it after Safari stuff
431
+ - regex: '(AppleWebKit)/(\d+)\.(\d+)\.(\d+)'
432
+ family_replacement: 'AppleMail'
433
+
434
+ # AFTER THE EDGE CASES ABOVE!
435
+ # AFTER IE11
436
+ # BEFORE all other IE
437
+ - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+)'
438
+ - regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*)?'
439
+
440
+ - regex: '([MS]?IE) (\d+)\.(\d+)'
376
441
  family_replacement: 'IE'
377
442
 
378
443
  - regex: '(python-requests)/(\d+)\.(\d+)'
379
444
  family_replacement: 'Python Requests'
380
445
 
381
446
  os_parsers:
447
+ ##########
448
+ # HbbTV vendors
449
+ ##########
450
+
451
+ # starts with the easy one : Panasonic seems consistent across years, hope it will continue
452
+ #HbbTV/1.1.1 (;Panasonic;VIERA 2011;f.532;0071-0802 2000-0000;)
453
+ #HbbTV/1.1.1 (;Panasonic;VIERA 2012;1.261;0071-3103 2000-0000;)
454
+ #HbbTV/1.2.1 (;Panasonic;VIERA 2013;3.672;4101-0003 0002-0000;)
455
+ #- regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Panasonic);VIERA ([0-9]{4});'
456
+
457
+ # Sony is consistent too but do not place year like the other
458
+ # Opera/9.80 (Linux armv7l; HbbTV/1.1.1 (; Sony; KDL32W650A; PKG3.211EUA; 2013;); ) Presto/2.12.362 Version/12.11
459
+ # Opera/9.80 (Linux mips; U; HbbTV/1.1.1 (; Sony; KDL40HX751; PKG1.902EUA; 2012;);; en) Presto/2.10.250 Version/11.60
460
+ # Opera/9.80 (Linux mips; U; HbbTV/1.1.1 (; Sony; KDL22EX320; PKG4.017EUA; 2011;);; en) Presto/2.7.61 Version/11.00
461
+ #- regex: 'HbbTV/\d+\.\d+\.\d+ \(; (Sony);.*;.*; ([0-9]{4});\)'
462
+
463
+
464
+ # LG is consistent too, but we need to add manually the year model
465
+ #Mozilla/5.0 (Unknown; Linux armv7l) AppleWebKit/537.1+ (KHTML, like Gecko) Safari/537.1+ HbbTV/1.1.1 ( ;LGE ;NetCast 4.0 ;03.20.30 ;1.0M ;)
466
+ #Mozilla/5.0 (DirectFB; Linux armv7l) AppleWebKit/534.26+ (KHTML, like Gecko) Version/5.0 Safari/534.26+ HbbTV/1.1.1 ( ;LGE ;NetCast 3.0 ;1.0 ;1.0M ;)
467
+ - regex: 'HbbTV/\d+\.\d+\.\d+ \( ;(LG)E ;NetCast 4.0'
468
+ os_v1_replacement: '2013'
469
+ - regex: 'HbbTV/\d+\.\d+\.\d+ \( ;(LG)E ;NetCast 3.0'
470
+ os_v1_replacement: '2012'
471
+
472
+ # Samsung is on its way of normalizing their user-agent
473
+ # HbbTV/1.1.1 (;Samsung;SmartTV2013;T-FXPDEUC-1102.2;;) WebKit
474
+ # HbbTV/1.1.1 (;Samsung;SmartTV2013;T-MST12DEUC-1102.1;;) WebKit
475
+ # HbbTV/1.1.1 (;Samsung;SmartTV2012;;;) WebKit
476
+ # HbbTV/1.1.1 (;;;;;) Maple_2011
477
+ - regex: 'HbbTV/1.1.1 \(;;;;;\) Maple_2011'
478
+ os_replacement: 'Samsung'
479
+ os_v1_replacement: '2011'
480
+ # manage the two models of 2013
481
+ - regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});.*FXPDEUC'
482
+ os_v2_replacement: 'UE40F7000'
483
+ - regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});.*MST12DEUC'
484
+ os_v2_replacement: 'UE32F4500'
485
+ # generic Samsung (works starting in 2012)
486
+ #- regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});'
487
+
488
+ # Philips : not found any other way than a manual mapping
489
+ # Opera/9.80 (Linux mips; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/4.1.3 PHILIPSTV/1.1.1; en) Presto/2.10.250 Version/11.60
490
+ # Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.2.1; en) Presto/2.6.33 Version/10.70
491
+ - regex: 'HbbTV/1.1.1 \(; (Philips);.*NETTV/4'
492
+ os_v1_replacement: '2013'
493
+ - regex: 'HbbTV/1.1.1 \(; (Philips);.*NETTV/3'
494
+ os_v1_replacement: '2012'
495
+ - regex: 'HbbTV/1.1.1 \(; (Philips);.*NETTV/2'
496
+ os_v1_replacement: '2011'
497
+
498
+ # the HbbTV emulator developers use HbbTV/1.1.1 (;;;;;) firetv-firefox-plugin 1.1.20
499
+ - regex: 'HbbTV/\d+\.\d+\.\d+.*(firetv)-firefox-plugin (\d+).(\d+).(\d+)'
500
+ os_replacement: 'FireHbbTV'
501
+
502
+ # generic HbbTV, hoping to catch manufacturer name (always after 2nd comma) and the first string that looks like a 2011-2019 year
503
+ - regex: 'HbbTV/\d+\.\d+\.\d+ \(.*; ?([a-zA-Z]+) ?;.*(201[1-9]).*\)'
382
504
 
383
505
  ##########
384
506
  # Android
@@ -420,7 +542,7 @@ os_parsers:
420
542
  # lots of ua strings have Windows NT 4.1 !?!?!?!? !?!? !? !????!?! !!! ??? !?!?! ?
421
543
  # (very) roughly ordered in terms of frequency of occurence of regex (win xp currently most frequent, etc)
422
544
  ##########
423
-
545
+
424
546
  - regex: '(Windows (?:NT 5\.2|NT 5\.1))'
425
547
  os_replacement: 'Windows XP'
426
548
 
@@ -435,6 +557,9 @@ os_parsers:
435
557
  - regex: '(Windows NT 6\.0)'
436
558
  os_replacement: 'Windows Vista'
437
559
 
560
+ - regex: '(Win 9x 4\.90)'
561
+ os_replacement: 'Windows Me'
562
+
438
563
  - regex: '(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\.0|Windows Vista|Windows 2000|Windows 3.1)'
439
564
 
440
565
  - regex: '(Windows NT 6\.2; ARM;)'
@@ -496,8 +621,6 @@ os_parsers:
496
621
 
497
622
  - regex: '(AppleTV)/(\d+)\.(\d+)'
498
623
  os_replacement: 'ATV OS X'
499
- os_v1_replacement: '$1'
500
- os_v2_replacement: '$2'
501
624
 
502
625
  ##########
503
626
  # Chrome OS
@@ -511,9 +634,10 @@ os_parsers:
511
634
  ##########
512
635
  # Linux distros
513
636
  ##########
514
- - regex: '(Debian)-(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?'
637
+ - regex: '([Dd]ebian)'
638
+ os_replacement: 'Debian'
515
639
  - regex: '(Linux Mint)(?:/(\d+))?'
516
- - regex: '(Mandriva)(?: Linux)?/(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?'
640
+ - regex: '(Mandriva)(?: Linux)?/(?:[\d.-]+m[a-z]{2}(\d+).(\d))?'
517
641
 
518
642
  ##########
519
643
  # Symbian + Symbian OS
@@ -554,7 +678,7 @@ os_parsers:
554
678
  ##########
555
679
  # Firefox OS
556
680
  ##########
557
- - regex: '\(Mobile;.+Firefox/\d+\.\d+'
681
+ - regex: '\((?:Mobile|Tablet);.+Firefox/\d+\.\d+'
558
682
  os_replacement: 'Firefox OS'
559
683
 
560
684
  ##########
@@ -573,7 +697,7 @@ os_parsers:
573
697
  ##########
574
698
  - regex: '(GoogleTV) (\d+)\.(\d+)\.(\d+)'
575
699
  # Old style
576
- - regex: '(GoogleTV)\/\d+'
700
+ - regex: '(GoogleTV)/[\da-z]+'
577
701
 
578
702
  - regex: '(WebTV)/(\d+).(\d+)'
579
703
 
@@ -589,16 +713,17 @@ os_parsers:
589
713
  # since the majority of os cases are very specific, these go last
590
714
  ##########
591
715
  # first.second.third.fourth bits
592
- - regex: '(SUSE|Fedora|Red Hat|PCLinuxOS)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
716
+ - regex: '(Fedora|Red Hat|PCLinuxOS)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
593
717
 
594
718
  # first.second.third bits
595
- - regex: '(SUSE|Fedora|Red Hat|Puppy|PCLinuxOS|CentOS)/(\d+)\.(\d+)\.(\d+)'
719
+ - regex: '(Red Hat|Puppy|PCLinuxOS)/(\d+)\.(\d+)\.(\d+)'
596
720
 
597
721
  # first.second bits
598
722
  - regex: '(Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Red Hat|Slackware)/(\d+)\.(\d+)'
599
723
 
600
724
  # just os
601
- - regex: '(Windows|OpenBSD|FreeBSD|NetBSD|Ubuntu|Kubuntu|Android|Arch Linux|CentOS|WeTab|Slackware)'
725
+ - regex: '(Windows|OpenBSD|FreeBSD|NetBSD|Android|WeTab)'
726
+ - regex: '(Ubuntu|Kubuntu|Arch Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red Hat|Fedora|PCLinuxOS|Gentoo|Mageia)'
602
727
  - regex: '(Linux)/(\d+)\.(\d+)'
603
728
  - regex: '(Linux|BSD)'
604
729
  - regex: 'SunOS'
@@ -675,6 +800,16 @@ device_parsers:
675
800
  device_replacement: 'Kindle Fire HD 8.9" WiFi'
676
801
  - regex: '(KFJWA Build)'
677
802
  device_replacement: 'Kindle Fire HD 8.9" 4G'
803
+ - regex: '(KFSOWI Build)'
804
+ device_replacement: 'Kindle Fire HD 7" WiFi'
805
+ - regex: '(KFTHWI Build)'
806
+ device_replacement: 'Kindle Fire HDX 7" WiFi'
807
+ - regex: '(KFTHWA Build)'
808
+ device_replacement: 'Kindle Fire HDX 7" 4G'
809
+ - regex: '(KFAPWI Build)'
810
+ device_replacement: 'Kindle Fire HDX 8.9" WiFi'
811
+ - regex: '(KFAPWA Build)'
812
+ device_replacement: 'Kindle Fire HDX 8.9" 4G'
678
813
  - regex: '(Kindle Fire)'
679
814
  - regex: '(Kindle)'
680
815
  - regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?'
@@ -683,11 +818,11 @@ device_parsers:
683
818
  #########
684
819
  # Android General Device Matching (far from perfect)
685
820
  #########
686
- - regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{2}; WOWMobile (.+) Build'
687
- - regex: 'Android[\- ][\d]+\.[\d]+\-update1; [A-Za-z]{2}\-[A-Za-z]{2}; (.+) Build'
688
- - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{2}; (.+) Build'
689
- - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+;[A-Za-z]{2}\-[A-Za-z]{2};(.+) Build'
690
- - regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{2}; (.+) Build'
821
+ - regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; WOWMobile (.+) Build'
822
+ - regex: 'Android[\- ][\d]+\.[\d]+\-update1; [A-Za-z]{2}\-[A-Za-z]{0,2}; (.+) Build'
823
+ - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; (.+) Build'
824
+ - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+;[A-Za-z]{2}\-[A-Za-z]{0,2};(.+) Build'
825
+ - regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; (.+) Build'
691
826
  - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; (.+) Build'
692
827
  - regex: 'Android[\- ][\d]+\.[\d]+; (.+) Build'
693
828
 
@@ -752,6 +887,16 @@ device_parsers:
752
887
  - regex: '(AppleTV)'
753
888
  device_replacement: 'AppleTV'
754
889
 
890
+ ##########
891
+ # Catch the google mobile crawler before checking for iPhones.
892
+ ##########
893
+
894
+ - regex: 'AdsBot-Google-Mobile'
895
+ device_replacement: 'Spider'
896
+
897
+ - regex: 'Googlebot-Mobile/(\d+).(\d+)'
898
+ device_replacement: 'Spider'
899
+
755
900
  ##########
756
901
  # complete but probably catches spoofs
757
902
  # iSTUFF
@@ -760,6 +905,7 @@ device_parsers:
760
905
  # cannot determine specific device type from ua string. (3g, 3gs, 4, etc)
761
906
  - regex: '(iPad) Simulator;'
762
907
  - regex: '(iPad);'
908
+ - regex: '(iPod) touch;'
763
909
  - regex: '(iPod);'
764
910
  - regex: '(iPhone) Simulator;'
765
911
  - regex: '(iPhone);'
@@ -854,6 +1000,12 @@ device_parsers:
854
1000
  - regex: 'Lenovo_([A-Za-z0-9]+)'
855
1001
  device_replacement: 'Lenovo $1'
856
1002
 
1003
+ ##########
1004
+ # HbbTV (European and Australian standard)
1005
+ # written before the LG regexes, as LG is making HbbTV too
1006
+ ##########
1007
+ - regex: '(HbbTV)/[0-9]+\.[0-9]+\.[0-9]+'
1008
+
857
1009
  ##########
858
1010
  # lg
859
1011
  ##########
@@ -963,6 +1115,6 @@ device_parsers:
963
1115
  ##########
964
1116
  # Spiders (this is hack...)
965
1117
  ##########
966
- - 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)'
1118
+ - 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)'
967
1119
  device_replacement: 'Spider'
968
1120
 
metadata CHANGED
@@ -1,26 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: user_agent_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
5
- prerelease:
4
+ version: 2.1.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Tim Lucas
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-18 00:00:00.000000000 Z
11
+ date: 2014-03-13 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: A simple, comprehensive Ruby gem for parsing user agent strings with
15
14
  the help of BrowserScope's UA database
16
15
  email: t@toolmantim.com
17
- executables: []
16
+ executables:
17
+ - user_agent_parser
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - MIT-LICENSE
22
22
  - Readme.md
23
+ - bin/user_agent_parser
23
24
  - lib/user_agent_parser.rb
25
+ - lib/user_agent_parser/cli.rb
24
26
  - lib/user_agent_parser/device.rb
25
27
  - lib/user_agent_parser/operating_system.rb
26
28
  - lib/user_agent_parser/parser.rb
@@ -30,27 +32,26 @@ files:
30
32
  homepage: http://github.com/toolmantim/user_agent_parser
31
33
  licenses:
32
34
  - MIT
35
+ metadata: {}
33
36
  post_install_message:
34
37
  rdoc_options: []
35
38
  require_paths:
36
39
  - lib
37
40
  required_ruby_version: !ruby/object:Gem::Requirement
38
- none: false
39
41
  requirements:
40
- - - ! '>='
42
+ - - ">="
41
43
  - !ruby/object:Gem::Version
42
44
  version: 1.8.7
43
45
  required_rubygems_version: !ruby/object:Gem::Requirement
44
- none: false
45
46
  requirements:
46
- - - ! '>='
47
+ - - ">="
47
48
  - !ruby/object:Gem::Version
48
49
  version: '0'
49
50
  requirements: []
50
51
  rubyforge_project:
51
- rubygems_version: 1.8.23
52
+ rubygems_version: 2.2.1
52
53
  signing_key:
53
- specification_version: 3
54
+ specification_version: 4
54
55
  summary: A simple, comprehensive Ruby gem for parsing user agent strings with the
55
56
  help of BrowserScope's UA database
56
57
  test_files: []