wurfl 1.0.2

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.
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require "getoptlong"
6
+ require "wurfl/handset"
7
+ require "wurfl/utils"
8
+
9
+ include Wurfl::Utils
10
+
11
+ def usage
12
+ puts "Usage: wurflcomparator.rb wurfl_pstore1_db wurfl_pstore2_db "
13
+ exit 1
14
+ end
15
+
16
+ if ARGV.size != 2
17
+ usage
18
+ end
19
+
20
+ # load the wurfl databases
21
+ wurfl1 = wurfl2 = nil
22
+ begin
23
+ wurfl1, = load_wurfl_pstore(ARGV[0])
24
+ wurfl2, = load_wurfl_pstore(ARGV[1])
25
+ rescue => err
26
+ efile = ""
27
+ if wurfl1.nil?
28
+ efile = ARGV[0]
29
+ else
30
+ efile = ARGV[1]
31
+ end
32
+ STDERR.puts "Error with file #{efile}"
33
+ STDERR.puts err.message
34
+ exit 1
35
+ end
36
+
37
+ puts "Comparing files: #{ARGV[0]} and #{ARGV[1]}"
38
+ puts "-------------------------------------"
39
+
40
+ if wurfl1.size > wurfl2.size
41
+ mwurfl = wurfl1
42
+ lwurfl = wurfl2
43
+ else
44
+ mwurfl = wurfl2
45
+ lwurfl = wurfl1
46
+ end
47
+
48
+ notfound = Array.new
49
+ different = Array.new
50
+ mwurfl.each do |key,handset|
51
+ if lwurfl.key?(key)
52
+ if handset != lwurfl[key]
53
+ different<< [handset,lwurfl[key]]
54
+ end
55
+ else
56
+ notfound<< handset
57
+ end
58
+ end
59
+
60
+
61
+ puts "Comparision complete."
62
+
63
+ puts "Not Found Handsets: #{notfound.size}"
64
+ puts "||||||||||||||||||||||||||||||||||||"
65
+ notfound = notfound.sort { |x,y| y.wurfl_id <=> x.wurfl_id }
66
+ notfound.each { |hand| puts hand.wurfl_id }
67
+ puts "||||||||||||||||||||||||||||||||||||"
68
+
69
+ puts "Different handsets: #{different.size}"
70
+ puts "||||||||||||||||||||||||||||||||||||"
71
+ different = different.sort { |x,y| y.first.wurfl_id <=> x.first.wurfl_id }
72
+ different.each do |hand1,hand2|
73
+ puts "-------------------------------------"
74
+ puts "Handset: #{hand1.user_agent} :ID: #{hand1.wurfl_id}"
75
+ diffkeys = hand1.compare(hand2)
76
+ diffkeys.each do |key,oval,oid|
77
+ next if hand1[key].nil? || hand2[key].nil?
78
+ puts "Key:#{key}"
79
+ puts "h1>:#{hand1[key]}"
80
+ puts "h2<:#{hand2[key]}"
81
+ end
82
+ puts "-------------------------------------"
83
+ end
84
+
85
+ puts "||||||||||||||||||||||||||||||||||||"
86
+
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require "getoptlong"
6
+ require "wurfl/handset"
7
+ require "wurfl/utils"
8
+
9
+ =begin
10
+ A class that lists wurfl handsets that match user specified search
11
+ criteria.
12
+ =end
13
+ class WurflInspector
14
+
15
+ # Constructor
16
+ # Parameters:
17
+ # handsets: A hashtable of wurfl handsets indexed by wurfl_id.
18
+ def initialize(handsets)
19
+ @handsets = handsets
20
+ end
21
+
22
+ # A method to get the WurflHandset that matches the passed wurfl_id.
23
+ # Parameters:
24
+ # id: is the wurfl_id of the WurflHandset to get.
25
+ # Returns:
26
+ # The WurflHandset that has the requested wurfl_id. If the wurfl_id
27
+ # is not found, then nil is returned.
28
+ def get_handset(id)
29
+ return @handsets[id]
30
+ end
31
+
32
+ # A method to retrieve a list of the inspector's handsets that match
33
+ # the passed search criteria.
34
+ # Parameters:
35
+ # proc: is a Proc object that defines a function that returns
36
+ # true or false from an evaluattion with a WurflHandset.
37
+ # Returns:
38
+ # An Array of all WurflHandsets that match the proc evaluation.
39
+ def search_handsets(proc)
40
+ rez = @handsets.values.select do |hand|
41
+ x = proc.call(hand)
42
+ end
43
+ return rez if rez != nil
44
+ return Array::new
45
+ end
46
+
47
+ end
48
+
49
+
50
+ include Wurfl::Utils
51
+
52
+ def usage
53
+ puts "Usage: wurflinspector.rb [-s rubyblock] [-i handsetid [-q attributename]] -d pstorefile"
54
+ puts "Examples:"
55
+ puts "wurflinspector.rb -d pstorehandsets.db -s '{ |hand| hand[\"colors\"].to_i > 2 }'"
56
+ puts "wurflinspector.rb -d pstorehandsets.db -i sonyericsson_t300_ver1"
57
+ puts "wurflinspector.rb -d pstorehandsets.db -i sonyericsson_t300_ver1 -q backlight"
58
+ exit 1
59
+ end
60
+
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
+
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require "getoptlong"
6
+ require "wurfl/utils"
7
+ require "wurfl/loader"
8
+
9
+ include Wurfl::Utils
10
+
11
+ print = false
12
+ insert = false
13
+ verbose = false
14
+ wurflfile = nil
15
+ patchfile = nil
16
+ pstorefile = nil
17
+ pstoreload = false
18
+
19
+ def usage
20
+ puts "Usage: wurflloader.rb [-p -v -h -e patchfile] -f wurflfile"
21
+ puts " --file, -f (wurflfile): The master WURFL file to load."
22
+ puts " --extension, -e (patchfile): A patch file to extend the traits of the master WURLF file."
23
+ puts " --print, -p : Prints out handsets."
24
+ puts " --verbose, -v : Verbose output."
25
+ puts " --help, -h : Prints this message."
26
+ puts " --database, -d (databasename): Makes a PStore database for quick loading of data with other tools."
27
+ puts " --load, -l (databasename): Loads handsets from a PStore database instead of XML file."
28
+ exit 1
29
+ end
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
+
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ # A simple command line tool to make sure that a wurfl file properly parses.
6
+ # Used to make sure changes to Wurfl/Patch files are OK.
7
+ if ARGV.size != 1
8
+ puts "Must have the path of the wurfl file to check"
9
+ exit 1
10
+ end
11
+ lines = File.open(ARGV[0],"r").readlines
12
+
13
+ curdev = nil
14
+ c = 0
15
+
16
+ lines.each do |line|
17
+ line = line.strip
18
+ if line =~ /^(<d)evice.*[^\/]>$/
19
+ curdev = line
20
+ elsif line =~ /^(<d)evice.*\/>$/
21
+ if curdev
22
+ puts "#{c}:A device was not closed and we got a new device! #{curdev}"
23
+ end
24
+ curdev = nil
25
+ elsif line =~ /^(<\/d)evice>$/
26
+ if curdev.nil?
27
+ puts "#{c}:A closing device with no opening! #{curdev}"
28
+ end
29
+ curdev=nil
30
+ end
31
+ c += 1
32
+ end
33
+
34
+ if curdev
35
+ puts "The curent device was not closed #{curdev}"
36
+ end
37
+
38
+
39
+ puts "Done"
@@ -0,0 +1,117 @@
1
+ require "singleton"
2
+
3
+ module Wurfl; end
4
+
5
+ =begin
6
+ A class that represents a handset based on information taken from the WURFL.
7
+ =end
8
+ class Wurfl::Handset
9
+
10
+ extend Enumerable
11
+
12
+ attr_accessor :wurfl_id, :user_agent
13
+
14
+ # Constructor
15
+ # Parameters:
16
+ # wurfl_id: is the WURFL ID of the handset
17
+ # useragent: is the user agent of the handset
18
+ # fallback: is the fallback handset that this handset
19
+ # uses for missing details.
20
+ def initialize (wurfl_id, useragent, fallback = nil)
21
+ # A hash to hold keys and values specific to this handset
22
+ @capabilityhash = Hash::new
23
+ @wurfl_id = wurfl_id
24
+ @user_agent = useragent
25
+ @fallback = fallback || NullHandset.instance
26
+ end
27
+
28
+ def fallback=(v)
29
+ @fallback = v || NullHandset.instance
30
+ end
31
+
32
+ # Hash accessor
33
+ # Parameters:
34
+ # key: the WURFL key whose value is desired
35
+ # Returns:
36
+ # The value of the key, nil if the handset does not have the key.
37
+ def [] (key)
38
+ @capabilityhash.key?(key) ? @capabilityhash[key] : @fallback[key]
39
+ end
40
+
41
+ # like the above accessor, but also to know who the value
42
+ # comes from
43
+ # Returns:
44
+ # the value and the id of the handset from which the value was obtained
45
+ def get_value_and_owner(key)
46
+ if @capabilityhash.key?(key)
47
+ [ @capabilityhash[key], @wurfl_id ]
48
+ else
49
+ @fallback.get_value_and_owner(key)
50
+ end
51
+ end
52
+
53
+ # Setter, A method to set a key and value of the handset.
54
+ def []= (key,val)
55
+ @capabilityhash[key] = val
56
+ end
57
+
58
+ # A Method to iterate over all of the keys and values that the handset has.
59
+ # Note: this will abstract the hash iterator to handle all the lower level
60
+ # calls for the fallback values.
61
+ def each
62
+ self.keys.each do |key|
63
+ # here is the magic that gives us the key and value of the handset
64
+ # all the way up to the fallbacks end.
65
+ # Call the pass block with the key and value passed
66
+ yield key, self[key]
67
+ end
68
+ end
69
+
70
+ # A method to get all of the keys that the handset has.
71
+ def keys
72
+ @capabilityhash.keys | @fallback.keys
73
+ end
74
+
75
+ # A method to do a simple equality check against two handsets.
76
+ # Parameter:
77
+ # other: Is the another WurflHandset to check against.
78
+ # Returns:
79
+ # true if the two handsets are equal in all values.
80
+ # false if they are not exactly equal in values, id and user agent.
81
+ # Note: for a more detailed comparison, use the compare method.
82
+ def ==(other)
83
+ return false unless other.instance_of?(Wurfl::Handset)
84
+ return false unless self.wurfl_id == other.wurfl_id && self.user_agent == other.user_agent
85
+ other.each do |key,value|
86
+ return false if value != self[key]
87
+ end
88
+ true
89
+ end
90
+
91
+ # A method to compare a handset's values against another handset.
92
+ # Parameters:
93
+ # other: is the another WurflHandset to compare against
94
+ # Returns:
95
+ # An array of the different values.
96
+ # Each entry in the Array is an Array of three values.
97
+ # The first value is the key in which both handsets have different values.
98
+ # The second is the other handset's value for the key.
99
+ # The third is the handset id from where the other handset got it's value.
100
+ def compare(other)
101
+ differences = Array.new
102
+ self.keys.each do |key|
103
+ oval,oid = other.get_value_and_owner(key)
104
+ if @capabilityhash[key].to_s != oval.to_s
105
+ differences << [key,oval,oid]
106
+ end
107
+ end
108
+ differences
109
+ end
110
+
111
+ class NullHandset
112
+ include Singleton
113
+ def [](key) nil end
114
+ def get_value_and_owner(key) [ nil, nil ] end
115
+ def keys; [] end
116
+ end
117
+ end