wurfl 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+