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.0" 
 37   
 38  from functools import partial 
 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 user_agent = self.normalizer(user_agent) 72 devid = self.conclusive_match(user_agent) 73 if not devid or devid == u"generic": 74 devid = self.recovery_match(user_agent) 75 if not devid or devid == u"generic": 76 devid = self.catch_all_recovery_match(user_agent) 77 return devid
78
79 - def conclusive_match(self, user_agent):
80 match = self.look_for_matching_user_agent(user_agent) 81 #print "%s -> conclusive_match -> %s" % (user_agent, match) 82 devid = u"generic" 83 if match: 84 devid = self.user_agent_map.get(match) 85 if not devid: 86 devid = u"generic" 87 return devid
88
89 - def look_for_matching_user_agent(self, user_agent):
90 tolerance = utils.first_slash(user_agent) 91 #print "AbstractMatcher tolerance %s" % tolerance 92 match = ris_match(self.user_agents, user_agent, tolerance) 93 #print "AbstractMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 94 return match
95
96 - def recovery_match(self, user_agent):
97 return u"generic"
98
99 - def catch_all_recovery_match(self, user_agent):
100 101 match = u"generic" 102 103 # Openwave 104 if u"UP.Browser/7.2" in user_agent: 105 match = u"opwv_v72_generic" 106 elif u"UP.Browser/7" in user_agent: 107 match = u"opwv_v7_generic" 108 elif u"UP.Browser/6.2" in user_agent: 109 match = u"opwv_v62_generic" 110 elif u"UP.Browser/6" in user_agent: 111 match = u"opwv_v6_generic" 112 elif u"UP.Browser/5" in user_agent: 113 match = u"upgui_generic" 114 elif u"UP.Browser/4" in user_agent: 115 match = u"uptext_generic" 116 elif u"UP.Browser/3" in user_agent: 117 match = u"uptext_generic" 118 119 # Series 60 120 elif u"Series60" in user_agent: 121 match = u"nokia_generic_series60" 122 123 # Access/Net Front 124 elif u"NetFront/3.0" in user_agent or u"ACS-NF/3.0" in user_agent: 125 match = u"netfront_ver3" 126 elif u"NetFront/3.1" in user_agent or u"ACS-NF/3.1" in user_agent: 127 match = u"netfront_ver3_1" 128 elif u"NetFront/3.2" in user_agent or u"ACS-NF/3.2" in user_agent: 129 match = u"netfront_ver3_2" 130 elif u"NetFront/3.3" in user_agent or u"ACS-NF/3.3" in user_agent: 131 match = u"netfront_ver3_3" 132 elif u"NetFront/3.4" in user_agent: 133 match = u"netfront_ver3_4" 134 elif u"NetFront/3.5" in user_agent: 135 match = u"netfront_ver3_5" 136 137 # Windows CE 138 elif u"Windows CE" in user_agent: 139 match = u"ms_mobile_browser_ver1" 140 141 # web browsers? 142 elif u"Mozilla/4.0" in user_agent: 143 match = u"generic_web_browser" 144 elif u"Mozilla/5.0" in user_agent: 145 match = u"generic_web_browser" 146 elif u"Mozilla/6.0" in user_agent: 147 match = u"generic_web_browser" 148 149 # Generic XHTML 150 elif u"Mozilla/" in user_agent: 151 match = u"generic_xhtml" 152 153 elif (u"ObigoInternetBrowser/Q03C" in user_agent or 154 u"AU-MIC/2" in user_agent or 155 u"AU-MIC-" in user_agent or 156 u"AU-OBIGO/" in user_agent or 157 u"Obigo/Q03" in user_agent or 158 u"Obigo/Q04" in user_agent or 159 u"ObigoInternetBrowser/2" in user_agent or 160 u"Teleca Q03B1" in user_agent): 161 match = u"generic_xhtml" 162 163 # Opera Mini 164 elif u"Opera Mini/1" in user_agent: 165 match = u"opera_mini_ver1" 166 elif u"Opera Mini/2" in user_agent: 167 match = u"opera_mini_ver2" 168 elif u"Opera Mini/3" in user_agent: 169 match = u"opera_mini_ver3" 170 elif u"Opera Mini/4" in user_agent: 171 match = u"opera_mini_ver4" 172 173 # DoCoMo 174 elif user_agent.startswith(u"DoCoMo") or user_agent.startswith(u"KDDI"): 175 match = u"docomo_generic_jap_ver1" 176 177 return match
178
179 180 -class AlcatelMatcher(AbstractMatcher):
181 - def can_handle(self, user_agent):
182 return (user_agent.startswith(u"Alcatel") or 183 user_agent.startswith(u"ALCATEL"))
184
185 186 -class AndroidMatcher(AbstractMatcher):
187 - def can_handle(self, user_agent):
188 return u"Android" in user_agent
189
190 - def look_for_matching_user_agent(self, user_agent):
191 tolerance = uiol(user_agent, u" ", uiol(user_agent, u"Android")) 192 match = ris_match(self.user_agents, user_agent, tolerance) 193 #print "AndroidMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 194 return match
195
196 197 -class AOLMatcher(AbstractMatcher):
198 - def can_handle(self, user_agent):
199 return not utils.is_mobile_browser(user_agent) and u"AOL" in user_agent
200
201 202 -class AppleMatcher(AbstractMatcher):
203 APPLE_LD_TOLLERANCE = 5 204
205 - def can_handle(self, user_agent):
206 return u"iPhone" in user_agent or u"iPod" in user_agent
207
208 - def look_for_matching_user_agent(self, user_agent):
209 match = ld_match(self.user_agents, user_agent, self.APPLE_LD_TOLLERANCE) 210 #print "AppleMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 211 return match
212
213 - def recovery_match(self, user_agent):
214 if u"iPhone" in user_agent: 215 return u"apple_iphone_ver1" 216 return u"apple_ipod_touch_ver1"
217
218 219 -class BenQMatcher(AbstractMatcher):
220 - def can_handle(self, user_agent):
221 return user_agent.startswith(u"BenQ") or user_agent.startswith(u"BENQ")
222
223 224 -class BlackberryMatcher(AbstractMatcher):
225 - def can_handle(self, user_agent):
226 return u"BlackBerry" in user_agent
227
228 - def recovery_match(self, user_agent):
229 match = u"generic" 230 231 if user_agent.startswith("BlackBerry"): 232 try: 233 position = user_agent.index('/') 234 if position + 4 < len(user_agent): 235 version = user_agent[position+1:position+4] 236 if version.startswith(u"2."): 237 match = u"blackberry_generic_ver2" 238 elif version.startswith(u"3.2"): 239 match = u"blackberry_generic_ver3_sub2" 240 elif version.startswith(u"3.3"): 241 match = u"blackberry_generic_ver3_sub30" 242 elif version.startswith(u"3.5"): 243 match = u"blackberry_generic_ver3_sub50" 244 elif version.startswith(u"3.6"): 245 match = u"blackberry_generic_ver3_sub60" 246 elif version.startswith(u"3.7"): 247 match = u"blackberry_generic_ver3_sub70" 248 elif version.startswith(u"4."): 249 match = u"blackberry_generic_ver4" 250 except ValueError: 251 pass 252 253 return match
254
255 256 -class BotMatcher(AbstractMatcher):
257 bots = (u"bot", u"crawler", u"novarra", u"transcoder") 258
259 - def can_handle(self, user_agent):
260 user_agent = user_agent.lower() 261 for bot in self.bots: 262 if bot in user_agent: 263 return True 264 return False
265
266 267 -class CatchAllMatcher(AbstractMatcher):
268 MOZILLA_LD_TOLLERANCE = 4 269
270 - def can_handle(self, user_agent):
271 return True
272
273 - def look_for_matching_user_agent(self, user_agent):
274 if user_agent.startswith(u"Mozilla"): 275 if user_agent.startswith(u"Mozilla/4"): 276 match = ld_match(self.extract_uas(u"Mozilla/4"), user_agent, 277 self.MOZILLA_LD_TOLLERANCE) 278 elif user_agent.startswith(u"Mozilla/5"): 279 match = ld_match(self.extract_uas(u"Mozilla/5"), user_agent, 280 self.MOZILLA_LD_TOLLERANCE) 281 else: 282 match = ld_match(self.extract_uas(u"Mozilla"), user_agent, 283 self.MOZILLA_LD_TOLLERANCE) 284 else: 285 match = AbstractMatcher.look_for_matching_user_agent(self, 286 user_agent) 287 #print "CatchAllMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 288 return match
289
290 - def extract_uas(self, start):
291 return [x for x in self.user_agents if x.startswith(start)]
292
293 294 -class ChromeMatcher(AbstractMatcher):
295 - def can_handle(self, user_agent):
296 return (not utils.is_mobile_browser(user_agent) and 297 u"Chrome" in user_agent)
298
299 300 -class DoCoMoMatcher(AbstractMatcher):
301 - def can_handle(self, user_agent):
302 return user_agent.startswith(u"DoCoMo")
303
304 - def look_for_matching_user_agent(self, user_agent):
305 return u""
306
307 - def recovery_match(self, user_agent):
308 return u"docomo_generic_jap_ver1"
309
310 311 -class FirefoxMatcher(AbstractMatcher):
312 - def can_handle(self, user_agent):
313 return (not utils.is_mobile_browser(user_agent) and 314 u"Firefox" in user_agent)
315
316 317 -class GrundigMatcher(AbstractMatcher):
318 - def can_handle(self, user_agent):
319 return (user_agent.startswith(u"Grundig") or 320 user_agent.startswith(u"GRUNDIG"))
321
322 323 -class HTCMatcher(AbstractMatcher):
324 - def can_handle(self, user_agent):
325 return user_agent.startswith(u"HTC")
326
327 328 -class KDDIMatcher(AbstractMatcher):
329 - def can_handle(self, user_agent):
330 return user_agent.startswith(u"KDDI")
331
332 - def look_for_matching_user_agent(self, user_agent):
333 if user_agent.startswith("KDDI/"): 334 tolerance = utils.second_slash(user_agent) 335 match = ris_match(self.user_agents, user_agent, tolerance) 336 else: 337 match = AbstractMatcher.look_for_matching_user_agent(self, 338 user_agent) 339 #print "KDDIMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 340 return match
341
342 - def recovery_match(self, user_agent):
343 return u"opwv_v62_generic"
344
345 346 -class KonquerorMatcher(AbstractMatcher):
347 - def can_handle(self, user_agent):
348 return (not utils.is_mobile_browser(user_agent) and 349 u"Konqueror" in user_agent)
350
351 352 -class KyoceraMatcher(AbstractMatcher):
353 - def can_handle(self, user_agent):
354 return (user_agent.startswith(u"kyocera") or 355 user_agent.startswith(u"QC-") or 356 user_agent.startswith(u"KWC-"))
357
358 359 -class LGMatcher(AbstractMatcher):
360 - def can_handle(self, user_agent):
361 return user_agent.startswith(u"LG") or user_agent.startswith(u"lg")
362
363 - def look_for_matching_user_agent(self, user_agent):
364 if user_agent.startswith(u"LGE/") or user_agent.startswith("LG/"): 365 tolerance = utils.second_slash(user_agent) 366 match = ris_match(self.user_agents, user_agent, tolerance) 367 else: 368 match = AbstractMatcher.look_for_matching_user_agent(self, 369 user_agent) 370 #print "LGMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 371 return match
372
373 374 -class MitsubishiMatcher(AbstractMatcher):
375 - def can_handle(self, user_agent):
376 return user_agent.startswith(u"Mitsu")
377
378 379 -class MotorolaMatcher(AbstractMatcher):
380 MOTOROLA_TOLERANCE = 5 381
382 - def can_handle(self, user_agent):
383 return (user_agent.startswith(u"Mot-") or 384 u"MOT-" in user_agent or 385 u"Motorola" in user_agent)
386
387 - def look_for_matching_user_agent(self, user_agent):
388 if (user_agent.startswith(u"Mot-") or user_agent.startswith(u"MOT-") or 389 user_agent.startswith(u"Motorola")): 390 match = AbstractMatcher.look_for_matching_user_agent(self, 391 user_agent) 392 else: 393 match = ld_match(self.user_agents, user_agent, 394 self.MOTOROLA_TOLERANCE) 395 #print "MotorolaMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 396 return match
397
398 - def recovery_match(self, user_agent):
399 if u"MIB/2.2" in user_agent or u"MIB/BER2.2" in user_agent: 400 match = u"mot_mib22_generic" 401 else: 402 match = u"generic" 403 return match
404
405 406 -class MSIEMatcher(AbstractMatcher):
407 - def can_handle(self, user_agent):
408 return (not utils.is_mobile_browser(user_agent) and 409 user_agent.startswith(u"Mozilla") and 410 u"MSIE" in user_agent)
411
412 413 -class NecMatcher(AbstractMatcher):
414 415 NEC_LD_TOLERANCE = 2 416
417 - def can_handle(self, user_agent):
418 return user_agent.startswith(u"NEC") or user_agent.startswith(u"KGT")
419
420 - def look_for_matching_user_agent(self, user_agent):
421 if user_agent.startswith(u"NEC"): 422 match = AbstractMatcher.look_for_matching_user_agent(self, 423 user_agent) 424 else: 425 match = ld_match(self.user_agents, user_agent, 426 self.NEC_LD_TOLERANCE) 427 #print "NecMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 428 return match
429
430 431 -class NokiaMatcher(AbstractMatcher):
432 - def can_handle(self, user_agent):
433 return u"Nokia" in user_agent
434
435 - def look_for_matching_user_agent(self, user_agent):
436 tolerance = uiol(user_agent, u"/", user_agent.index(u"Nokia")) 437 #print "NokiaMatcher tolerance %s" % tolerance 438 match = ris_match(self.user_agents, user_agent, tolerance) 439 #print "NokiaMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 440 return match
441
442 - def recovery_match(self, user_agent):
443 if u"Series60" in user_agent: 444 match = u"nokia_generic_series60" 445 elif u"Series80" in user_agent: 446 match = u"nokia_generic_series80" 447 else: 448 match = u"generic"
449
450 451 -class OperaMatcher(AbstractMatcher):
452 453 OPERA_TOLERANCE = 5 454
455 - def can_handle(self, user_agent):
456 return (not utils.is_mobile_browser(user_agent) and 457 u"Opera" in user_agent)
458
459 - def look_for_matching_user_agent(self, user_agent):
460 match = ld_match(self.user_agents, user_agent, self.OPERA_TOLERANCE) 461 #print "OperaMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 462 return match
463
464 465 -class OperaMiniMatcher(AbstractMatcher):
466 - def can_handle(self, user_agent):
467 return u"Opera Mini" in user_agent
468
469 - def recovery_match(self, user_agent):
470 match = u"" 471 if u"Opera Mini/1" in user_agent: 472 match = u"opera_mini_ver1" 473 elif u"Opera Mini/2" in user_agent: 474 match = u"opera_mini_ver2" 475 elif u"Opera Mini/3" in user_agent: 476 match = u"opera_mini_ver3" 477 elif u"Opera Mini/4" in user_agent: 478 match = u"opera_mini_ver4" 479 480 return match
481
482 483 -class PanasonicMatcher(AbstractMatcher):
484 - def can_handle(self, user_agent):
485 return user_agent.startswith(u"Panasonic")
486
487 488 -class PantechMatcher(AbstractMatcher):
489 490 PANTECH_LD_TOLERANCE = 4 491
492 - def can_handle(self, user_agent):
493 return (user_agent.startswith(u"Pantech") or 494 user_agent.startswith(u"PT-") or 495 user_agent.startswith(u"PANTECH") or 496 user_agent.startswith(u"PG-"))
497
498 - def look_for_matching_user_agent(self, user_agent):
499 if user_agent.startswith(u"Pantech"): 500 match = ld_match(self.user_agents, user_agent, 501 self.PANTECH_LD_TOLERANCE) 502 else: 503 match = AbstractMatcher.look_for_matching_user_agent(self, 504 user_agent) 505 #print "PantechMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 506 return match
507
508 509 -class PhilipsMatcher(AbstractMatcher):
510 - def can_handle(self, user_agent):
511 return (user_agent.startswith(u"Philips") or 512 user_agent.startswith(u"PHILIPS"))
513
514 515 -class PortalmmmMatcher(AbstractMatcher):
516 - def can_handle(self, user_agent):
517 return user_agent.startswith(u"portalmmm")
518
519 - def look_for_matching_user_agent(self, user_agent):
520 return u""
521
522 523 -class QtekMatcher(AbstractMatcher):
524 - def can_handle(self, user_agent):
525 return user_agent.startswith(u"Qtek")
526
527 528 -class SafariMatcher(AbstractMatcher):
529 - def can_handle(self, user_agent):
530 return (not utils.is_mobile_browser(user_agent) and 531 user_agent.startswith(u"Mozilla") and 532 u"Safari" in user_agent)
533
534 - def recovery_match(self, user_agent):
535 if u"Macintosh" in user_agent or u"Windows" in user_agent: 536 match = u"generic_web_browser" 537 else: 538 match = u"generic" 539 return match
540
541 542 543 -class SagemMatcher(AbstractMatcher):
544 - def can_handle(self, user_agent):
545 return (user_agent.startswith(u"Sagem") or 546 user_agent.startswith(u"SAGEM"))
547
548 549 -class SamsungMatcher(AbstractMatcher):
550 - def can_handle(self, user_agent):
551 return (u"Samsung/SGH" in user_agent or 552 user_agent.startswith(u"SEC-") or 553 user_agent.startswith(u"Samsung") or 554 user_agent.startswith(u"SAMSUNG") or 555 user_agent.startswith(u"SPH") or 556 user_agent.startswith(u"SGH") or 557 user_agent.startswith(u"SCH"))
558
559 - def look_for_matching_user_agent(self, user_agent):
560 match = u"" 561 if (user_agent.startswith(u"SEC-") or 562 user_agent.startswith(u"SAMSUNG-") or 563 user_agent.startswith(u"SCH")): 564 match = AbstractMatcher.look_for_matching_user_agent(self, 565 user_agent) 566 elif (user_agent.startswith(u"Samsung") or 567 user_agent.startswith(u"SPH") or 568 user_agent.startswith(u"SGH")): 569 tolerance = utils.first_space(user_agent) 570 match = ris_match(self.user_agents, user_agent, 571 tolerance) 572 elif user_agent.startswith(u"SAMSUNG/"): 573 tolerance = utils.second_slash(user_agent) 574 match = ris_match(self.user_agents, user_agent, tolerance) 575 elif u"Samsung/SGH-L870" in user_agent: 576 tolerance = uiol(user_agent, u"/", 5) 577 match = ris_match(self.user_agents, user_agent, tolerance) 578 #print "SamsungMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 579 return match
580
581 582 -class SanyoMatcher(AbstractMatcher):
583 - def can_handle(self, user_agent):
584 return (user_agent.startswith(u"Sanyo") or 585 user_agent.startswith(u"SANYO"))
586
587 588 -class SharpMatcher(AbstractMatcher):
589 - def can_handle(self, user_agent):
590 return (user_agent.startswith(u"Sharp") or 591 user_agent.startswith(u"SHARP"))
592
593 594 -class SiemensMatcher(AbstractMatcher):
595 - def can_handle(self, user_agent):
596 return user_agent.startswith(u"SIE-")
597
598 599 -class SonyEricssonMatcher(AbstractMatcher):
600 - def can_handle(self, user_agent):
601 return u"SonyEricsson" in user_agent
602
603 - def look_for_matching_user_agent(self, user_agent):
604 if user_agent.startswith(u"SonyEricsson"): 605 match = AbstractMatcher.look_for_matching_user_agent(self, 606 user_agent) 607 else: 608 tolerance = utils.second_slash(user_agent) 609 match = ris_match(self.user_agents, user_agent, tolerance) 610 #print "SonyEricssonMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 611 return match
612
613 614 -class SPVMatcher(AbstractMatcher):
615 - def can_handle(self, user_agent):
616 return u"SPV" in user_agent
617
618 - def look_for_matching_user_agent(self, user_agent):
619 tolerance = uiol(user_agent, u";", uiol(user_agent, u"SPV")) 620 match = ris_match(self.user_agents, user_agent, tolerance) 621 return match
622
623 624 -class ToshibaMatcher(AbstractMatcher):
625 - def can_handle(self, user_agent):
626 return user_agent.startswith(u"Toshiba")
627
628 629 -class VodafoneMatcher(AbstractMatcher):
630 631 VODAFONE_TOLLERANCE = 3 632
633 - def can_handle(self, user_agent):
634 return user_agent.startswith(u"Vodafone")
635
636 - def look_for_matching_user_agent(self, user_agent):
637 tolerance = self.VODAFONE_TOLLERANCE 638 if u"Nokia" in user_agent: 639 tolerance = uiol(user_agent, u"/", uiol(user_agent, u"Nokia")) 640 match = ris_match(self.user_agents, user_agent, tolerance) 641 else: 642 match = ld_match(self.user_agents, user_agent, 643 self.VODAFONE_TOLLERANCE) 644 #print "VodafoneMatcher %s -> l_f_m_ua -> %s" % (user_agent, match) 645 return match
646
647 648 -class WindowsCEMatcher(AbstractMatcher):
649 WINDOWS_CE_TOLERANCE = 3 650
651 - def can_handle(self, user_agent):
652 return u"Mozilla/" in user_agent and u"Windows CE" in user_agent
653
654 - def look_for_matching_user_agent(self, user_agent):
655 match = ld_match(self.user_agents, user_agent, 656 self.WINDOWS_CE_TOLERANCE) 657 return match
658
659 - def recovery_match(self, user_agent):
660 return u"ms_mobile_browser_ver1"
661 662 663 handlers = [VodafoneMatcher(), 664 NokiaMatcher(), 665 SonyEricssonMatcher(), 666 MotorolaMatcher(), 667 BlackberryMatcher(), 668 SiemensMatcher(), 669 SagemMatcher(), 670 SamsungMatcher(), 671 PanasonicMatcher(), 672 NecMatcher(), 673 QtekMatcher(), 674 MitsubishiMatcher(), 675 PhilipsMatcher(), 676 LGMatcher(), 677 AppleMatcher(), 678 KyoceraMatcher(), 679 AlcatelMatcher(), 680 SharpMatcher(), 681 SanyoMatcher(), 682 BenQMatcher(), 683 PantechMatcher(), 684 ToshibaMatcher(), 685 GrundigMatcher(), 686 HTCMatcher(), 687 SPVMatcher(), 688 WindowsCEMatcher(), 689 PortalmmmMatcher(), 690 DoCoMoMatcher(), 691 KDDIMatcher(), 692 AndroidMatcher(), 693 OperaMiniMatcher(), 694 BotMatcher(), 695 ChromeMatcher(normalizers.chrome), 696 AOLMatcher(), 697 OperaMatcher(normalizers.opera), 698 KonquerorMatcher(normalizers.konqueror), 699 SafariMatcher(normalizers.safari), 700 FirefoxMatcher(normalizers.firefox), 701 MSIEMatcher(normalizers.msie), 702 CatchAllMatcher()] 703