steveh-browscap 0.3.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 +4 -0
- data/Gemfile +3 -0
- data/LICENSE +280 -0
- data/README.markdown +20 -0
- data/Rakefile +3 -0
- data/browscap.gemspec +25 -0
- data/ini/default.ini +17765 -0
- data/lib/browscap.rb +5 -0
- data/lib/browscap/browser.rb +19 -0
- data/lib/browscap/parser.rb +112 -0
- data/lib/browscap/version.rb +3 -0
- data/spec/browscap_spec.rb +69 -0
- data/spec/spec_helper.rb +1 -0
- metadata +95 -0
data/lib/browscap.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Browscap
|
2
|
+
class Browser
|
3
|
+
|
4
|
+
BOOLEAN_ATTRIBUTES = [:activex_controls, :alpha, :aol, :background_sounds,
|
5
|
+
:beta, :cookies, :crawler, :frames, :iframes, :banned, :mobile_device,
|
6
|
+
:syndication_reader, :java_applets, :javascript, :supports_css, :tables,
|
7
|
+
:vbscript, :win16, :win32, :win64]
|
8
|
+
|
9
|
+
OTHER_ATTRIBUTES = [:aol_version, :browser, :css_version, :major_ver,
|
10
|
+
:minor_ver, :platform, :version]
|
11
|
+
|
12
|
+
attr_accessor *(BOOLEAN_ATTRIBUTES + OTHER_ATTRIBUTES)
|
13
|
+
|
14
|
+
BOOLEAN_ATTRIBUTES.each do |attribute|
|
15
|
+
alias :"#{attribute}?" :"#{attribute}"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "inifile"
|
2
|
+
|
3
|
+
module Browscap
|
4
|
+
class Parser
|
5
|
+
|
6
|
+
def initialize(filename = File.join(File.dirname(__FILE__), '../..', 'ini', 'default.ini'), opts={})
|
7
|
+
@@user_agent_properties ||= {}
|
8
|
+
@@user_agent_regexps ||= {}
|
9
|
+
@@match_cache ||= {}
|
10
|
+
@@encoding = opts[:encoding] || 'ISO-8859-1'
|
11
|
+
|
12
|
+
if @@user_agent_properties.empty? || @@user_agent_regexps.empty?
|
13
|
+
ini = IniFile.load(filename, :encoding => @@encoding)
|
14
|
+
|
15
|
+
# Remote meta sections
|
16
|
+
ini.delete_section '*'
|
17
|
+
ini.delete_section 'GJK_Browscap_Version'
|
18
|
+
|
19
|
+
# Create a list of non-parent sections
|
20
|
+
child_sections = ini.sections.dup
|
21
|
+
ini.sections.each do |section|
|
22
|
+
child_sections.delete ini[section]["Parent"]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Populate user_agent_properties and user_agent_regexps
|
26
|
+
child_sections.each do |section|
|
27
|
+
properties = get_browser_props(ini, section)
|
28
|
+
|
29
|
+
browser = Browser.new
|
30
|
+
browser.browser = properties['Browser']
|
31
|
+
browser.version = properties['Version']
|
32
|
+
browser.major_ver = properties['MajorVer'].to_i
|
33
|
+
browser.minor_ver = properties['MinorVer'].to_i
|
34
|
+
browser.platform = properties['Platform']
|
35
|
+
browser.alpha = properties['Alpha'].downcase == 'true'
|
36
|
+
browser.beta = properties['Beta'].downcase == 'true'
|
37
|
+
browser.win16 = properties['Win16'].downcase == 'true'
|
38
|
+
browser.win32 = properties['Win32'].downcase == 'true'
|
39
|
+
browser.win64 = properties['Win64'].downcase == 'true'
|
40
|
+
browser.frames = properties['Frames'].downcase == 'true'
|
41
|
+
browser.iframes = properties['IFrames'].downcase == 'true'
|
42
|
+
browser.tables = properties['Tables'].downcase == 'true'
|
43
|
+
browser.cookies = properties['Cookies'].downcase == 'true'
|
44
|
+
browser.background_sounds = properties['BackgroundSounds'].downcase == 'true'
|
45
|
+
browser.javascript = properties['JavaScript'].downcase == 'true'
|
46
|
+
browser.vbscript = properties['VBScript'].downcase == 'true'
|
47
|
+
browser.java_applets = properties['JavaApplets'].downcase == 'true'
|
48
|
+
browser.activex_controls = properties['ActiveXControls'].downcase == 'true'
|
49
|
+
browser.banned = properties['isBanned'].downcase == 'true'
|
50
|
+
browser.mobile_device = properties['isMobileDevice'].downcase == 'true'
|
51
|
+
browser.syndication_reader = properties['isSyndicationReader'].downcase == 'true'
|
52
|
+
browser.crawler = properties['Crawler'].downcase == 'true'
|
53
|
+
browser.css_version = properties['CssVersion'].to_i
|
54
|
+
browser.supports_css = properties['supportsCSS'].downcase == 'true'
|
55
|
+
browser.aol_version = properties['aolVersion'].to_i
|
56
|
+
browser.aol = properties['AOL'].downcase == 'true'
|
57
|
+
|
58
|
+
@@user_agent_properties[section] = browser
|
59
|
+
|
60
|
+
# Convert .ini file regexp syntax into ruby regexp syntax
|
61
|
+
regexp = section.dup
|
62
|
+
regexp.gsub! /([\^\$\(\)\[\]\.\-])/, "\\\\\\1"
|
63
|
+
regexp.gsub! "?", "."
|
64
|
+
regexp.gsub! "*", ".*?"
|
65
|
+
|
66
|
+
@@user_agent_regexps[section] = Regexp.new(("^%s$" % regexp).force_encoding(@@encoding))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Looks up the given user agent string and returns a dictionary containing information on this browser or bot.
|
72
|
+
def query(user_agent)
|
73
|
+
section = match(user_agent)
|
74
|
+
@@user_agent_properties[section]
|
75
|
+
end
|
76
|
+
|
77
|
+
alias =~ query
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
def match(user_agent)
|
82
|
+
return @@match_cache[user_agent] if @@match_cache[user_agent]
|
83
|
+
|
84
|
+
matching_section = ''
|
85
|
+
|
86
|
+
@@user_agent_regexps.each do |section, regexp|
|
87
|
+
# Find the longest regexp that matches the given user_agent_string. The length check is needed since multiple reg-exps may match the user_agent_string.
|
88
|
+
if regexp.match(user_agent) && section.length > matching_section.length
|
89
|
+
matching_section = section
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
@@match_cache[user_agent] = matching_section
|
94
|
+
matching_section
|
95
|
+
end
|
96
|
+
|
97
|
+
# Recursively traverses the properties tree (based on 'parent' attribute of each section) and
|
98
|
+
# returns a dictionary of all browser properties for the given section name. The properties lower
|
99
|
+
# in the tree override those higher in the tree.
|
100
|
+
def get_browser_props(ini, section)
|
101
|
+
data = {}
|
102
|
+
|
103
|
+
if parent = ini[section]["Parent"]
|
104
|
+
data.merge! get_browser_props(ini, parent)
|
105
|
+
end
|
106
|
+
|
107
|
+
data.merge! ini[section]
|
108
|
+
data
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Browscap::Parser do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@browscap = Browscap::Parser.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should detect Konqueror 3.5 on Linux" do
|
10
|
+
konq35 = @browscap.query "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; X11; de) KHTML/3.5.2 (like Gecko) Kubuntu 6.06 Dapper"
|
11
|
+
konq35.browser.should == 'Konqueror'
|
12
|
+
konq35.version.should == '3.5'
|
13
|
+
konq35.platform.should == 'Linux'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should detect Firefox 1.5 on Linux" do
|
17
|
+
ff15 = @browscap.query "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.8.0.5) Gecko/20060731 Ubuntu/dapper-security Firefox/1.5.0.5"
|
18
|
+
ff15.browser.should == 'Firefox'
|
19
|
+
ff15.version.should == '1.5'
|
20
|
+
ff15.platform.should == 'Linux'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should detect Mozilla 1.7 on Linux" do
|
24
|
+
moz17 = @browscap.query "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20060216 Debian/1.7.12-1.1ubuntu2"
|
25
|
+
moz17.browser.should == 'Mozilla'
|
26
|
+
moz17.version.should == '1.7'
|
27
|
+
moz17.platform.should == 'Linux'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should detect Firefox 1.5 on Linux (2)" do
|
31
|
+
ff15 = @browscap.query "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.5) Gecko/20060731 Ubuntu/dapper-security Epiphany/2.14 Firefox/1.5.0.5"
|
32
|
+
ff15.browser.should == 'Firefox'
|
33
|
+
ff15.version.should == '1.5'
|
34
|
+
ff15.platform.should == 'Linux'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should detect Opera 9.0 on Linux" do
|
38
|
+
opera90 = @browscap.query "Opera/9.00 (X11; Linux i686; U; en)"
|
39
|
+
opera90.browser.should == 'Opera'
|
40
|
+
opera90.version.should == '9.0'
|
41
|
+
opera90.platform.should == 'Linux'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "shouldn't detect Kazehakase" do
|
45
|
+
@browscap.query("Mozilla/5.0 (X11; Linux i686; U;) Gecko/20051128 Kazehakase/0.3.3 Debian/0.3.3-1").should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should detect MSIE 6.0 on Windows 98" do
|
49
|
+
ie6 = @browscap.query "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)"
|
50
|
+
ie6.browser.should == 'IE'
|
51
|
+
ie6.version.should == '6.0'
|
52
|
+
ie6.platform.should == 'Win98'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should detect Wget as crawler" do
|
56
|
+
wget = @browscap.query "Wget/1.10.2"
|
57
|
+
wget.crawler.should == true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should detect Googlebot as crawler" do
|
61
|
+
google = @browscap.query "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
|
62
|
+
google.crawler.should == true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should detect Yahoo! bot as crawler" do
|
66
|
+
yahoo = @browscap.query "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)"
|
67
|
+
yahoo.crawler.should == true
|
68
|
+
end
|
69
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "browscap"
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: steveh-browscap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.3.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Henning Schroeder
|
9
|
+
- Lukas Fittl
|
10
|
+
- Jason Adams
|
11
|
+
- Gilles Devaux
|
12
|
+
- Steve Hoeksema
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-06-17 00:00:00 +12:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: inifile
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: "0.4"
|
29
|
+
type: :runtime
|
30
|
+
version_requirements: *id001
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: rspec
|
33
|
+
prerelease: false
|
34
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ~>
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: "2.6"
|
40
|
+
type: :development
|
41
|
+
version_requirements: *id002
|
42
|
+
description: A simple library to parse the beloved browscap.ini file (ported to ruby from Henning Schroeder's python code by Lukas Fittl).
|
43
|
+
email:
|
44
|
+
- steve@seven.net.nz
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
extra_rdoc_files: []
|
50
|
+
|
51
|
+
files:
|
52
|
+
- .gitignore
|
53
|
+
- Gemfile
|
54
|
+
- LICENSE
|
55
|
+
- README.markdown
|
56
|
+
- Rakefile
|
57
|
+
- browscap.gemspec
|
58
|
+
- ini/default.ini
|
59
|
+
- lib/browscap.rb
|
60
|
+
- lib/browscap/browser.rb
|
61
|
+
- lib/browscap/parser.rb
|
62
|
+
- lib/browscap/version.rb
|
63
|
+
- spec/browscap_spec.rb
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: https://github.com/steveh/browscap
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: steveh-browscap
|
89
|
+
rubygems_version: 1.5.0
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: A simple library to parse the beloved browscap.ini file
|
93
|
+
test_files:
|
94
|
+
- spec/browscap_spec.rb
|
95
|
+
- spec/spec_helper.rb
|