Package pywurfl :: Package algorithms :: Package wurfl :: Module handlers
[hide private]
[frames] | no frames]

Source Code for Module pywurfl.algorithms.wurfl.handlers

  1  # pywurfl - Wireless Universal Resource File Tools in Python 
  2  # Copyright (C) 2006-2010 Armand Lynch 
  3  # 
  4  # This library is free software; you can redistribute it and/or modify it 
  5  # under the terms of the GNU Lesser General Public License as published by the 
  6  # Free Software Foundation; either version 2.1 of the License, or (at your 
  7  # option) any later version. 
  8  # 
  9  # This library is distributed in the hope that it will be useful, but WITHOUT 
 10  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 11  # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 
 12  # details. 
 13  # 
 14  # You should have received a copy of the GNU Lesser General Public License 
 15  # along with this library; if not, write to the Free Software Foundation, Inc., 
 16  # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 17  # 
 18  # Armand Lynch <lyncha@users.sourceforge.net> 
 19   
 20  __doc__ = """ 
 21  This module contains the supporting classes for the Two Step Analysis user agent 
 22  algorithm that is used as the primary way to match user agents with the Java API 
 23  for the WURFL. 
 24   
 25  A description of the way the following source is intended to work can be found 
 26  within the source for the original Java API implementation here: 
 27  http://sourceforge.net/projects/wurfl/files/WURFL Java API/ 
 28   
 29  The original Java code is GPLd and Copyright (c) 2008-2009 WURFL-Pro srl 
 30  """ 
 31   
 32  __author__ = "Armand Lynch <lyncha@users.sourceforge.net>" 
 33  __copyright__ = "Copyright 2010, Armand Lynch" 
 34  __license__ = "LGPL" 
 35  __url__ = "http://celljam.net/" 
 36  __version__ = "1.0.1" 
 37   
 38  import re 
 39   
 40  from pywurfl.algorithms.wurfl import utils 
 41  from pywurfl.algorithms.wurfl import normalizers 
 42  from pywurfl.algorithms.wurfl.strategies import ld_match, ris_match 
 43   
 44   
 45  uiol = utils.indexof_or_length 
 46  uoi = utils.ordinal_index 
