aua 0.1.0

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/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.2@aua
data/CHANGES.md ADDED
@@ -0,0 +1,7 @@
1
+ ### dev
2
+
3
+ [full changelog](http://github.com/yolk/aua/compare/v0.1.0...master)
4
+
5
+ ### 0.1.0 / 2011-01-27
6
+
7
+ * Initial version
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in aua.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ aua (0.1.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ configuration (1.2.0)
10
+ diff-lcs (1.1.2)
11
+ growl (1.0.3)
12
+ guard (0.3.0)
13
+ open_gem (~> 1.4.2)
14
+ thor (~> 0.14.6)
15
+ guard-rspec (0.1.9)
16
+ guard (>= 0.2.2)
17
+ launchy (0.3.7)
18
+ configuration (>= 0.0.5)
19
+ rake (>= 0.8.1)
20
+ open_gem (1.4.2)
21
+ launchy (~> 0.3.5)
22
+ rake (0.8.7)
23
+ rb-fsevent (0.3.9)
24
+ rspec (2.4.0)
25
+ rspec-core (~> 2.4.0)
26
+ rspec-expectations (~> 2.4.0)
27
+ rspec-mocks (~> 2.4.0)
28
+ rspec-core (2.4.0)
29
+ rspec-expectations (2.4.0)
30
+ diff-lcs (~> 1.1.2)
31
+ rspec-mocks (2.4.0)
32
+ thor (0.14.6)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ aua!
39
+ growl (>= 1.0.3)
40
+ guard-rspec (>= 0.1.9)
41
+ rb-fsevent (>= 0.3.9)
42
+ rspec (>= 2.4.0)
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(/^spec\/(.*)_spec\.rb/) { "spec" }
3
+ watch(/^lib\/(.*)\.rb/) { "spec" } # { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch(/^spec\/spec_helper\.rb/) { "spec" }
5
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Yolk Sebastian Munz & Julia Soergel GbR
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.md ADDED
@@ -0,0 +1,22 @@
1
+ Aua
2
+ =============
3
+
4
+ aua = a user agent (parser).
5
+
6
+ Installation
7
+ -------
8
+
9
+ gem install aua
10
+
11
+
12
+ Basic Usage
13
+ -------
14
+
15
+ Aua.parse("Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; de; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13")
16
+
17
+ BlaBla
18
+ -------
19
+
20
+ Copyright (c) 2011 Yolk Sebastian Munz & Julia Soergel GbR
21
+
22
+ Beyond that, the implementation is licensed under the MIT License.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
data/aua.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "aua/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "aua"
7
+ s.version = Aua::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Sebastian Munz"]
10
+ s.email = ["sebastian@yo.lk"]
11
+ s.homepage = "http://rubygems.org/gems/aua"
12
+ s.summary = %q{aua = a user agent (parser).}
13
+ s.description = %q{aua = a user agent (parser).}
14
+
15
+ s.rubyforge_project = "aua"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency 'rspec', '>= 2.4.0'
23
+ s.add_development_dependency 'guard-rspec', '>=0.1.9'
24
+ s.add_development_dependency 'growl', '>=1.0.3'
25
+ s.add_development_dependency 'rb-fsevent', '>=0.3.9'
26
+ end
data/lib/aua.rb ADDED
@@ -0,0 +1,87 @@
1
+ class Aua
2
+ MATCHER = %r{
3
+ ^([^\s/]+) # Product
4
+ /?([^\s]*) # Version
5
+ (\s\(([^\)]*)\))? # Comment
6
+ }x.freeze
7
+
8
+ def initialize(string="")
9
+ @raw = string.to_s
10
+ parse
11
+ end
12
+
13
+ def self.parse(raw)
14
+ new(raw)
15
+ end
16
+
17
+ def parse
18
+ string = @raw.dup
19
+ @parts = []
20
+ while m = string.match(MATCHER)
21
+ @parts << [m[1] ? m[1].sub(/;$/,"") : m[1], m[2], m[4] ? m[4].split(/\s?;\s?/) : []]
22
+ string = string.sub(m[0], '').strip
23
+ end
24
+
25
+ Aua::Agents.extend_agent(self)
26
+ Aua::OperatingSystems.extend_agent(self)
27
+ end
28
+
29
+ attr_reader :type, :name, :version, :os_name, :os_version, :parts, :raw, :platform
30
+
31
+ def products
32
+ @products ||= parts.map{|p| p[0] }
33
+ end
34
+
35
+ def versions
36
+ @versions ||= parts.map{|p| p[1] != "" ? p[1] : nil }
37
+ end
38
+
39
+ def app
40
+ products[0]
41
+ end
42
+
43
+ def comments
44
+ @comments ||= parts.map{|p| p[2] }
45
+ end
46
+
47
+ def app_comments
48
+ @app_comments ||= (comments.first || []) + [""]*5
49
+ end
50
+
51
+ def app_comments_string
52
+ @app_comments_string ||= (comments.first || []).join(";")
53
+ end
54
+
55
+ def comments_string
56
+ @comments_string ||= comments.flatten.join(";")
57
+ end
58
+
59
+ def version_of(product)
60
+ i = products.index(product.to_s)
61
+ versions[i] if i && versions[i] != ""
62
+ end
63
+
64
+ def platform_string
65
+ @platform_string ||= comments.first && comments.first.first
66
+ end
67
+
68
+ def os_string
69
+ @os_string ||= comments.first && comments.first[2]
70
+ end
71
+
72
+ def version
73
+ @version ||= name ? version_of(name) : nil
74
+ end
75
+
76
+ def unknown?
77
+ !name.is_a?(Symbol)
78
+ end
79
+
80
+ def to_s
81
+ return "Unknown: #{raw}" if unknown?
82
+ "#{type} #{name}/#{version} #{os_name}/#{os_version} #{platform}"
83
+ end
84
+ end
85
+
86
+ require 'aua/agents'
87
+ require 'aua/operating_systems'
data/lib/aua/agents.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'aua/stack_base'
2
+
3
+ class Aua
4
+ module Agents
5
+ extend StackBase
6
+ extend self
7
+
8
+ def default
9
+ @default ||= [HttpChecker, ApiClients, FeedReader, Firefox, Chrome::Frame, Chrome, Safari, Opera, Msie, SearchBot, Konqueror, Others, EngineFallback]
10
+ end
11
+ end
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/agents/*.rb"].each do |agent|
15
+ require(agent)
16
+ end
@@ -0,0 +1,42 @@
1
+ module Aua::Agents::ApiClients
2
+ KNOWN_CLIENTS = %w(curl Zendesk Python-urllib Ruby PEAR NativeHost Java AppEngine-Google Twisted)
3
+
4
+ def self.extend?(agent)
5
+ KNOWN_CLIENTS.include?(agent.app) ||
6
+ agent.raw =~ /^Yahoo Pipes ([\d\.]+)$/ ||
7
+ agent.app =~ /^Systemeinstellungen/ ||
8
+ agent.app =~ /^SystemUIServer/
9
+ end
10
+
11
+ def type
12
+ :ApiClient
13
+ end
14
+
15
+ def name
16
+ @name ||= begin
17
+ if raw =~ /^Yahoo Pipes ([\d\.]+)$/
18
+ :YahooPipes
19
+ elsif app == "PEAR"
20
+ :PearPHP
21
+ elsif app == "NativeHost"
22
+ :CappucinosNativeHost
23
+ elsif app =~ /^Systemeinstellungen/
24
+ :SystemPreferences
25
+ elsif app =~ /^SystemUIServer/
26
+ :SystemUIServer
27
+ elsif app == "Twisted"
28
+ :PythonTwistedPageGetter
29
+ else
30
+ app.to_sym
31
+ end
32
+ end
33
+ end
34
+
35
+ def version
36
+ @version ||= begin
37
+ return $1 if raw =~ /^Yahoo Pipes ([\d\.]+)$/
38
+ return comments.first[1] if name == :"AppEngine-Google" && comments.first[1]
39
+ versions.first
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ module Aua::Agents::Chrome
2
+ def self.extend?(agent)
3
+ agent.products.include?("Safari") && agent.products.include?("Chrome")
4
+ end
5
+
6
+ def type
7
+ :Browser
8
+ end
9
+
10
+ def name
11
+ @name ||= begin
12
+ return :Iron if products.include?("Iron")
13
+ return :RockMelt if products.include?("RockMelt")
14
+ :Chrome
15
+ end
16
+ end
17
+
18
+ module Frame
19
+ def self.extend?(agent)
20
+ agent.products.include?("chromeframe")
21
+ end
22
+
23
+ def type
24
+ :Browser
25
+ end
26
+
27
+ def name
28
+ :Chromeframe
29
+ end
30
+
31
+ def version
32
+ @version ||= version_of("chromeframe")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ module Aua::Agents::EngineFallback
2
+ def self.extend?(agent)
3
+ agent.app == "Mozilla" &&
4
+ (agent.products.include?("AppleWebKit") ||
5
+ agent.products.include?("Gecko"))
6
+ end
7
+
8
+ def type
9
+ :Browser
10
+ end
11
+
12
+ def name
13
+ @name ||= begin
14
+ return :AppleWebKit if products.include?("AppleWebKit")
15
+ return :Gecko if products.include?("Gecko")
16
+ nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Aua::Agents::FeedReader
2
+ KNOWN_CLIENTS = %w(AppleSyndication Netvibes Windows-RSS-Platform Vienna NewsGatorOnline NewsFire NetNewsWire MWFeedParser SimplePie MagpieRSS Feedfetcher-Google Apple-PubSub)
3
+
4
+ def self.extend?(agent)
5
+ KNOWN_CLIENTS.include?(agent.app)
6
+ end
7
+
8
+ def type
9
+ :FeedReader
10
+ end
11
+
12
+ def name
13
+ app.to_sym
14
+ end
15
+
16
+ def version
17
+ @version ||= versions.first
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ module Aua::Agents::Firefox
2
+ PATTERN = /^(Firefox|(p|P)rism|SeaMonkey|Camino|Iceweasel|Thunderbird|Epiphany|Namoroka|Flock|Navigator|Netscape)/
3
+
4
+ def self.extend?(agent)
5
+ agent.products.find{|product| product =~ PATTERN}
6
+ end
7
+
8
+ def type
9
+ :Browser
10
+ end
11
+
12
+ def name
13
+ @name ||= begin
14
+ if products.include?("Prism") || products.include?("prism")
15
+ products[products.index("prism")] = "Prism" if products.include?("prism")
16
+ return :Prism
17
+ end
18
+ return :Camino if products.include?("Camino")
19
+ return :SeaMonkey if products.include?("SeaMonkey")
20
+ return :Iceweasel if products.include?("Iceweasel")
21
+ return :Thunderbird if products.include?("Thunderbird")
22
+ return :Epiphany if products.include?("Epiphany")
23
+ return :Flock if products.include?("Flock")
24
+ return :NetscapeNavigator if products.include?("Navigator") || products.include?("Netscape")
25
+ if p = products.find{|product| product =~ /^Firefox-/}
26
+ products[products.index(p)] = "Firefox"
27
+ end
28
+ :Firefox
29
+ end
30
+ end
31
+
32
+ def version
33
+ @version ||= begin
34
+ return version_of("Namoroka") if products.include?("Namoroka")
35
+ return version_of("Netscape") if products.include?("Netscape")
36
+ return version_of("Navigator") if products.include?("Navigator")
37
+ super
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ module Aua::Agents::HttpChecker
2
+ KNOWN_CLIENTS = %w(check_http NewRelicPinger W3C_Validator FeedValidator)
3
+
4
+ def self.extend?(agent)
5
+ agent.app &&
6
+ (KNOWN_CLIENTS.include?(agent.app) ||
7
+ agent.app =~ /Pingdom\.com_bot_version_/)
8
+ end
9
+
10
+ def type
11
+ :HttpChecker
12
+ end
13
+
14
+ def name
15
+ @name ||= begin
16
+ return :PingdomBot if app =~ /Pingdom\.com_bot_version_([\d\.]+)/
17
+ return :Nagios if app == "check_http"
18
+ app.to_sym
19
+ end
20
+ end
21
+
22
+ def version
23
+ @version ||= begin
24
+ return $1 if app =~ /Pingdom\.com_bot_version_([\d\.]+)/
25
+ versions.first
26
+ end
27
+ end
28
+ end