wurfl 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  *.swp
2
2
  pkg/*
3
+ rdoc/*
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
- === wurflloader.rb
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
- === wurflinspector.rb
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
- *) This command will return all handsets that have more than 2 colors.
28
- "wurflinspector.rb -d pstorehandsets.db -s '{ |hand| hand["colors"].to_i > 2 }'"
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
- *) This command shows you how you can cheat with the current design of
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
- "wurflinspector.rb -d pstorehandsets.db -s '{|hand| puts
41
- "#{hand["brand_name"]} #{hand["model_name"]}" if hand["colors"].to_i >
42
- 2}' | sort | uniq"
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
- *) A command to query the handset with the id sonyericsson_t300_ver1
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
- *) A command to query the handset with the id sonyericsson_t300_ver1 for
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
- === wurflsanitycheck.rb
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
- === wurflcomparator.rb
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.rb
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
- ruby uaproftowurfl.rb sampleprofile.xml
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
- ruby uaproftowurfl.rb profiles/$i >output/$i.wurfl
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.rb
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
- uaprofwurflcomparator.rb -d ./profiles -f all-profile.2003-08.log -c -w wurfl.db
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.2
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,4 @@
1
+ module Wurfl
2
+ class Command
3
+ end
4
+ end
@@ -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