device_detector 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c4c30ed187479291cfd7f71cff4db8bffd0c69b4
4
+ data.tar.gz: 3e2af5d2b3b5cfb9f7ee9d30b47c976d3a2230d8
5
+ SHA512:
6
+ metadata.gz: 28cc68b8699240a8fa4f099792c25ed73bc2dade2fecc30d2c9c678c88043816cde9667f80735fb15b9811d001f06fa19ec2f27cee03e54e23b31b90f3436d74
7
+ data.tar.gz: 2f9fc0bbde16054f926247af64027d63a91ee6601d2e4c8459cbba94cb07636e07c83d13a000a8329d297a4c2f6afb4c18e8d62b30220f42edcd9ddaed00149b
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in device_detector.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Mati Sójka
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ # DeviceDetector
2
+
3
+ This is a Ruby port of the Universal Device Detection library. You can find the original code here: [https://github.com/piwik/device-detector].
4
+
5
+ The Universal Device Detection library will parse any User Agent and detect the browser, operating system, device used (desktop, tablet, mobile, tv, cars, console, etc.), brand and model.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'device_detector'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install device_detector
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ user_agent = 'foo'
27
+ detector = DeviceDetector.new(user_agent)
28
+
29
+ os = detector.os # extract the operating system details
30
+ os.name # => Mac
31
+ os.full_version # => '10_8_5'
32
+
33
+ client = detector.client # extract the client (browser, device, feed reader) details
34
+ client.name # => Chrome
35
+ client.full_version # => '30.0.1599.69'
36
+ ```
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it ( https://github.com/[my-github-username]/device_detector/fork )
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create a new Pull Request
@@ -0,0 +1,11 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task default: :spec
11
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'device_detector/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'device_detector'
8
+ spec.version = DeviceDetector::VERSION
9
+ spec.authors = ['Mati Sójka', 'Ben Zimmer']
10
+ spec.email = ['yagooar@gmail.com']
11
+ spec.summary = %q{Universal Device Detection}
12
+ spec.description = %q{The Universal Device Detection library will parse any User Agent and detect the browser, operating system, device, brand and model.}
13
+ spec.homepage = 'https://github.com/podigee/device_detector'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = []
18
+ spec.test_files = spec.files.grep(%r{^(spec)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'rspec' ,'~> 3.1', '>= 3.1.0'
22
+ spec.add_development_dependency 'pry', '~> 0.10'
23
+ end
@@ -0,0 +1,31 @@
1
+ require 'yaml'
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+
6
+ require 'device_detector/version'
7
+ require 'device_detector/version_extractor'
8
+ require 'device_detector/os'
9
+ require 'device_detector/client'
10
+ require 'device_detector/os_detector'
11
+ require 'device_detector/client_detector'
12
+
13
+ class DeviceDetector
14
+
15
+ ROOT = Pathname.new(File.expand_path('../..', __FILE__))
16
+
17
+ attr_reader :user_agent
18
+
19
+ def initialize(user_agent)
20
+ @user_agent = user_agent
21
+ end
22
+
23
+ def os
24
+ OSDetector.new(user_agent).call
25
+ end
26
+
27
+ def client
28
+ ClientDetector.new(user_agent).call
29
+ end
30
+
31
+ end
@@ -0,0 +1,18 @@
1
+ class DeviceDetector
2
+ class Client
3
+
4
+ def initialize(user_agent, regex_meta)
5
+ @user_agent = user_agent
6
+ @regex_meta = regex_meta
7
+ end
8
+
9
+ def name
10
+ @regex_meta['name']
11
+ end
12
+
13
+ def full_version
14
+ VersionExtractor.new(@user_agent, @regex_meta).call
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ class DeviceDetector
2
+ class ClientDetector
3
+
4
+ attr_reader :user_agent
5
+
6
+ def initialize(user_agent)
7
+ @user_agent = user_agent
8
+ end
9
+
10
+ def call
11
+ DeviceDetector::Client.new(user_agent, matching_regex)
12
+ end
13
+
14
+ private
15
+
16
+ def matching_regex
17
+ regexes.find { |r| user_agent =~ Regexp.new(r['regex']) }
18
+ end
19
+
20
+ def regexes
21
+ YAML.load(filepaths.map { |filepath| File.read(filepath) }.join)
22
+ end
23
+
24
+ def filepaths
25
+ filenames.map do |filename|
26
+ File.join(DeviceDetector::ROOT, 'regexes', filename)
27
+ end
28
+ end
29
+
30
+ def filenames
31
+ [
32
+ 'browsers.yml',
33
+ 'feed_readers.yml',
34
+ 'libraries.yml',
35
+ 'mediaplayers.yml',
36
+ 'mobile_apps.yml',
37
+ 'pim.yml'
38
+ ]
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ class DeviceDetector
2
+ class OS
3
+
4
+ def initialize(user_agent, regex_meta)
5
+ @user_agent = user_agent
6
+ @regex_meta = regex_meta
7
+ end
8
+
9
+ def name
10
+ @regex_meta['name']
11
+ end
12
+
13
+ def full_version
14
+ VersionExtractor.new(@user_agent, @regex_meta).call
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,29 @@
1
+ class DeviceDetector
2
+ class OSDetector
3
+
4
+ attr_reader :user_agent
5
+
6
+ def initialize(user_agent)
7
+ @user_agent = user_agent
8
+ end
9
+
10
+ def call
11
+ DeviceDetector::OS.new(user_agent, matching_regex)
12
+ end
13
+
14
+ private
15
+
16
+ def matching_regex
17
+ regexes.find { |r| user_agent =~ Regexp.new(r['regex']) }
18
+ end
19
+
20
+ def regexes
21
+ @regexes ||= YAML.load(File.read(filepath))
22
+ end
23
+
24
+ def filepath
25
+ File.join(DeviceDetector::ROOT, 'regexes', 'oss.yml')
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ class DeviceDetector
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,36 @@
1
+ class DeviceDetector
2
+ class VersionExtractor < Struct.new(:user_agent, :regex_meta)
3
+
4
+ def call
5
+ extract_version
6
+ end
7
+
8
+ private
9
+
10
+ def version_string
11
+ regex_meta['version']
12
+ end
13
+
14
+ def extract_version
15
+ user_agent.match(regex) do |match_data|
16
+ replace_version_string_with(match_data)
17
+ end
18
+ end
19
+
20
+ def replace_version_string_with(match_data)
21
+ string = version_string
22
+
23
+ 1.upto(9) do |index|
24
+ string = string.gsub(/\$#{index}/, match_data[index]) if match_data[index]
25
+ end
26
+
27
+ string
28
+ end
29
+
30
+ def regex
31
+ Regexp.new(regex_meta['regex'])
32
+ end
33
+
34
+ end
35
+ end
36
+
@@ -0,0 +1,27 @@
1
+ ###############
2
+ # Device Detector - The Universal Device Detection library for parsing User Agents
3
+ #
4
+ # @link http://piwik.org
5
+ # @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
6
+ ###############
7
+
8
+ - regex: 'NetFront'
9
+ name: 'NetFront'
10
+
11
+ - regex: 'Trident'
12
+ name: 'Trident'
13
+
14
+ - regex: 'Blink'
15
+ name: 'Blink'
16
+
17
+ - regex: '(?:Apple)?WebKit'
18
+ name: 'WebKit'
19
+
20
+ - regex: 'Presto'
21
+ name: 'Presto'
22
+
23
+ - regex: '(?<!like )Gecko'
24
+ name: 'Gecko'
25
+
26
+ - regex: 'KHTML'
27
+ name: 'KHTML'
@@ -0,0 +1,742 @@
1
+ ###############
2
+ # Device Detector - The Universal Device Detection library for parsing User Agents
3
+ #
4
+ # @link http://piwik.org
5
+ # @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
6
+ ###############
7
+
8
+ #SailfishBrowser
9
+ - regex: 'SailfishBrowser(?:/(\d+[\.\d]+))?'
10
+ name: 'Sailfish Browser'
11
+ version: '$1'
12
+ engine:
13
+ default: 'Gecko'
14
+
15
+ # SeaMonkey
16
+ - regex: '(Iceape|SeaMonkey|gnuzilla)(?:/(\d+[\.\d]+))?'
17
+ name: '$1'
18
+ version: '$2'
19
+ engine:
20
+ default: 'Gecko'
21
+
22
+ # Camino
23
+ - regex: 'Camino(?:/(\d+[\.\d]+))?'
24
+ name: 'Camino'
25
+ version: '$1'
26
+ engine:
27
+ default: 'Gecko'
28
+
29
+ #Fennec (Firefox for mobile)
30
+ - regex: 'Fennec(?:/(\d+[\.\d]+))?'
31
+ name: 'Fennec'
32
+ version: '$1'
33
+ engine:
34
+ default: 'Gecko'
35
+
36
+ #MicroB
37
+ - regex: 'Firefox.*Tablet browser (\d+[\.\d]+)'
38
+ name: 'MicroB'
39
+ version: '$1'
40
+ engine:
41
+ default: 'Gecko'
42
+
43
+ #Avant Browser
44
+ - regex: 'Avant Browser'
45
+ name: 'Avant Browser'
46
+ version: ''
47
+ engine:
48
+ default: '' # multiple
49
+
50
+ #Bunjalloo
51
+ - regex: 'Bunjalloo(?:/(\d+[\.\d]+))?'
52
+ name: 'Bunjalloo'
53
+ version: '$1'
54
+
55
+ #Iceweasel
56
+ - regex: 'Iceweasel(?:/(\d+[\.\d]+))?'
57
+ name: 'Iceweasel'
58
+ version: '$1'
59
+ engine:
60
+ default: 'Gecko'
61
+
62
+ #WebPositive
63
+ - regex: 'WebPositive'
64
+ name: 'WebPositive'
65
+ version: ''
66
+ engine:
67
+ default: 'WebKit'
68
+
69
+
70
+ #Pale Moon
71
+ - regex: 'PaleMoon(?:/(\d+[\.\d]+))?'
72
+ name: 'Pale Moon'
73
+ version: '$1'
74
+ engine:
75
+ default: 'Gecko'
76
+
77
+ #CometBird
78
+ - regex: 'CometBird(?:/(\d+[\.\d]+))?'
79
+ name: 'CometBird'
80
+ version: '$1'
81
+ engine:
82
+ default: 'Gecko'
83
+
84
+ #IceDragon
85
+ - regex: 'IceDragon(?:/(\d+[\.\d]+))?'
86
+ name: 'IceDragon'
87
+ version: '$1'
88
+ engine:
89
+ default: 'Gecko'
90
+
91
+ #Flock
92
+ - regex: 'Flock(?:/(\d+[\.\d]+))?'
93
+ name: 'Flock'
94
+ version: '$1'
95
+ engine:
96
+ default: 'Gecko'
97
+ versions:
98
+ 3: 'WebKit'
99
+
100
+ #Kapiko
101
+ - regex: 'Kapiko(?:/(\d+[\.\d]+))?'
102
+ name: 'Kapiko'
103
+ version: '$1'
104
+ engine:
105
+ default: 'Gecko'
106
+
107
+ #Swiftfox
108
+ - regex: 'Firefox/(\d+[\.\d]+).*\(Swiftfox\)'
109
+ name: 'Swiftfox'
110
+ version: '$1'
111
+ engine:
112
+ default: 'Gecko'
113
+
114
+ #Firefox
115
+ - regex: 'Firefox(?:/(\d+[\.\d]+))?'
116
+ name: 'Firefox'
117
+ version: '$1'
118
+ engine:
119
+ default: 'Gecko'
120
+ - regex: '(BonEcho|GranParadiso|Lorentz|Minefield|Namoroka|Shiretoko)/(\d+[\.\d]+)'
121
+ name: 'Firefox'
122
+ version: '$1 ($2)'
123
+ engine:
124
+ default: 'Gecko'
125
+
126
+ #ANTGalio
127
+ - regex: 'ANTGalio(?:/(\d+[\.\d]+))?'
128
+ name: 'ANTGalio'
129
+ version: '$1'
130
+
131
+ #Espial TV Browser
132
+ - regex: '(?:Espial|Escape)(?:[/ ](\d+[\.\d]+))?'
133
+ name: 'Espial TV Browser'
134
+ version: '$1'
135
+
136
+ #RockMelt
137
+ - regex: 'RockMelt(?:/(\d+[\.\d]+))?'
138
+ name: 'RockMelt'
139
+ version: '$1'
140
+ engine:
141
+ default: 'WebKit'
142
+
143
+ #Fireweb Navigator
144
+ - regex: 'Fireweb Navigator(?:/(\d+[\.\d]+))?'
145
+ name: 'Fireweb Navigator'
146
+ version: '$1'
147
+
148
+ #Netscape
149
+ - regex: '(?:Navigator|Netscape6)(?:/(\d+[\.\d]+))?'
150
+ name: 'Netscape'
151
+ version: '$1'
152
+ engine:
153
+ default: '' # Mosaic in the first versions, then Gecko
154
+
155
+ #Opera
156
+ - regex: '(?:Opera Tablet.*Version|Opera/.+Opera Mobi.+Version|Mobile.+OPR)/(\d+[\.\d]+)'
157
+ name: 'Opera Mobile'
158
+ version: '$1'
159
+ engine:
160
+ default: 'Presto'
161
+ versions:
162
+ 15: 'Blink'
163
+ - regex: 'Opera Mini/(?:att/)?(\d+[\.\d]+)'
164
+ name: 'Opera Mini'
165
+ version: '$1'
166
+ engine:
167
+ default: 'Presto'
168
+ - regex: 'Opera.+Edition Next.+Version/(\d+[\.\d]+)'
169
+ name: 'Opera Next'
170
+ version: '$1'
171
+ engine:
172
+ default: 'Presto'
173
+ versions:
174
+ 15: 'Blink'
175
+ - regex: '(?:Opera|OPR)[/ ](?:9.80.*Version/)?(\d+[\.\d]+).+Edition Next'
176
+ name: 'Opera Next'
177
+ version: '$1'
178
+ engine:
179
+ default: 'Presto'
180
+ versions:
181
+ 15: 'Blink'
182
+ - regex: '(?:Opera|OPR)[/ ](?:9.80.*Version/)?(\d+[\.\d]+)'
183
+ name: 'Opera'
184
+ version: '$1'
185
+ engine:
186
+ default: 'Presto'
187
+ versions:
188
+ 15: 'Blink'
189
+
190
+ #Rekonq
191
+ - regex: 'rekonq(?:/(\d+[\.\d]+))?'
192
+ name: 'Rekonq'
193
+ version: '$1'
194
+ engine:
195
+ default: 'WebKit'
196
+
197
+ #CoolNovo (former ChromePlus)
198
+ - regex: 'CoolNovo(?:/(\d+[\.\d]+))?'
199
+ name: 'CoolNovo'
200
+ version: '$1'
201
+ engine:
202
+ default: '' # multi engine
203
+
204
+ #Comodo Dragon
205
+ - regex: 'Comodo[ _]Dragon(?:/(\d+[\.\d]+))?'
206
+ name: 'Comodo Dragon'
207
+ version: '$1'
208
+ engine:
209
+ default: 'WebKit'
210
+ versions:
211
+ 28: 'Blink'
212
+
213
+ #ChromePlus
214
+ - regex: 'ChromePlus(?:/(\d+[\.\d]+))?'
215
+ name: 'ChromePlus'
216
+ version: '$1'
217
+ engine:
218
+ default: '' # multi engine
219
+
220
+ #Conkeror
221
+ - regex: 'Conkeror(?:/(\d+[\.\d]+))?'
222
+ name: 'Conkeror'
223
+ version: '$1'
224
+ engine:
225
+ default: 'Gecko'
226
+
227
+ #Konqueror
228
+ - regex: 'Konqueror(?:/(\d+[\.\d]+))?'
229
+ name: 'Konqueror'
230
+ version: '$1'
231
+ engine:
232
+ default: 'KHTML'
233
+ versions:
234
+ 4: '' # multiple (KHTML or WebKit)
235
+
236
+ #Baidu Browser
237
+ - regex: 'baidubrowser(?:[/ ](\d+[\.\d]*))?'
238
+ name: 'Baidu Browser'
239
+ version: '$1'
240
+
241
+ #Baidu Spark
242
+ - regex: '(?:(?:BD)?Spark|BIDUBrowser)[/ ](\d+[\.\d]*)'
243
+ name: 'Baidu Spark'
244
+ version: '$1'
245
+
246
+ #Yandex Browser
247
+ - regex: 'YaBrowser(?:/(\d+[\.\d]*))?'
248
+ name: 'Yandex Browser'
249
+ version: '$1'
250
+ engine:
251
+ default: 'Blink'
252
+
253
+ #Midori
254
+ - regex: 'Midori(?:/(\d+[\.\d]+))?'
255
+ name: 'Midori'
256
+ version: '$1'
257
+ engine:
258
+ default: 'WebKit'
259
+
260
+ #Mercury
261
+ - regex: 'Mercury(?:/(\d+[\.\d]+))?'
262
+ name: 'Mercury'
263
+ version: '$1'
264
+
265
+ #Maxthon
266
+ - regex: 'Maxthon[ /](\d+[\.\d]+)'
267
+ name: 'Maxthon'
268
+ version: '$1'
269
+ engine:
270
+ default: '' # Trident and WebKit
271
+ versions:
272
+ 3: 'WebKit'
273
+
274
+ - regex: '(?:Maxthon|MyIE2|Uzbl)'
275
+ name: 'Maxthon'
276
+ version: ''
277
+ engine:
278
+ default: '' # Trident and WebKit
279
+
280
+ #Puffin
281
+ - regex: 'Puffin(?:/(\d+[\.\d]+))?'
282
+ name: 'Puffin'
283
+ version: '$1'
284
+
285
+ #Iron
286
+ - regex: 'Iron(?:/(\d+[\.\d]+))?'
287
+ name: 'Iron'
288
+ version: '$1'
289
+ engine:
290
+ default: 'WebKit'
291
+ versions:
292
+ 28: 'Blink'
293
+
294
+ #Epiphany
295
+ - regex: 'Epiphany(?:/(\d+[\.\d]+))?'
296
+ name: 'Epiphany'
297
+ version: '$1'
298
+ engine:
299
+ default: 'Gecko'
300
+ versions:
301
+ 2.9.16: '' # multi engine
302
+ 2.28: 'WebKit'
303
+
304
+ # Liebao
305
+ - regex: 'LBBrowser(?:[ /](\d+[\.\d]+))?'
306
+ name: 'Liebao'
307
+ version: '$1'
308
+
309
+ # Sogou Explorer
310
+ - regex: 'SE (\d+[\.\d]+)'
311
+ name: 'Sogou Explorer'
312
+ version: '$1'
313
+
314
+ #Chrome
315
+ - regex: 'CrMo(?:/(\d+[\.\d]+))?'
316
+ name: 'Chrome Mobile'
317
+ version: '$1'
318
+ engine:
319
+ default: 'WebKit'
320
+ versions:
321
+ 28: 'Blink'
322
+ - regex: 'CriOS(?:/(\d+[\.\d]+))?'
323
+ name: 'Chrome Mobile iOS'
324
+ version: '$1'
325
+ engine:
326
+ default: 'WebKit'
327
+ - regex: 'Chrome(?:/(\d+[\.\d]+))?.*Mobile'
328
+ name: 'Chrome Mobile'
329
+ version: '$1'
330
+ engine:
331
+ default: 'WebKit'
332
+ versions:
333
+ 28: 'Blink'
334
+ - regex: 'chromeframe(?:/(\d+[\.\d]+))?'
335
+ name: 'Chrome Frame'
336
+ version: '$1'
337
+ engine:
338
+ default: 'WebKit'
339
+ - regex: 'Chromium(?:/(\d+[\.\d]+))?'
340
+ name: 'Chromium'
341
+ version: '$1'
342
+ engine:
343
+ default: 'WebKit'
344
+ versions:
345
+ 28: 'Blink'
346
+ - regex: 'Chrome(?:/(\d+[\.\d]+))?'
347
+ name: 'Chrome'
348
+ version: '$1'
349
+ engine:
350
+ default: 'WebKit'
351
+ versions:
352
+ 28: 'Blink'
353
+
354
+ #UC Browser
355
+ - regex: 'UC[ ]?Browser(?:[ /]?(\d+[\.\d]+))?'
356
+ name: 'UC Browser'
357
+ version: '$1'
358
+ - regex: 'UCWEB(?:[ /]?(\d+[\.\d]+))?'
359
+ name: 'UC Browser'
360
+ version: '$1'
361
+
362
+ #Tizen Browser
363
+ - regex: '(?:Tizen|SLP) Browser(?:/(\d+[\.\d]+))?'
364
+ name: 'Tizen Browser'
365
+ version: '$1'
366
+
367
+ #Palm Blazer
368
+ - regex: 'Blazer(?:/(\d+[\.\d]+))?'
369
+ name: 'Palm Blazer'
370
+ version: '$1'
371
+ - regex: 'Pre/(\d+[\.\d]+)'
372
+ name: 'Palm Pre'
373
+ version: '$1'
374
+
375
+ #wOSBrowser
376
+ - regex: '(?:hpw|web)OS/(\d+[\.\d]+)'
377
+ name: 'wOSBrowser'
378
+ version: '$1'
379
+
380
+ #Palm WebPro
381
+ - regex: 'WebPro(?:[ /](\d+[\.\d]+))?'
382
+ name: 'Palm WebPro'
383
+ version: '$1'
384
+
385
+ #Jasmine
386
+ - regex: 'Jasmine(?:[ /](\d+[\.\d]+))?'
387
+ name: 'Jasmine'
388
+ version: '$1'
389
+
390
+ #Lynx
391
+ - regex: 'Lynx(?:/(\d+[\.\d]+))?'
392
+ name: 'Lynx'
393
+ version: '$1'
394
+ engine:
395
+ default: 'Text-based'
396
+
397
+ #NCSA Mosaic
398
+ - regex: 'NCSA_Mosaic(?:/(\d+[\.\d]+))?'
399
+ name: 'NCSA Mosaic'
400
+ version: '$1'
401
+
402
+ #ABrowse
403
+ - regex: 'ABrowse(?: (\d+[\.\d]+))?'
404
+ name: 'ABrowse'
405
+ version: '$1'
406
+
407
+ #Amaya
408
+ - regex: 'amaya(?:/(\d+[\.\d]+))?'
409
+ name: 'Amaya'
410
+ version: '$1'
411
+
412
+ #Amiga Voyager
413
+ - regex: 'AmigaVoyager(?:/(\d+[\.\d]+))?'
414
+ name: 'Amiga Voyager'
415
+ version: '$1'
416
+
417
+ #Amiga Aweb
418
+ - regex: 'Amiga-Aweb(?:/(\d+[\.\d]+))?'
419
+ name: 'Amiga Aweb'
420
+ version: '$1'
421
+
422
+ #Arora
423
+ - regex: 'Arora(?:/(\d+[\.\d]+))?'
424
+ name: 'Arora'
425
+ version: '$1'
426
+ engine:
427
+ default: 'WebKit'
428
+
429
+ #Beonex
430
+ - regex: 'Beonex(?:/(\d+[\.\d]+))?'
431
+ name: 'Beonex'
432
+ version: '$1'
433
+ engine:
434
+ default: 'Gecko'
435
+
436
+ #BlackBerry Browser
437
+ - regex: 'BlackBerry|PlayBook|BB10'
438
+ name: 'BlackBerry Browser'
439
+ version: ''
440
+
441
+ #BrowseX
442
+ - regex: 'BrowseX \((\d+[\.\d]+)'
443
+ name: 'BrowseX'
444
+ version: '$1'
445
+
446
+ #Charon
447
+ - regex: 'Charon(?:[/ ](\d+[\.\d]+))?'
448
+ name: 'Charon'
449
+ version: '$1'
450
+
451
+ #Cheshire
452
+ - regex: 'Cheshire(?:/(\d+[\.\d]+))?'
453
+ name: 'Cheshire'
454
+ version: '$1'
455
+
456
+ #Dillo
457
+ - regex: 'Dillo(?:/(\d+[\.\d]+))?'
458
+ name: 'Dillo'
459
+ version: '$1'
460
+ engine:
461
+ default: 'Dillo'
462
+
463
+ #Dolphin
464
+ - regex: 'Dolfin(?:/(\d+[\.\d]+))?|dolphin'
465
+ name: 'Dolphin'
466
+ version: '$1'
467
+ engine:
468
+ default: 'WebKit'
469
+
470
+ #Elinks
471
+ - regex: 'Elinks(?:/(\d+[\.\d]+))?'
472
+ name: 'Elinks'
473
+ version: '$1'
474
+ engine:
475
+ default: 'Text-based'
476
+
477
+ #Firebird
478
+ - regex: 'Firebird(?:/(\d+[\.\d]+))?'
479
+ name: 'Firebird'
480
+ version: '$1'
481
+ engine:
482
+ default: 'Gecko'
483
+
484
+ #Fluid
485
+ - regex: 'Fluid(?:/(\d+[\.\d]+))?'
486
+ name: 'Fluid'
487
+ version: '$1'
488
+ engine:
489
+ default: 'WebKit'
490
+
491
+ #Galeon
492
+ - regex: 'Galeon(?:/(\d+[\.\d]+))?'
493
+ name: 'Galeon'
494
+ version: '$1'
495
+ engine:
496
+ default: 'Gecko'
497
+
498
+ #Google Earth
499
+ - regex: 'Google Earth(?:/(\d+[\.\d]+))?'
500
+ name: 'Google Earth'
501
+ version: '$1'
502
+ engine:
503
+ default: 'WebKit'
504
+
505
+ #HotJava
506
+ - regex: 'HotJava(?:/(\d+[\.\d]+))?'
507
+ name: 'HotJava'
508
+ version: '$1'
509
+
510
+ #IBrowse
511
+ - regex: 'IBrowse(?:[ /](\d+[\.\d]+))?'
512
+ name: 'IBrowse'
513
+ version: '$1'
514
+
515
+ #iCab
516
+ - regex: 'iCab(?:[ /](\d+[\.\d]+))?'
517
+ name: 'iCab'
518
+ version: '$1'
519
+ engine:
520
+ default: 'iCab'
521
+ versions:
522
+ 4: 'WebKit'
523
+
524
+ #Sleipnir
525
+ - regex: 'Sleipnir(?:[ /](\d+[\.\d]+))?'
526
+ name: 'Sleipnir'
527
+ version: '$1'
528
+ engine:
529
+ default: '' # multi engine
530
+
531
+ #Lunascape
532
+ - regex: 'Lunascape(?:[/ ](\d+[\.\d]+))?'
533
+ name: 'Lunascape'
534
+ version: '$1'
535
+ engine:
536
+ default: '' # multi engine
537
+
538
+ #Internet Explorer
539
+ - regex: 'IEMobile[ /](\d+[\.\d]+)'
540
+ name: 'IE Mobile'
541
+ version: '$1'
542
+ engine:
543
+ default: 'Trident'
544
+ - regex: 'MSIE (\d+[\.\d]+).*XBLWP7'
545
+ name: 'IE Mobile'
546
+ version: '$1'
547
+ engine:
548
+ default: 'Trident'
549
+ - regex: 'MSIE.*Trident/4.0'
550
+ name: 'Internet Explorer'
551
+ version: 8.0
552
+ engine:
553
+ default: 'Trident'
554
+ - regex: 'MSIE.*Trident/5.0'
555
+ name: 'Internet Explorer'
556
+ version: 9.0
557
+ engine:
558
+ default: 'Trident'
559
+ - regex: 'MSIE.*Trident/6.0'
560
+ name: 'Internet Explorer'
561
+ version: 10.0
562
+ engine:
563
+ default: 'Trident'
564
+ - regex: 'Trident/7.0'
565
+ name: 'Internet Explorer'
566
+ version: 11.0
567
+ engine:
568
+ default: 'Trident'
569
+ - regex: 'MSIE (\d+[\.\d]+)'
570
+ name: 'Internet Explorer'
571
+ version: '$1'
572
+ engine:
573
+ default: 'Trident'
574
+ - regex: 'IE[ /](\d+[\.\d]++)'
575
+ name: 'Internet Explorer'
576
+ version: '$1'
577
+ engine:
578
+ default: 'Trident'
579
+
580
+ #Kazehakase
581
+ - regex: 'Kazehakase(?:/(\d+[\.\d]+))?'
582
+ name: 'Kazehakase'
583
+ version: '$1'
584
+ engine:
585
+ default: '' # multi engine
586
+
587
+ #Kindle Browser
588
+ - regex: 'Kindle/(\d+[\.\d]+)'
589
+ name: 'Kindle Browser'
590
+ version: '$1'
591
+
592
+ #K-meleon
593
+ - regex: 'K-meleon(?:/(\d+[\.\d]+))?'
594
+ name: 'K-meleon'
595
+ version: '$1'
596
+ engine:
597
+ default: 'Gecko'
598
+
599
+ #Links
600
+ - regex: 'Links(?: \((\d+[\.\d]+))?'
601
+ name: 'Links'
602
+ version: '$1'
603
+ engine:
604
+ default: 'Text-based'
605
+
606
+ #Openwave Mobile Browser
607
+ - regex: 'UP.Browser(?:/(\d+[\.\d]+))?'
608
+ name: 'Openwave Mobile Browser'
609
+ version: '$1'
610
+
611
+ #OmniWeb
612
+ - regex: 'OmniWeb(?:/[v]?(\d+[\.\d]+))?'
613
+ name: 'OmniWeb'
614
+ version: '$1'
615
+ engine:
616
+ default: 'WebKit'
617
+
618
+ #Phoenix
619
+ - regex: 'Phoenix(?:/(\d+[\.\d]+))?'
620
+ name: 'Phoenix'
621
+ version: '$1'
622
+
623
+ #Mobile Silk
624
+ - regex: 'Silk(?:/(\d+[\.\d]+))?'
625
+ name: 'Mobile Silk'
626
+ version: '$1'
627
+ engine:
628
+ default: 'Blink'
629
+
630
+ #Nokia Browser
631
+ - regex: '(?:NokiaBrowser|BrowserNG)(?:/(\d+[\.\d]+))?'
632
+ name: 'Nokia Browser'
633
+ version: '$1'
634
+ - regex: 'Series60/5\.0'
635
+ name: 'Nokia Browser'
636
+ version: '7.0'
637
+ - regex: 'Series60/(\d+[\.\d]+)'
638
+ name: 'Nokia OSS Browser'
639
+ version: '$1'
640
+ - regex: 'S40OviBrowser/(\d+[\.\d]+)'
641
+ name: 'Nokia Ovi Browser'
642
+ version: '$1'
643
+ - regex: '^Nokia|Nokia[EN]?\d+'
644
+ name: 'Nokia Browser'
645
+ version: ''
646
+
647
+ #NetFront
648
+ - regex: 'NetFrontLifeBrowser(?:/(\d+[\.\d]+))?'
649
+ name: 'NetFront Life'
650
+ version: '$1'
651
+ engine:
652
+ default: 'NetFront'
653
+ - regex: 'NetFront(?:/(\d+[\.\d]+))?'
654
+ name: 'NetFront'
655
+ version: '$1'
656
+ engine:
657
+ default: 'NetFront'
658
+ - regex: 'PLAYSTATION|NINTENDO 3|AppleWebKit.+ NX/\d+\.\d+\.\d+'
659
+ name: 'NetFront'
660
+ version: ''
661
+
662
+ #NetPositive
663
+ - regex: 'NetPositive(?:/(\d+[\.\d]+))?'
664
+ name: 'NetPositive'
665
+ version: '$1'
666
+
667
+ #Obigo
668
+ - regex: 'Obigo[ ]?(?:InternetBrowser|Browser)?(?:[ /]([a-z0-9]*))?'
669
+ name: 'Obigo'
670
+ version: '$1'
671
+ - regex: 'Obigo|Teleca'
672
+ name: 'Obigo'
673
+ version: ''
674
+
675
+ #Oregano
676
+ - regex: 'Oregano(?:[ /](\d+[\.\d]+))?'
677
+ name: 'Oregano'
678
+ version: '$1'
679
+
680
+ #Polaris
681
+ - regex: '(?:Polaris|Embider)(?:[/ ](\d+[\.\d]+))?'
682
+ name: 'Polaris'
683
+ version: '$1'
684
+
685
+ #SEMC Browser
686
+ - regex: 'SEMC-Browser(?:[/ ](\d+[\.\d]+))?'
687
+ name: 'SEMC-Browser'
688
+ version: '$1'
689
+
690
+ #Shiira
691
+ - regex: 'Shiira(?:[/ ](\d+[\.\d]+))?'
692
+ name: 'Shiira'
693
+ version: '$1'
694
+ engine:
695
+ default: 'WebKit'
696
+
697
+ #Snowshoe
698
+ - regex: 'Snowshoe(?:/(\d+[\.\d]+))?'
699
+ name: 'Snowshoe'
700
+ version: '$1'
701
+ engine:
702
+ default: 'WebKit'
703
+
704
+ #Sunrise
705
+ - regex: 'Sunrise(?:Browser)?(?:/(\d+[\.\d]+))?'
706
+ name: 'Sunrise'
707
+ version: '$1'
708
+
709
+ #Xiino
710
+ - regex: 'Xiino(?:/(\d+[\.\d]+))?'
711
+ name: 'Xiino'
712
+ version: '$1'
713
+
714
+ #Android Browser
715
+ - regex: 'Android'
716
+ name: 'Android Browser'
717
+ version: ''
718
+ engine:
719
+ default: 'WebKit'
720
+
721
+ #Safari
722
+ - regex: '(?:iPod|iPad|iPhone).+Version/(\d+[\.\d]+)'
723
+ name: 'Mobile Safari'
724
+ version: '$1'
725
+ engine:
726
+ default: 'WebKit'
727
+ - regex: 'Version/(\d+[\.\d]+).*Mobile.*Safari/'
728
+ name: 'Mobile Safari'
729
+ version: '$1'
730
+ engine:
731
+ default: 'WebKit'
732
+ - regex: '(?:iPod|iPhone|iPad)'
733
+ name: 'Mobile Safari'
734
+ version: ''
735
+ engine:
736
+ default: 'WebKit'
737
+ - regex: 'Version/(\d+[\.\d]+).*Safari/|Safari/\d+'
738
+ name: 'Safari'
739
+ version: '$1'
740
+ engine:
741
+ default: 'WebKit'
742
+