double_agent 0.2.3 → 1.0.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/CHANGELOG +15 -0
- data/README.rdoc +33 -47
- data/data/browsers.yml +39 -35
- data/data/oses.yml +63 -37
- data/lib/double_agent/double_agent.rb +60 -0
- data/lib/double_agent/parser.rb +35 -155
- data/lib/double_agent/{resources.rb → resource.rb} +24 -31
- data/lib/double_agent/user_agent.rb +14 -0
- data/lib/double_agent/version.rb +1 -1
- data/lib/double_agent.rb +7 -1
- metadata +8 -16
- data/lib/double_agent/all.rb +0 -5
- data/lib/double_agent/logs.rb +0 -110
- data/lib/double_agent/stats.rb +0 -65
- data/spec/data/httpd.access.log +0 -20
- data/spec/data/httpd.access.log.1.gz +0 -0
- data/spec/data_spec.rb +0 -105
- data/spec/parser_spec.rb +0 -114
- data/spec/resources_spec.rb +0 -78
- data/spec/spec_helper.rb +0 -19
- data/spec/stats_spec.rb +0 -64
@@ -1,78 +1,71 @@
|
|
1
1
|
module DoubleAgent
|
2
|
-
#
|
3
2
|
# Any class with a "user_agent" method returning a User Agent string
|
4
3
|
# may include this module to easily parse out Browser and OS info.
|
5
|
-
#
|
6
4
|
module Resource
|
7
|
-
# Return's this object's browser name
|
5
|
+
# Return's this object's browser name and version
|
8
6
|
def browser
|
9
|
-
|
7
|
+
browser_parser.browser(user_agent)
|
10
8
|
end
|
11
9
|
|
12
|
-
# Return's this object's browser
|
13
|
-
def
|
14
|
-
|
10
|
+
# Return's this object's browser name
|
11
|
+
def browser_name
|
12
|
+
browser_parser.name
|
13
|
+
end
|
14
|
+
|
15
|
+
# Return's this object's browser version (if any)
|
16
|
+
def browser_version
|
17
|
+
browser_parser.version(user_agent)
|
15
18
|
end
|
16
19
|
|
17
|
-
# Return's this object's browser
|
18
|
-
def
|
19
|
-
|
20
|
+
# Return's this object's browser symbol name
|
21
|
+
def browser_sym
|
22
|
+
browser_parser.sym
|
20
23
|
end
|
21
24
|
|
22
25
|
# Return's this object's browser family name
|
23
26
|
def browser_family
|
24
|
-
|
27
|
+
browser_parser.family.browser
|
25
28
|
end
|
26
29
|
|
27
30
|
# Return's this object's browser family symbol name
|
28
31
|
def browser_family_sym
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
# Return's this object's browser family icon name
|
33
|
-
def browser_family_icon
|
34
|
-
_browser_parser.family.icon
|
32
|
+
browser_parser.family_sym
|
35
33
|
end
|
36
34
|
|
37
35
|
# Return's this object's OS name
|
38
36
|
def os
|
39
|
-
|
37
|
+
os_parser.os
|
40
38
|
end
|
41
39
|
|
42
40
|
# Return's this object's OS symbol name
|
43
41
|
def os_sym
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
# Return's this object's OS icon name
|
48
|
-
def os_icon
|
49
|
-
_os_parser.icon
|
42
|
+
os_parser.sym
|
50
43
|
end
|
51
44
|
|
52
45
|
# Return's this object's OS family name
|
53
46
|
def os_family
|
54
|
-
|
47
|
+
os_parser.family.os
|
55
48
|
end
|
56
49
|
|
57
50
|
# Return's this object's OS family symbol name
|
58
51
|
def os_family_sym
|
59
|
-
|
52
|
+
os_parser.family_sym
|
60
53
|
end
|
61
54
|
|
62
|
-
#
|
63
|
-
def
|
64
|
-
|
55
|
+
# Returs true if the browser appears to be on a mobile device, false if not
|
56
|
+
def mobile?
|
57
|
+
os_parser.mobile?
|
65
58
|
end
|
66
59
|
|
67
60
|
private
|
68
61
|
|
69
62
|
# Returns and caches a BrowserParser for this object
|
70
|
-
def
|
63
|
+
def browser_parser
|
71
64
|
@browser_parser ||= DoubleAgent.browser_parser(user_agent)
|
72
65
|
end
|
73
66
|
|
74
67
|
# Returns and caches an OSParser for this object
|
75
|
-
def
|
68
|
+
def os_parser
|
76
69
|
@os_parser ||= DoubleAgent.os_parser(user_agent)
|
77
70
|
end
|
78
71
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module DoubleAgent
|
2
|
+
# A class representing a browser's user agent string. Various member methods parse and return browser and OS details.
|
3
|
+
class UserAgent
|
4
|
+
include DoubleAgent::Resource
|
5
|
+
|
6
|
+
# The user agent string
|
7
|
+
attr_reader :user_agent
|
8
|
+
|
9
|
+
# Instantiate a new UserAgent object
|
10
|
+
def initialize(user_agent_string)
|
11
|
+
@user_agent = user_agent_string
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/double_agent/version.rb
CHANGED
data/lib/double_agent.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
require 'psych'
|
1
2
|
require 'double_agent/version'
|
2
3
|
require 'double_agent/parser'
|
3
|
-
require 'double_agent/
|
4
|
+
require 'double_agent/resource'
|
5
|
+
require 'double_agent/user_agent'
|
6
|
+
require 'double_agent/double_agent'
|
7
|
+
|
8
|
+
DoubleAgent.load_browsers!
|
9
|
+
DoubleAgent.load_oses!
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: double_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,9 +9,9 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-11-10 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: Browser User Agent string parser
|
14
|
+
description: Browser User Agent string parser
|
15
15
|
email: jordan@jordanhollinger.com
|
16
16
|
executables: []
|
17
17
|
extensions: []
|
@@ -20,25 +20,17 @@ extra_rdoc_files:
|
|
20
20
|
- CHANGELOG
|
21
21
|
files:
|
22
22
|
- lib/double_agent.rb
|
23
|
-
- lib/double_agent/
|
24
|
-
- lib/double_agent/
|
23
|
+
- lib/double_agent/double_agent.rb
|
24
|
+
- lib/double_agent/resource.rb
|
25
|
+
- lib/double_agent/user_agent.rb
|
25
26
|
- lib/double_agent/version.rb
|
26
|
-
- lib/double_agent/logs.rb
|
27
27
|
- lib/double_agent/parser.rb
|
28
|
-
- lib/double_agent/stats.rb
|
29
28
|
- data/browsers.yml
|
30
29
|
- data/oses.yml
|
31
|
-
- spec/resources_spec.rb
|
32
|
-
- spec/data_spec.rb
|
33
|
-
- spec/spec_helper.rb
|
34
|
-
- spec/parser_spec.rb
|
35
|
-
- spec/stats_spec.rb
|
36
|
-
- spec/data/httpd.access.log.1.gz
|
37
|
-
- spec/data/httpd.access.log
|
38
30
|
- README.rdoc
|
39
31
|
- LICENSE
|
40
32
|
- CHANGELOG
|
41
|
-
homepage:
|
33
|
+
homepage: https://github.com/jhollinger/double_agent
|
42
34
|
licenses: []
|
43
35
|
post_install_message:
|
44
36
|
rdoc_options: []
|
@@ -58,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
50
|
version: '0'
|
59
51
|
requirements: []
|
60
52
|
rubyforge_project:
|
61
|
-
rubygems_version: 1.8.
|
53
|
+
rubygems_version: 1.8.23
|
62
54
|
signing_key:
|
63
55
|
specification_version: 3
|
64
56
|
summary: Browser User Agent string parser
|
data/lib/double_agent/all.rb
DELETED
data/lib/double_agent/logs.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'date'
|
2
|
-
|
3
|
-
module DoubleAgent
|
4
|
-
#
|
5
|
-
# The Logs module contains methods and classes for parsing user agent strings
|
6
|
-
# from Apache-style logs (includes default Nginx log format). Gzipped logs
|
7
|
-
# are also supported.
|
8
|
-
#
|
9
|
-
module Logs
|
10
|
-
begin
|
11
|
-
require 'zlib'
|
12
|
-
ZLIB = true
|
13
|
-
rescue LoadError
|
14
|
-
$stderr.puts "Zlib not available for DoubleAgent::Logs; gzipped log files will be skipped."
|
15
|
-
ZLIB = false
|
16
|
-
end
|
17
|
-
|
18
|
-
# This class represents a line in an Apache or Nginx access log.
|
19
|
-
# The user agent string is parsed out and available through the
|
20
|
-
# user_agent attribute, making it available to the mixed-in DoubleAgent::Resource methods.
|
21
|
-
# Datestamps and Timestamps may also be retrieved for each instance, using the #on and #at methods, respectively.
|
22
|
-
|
23
|
-
class Entry
|
24
|
-
include DoubleAgent::Resource
|
25
|
-
# Returns the user agent string
|
26
|
-
attr_reader :user_agent, :line
|
27
|
-
|
28
|
-
# Regular expression for pulling a user agent string out of a log entry. It is rather imprecise
|
29
|
-
# only for efficiency's sake.
|
30
|
-
USER_AGENT_REGEXP = /" ".+$/
|
31
|
-
|
32
|
-
# Regexp for parsing an IP address
|
33
|
-
IP_REGEXP = /^[0-9a-z\.:]+/
|
34
|
-
|
35
|
-
# Regex for parsing the date out of the log line
|
36
|
-
DATESTAMP_REGEXP = %r{[0-9]+/[a-z]+/[0-9]+:}i
|
37
|
-
# Regex for parsing DATESTAMP_REGEXP into a Date object
|
38
|
-
DATESTAMP_FORMAT = '%d/%B/%Y:'
|
39
|
-
|
40
|
-
# Regex for parsing the datetime out of the log line
|
41
|
-
TIMESTAMP_REGEXP = %r{[0-9]+/[a-z]+/[0-9]+:[0-9]+:[0-9]+:[0-9]+ (-|\+)[0-9]+}i
|
42
|
-
# Regex for parsing TIMESTAMP_REGEXP into a DateTime object
|
43
|
-
TIMESTAMP_FORMAT = '%d/%B/%Y:%H:%M:%S %z'
|
44
|
-
|
45
|
-
# Initializes a new Entry object. An Apache or Nginx log line should be
|
46
|
-
# passed to it.
|
47
|
-
def initialize(line)
|
48
|
-
@line = line
|
49
|
-
@user_agent = line.slice(USER_AGENT_REGEXP)
|
50
|
-
end
|
51
|
-
|
52
|
-
# Returns the IP address the hit originated from
|
53
|
-
def ip
|
54
|
-
@line.slice(IP_REGEXP)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Returns the Date the hit occurred on
|
58
|
-
def on
|
59
|
-
date_str = @line.slice(DATESTAMP_REGEXP)
|
60
|
-
date_str ? Date.strptime(date_str, DATESTAMP_FORMAT) : nil
|
61
|
-
end
|
62
|
-
|
63
|
-
# Returns the DateTime the hit occurred at
|
64
|
-
def at
|
65
|
-
datetime_str = @line.slice(TIMESTAMP_REGEXP)
|
66
|
-
datetime_str ? DateTime.strptime(datetime_str, TIMESTAMP_FORMAT) : nil
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Accepts a glob path like /var/logs/apache/my-site.access.log*,
|
71
|
-
# parses all matching files into an array of Entry objects, and returns them.
|
72
|
-
# Gzipped log files are parsed by Zlib.
|
73
|
-
#
|
74
|
-
# Options:
|
75
|
-
#
|
76
|
-
# :match A regular expression. Only lines which match this will be returned.
|
77
|
-
# :ignore A regular expression. Any lines which match this will be ignored.
|
78
|
-
def self.entries(glob_str, options={})
|
79
|
-
match, ignore = options[:match], options[:ignore]
|
80
|
-
entries = []
|
81
|
-
|
82
|
-
# Define the parse lambda
|
83
|
-
parse = if match or ignore
|
84
|
-
lambda { |line|
|
85
|
-
begin
|
86
|
-
entries << Entry.new(line) unless (match and line !~ match) or (ignore and line =~ ignore)
|
87
|
-
rescue ArgumentError => e
|
88
|
-
$stderr.puts "#{e.message}: #{line}"
|
89
|
-
end
|
90
|
-
}
|
91
|
-
else
|
92
|
-
lambda { |line| entries << Entry.new(line) }
|
93
|
-
end
|
94
|
-
|
95
|
-
# Define the read lambda
|
96
|
-
read = lambda do |f|
|
97
|
-
zipped = f =~ /\.gz\Z/i
|
98
|
-
return unless ZLIB or not zipped
|
99
|
-
File.open(f, 'r:UTF-8') do |file|
|
100
|
-
handle = zipped ? Zlib::GzipReader.new(file) : file
|
101
|
-
#handle.each_line &parse # A little slower, but may be more memory efficient
|
102
|
-
handle.readlines.each &parse
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
Dir.glob(glob_str).each &read
|
107
|
-
entries
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
data/lib/double_agent/stats.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
module DoubleAgent
|
2
|
-
#
|
3
|
-
# The Stats module provides methods for determining browser and/or OS share
|
4
|
-
# for large numbers of DoubleAgent::Resource objects.
|
5
|
-
#
|
6
|
-
module Stats
|
7
|
-
# True if running under less than Ruby 1.9
|
8
|
-
BAD_RUBY = RUBY_VERSION < '1.9.0'
|
9
|
-
|
10
|
-
if BAD_RUBY
|
11
|
-
require 'bigdecimal'
|
12
|
-
# If BAD_RUBY, this is used in lieu of the native round method
|
13
|
-
def self.better_round(f, n)
|
14
|
-
d = BigDecimal.new f.to_s
|
15
|
-
d.round(n).to_f
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# For the given "things", returns the share of the group that each attr has.
|
20
|
-
#
|
21
|
-
# "things" is an array of objects who's classes mix-in DoubleAgent::Resource.
|
22
|
-
#
|
23
|
-
# "args" is one or more method symbols from DoubleAgent::Resource.
|
24
|
-
#
|
25
|
-
# "args" may have, as it's last member, :threshold => n, where n is the number of the lowest
|
26
|
-
# percentage you want returned.
|
27
|
-
#
|
28
|
-
# Returns an array of [attribute(s), percent of total, number of total]
|
29
|
-
#
|
30
|
-
# Example, Browser Family share:
|
31
|
-
#
|
32
|
-
# DoubleAgent::Stats.percentages_for(logins, :browser_family)
|
33
|
-
# [['Firefox', 50.4, 5040], ['Chrome', 19.6, 1960], ['Internet Explorer', 15, 1500], ['Safari', 10, 1000], ['Unknown', 5, 500]]
|
34
|
-
#
|
35
|
-
# Example, Browser/OS share, asking for symbols back:
|
36
|
-
#
|
37
|
-
# DoubleAgent::Stats.percentages_for(server_log_entries, :browser_sym, :os_sym)
|
38
|
-
# [[:firefox, :windows_7, 50.4, 5040], [:chrome, :osx, 19.6, 1960], [:msie, :windows_xp, 15, 1500], [:safari, :osx, 10, 1000], [:other, :other, 5, 100]]
|
39
|
-
def self.percentages_for(things, *args)
|
40
|
-
options = args.last.is_a?(Hash) ? args.pop : {} # Break out options
|
41
|
-
results = {}
|
42
|
-
# Count each instance
|
43
|
-
things.each do |h|
|
44
|
-
syms = args.map { |attr| h.send attr }
|
45
|
-
results[syms] ||= 0
|
46
|
-
results[syms] += 1
|
47
|
-
end
|
48
|
-
size = things.size.to_f
|
49
|
-
results = results.to_a
|
50
|
-
# From the total, calculate the percentage held by each browser, OS, etc.
|
51
|
-
if BAD_RUBY
|
52
|
-
results.collect! { |k,n| [*k.<<(better_round(((n * 100) / size), 2)).<<(n)] }
|
53
|
-
else
|
54
|
-
# Ruby 1.9 syntax that blows up in Ruby 1.8
|
55
|
-
#results.collect! { |k,n| [*k, ((n * 100) / size).round(2), n] }
|
56
|
-
results.collect! { |k,n| [*k.<<(((n * 100) / size).round(2)).<<(n)] }
|
57
|
-
end
|
58
|
-
# Sort in ascending order
|
59
|
-
results.sort! { |a,b| b.last <=> a.last }
|
60
|
-
# Reject percentages below a specified threshold
|
61
|
-
results.reject! { |a| a[-2] < options[:threshold] } if options[:threshold]
|
62
|
-
results
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
data/spec/data/httpd.access.log
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
68.52.99.211 - - [05/May/2011:08:21:04 -0400] "GET / HTTP/1.1" 200 1312 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.17) Gecko/20110420 Firefox/3.6.17"
|
2
|
-
68.52.99.211 - - [05/May/2011:08:25:47 -0400] "POST /entries HTTP/1.1" 200 7889 "http://www.example.com/entries/new" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.17) Gecko/20110420 Firefox/3.6.17"
|
3
|
-
216.84.130.30 - - [04/May/2011:09:45:42 -0400] "GET /dashboard HTTP/1.1" 302 104 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_6 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8E200 Safari/6533.18.5"
|
4
|
-
173.190.91.2 - - [04/May/2011:10:51:09 -0400] "GET /images/icons/opera_browser.png?1295928127 HTTP/1.1" 304 0 "http://cur8.cur8.net/sbin/sites/2/page_hit_stats" "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
|
5
|
-
173.190.91.2 - - [04/May/2011:10:51:09 -0400] "GET /images/icons/ubuntu_os.png?1295928127 HTTP/1.1" 304 0 "http://cur8.cur8.net/sbin/sites/2/page_hit_stats" "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
|
6
|
-
173.190.91.2 - - [04/May/2011:10:52:29 -0400] "GET /sbin/sites/2/login_stats HTTP/1.1" 200 10131 "http://cur8.cur8.net/sbin/sites/2/page_hit_stats" "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
|
7
|
-
173.190.91.2 - - [04/May/2011:10:52:34 -0400] "GET /sbin/sites/2/page_hit_stats HTTP/1.1" 200 12460 "http://cur8.cur8.net/sbin/sites/2/login_stats" "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
|
8
|
-
bad log line!
|
9
|
-
173.190.91.2 - - [04/May/2011:10:53:10 -0400] "GET /sbin/sites/2 HTTP/1.1" 304 0 "http://cur8.cur8.net/sbin/sites/2/page_hit_stats" "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
|
10
|
-
216.84.130.30 - - [04/May/2011:11:11:39 -0400] "GET /login HTTP/1.1" 200 1104 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
|
11
|
-
216.84.130.30 - - [04/May/2011:11:11:39 -0400] "GET /stylesheets/styles.css?1303352447 HTTP/1.1" 304 0 "http://www.example.com/login" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
|
12
|
-
216.84.130.30 - - [04/May/2011:11:11:39 -0400] "GET /javascripts/lib.js?1303099416 HTTP/1.1" 304 0 "http://www.example.com/login" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
|
13
|
-
216.84.130.30 - - [04/May/2011:11:11:39 -0400] "GET /stylesheets/print.css?1290464093 HTTP/1.1" 304 0 "http://www.example.com/login" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
|
14
|
-
bad log line!
|
15
|
-
216.84.130.30 - - [04/May/2011:11:11:39 -0400] "GET /javascripts/application.js?1303352447 HTTP/1.1" 304 0 "http://www.example.com/login" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
|
16
|
-
75.201.10.91 - - [04/May/2011:18:37:10 -0400] "GET /entries/new HTTP/1.1" 302 104 "-" "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; ADR6400L 4G Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
|
17
|
-
75.201.10.91 - - [04/May/2011:18:37:10 -0400] "GET /login HTTP/1.1" 200 1107 "-" "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; ADR6400L 4G Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
|
18
|
-
75.201.10.91 - - [04/May/2011:18:43:33 -0400] "GET /dashboard HTTP/1.1" 200 8098 "http://www.example.com/login" "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; ADR6400L 4G Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
|
19
|
-
75.201.10.91 - - [04/May/2011:18:43:55 -0400] "GET /search HTTP/1.1" 200 4070 "http://www.example.com/dashboard" "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; ADR6400L 4G Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
|
20
|
-
bad log line!
|
Binary file
|
data/spec/data_spec.rb
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
-
|
3
|
-
DA = DoubleAgent
|
4
|
-
|
5
|
-
describe DoubleAgent do
|
6
|
-
# Internet Explorer
|
7
|
-
it 'should be Internet Explorer 10 on Windows 8' do
|
8
|
-
ua = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/5.0"
|
9
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Internet Explorer 10 on Windows 8'
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should be Internet Explorer 9 on Windows 7' do
|
13
|
-
ua = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0"
|
14
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Internet Explorer 9 on Windows 7'
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'should be Internet Explorer 8 on Windows Vista' do
|
18
|
-
ua = "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Win64; x64; Trident/5.0"
|
19
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Internet Explorer 8 on Windows Vista'
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should be Internet Explorer 7 on Windows XP' do
|
23
|
-
ua = "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.2; Win64; x64; Trident/5.0"
|
24
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Internet Explorer 7 on Windows XP'
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'should be Internet Explorer 7 on Windows XP' do
|
28
|
-
ua = "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Win64; x64; Trident/5.0"
|
29
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Internet Explorer 7 on Windows XP'
|
30
|
-
end
|
31
|
-
|
32
|
-
# Chrome
|
33
|
-
it 'should be Chrome 12 on Windows XP' do
|
34
|
-
ua = "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.25 (KHTML, like Gecko) Chrome/12.0.706.0 Safari/534.25"
|
35
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Chrome 12 on Windows XP'
|
36
|
-
end
|
37
|
-
|
38
|
-
# Chromium
|
39
|
-
it 'should be Chrome 12 on Ubuntu' do
|
40
|
-
ua = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24"
|
41
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Chrome 12 on Ubuntu'
|
42
|
-
end
|
43
|
-
|
44
|
-
# Android
|
45
|
-
it 'should be Android 2.3 on Android' do
|
46
|
-
ua = "Mozilla/5.0 (Linux; U; Android 2.3.3; zh-tw; HTC_Pyramid Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
|
47
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Android 2.3 on Android'
|
48
|
-
end
|
49
|
-
|
50
|
-
# Safari
|
51
|
-
it 'should be Safari 5 on OS X' do
|
52
|
-
ua = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; zh-cn) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27"
|
53
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Safari 5 on OS X'
|
54
|
-
end
|
55
|
-
|
56
|
-
# Opera
|
57
|
-
it 'should be Opera 11 on GNU/Linux' do
|
58
|
-
ua = "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00"
|
59
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Opera 11 on GNU/Linux'
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'should be Opera 11 on Windows 7' do
|
63
|
-
ua = "Mozilla/5.0 (Windows NT 6.1; U; nl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01"
|
64
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Opera 11 on Windows 7'
|
65
|
-
end
|
66
|
-
|
67
|
-
# Firefox
|
68
|
-
it 'should be Firefox 4 on GNU/Linux' do
|
69
|
-
ua = "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:2.0) Gecko/20110307 Firefox/4.0"
|
70
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Firefox 4 on GNU/Linux'
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'should be Firefox 7 on Android' do
|
74
|
-
ua = "Mozilla/5.0 (Android; Linux armv7l; rv:7.0.1) Gecko/20110928 Firefox/7.0.1 Fennec/7.0.1"
|
75
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Firefox 7 on Android'
|
76
|
-
end
|
77
|
-
|
78
|
-
# Epiphany
|
79
|
-
it 'should be Epiphany on GNU/Linux' do
|
80
|
-
ua = "Mozilla/5.0 (X11; U; Linux x86_64; fr-FR) AppleWebKit/534.7 (KHTML, like Gecko) Epiphany/2.30.6 Safari/534.7"
|
81
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Epiphany on GNU/Linux'
|
82
|
-
end
|
83
|
-
|
84
|
-
# Konqueror
|
85
|
-
it 'should be Konqueror on FreeBSD' do
|
86
|
-
ua = "Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)"
|
87
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Konqueror on FreeBSD'
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'should be Konqueror on Fedora' do
|
91
|
-
ua = "Mozilla/5.0 (compatible; Konqueror/4.4; Linux) KHTML/4.4.1 (like Gecko) Fedora/4.4.1-1.fc12"
|
92
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Konqueror on Fedora'
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'should be Konqueror on Slackware' do
|
96
|
-
ua = "Mozilla/5.0 (compatible; Konqueror/4.2; Linux) KHTML/4.2.4 (like Gecko) Slackware/13.0"
|
97
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'Konqueror on Slackware'
|
98
|
-
end
|
99
|
-
|
100
|
-
# BlackBerry
|
101
|
-
it 'should be BlackBerry on BlackBerry' do
|
102
|
-
ua = "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; zh-TW) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.448 Mobile Safari/534.8+"
|
103
|
-
"#{DA.browser ua} on #{DA.os ua}".should == 'BlackBerry on BlackBerry'
|
104
|
-
end
|
105
|
-
end
|