47 48 49 -class AbstractMatcher(object):
50 user_agent_map = {} 51
52 - def __init__(self, normalizer=None):
53 if normalizer is None: 54 self.normalizer = lambda x: x 55 else: 56 self.normalizer = normalizer 57 self.known_user_agents = set()
58
59 - def add(self, user_agent, wurfl_id):
60 self.known_user_agents.add(user_agent) 61 self.user_agent_map[user_agent] = wurfl_id
62 63 @property
64 - def user_agents(self):
65 return sorted(self.known_user_agents)
66
67 - def can_handle(self, user_agent):
68 raise NotImplementedError
69
70 - def __call__(self, user_agent):
71 devid = self.conclusive_match(user_agent) 72 if not devid or devid == u"generic": 73 devid = self.recovery_match(user_agent) 74 if not devid or devid == u"generic": 75 devid = self.catch_all_recovery_match(user_agent) 76 return devid
77
78 - def conclusive_match(self, user_agent):
79 user_agent = self.normalizer(user_agent) 80 match = self.look_for_matching_user_agent(user_agent) 81 #print "%s -> conclusive_match -> %s" % (user_agent, match) 82 devid = self.user_agent_map.get(match, u"generic") 83 return devid
84
85 - def look_for_matching_user_agent(self, user_agent):
86 tolerance = utils.first_slash(user_agent) 87 #print "AbstractMatcher tolerance %s" % tolerance 88 match = ris_match(self.user_agents, user_agent, tolerance) 89 #print "AbstractMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 90 return match
91
92 - def recovery_match(self, user_agent):
93 return u"generic"
94 95 recovery_map = ( 96 # Openwave 97 (u"UP.Browser/7.2", u"opwv_v72_generic"), 98 (u"UP.Browser/7", u"opwv_v7_generic"), 99 (u"UP.Browser/6.2", u"opwv_v62_generic"), 100 (u"UP.Browser/6", u"opwv_v6_generic"), 101 (u"UP.Browser/5", u"upgui_generic"), 102 (u"UP.Browser/4", u"uptext_generic"), 103 (u"UP.Browser/3", u"uptext_generic"), 104 105 # Series 60 106 (u"Series60", u"nokia_generic_series60"), 107 108 # Access/Net Front 109 (u"NetFront/3.0", u"netfront_ver3"), 110 (u"ACS-NF/3.0", u"netfront_ver3"), 111 (u"NetFront/3.1", u"netfront_ver3_1"), 112 (u"ACS-NF/3.1", u"netfront_ver3_1"), 113 (u"NetFront/3.2", u"netfront_ver3_2"), 114 (u"ACS-NF/3.2", u"netfront_ver3_2"), 115 (u"NetFront/3.3", u"netfront_ver3_3"), 116 (u"ACS-NF/3.3", u"netfront_ver3_3"), 117 (u"NetFront/3.4", u"netfront_ver3_4"), 118 (u"NetFront/3.5", u"netfront_ver3_5"), 119 120 # Windows CE 121 (u"Windows CE", u"ms_mobile_browser_ver1"), 122 123 # web browsers? 124 (u"Mozilla/4.0", u"generic_web_browser"), 125 (u"Mozilla/5.0", u"generic_web_browser"), 126 (u"Mozilla/5.0", u"generic_web_browser"), 127 128 # Generic XHTML 129 (u"Mozilla/", u"generic_xhtml"), 130 (u"ObigoInternetBrowser/Q03C", u"generic_xhtml"), 131 (u"AU-MIC/2", u"generic_xhtml"), 132 (u"AU-MIC-", u"generic_xhtml"), 133 (u"AU-OBIGO/", u"generic_xhtml"), 134 (u"Obigo/Q03", u"generic_xhtml"), 135 (u"Obigo/Q04", u"generic_xhtml"), 136 (u"ObigoInternetBrowser/2", u"generic_xhtml"), 137 (u"Teleca Q03B1", u"generic_xhtml"), 138 139 # Opera Mini 140 (u"Opera Mini/1", u"opera_mini_ver1"), 141 (u"Opera Mini/2", u"opera_mini_ver2"), 142 (u"Opera Mini/3", u"opera_mini_ver3"), 143 (u"Opera Mini/4", u"opera_mini_ver4"), 144 145 # DoCoMo 146 (u"DoCoMo", u"docomo_generic_jap_ver1"), 147 (u"KDDI", u"docomo_generic_jap_ver1")) 148
149 - def catch_all_recovery_match(self, user_agent):
150 151 match = u"generic" 152 for partial_agent, wdevice in self.recovery_map: 153 if partial_agent in user_agent: 154 match = wdevice 155 break 156 return match
157
158 159 -class AlcatelMatcher(AbstractMatcher):
160 - def can_handle(self, user_agent):
161 return (user_agent.startswith(u"Alcatel") or 162 user_agent.startswith(u"ALCATEL"))
163
164 165 -class AndroidMatcher(AbstractMatcher):
166 - def can_handle(self, user_agent):
167 return u"Android" in user_agent
168
169 - def look_for_matching_user_agent(self, user_agent):
170 tolerance = uiol(user_agent, u" ", 171 start_index=uiol(user_agent, u"Android")) 172 match = ris_match(self.user_agents, user_agent, tolerance) 173 #print "AndroidMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 174 return match
175
176 - def recovery_match(self, user_agent):
177 return u"generic_android"
178
179 180 -class AOLMatcher(AbstractMatcher):
181 - def can_handle(self, user_agent):
182 return not utils.is_mobile_browser(user_agent) and u"AOL" in user_agent
183
184 185 -class AppleMatcher(AbstractMatcher):
186 APPLE_LD_TOLERANCE = 5 187
188 - def can_handle(self, user_agent):
189 return (u"iPhone" in user_agent or u"iPod" in user_agent or u"iPad" in 190 user_agent)
191
192 - def look_for_matching_user_agent(self, user_agent):
193 tolerance = utils.first_semi_colon(user_agent) 194 match = ld_match(self.user_agents, user_agent, tolerance) 195 #print "AppleMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 196 return match
197
198 - def recovery_match(self, user_agent):
199 if u"iPad" in user_agent: 200 return "apple_ipad_ver1" 201 if u"iPod" in user_agent: 202 return u"apple_ipod_ver1" 203 return u"apple_iphone_ver1"
204
205 206 -class BenQMatcher(AbstractMatcher):
207 - def can_handle(self, user_agent):
208 return user_agent.startswith(u"BENQ") or user_agent.startswith(u"BenQ")
209
210 211 -class BlackberryMatcher(AbstractMatcher):
212 blackberries = {} 213 blackberries["2."] = u"blackberry_generic_ver2" 214 blackberries["3.2"] = u"blackberry_generic_ver3_sub2" 215 blackberries["3.3"] = u"blackberry_generic_ver3_sub30" 216 blackberries["3.5"] = u"blackberry_generic_ver3_sub50" 217 blackberries["3.6"] = u"blackberry_generic_ver3_sub60" 218 blackberries["3.7"] = u"blackberry_generic_ver3_sub70" 219 blackberries["4."] = u"blackberry_generic_ver4" 220
221 - def can_handle(self, user_agent):
222 return u"BlackBerry" in user_agent
223
224 - def recovery_match(self, user_agent):
225 match = u"generic" 226 227 if user_agent.startswith(u"BlackBerry"): 228 version = self.get_version(user_agent) 229 match = self.blackberries.get(version, u"generic") 230 231 return match
232
233 - def get_version(self, user_agent):
234 version = u"" 235 position = user_agent.index('/') 236 if position + 4 < len(user_agent): 237 version = user_agent[position+1:position+4] 238 return version
239
240 241 -class BotMatcher(AbstractMatcher):
242 bots = (u"bot", u"crawler", u"spider", u"novarra", u"transcoder", 243 u"yahoo! searchmonkey", u"yahoo! slurp", u"feedfetcher-google", 244 u"toolbar", u"mowser") 245 246 BOT_TOLERANCE = 4 247
248 - def can_handle(self, user_agent):
249 user_agent = user_agent.lower() 250 for bot in self.bots: 251 if bot in user_agent: 252 return True 253 return False
254
255 - def look_for_matching_user_agent(self, user_agent):
256 match = ld_match(self.user_agents, user_agent, self.BOT_TOLERANCE) 257 return match
258
259 - def recovery_match(self, user_agent):
260 return u"generic_web_crawler"
261
262 263 -class CatchAllMatcher(AbstractMatcher):
264 MOZILLA_LD_TOLERANCE = 4 265
266 - def can_handle(self, user_agent):
267 return True
268
269 - def look_for_matching_user_agent(self, user_agent):
270 if user_agent.startswith(u"Mozilla"): 271 if user_agent.startswith(u"Mozilla/4"): 272 match = ld_match(self.extract_uas(u"Mozilla/4"), user_agent, 273 self.MOZILLA_LD_TOLERANCE) 274 elif user_agent.startswith(u"Mozilla/5"): 275 match = ld_match(self.extract_uas(u"Mozilla/5"), user_agent, 276 self.MOZILLA_LD_TOLERANCE) 277 else: 278 match = ld_match(self.extract_uas(u"Mozilla"), user_agent, 279 self.MOZILLA_LD_TOLERANCE) 280 else: 281 match = AbstractMatcher.look_for_matching_user_agent(self, 282 user_agent) 283 #print "CatchAllMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 284 return match
285
286 - def extract_uas(self, start):
287 return (x for x in self.user_agents if x.startswith(start))
288
289 290 -class ChromeMatcher(AbstractMatcher):
291 - def can_handle(self, user_agent):
292 return (not utils.is_mobile_browser(user_agent) and 293 u"Chrome" in user_agent)
294
295 296 -class DoCoMoMatcher(AbstractMatcher):
297 - def can_handle(self, user_agent):
298 return user_agent.startswith(u"DoCoMo")
299
300 - def look_for_matching_user_agent(self, user_agent):
301 return u""
302
303 - def recovery_match(self, user_agent):
304 if user_agent.startswith(u"DoCoMo/2"): 305 return u"docomo_generic_jap_ver2" 306 return u"docomo_generic_jap_ver1"
307
308 309 -class FirefoxMatcher(AbstractMatcher):
310 - def can_handle(self, user_agent):
311 return (not utils.is_mobile_browser(user_agent) and 312 u"Firefox" in user_agent)
313
314 315 -class GrundigMatcher(AbstractMatcher):
316 - def can_handle(self, user_agent):
317 return (user_agent.startswith(u"Grundig") or 318 user_agent.startswith(u"GRUNDIG"))
319
320 321 -class HTCMatcher(AbstractMatcher):
322 - def can_handle(self, user_agent):
323 return user_agent.startswith(u"HTC")
324
325 326 -class KDDIMatcher(AbstractMatcher):
327 - def can_handle(self, user_agent):
328 return u"KDDI" in user_agent
329
330 - def look_for_matching_user_agent(self, user_agent):
331 if user_agent.startswith(u"KDDI/"): 332 tolerance = utils.second_slash(user_agent) 333 elif user_agent.startswith(u"KDDI"): 334 tolerance = utils.first_slash(user_agent) 335 else: 336 tolerance = uiol(user_agent, ")") 337 338 match = ris_match(self.user_agents, user_agent, tolerance) 339 #print "KDDIMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 340 return match
341
342 - def recovery_match(self, user_agent):
343 if u"Opera" in user_agent: 344 return u"opera" 345 return u"opwv_v62_generic"
346
347 348 -class KonquerorMatcher(AbstractMatcher):
349 - def can_handle(self, user_agent):
350 return (not utils.is_mobile_browser(user_agent) and 351 u"Konqueror" in user_agent)
352
353 354 -class KyoceraMatcher(AbstractMatcher):
355 - def can_handle(self, user_agent):
356 return (user_agent.startswith(u"kyocera") or 357 user_agent.startswith(u"QC-") or 358 user_agent.startswith(u"KWC-"))
359
360 361 -class LGMatcher(AbstractMatcher):
362 - def can_handle(self, user_agent):
363 return (user_agent.startswith(u"lg") or u"LG-" in user_agent or 364 u"LGE" in user_agent)
365
366 - def look_for_matching_user_agent(self, user_agent):
367 if u"Vodafone" in user_agent: 368 tolerance = uiol(user_agent, u"LG") 369 elif user_agent.startswith(u"LGE/") or user_agent.startswith("LG/"): 370 tolerance = utils.second_slash(user_agent) 371 else: 372 tolerance = utils.first_slash(user_agent) 373 374 return ris_match(self.user_agents, user_agent, tolerance)
375
376 377 -class MitsubishiMatcher(AbstractMatcher):
378 - def can_handle(self, user_agent):
379 return user_agent.startswith(u"Mitsu")
380
381 382 -class MotorolaMatcher(AbstractMatcher):
383 MOTOROLA_TOLERANCE = 5 384
385 - def can_handle(self, user_agent):
386 return (user_agent.startswith(u"Mot-") or 387 u"MOT-" in user_agent or 388 u"Motorola" in user_agent)
389
390 - def look_for_matching_user_agent(self, user_agent):
391 if (user_agent.startswith(u"Mot-") or user_agent.startswith(u"MOT-") or 392 user_agent.startswith(u"Motorola")): 393 match = AbstractMatcher.look_for_matching_user_agent(self, 394 user_agent) 395 else: 396 match = ld_match(self.user_agents, user_agent, 397 self.MOTOROLA_TOLERANCE) 398 #print "MotorolaMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 399 return match
400
401 - def recovery_match(self, user_agent):
402 if u"MIB/2.2" in user_agent or u"MIB/BER2.2" in user_agent: 403 match = u"mot_mib22_generic" 404 else: 405 match = u"generic" 406 return match
407
408 409 -class MSIEMatcher(AbstractMatcher):
410 - def can_handle(self, user_agent):
411 return (not utils.is_mobile_browser(user_agent) and 412 user_agent.startswith(u"Mozilla") and 413 u"MSIE" in user_agent)
414
415 416 -class NecMatcher(AbstractMatcher):
417 418 NEC_LD_TOLERANCE = 2 419
420 - def can_handle(self, user_agent):
421 return user_agent.startswith(u"NEC") or user_agent.startswith(u"KGT")
422
423 - def look_for_matching_user_agent(self, user_agent):
424 if user_agent.startswith(u"NEC"): 425 match = AbstractMatcher.look_for_matching_user_agent(self, 426 user_agent) 427 else: 428 match = ld_match(self.user_agents, user_agent, 429 self.NEC_LD_TOLERANCE) 430 #print "NecMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 431 return match
432
433 434 -class NokiaMatcher(AbstractMatcher):
435 - def can_handle(self, user_agent):
436 return u"Nokia" in user_agent
437
438 - def look_for_matching_user_agent(self, user_agent):
439 tolerance = uiol(user_agent, u"/", 440 start_index=user_agent.index(u"Nokia")) 441 #print "NokiaMatcher tolerance %s" % tolerance 442 match = ris_match(self.user_agents, user_agent, tolerance) 443 #print "NokiaMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 444 return match
445
446 - def recovery_match(self, user_agent):
447 if u"Series60" in user_agent: 448 match = u"nokia_generic_series60" 449 elif u"Series80" in user_agent: 450 match = u"nokia_generic_series80" 451 else: 452 match = u"generic" 453 return match
454
455 456 -class OperaMatcher(AbstractMatcher):
457 458 OPERA_TOLERANCE = 3 459 460 operas = {} 461 operas["7"] = u"opera_7" 462 operas["8"] = u"opera_8" 463 operas["9"] = u"opera_9" 464 operas["10"] = u"opera_10" 465 466 opera_re = re.compile(r".*Opera/(\d+).*") 467
468 - def can_handle(self, user_agent):
469 return (not utils.is_mobile_browser(user_agent) and 470 u"Opera" in user_agent)
471
472 - def look_for_matching_user_agent(self, user_agent):
473 match = ld_match(self.user_agents, user_agent, self.OPERA_TOLERANCE) 474 #print "OperaMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 475 return match
476
477 - def recovery_match(self, user_agent):
478 match = self.opera_re.match(user_agent) 479 if match: 480 return self.operas.get(match.groups()[0], u"opera") 481 return u"opera"
482
483 484 -class OperaMiniMatcher(AbstractMatcher):
485 - def can_handle(self, user_agent):
486 return u"Opera Mini" in user_agent
487
488 - def recovery_match(self, user_agent):
489 match = u"" 490 if u"Opera Mini/1" in user_agent: 491 match = u"opera_mini_ver1" 492 elif u"Opera Mini/2" in user_agent: 493 match = u"opera_mini_ver2" 494 elif u"Opera Mini/3" in user_agent: 495 match = u"opera_mini_ver3" 496 elif u"Opera Mini/4" in user_agent: 497 match = u"opera_mini_ver4" 498 return match
499
500 501 -class PanasonicMatcher(AbstractMatcher):
502 - def can_handle(self, user_agent):
503 return user_agent.startswith(u"Panasonic")
504
505 506 -class PantechMatcher(AbstractMatcher):
507 508 PANTECH_LD_TOLERANCE = 4 509
510 - def can_handle(self, user_agent):
511 return (user_agent.startswith(u"Pantech") or 512 user_agent.startswith(u"PT-") or 513 user_agent.startswith(u"PANTECH") or 514 user_agent.startswith(u"PG-"))
515
516 - def look_for_matching_user_agent(self, user_agent):
517 if user_agent.startswith(u"Pantech"): 518 match = ld_match(self.user_agents, user_agent, 519 self.PANTECH_LD_TOLERANCE) 520 else: 521 match = AbstractMatcher.look_for_matching_user_agent(self, 522 user_agent) 523 #print "PantechMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 524 return match
525
526 527 -class PhilipsMatcher(AbstractMatcher):
528 - def can_handle(self, user_agent):
529 return (user_agent.startswith(u"Philips") or 530 user_agent.startswith(u"PHILIPS"))
531
532 533 -class PortalmmmMatcher(AbstractMatcher):
534 - def can_handle(self, user_agent):
535 return user_agent.startswith(u"portalmmm")
536
537 - def look_for_matching_user_agent(self, user_agent):
538 return u""
539
540 541 -class QtekMatcher(AbstractMatcher):
542 - def can_handle(self, user_agent):
543 return user_agent.startswith(u"Qtek")
544
545 546 -class SafariMatcher(AbstractMatcher):
547 - def can_handle(self, user_agent):
548 return (not utils.is_mobile_browser(user_agent) and 549 user_agent.startswith(u"Mozilla") and 550 u"Safari" in user_agent)
551
552 - def recovery_match(self, user_agent):
553 if u"Macintosh" in user_agent or u"Windows" in user_agent: 554 match = u"generic_web_browser" 555 else: 556 match = u"generic" 557 return match
558
559 560 -class SagemMatcher(AbstractMatcher):
561 - def can_handle(self, user_agent):
562 return (user_agent.startswith(u"Sagem") or 563 user_agent.startswith(u"SAGEM"))
564
565 566 -class SamsungMatcher(AbstractMatcher):
567 - def can_handle(self, user_agent):
568 return (u"Samsung/SGH" in user_agent or 569 user_agent.startswith(u"SEC-") or 570 user_agent.startswith(u"Samsung") or 571 user_agent.startswith(u"SAMSUNG") or 572 user_agent.startswith(u"SPH") or 573 user_agent.startswith(u"SGH") or 574 user_agent.startswith(u"SCH"))
575
576 - def look_for_matching_user_agent(self, user_agent):
577 if (user_agent.startswith(u"SEC-") or 578 user_agent.startswith(u"SAMSUNG-") or 579 user_agent.startswith(u"SCH")): 580 tolerance = utils.first_slash(user_agent) 581 elif (user_agent.startswith(u"Samsung") or 582 user_agent.startswith(u"SPH") or 583 user_agent.startswith(u"SGH")): 584 tolerance = utils.first_space(user_agent) 585 elif user_agent.startswith(u"SAMSUNG/"): 586 tolerance = utils.second_slash(user_agent) 587 elif u"Samsung/SGH-L870" in user_agent: 588 tolerance = uiol(user_agent, u"/", 5) 589 else: 590 tolerance = len(user_agent) 591 match = ris_match(self.user_agents, user_agent, tolerance) 592 #print "SamsungMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 593 return match
594
595 596 -class SanyoMatcher(AbstractMatcher):
597 - def can_handle(self, user_agent):
598 return (user_agent.startswith(u"Sanyo") or 599 user_agent.startswith(u"SANYO"))
600
601 602 -class SharpMatcher(AbstractMatcher):
603 - def can_handle(self, user_agent):
604 return (user_agent.startswith(u"Sharp") or 605 user_agent.startswith(u"SHARP"))
606
607 608 -class SiemensMatcher(AbstractMatcher):
609 - def can_handle(self, user_agent):
610 return user_agent.startswith(u"SIE-")
611
612 613 -class SonyEricssonMatcher(AbstractMatcher):
614 - def can_handle(self, user_agent):
615 return u"SonyEricsson" in user_agent
616
617 - def look_for_matching_user_agent(self, user_agent):
618 if user_agent.startswith(u"SonyEricsson"): 619 match = AbstractMatcher.look_for_matching_user_agent(self, 620 user_agent) 621 else: 622 tolerance = utils.second_slash(user_agent) 623 match = ris_match(self.user_agents, user_agent, tolerance) 624 #print "SonyEricssonMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 625 return match
626
627 628 -class SPVMatcher(AbstractMatcher):
629 - def can_handle(self, user_agent):
630 return u"SPV" in user_agent
631
632 - def look_for_matching_user_agent(self, user_agent):
633 tolerance = uiol(user_agent, u";", start_index=uiol(user_agent, u"SPV")) 634 match = ris_match(self.user_agents, user_agent, tolerance) 635 return match
636
637 638 -class ToshibaMatcher(AbstractMatcher):
639 - def can_handle(self, user_agent):
640 return user_agent.startswith(u"Toshiba")
641
642 643 -class VodafoneMatcher(AbstractMatcher):
644
645 - def can_handle(self, user_agent):
646 return user_agent.startswith(u"Vodafone")
647
648 - def look_for_matching_user_agent(self, user_agent):
649 tolerance = uiol(user_agent, u"/", 3) 650 match = ris_match(self.user_agents, user_agent, tolerance) 651 #print "VodafoneMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 652 return match
653
654 655 -class WindowsCEMatcher(AbstractMatcher):
656 WINDOWS_CE_TOLERANCE = 3 657
658 - def can_handle(self, user_agent):
659 return u"Mozilla/" in user_agent and (u"Windows CE" in user_agent or 660 u"WindowsCE" in user_agent)
661
662 - def look_for_matching_user_agent(self, user_agent):
663 match = ld_match(self.user_agents, user_agent, 664 self.WINDOWS_CE_TOLERANCE) 665 return match
666
667 - def recovery_match(self, user_agent):
668 return u"ms_mobile_browser_ver1"
669 670 671 handlers = [NokiaMatcher(), 672 AndroidMatcher(normalizers.android), 673 SonyEricssonMatcher(), 674 MotorolaMatcher(), 675 BlackberryMatcher(), 676 SiemensMatcher(), 677 SagemMatcher(), 678 SamsungMatcher(), 679 PanasonicMatcher(), 680 NecMatcher(), 681 QtekMatcher(), 682 MitsubishiMatcher(), 683 PhilipsMatcher(), 684 LGMatcher(), 685 AppleMatcher(), 686 KyoceraMatcher(), 687 AlcatelMatcher(), 688 SharpMatcher(), 689 SanyoMatcher(), 690 BenQMatcher(), 691 PantechMatcher(), 692 ToshibaMatcher(), 693 GrundigMatcher(), 694 HTCMatcher(), 695 BotMatcher(), 696 SPVMatcher(), 697 WindowsCEMatcher(), 698 PortalmmmMatcher(), 699 DoCoMoMatcher(), 700 KDDIMatcher(), 701 VodafoneMatcher(), 702 OperaMiniMatcher(), 703 ChromeMatcher(normalizers.chrome), 704 AOLMatcher(), 705 OperaMatcher(normalizers.opera), 706 KonquerorMatcher(normalizers.konqueror), 707 SafariMatcher(normalizers.safari), 708 FirefoxMatcher(normalizers.firefox), 709 MSIEMatcher(normalizers.msie), 710 CatchAllMatcher()] 711