agent_orange 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.rdoc +153 -0
- data/Rakefile +1 -0
- data/agent_orange.gemspec +20 -0
- data/bin/agent_orange_example +19 -0
- data/lib/agent_orange/browser.rb +64 -0
- data/lib/agent_orange/device.rb +109 -0
- data/lib/agent_orange/engine.rb +68 -0
- data/lib/agent_orange/operating_system.rb +9 -0
- data/lib/agent_orange/platform.rb +9 -0
- data/lib/agent_orange/user_agent.rb +71 -0
- data/lib/agent_orange/version.rb +11 -0
- data/lib/agent_orange.rb +8 -0
- metadata +79 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
= agent_orange
|
2
|
+
|
3
|
+
User Agent detection for Ruby. ActionController integration coming soon.
|
4
|
+
|
5
|
+
== About
|
6
|
+
|
7
|
+
There are quite a few User Agent parsing libraries already, but none of them make adequate
|
8
|
+
detection of mobile browsers and clients. With such a significant number of requests
|
9
|
+
coming from mobile users a library with the ability to detect what type of device a user
|
10
|
+
is coming from is necessary.
|
11
|
+
|
12
|
+
This library for Ruby will allow you to detect whether a user is on a computer, a mobile
|
13
|
+
device, or is a bot (such as Google). It was composed by using techniques gathered from
|
14
|
+
several other libraries/gems in an effort to be consistent and cover as many types
|
15
|
+
of agents as possible.
|
16
|
+
|
17
|
+
== Status
|
18
|
+
|
19
|
+
=== Improvement stage.
|
20
|
+
|
21
|
+
This library is not yet testable but does function. Please contact me if you'd like
|
22
|
+
to participate.
|
23
|
+
|
24
|
+
== Installation
|
25
|
+
|
26
|
+
gem install agent_orange
|
27
|
+
|
28
|
+
If you're going to use it with Rails then add the gem to your Gemfile.
|
29
|
+
|
30
|
+
== Example Usage
|
31
|
+
|
32
|
+
=== Create new user agent parser
|
33
|
+
|
34
|
+
>> ua = AgentOrange::UserAgent.new(user_agent_string)
|
35
|
+
|
36
|
+
=== Looking at the device
|
37
|
+
|
38
|
+
>> device = ua.device
|
39
|
+
=> "iPhone 3G"
|
40
|
+
>> device.type
|
41
|
+
=> "mobile"
|
42
|
+
>> device.manufacturer
|
43
|
+
=> "Apple"
|
44
|
+
>> device.name
|
45
|
+
=> "iPhone"
|
46
|
+
>> device.version
|
47
|
+
=> nil
|
48
|
+
|
49
|
+
=== Check to see if the device is mobile, a desktop/laptop/server computer, or a bot
|
50
|
+
|
51
|
+
>> device.is_mobile?
|
52
|
+
=> true
|
53
|
+
>> device.is_computer?
|
54
|
+
=> false
|
55
|
+
>> device.is_bot?
|
56
|
+
=> false
|
57
|
+
|
58
|
+
=== Use the proxies to check if the user is on a mobile device
|
59
|
+
|
60
|
+
>> ua.is_mobile?
|
61
|
+
=> true
|
62
|
+
|
63
|
+
=== Looking at the web engine
|
64
|
+
|
65
|
+
>> engine = ua.device.engine
|
66
|
+
=> "WebKit 5.3"
|
67
|
+
>> engine.type
|
68
|
+
=> "webkit"
|
69
|
+
>> engine.name
|
70
|
+
=> "WebKit"
|
71
|
+
>> engine.version
|
72
|
+
=> "5.3.1.2321"
|
73
|
+
|
74
|
+
=== Looking at the browser
|
75
|
+
|
76
|
+
>> browser = ua.device.engine.browser
|
77
|
+
=> "Internet Explorer 10"
|
78
|
+
>> browser.type
|
79
|
+
=> "ie"
|
80
|
+
>> browser.name
|
81
|
+
=> "Internet Explorer"
|
82
|
+
>> browser.version
|
83
|
+
=> "10.0.112"
|
84
|
+
|
85
|
+
=== Quickly get to the browser version
|
86
|
+
|
87
|
+
>> AgentOrange::UserAgent.new(user_agent_string).device.engine.browser.version
|
88
|
+
=> "10.0.112"
|
89
|
+
|
90
|
+
== General Class Definition
|
91
|
+
|
92
|
+
This is not up to date or a reflection of the actual class structure. This will be updated eventually.
|
93
|
+
|
94
|
+
AgentOrange::UserAgent
|
95
|
+
device
|
96
|
+
parse
|
97
|
+
is_computer? # proxy
|
98
|
+
is_mobile? # proxy
|
99
|
+
is_bot? # proxy
|
100
|
+
to_s
|
101
|
+
|
102
|
+
AgentOrange::Device
|
103
|
+
parse
|
104
|
+
type
|
105
|
+
name
|
106
|
+
version
|
107
|
+
is_computer?(name=nil) #
|
108
|
+
is_mobile?(name=nil) # accepts a :symbol or "String"
|
109
|
+
is_bot?(name=nil) #
|
110
|
+
to_s
|
111
|
+
|
112
|
+
AgentOrange::Engine
|
113
|
+
parse
|
114
|
+
type
|
115
|
+
name
|
116
|
+
version
|
117
|
+
to_s
|
118
|
+
|
119
|
+
AgentOrange::Version
|
120
|
+
parse
|
121
|
+
major
|
122
|
+
minor
|
123
|
+
patch_level
|
124
|
+
build_number
|
125
|
+
to_s
|
126
|
+
|
127
|
+
== Maintainer
|
128
|
+
|
129
|
+
* Kevin Elliott - http://kevinelliott.net
|
130
|
+
* WeLike - http://www.welikeinc.com - http://github.com/welike
|
131
|
+
|
132
|
+
== License
|
133
|
+
|
134
|
+
(The MIT License)
|
135
|
+
|
136
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
137
|
+
a copy of this software and associated documentation files (the
|
138
|
+
'Software'), to deal in the Software without restriction, including
|
139
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
140
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
141
|
+
permit persons to whom the Software is furnished to do so, subject to
|
142
|
+
the following conditions:
|
143
|
+
|
144
|
+
The above copyright notice and this permission notice shall be
|
145
|
+
included in all copies or substantial portions of the Software.
|
146
|
+
|
147
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
148
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
149
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
150
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
151
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
152
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
153
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "agent_orange/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "agent_orange"
|
7
|
+
s.version = AgentOrange::VERSION
|
8
|
+
s.authors = ["Kevin Elliott"]
|
9
|
+
s.email = ["kevin@welikeinc.com"]
|
10
|
+
s.homepage = "http://github.com/kevinelliott/agent_orange"
|
11
|
+
s.summary = %q{Parse and process User Agents like a secret one}
|
12
|
+
s.description = %q{Parse and process User Agents like a secret one}
|
13
|
+
|
14
|
+
s.rubyforge_project = "agent_orange"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "agent_orange/user_agent"
|
4
|
+
|
5
|
+
def process_user_agent(ua_str)
|
6
|
+
puts
|
7
|
+
puts '='*120
|
8
|
+
puts "User-Agent:"
|
9
|
+
puts " #{ua_str}"
|
10
|
+
puts
|
11
|
+
ua = AgentOrange::UserAgent.new(:user_agent => ua_str)
|
12
|
+
puts '='*120
|
13
|
+
end
|
14
|
+
|
15
|
+
ua_str = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; sv-se) AppleWebKit/525.26.2 (KHTML, like Gecko) Version/3.2 Safari/525.26.12"
|
16
|
+
process_user_agent(ua_str)
|
17
|
+
|
18
|
+
ua_str = "Mozilla/5.0 (iPhone; U; Linux i686; pt-br) AppleWebKit/532+ (KHTML, like Gecko) Version/3.0 Mobile/1A538b Safari/419.3 Midori/0.2.0"
|
19
|
+
process_user_agent(ua_str)
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module AgentOrange
|
2
|
+
class Browser
|
3
|
+
attr_accessor :type, :name, :version
|
4
|
+
attr_accessor :security
|
5
|
+
|
6
|
+
BROWSERS = {
|
7
|
+
:ie => 'MSIE|Internet Explorer|IE',
|
8
|
+
:firefox => 'Firefox',
|
9
|
+
:safari => 'Safari'
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize(user_agent)
|
13
|
+
self.parse(user_agent)
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse(user_agent)
|
17
|
+
AgentOrange.debug "BROWSER PARSING", 2
|
18
|
+
groups = user_agent.scan(/([^\/[:space:]]*)(\/([^[:space:]]*))?([[:space:]]*\[[a-zA-Z][a-zA-Z]\])?[[:space:]]*(\((([^()]|(\([^()]*\)))*)\))?[[:space:]]*/i)
|
19
|
+
groups.each_with_index do |pieces,i|
|
20
|
+
name = pieces[0]
|
21
|
+
version = pieces[2]
|
22
|
+
comment = pieces[5]
|
23
|
+
|
24
|
+
if name =~ /(#{BROWSERS.collect{|cat,regex| regex}.join(')|(')})/i
|
25
|
+
# Found the browser
|
26
|
+
AgentOrange.debug " Got a browser in group #{i+1}!", 2
|
27
|
+
AgentOrange.debug " Raw Name : #{name}", 2
|
28
|
+
AgentOrange.debug " Raw Version: #{version}", 2
|
29
|
+
AgentOrange.debug " Raw Comment: #{comment}", 2
|
30
|
+
AgentOrange.debug "", 2
|
31
|
+
|
32
|
+
# Determine browser type
|
33
|
+
if name =~ /(#{BROWSERS[:ie]})/i
|
34
|
+
self.type = "ie"
|
35
|
+
elsif name =~ /(#{BROWSERS[:firefox]})/i
|
36
|
+
self.type = "firefox"
|
37
|
+
elsif name =~ /(#{BROWSERS[:safari]})/i
|
38
|
+
self.type = "safari"
|
39
|
+
else
|
40
|
+
self.type = "other"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Determine browser name
|
44
|
+
self.name = name
|
45
|
+
|
46
|
+
# Determine device version
|
47
|
+
self.version = version
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
AgentOrange.debug "BROWSER ANALYSIS", 2
|
54
|
+
AgentOrange.debug " Type: #{self.type}", 2
|
55
|
+
AgentOrange.debug " Name: #{self.name}", 2
|
56
|
+
AgentOrange.debug " Version: #{self.version}", 2
|
57
|
+
AgentOrange.debug "", 2
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
[self.name, self.version].compact.join(' ')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'agent_orange/engine'
|
2
|
+
|
3
|
+
module AgentOrange
|
4
|
+
class Device
|
5
|
+
attr_accessor :type, :name, :version
|
6
|
+
attr_accessor :platform
|
7
|
+
attr_accessor :operating_system
|
8
|
+
attr_accessor :engine
|
9
|
+
|
10
|
+
DEVICES = {
|
11
|
+
:computer => 'windows|macintosh|x11|linux',
|
12
|
+
:mobile => 'ipod|ipad|iphone|palm|android|opera mini|hiptop|windows ce|smartphone|mobile|treo|psp',
|
13
|
+
:bot => 'bot'
|
14
|
+
}
|
15
|
+
|
16
|
+
def initialize(user_agent)
|
17
|
+
self.parse(user_agent)
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse(user_agent)
|
21
|
+
AgentOrange.debug "DEVICE PARSING", 2
|
22
|
+
groups = user_agent.scan(/([^\/[:space:]]*)(\/([^[:space:]]*))?([[:space:]]*\[[a-zA-Z][a-zA-Z]\])?[[:space:]]*(\((([^()]|(\([^()]*\)))*)\))?[[:space:]]*/i)
|
23
|
+
groups.each_with_index do |pieces,i|
|
24
|
+
name = pieces[0]
|
25
|
+
version = pieces[2]
|
26
|
+
comment = pieces[5]
|
27
|
+
|
28
|
+
if comment =~ /(#{DEVICES.collect{|cat,regex| regex}.join(')|(')})/i
|
29
|
+
# Found the device
|
30
|
+
AgentOrange.debug " Got a device in group #{i+1}!", 2
|
31
|
+
AgentOrange.debug " Raw Name : #{name}", 2
|
32
|
+
AgentOrange.debug " Raw Version: #{version}", 2
|
33
|
+
AgentOrange.debug " Raw Comment: #{comment}", 2
|
34
|
+
AgentOrange.debug "", 2
|
35
|
+
|
36
|
+
# Determine device type
|
37
|
+
if comment =~ /(#{DEVICES[:computer]})/i
|
38
|
+
self.type = "computer"
|
39
|
+
end
|
40
|
+
if comment =~ /(#{DEVICES[:mobile]})/i
|
41
|
+
self.type = "mobile"
|
42
|
+
end
|
43
|
+
if comment =~ /(#{DEVICES[:bot]})/i
|
44
|
+
self.type = "bot"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Determine device name
|
48
|
+
self.name = comment.split(';')[0]
|
49
|
+
|
50
|
+
# Determine device version
|
51
|
+
self.version = nil
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
AgentOrange.debug "DEVICE ANALYSIS", 2
|
58
|
+
AgentOrange.debug " Type: #{self.type}", 2
|
59
|
+
AgentOrange.debug " Name: #{self.name}", 2
|
60
|
+
AgentOrange.debug " Version: #{self.version}", 2
|
61
|
+
AgentOrange.debug "", 2
|
62
|
+
|
63
|
+
self.engine = AgentOrange::Engine.new(user_agent)
|
64
|
+
end
|
65
|
+
|
66
|
+
def is_computer?(name=nil)
|
67
|
+
if name
|
68
|
+
case name
|
69
|
+
when String
|
70
|
+
return self.name.downcase.include?(name.downcase)
|
71
|
+
when Symbol
|
72
|
+
return self.name.downcase.include?(name.to_s.downcase)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
(self.type == "computer")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def is_mobile?(name=nil)
|
80
|
+
if name
|
81
|
+
case name
|
82
|
+
when String
|
83
|
+
return self.name.downcase.include?(name.downcase)
|
84
|
+
when Symbol
|
85
|
+
return self.name.downcase.include?(name.to_s.downcase)
|
86
|
+
end
|
87
|
+
else
|
88
|
+
self.type == "mobile"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def is_bot?(name=nil)
|
93
|
+
if name
|
94
|
+
case name
|
95
|
+
when String
|
96
|
+
return self.name.downcase.include?(name.downcase)
|
97
|
+
when Symbol
|
98
|
+
return self.name.downcase.include?(name.to_s.downcase)
|
99
|
+
end
|
100
|
+
else
|
101
|
+
self.type == "bot"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_s
|
106
|
+
[self.name, self.version].compact.join(' ')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'agent_orange/browser'
|
2
|
+
|
3
|
+
module AgentOrange
|
4
|
+
class Engine
|
5
|
+
attr_accessor :type, :name, :version
|
6
|
+
attr_accessor :browser
|
7
|
+
|
8
|
+
ENGINES = {
|
9
|
+
:gecko => 'Gecko',
|
10
|
+
:presto => 'Presto',
|
11
|
+
:webkit => 'AppleWebKit'
|
12
|
+
}
|
13
|
+
|
14
|
+
def initialize(user_agent)
|
15
|
+
self.parse(user_agent)
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse(user_agent)
|
19
|
+
AgentOrange.debug "ENGINE PARSING", 2
|
20
|
+
groups = user_agent.scan(/([^\/[:space:]]*)(\/([^[:space:]]*))?([[:space:]]*\[[a-zA-Z][a-zA-Z]\])?[[:space:]]*(\((([^()]|(\([^()]*\)))*)\))?[[:space:]]*/i)
|
21
|
+
groups.each_with_index do |pieces,i|
|
22
|
+
name = pieces[0]
|
23
|
+
version = pieces[2]
|
24
|
+
comment = pieces[5]
|
25
|
+
|
26
|
+
if name =~ /(#{ENGINES.collect{|cat,regex| regex}.join(')|(')})/i
|
27
|
+
# Found the engine
|
28
|
+
AgentOrange.debug " Got an engine in group #{i+1}!", 2
|
29
|
+
AgentOrange.debug " Raw Name : #{name}", 2
|
30
|
+
AgentOrange.debug " Raw Version: #{version}", 2
|
31
|
+
AgentOrange.debug " Raw Comment: #{comment}", 2
|
32
|
+
AgentOrange.debug "", 2
|
33
|
+
|
34
|
+
# Determine engine type
|
35
|
+
if name =~ /(#{ENGINES[:gecko]})/i
|
36
|
+
self.type = "gecko"
|
37
|
+
end
|
38
|
+
if name =~ /(#{ENGINES[:presto]})/i
|
39
|
+
self.type = "presto"
|
40
|
+
end
|
41
|
+
if name =~ /(#{ENGINES[:webkit]})/i
|
42
|
+
self.type = "webkit"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Determine engine name
|
46
|
+
self.name = name
|
47
|
+
|
48
|
+
# Determine device version
|
49
|
+
self.version = version
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
AgentOrange.debug "ENGINE ANALYSIS", 2
|
56
|
+
AgentOrange.debug " Type: #{self.type}", 2
|
57
|
+
AgentOrange.debug " Name: #{self.name}", 2
|
58
|
+
AgentOrange.debug " Version: #{self.version}", 2
|
59
|
+
AgentOrange.debug "", 2
|
60
|
+
|
61
|
+
self.browser = AgentOrange::Browser.new(user_agent)
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_s
|
65
|
+
[self.name, self.version].compact.join(' ')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'agent_orange/device'
|
2
|
+
|
3
|
+
module AgentOrange
|
4
|
+
DEBUG = true
|
5
|
+
DEBUG_LEVEL = 1
|
6
|
+
|
7
|
+
class UserAgent
|
8
|
+
attr_accessor :user_agent_string
|
9
|
+
attr_accessor :user_language
|
10
|
+
attr_accessor :device
|
11
|
+
|
12
|
+
def initialize(options = {}, &block)
|
13
|
+
@user_agent_string = options[:user_agent].to_s
|
14
|
+
self.parse(@user_agent_string)
|
15
|
+
|
16
|
+
yield self if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(user_agent)
|
20
|
+
self.device = AgentOrange::Device.new(user_agent)
|
21
|
+
|
22
|
+
AgentOrange.debug "Device = #{self.device}"
|
23
|
+
AgentOrange.debug " Is computer? #{self.is_computer?}"
|
24
|
+
AgentOrange.debug " Is mobile? #{self.is_mobile?}"
|
25
|
+
if self.is_mobile?
|
26
|
+
AgentOrange.debug " Is an iPhone? #{self.is_mobile? :iphone}"
|
27
|
+
AgentOrange.debug " Is an iPad? #{self.is_mobile? :ipad}"
|
28
|
+
AgentOrange.debug " Is an iPod? #{self.is_mobile? :ipod}"
|
29
|
+
AgentOrange.debug " Is an Android? #{self.is_mobile? :android}"
|
30
|
+
end
|
31
|
+
AgentOrange.debug " Is bot? #{self.is_bot?}"
|
32
|
+
AgentOrange.debug
|
33
|
+
|
34
|
+
AgentOrange.debug "Engine = #{self.device.engine}"
|
35
|
+
AgentOrange.debug "Browser = #{self.device.engine.browser}"
|
36
|
+
|
37
|
+
AgentOrange.debug "", 2
|
38
|
+
AgentOrange.debug "user_agent.to_s = #{self}", 2
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_computer?(type=nil)
|
42
|
+
self.device.is_computer?(type)
|
43
|
+
end
|
44
|
+
|
45
|
+
def is_mobile?(type=nil)
|
46
|
+
self.device.is_mobile?(type)
|
47
|
+
end
|
48
|
+
|
49
|
+
def is_bot?(type=nil)
|
50
|
+
self.device.is_bot?(type)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
[self.device, self.device.engine, self.device.engine.browser].compact.join(", ")
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_human_string
|
58
|
+
if self.device && self.device.engine && self.device.engine.browser
|
59
|
+
"User has a #{self.device} running #{self.device.engine.browser} (which is based on #{self.device.engine})."
|
60
|
+
else
|
61
|
+
"User has some kind of device that I've never seen."
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.debug(str="", level=1)
|
68
|
+
puts str if DEBUG && (DEBUG_LEVEL >= level)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module AgentOrange
|
2
|
+
VERSION = "0.0.1" # This is for the gem and does not conflict with the rest of the functionality
|
3
|
+
|
4
|
+
class Version
|
5
|
+
attr_accessor :major, :minor, :patch_level, :build_number
|
6
|
+
|
7
|
+
def to_s
|
8
|
+
"#{self.major}.#{self.minor}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/agent_orange.rb
ADDED
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: agent_orange
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Kevin Elliott
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-09-11 00:00:00 Z
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Parse and process User Agents like a secret one
|
22
|
+
email:
|
23
|
+
- kevin@welikeinc.com
|
24
|
+
executables:
|
25
|
+
- agent_orange_example
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- Gemfile
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- agent_orange.gemspec
|
36
|
+
- bin/agent_orange_example
|
37
|
+
- lib/agent_orange.rb
|
38
|
+
- lib/agent_orange/browser.rb
|
39
|
+
- lib/agent_orange/device.rb
|
40
|
+
- lib/agent_orange/engine.rb
|
41
|
+
- lib/agent_orange/operating_system.rb
|
42
|
+
- lib/agent_orange/platform.rb
|
43
|
+
- lib/agent_orange/user_agent.rb
|
44
|
+
- lib/agent_orange/version.rb
|
45
|
+
homepage: http://github.com/kevinelliott/agent_orange
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project: agent_orange
|
74
|
+
rubygems_version: 1.8.5
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Parse and process User Agents like a secret one
|
78
|
+
test_files: []
|
79
|
+
|