wurfl_client 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ run
2
+ pkg
3
+ rdoc
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