wurfl_client 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/README +98 -0
- data/Rakefile +32 -0
- data/VERSION +1 -0
- data/bin/prepare_lookup.rb +17 -0
- data/bin/wurfl_minimize.rb +69 -0
- data/lib/wurfl_client/device_profile.rb +31 -0
- data/lib/wurfl_client/lookup_helper.rb +27 -0
- data/lib/wurfl_client/lookup_preparer.rb +54 -0
- data/lib/wurfl_client/ua_device_detector.rb +65 -0
- data/lib/wurfl_client/wurfl_client.rb +30 -0
- data/test/device_profile_test.rb +30 -0
- data/test/lookup_helper_test.rb +28 -0
- data/test/ua_device_detector_test.rb +38 -0
- data/test/wurfl_client_test.rb +16 -0
- data/wurfl_client.gemspec +59 -0
- metadata +95 -0
data/.gitignore
ADDED
data/README
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
= WURFL Client
|
2
|
+
|
3
|
+
WURFL Client is a library to do WURFL (http://wurfl.sourceforge.net/) mobile device detection for web applications.
|
4
|
+
Included are tools to keep the WURFL file up to date automatically and to prepare a customized lookup tables, which
|
5
|
+
allow a fast device detection.
|
6
|
+
|
7
|
+
== Mode of Operation
|
8
|
+
The complete WURFL file is as big as ~16MB. A single device detection against it in Ruby took me 12 seconds, which is
|
9
|
+
inaceptable even for the first request of any client.
|
10
|
+
|
11
|
+
There are three optimizations to make the detection work faster:
|
12
|
+
1.) The WURFL file is customized to remove unused capabilities, reducing it's size considerably.
|
13
|
+
2.) Client devices are roughly detected by type (e.g. iPhone like, Nokia devices, etc.)
|
14
|
+
3.) The WURFL Client works with previously prepared lookup tables for the roughly detected device types
|
15
|
+
in a Ruby PStore data structure, so Ruby doesn't have to parse XML files on each request.
|
16
|
+
|
17
|
+
The lookup tables are prepared during the WURFL update task, which takes quite some time. But this allows for a
|
18
|
+
very fast and for our appliances also accurate recognition.
|
19
|
+
|
20
|
+
The WURFL Client can then be implemented f.i. as a thin Rack service, see Examples.
|
21
|
+
|
22
|
+
|
23
|
+
== Requirements
|
24
|
+
|
25
|
+
Ruby 1.9: (.ord!) -> http://gist.github.com/251465
|
26
|
+
wurfl gem (http://github.com/pwim/wurfl): Handset, UserAgentMatcher, WURFL Loader
|
27
|
+
|
28
|
+
== Installation
|
29
|
+
|
30
|
+
sudo gem install wurfl_client
|
31
|
+
|
32
|
+
== Setup
|
33
|
+
|
34
|
+
To setup the environment, you have to execute following steps:
|
35
|
+
1.) download and extract the latest WURFL file
|
36
|
+
* curl -L -o wurfl-latest.xml.gz
|
37
|
+
* gunzip wurfl-latest.xml.gz
|
38
|
+
|
39
|
+
2.) minimize the WURFL XML file. You can adapt wurfl_minimize.yml to your needs, see http://wurfl.sourceforge.net/help_doc.php for a list of available capabilities)
|
40
|
+
* wurfl_minimize.rb
|
41
|
+
|
42
|
+
3.) prepare the lookup tables (builds them into ./lookup directory by default). This will take some time!
|
43
|
+
* lookup_prepare.rb
|
44
|
+
|
45
|
+
Now, you are ready for device detection. If you make an automated script to do this update regularly, you must not forget to clear the lookup directory first.
|
46
|
+
The preparation script doesn't overwrite files. For minimal effect on your running webservice, you should use another lookup directory there and copy the
|
47
|
+
new data after the update is complete.
|
48
|
+
|
49
|
+
Here is an example automatic update script:
|
50
|
+
* #!/bin/sh
|
51
|
+
* curl -L -o wurfl-latest.xml.gz
|
52
|
+
* gunzip wurfl-latest.xml.gz
|
53
|
+
* wurfl_minimize.rb
|
54
|
+
* rm lookup/*
|
55
|
+
* lookup_prepare.rb
|
56
|
+
* cp lookup/* /path/to/production/lookup
|
57
|
+
|
58
|
+
== Examples
|
59
|
+
|
60
|
+
TODO: simple detection example
|
61
|
+
TODO: rack application
|
62
|
+
|
63
|
+
== Authors
|
64
|
+
|
65
|
+
* Guido Pinkas (Original Author)
|
66
|
+
|
67
|
+
== Thanks
|
68
|
+
|
69
|
+
Thanks to S. Kamerman from TERA-WURFL (http://www.tera-wurfl.com/) for his WURFL Customizer (http://www.tera-wurfl.com/wiki/index.php/WURFL_Customizer).
|
70
|
+
I only had to port the functionality to ruby.
|
71
|
+
|
72
|
+
== Contribution
|
73
|
+
|
74
|
+
Contribution is welcome. Please use the github tools (fork, pull request, etc) here on http://github.com/bluecat76/wurfl_client.
|
75
|
+
|
76
|
+
== License
|
77
|
+
|
78
|
+
The MIT License
|
79
|
+
|
80
|
+
Copyright (c) 2010 Binder Trittenwein Kommunikation GmbH (http://www.bindertrittenwein.com/)
|
81
|
+
|
82
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
83
|
+
of this software and associated documentation files (the "Software"), to deal
|
84
|
+
in the Software without restriction, including without limitation the rights
|
85
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
86
|
+
copies of the Software, and to permit persons to whom the Software is
|
87
|
+
furnished to do so, subject to the following conditions:
|
88
|
+
|
89
|
+
The above copyright notice and this permission notice shall be included in
|
90
|
+
all copies or substantial portions of the Software.
|
91
|
+
|
92
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
93
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
94
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
95
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
96
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
97
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
98
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rake/rdoctask'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'shoulda/tasks'
|
4
|
+
|
5
|
+
task :default => ['test']
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test) do |t|
|
8
|
+
t.test_files = FileList['test/*_test.rb']
|
9
|
+
end
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gemspec|
|
14
|
+
gemspec.name = "wurfl_client"
|
15
|
+
gemspec.summary = "Fast WURFL mobile device detection"
|
16
|
+
gemspec.description = "WURFL Client is a library to do WURFL (http://wurfl.sourceforge.net/) mobile device detection for web applications. Included are tools to keep the WURFL file up to date automatically and to prepare a customized lookup tables, which allow a fast device detection."
|
17
|
+
gemspec.email = "guido.pinkas@bindertrittenwein.com"
|
18
|
+
gemspec.homepage = "http://github.com/bluecat76/wurfl_client"
|
19
|
+
gemspec.authors = ["Guido Pinkas"]
|
20
|
+
gemspec.add_dependency 'wurfl'
|
21
|
+
end
|
22
|
+
Jeweler::GemcutterTasks.new
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
25
|
+
end
|
26
|
+
|
27
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
28
|
+
rdoc.rdoc_dir = 'rdoc'
|
29
|
+
rdoc.title = 'WURFL Client'
|
30
|
+
rdoc.main = "README"
|
31
|
+
rdoc.rdoc_files.include("README", "lib/**/*.rb")
|
32
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.0
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# use this program to generate lookup tables from the input WURFL XML file
|
4
|
+
|
5
|
+
require "wurfl_client/lookup_preparer"
|
6
|
+
require "yaml"
|
7
|
+
|
8
|
+
def load_configuration(file_path)
|
9
|
+
begin
|
10
|
+
config = YAML::load_file(file_path)
|
11
|
+
rescue
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
preparer = WurflClient::LookupPreparer.new load_configuration('prepare_lookup.yml')
|
17
|
+
preparer.prepareLookupTables
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "xml"
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
# use this program to minimize the WURFL XML file, so it contains only capabilities you need.
|
6
|
+
# This can reduce the lookup store size considerably!
|
7
|
+
|
8
|
+
default_config = {
|
9
|
+
'input_file' => 'wurfl-test.xml',
|
10
|
+
'output_file' => 'wurfl-default.xml',
|
11
|
+
'capabilities' => ['brand_name', 'model_name', 'max_image_width', 'max_image_height', 'wta_voice_call']
|
12
|
+
}
|
13
|
+
|
14
|
+
def load_configuration(file_path)
|
15
|
+
begin
|
16
|
+
config = YAML::load_file(file_path)
|
17
|
+
rescue
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def minimize_wurfl(configuration)
|
23
|
+
# open input file
|
24
|
+
doc = XML::Document.file(configuration['input_file'])
|
25
|
+
|
26
|
+
# prepare output file
|
27
|
+
out = XML::Document.new()
|
28
|
+
out.root = XML::Node.new('wurfl')
|
29
|
+
out.root << XML::Node.new('devices')
|
30
|
+
devices_node = out.root.first
|
31
|
+
|
32
|
+
# go through devices list
|
33
|
+
doc.find("///devices/device").each do |element|
|
34
|
+
wurfl_id = element.attributes["id"]
|
35
|
+
user_agent = element.attributes["user_agent"]
|
36
|
+
|
37
|
+
# copy node to output
|
38
|
+
new_node = XML::Node.new('device')
|
39
|
+
element.each_attr do |attr|
|
40
|
+
new_node.attributes[attr.name] = attr.value
|
41
|
+
end
|
42
|
+
|
43
|
+
element.each do |group|
|
44
|
+
new_group = XML::Node.new('group')
|
45
|
+
# check capabilities
|
46
|
+
group.each do |cap|
|
47
|
+
if configuration['capabilities'].include? cap.attributes["name"]
|
48
|
+
# add capability
|
49
|
+
new_cap = XML::Node.new('capability')
|
50
|
+
cap.each_attr { |cap_attr| new_cap.attributes[cap_attr.name] = cap_attr.value }
|
51
|
+
new_group << new_cap
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# copy group if not empty
|
55
|
+
if new_group.children?
|
56
|
+
new_node << new_group
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# add node to output document
|
61
|
+
devices_node << new_node
|
62
|
+
end
|
63
|
+
|
64
|
+
# save ouput file
|
65
|
+
out.save(configuration['output_file'], :indent => true, :encoding => XML::Encoding::UTF_8)
|
66
|
+
end
|
67
|
+
|
68
|
+
config = load_configuration('wurfl_minimize.yml') || default_config
|
69
|
+
minimize_wurfl(config)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module WurflClient
|
2
|
+
|
3
|
+
# DeviceProfile stores "device context" information (desktop or mobile)
|
4
|
+
# and the "lookup prefix" used to find the correct lookup file
|
5
|
+
class DeviceProfile
|
6
|
+
attr_reader :context
|
7
|
+
attr_reader :lookup_prefix
|
8
|
+
|
9
|
+
def initialize(context, lookup_prefix)
|
10
|
+
@context = context # like "desktop, mobile, iphone, etc"
|
11
|
+
@lookup_prefix = lookup_prefix
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.mobile(lookup_prefix)
|
15
|
+
DeviceProfile.new(:mobile, lookup_prefix)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.desktop
|
19
|
+
DeviceProfile.new(:desktop, nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def mobile?
|
23
|
+
@context != :desktop
|
24
|
+
end
|
25
|
+
|
26
|
+
def desktop?
|
27
|
+
@context == :desktop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "wurfl_client/device_profile"
|
2
|
+
require "wurfl/handset"
|
3
|
+
require "pstore"
|
4
|
+
|
5
|
+
module WurflClient
|
6
|
+
|
7
|
+
# This class is used to generate paths to the lookup files
|
8
|
+
class LookupHelper
|
9
|
+
def self.encodeFilename(str)
|
10
|
+
str.gsub(/[^a-zA-Z0-9_\.\-]/n) {|s| sprintf('%%%02x', s[0].ord) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(lookup_base_path)
|
14
|
+
@lookup_base_path = lookup_base_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def getStoreFilePath(lookup_prefix)
|
18
|
+
File.join(@lookup_base_path, LookupHelper.encodeFilename(lookup_prefix) + '.pstore')
|
19
|
+
end
|
20
|
+
|
21
|
+
def loadLookupTable(profile)
|
22
|
+
store_filename = getStoreFilePath(profile.lookup_prefix)
|
23
|
+
PStore.new(store_filename).transaction {|ps| ps["handsets"]}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "wurfl/loader"
|
2
|
+
require "wurfl_client/lookup_helper.rb"
|
3
|
+
require "wurfl_client/ua_device_detector.rb"
|
4
|
+
require "pstore"
|
5
|
+
|
6
|
+
module WurflClient
|
7
|
+
|
8
|
+
# This class is used to prepare lookup tables for fast device recognition.
|
9
|
+
# The information is collected from the given WURFL XML file
|
10
|
+
class LookupPreparer
|
11
|
+
|
12
|
+
def initialize(set_config)
|
13
|
+
config = set_config || {}
|
14
|
+
@wurfl_path = config['wurfl_path'] || 'wurfl-custom.xml'
|
15
|
+
@lookup_base_path = config['lookup_base_path'] || 'lookup/'
|
16
|
+
|
17
|
+
@helper = LookupHelper.new(@lookup_base_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def prepareLookupTables
|
21
|
+
@handsets = Wurfl::Loader.new.load_wurfl(@wurfl_path)
|
22
|
+
@handsets.each do |wurfl_id, handset|
|
23
|
+
target = UserAgentDeviceDetector.detect(handset.user_agent)
|
24
|
+
if target.lookup_prefix && !(target.lookup_prefix =~ /DO_NOT_MATCH/)
|
25
|
+
saveLookupTable target
|
26
|
+
else
|
27
|
+
puts "IGNORING UA: #{handset.user_agent}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def saveLookupTable(profile)
|
35
|
+
store_filename = @helper.getStoreFilePath(profile.lookup_prefix)
|
36
|
+
return if File.exists?(store_filename)
|
37
|
+
|
38
|
+
puts "building store: #{store_filename}"
|
39
|
+
|
40
|
+
# load similar user agent strings
|
41
|
+
lookup_table = {}
|
42
|
+
@handsets.each do |wurfl_id, handset|
|
43
|
+
target = UserAgentDeviceDetector.detect(handset.user_agent)
|
44
|
+
if target.lookup_prefix==profile.lookup_prefix
|
45
|
+
lookup_table[wurfl_id] ||= handset
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# save as pstore
|
50
|
+
PStore.new(store_filename).transaction {|ps| ps["handsets"] = lookup_table}
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "wurfl_client/device_profile"
|
2
|
+
|
3
|
+
module WurflClient
|
4
|
+
|
5
|
+
# This class is used to determine a rough device profile from the given UserAgent string
|
6
|
+
class UserAgentDeviceDetector
|
7
|
+
|
8
|
+
def self.detect(ua_string)
|
9
|
+
detectIphone(ua_string) || detectOtherMozilla(ua_string) || detectGeneric(ua_string) || DeviceProfile.new(:desktop)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def self.detectIphone(ua_string)
|
15
|
+
case ua_string
|
16
|
+
when /iPod/
|
17
|
+
return DeviceProfile.new('iphone', 'iphone_ipod')
|
18
|
+
when /iPhone/
|
19
|
+
os_ver = ua_string[/OS ([0-9_]+)/]
|
20
|
+
prefix = 'iphone'
|
21
|
+
prefix += "_#{os_ver[$1]}" if os_ver
|
22
|
+
return DeviceProfile.new('iphone', prefix)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.detectOtherMozilla(ua_string)
|
27
|
+
if ua_string =~ /^Mozilla/
|
28
|
+
case ua_string
|
29
|
+
when /Nokia/
|
30
|
+
os_ver = ua_string[/Nokia([a-zA-Z0-9\-\.]+)/]
|
31
|
+
prefix = 'mozilla_nokia'
|
32
|
+
prefix += "_#{os_ver[$1]}" if os_ver
|
33
|
+
return DeviceProfile.mobile(prefix)
|
34
|
+
when /Windows CE/
|
35
|
+
os_ver = ua_string[/Windows CE; ([a-zA-Z0-9 \.]+)/]
|
36
|
+
prefix = 'mozilla_wince'
|
37
|
+
prefix += "_#{os_ver[$1]}" if os_ver
|
38
|
+
return DeviceProfile.mobile(prefix)
|
39
|
+
when /Symbian ?OS/
|
40
|
+
return DeviceProfile.mobile('mozilla_symbian')
|
41
|
+
when /PalmOS/
|
42
|
+
return DeviceProfile.mobile('mozilla_palm')
|
43
|
+
when /Motorola/
|
44
|
+
return DeviceProfile.mobile('mozilla_motorola')
|
45
|
+
when /MIDP-[0-9\.]/
|
46
|
+
prefix = 'mozilla_' + ua_string[/MIDP-[0-9\.]+/]
|
47
|
+
return DeviceProfile.mobile(prefix)
|
48
|
+
when /phone/i
|
49
|
+
return DeviceProfile.mobile('mozilla_phone')
|
50
|
+
when /mobile/i
|
51
|
+
return DeviceProfile.mobile('mozilla_mobile')
|
52
|
+
else # other mozilla is considered desktop
|
53
|
+
return DeviceProfile.desktop
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.detectGeneric(ua_string)
|
59
|
+
# TODO: detect desktop vs. mobile here!
|
60
|
+
return DeviceProfile.mobile(ua_string[/^[0-9a-zA-z_\.\-]+/])
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "wurfl_client/ua_device_detector"
|
2
|
+
require "wurfl_client/lookup_helper"
|
3
|
+
require "wurfl/user_agent_matcher"
|
4
|
+
|
5
|
+
module WurflClient
|
6
|
+
@@lookup_base_path = 'lookup/'
|
7
|
+
|
8
|
+
# change the path to the previously generated lookup files
|
9
|
+
def self.setLookupBasePath(lookup_base_path)
|
10
|
+
@@lookup_base_path = lookup_base_path
|
11
|
+
end
|
12
|
+
|
13
|
+
# main function to detect devices
|
14
|
+
def self.detectMobileDevice(user_agent)
|
15
|
+
profile = UserAgentDeviceDetector.detect(user_agent)
|
16
|
+
if profile.mobile?
|
17
|
+
# load prepared handset list
|
18
|
+
lookup = LookupHelper.new(@@lookup_base_path)
|
19
|
+
handsets = lookup.loadLookupTable(profile)
|
20
|
+
|
21
|
+
if handsets
|
22
|
+
# TODO: load complete table as fallback!
|
23
|
+
uam = Wurfl::UserAgentMatcher.new(handsets)
|
24
|
+
|
25
|
+
# return first matching entry
|
26
|
+
uam.match_handsets(user_agent).flatten.first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'test/unit'
|
3
|
+
require 'wurfl_client/device_profile'
|
4
|
+
|
5
|
+
class DeviceProfileTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@mobile_prefix = 'test_mobile'
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_create_mobile
|
11
|
+
dp = WurflClient::DeviceProfile.mobile(@mobile_prefix)
|
12
|
+
assert_equal dp.mobile?, true
|
13
|
+
assert_equal dp.desktop?, false
|
14
|
+
assert_equal dp.lookup_prefix, @mobile_prefix
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_create_desktop
|
18
|
+
dp = WurflClient::DeviceProfile.desktop
|
19
|
+
assert_equal dp.desktop?, true
|
20
|
+
assert_equal dp.mobile?, false
|
21
|
+
assert_equal dp.lookup_prefix, nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_initialite
|
25
|
+
dp = WurflClient::DeviceProfile.new(:mobile, @mobile_prefix)
|
26
|
+
assert_equal dp.mobile?, true
|
27
|
+
assert_equal dp.desktop?, false
|
28
|
+
assert_equal dp.lookup_prefix, @mobile_prefix
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'test/unit'
|
3
|
+
require 'wurfl_client/lookup_helper'
|
4
|
+
|
5
|
+
class LookupHelperTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_encode_filename
|
10
|
+
s = WurflClient::LookupHelper.encodeFilename("br#l'@*ig$^/?!--and+zurg")
|
11
|
+
assert_match /[a-z0-9\_\-\.]+/i, s
|
12
|
+
s = WurflClient::LookupHelper.encodeFilename("simpletest09-10.20")
|
13
|
+
assert_equal "simpletest09-10.20", s
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_get_path
|
17
|
+
lh = WurflClient::LookupHelper.new("path/")
|
18
|
+
assert_match /^path\/.*test.*$/, lh.getStoreFilePath("test")
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_load_table
|
22
|
+
lh = WurflClient::LookupHelper.new(File.join(File.dirname(__FILE__), 'data'))
|
23
|
+
p = WurflClient::DeviceProfile.mobile("iphone")
|
24
|
+
handsets = lh.loadLookupTable(p)
|
25
|
+
assert_instance_of Hash, handsets
|
26
|
+
assert_instance_of Wurfl::Handset, handsets.first[1]
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'test/unit'
|
3
|
+
require 'wurfl_client/ua_device_detector'
|
4
|
+
|
5
|
+
class UserAgentDeviceDetectorTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_functionality
|
10
|
+
dp = WurflClient::UserAgentDeviceDetector.detect ""
|
11
|
+
assert_instance_of WurflClient::DeviceProfile, dp
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_desktop
|
15
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10"
|
16
|
+
assert_equal true, dp.desktop?
|
17
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
|
18
|
+
assert_equal true, dp.desktop?
|
19
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5"
|
20
|
+
assert_equal true, dp.desktop?
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_mobile
|
24
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "SAMSUNG-GT-S5230/S5230MMIG2 SHP/VPP/R5 Jasmine/0.8 Nextreaming SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1"
|
25
|
+
assert_equal true, dp.mobile?
|
26
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "BlackBerry8320/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/100"
|
27
|
+
assert_equal true, dp.mobile?
|
28
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16"
|
29
|
+
assert_equal true, dp.mobile?
|
30
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "Mozilla/5.0 (Linux; U; Android 1.6; de-at; T-Mobile G1 Build/DRC92) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1"
|
31
|
+
assert_equal true, dp.mobile?
|
32
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "SonyEricssonK550i/R1JD Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1"
|
33
|
+
assert_equal true, dp.mobile?
|
34
|
+
dp = WurflClient::UserAgentDeviceDetector.detect "Nokia6230i/2.0 (03.80) Profile/MIDP-2.0 Configuration/CLDC-1.1"
|
35
|
+
assert_equal true, dp.mobile?
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'test/unit'
|
3
|
+
require 'wurfl_client/wurfl_client'
|
4
|
+
|
5
|
+
class WurflClientTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_functionality
|
10
|
+
user_agent = 'Mozilla/5.0 (iPhone; U; CPU iPhone like Mac OS X; en-us)'
|
11
|
+
WurflClient::setLookupBasePath(File.join(File.dirname(__FILE__), 'data'))
|
12
|
+
device = WurflClient::detectMobileDevice(user_agent)
|
13
|
+
assert_instance_of Wurfl::Handset, device
|
14
|
+
assert_equal 'iPhone', device['model_name']
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{wurfl_client}
|
8
|
+
s.version = "0.4.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Guido Pinkas"]
|
12
|
+
s.date = %q{2010-09-27}
|
13
|
+
s.description = %q{WURFL Client is a library to do WURFL (http://wurfl.sourceforge.net/) mobile device detection for web applications. Included are tools to keep the WURFL file up to date automatically and to prepare a customized lookup tables, which allow a fast device detection.}
|
14
|
+
s.email = %q{guido.pinkas@bindertrittenwein.com}
|
15
|
+
s.executables = ["prepare_lookup.rb", "wurfl_minimize.rb"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"README"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"README",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"bin/prepare_lookup.rb",
|
25
|
+
"bin/wurfl_minimize.rb",
|
26
|
+
"lib/wurfl_client/device_profile.rb",
|
27
|
+
"lib/wurfl_client/lookup_helper.rb",
|
28
|
+
"lib/wurfl_client/lookup_preparer.rb",
|
29
|
+
"lib/wurfl_client/ua_device_detector.rb",
|
30
|
+
"lib/wurfl_client/wurfl_client.rb",
|
31
|
+
"test/device_profile_test.rb",
|
32
|
+
"wurfl_client.gemspec"
|
33
|
+
]
|
34
|
+
s.homepage = %q{http://github.com/bluecat76/wurfl_client}
|
35
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = %q{1.3.7}
|
38
|
+
s.summary = %q{Fast WURFL mobile device detection}
|
39
|
+
s.test_files = [
|
40
|
+
"test/lookup_helper_test.rb",
|
41
|
+
"test/device_profile_test.rb",
|
42
|
+
"test/wurfl_client_test.rb",
|
43
|
+
"test/ua_device_detector_test.rb"
|
44
|
+
]
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_runtime_dependency(%q<wurfl>, [">= 0"])
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<wurfl>, [">= 0"])
|
54
|
+
end
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<wurfl>, [">= 0"])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wurfl_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
version: 0.4.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Guido Pinkas
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-09-27 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: wurfl
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
description: WURFL Client is a library to do WURFL (http://wurfl.sourceforge.net/) mobile device detection for web applications. Included are tools to keep the WURFL file up to date automatically and to prepare a customized lookup tables, which allow a fast device detection.
|
34
|
+
email: guido.pinkas@bindertrittenwein.com
|
35
|
+
executables:
|
36
|
+
- prepare_lookup.rb
|
37
|
+
- wurfl_minimize.rb
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files:
|
41
|
+
- README
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- README
|
45
|
+
- Rakefile
|
46
|
+
- VERSION
|
47
|
+
- bin/prepare_lookup.rb
|
48
|
+
- bin/wurfl_minimize.rb
|
49
|
+
- lib/wurfl_client/device_profile.rb
|
50
|
+
- lib/wurfl_client/lookup_helper.rb
|
51
|
+
- lib/wurfl_client/lookup_preparer.rb
|
52
|
+
- lib/wurfl_client/ua_device_detector.rb
|
53
|
+
- lib/wurfl_client/wurfl_client.rb
|
54
|
+
- test/device_profile_test.rb
|
55
|
+
- wurfl_client.gemspec
|
56
|
+
- test/lookup_helper_test.rb
|
57
|
+
- test/wurfl_client_test.rb
|
58
|
+
- test/ua_device_detector_test.rb
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://github.com/bluecat76/wurfl_client
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --charset=UTF-8
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.3.7
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Fast WURFL mobile device detection
|
91
|
+
test_files:
|
92
|
+
- test/lookup_helper_test.rb
|
93
|
+
- test/device_profile_test.rb
|
94
|
+
- test/wurfl_client_test.rb
|
95
|
+
- test/ua_device_detector_test.rb
|