module LogfileAnalyser

class UserAgentStringParser

def parse(user_agent_string)
user_agent_name = nil
user_agent_version = nil

case user_agent_string
# Parse Opera
# e.g. Opera/9.63 (Windows NT 5.1; U; en) Presto/2.1.1
# e.g. Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.10
when /^Opera\/(.+)\..+? \(.*?\)/
user_agent_name = :opera
user_agent_version = $1.to_i
when /^Mozilla\/4\.0 \(compatible; MSIE ([^.]+)\.([^;]+); .+?\) (.*? )*?Opera ((.+)\..+?)/
user_agent_name = :opera
user_agent_version = $4.to_i
# Parse Internet Explorer
# e.g. Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)
when /^Mozilla\/4\.0 \(compatible; +MSIE ([^.]+)\.([^;]+);/
user_agent_name = :msie
user_agent_version = $1.to_i
# Parse Firefox
# e.g. Mozilla/5.0 (Windows; U; Windows NT 6.0; it; rv:1.9.1b2) Gecko/2008092313 Ubuntu/8.04 (hardy) Firefox/3.1.6
# FIXME e.g. Mozilla/5.0 Gecko/20070713 Firefox/2.0.0.0
when /^Mozilla\/.\.. \(.*?; .*?; .*?; .*?; rv:.*?\) Gecko\/\d+ (.*? )*?(Firefox|Shiretoko|Iceweasel|Iceweasel not firefox)\/(.+)\..+/
user_agent_name = :firefox
user_agent_version = $3.to_i
# Parse SeaMonkey
# e.g. Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.19) Gecko/20081204 SeaMonkey/1.1.14
when /^Mozilla\/.\.. \(.*?; .*?; .*?; .*?; rv:.*?\) Gecko\/\d+ (.*? )*SeaMonkey\/(.+)\..+?/
user_agent_name = :seamonkey
user_agent_version = $2.to_i
# Parse Safari
# e.g. Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1
when /^Mozilla\/5\.0 \(.*?; .*?; .*?; .*?\) AppleWebKit\/\S+ \(KHTML, like Gecko\) Version\/(.)\S+ Safari\/\S+/
user_agent_name = :safari
user_agent_version = $1.to_i
# Parse Chrome
# e.g. Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.43 Safari/525.19
when /^Mozilla\/5\.0 \(.*?; .*?; .*?; .*?\) AppleWebKit\/\S+ \(KHTML, like Gecko\) Chrome\/(.)\S+ Safari\/\S+/
user_agent_name = :chrome
user_agent_version = $1.to_i
# Parse Konqueror
# e.g. Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu)
when /^Mozilla\/5\.0 \(compatible; Konqueror\/(.+)\..+?(;|\)) /
user_agent_name = :konqueror
user_agent_version = $1.to_i
# Parse WordPress
when /^WordPress\/(.+)\..+?$/
user_agent_name = :wordpress
user_agent_version = $1.to_i
# Parse mobile Safari
# e.g. Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_2 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5G77 Safari/525.20
when /^Mozilla\/5\.0 \(.*?; .*?; .*?; .*?\) AppleWebKit\/\S+ \(KHTML, like Gecko\) Version\/(.)\S+ Mobile\/\S+ Safari\/\S+/
user_agent_name = :mobile_safari
user_agent_version = $1.to_i
# Parse generic Gecko-based user_agent
# e.g. Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b3pre) Gecko/20090112 Shiretoko/3.1b3pre
when /^Mozilla\/.\.. \(.*?; .*?; .*?; .*?; rv:.*?\) Gecko\/\d+/
user_agent_name = :generic_gecko
user_agent_version = 1
# Parse generic WebKit-based user_agent
# e.g. Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/528.9+ (KHTML, like Gecko) Stainless/0.4.5 Safari/525.20.1
when /^Mozilla\/5\.0 \(.*?; .*?; .*?; .*?\) AppleWebKit\/\S+/
user_agent_name = :generic_webkit
user_agent_version = 1
# Parse bots
# e.g. Mozilla/5.0 (compatible; Yahoo! Slurp/3.0; http://help.yahoo.com/help/us/ysearch/slurp)
# e.g. Googlebot-Image/1.0
# e.g. msnbot-media/1.1 (+http://search.msn.com/msnbot.htm)
when /Mozilla\/5.0 \(compatible; Yahoo! Slurp\// || user_agent_string =~ /^Googlebot-Image\// || user_agent_string =~ /^msnbot-media\//
user_agent_name = :generic_spider
user_agent_version = 1
else
$stderr.puts "Unknown UA: #{user_agent_string}"
end

# Done
{
:user_agent_name => user_agent_name,
:user_agent_version => user_agent_version
}
end

end

end