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,130 @@
1
+ require "wurfl/handset"
2
+ require "rexml/document"
3
+ begin
4
+ require "xml"
5
+ rescue LoadError
6
+ require "rubygems"
7
+ require "xml"
8
+ end
9
+
10
+ module Wurfl; end
11
+
12
+ =begin
13
+ A class the handles the loading, debug printing and inserting of WURFL
14
+ handsets into a handset DB.
15
+ =end
16
+ class Wurfl::Loader
17
+
18
+ attr_accessor :new_hands, :ttl_keys, :verbose
19
+
20
+ def initialize
21
+ @new_hands = 0
22
+ @ttl_keys = 0
23
+ @verbose = false
24
+ @handsets = Hash::new
25
+ @fallbacks = Hash::new
26
+ end
27
+
28
+ # A simple debuging method to print all user agents in a WURFL file
29
+ def print_handsets_in_wurfl(wurflfile)
30
+ file = File.new(wurflfile)
31
+ doc = REXML::Document.new file
32
+ doc.elements.each("wurfl/devices/device") do |element|
33
+ puts element.attributes["user_agent"]
34
+ end
35
+ end
36
+
37
+ # Returns a Hashtable of handsets and a hashtable of Fallback id and agents
38
+ def load_wurfl(wurflfilepath)
39
+ parse_wurfl(XML::Document.file(wurflfilepath))
40
+ end
41
+
42
+ def parse_xml(s)
43
+ parse_wurfl(XML::Document.string(s))
44
+ end
45
+
46
+ # Prints out WURFL handsets from a hashtable
47
+ def print_wurfl(handsets)
48
+
49
+ handsets.each do |key,value|
50
+ puts "********************************************\n\n"
51
+ puts "#{key}\n"
52
+ value.each { |key,value| puts "#{key} = #{value}" }
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def parse_wurfl(doc)
59
+ # read counter
60
+ rcount = 0
61
+
62
+ # iterate over all of the devices in the file
63
+ doc.find("///devices/device").each do |element|
64
+
65
+ rcount += 1
66
+ hands = nil # the reference to the current handset
67
+ if element.attributes["id"] == "generic"
68
+ # setup the generic Handset
69
+
70
+ if @handsets.key?("generic") then
71
+ hands = @handsets["generic"]
72
+ puts "Updating the generic handset at count #{rcount}" if @verbose
73
+ else
74
+ # the generic handset has not been created. Make it
75
+ hands = Wurfl::Handset.new "generic","generic"
76
+ @handsets["generic"] = hands
77
+ @fallbacks["generic"] = Array::new
78
+ puts "Made the generic handset at count #{rcount}" if @verbose
79
+ end
80
+
81
+ else
82
+ # Setup an actual handset
83
+
84
+ # check if handset already exists.
85
+ wurflid = element.attributes["id"]
86
+ if @handsets.key?(wurflid)
87
+ # Must have been created by someone who named it as a fallback earlier.
88
+ hands = @handsets[wurflid]
89
+ else
90
+ hands = Wurfl::Handset.new "",""
91
+ end
92
+ hands.wurfl_id = wurflid
93
+ hands.user_agent = element.attributes["user_agent"]
94
+
95
+ # get the fallback and copy it's values into this handset's hashtable
96
+ fallb = element.attributes["fall_back"]
97
+
98
+ # for tracking of who has fallbacks
99
+ if !@fallbacks.key?(fallb)
100
+ @fallbacks[fallb] = Array::new
101
+ end
102
+ @fallbacks[fallb]<< hands.user_agent
103
+
104
+ # Now set the handset to the proper fallback reference
105
+ if !@handsets.key?(fallb)
106
+ # We have a fallback that does not exist yet, create the reference.
107
+ @handsets[fallb] = Wurfl::Handset.new "",""
108
+ end
109
+ hands.fallback = @handsets[fallb]
110
+ end
111
+
112
+ # now copy this handset's specific capabilities into it's hashtable
113
+ element.find("group/capability").each do |el2|
114
+ hands[el2.attributes["name"]] = el2.attributes["value"]
115
+ end
116
+ @handsets[hands.wurfl_id] = hands
117
+
118
+ # Do some error checking
119
+ if hands.wurfl_id.nil?
120
+ puts "a handset with a nil id at #{rcount}"
121
+ elsif hands.user_agent.nil?
122
+ puts "a handset with a nil agent at #{rcount}"
123
+ end
124
+ end
125
+
126
+ return @handsets, @fallbacks
127
+ end
128
+
129
+ end
130
+
@@ -0,0 +1,1013 @@
1
+ require "rexml/document"
2
+
3
+ # A class to handle reading a UAProfile and generating an equivalent
4
+ # WURFL entry.
5
+ # See http://wurfl.sourceforge.net/ for more details about the WURFL.
6
+ # Authors: Zev Blut, Paul McMahon (paul@mobalean.com)
7
+ # Version: 1.1 Additional mappings added from Andrea Trasatti
8
+ # Version: 1.2 More mappings added from Andrea Trasatti
9
+ # Version: 1.3 more mappings and a few changes for error handling.
10
+ class UAProfToWURLF
11
+
12
+ def initialize
13
+ # The WURFL is considered a hashtable of hashtables for all the
14
+ # wurfl groups.
15
+ @wurfl = Hash.new
16
+ #Initialize all of the sub hashes
17
+ @wurflgroups = [
18
+ "product_info","wml_ui","chtml_ui","xhtml_ui",
19
+ "markup","cache","display","image_format","bugs",
20
+ "wta","security","storage","downloadfun","wap_push",
21
+ "j2me","mms","sound_format"
22
+ ]
23
+ @wurflgroups.each do |key|
24
+ @wurfl[key] = Hash.new
25
+ end
26
+ @wurfl["user_agent"] = ""
27
+ end
28
+
29
+ # Takes a UAProfile file (in the future could also take a URL)
30
+ # and then calls the method named after each UAProfile entry.
31
+ # This then maps the UAProfile component entry to a WURFL entry.
32
+ # This method can be called multiple times to create patched WURFL
33
+ # entry.
34
+ def parse_UAProf(uaproffile)
35
+ file = File.new(uaproffile)
36
+ begin
37
+ doc = REXML::Document.new(file)
38
+ rescue Exception => err
39
+ $stderr.puts "Exception while parsing the UAProfile RDF file #{uaproffile}."
40
+ $stderr.puts "This UAProfToWurfl instance is invalid."
41
+ $stderr.puts err.class
42
+ $stderr.puts err.message
43
+ $stderr.puts err.backtrace
44
+ return
45
+ end
46
+
47
+ #get rdf:Description ID as that says the profile of phone..?
48
+ doc.elements.each("rdf:RDF/rdf:Description/prf:component/rdf:Description/*") do |element|
49
+ #doc.elements.each("//rdf:Description/*") do |element|
50
+ next if element.expanded_name == "rdf:type" #ignore the type value
51
+ methodname = make_method_name(element.name)
52
+ if self.respond_to?(methodname)
53
+ begin
54
+ method = self.method(methodname)
55
+ method.call(element)
56
+ rescue Exception => err
57
+ $stderr.puts "Uncaught exception calling #{element.name}"
58
+ $stderr.puts err.class
59
+ $stderr.puts err.message
60
+ $stderr.puts err.backtrace
61
+ end
62
+ else
63
+ $stderr.puts "Undefined UAProf component: #{element.name}"
64
+ end
65
+ end
66
+ end
67
+
68
+ # Generates a WURFL entry.
69
+ # For now simply outputs the XML to Standard Out.
70
+ def output_WURFL(filters=nil)
71
+ puts "<device fall_back=\"generic\" id=\"UAProf\" user_agent=\"#{@wurfl["user_agent"]}\">"
72
+ @wurflgroups.each do |group|
73
+ next if @wurfl[group].size == 0 || (!filters.nil? && (@wurfl[group].keys & filters.to_a).size == 0)
74
+ puts " <group id=\"#{group}\">"
75
+ @wurfl[group].sort.each do |key,value|
76
+ next if !filters.nil? && !filters.include?(key)
77
+ puts " <capability name=\"#{key}\" value=\"#{value}\"/>"
78
+ end
79
+ puts " </group>"
80
+ end
81
+ puts "</device>"
82
+ end
83
+
84
+
85
+ ######################################################################
86
+ # UAProfile Mappings
87
+ # Each entry below is an item in the UAProfile.
88
+ # The element is the XML entry that contains the data about the
89
+ # UAProfile item. It is used to then create a mappings to the WURFL.
90
+ ######################################################################
91
+
92
+
93
+ def BitsPerPixel(element)
94
+ bits = element.text.to_i
95
+ bits = 2 ** bits if bits !=2
96
+ @wurfl["image_format"]["colors"] = bits
97
+ end
98
+
99
+ def ColorCapable(element)
100
+ if element.text == "No"
101
+ if @wurfl["image_format"].key?("colors")
102
+ if @wurfl["image_format"]["colors"] > 2
103
+ @wurfl["image_format"]["greyscale"] = true
104
+ end
105
+ else
106
+ $stderr.puts "ColorCapable called before BitsPerPixel, thus unable to determine if greyscale."
107
+ end
108
+ end
109
+ end
110
+
111
+ def CPU(element)
112
+ end
113
+
114
+ def ImageCapable(element)
115
+ end
116
+
117
+ def InputCharSet(element)
118
+ end
119
+
120
+ def Keyboard(element)
121
+ end
122
+
123
+ def Model(element)
124
+ @wurfl["product_info"]["model_name"] = element.text
125
+ end
126
+
127
+ def NumberOfSoftKeys(element)
128
+ num = element.text.to_i
129
+ if num > 0
130
+ @wurfl["wml_ui"]["softkey_support"] = true
131
+ @wurfl["j2me"]["j2me_softkeys"] = num # in theory we should only check this if j2me support exists
132
+ end
133
+ end
134
+
135
+ def OutputCharSet(element)
136
+ end
137
+
138
+ def PixelAspectRatio(element)
139
+ end
140
+
141
+ def PointingResolution(element)
142
+ end
143
+
144
+ def ScreenSize(element)
145
+ width, height = break_num_x_num(element.text)
146
+ @wurfl["display"]["resolution_width"] = width
147
+ @wurfl["display"]["resolution_height"] = height
148
+ end
149
+
150
+ def ScreenSizeChar(element)
151
+ columns,rows = break_num_x_num(element.text)
152
+ @wurfl["display"]["columns"] = columns
153
+ @wurfl["display"]["rows"] = rows
154
+ end
155
+
156
+ def StandardFontProportional(element)
157
+ end
158
+
159
+ def SoundOutputCapable(element)
160
+ end
161
+
162
+ def TextInputCapable(element)
163
+ end
164
+
165
+ def VoiceInputCapable(element)
166
+ end
167
+
168
+ def Vendor(element)
169
+ @wurfl["product_info"]["brand_name"] = element.text
170
+ end
171
+
172
+ ########## SoftwarePlatform
173
+ def AcceptDownloadableSoftware(element)
174
+ #?good to know?
175
+ end
176
+
177
+ def AudioInputEncoder(element)
178
+ end
179
+
180
+ # This one does a large amount of mapping
181
+ def CcppAccept(element)
182
+ items = get_items_from_bag(element)
183
+ items.each do |type|
184
+ # Use regular expression comparisons to deal with values
185
+ # that sometimes contain q or Type that we do not need
186
+ # to bother with.
187
+ case type
188
+ when /^image\/jpeg/,"image/jpg"
189
+ @wurfl["image_format"]["jpg"] = true
190
+ when /^image\/gif/
191
+ @wurfl["image_format"]["gif"] = true
192
+ when /image\/vnd\.wap\.wbmp/
193
+ @wurfl["image_format"]["wbmp"] = true
194
+ when /^image\/bmp/,"image/x-bmp"
195
+ @wurfl["image_format"]["bmp"] = true
196
+ when /^image\/png/
197
+ @wurfl["image_format"]["png"] = true
198
+ when "application/smil"
199
+ ### Where is the SMAF in MMS of WURFL?###
200
+ when "application/vnd.smaf","application/x-smaf","application/smaf"
201
+ #how to determine mmf version?
202
+ $stderr.puts "CcppAccept supports MMF but what number: #{type}"
203
+ when "audio/amr","audio/x-amr"
204
+ @wurfl["sound_format"]["amr"] = true
205
+ when "audio/midi","audio/mid","audio/x-midi","audio/x-mid"
206
+ @wurfl["sound_format"]["midi_monophonic"] = true
207
+ # We can play it safe an say mono. what about poly?
208
+ when "audio/sp-midi"
209
+ @wurfl["sound_format"]["sp_midi"] = true
210
+ when "audio/wav","audio/x-wav","application/wav","application/x-wav"
211
+ @wurfl["sound_format"]["wav"] = true
212
+ when "image/tiff"
213
+ @wurfl["image_format"]["tiff"] = true
214
+ when "audio/imelody","audio/x-imy","text/x-iMelody","text/iMelody","text/x-imelody","audio/iMelody"
215
+ @wurfl["sound_format"]["imelody"] = true
216
+ when "application/vnd.nokia.ringing-tone"
217
+ @wurfl["sound_format"]["nokia_ringtone"] = true
218
+ when "audio/mpeg3"
219
+ @wurfl["sound_format"]["mp3"] = true
220
+ when "text/x-eMelody"
221
+ when "text/x-vMel"
222
+ when /^text\/plain/
223
+ when "text/x-vCard"
224
+ when "text/x-vCalendar"
225
+ when "application/vnd.wap.mms-message"
226
+ when "application/vnd.wap.multipart.mixed"
227
+ when "application/vnd.wap.multipart.related"
228
+ when "application/octet-stream"
229
+ when "application/vnd.eri.thm"
230
+ when "application/vnd.openwave.pp"
231
+ when "application/vnd.phonecom.im"
232
+ when "application/vnd.phonecom.mmc-wbxml"
233
+ when "application/vnd.phonecom.mmc-wbxml;Type=4364"
234
+ when "application/vnd.phonecom.mmc-xml"
235
+ when "application/vnd.syncml-xml-wbxml"
236
+ when "application/vnd.uplanet.alert"
237
+ when "application/vnd.uplanet.alert-wbxml"
238
+ when "application/vnd.uplanet.bearer-choice"
239
+ when "application/vnd.uplanet.bearer-choice-wbxml"
240
+ when "application/vnd.uplanet.cacheop"
241
+ when "application/vnd.uplanet.cacheop-wbxml"
242
+ when "application/vnd.uplanet.channel"
243
+ when "application/vnd.uplanet.channel-wbxml"
244
+ when "application/vnd.uplanet.list"
245
+ when "application/vnd.uplanet.listcmd"
246
+ when "application/vnd.uplanet.listcmd-wbxml"
247
+ when "application/vnd.uplanet.list-wbxml"
248
+ when "application/vnd.uplanet.provisioning-status-uri"
249
+ when "application/vnd.uplanet.signal"
250
+ when "application/vnd.wap.coc"
251
+ when "application/vnd.wap.multipart.header-set"
252
+ when "application/vnd.wap.sia"
253
+ when "application/vnd.wap.sic"
254
+ when "application/vnd.wap.slc"
255
+ when "application/vnd.wap.si"
256
+ when "application/vnd.wap.sl"
257
+ #The si and sl are probably related to the sia/sic and slc?
258
+ when "application/vnd.wap.wbxml"
259
+ when /^application\/vnd\.wap\.wmlc/i
260
+ #"application/vnd.wap.wmlc;Level=1.3"
261
+ #"application/vnd.wap.wmlc;Type=1108"
262
+ #"application/vnd.wap.wmlc;Type=4360"
263
+ #"application/vnd.wap.wmlc;Type=4365"
264
+ when /application\/vnd\.wap\.wml(.)?scriptc/i
265
+ when "application/vnd.wap.wtls-ca-certificate"
266
+ when "application/vnd.wap.wtls-user-certificate"
267
+ when "application/vnd.wap.xhtml+xml","application/xhtml+xml",
268
+ "application/xhtml+xml;profile=\"http://www.wapforum.org/xhtml\""
269
+ when "application/xml"
270
+ when /application\/x-mmc\./
271
+ @wurfl["downloadfun"]["downloadfun_support"] = true
272
+ # There is much Download Fun logic to do here
273
+ # A few examples of what we may get are included
274
+
275
+ val = parse_download_fun_accept(type)
276
+ if val.nil?
277
+ next
278
+ # Then we probably received one of these what to do about them?
279
+ # when "application/x-mmc.title;charset=us-ascii;size=255"
280
+ # when "application/x-mmc.title;charset=us-ascii;size=30"
281
+ # when "application/x-mmc.title;charset=UTF-8;size=80"
282
+ end
283
+
284
+ case val["object-type"]
285
+ when "audio","ringtone"
286
+ #application/x-mmc.audio;Content-Type=audio/midi;size=25600;voices=16
287
+ #application/x-mmc.ringtone;Content-Type=audio/x-sagem1.0;size=1000
288
+ #application/x-mmc.ringtone;Content-Type=audio/x-sagem2.0;size=5500
289
+ #application/x-mmc.ringtone;Content-Type=audio/x-wav;codec=pcm;samp=8000;res=16;size=200000
290
+ #application/x-mmc.ringtone;Content-Type=audio/x-wav;codec=pcm;samp=8000;res=8,16;size=200000
291
+ @wurfl["downloadfun"]["ringtone"] = true
292
+ case val["content-type"]
293
+ when "audio/midi","audio/mid","audio/x-midi","audio/x-mid"
294
+ @wurfl["downloadfun"]["ringtone_midi_monophonic"] = true
295
+ when "audio/imelody","audio/x-imy","text/x-iMelody","text/iMelody","text/x-imelody"
296
+ @wurfl["downloadfun"]["ringtone_imelody"] = true
297
+ else
298
+ $stderr.puts "CcppAccept unknown download fun audio Content-Type: #{val["content-type"]}"
299
+ end
300
+
301
+ if val.key?("voices")
302
+ set_value_if_greater(@wurfl["sound_format"],"voices",val["voices"].to_i)
303
+ # determine if it has multiple voices and does midi to set
304
+ # the polyphonic value
305
+ if val["voices"].to_i > 1 && val["content-type"] =~ /midi/
306
+ @wurfl["downloadfun"]["ringtone_midi_polyphonic"] = true
307
+ @wurfl["sound_format"]["midi_polyphonic"] = true
308
+ end
309
+ end
310
+ if val.key?("size")
311
+ set_value_if_greater(@wurfl["downloadfun"],"ringtone_size_limit",val["size"].to_i)
312
+ end
313
+
314
+ when "picture"
315
+ #application/x-mmc.picture;Content-Type=image/bmp;size=25600;color=8;h=120;w=136
316
+ #application/x-mmc.picture;Content-Type=image/bmp;size=38000;color=16M;h=96;w=128
317
+ #application/x-mmc.picture;Content-Type=image/gif;size=16000;color=256;h=96;w=128
318
+ #application/x-mmc.picture;Content-Type=image/vnd.wap.wbmp;size=25600;gray=1;h=120;w=136
319
+ #application/x-mmc.picture;Content-Type=image/wbmp;size=2000;gray=1;h=96;w=128
320
+ @wurfl["downloadfun"]["picture"] = true
321
+ case val["content-type"]
322
+ when "image/bmp","image/x-bmp"
323
+ @wurfl["downloadfun"]["picture_bmp"] = true
324
+ when "image/gif"
325
+ @wurfl["downloadfun"]["picture_gif"] = true
326
+ when /wbmp/
327
+ @wurfl["downloadfun"]["picture_wbmp"] = true
328
+ when "image/jpeg","image/jpg"
329
+ @wurfl["downloadfun"]["picture_jpg"] = true
330
+ when "image/png"
331
+ @wurfl["downloadfun"]["picture_png"] = true
332
+ else
333
+ $stderr.puts "CcppAccept unknown download fun picture content-type: #{val["content-type"]}"
334
+ end
335
+
336
+ if val.key?("gray")
337
+ @wurfl["downloadfun"]["picture_greyscale"] = true
338
+ end
339
+ if val.key?("h")
340
+ set_value_if_greater(@wurfl["downloadfun"],"picture_height",val["h"].to_i)
341
+ end
342
+ if val.key?("w")
343
+ set_value_if_greater(@wurfl["downloadfun"],"picture_width",val["w"].to_i)
344
+ end
345
+ if val.key?("size")
346
+ set_value_if_greater(@wurfl["downloadfun"],"picture_size_limit",val["size"].to_i)
347
+ end
348
+ if val.key?("color")
349
+ val["color"] = convert_download_fun_color(val["color"])
350
+ set_value_if_greater(@wurfl["downloadfun"],"picture_colors",val["color"].to_i)
351
+ end
352
+ when "screensaver"
353
+ #application/x-mmc.screensaver;Content-Type=image/png;size=25600;color=8;h=120;w=136
354
+ #application/x-mmc.screensaver;Content-Type=image/png;size=32000;color=16M;h=96;w=128
355
+ @wurfl["downloadfun"]["screensaver"] = true
356
+ case val["content-type"]
357
+ when "image/bmp","image/x-bmp"
358
+ @wurfl["downloadfun"]["screensaver_bmp"] = true
359
+ when "image/gif"
360
+ @wurfl["downloadfun"]["screensaver_gif"] = true
361
+ when /wbmp/
362
+ @wurfl["downloadfun"]["screensaver_wbmp"] = true
363
+ when "image/jpeg","image/jpg"
364
+ @wurfl["downloadfun"]["screensaver_jpg"] = true
365
+ when "image/png"
366
+ @wurfl["downloadfun"]["screensaver_png"] = true
367
+ else
368
+ $stderr.puts "CcppAccept unknown download fun screensaver content-type: #{val["content-type"]}"
369
+ end
370
+
371
+ if val.key?("gray")
372
+ @wurfl["downloadfun"]["screensaver_greyscale"] = true
373
+ end
374
+ if val.key?("h")
375
+ set_value_if_greater(@wurfl["downloadfun"],"screensaver_height",val["h"].to_i)
376
+ end
377
+ if val.key?("w")
378
+ set_value_if_greater(@wurfl["downloadfun"],"screensaver_width",val["w"].to_i)
379
+ end
380
+ if val.key?("size")
381
+ set_value_if_greater(@wurfl["downloadfun"],"screensaver_size_limit",val["size"].to_i)
382
+ end
383
+ if val.key?("color")
384
+ val["color"] = convert_download_fun_color(val["color"])
385
+ set_value_if_greater(@wurfl["downloadfun"],"screensaver_colors",val["color"].to_i)
386
+ end
387
+ when "wallpaper"
388
+ #application/x-mmc.wallpaper;Content-Type=image/bmp;size=38000;color=16M;h=96;w=128
389
+ #application/x-mmc.wallpaper;Content-Type=image/vnd.wap.wbmp;size=10240;gray=1;h=120;w=136
390
+ #application/x-mmc.wallpaper;Content-Type=image/wbmp;size=2000;gray=1;h=96;w=128
391
+ #application/x-mmc.wallpaper;type=image/bmp;size=2000;gray=1;w=101;h=64
392
+ @wurfl["downloadfun"]["wallpaper"] = true
393
+ case val["content-type"]
394
+ when "image/bmp","image/x-bmp"
395
+ @wurfl["downloadfun"]["wallpaper_bmp"] = true
396
+ when "image/gif"
397
+ @wurfl["downloadfun"]["wallpaper_gif"] = true
398
+ when /wbmp/
399
+ @wurfl["downloadfun"]["wallpaper_wbmp"] = true
400
+ when "image/jpeg","image/jpg"
401
+ @wurfl["downloadfun"]["wallpaper_jpg"] = true
402
+ when "image/png"
403
+ @wurfl["downloadfun"]["wallpaper_png"] = true
404
+ else
405
+ $stderr.puts "CcppAccept unknown download fun wallpaper content-type: #{val["content-type"]}"
406
+ end
407
+
408
+ if val.key?("gray")
409
+ @wurfl["downloadfun"]["wallpaper_greyscale"] = true
410
+ end
411
+ if val.key?("h")
412
+ set_value_if_greater(@wurfl["downloadfun"],"wallpaper_height",val["h"].to_i)
413
+ end
414
+ if val.key?("w")
415
+ set_value_if_greater(@wurfl["downloadfun"],"wallpaper_width",val["w"].to_i)
416
+ end
417
+ if val.key?("size")
418
+ set_value_if_greater(@wurfl["downloadfun"],"wallpaper_size_limit",val["size"].to_i)
419
+ end
420
+ if val.key?("color")
421
+ val["color"] = convert_download_fun_color(val["color"])
422
+ set_value_if_greater(@wurfl["downloadfun"],"wallpaper_colors",val["color"].to_i)
423
+ end
424
+
425
+ else
426
+ $stderr.puts "CcppAccept unknown download fun accept Object-Type: #{type}"
427
+ end
428
+
429
+ when "application/x-NokiaGameData"
430
+ when "application/x-up-alert"
431
+ when "application/x-up-cacheop"
432
+ when "application/x-up-device"
433
+ when "image/vnd.nok-wallpaper"
434
+ when "image/vnd.wap.wml"
435
+ when "image/vnd.wap.wmlscript"
436
+ # the two above seem like errors
437
+ when "image/x-MS-bmp"
438
+ when "image/x-up-wpng"
439
+ when "image/x-xbitmap"
440
+ when "text/css"
441
+ when "text/html"
442
+ when "text/vnd.sun.j2me.app-descriptor"
443
+ # Andrea: this means the device can download jad (J2ME)
444
+ when "text/vnd.wap.co"
445
+ when "text/vnd.wap.si"
446
+ when "text/vnd.wap.sl"
447
+ # can these be used to determine about WAP Push SI and SL styles?
448
+ # Andrea: These should be valid to set the values for
449
+ # Andrea: connectionoriented_<push>. I will need to check better,
450
+ # Andrea: but from what I can remember, if connectionoriented is
451
+ # Andrea: supported, connectionless should be supported too.
452
+ when "text/vnd.wap.wml"
453
+ when "text/vnd.wap.wmlc"
454
+ when "text/vnd.wap.wmlscript"
455
+ when "text/vnd.wap.wmlscriptc"
456
+ when "text/x-co-desc"
457
+ when "text/x-hdml"
458
+ when "text/xml"
459
+ when "text/x-wap.wml"
460
+ when "video/x-mng"
461
+ when "image/*"
462
+ when "*/*"
463
+ else
464
+ $stderr.puts "CcppAccept unknown accept type: #{type}"
465
+ end
466
+ end
467
+ end
468
+
469
+ def CcppAccept_Charset(element)
470
+ end
471
+
472
+ def CcppAccept_Encoding(element)
473
+ end
474
+
475
+ def CcppAccept_Language(element)
476
+ end
477
+
478
+ def DownloadableSoftwareSupport(element)
479
+ #=> "bagMapping"
480
+ end
481
+
482
+ def JavaEnabled(element)
483
+ #=> "j2me",
484
+ end
485
+
486
+ def JavaPlatform(element)
487
+ items = get_items_from_bag(element)
488
+ items.each do |platform|
489
+ # Cheat and ignore the Versions for now
490
+ case platform
491
+ when /CLDC/i
492
+ @wurfl["j2me"]["cldc_10"] = true
493
+ when /MIDP/i
494
+ @wurfl["j2me"]["midp_10"] = true
495
+ when /Pjava/i
496
+ @wurfl["j2me"]["personal_java"] = true
497
+ else
498
+ $stderr.puts "JavaPlatform Mapping unknown for: #{platform}"
499
+ end
500
+ end
501
+ end
502
+
503
+ def JVMVersion(element)
504
+ end
505
+
506
+ def MExEClassmarks(element)
507
+ #has some interesting possibilitesfor matching MIDP/WAP Java...
508
+ end
509
+
510
+ def MexeSpec(element)
511
+ end
512
+
513
+ def MexeSecureDomains(element)
514
+ end
515
+
516
+ def OSName(element)
517
+ end
518
+
519
+ def OSVendor(element)
520
+ end
521
+
522
+ def RecipientAppAgent(element)
523
+ end
524
+
525
+ def SoftwareNumber(element)
526
+ end
527
+
528
+ def VideoInputEncoder(element)
529
+ end
530
+
531
+ def Email_URI_Schemes(element)
532
+ end
533
+
534
+ def JavaPackage(element)
535
+ $stderr.puts "JavaPackage:#{element.text}"
536
+ # Would show the Motorola extension etc???
537
+ end
538
+
539
+ def JavaProtocol(element)
540
+ # Perhaps details SMS support etc?
541
+ $stderr.puts "JavaProtocol:#{element.text}"
542
+ end
543
+
544
+ def CLIPlatform(element)
545
+ end
546
+
547
+ ############### NetworkCharacteristics
548
+ def SupportedBluetoothVersion(element)
549
+ end
550
+
551
+ def CurrentBearerService(element)
552
+ end
553
+
554
+ def SecuritySupport(element)
555
+ items = get_items_from_bag(element)
556
+ items.each do |secure|
557
+ if /WTLS/.match(secure)
558
+ #check and just assume that this means https?
559
+ #@wurfl["security"]["https_support"] = true
560
+ end
561
+ end
562
+ end
563
+
564
+ def SupportedBearers(element)
565
+ end
566
+
567
+ ############### BrowserUA
568
+
569
+ # These two can sometimes make the user agent?
570
+ def BrowserName(element)
571
+ @wurfl["user_agent"]<< element.text
572
+ end
573
+
574
+ def BrowserVersion(element)
575
+ @wurfl["user_agent"]<< element.text
576
+ end
577
+
578
+ def DownloadableBrowserApps(element)
579
+ # This might have some good information to work with
580
+ end
581
+
582
+ def HtmlVersion(element)
583
+ version = element.text.to_i
584
+ if version == 4
585
+ @wurfl["markup"]["html4"] = true
586
+ elsif version < 4 && version >= 3
587
+ @wurfl["markup"]["html32"] = true
588
+ else
589
+ $stderr.puts "HtmlVersion unknown version mapping:#{version}"
590
+ end
591
+ end
592
+
593
+ def JavaAppletEnabled(element)
594
+ end
595
+
596
+ def JavaScriptEnabled(element)
597
+ end
598
+
599
+ def JavaScriptVersion(element)
600
+ end
601
+
602
+ def PreferenceForFrames(element)
603
+ end
604
+
605
+ def TablesCapable(element)
606
+ value = convert_value(element.text)
607
+ @wurfl["wml_ui"]["table_support"] = value
608
+ end
609
+
610
+ def XhtmlVersion(element)
611
+ version = element.text.to_i
612
+ if version >= 1
613
+ if version != 1
614
+ $stderr.puts "XhtmlVersion that might map to a new WURFL trait. Version:#{version}"
615
+ end
616
+ @wurfl["markup"]["xhtml_basic"] = true
617
+ end
618
+ end
619
+
620
+ def XhtmlModules(element)
621
+ #What does the mobile profile module look like?
622
+ $stderr.puts "XhtmlModules items are:"
623
+ items = get_items_from_bag(element)
624
+ items.each do |mods|
625
+ $stderr.puts "XhtmlModules item: #{mods}"
626
+ if mods =~ /mobile*profile/i
627
+ #Wow this worked?!
628
+ @wurfl["markup"]["xhtml_mobileprofile"] = true
629
+ end
630
+ end
631
+ end
632
+
633
+ ################# WapCharacteristics
634
+ def SupportedPictogramSet(element)
635
+ # There could be WAP ones, but no list?
636
+ #=> "chtml_ui/emoji",
637
+ end
638
+
639
+ def WapDeviceClass(element)
640
+ end
641
+
642
+ def WapVersion(element)
643
+ end
644
+
645
+ def WmlDeckSize(element)
646
+ @wurfl["storage"]["max_deck_size"] = element.text.to_i
647
+ end
648
+
649
+ def WmlScriptLibraries(element)
650
+ end
651
+
652
+ def WmlScriptVersion(element)
653
+ items = get_items_from_bag(element)
654
+ items.each do |version|
655
+ case version
656
+ when "1.0"
657
+ @wurfl["markup"]["wmlscript10"] = true
658
+ when "1.1"
659
+ @wurfl["markup"]["wmlscript11"] = true
660
+ when /1\.2/i
661
+ @wurfl["markup"]["wmlscript12"] = true
662
+ else
663
+ $stderr.puts "WmlScriptVersion unknown version mapping: #{version}"
664
+ end
665
+ end
666
+ end
667
+
668
+ def WmlVersion(element)
669
+ items = get_items_from_bag(element)
670
+ items.each do |version|
671
+ case version
672
+ when "1.0"
673
+ # It appears we do not care about this one
674
+ when "1.1"
675
+ @wurfl["markup"]["wml_11"] = true
676
+ when "1.2"
677
+ @wurfl["markup"]["wml_12"] = true
678
+ when "1.3"
679
+ @wurfl["markup"]["wml_13"] = true
680
+ else
681
+ $stderr.puts "WmlVersion unknown version mapping: #{version}"
682
+ end
683
+ end
684
+ end
685
+
686
+ #Conversions needed on Bag
687
+ def WtaiLibraries(element)
688
+ items = get_items_from_bag(element)
689
+ items.each do |lib|
690
+ case lib
691
+ when "WTAVoiceCall"
692
+ @wurfl["wta"]["wta_voice_call"] = true
693
+ when "WTANetText"
694
+ @wurfl["wta"]["wta_net_text"] = true
695
+ when "WTAPhoneBook"
696
+ @wurfl["wta"]["wta_phonebook"] = true
697
+ when "WTACallLog"
698
+ @wurfl["wta"]["wta_call_log"] = true
699
+ when "WTAMisc"
700
+ @wurfl["wta"]["wta_misc"] = true
701
+ when "WTAGSM"
702
+ @wurfl["wta"]["wta_gsm"] = true
703
+ when "WTAIS136"
704
+ @wurfl["wta"]["wta_is136"] = true
705
+ when "WTAPDC"
706
+ @wurfl["wta"]["wta_pdc"] = true
707
+ when "AddPBEntry"
708
+ @wurfl["wta"]["wta_phonebook"] = true
709
+ when "MakeCall"
710
+ @wurfl["wta"]["nokia_voice_call"] = true
711
+ when "WTAIGSM"
712
+ @wurfl["wta"]["wta_gsm"] = true
713
+ when "WTAIPublic.makeCall"
714
+ @wurfl["wta"]["nokia_voice_call"] = true
715
+ when "WTA.Public.addPBEntry"
716
+ @wurfl["wta"]["wta_phonebook"] = true
717
+ when "WTA.Public.makeCall"
718
+ @wurfl["wta"]["nokia_voice_call"] = true
719
+ when "WTAPublic.makeCall"
720
+ @wurfl["wta"]["nokia_voice_call"] = true
721
+ when "SendDTMF","WTA.Public.sendDTMF"
722
+ # Not in WURFL
723
+ when "WTAPublic"
724
+ # Not enough information
725
+ else
726
+ $stderr.puts "WtaiLibraries unknown mapping: #{lib}"
727
+ end
728
+ end
729
+ end
730
+
731
+ def WtaVersion(element)
732
+ end
733
+
734
+ # add the proposals to WURFL for download methods
735
+ def DrmClass(element)
736
+ #=> ["drm/OMAv1_forward-lock","drm/OMAv1_combined_delivery","drm/OMAv1_separate_delivery"],
737
+ end
738
+ def DrmConstraints(element)
739
+ end
740
+ def OmaDownload(element)
741
+ # "download_methods/OMAv1_download"
742
+ end
743
+
744
+ ############### PushCharacteristics
745
+ def Push_Accept(element)
746
+ set_wap_push
747
+ items = get_items_from_bag(element)
748
+ items.each do |type|
749
+ $stderr.puts "Push_Accept unknown type: #{type}"
750
+ end
751
+ end
752
+
753
+ def Push_Accept_Charset(element)
754
+ set_wap_push
755
+ items = get_items_from_bag(items)
756
+ items.each do |charset|
757
+ if charset =~ /utf8/i
758
+ @wurfl["wap_push"]["utf8_support"] = true
759
+ elsif charset =~ /iso8859/i
760
+ @wurfl["wap_push"]["iso8859_support"] = true
761
+ end
762
+ end
763
+ end
764
+ def Push_Accept_Encoding(element)
765
+ set_wap_push
766
+ end
767
+ def Push_Accept_Language(element)
768
+ set_wap_push
769
+ end
770
+ def Push_Accept_AppID(element)
771
+ set_wap_push
772
+ #!! maps to confirmed and unconfirmed service indication/loads? !!
773
+ end
774
+ def Push_MsgSize(element)
775
+ set_wap_push
776
+ # Feels like the WURFL PUSH data is lacking in some items
777
+ end
778
+ def Push_MaxPushReq(element)
779
+ set_wap_push
780
+ end
781
+
782
+ #Need MMS Mappings taken from Siemens example
783
+ ############MmsCharacteristics
784
+ def MmsMaxMessageSize(element)
785
+ size = element.text.to_i
786
+ @wurfl["mms"]["mms_max_size"] = size
787
+ end
788
+
789
+ def MmsMaxImageResolution(element)
790
+ width,height = break_num_x_num(element.text)
791
+ @wurfl["mms"]["mms_max_width"] = width
792
+ @wurfl["mms"]["mms_max_height"] = height
793
+ end
794
+
795
+ def MmsCcppAccept(element)
796
+ items = get_items_from_bag(element)
797
+ items.each do |type|
798
+ case type
799
+ when "image/jpeg","image/jpg"
800
+ @wurfl["mms"]["mms_jpeg_baseline"] = true
801
+ #what about progressive?
802
+ # Andrea: is there any way to determine from the content type?
803
+ when "image/gif"
804
+ @wurfl["mms"]["mms_gif_static"] = true
805
+ #animated?
806
+ when "image/vnd.wap.wbmp"
807
+ @wurfl["mms"]["mms_wbmp"] = true
808
+ when "image/bmp"
809
+ @wurfl["mms"]["mms_bmp"] = true
810
+ when "image/png"
811
+ @wurfl["mms"]["mms_png"] = true
812
+ when "application/smil"
813
+ when "application/x-sms"
814
+ when "application/vnd.3gpp.sms"
815
+ ### Where is the SMAF in MMS of WURFL?###
816
+ # Andrea: we had never found a device supporting SMAF and MMS
817
+ # Andrea: should be added
818
+ when "application/vnd.smaf"
819
+ when "application/x-smaf"
820
+ when "audio/amr","audio/x-amr"
821
+ @wurfl["mms"]["mms_amr"] = true
822
+ when "audio/midi","audio/mid","audio/x-midi","audio/x-mid"
823
+ @wurfl["mms"]["mms_midi_monophonic"] = true
824
+ # We can play it safe an say mono. what about poly?
825
+ when "audio/sp-midi"
826
+ @wurfl["mms"]["mms_spmidi"] = true
827
+ when "audio/wav","audio/x-wav","application/wav","application/x-wav"
828
+ @wurfl["mms"]["mms_wav"] = true
829
+ when "text/plain"
830
+ when "text/x-vCard","text/x-vcard"
831
+ @wurfl["mms"]["mms_vcard"] = true
832
+ when "application/vnd.nokia.ringing-tone"
833
+ @wurfl["mms"]["mms_nokia_ringingtone"] = true
834
+ when "image/vnd.nok-wallpaper"
835
+ @wurfl["mms"]["mms_nokia_wallpaper"] = true
836
+ when "audio/x-beatnik-rmf","audio/x-rmf","audio/rmf"
837
+ @wurfl["mms"]["mms_rmf"] = true
838
+ when "application/vnd.symbian.install"
839
+ @wurfl["mms"]["mms_symbian_install"] = true
840
+ when "application/java-archive","application/x-java-archive"
841
+ @wurfl["mms"]["mms_jar"] = true
842
+ when "text/vnd.sun.j2me.app-descriptor"
843
+ @wurfl["mms"]["mms_jad"] = true
844
+ when "application/vnd.wap.wmlc"
845
+ @wurfl["mms"]["mms_wmlc"] = true
846
+ when "text/x-vCalendar"
847
+ when "application/vnd.wap.mms-message"
848
+ when "application/vnd.wap.multipart.mixed"
849
+ when "application/vnd.wap.multipart.related"
850
+ else
851
+ $stderr.puts "MmsCcppAccept unknown accept type: #{type}"
852
+ end
853
+ end
854
+ end
855
+
856
+ def MmsCcppAcceptCharset(element)
857
+ end
858
+
859
+ def MmsVersion(element)
860
+ end
861
+
862
+ ############### Extra Components found from running on profs
863
+ def BluetoothProfile(element)
864
+ end
865
+
866
+ def FramesCapable(element)
867
+ end
868
+
869
+ def OSVersion(element)
870
+ end
871
+
872
+ def MmsCcppAcceptEncoding(element)
873
+ end
874
+
875
+ def MmsCcppAcceptLanguage(element)
876
+ end
877
+
878
+ def MmsMaxAudio(element)
879
+ end
880
+
881
+ def MmsMaxComponents(element)
882
+ end
883
+
884
+ def MmsMaxImage(element)
885
+ # examples have Values of -1...
886
+ end
887
+
888
+ def MmsMaxText(element)
889
+ end
890
+
891
+ def WapPushMsgPriority(element)
892
+ end
893
+
894
+ def WapPushMsgSize(element)
895
+ end
896
+
897
+ def WapSupportedApplications(element)
898
+ end
899
+
900
+
901
+ ############## Alias to methods already defined.
902
+ alias :AudioInputEncorder :AudioInputEncoder
903
+ alias :MexeClassmark :MExEClassmarks
904
+ alias :MexeClassmarks :MExEClassmarks
905
+ alias :MmsCcppAccept_Charset :MmsCcppAcceptCharset
906
+ alias :MmsCcppAcceptCharSet :MmsCcppAcceptCharset
907
+ alias :OutputCharset :OutputCharSet
908
+ alias :PixelsAspectRatio :PixelAspectRatio
909
+ alias :SofwareNumber :SoftwareNumber
910
+ alias :SupportedBearer :SupportedBearers
911
+ alias :TableCapable :TablesCapable
912
+ alias :WmlscriptLibraries :WmlScriptLibraries
913
+ alias :wtaVersion :WtaVersion
914
+
915
+
916
+ #############################################################
917
+ # Utility methods
918
+ #############################################################
919
+
920
+ def set_wap_push
921
+ # if Push items exist then set wap_push/wap_push_support = true
922
+ @wurfl["wap_push"]["wap_push_support"] = true
923
+ end
924
+
925
+ # escape the passed method name to something valid for Ruby
926
+ def make_method_name(method)
927
+ # should do more, but will add them as errors occur
928
+ method.gsub(/-/,"_")
929
+ end
930
+
931
+ def break_num_x_num(val)
932
+ width = height = 0
933
+ if m = /(\d*)x(\d*)/.match(val)
934
+ width, height = m[1],m[2]
935
+ end
936
+ return width.to_i,height.to_i
937
+ end
938
+
939
+ def get_items_from_bag(element)
940
+ items = Array.new
941
+ return items if element.nil?
942
+ element.elements.each("rdf:Bag/rdf:li") do |se|
943
+ items<< se.text
944
+ end
945
+ return items
946
+ end
947
+
948
+ # used to convert Yes/No to true false
949
+ def convert_value(value)
950
+ if value =~ /Yes/i
951
+ return true
952
+ elsif value =~ /No/i
953
+ return false
954
+ end
955
+ begin
956
+ # try to convert to an integer
957
+ return value.to_i
958
+ rescue
959
+ end
960
+ # just leave it alone
961
+ return value
962
+ end
963
+
964
+ def set_value_if_greater(wurflhash,key,value)
965
+ if wurflhash.key?(key)
966
+ if value.is_a?(Fixnum)
967
+ if wurflhash[key] < value
968
+ wurflhash[key] = value
969
+ end
970
+ else
971
+ # Should probably just overwrite the entry then.
972
+ $stderr.puts "set_value_if_greater called with something that is not a number.Key:#{key};Value:#{value}"
973
+ end
974
+ else
975
+ # it is not set so set it
976
+ wurflhash[key] = value
977
+ end
978
+ end
979
+
980
+ def convert_download_fun_color(color)
981
+ res = color
982
+ if color =~ /M$/i
983
+ # multiply it by a million
984
+ res = color.to_i * 1000000
985
+ elsif color =~ /K$"/i
986
+ # multiply it by ten thousand
987
+ res = color.to_i * 10000
988
+ end
989
+ return res
990
+ end
991
+
992
+ def parse_download_fun_accept(accept)
993
+ #application/x-mmc.object_type;content-type=format;size=n;other=y
994
+ m = /application\/x-mmc\.(.*);(content-)?type=(.*);size=(\d*);(.*)/i.match(accept)
995
+ return nil if m.nil? # no match
996
+
997
+ res = Hash.new
998
+ res["object-type"] = m[1]
999
+ res["content-type"] = m[3]
1000
+ res["size"] = m[4]
1001
+ if m[5]
1002
+ others = m[5].split(";")
1003
+ others.each do |keypair|
1004
+ key,value = keypair.split("=")
1005
+ res[key] = value
1006
+ end
1007
+ end
1008
+
1009
+ return res
1010
+ end
1011
+
1012
+ end
1013
+