wurfl_client 0.4.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 +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
|