wurfl 1.0.2 → 1.1.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 +1 -0
- data/README.rdoc +31 -22
- data/VERSION +1 -1
- data/bin/wurfltools.rb +21 -0
- data/lib/wurfl/command.rb +4 -0
- data/lib/wurfl/command/comparator.rb +86 -0
- data/lib/wurfl/command/inspector.rb +142 -0
- data/lib/wurfl/command/loader.rb +129 -0
- data/lib/wurfl/command/sanitycheck.rb +40 -0
- data/lib/wurfl/command/uaproftowurfl.rb +28 -0
- data/lib/wurfl/command/uaprofwurflcomparator.rb +224 -0
- data/wurfl.gemspec +12 -9
- metadata +12 -15
- data/bin/uaproftowurfl.rb +0 -28
- data/bin/uaprofwurflcomparator.rb +0 -223
- data/bin/wurflcomparator.rb +0 -86
- data/bin/wurflinspector.rb +0 -141
- data/bin/wurflloader.rb +0 -127
- data/bin/wurflsanitycheck.rb +0 -39
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -6,14 +6,16 @@ WURFL is a collection of libraries and command line tools for using and manipula
|
|
6
6
|
|
7
7
|
== Tools
|
8
8
|
|
9
|
-
|
9
|
+
All tools are run via wurfltools.rb
|
10
|
+
|
11
|
+
=== loader
|
10
12
|
|
11
13
|
Is used to parse and load a WURFL XML file into memory or save a
|
12
14
|
PStore database that is used by most of the other tools. This
|
13
15
|
application creates WURFL PStore databases that are essential for use
|
14
16
|
with the other Ruby applications.
|
15
17
|
|
16
|
-
===
|
18
|
+
=== inspector
|
17
19
|
|
18
20
|
Is a tool that will let you do various searches and queries on the
|
19
21
|
WURFL. This is a very simple, yet powerful program for finding
|
@@ -24,12 +26,15 @@ examples section for usage.
|
|
24
26
|
|
25
27
|
The command below will search through all handsets and return the ids
|
26
28
|
of handsets that match the passed Ruby boolean evaluation
|
27
|
-
|
28
|
-
|
29
|
+
|
30
|
+
This command will return all handsets that have more than 2 colors.
|
31
|
+
|
32
|
+
wurfltools.rb inspector -d pstorehandsets.db -s '{ |hand| hand["colors"].to_i > 2 }'"
|
33
|
+
|
29
34
|
The Ruby query must go in between the single quote marks and needs to
|
30
35
|
declare the WurflHandset instance variable name.
|
31
36
|
|
32
|
-
|
37
|
+
This command shows you how you can cheat with the current design of
|
33
38
|
the wurflinspector and print more user friendly results. This example
|
34
39
|
assumes you have the command line programs sort and uniq, but that is
|
35
40
|
only to make the output look better. This example does the same as the
|
@@ -37,24 +42,27 @@ above, except that it prints out the brand name and model name of the
|
|
37
42
|
matching handsets instead of the WURFL id.
|
38
43
|
|
39
44
|
Note: this should all go into one command line call
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
|
46
|
+
wurfltools.rb inspector -d pstorehandsets.db -s '{|hand| puts
|
47
|
+
"#{hand["brand_name"]} #{hand["model_name"]}" if hand["colors"].to_i >
|
48
|
+
2}' | sort | uniq"
|
43
49
|
|
44
50
|
|
45
51
|
The following individual handset query commands will tell the value of
|
46
52
|
capabilities and from where it obtained the setting.
|
47
53
|
|
48
|
-
|
54
|
+
A command to query the handset with the id sonyericsson_t300_ver1
|
49
55
|
for all of its' capabilities:
|
50
|
-
"wurflinspector.rb -d pstorehandsets.db -i sonyericsson_t300_ver1"
|
51
56
|
|
52
|
-
|
57
|
+
wurfltools.rb inspector -d pstorehandsets.db -i sonyericsson_t300_ver1
|
58
|
+
|
59
|
+
A command to query the handset with the id sonyericsson_t300_ver1 for
|
53
60
|
backlight capability:
|
54
|
-
"wurflinspector.rb -d pstorehandsets.db -i sonyericsson_t300_ver1 -q
|
55
|
-
backlight"
|
56
61
|
|
57
|
-
|
62
|
+
wurfltools.rb inspector -d pstorehandsets.db -i sonyericsson_t300_ver1 -q
|
63
|
+
backlight
|
64
|
+
|
65
|
+
=== sanitycheck
|
58
66
|
|
59
67
|
Is a partial WURFL validating program. It does a few simple
|
60
68
|
checks to make sure the XML structure is parse-able by the wurflloader.
|
@@ -62,14 +70,14 @@ If you receive loading errors by the wurflloader, then you can run the
|
|
62
70
|
wurflsanitycheck program to find the lines in the XML file that might
|
63
71
|
be causing the problem.
|
64
72
|
|
65
|
-
===
|
73
|
+
=== comparator
|
66
74
|
|
67
75
|
Is a another simple program that will find the differences from two
|
68
76
|
WURFL Ruby PStore databases. This is another way of finding changes
|
69
77
|
from the different versions of the WURFL without running a diff on the
|
70
78
|
XML files.
|
71
79
|
|
72
|
-
=== uaproftowurfl
|
80
|
+
=== uaproftowurfl
|
73
81
|
|
74
82
|
Is a program that takes UAProfiles and creates an equivalent WURFL
|
75
83
|
entry. It holds all of the mappings used to convert a UAProfile to a
|
@@ -97,12 +105,12 @@ the UAProfToWurfl class later.
|
|
97
105
|
|
98
106
|
A simple usage is:
|
99
107
|
|
100
|
-
|
108
|
+
wurfltools.rb uaproftowurfl sampleprofile.xml
|
101
109
|
|
102
110
|
Example use from a bash shell with many profiles:
|
103
111
|
|
104
112
|
for i in `ls profiles`; do
|
105
|
-
|
113
|
+
wurfltools.rb uaproftowurfl profiles/$i >output/$i.wurfl
|
106
114
|
2> output/$i.parser.err;
|
107
115
|
done
|
108
116
|
|
@@ -110,7 +118,7 @@ This assumes that you have a profiles directory with all of the UAProf
|
|
110
118
|
file you wish to parse and a output directory to place the results and
|
111
119
|
errors.
|
112
120
|
|
113
|
-
=== uaprofwurflcomparator
|
121
|
+
=== uaprofwurflcomparator
|
114
122
|
|
115
123
|
Is a program that compares UAProfiles against the equivalent WURFL
|
116
124
|
entries. It takes a file that contains an UAProfile URL and an
|
@@ -126,12 +134,13 @@ from the given URL, a file that holds the UAProfil URL and User-Agent
|
|
126
134
|
mappings, and the Ruby PStore database that holds the WURFL.
|
127
135
|
|
128
136
|
The following is a simple example of execution
|
129
|
-
|
137
|
+
|
138
|
+
wurfltools.rb uaprofwurflcomparator -d ./profiles -f all-profile.2003-08.log -c -w wurfl.db
|
130
139
|
|
131
140
|
== Authors
|
132
141
|
|
133
|
-
Zev Blut (Original Author)
|
134
|
-
Paul McMahon (gem installer, refactorings)
|
142
|
+
* Zev Blut (Original Author)
|
143
|
+
* Paul McMahon (gem installer, refactorings)
|
135
144
|
|
136
145
|
== Copyright
|
137
146
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
data/bin/wurfltools.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
4
|
+
|
5
|
+
def usage
|
6
|
+
puts "usage: wurfltools.rb command options"
|
7
|
+
path = "#{File.dirname(__FILE__)}/../lib/wurfl/command/*"
|
8
|
+
a = Dir.glob(path).map {|s| File.basename(s,".rb")}
|
9
|
+
puts "available commands:"
|
10
|
+
puts a
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
usage if ARGV.size < 1
|
15
|
+
|
16
|
+
command = ARGV.shift
|
17
|
+
|
18
|
+
require "wurfl/command/#{command}"
|
19
|
+
|
20
|
+
c = Wurfl::Command.const_get(command.capitalize).new
|
21
|
+
c.execute
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "wurfl/command"
|
2
|
+
require "getoptlong"
|
3
|
+
require "wurfl/handset"
|
4
|
+
require "wurfl/utils"
|
5
|
+
|
6
|
+
class Wurfl::Command::Comparator < Wurfl::Command
|
7
|
+
include Wurfl::Utils
|
8
|
+
|
9
|
+
def usage
|
10
|
+
puts "Usage: wurfltools.rb comparator wurfl_pstore1_db wurfl_pstore2_db "
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute
|
15
|
+
if ARGV.size != 2
|
16
|
+
usage
|
17
|
+
end
|
18
|
+
|
19
|
+
# load the wurfl databases
|
20
|
+
wurfl1 = wurfl2 = nil
|
21
|
+
begin
|
22
|
+
wurfl1, = load_wurfl_pstore(ARGV[0])
|
23
|
+
wurfl2, = load_wurfl_pstore(ARGV[1])
|
24
|
+
rescue => err
|
25
|
+
efile = ""
|
26
|
+
if wurfl1.nil?
|
27
|
+
efile = ARGV[0]
|
28
|
+
else
|
29
|
+
efile = ARGV[1]
|
30
|
+
end
|
31
|
+
STDERR.puts "Error with file #{efile}"
|
32
|
+
STDERR.puts err.message
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "Comparing files: #{ARGV[0]} and #{ARGV[1]}"
|
37
|
+
puts "-------------------------------------"
|
38
|
+
|
39
|
+
if wurfl1.size > wurfl2.size
|
40
|
+
mwurfl = wurfl1
|
41
|
+
lwurfl = wurfl2
|
42
|
+
else
|
43
|
+
mwurfl = wurfl2
|
44
|
+
lwurfl = wurfl1
|
45
|
+
end
|
46
|
+
|
47
|
+
notfound = Array.new
|
48
|
+
different = Array.new
|
49
|
+
mwurfl.each do |key,handset|
|
50
|
+
if lwurfl.key?(key)
|
51
|
+
if handset != lwurfl[key]
|
52
|
+
different<< [handset,lwurfl[key]]
|
53
|
+
end
|
54
|
+
else
|
55
|
+
notfound<< handset
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
puts "Comparision complete."
|
61
|
+
|
62
|
+
puts "Not Found Handsets: #{notfound.size}"
|
63
|
+
puts "||||||||||||||||||||||||||||||||||||"
|
64
|
+
notfound = notfound.sort { |x,y| y.wurfl_id <=> x.wurfl_id }
|
65
|
+
notfound.each { |hand| puts hand.wurfl_id }
|
66
|
+
puts "||||||||||||||||||||||||||||||||||||"
|
67
|
+
|
68
|
+
puts "Different handsets: #{different.size}"
|
69
|
+
puts "||||||||||||||||||||||||||||||||||||"
|
70
|
+
different = different.sort { |x,y| y.first.wurfl_id <=> x.first.wurfl_id }
|
71
|
+
different.each do |hand1,hand2|
|
72
|
+
puts "-------------------------------------"
|
73
|
+
puts "Handset: #{hand1.user_agent} :ID: #{hand1.wurfl_id}"
|
74
|
+
diffkeys = hand1.compare(hand2)
|
75
|
+
diffkeys.each do |key,oval,oid|
|
76
|
+
next if hand1[key].nil? || hand2[key].nil?
|
77
|
+
puts "Key:#{key}"
|
78
|
+
puts "h1>:#{hand1[key]}"
|
79
|
+
puts "h2<:#{hand2[key]}"
|
80
|
+
end
|
81
|
+
puts "-------------------------------------"
|
82
|
+
end
|
83
|
+
|
84
|
+
puts "||||||||||||||||||||||||||||||||||||"
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require "wurfl/command"
|
2
|
+
|
3
|
+
require "getoptlong"
|
4
|
+
require "wurfl/handset"
|
5
|
+
require "wurfl/utils"
|
6
|
+
|
7
|
+
class Wurfl::Command::Inspector < Wurfl::Command
|
8
|
+
=begin
|
9
|
+
A class that lists wurfl handsets that match user specified search
|
10
|
+
criteria.
|
11
|
+
=end
|
12
|
+
class WurflInspector
|
13
|
+
|
14
|
+
# Constructor
|
15
|
+
# Parameters:
|
16
|
+
# handsets: A hashtable of wurfl handsets indexed by wurfl_id.
|
17
|
+
def initialize(handsets)
|
18
|
+
@handsets = handsets
|
19
|
+
end
|
20
|
+
|
21
|
+
# A method to get the WurflHandset that matches the passed wurfl_id.
|
22
|
+
# Parameters:
|
23
|
+
# id: is the wurfl_id of the WurflHandset to get.
|
24
|
+
# Returns:
|
25
|
+
# The WurflHandset that has the requested wurfl_id. If the wurfl_id
|
26
|
+
# is not found, then nil is returned.
|
27
|
+
def get_handset(id)
|
28
|
+
return @handsets[id]
|
29
|
+
end
|
30
|
+
|
31
|
+
# A method to retrieve a list of the inspector's handsets that match
|
32
|
+
# the passed search criteria.
|
33
|
+
# Parameters:
|
34
|
+
# proc: is a Proc object that defines a function that returns
|
35
|
+
# true or false from an evaluattion with a WurflHandset.
|
36
|
+
# Returns:
|
37
|
+
# An Array of all WurflHandsets that match the proc evaluation.
|
38
|
+
def search_handsets(proc)
|
39
|
+
rez = @handsets.values.select do |hand|
|
40
|
+
x = proc.call(hand)
|
41
|
+
end
|
42
|
+
return rez if rez != nil
|
43
|
+
return Array::new
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
include Wurfl::Utils
|
50
|
+
|
51
|
+
def usage
|
52
|
+
puts "Usage: wurfltools.rb inspector [-s rubyblock] [-i handsetid [-q attributename]] -d pstorefile"
|
53
|
+
puts "Examples:"
|
54
|
+
puts "wurfltools.rb inspector -d pstorehandsets.db -s '{ |hand| hand[\"colors\"].to_i > 2 }'"
|
55
|
+
puts "wurfltools inspector -d pstorehandsets.db -i sonyericsson_t300_ver1"
|
56
|
+
puts "wurfltools inspector -d pstorehandsets.db -i sonyericsson_t300_ver1 -q backlight"
|
57
|
+
exit 1
|
58
|
+
end
|
59
|
+
|
60
|
+
def execute
|
61
|
+
pstorefile = nil
|
62
|
+
procstr = nil
|
63
|
+
handset = nil
|
64
|
+
query = nil
|
65
|
+
begin
|
66
|
+
opt = GetoptLong.new(
|
67
|
+
["-d","--database", GetoptLong::REQUIRED_ARGUMENT],
|
68
|
+
["-s","--search", GetoptLong::REQUIRED_ARGUMENT],
|
69
|
+
["-i","--id", GetoptLong::REQUIRED_ARGUMENT],
|
70
|
+
["-q","--query", GetoptLong::REQUIRED_ARGUMENT]
|
71
|
+
)
|
72
|
+
|
73
|
+
opt.each do |arg,val|
|
74
|
+
case arg
|
75
|
+
when "-d"
|
76
|
+
pstorefile = val
|
77
|
+
when "-s"
|
78
|
+
procstr = val.strip
|
79
|
+
when "-i"
|
80
|
+
handset = val
|
81
|
+
when "-q"
|
82
|
+
query = val
|
83
|
+
else
|
84
|
+
usage
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
rescue => err
|
89
|
+
usage
|
90
|
+
end
|
91
|
+
|
92
|
+
if !pstorefile
|
93
|
+
puts "You must specify a Wurfl PStore db"
|
94
|
+
usage
|
95
|
+
end
|
96
|
+
|
97
|
+
begin
|
98
|
+
handsets, = load_wurfl_pstore(pstorefile)
|
99
|
+
insp = WurflInspector.new(handsets)
|
100
|
+
rescue => err
|
101
|
+
STDERR.puts "Error with file #{pstorefile}"
|
102
|
+
STDERR.puts err.message
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
|
106
|
+
if procstr
|
107
|
+
pr = nil
|
108
|
+
eval("pr = proc#{procstr}")
|
109
|
+
|
110
|
+
if pr.class != Proc
|
111
|
+
puts "You must pass a valid ruby block!"
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
|
115
|
+
puts "--------- Searching handsets -----------"
|
116
|
+
res = insp.search_handsets(pr)
|
117
|
+
puts "Number of results: #{res.size}"
|
118
|
+
|
119
|
+
res.each { |handset| puts handset.wurfl_id }
|
120
|
+
exit 0
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
if handset
|
125
|
+
handset = insp.get_handset(handset)
|
126
|
+
puts "Handset user agent: #{handset.user_agent}"
|
127
|
+
if query
|
128
|
+
puts "Result of handset query: #{query}"
|
129
|
+
rez = handset.get_value_and_owner(query)
|
130
|
+
puts "#{rez[0]} from #{rez[1]}"
|
131
|
+
else
|
132
|
+
puts "Attributes of handset"
|
133
|
+
keys = handset.keys
|
134
|
+
keys.each do |key|
|
135
|
+
rez = handset.get_value_and_owner(key)
|
136
|
+
puts "Attr:#{key} Val:#{rez[0]} from #{rez[1]}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
exit 0
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "wurfl/command"
|
2
|
+
|
3
|
+
require "getoptlong"
|
4
|
+
require "wurfl/utils"
|
5
|
+
require "wurfl/loader"
|
6
|
+
|
7
|
+
class Wurfl::Command::Loader < Wurfl::Command
|
8
|
+
include Wurfl::Utils
|
9
|
+
|
10
|
+
def usage
|
11
|
+
puts "Usage: wurfltools.rb loader [-p -v -h -e patchfile] -f wurflfile"
|
12
|
+
puts " --file, -f (wurflfile): The master WURFL file to load."
|
13
|
+
puts " --extension, -e (patchfile): A patch file to extend the traits of the master WURLF file."
|
14
|
+
puts " --print, -p : Prints out handsets."
|
15
|
+
puts " --verbose, -v : Verbose output."
|
16
|
+
puts " --help, -h : Prints this message."
|
17
|
+
puts " --database, -d (databasename): Makes a PStore database for quick loading of data with other tools."
|
18
|
+
puts " --load, -l (databasename): Loads handsets from a PStore database instead of XML file."
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute
|
23
|
+
print = false
|
24
|
+
insert = false
|
25
|
+
verbose = false
|
26
|
+
wurflfile = nil
|
27
|
+
patchfile = nil
|
28
|
+
pstorefile = nil
|
29
|
+
pstoreload = false
|
30
|
+
|
31
|
+
begin
|
32
|
+
options = GetoptLong.new(
|
33
|
+
["-p","--print", GetoptLong::NO_ARGUMENT],
|
34
|
+
["-h","--help", GetoptLong::NO_ARGUMENT],
|
35
|
+
["-v","--verbose", GetoptLong::NO_ARGUMENT],
|
36
|
+
["-f","--file", GetoptLong::REQUIRED_ARGUMENT],
|
37
|
+
["-e","--extension", GetoptLong::REQUIRED_ARGUMENT],
|
38
|
+
["-d","--database", GetoptLong::REQUIRED_ARGUMENT],
|
39
|
+
["-l","--load", GetoptLong::REQUIRED_ARGUMENT]
|
40
|
+
)
|
41
|
+
|
42
|
+
options.each do |opt,arg|
|
43
|
+
case opt
|
44
|
+
when "-p"
|
45
|
+
print = true
|
46
|
+
when "-v"
|
47
|
+
verbose = true
|
48
|
+
when "-h"
|
49
|
+
usage
|
50
|
+
exit 1
|
51
|
+
when "-f"
|
52
|
+
wurflfile = arg
|
53
|
+
when "-e"
|
54
|
+
patchfile = arg
|
55
|
+
when "-d"
|
56
|
+
pstorefile = arg
|
57
|
+
when "-l"
|
58
|
+
pstorefile = arg
|
59
|
+
pstoreload = true
|
60
|
+
else
|
61
|
+
STDERR.puts "Unknown argument #{opt}"
|
62
|
+
usage
|
63
|
+
exit 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
rescue => err
|
67
|
+
STDERR.puts "Error: #{err}"
|
68
|
+
usage
|
69
|
+
exit 1
|
70
|
+
end
|
71
|
+
|
72
|
+
wurfll = Wurfl::Loader.new
|
73
|
+
hands = nil
|
74
|
+
fallbacks = nil
|
75
|
+
|
76
|
+
if pstorefile && pstoreload
|
77
|
+
begin
|
78
|
+
puts "Loading data from #{pstorefile}"
|
79
|
+
hands, fallbacks = load_wurfl_pstore(pstorefile)
|
80
|
+
puts "Loaded"
|
81
|
+
rescue => err
|
82
|
+
STDERR.puts "Error: Cannot load PStore file."
|
83
|
+
STDERR.puts err.message
|
84
|
+
exit 1
|
85
|
+
end
|
86
|
+
else
|
87
|
+
if !wurflfile
|
88
|
+
STDERR.puts "You must pass a wurflfile if you want to do more."
|
89
|
+
usage
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
|
93
|
+
starttime = Time.now
|
94
|
+
puts "Loading wurfl file #{wurflfile}"
|
95
|
+
|
96
|
+
wurfll.verbose = verbose
|
97
|
+
|
98
|
+
hands, fallbacks = wurfll.load_wurfl(wurflfile)
|
99
|
+
restime = Time.now - starttime
|
100
|
+
|
101
|
+
puts "Done loading wurfl. Load took #{restime} seconds."
|
102
|
+
|
103
|
+
if patchfile
|
104
|
+
starttime = Time.now
|
105
|
+
puts "Loading Patch file #{patchfile}"
|
106
|
+
hands, fallbacks = wurfll.load_wurfl(patchfile)
|
107
|
+
restime = Time.now - starttime
|
108
|
+
puts "Done loading patchfile. Load took #{restime} seconds."
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
if pstorefile && !pstoreload
|
114
|
+
begin
|
115
|
+
puts "Saving data into #{pstorefile}"
|
116
|
+
save_wurfl_pstore(pstorefile, hands, fallbacks)
|
117
|
+
puts "Saved"
|
118
|
+
rescue => err
|
119
|
+
STDERR.puts "Error: Cannot creat PStore file."
|
120
|
+
STDERR.puts err.message
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
if print
|
125
|
+
wurfll.print_wurfl hands
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|