useragent-fl 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +19 -0
- data/lib/user_agent.rb +89 -0
- data/lib/user_agent/browsers.rb +26 -0
- data/lib/user_agent/browsers/all.rb +80 -0
- data/lib/user_agent/browsers/gecko.rb +60 -0
- data/lib/user_agent/browsers/internet_explorer.rb +47 -0
- data/lib/user_agent/browsers/opera.rb +41 -0
- data/lib/user_agent/browsers/webkit.rb +123 -0
- data/lib/user_agent/comparable.rb +25 -0
- data/lib/user_agent/operating_systems.rb +20 -0
- data/lib/user_agent/version.rb +89 -0
- data/lib/useragent.rb +1 -0
- metadata +106 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Joshua Peek
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= UserAgent
|
2
|
+
|
3
|
+
UserAgent is a Ruby library that parses and compares HTTP User Agents.
|
4
|
+
|
5
|
+
|
6
|
+
=== Example
|
7
|
+
|
8
|
+
Browser = Struct.new(:browser, :version)
|
9
|
+
SupportedBrowsers = [
|
10
|
+
Browser.new("Safari", "3.1.1"),
|
11
|
+
Browser.new("Firefox", "2.0.0.14"),
|
12
|
+
Browser.new("Internet Explorer", "7.0")
|
13
|
+
]
|
14
|
+
|
15
|
+
user_agent = UserAgent.parse(request.user_agent)
|
16
|
+
SupportedBrowsers.detect { |browser| user_agent >= browser }
|
17
|
+
|
18
|
+
|
19
|
+
Copyright (c) 2009 Joshua Peek, released under the MIT license
|
data/lib/user_agent.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'user_agent/comparable'
|
2
|
+
require 'user_agent/browsers'
|
3
|
+
require 'user_agent/operating_systems'
|
4
|
+
require 'user_agent/version'
|
5
|
+
|
6
|
+
class UserAgent
|
7
|
+
# http://www.texsoft.it/index.php?m=sw.php.useragent
|
8
|
+
MATCHER = %r{
|
9
|
+
^([^/\s]+) # Product
|
10
|
+
/?([^\s]*) # Version
|
11
|
+
(\s\(([^\)]*)\))? # Comment
|
12
|
+
}x.freeze
|
13
|
+
|
14
|
+
DEFAULT_USER_AGENT = "Mozilla/4.0 (compatible)"
|
15
|
+
|
16
|
+
def self.parse(string)
|
17
|
+
if string.nil? || string == ""
|
18
|
+
string = DEFAULT_USER_AGENT
|
19
|
+
end
|
20
|
+
|
21
|
+
agents = []
|
22
|
+
while m = string.to_s.match(MATCHER)
|
23
|
+
agents << new(m[1], m[2], m[4])
|
24
|
+
string = string[m[0].length..-1].strip
|
25
|
+
end
|
26
|
+
Browsers.extend(agents)
|
27
|
+
agents
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :product, :version, :comment
|
31
|
+
|
32
|
+
def initialize(product, version = nil, comment = nil)
|
33
|
+
if product
|
34
|
+
@product = product
|
35
|
+
else
|
36
|
+
raise ArgumentError, "expected a value for product"
|
37
|
+
end
|
38
|
+
|
39
|
+
if version && !version.empty?
|
40
|
+
@version = Version.new(version)
|
41
|
+
else
|
42
|
+
@version = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
if comment.respond_to?(:split)
|
46
|
+
@comment = comment.split("; ")
|
47
|
+
else
|
48
|
+
@comment = comment
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
include Comparable
|
53
|
+
|
54
|
+
# Any comparsion between two user agents with different products will
|
55
|
+
# always return false.
|
56
|
+
def <=>(other)
|
57
|
+
if @product == other.product
|
58
|
+
if @version && other.version
|
59
|
+
@version <=> other.version
|
60
|
+
else
|
61
|
+
0
|
62
|
+
end
|
63
|
+
else
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def eql?(other)
|
69
|
+
@product == other.product &&
|
70
|
+
@version == other.version &&
|
71
|
+
@comment == other.comment
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
to_str
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_str
|
79
|
+
if @product && @version && @comment
|
80
|
+
"#{@product}/#{@version} (#{@comment.join("; ")})"
|
81
|
+
elsif @product && @version
|
82
|
+
"#{@product}/#{@version}"
|
83
|
+
elsif @product && @comment
|
84
|
+
"#{@product} (#{@comment.join("; ")})"
|
85
|
+
else
|
86
|
+
@product
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'user_agent/browsers/all'
|
2
|
+
require 'user_agent/browsers/gecko'
|
3
|
+
require 'user_agent/browsers/internet_explorer'
|
4
|
+
require 'user_agent/browsers/opera'
|
5
|
+
require 'user_agent/browsers/webkit'
|
6
|
+
|
7
|
+
class UserAgent
|
8
|
+
module Browsers
|
9
|
+
Security = {
|
10
|
+
"N" => :none,
|
11
|
+
"U" => :strong,
|
12
|
+
"I" => :weak
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
def self.all
|
16
|
+
[InternetExplorer, Webkit, Opera, Gecko]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.extend(array)
|
20
|
+
array.extend(All)
|
21
|
+
all.each do |extension|
|
22
|
+
return array.extend(extension) if extension.extend?(array)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class UserAgent
|
2
|
+
module Browsers
|
3
|
+
module All
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
def <=>(other)
|
7
|
+
if respond_to?(:browser) && other.respond_to?(:browser) &&
|
8
|
+
browser == other.browser
|
9
|
+
version <=> other.version
|
10
|
+
else
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def eql?(other)
|
16
|
+
self == other
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
to_str
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_str
|
24
|
+
join(" ")
|
25
|
+
end
|
26
|
+
|
27
|
+
def application
|
28
|
+
first
|
29
|
+
end
|
30
|
+
|
31
|
+
def browser
|
32
|
+
application.product
|
33
|
+
end
|
34
|
+
|
35
|
+
def version
|
36
|
+
application.version
|
37
|
+
end
|
38
|
+
|
39
|
+
def platform
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def os
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def respond_to?(symbol)
|
48
|
+
detect_product(symbol) ? true : super
|
49
|
+
end
|
50
|
+
|
51
|
+
def method_missing(method, *args, &block)
|
52
|
+
detect_product(method) || super
|
53
|
+
end
|
54
|
+
|
55
|
+
def webkit?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def mobile?
|
60
|
+
if browser == 'webOS'
|
61
|
+
true
|
62
|
+
elsif platform == 'Symbian'
|
63
|
+
true
|
64
|
+
elsif detect_product('Mobile')
|
65
|
+
true
|
66
|
+
elsif application.comment &&
|
67
|
+
application.comment.detect { |k, v| k =~ /^IEMobile/ }
|
68
|
+
true
|
69
|
+
else
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def detect_product(product)
|
76
|
+
detect { |useragent| useragent.product.to_s.downcase == product.to_s.downcase }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class UserAgent
|
2
|
+
module Browsers
|
3
|
+
module Gecko
|
4
|
+
def self.extend?(agent)
|
5
|
+
agent.application && agent.application.product == "Mozilla"
|
6
|
+
end
|
7
|
+
|
8
|
+
GeckoBrowsers = %w(
|
9
|
+
Firefox
|
10
|
+
Camino
|
11
|
+
Iceweasel
|
12
|
+
Seamonkey
|
13
|
+
).freeze
|
14
|
+
|
15
|
+
def browser
|
16
|
+
GeckoBrowsers.detect { |browser| respond_to?(browser) } || super
|
17
|
+
end
|
18
|
+
|
19
|
+
def version
|
20
|
+
send(browser).version || super
|
21
|
+
end
|
22
|
+
|
23
|
+
def platform
|
24
|
+
if comment = application.comment
|
25
|
+
if comment[0] =~ /Windows/
|
26
|
+
"Windows"
|
27
|
+
else
|
28
|
+
comment[0] == 'compatible' ? nil : comment[0]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def security
|
34
|
+
Security[application.comment[1]] || :strong
|
35
|
+
end
|
36
|
+
|
37
|
+
def os
|
38
|
+
if comment = application.comment
|
39
|
+
i =
|
40
|
+
if comment[1] == "U"
|
41
|
+
2
|
42
|
+
else
|
43
|
+
if comment[1] == "WOW64"
|
44
|
+
0
|
45
|
+
else
|
46
|
+
1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
OperatingSystems.normalize_os(comment[i])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def localization
|
54
|
+
if comment = application.comment
|
55
|
+
comment[3]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class UserAgent
|
2
|
+
module Browsers
|
3
|
+
module InternetExplorer
|
4
|
+
def self.extend?(agent)
|
5
|
+
agent.application &&
|
6
|
+
agent.application.comment &&
|
7
|
+
agent.application.comment[0] == "compatible" &&
|
8
|
+
agent.application.comment[1] =~ /MSIE/
|
9
|
+
end
|
10
|
+
|
11
|
+
def browser
|
12
|
+
"Internet Explorer"
|
13
|
+
end
|
14
|
+
|
15
|
+
def version
|
16
|
+
application.comment[1].sub("MSIE ", "")
|
17
|
+
end
|
18
|
+
|
19
|
+
def compatibility
|
20
|
+
application.comment[0]
|
21
|
+
end
|
22
|
+
|
23
|
+
def compatible?
|
24
|
+
compatibility == "compatible"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Before version 4.0, Chrome Frame declared itself (unversioned) in a comment;
|
28
|
+
# as of 4.0 it can declare itself versioned in a comment
|
29
|
+
# or as a separate product with a version
|
30
|
+
|
31
|
+
def chromeframe
|
32
|
+
cf = application.comment.include?("chromeframe") || detect_product("chromeframe")
|
33
|
+
return cf if cf
|
34
|
+
cf_comment = application.comment.detect{|c| c['chromeframe/']}
|
35
|
+
cf_comment ? UserAgent.new(*cf_comment.split('/', 2)) : nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def platform
|
39
|
+
"Windows"
|
40
|
+
end
|
41
|
+
|
42
|
+
def os
|
43
|
+
OperatingSystems.normalize_os(application.comment[2])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class UserAgent
|
2
|
+
module Browsers
|
3
|
+
module Opera
|
4
|
+
def self.extend?(agent)
|
5
|
+
agent.application && agent.application.product == "Opera"
|
6
|
+
end
|
7
|
+
|
8
|
+
def platform
|
9
|
+
if application.comment[0] =~ /Windows/
|
10
|
+
"Windows"
|
11
|
+
else
|
12
|
+
application.comment[0]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def security
|
17
|
+
if platform == "Macintosh"
|
18
|
+
Security[application.comment[2]]
|
19
|
+
else
|
20
|
+
Security[application.comment[1]]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def os
|
25
|
+
if application.comment[0] =~ /Windows/
|
26
|
+
OperatingSystems.normalize_os(application.comment[0])
|
27
|
+
else
|
28
|
+
application.comment[1]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def localization
|
33
|
+
if platform == "Macintosh"
|
34
|
+
application.comment[3]
|
35
|
+
else
|
36
|
+
application.comment[2]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
class UserAgent
|
2
|
+
module Browsers
|
3
|
+
module Webkit
|
4
|
+
def self.extend?(agent)
|
5
|
+
agent.detect { |useragent| useragent.product == 'AppleWebKit' }
|
6
|
+
end
|
7
|
+
|
8
|
+
def webkit?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def browser
|
13
|
+
if os =~ /Android/
|
14
|
+
'Android'
|
15
|
+
elsif detect_product('Chrome')
|
16
|
+
'Chrome'
|
17
|
+
elsif platform == 'webOS' || platform == 'BlackBerry' || platform == 'Symbian'
|
18
|
+
platform
|
19
|
+
else
|
20
|
+
'Safari'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def build
|
25
|
+
webkit.version
|
26
|
+
end
|
27
|
+
|
28
|
+
BuildVersions = {
|
29
|
+
"85.7" => "1.0",
|
30
|
+
"85.8.5" => "1.0.3",
|
31
|
+
"85.8.2" => "1.0.3",
|
32
|
+
"124" => "1.2",
|
33
|
+
"125.2" => "1.2.2",
|
34
|
+
"125.4" => "1.2.3",
|
35
|
+
"125.5.5" => "1.2.4",
|
36
|
+
"125.5.6" => "1.2.4",
|
37
|
+
"125.5.7" => "1.2.4",
|
38
|
+
"312.1.1" => "1.3",
|
39
|
+
"312.1" => "1.3",
|
40
|
+
"312.5" => "1.3.1",
|
41
|
+
"312.5.1" => "1.3.1",
|
42
|
+
"312.5.2" => "1.3.1",
|
43
|
+
"312.8" => "1.3.2",
|
44
|
+
"312.8.1" => "1.3.2",
|
45
|
+
"412" => "2.0",
|
46
|
+
"412.6" => "2.0",
|
47
|
+
"412.6.2" => "2.0",
|
48
|
+
"412.7" => "2.0.1",
|
49
|
+
"416.11" => "2.0.2",
|
50
|
+
"416.12" => "2.0.2",
|
51
|
+
"417.9" => "2.0.3",
|
52
|
+
"418" => "2.0.3",
|
53
|
+
"418.8" => "2.0.4",
|
54
|
+
"418.9" => "2.0.4",
|
55
|
+
"418.9.1" => "2.0.4",
|
56
|
+
"419" => "2.0.4",
|
57
|
+
"425.13" => "2.2"
|
58
|
+
}.freeze
|
59
|
+
|
60
|
+
# Prior to Safari 3, the user agent did not include a version number
|
61
|
+
def version
|
62
|
+
str = if os =~ /CPU (?:iPhone |iPod )?OS ([\d_]+) like Mac OS X/
|
63
|
+
$1.gsub(/_/, '.')
|
64
|
+
elsif product = detect_product('Version')
|
65
|
+
product.version
|
66
|
+
elsif browser == 'Chrome'
|
67
|
+
chrome.version
|
68
|
+
else
|
69
|
+
BuildVersions[build.to_s]
|
70
|
+
end
|
71
|
+
|
72
|
+
Version.new(str) if str
|
73
|
+
end
|
74
|
+
|
75
|
+
def application
|
76
|
+
apps = self.reject{|agent| agent.comment.nil? || agent.comment.empty?}
|
77
|
+
apps.first
|
78
|
+
end
|
79
|
+
|
80
|
+
def platform
|
81
|
+
if application.comment[0] =~ /Symbian/
|
82
|
+
'Symbian'
|
83
|
+
elsif application.comment[0] =~ /webOS/
|
84
|
+
'webOS'
|
85
|
+
elsif application.comment[0] =~ /Windows/
|
86
|
+
"Windows"
|
87
|
+
else
|
88
|
+
application.comment[0]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def webkit
|
93
|
+
detect { |useragent| useragent.product == "AppleWebKit" }
|
94
|
+
end
|
95
|
+
|
96
|
+
def security
|
97
|
+
Security[application.comment[1]]
|
98
|
+
end
|
99
|
+
|
100
|
+
def os
|
101
|
+
if platform == 'webOS'
|
102
|
+
"Palm #{last.product} #{last.version}"
|
103
|
+
elsif platform == 'Symbian'
|
104
|
+
application.comment[0]
|
105
|
+
elsif application.comment[0] =~ /Windows NT/
|
106
|
+
OperatingSystems.normalize_os(application.comment[0])
|
107
|
+
else
|
108
|
+
OperatingSystems.normalize_os(application.comment[2] || application.comment[1] || application.comment[0])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def localization
|
113
|
+
# TODO: Ensure that this is common to all webOS UserAgent
|
114
|
+
if platform == 'webOS'
|
115
|
+
application.comment[2]
|
116
|
+
else
|
117
|
+
application.comment[3]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class UserAgent
|
2
|
+
# A custom Comparable module that will always return false
|
3
|
+
# if the <=> returns false
|
4
|
+
module Comparable
|
5
|
+
def <(other)
|
6
|
+
(c = self <=> other) ? c == -1 : false
|
7
|
+
end
|
8
|
+
|
9
|
+
def <=(other)
|
10
|
+
(c = self <=> other) ? c == -1 || c == 0 : false
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
(c = self <=> other) ? c == 0 : false
|
15
|
+
end
|
16
|
+
|
17
|
+
def >(other)
|
18
|
+
(c = self <=> other) ? c == 1 : false
|
19
|
+
end
|
20
|
+
|
21
|
+
def >=(other)
|
22
|
+
(c = self <=> other) ? c == 1 || c == 0 : false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class UserAgent
|
2
|
+
module OperatingSystems
|
3
|
+
Windows = {
|
4
|
+
"Windows NT 6.1" => "Windows 7",
|
5
|
+
"Windows NT 6.0" => "Windows Vista",
|
6
|
+
"Windows NT 5.2" => "Windows XP x64 Edition",
|
7
|
+
"Windows NT 5.1" => "Windows XP",
|
8
|
+
"Windows NT 5.01" => "Windows 2000, Service Pack 1 (SP1)",
|
9
|
+
"Windows NT 5.0" => "Windows 2000",
|
10
|
+
"Windows NT 4.0" => "Windows NT 4.0",
|
11
|
+
"Windows 98" => "Windows 98",
|
12
|
+
"Windows 95" => "Windows 95",
|
13
|
+
"Windows CE" => "Windows CE"
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
def self.normalize_os(os)
|
17
|
+
Windows[os] || os
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class UserAgent
|
2
|
+
class Version
|
3
|
+
include ::Comparable
|
4
|
+
|
5
|
+
def self.new(obj)
|
6
|
+
case obj
|
7
|
+
when Version
|
8
|
+
obj
|
9
|
+
when String
|
10
|
+
super
|
11
|
+
else
|
12
|
+
raise ArgumentError, "invalid value for Version: #{obj.inspect}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(str)
|
17
|
+
@str = str
|
18
|
+
|
19
|
+
if str =~ /^\d+$/ || str =~ /^\d+\./
|
20
|
+
@sequences = str.scan(/\d+|[A-Za-z][0-9A-Za-z-]*$/).map { |s| s =~ /^\d+$/ ? s.to_i : s }
|
21
|
+
@comparable = true
|
22
|
+
else
|
23
|
+
@sequences = [str]
|
24
|
+
@comparable = false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_a
|
29
|
+
@sequences.dup
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_str
|
33
|
+
@str.dup
|
34
|
+
end
|
35
|
+
|
36
|
+
def eql?(other)
|
37
|
+
other.is_a?(self.class) && to_s == other.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
case other
|
42
|
+
when Version
|
43
|
+
eql?(other)
|
44
|
+
when String
|
45
|
+
eql?(self.class.new(other))
|
46
|
+
else
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def <=>(other)
|
52
|
+
case other
|
53
|
+
when Version
|
54
|
+
if @comparable
|
55
|
+
to_a.zip(other.to_a).each do |a, b|
|
56
|
+
if b.nil?
|
57
|
+
return -1
|
58
|
+
elsif a.nil?
|
59
|
+
return 1
|
60
|
+
elsif a.is_a?(String) && b.is_a?(Integer)
|
61
|
+
return -1
|
62
|
+
elsif a.is_a?(Integer) && b.is_a?(String)
|
63
|
+
return 1
|
64
|
+
elsif a == b
|
65
|
+
next
|
66
|
+
else
|
67
|
+
return a <=> b
|
68
|
+
end
|
69
|
+
end
|
70
|
+
0
|
71
|
+
else
|
72
|
+
to_s == other.to_s ? 0 : nil
|
73
|
+
end
|
74
|
+
when String
|
75
|
+
self <=> self.class.new(other)
|
76
|
+
else
|
77
|
+
raise ArgumentError, "comparison of Version with #{other.inspect} failed"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_s
|
82
|
+
to_str
|
83
|
+
end
|
84
|
+
|
85
|
+
def inspect
|
86
|
+
"#<#{self.class} #{to_s}>"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/useragent.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'user_agent'
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: useragent-fl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 9
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 3
|
10
|
+
version: 0.4.3
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Joshua Peek
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-08-25 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rake
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description: " HTTP User Agent parser\n"
|
50
|
+
email: josh@joshpeek.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- lib/user_agent.rb
|
59
|
+
- lib/user_agent/browsers.rb
|
60
|
+
- lib/user_agent/browsers/all.rb
|
61
|
+
- lib/user_agent/browsers/gecko.rb
|
62
|
+
- lib/user_agent/browsers/internet_explorer.rb
|
63
|
+
- lib/user_agent/browsers/opera.rb
|
64
|
+
- lib/user_agent/browsers/webkit.rb
|
65
|
+
- lib/user_agent/comparable.rb
|
66
|
+
- lib/user_agent/operating_systems.rb
|
67
|
+
- lib/user_agent/version.rb
|
68
|
+
- lib/useragent.rb
|
69
|
+
- LICENSE
|
70
|
+
- README.rdoc
|
71
|
+
has_rdoc: true
|
72
|
+
homepage: http://github.com/jakedouglas/useragent
|
73
|
+
licenses: []
|
74
|
+
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.6.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: HTTP User Agent parser
|
105
|
+
test_files: []
|
106
|
+
|