useragent-fl 0.4.3

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.
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
+