robworley-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.
@@ -0,0 +1,144 @@
1
+ # Browscap Ruby Gem - A simple library to parse the beloved browscap.ini file.
2
+ # Copyright (C) 2010
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License along
15
+ # with this program; if not, write to the Free Software Foundation, Inc.,
16
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
+ #
18
+ # Original python code by Henning Schroeder
19
+ # Ported to Ruby by Lukas Fittl
20
+ #
21
+
22
+ require 'inifile'
23
+
24
+ class Browscap
25
+ def initialize(filename = File.join(File.dirname(__FILE__), '..', 'ini', 'default.ini'))
26
+ @@user_agent_properties ||= {}
27
+ @@user_agent_regexps ||= {}
28
+ @@match_cache ||= {}
29
+
30
+ if @@user_agent_properties.empty? || @@user_agent_regexps.empty?
31
+ ini = IniFile.load(filename)
32
+
33
+ # Remote meta sections
34
+ ini.delete_section '*'
35
+ ini.delete_section 'GJK_Browscap_Version'
36
+
37
+ # Create a list of non-parent sections
38
+ child_sections = ini.sections.dup
39
+ ini.sections.each do |section|
40
+ child_sections.delete ini[section]["Parent"]
41
+ end
42
+
43
+ # Populate user_agent_properties and user_agent_regexps
44
+ child_sections.each do |section|
45
+ properties = get_browser_props(ini, section)
46
+
47
+ browser = Browser.new
48
+ browser.browser = properties['Browser']
49
+ browser.version = properties['Version']
50
+ browser.major_ver = properties['MajorVer'].to_i
51
+ browser.minor_ver = properties['MinorVer'].to_i
52
+ browser.platform = properties['Platform']
53
+ browser.alpha = properties['Alpha'].downcase == 'true'
54
+ browser.beta = properties['Beta'].downcase == 'true'
55
+ browser.win16 = properties['Win16'].downcase == 'true'
56
+ browser.win32 = properties['Win32'].downcase == 'true'
57
+ browser.win64 = properties['Win64'].downcase == 'true'
58
+ browser.frames = properties['Frames'].downcase == 'true'
59
+ browser.iframes = properties['IFrames'].downcase == 'true'
60
+ browser.tables = properties['Tables'].downcase == 'true'
61
+ browser.cookies = properties['Cookies'].downcase == 'true'
62
+ browser.background_sounds = properties['BackgroundSounds'].downcase == 'true'
63
+ browser.javascript = properties['JavaScript'].downcase == 'true'
64
+ browser.vbscript = properties['VBScript'].downcase == 'true'
65
+ browser.java_applets = properties['JavaApplets'].downcase == 'true'
66
+ browser.activex_controls = properties['ActiveXControls'].downcase == 'true'
67
+ browser.is_banned = properties['isBanned'].downcase == 'true'
68
+ browser.is_mobile_device = properties['isMobileDevice'].downcase == 'true'
69
+ browser.is_syndication_reader = properties['isSyndicationReader'].downcase == 'true'
70
+ browser.crawler = properties['Crawler'].downcase == 'true'
71
+ browser.css_version = properties['CssVersion'].to_i
72
+ browser.aol_version = properties['aolVersion'].to_i
73
+
74
+ @@user_agent_properties[section] = browser
75
+
76
+ # Convert .ini file regexp syntax into ruby regexp syntax
77
+ regexp = section.dup
78
+ regexp.gsub! /([\^\$\(\)\[\]\.\-])/, "\\\\\\1"
79
+ regexp.gsub! "?", "."
80
+ regexp.gsub! "*", ".*?"
81
+
82
+ @@user_agent_regexps[section] = Regexp.new("^%s$" % regexp)
83
+ end
84
+ end
85
+ end
86
+
87
+ # Looks up the given user agent string and returns a dictionary containing information on this browser or bot.
88
+ def query(user_agent)
89
+ section = match(user_agent)
90
+ @@user_agent_properties[section]
91
+ end
92
+ alias =~ query
93
+
94
+ protected
95
+
96
+ def match(user_agent)
97
+ return @@match_cache[user_agent] if @@match_cache[user_agent]
98
+
99
+ matching_section = ''
100
+
101
+ @@user_agent_regexps.each do |section, regexp|
102
+ # 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.
103
+ if regexp.match(user_agent) && section.length > matching_section.length
104
+ matching_section = section
105
+ end
106
+ end
107
+
108
+ @@match_cache[user_agent] = matching_section
109
+ matching_section
110
+ end
111
+
112
+ # Recursively traverses the properties tree (based on 'parent' attribute of each section) and
113
+ # returns a dictionary of all browser properties for the given section name. The properties lower
114
+ # in the tree override those higher in the tree.
115
+ def get_browser_props(ini, section)
116
+ data = {}
117
+
118
+ if parent = ini[section]["Parent"]
119
+ data.merge! get_browser_props(ini, parent)
120
+ end
121
+
122
+ data.merge! ini[section]
123
+ data
124
+ end
125
+ end
126
+
127
+ class Browser
128
+ attr_accessor :activex_controls, :alpha, :aol_version, :background_sounds, :beta,
129
+ :browser, :cookies, :crawler, :css_version, :frames, :iframes, :is_banned, :is_mobile_device,
130
+ :is_syndication_reader, :java_applets, :javascript, :major_ver, :minor_ver, :platform,
131
+ :css_version, :tables, :vbscript, :version, :win16, :win32, :win64
132
+
133
+ [
134
+ :activex_controls, :alpha, :aol_version, :background_sounds, :beta, :cookies, :crawler, :frames,
135
+ :iframes, :is_banned, :is_mobile_device, :is_syndication_reader, :java_applets, :javascript,
136
+ :css_version, :tables, :vbscript, :win16, :win32, :win64
137
+ ].each do |method_name|
138
+ class_eval %{
139
+ def #{method_name}?
140
+ @#{method_name}
141
+ end
142
+ }
143
+ end
144
+ end
@@ -0,0 +1,70 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'browscap'
4
+
5
+ describe Browscap do
6
+ before(:each) do
7
+ @browscap = Browscap.new
8
+ end
9
+
10
+ it "should detect Konqueror 3.5 on Linux" do
11
+ konq35 = @browscap.query "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; X11; de) KHTML/3.5.2 (like Gecko) Kubuntu 6.06 Dapper"
12
+ konq35.browser.should == 'Konqueror'
13
+ konq35.version.should == '3.5'
14
+ konq35.platform.should == 'Linux'
15
+ end
16
+
17
+ it "should detect Firefox 1.5 on Linux" do
18
+ 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"
19
+ ff15.browser.should == 'Firefox'
20
+ ff15.version.should == '1.5'
21
+ ff15.platform.should == 'Linux'
22
+ end
23
+
24
+ it "should detect Mozilla 1.7 on Linux" do
25
+ moz17 = @browscap.query "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20060216 Debian/1.7.12-1.1ubuntu2"
26
+ moz17.browser.should == 'Mozilla'
27
+ moz17.version.should == '1.7'
28
+ moz17.platform.should == 'Linux'
29
+ end
30
+
31
+ it "should detect Firefox 1.5 on Linux (2)" do
32
+ 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"
33
+ ff15.browser.should == 'Firefox'
34
+ ff15.version.should == '1.5'
35
+ ff15.platform.should == 'Linux'
36
+ end
37
+
38
+ it "should detect Opera 9.0 on Linux" do
39
+ opera90 = @browscap.query "Opera/9.00 (X11; Linux i686; U; en)"
40
+ opera90.browser.should == 'Opera'
41
+ opera90.version.should == '9.0'
42
+ opera90.platform.should == 'Linux'
43
+ end
44
+
45
+ it "shouldn't detect Kazehakase" do
46
+ @browscap.query("Mozilla/5.0 (X11; Linux i686; U;) Gecko/20051128 Kazehakase/0.3.3 Debian/0.3.3-1").should be_nil
47
+ end
48
+
49
+ it "should detect MSIE 6.0 on Windows 98" do
50
+ ie6 = @browscap.query "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)"
51
+ ie6.browser.should == 'IE'
52
+ ie6.version.should == '6.0'
53
+ ie6.platform.should == 'Win98'
54
+ end
55
+
56
+ it "should detect Wget as crawler" do
57
+ wget = @browscap.query "Wget/1.10.2"
58
+ wget.crawler.should == true
59
+ end
60
+
61
+ it "should detect Googlebot as crawler" do
62
+ google = @browscap.query "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
63
+ google.crawler.should == true
64
+ end
65
+
66
+ it "should detect Yahoo! bot as crawler" do
67
+ yahoo = @browscap.query "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)"
68
+ yahoo.crawler.should == true
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: robworley-browscap
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
+ platform: ruby
12
+ authors:
13
+ - Henning Schroeder
14
+ - Lukas Fittl
15
+ - Jason Adams
16
+ - Rob Worley
17
+ autorequire:
18
+ bindir: bin
19
+ cert_chain: []
20
+
21
+ date: 2010-07-01 00:00:00 -04:00
22
+ default_executable:
23
+ dependencies:
24
+ - !ruby/object:Gem::Dependency
25
+ name: inifile
26
+ prerelease: false
27
+ requirement: &id001 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ hash: 19
33
+ segments:
34
+ - 0
35
+ - 3
36
+ - 0
37
+ version: 0.3.0
38
+ type: :runtime
39
+ version_requirements: *id001
40
+ description: A simple library to parse the beloved browscap.ini file (ported to ruby from Henning Schroeder's python code by Lukas Fittl).
41
+ email:
42
+ - lukas@fittl.com
43
+ - jasonmadams@gmail.com
44
+ - robert.worley@gmail.com
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ extra_rdoc_files:
50
+ - LICENSE
51
+ - README.markdown
52
+ files:
53
+ - .document
54
+ - .gitignore
55
+ - LICENSE
56
+ - README.markdown
57
+ - Rakefile
58
+ - VERSION
59
+ - browscap.gemspec
60
+ - ini/default.ini
61
+ - lib/browscap.rb
62
+ - spec/browscap_spec.rb
63
+ has_rdoc: true
64
+ homepage: http://github.com/robworley/browscap
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options:
69
+ - --charset=UTF-8
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.5.2
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: A simple library to parse the beloved browscap.ini file
97
+ test_files:
98
+ - spec/browscap_spec.rb