double_agent 0.2.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +15 -0
- data/README.rdoc +33 -47
- data/data/browsers.yml +39 -35
- data/data/oses.yml +63 -37
- data/lib/double_agent/double_agent.rb +60 -0
- data/lib/double_agent/parser.rb +35 -155
- data/lib/double_agent/{resources.rb → resource.rb} +24 -31
- data/lib/double_agent/user_agent.rb +14 -0
- data/lib/double_agent/version.rb +1 -1
- data/lib/double_agent.rb +7 -1
- metadata +8 -16
- data/lib/double_agent/all.rb +0 -5
- data/lib/double_agent/logs.rb +0 -110
- data/lib/double_agent/stats.rb +0 -65
- data/spec/data/httpd.access.log +0 -20
- data/spec/data/httpd.access.log.1.gz +0 -0
- data/spec/data_spec.rb +0 -105
- data/spec/parser_spec.rb +0 -114
- data/spec/resources_spec.rb +0 -78
- data/spec/spec_helper.rb +0 -19
- data/spec/stats_spec.rb +0 -64
data/CHANGELOG
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
== Release 1.0.0 (November 11, 2012) ==
|
2
|
+
|
3
|
+
* Changes to parser API
|
4
|
+
* Add "mobile?" method to detect mobile OS's
|
5
|
+
* Android's browser isn't part of the Chromium family
|
6
|
+
* Android OS isn't part of the GNU/Linux family
|
7
|
+
* iOS isn't part of the OS X family
|
8
|
+
* Add iPhone and iPad
|
9
|
+
* Add Kindle, Kindle Fire
|
10
|
+
* Refactor the Logs module
|
11
|
+
* Drop Stats module (use the "graphene" gem instead)
|
12
|
+
* Drop Logs module
|
13
|
+
* Drop icon methods - they just don't make much sense in the library
|
14
|
+
* Drop support for Ruby 1.8
|
15
|
+
|
1
16
|
== Release 0.2.3 (July 14, 2012) ==
|
2
17
|
|
3
18
|
* Handle exceptions on encoding errors
|
data/README.rdoc
CHANGED
@@ -3,41 +3,50 @@
|
|
3
3
|
double_agent is a library for parsing browser and operating system info out of user
|
4
4
|
agent strings. It is designed for parsing large sets for review or analysis.
|
5
5
|
|
6
|
-
|
6
|
+
*NOTE* Support for Ruby 1.8 was dropped after version 0.2.3.
|
7
7
|
|
8
|
-
|
8
|
+
== Installation
|
9
9
|
|
10
|
-
|
10
|
+
[sudo] gem install double_agent
|
11
|
+
# Or add "double_agent" to your Gemfile
|
11
12
|
|
12
|
-
|
13
|
+
Read the full documentation at http://jordanhollinger.com/docs/double_agent/
|
13
14
|
|
14
|
-
|
15
|
-
require 'double_agent'
|
15
|
+
== Parser
|
16
16
|
|
17
|
-
|
18
|
-
require 'double_agent/parser|resources|stats|logs|all'
|
17
|
+
user_agent = DoubleAgent.parse("Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/12.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19")
|
19
18
|
|
20
|
-
|
19
|
+
user_agent.browser
|
20
|
+
=> "Chrome 18"
|
21
21
|
|
22
|
-
|
22
|
+
user_agent.browser_name
|
23
|
+
=> "Chrome"
|
23
24
|
|
24
|
-
|
25
|
-
=> "
|
25
|
+
user_agent.browser_version
|
26
|
+
=> "18"
|
26
27
|
|
27
|
-
|
28
|
+
user_agent.browser_family
|
28
29
|
=> "Chromium"
|
29
30
|
|
30
|
-
|
31
|
+
user_agent.os
|
31
32
|
=> "Ubuntu"
|
32
33
|
|
33
|
-
|
34
|
+
user_agent.os_family
|
34
35
|
=> "GNU/Linux"
|
35
36
|
|
36
|
-
|
37
|
+
user_agent.mobile?
|
38
|
+
=> false
|
39
|
+
|
40
|
+
# Or
|
37
41
|
|
38
|
-
|
42
|
+
DoubleAgent.browser("Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/12.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19")
|
43
|
+
=> "Chrome 18"
|
39
44
|
|
40
|
-
|
45
|
+
See the DoubleAgent module for more info.
|
46
|
+
|
47
|
+
== Resources
|
48
|
+
|
49
|
+
DoubleAgent::Resource is a mix-in for objects with a user_agent method.
|
41
50
|
It gives that class's objects all of the above methods and more.
|
42
51
|
|
43
52
|
class Login
|
@@ -56,36 +65,13 @@ It gives that class's objects all of the above methods and more.
|
|
56
65
|
login.os_family
|
57
66
|
=> "OS X"
|
58
67
|
|
59
|
-
|
60
|
-
|
61
|
-
Calculate browser and OS shares for large sets of DoubleAgent::Resource objects with DoubleAgent::Stats::percentages_for.
|
62
|
-
|
63
|
-
logins = Login.all
|
64
|
-
p logins.size
|
65
|
-
=> 1000
|
66
|
-
|
67
|
-
stats = DoubleAgent::Stats.percentages_for(logins, :browser_family, :os_family)
|
68
|
-
p stats
|
69
|
-
=> [["Firefox", "Windows", 50.0, 500], ["Internet Explorer", "Windows", 20.0, 200], ["Safari", "OS X", 20.0, 200], ["Firefox", "GNU/Linux", 10.0, 100]]
|
70
|
-
|
71
|
-
stats.each do |browser_family, os_family, percent, real_num|
|
72
|
-
puts "#{browser_family} on #{os_family} - #{percent}% (#{real_num} hits)"
|
73
|
-
end
|
74
|
-
=> "Firefox on Windows - 50% (500 hits)"
|
75
|
-
=> "Internet Explorer on Windows - 20% (200 hits)"
|
76
|
-
=> "Safari on OS X - 20% (200 hits)"
|
77
|
-
=> "Firefox on GNU/Linux - 10% (100 hits)"
|
78
|
-
|
79
|
-
= Logs
|
68
|
+
See the DoubleAgent::Resource module for more info.
|
80
69
|
|
81
|
-
|
82
|
-
object. It even reads gzipped logs (requires zlib)! Since the DoubleAgent::Logs::Entry class mixes in DoubleAgent::Resource, you
|
83
|
-
can easily calculate browser and/or OS share on your site.
|
70
|
+
== Where did stats and logs go?
|
84
71
|
|
85
|
-
|
86
|
-
stats = DoubleAgent::Stats.percentages_for(entries, :browser)
|
72
|
+
As of version 1.0.0, double_agent underwent a downsizing. Stats were dropped and moved to their own more generic gem called Graphene. More info at https://github.com/jhollinger/graphene. Logs were also dropped; there are several HTTP log parsers for Ruby, including http-log-parser and Beaver.
|
87
73
|
|
88
|
-
|
89
|
-
|
74
|
+
== License
|
75
|
+
Copyright 2011 Jordan Hollinger
|
90
76
|
|
91
|
-
|
77
|
+
Licensed under the Apache License
|
data/data/browsers.yml
CHANGED
@@ -1,65 +1,69 @@
|
|
1
1
|
# The ordering is very important; matches are performed in the specified order.
|
2
2
|
# This allows for greatly simplified regexes.
|
3
3
|
|
4
|
-
|
5
|
-
:
|
4
|
+
:msie:
|
5
|
+
:name: Internet Explorer
|
6
6
|
:regex: msie \d+
|
7
7
|
:version: (?<=msie )[0-9]+
|
8
|
-
:safe_version: ["msie [0-9]+", "[0-9]+"]
|
9
8
|
|
10
|
-
|
11
|
-
:
|
9
|
+
:epiphany:
|
10
|
+
:name: Epiphany
|
11
|
+
:regex: epiphany
|
12
|
+
:version: (?<=epiphany/)[0-9]+
|
13
|
+
|
14
|
+
:chrome:
|
15
|
+
:name: Chrome
|
12
16
|
:family_sym: :chromium
|
13
17
|
:regex: chrome/\d+
|
14
18
|
:version: (?<=chrome/)[0-9]+
|
15
|
-
:safe_version: ["chrome/[0-9]+", "[0-9]+"]
|
16
19
|
|
17
|
-
|
18
|
-
:
|
20
|
+
:chromium:
|
21
|
+
:name: Chromium
|
19
22
|
:regex: chromium/\d+
|
20
23
|
:version: (?<=chromium/)[0-9]+
|
21
|
-
:safe_version: ["chromium/[0-9]+", "[0-9]+"]
|
22
24
|
|
23
|
-
|
24
|
-
:
|
25
|
+
:opera:
|
26
|
+
:name: Opera
|
25
27
|
:regex: opera
|
26
28
|
:version: ((?<=version/)[0-9]+)|((?<=opera )[0-9]+)
|
27
|
-
:safe_version: ["(version/[0-9]+)|(opera [0-9]+)", "[0-9]+"]
|
28
29
|
|
29
|
-
|
30
|
-
:
|
30
|
+
:firefox:
|
31
|
+
:name: Firefox
|
31
32
|
:regex: firefox
|
32
33
|
:version: (?<=firefox/)[0-9]+
|
33
|
-
:safe_version: ["firefox/[0-9]+", "[0-9]+"]
|
34
34
|
|
35
|
-
|
36
|
-
:
|
37
|
-
:family_sym: :
|
35
|
+
:kindle_fire_silk:
|
36
|
+
:name: Kindle Fire (Silk)
|
37
|
+
:family_sym: :kindle
|
38
|
+
:regex: silk-accelerated
|
39
|
+
|
40
|
+
:kindle_fire:
|
41
|
+
:name: Kindle Fire
|
42
|
+
:family_sym: :kindle
|
43
|
+
:regex: kindle fire
|
44
|
+
|
45
|
+
:kindle:
|
46
|
+
:name: Kindle
|
47
|
+
:regex: kindle
|
48
|
+
|
49
|
+
:android:
|
50
|
+
:name: Android
|
38
51
|
:regex: android
|
39
52
|
:version: (?<=android )[0-9]+(\.[0-9]+)?
|
40
|
-
:safe_version: ["android [0-9]+(\\.[0-9]+)?", "[0-9]+(\\.[0-9]+)?"]
|
41
53
|
|
42
|
-
|
43
|
-
:
|
54
|
+
:blackberry:
|
55
|
+
:name: BlackBerry
|
44
56
|
:regex: blackberry
|
45
57
|
|
46
|
-
|
47
|
-
:
|
48
|
-
:regex: epiphany
|
49
|
-
:version: (?<=epiphany/)[0-9]+
|
50
|
-
:safe_version: ["epiphany/[0-9]+", "[0-9]+"]
|
51
|
-
|
52
|
-
- :name: Safari %s
|
53
|
-
:sym: :safari
|
58
|
+
:safari:
|
59
|
+
:name: Safari
|
54
60
|
:regex: safari
|
55
61
|
:version: (?<=version/)[0-9]+
|
56
|
-
:safe_version: ["version/[0-9]+", "[0-9]+"]
|
57
62
|
|
58
|
-
|
59
|
-
:
|
63
|
+
:konqueror:
|
64
|
+
:name: Konqueror
|
60
65
|
:regex: konqueror
|
61
66
|
|
62
|
-
|
63
|
-
:
|
67
|
+
:unknown:
|
68
|
+
:name: Unknown
|
64
69
|
:regex: .*
|
65
|
-
:version: .*
|
data/data/oses.yml
CHANGED
@@ -1,72 +1,98 @@
|
|
1
|
-
|
2
|
-
:
|
1
|
+
:windows_8:
|
2
|
+
:name: Windows 8
|
3
3
|
:family_sym: :windows
|
4
4
|
:regex: windows nt 6\.2
|
5
|
-
:icon: windows
|
6
5
|
|
7
|
-
|
8
|
-
:
|
6
|
+
:windows_7:
|
7
|
+
:name: Windows 7
|
9
8
|
:family_sym: :windows
|
10
9
|
:regex: windows nt 6\.1
|
11
|
-
:icon: windows
|
12
10
|
|
13
|
-
|
14
|
-
:
|
11
|
+
:windows_vista:
|
12
|
+
:name: Windows Vista
|
15
13
|
:family_sym: :windows
|
16
14
|
:regex: windows nt 6\.0
|
17
|
-
:icon: windows
|
18
15
|
|
19
|
-
|
20
|
-
:
|
16
|
+
:windows_xp:
|
17
|
+
:name: Windows XP
|
21
18
|
:family_sym: :windows
|
22
19
|
:regex: windows nt 5\.[12]
|
23
|
-
:icon: windows
|
24
20
|
|
25
|
-
|
26
|
-
:
|
21
|
+
:windows:
|
22
|
+
:name: Windows
|
27
23
|
:regex: windows
|
28
24
|
|
29
|
-
|
30
|
-
:
|
31
|
-
:family_sym: :
|
32
|
-
:regex: (
|
25
|
+
:kindle_fire:
|
26
|
+
:name: Kindle Fire
|
27
|
+
:family_sym: :kindle
|
28
|
+
:regex: (kindle fire)|(silk-accelerated)
|
29
|
+
:mobile: true
|
33
30
|
|
34
|
-
|
35
|
-
:
|
31
|
+
:kindle:
|
32
|
+
:name: Kindle
|
33
|
+
:regex: kindle
|
34
|
+
:mobile: true
|
35
|
+
|
36
|
+
:ipod:
|
37
|
+
:name: iPod
|
38
|
+
:family_sym: :ios
|
39
|
+
:regex: \(ipod;
|
40
|
+
:mobile: true
|
41
|
+
|
42
|
+
:iphone:
|
43
|
+
:name: iPhone
|
44
|
+
:family_sym: :ios
|
45
|
+
:regex: \(iphone;
|
46
|
+
:mobile: true
|
47
|
+
|
48
|
+
:ipad:
|
49
|
+
:name: iPad
|
50
|
+
:family_sym: :ios
|
51
|
+
:regex: \(ipad;
|
52
|
+
:mobile: true
|
53
|
+
|
54
|
+
:ios:
|
55
|
+
:name: iOS
|
56
|
+
:regex: \(i\w+; .* like mac os x;
|
57
|
+
:mobile: true
|
58
|
+
|
59
|
+
:osx:
|
60
|
+
:name: OS X
|
36
61
|
:regex: macintosh
|
37
62
|
|
38
|
-
|
39
|
-
:
|
40
|
-
:family_sym: :linux
|
63
|
+
:android:
|
64
|
+
:name: Android
|
41
65
|
:regex: android
|
66
|
+
:mobile: true
|
42
67
|
|
43
|
-
|
44
|
-
:
|
68
|
+
:ubuntu:
|
69
|
+
:name: Ubuntu
|
45
70
|
:family_sym: :linux
|
46
71
|
:regex: ubuntu
|
47
72
|
|
48
|
-
|
49
|
-
:
|
73
|
+
:fedora:
|
74
|
+
:name: Fedora
|
50
75
|
:family_sym: :linux
|
51
76
|
:regex: fedora
|
52
77
|
|
53
|
-
|
54
|
-
:
|
78
|
+
:slackware:
|
79
|
+
:name: Slackware
|
55
80
|
:family_sym: :linux
|
56
81
|
:regex: slackware
|
57
82
|
|
58
|
-
|
59
|
-
:
|
83
|
+
:linux:
|
84
|
+
:name: GNU/Linux
|
60
85
|
:regex: linux
|
61
86
|
|
62
|
-
|
63
|
-
:
|
87
|
+
:freebsd:
|
88
|
+
:name: FreeBSD
|
64
89
|
:regex: freebsd
|
65
90
|
|
66
|
-
|
67
|
-
:
|
91
|
+
:blackberry:
|
92
|
+
:name: BlackBerry
|
68
93
|
:regex: blackberry
|
94
|
+
:mobile: true
|
69
95
|
|
70
|
-
|
71
|
-
:
|
96
|
+
:unknown:
|
97
|
+
:name: Unknown
|
72
98
|
:regex: .*
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# A browser user agent string parser. Use DoubleAgent.parse(user_agent) to return a DoubleAgent::UserAgent object, which you can
|
2
|
+
# query with methods like "browser_name" or "os". The DoubleAgent module itself responds to those same method - just
|
3
|
+
# pass the user agent string as an argument.
|
4
|
+
module DoubleAgent
|
5
|
+
# A hash of browser data, the basis for browser parsing. You may edit this data and call load_browsers! to customize parsing.
|
6
|
+
BROWSER_DATA = Psych.load_file(File.expand_path('../../../data/browsers.yml', __FILE__))
|
7
|
+
|
8
|
+
# A hash of OS hashes, the basis for OS parsing. You may edit this data and call load_oses! to customize parsing.
|
9
|
+
OS_DATA = Psych.load_file(File.expand_path('../../../data/oses.yml', __FILE__))
|
10
|
+
|
11
|
+
BROWSER_PARSERS, OS_PARSERS = {}, {} # :nodoc:
|
12
|
+
|
13
|
+
# Returns a new UserAgent object
|
14
|
+
def self.parse(user_agent_string)
|
15
|
+
UserAgent.new(user_agent_string)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Forwards calls to a UserAgent object
|
19
|
+
def self.method_missing(method, *args, &block)
|
20
|
+
parse(args.first).send(method)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Transforms BROWSER_DATA into a case statement inside of the _browser_sym method
|
24
|
+
def self.load_browsers!
|
25
|
+
BROWSER_PARSERS.clear.merge! Hash[BROWSER_DATA.map { |sym, data| [sym, BrowserParser.new(sym, data)] }]
|
26
|
+
|
27
|
+
module_eval <<-CODEZ
|
28
|
+
def self._browser_sym(user_agent)
|
29
|
+
case user_agent.to_s
|
30
|
+
#{BROWSER_DATA.map { |sym, data| "when %r{#{data[:regex]}}i then :\"#{sym}\"" }.join("\n")}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
CODEZ
|
34
|
+
end
|
35
|
+
|
36
|
+
# Transforms OS_DATA into a case statement inside of the _os_sym method
|
37
|
+
def self.load_oses!
|
38
|
+
OS_PARSERS.clear.merge! Hash[OS_DATA.map { |sym, data| [sym, OSParser.new(sym, data)] }]
|
39
|
+
|
40
|
+
module_eval <<-CODEZ
|
41
|
+
def self._os_sym(user_agent)
|
42
|
+
case user_agent.to_s
|
43
|
+
#{OS_DATA.map { |sym, data| "when %r{#{data[:regex]}}i then :\"#{sym}\"" }.join("\n")}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
CODEZ
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# Returns the correct BrowerParser for the given user agent or symbol
|
52
|
+
def self.browser_parser(ua_or_sym)
|
53
|
+
BROWSER_PARSERS[ua_or_sym.is_a?(Symbol) ? ua_or_sym : _browser_sym(ua_or_sym)]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the correct OSParser for the given user agent or symbol
|
57
|
+
def self.os_parser(ua_or_sym)
|
58
|
+
OS_PARSERS[ua_or_sym.is_a?(Symbol) ? ua_or_sym : _os_sym(ua_or_sym)]
|
59
|
+
end
|
60
|
+
end
|
data/lib/double_agent/parser.rb
CHANGED
@@ -1,192 +1,72 @@
|
|
1
|
-
begin
|
2
|
-
require 'psych'
|
3
|
-
rescue LoadError
|
4
|
-
end
|
5
|
-
require 'yaml'
|
6
|
-
|
7
1
|
module DoubleAgent
|
8
|
-
# An array of "browser knowledge hashes," the basis of browser parsing. You may edit this data and call load_browsers! to customize parsing.
|
9
|
-
BROWSER_DATA = YAML.load_file(File.expand_path('../../../data/browsers.yml', __FILE__))
|
10
|
-
|
11
|
-
# An array of "OS knowledge hashes," the basis of OS parsing. You may edit this data and call load_oses! to customize parsing.
|
12
|
-
OS_DATA = YAML.load_file(File.expand_path('../../../data/oses.yml', __FILE__))
|
13
|
-
|
14
|
-
# An array of BrowserParser objects created from the data in BROWSER_DATA.
|
15
|
-
BROWSERS = {}
|
16
|
-
|
17
|
-
# An array of OSParser objects created from the data in OS_DATA.
|
18
|
-
OSES = {}
|
19
|
-
|
20
2
|
# Each browser in BROWSER_DATA gets its own BrowserParser object. These
|
21
3
|
# parser objects are then used to parse specific data out of a user agent string.
|
22
|
-
|
23
4
|
class BrowserParser
|
24
|
-
|
25
|
-
|
26
|
-
|
5
|
+
# The browser name
|
6
|
+
attr_reader :name
|
7
|
+
# The browser name as a symbol
|
8
|
+
attr_reader :sym
|
9
|
+
# The browser family name as a symbol
|
10
|
+
attr_reader :family_sym
|
27
11
|
|
28
12
|
# Instantiate a new BrowserParser using a "browser family" element from BROWSER_DATA
|
29
|
-
def initialize(attrs={})
|
30
|
-
@sym =
|
13
|
+
def initialize(sym, attrs={})
|
14
|
+
@sym = sym
|
31
15
|
@family_sym = attrs[:family_sym] || @sym
|
32
16
|
@name = attrs[:name]
|
33
|
-
|
34
|
-
|
35
|
-
@safe_version = attrs[:safe_version].map { |r| Regexp.new r, Regexp::IGNORECASE }
|
36
|
-
elsif attrs[:version]
|
37
|
-
@version = Regexp.new(attrs[:version], Regexp::IGNORECASE)
|
17
|
+
if attrs[:version]
|
18
|
+
@version_pattern = Regexp.new(attrs[:version], Regexp::IGNORECASE)
|
38
19
|
end
|
39
20
|
end
|
40
21
|
|
41
22
|
# Returns the browser's name. If you provide a user agent string as an argument,
|
42
23
|
# it will attempt to also return the major version number. E.g. "Firefox 4".
|
43
24
|
def browser(ua=nil)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
25
|
+
(ua and @version_pattern) ? "#{name} #{version(ua)}" : name
|
26
|
+
end
|
27
|
+
|
28
|
+
# Attempts to parse and return the browser's version from a user agent string. Returns
|
29
|
+
# nil if nothing is found.
|
30
|
+
def version(ua)
|
31
|
+
ua.slice(@version_pattern)
|
49
32
|
end
|
50
33
|
|
51
34
|
# Returns the BrowserParser for this BrowserParser object's Family. E.g. the Chrome
|
52
35
|
# BrowserParser would return the Chromium BrowserParser. For browsers that are their
|
53
36
|
# own family (e.g. Firefox, IE) it will end up returning itself.
|
54
37
|
def family
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# Attempts to parse and return the browser's version from a user agent string. Returns
|
61
|
-
# nil if nothing is found.
|
62
|
-
def version(ua)
|
63
|
-
if @safe_version
|
64
|
-
ua.slice(@safe_version[0]).slice(@safe_version[1]) rescue nil
|
65
|
-
else
|
66
|
-
ua.slice(@version)
|
67
|
-
end
|
38
|
+
BROWSER_PARSERS[family_sym]
|
68
39
|
end
|
69
40
|
end
|
70
41
|
|
71
|
-
# Each OS in OS_DATA gets its own
|
72
|
-
# objects
|
73
|
-
# that is not currently happening.
|
74
|
-
|
42
|
+
# Each OS in OS_DATA gets its own BrowserParser object. These
|
43
|
+
# parser objects are then used to parse specific data out of a user agent string.
|
75
44
|
class OSParser
|
76
|
-
|
45
|
+
# The operating system name
|
46
|
+
attr_reader :os
|
47
|
+
# The operating system name as a symbol
|
48
|
+
attr_reader :sym
|
49
|
+
# The operating system family name as a symbol
|
50
|
+
attr_reader :family_sym
|
77
51
|
|
78
52
|
# Instantiate a new OSParser using an "OS family" element from OS_DATA
|
79
|
-
def initialize(attrs={})
|
80
|
-
@sym =
|
53
|
+
def initialize(sym, attrs={})
|
54
|
+
@sym = sym
|
81
55
|
@family_sym = attrs[:family_sym] || @sym
|
82
56
|
@os = attrs[:name]
|
83
|
-
@
|
57
|
+
@mobile = attrs[:mobile] || false
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returs true if this is mobile OS, false if not
|
61
|
+
def mobile?
|
62
|
+
@mobile
|
84
63
|
end
|
85
64
|
|
86
65
|
# Returns the OSParser for this OSParser object's Family. E.g. the Ubuntu
|
87
66
|
# OSParser would return the GNU/Linux OSerParser. For OSes that are their own
|
88
67
|
# family (e.g. OS X) it will end up returning itself.
|
89
68
|
def family
|
90
|
-
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# Returns the browser's name, possibly including the version number, e.g. "Chrome 12"
|
95
|
-
def self.browser(ua)
|
96
|
-
browser_parser(ua).browser(ua)
|
97
|
-
end
|
98
|
-
|
99
|
-
# Returns the browser's symbol name, e.g. :chrome
|
100
|
-
def self.browser_sym(user_agent)
|
101
|
-
# This method is overwitten by load_browsers!
|
102
|
-
end
|
103
|
-
|
104
|
-
# Returns the browser's icon name, e.g. :chrome
|
105
|
-
def self.browser_icon(ua)
|
106
|
-
browser_parser(ua).icon
|
107
|
-
end
|
108
|
-
|
109
|
-
# Returns the browser's family name, e.g. "Chromium"
|
110
|
-
def self.browser_family(ua)
|
111
|
-
browser_parser(ua).family.browser
|
112
|
-
end
|
113
|
-
|
114
|
-
# Returns the browser's family's symbol name, e.g. :chromium
|
115
|
-
def self.browser_family_sym(ua)
|
116
|
-
browser_parser(ua).family_sym
|
117
|
-
end
|
118
|
-
|
119
|
-
# Returns the browser's family's icon name, e.g. :chromium
|
120
|
-
def self.browser_family_icon(ua)
|
121
|
-
browser_parser(ua).family.icon
|
122
|
-
end
|
123
|
-
|
124
|
-
# Returns the OS's name, e.g. "Ubuntu"
|
125
|
-
def self.os(ua)
|
126
|
-
os_parser(ua).os
|
127
|
-
end
|
128
|
-
|
129
|
-
# Returns the OS's symbol name, e.g. :ubuntu
|
130
|
-
def self.os_sym(user_agent)
|
131
|
-
# This method is overwitten by load_oses!
|
132
|
-
end
|
133
|
-
|
134
|
-
# Returns the OS's icon name, e.g. :ubuntu
|
135
|
-
def self.os_icon(ua)
|
136
|
-
os_parser(ua).icon
|
137
|
-
end
|
138
|
-
|
139
|
-
# Returns the OS's family, e.g. "GNU/Linux"
|
140
|
-
def self.os_family(ua)
|
141
|
-
os_parser(ua).family.os
|
142
|
-
end
|
143
|
-
|
144
|
-
# Returns the OS's family's symbol name, e.g. :linux
|
145
|
-
def self.os_family_sym(ua)
|
146
|
-
os_parser(ua).family_sym
|
147
|
-
end
|
148
|
-
|
149
|
-
# Returns the OS's family's symbol icon, e.g. :linux
|
150
|
-
def self.os_family_icon(ua)
|
151
|
-
os_parser(ua).family.icon
|
152
|
-
end
|
153
|
-
|
154
|
-
# Returns the correct BrowerParser for the given user agent or symbol
|
155
|
-
def self.browser_parser(ua_or_sym)
|
156
|
-
BROWSERS[ua_or_sym.is_a?(Symbol) ? ua_or_sym : browser_sym(ua_or_sym)]
|
157
|
-
end
|
158
|
-
|
159
|
-
# Returns the correct OSParser for the given user agent or symbol
|
160
|
-
def self.os_parser(ua_or_sym)
|
161
|
-
OSES[ua_or_sym.is_a?(Symbol) ? ua_or_sym : os_sym(ua_or_sym)]
|
162
|
-
end
|
163
|
-
|
164
|
-
# Parses BROWSER_DATA into BROWSERS, a hash of BrowserParser objects indexed by their symbol names.
|
165
|
-
# Parses and evals BROWSER_DATA into a case statement inside of the browser_sym method.
|
166
|
-
def self.load_browsers!
|
167
|
-
BROWSERS.clear
|
168
|
-
str = "case user_agent.to_s\n"
|
169
|
-
BROWSER_DATA.each do |data|
|
170
|
-
BROWSERS[data[:sym]] = BrowserParser.new(data)
|
171
|
-
str << " when %r{#{data[:regex]}}i then :#{data[:sym]}\n"
|
69
|
+
OS_PARSERS[family_sym]
|
172
70
|
end
|
173
|
-
str << 'end'
|
174
|
-
module_eval "def self.browser_sym(user_agent); #{str}; end"
|
175
|
-
end
|
176
|
-
|
177
|
-
# Parses OS_DATA into OSES, a hash of OSParser objects indexed by their symbol names.
|
178
|
-
# Parses and evals OS_DATA into a case statement inside of the os_sym method.
|
179
|
-
def self.load_oses!
|
180
|
-
OSES.clear
|
181
|
-
str = "case user_agent.to_s\n"
|
182
|
-
OS_DATA.each do |data|
|
183
|
-
OSES[data[:sym]] = OSParser.new(data)
|
184
|
-
str << " when %r{#{data[:regex]}}i then :#{data[:sym]}\n"
|
185
|
-
end
|
186
|
-
str << 'end'
|
187
|
-
module_eval "def self.os_sym(user_agent); #{str}; end"
|
188
71
|
end
|
189
72
|
end
|
190
|
-
|
191
|
-
DoubleAgent.load_browsers!
|
192
|
-
DoubleAgent.load_oses!
|