useragent-fl 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
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.
@@ -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
@@ -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
@@ -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
+