Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
__init__.py722 linesDownload Raw Back to httpagentparser
1"""2Extract client information from http user agent3The module does not try to detect all capabilities of browser in current form (it can easily be extended though).4Tries to5    * be fast6    * very easy to extend7    * reliable enough for practical purposes8    * assist python web apps to detect clients.9"""10 11__version__ = '1.9.5'12 13 14class DetectorsHub(dict):15    _known_types = ['os', 'dist', 'flavor', 'browser']16 17    def __init__(self, *args, **kw):18        dict.__init__(self, *args, **kw)19        for typ in self._known_types:20            self.setdefault(typ, [])21        self.registerDetectors()22 23    def register(self, detector):24        if detector.info_type not in self._known_types:25            self[detector.info_type] = [detector]26            self._known_types.insert(detector.order, detector.info_type)27        else:28            self[detector.info_type].append(detector)29 30    def __iter__(self):31        return iter(self._known_types)32 33    def registerDetectors(self):34        detectors = [v() for v in list(globals().values()) if DetectorBase in getattr(v, '__mro__', [])]35        for d in detectors:36            if d.can_register:37                self.register(d)38 39 40class DetectorBase(object):41    name = ""  # "to perform match in DetectorsHub object"42    info_type = "override me"43    result_key = "override me"44    order = 10  # 0 is highest45    look_for = "string to look for"46    skip_if_found = []  # strings if present stop processin47    can_register = False48    version_markers = [("/", " ")]49    allow_space_in_version = False50    _suggested_detectors = None51    platform = None52    bot = False53 54    def __init__(self):55        if not self.name:56            self.name = self.__class__.__name__57        self.can_register = (self.__class__.__dict__.get('can_register', True))58 59    def detect(self, agent, result):60        # -> True/None61        word = self.checkWords(agent)62        if word:63            result[self.info_type] = dict(name=self.name)64            result['bot'] = self.bot65            version = self.getVersion(agent, word)66            if version:67                result[self.info_type]['version'] = version68            if self.platform:69                result['platform'] = {'name': self.platform, 'version': version}70            return True71 72    def checkWords(self, agent):73        # -> True/None74        for w in self.skip_if_found:75            if w in agent:76                return False77        if isinstance(self.look_for, (tuple, list)):78            for word in self.look_for:79                if word in agent:80                    return word81        elif self.look_for in agent:82            return self.look_for83 84    def getVersion(self, agent, word):85        """86        => version string /None87        """88        version_markers = self.version_markers if \89            isinstance(self.version_markers[0], (list, tuple)) else [self.version_markers]90        version_part = agent.split(word, 1)[-1]91        for start, end in version_markers:92            if version_part.startswith(start) and end in version_part:93                version = version_part[1:]94                if end:  # end could be empty string95                    version = version.split(end)[0]96                if not self.allow_space_in_version:97                    version = version.split()[0]98                return version99 100 101class OS(DetectorBase):102    info_type = "os"103    can_register = False104    version_markers = [";", " "]105    allow_space_in_version = True106    platform = None107 108 109class Dist(DetectorBase):110    info_type = "dist"111    can_register = False112    platform = None113 114 115class Flavor(DetectorBase):116    info_type = "flavor"117    can_register = False118    platform = None119 120 121class Browser(DetectorBase):122    info_type = "browser"123    can_register = False124 125 126class Konqueror(Browser):127    look_for = "Konqueror"128    version_markers = ["/", ";"]129 130 131class OperaMobile(Browser):132    look_for = "Opera Mobi"133    name = "Opera Mobile"134 135    def getVersion(self, agent, word):136        try:137            look_for = "Version"138            return agent.split(look_for)[1][1:].split(' ')[0]139        except IndexError:140            look_for = "Opera"141            return agent.split(look_for)[1][1:].split(' ')[0]142 143 144class Opera(Browser):145    look_for = "Opera"146    skip_if_found = ['Opera Mobi']147 148    def getVersion(self, agent, word):149        try:150            look_for = "Version"151            return agent.split(look_for)[1][1:].split(' ')[0]152        except IndexError:153            look_for = "Opera"154            version = agent.split(look_for)[1][1:].split(' ')[0]155            return version.split('(')[0]156 157 158class OperaNew(Browser):159    """160    Opera after version 15161    """162    name = "Opera"163    look_for = "OPR"164    skip_if_found = ["Build/OPR"]165    version_markers = [('/', '')]166 167 168class Netscape(Browser):169    look_for = "Netscape"170    version_markers = [("/", '')]171 172 173class Trident(Browser):174    look_for = "Trident"175    skip_if_found = ["MSIE", "Opera"]176    name = "Microsoft Internet Explorer"177    version_markers = ["/", ";"]178    trident_to_ie_versions = {179        '4.0': '8.0',180        '5.0': '9.0',181        '6.0': '10.0',182        '7.0': '11.0',183    }184 185    def getVersion(self, agent, word):186        return self.trident_to_ie_versions.get(super(Trident, self).getVersion(agent, word))187 188 189class MSIE(Browser):190    look_for = "MSIE"191    skip_if_found = ["Opera"]192    name = "Microsoft Internet Explorer"193    version_markers = [" ", ";"]194 195class MSEdge(Browser):196    look_for = "Edge"197    skip_if_found = ["MSIE"]198    version_markers = ["/", ""]199 200class ChromiumEdge(Browser):201    look_for = "Edg/"202 203    def getVersion(self, agent, word):204        if "Edg/" in agent:205            return agent.split('Edg/')[-1].strip()206 207 208class Galeon(Browser):209    look_for = "Galeon"210 211 212class WOSBrowser(Browser):213    look_for = "wOSBrowser"214 215    def getVersion(self, agent, word):216        pass217 218 219class Safari(Browser):220    look_for = "Safari"221    skip_if_found = ["Edge", "YaBrowser", "FxiOS"]222 223    def checkWords(self, agent):224        unless_list = ["Chrome", "OmniWeb", "wOSBrowser", "Android", "CriOS"]225        if self.look_for in agent:226            for word in unless_list:227                if word in agent:228                    return False229            return self.look_for230 231    def getVersion(self, agent, word):232        if "Version/" in agent:233            return agent.split('Version/')[-1].split(' ')[0].strip()234        if "Safari/" in agent:235            return agent.split('Safari/')[-1].split(' ')[0].strip()236        else:237            return agent.split('Safari ')[-1].split(' ')[0].strip()  # Mobile Safari238 239class GoogleBot(Browser):240    # https://support.google.com/webmasters/answer/1061943241    look_for = ["Googlebot", "Googlebot-News", "Googlebot-Image",242                "Googlebot-Video", "Googlebot-Mobile", "Mediapartners-Google",243                "Mediapartners", "AdsBot-Google", "web/snippet"]244    bot = True245    version_markers = [('/', ';'), ('/', ' ')]246 247class GoogleFeedFetcher(Browser):248    look_for = "Feedfetcher-Google"249    bot = True250 251    def get_version(self, agent):252        pass253 254class RunscopeRadar(Browser):255    look_for = "runscope-radar"256    bot = True257 258class GoogleAppEngine(Browser):259    look_for = "AppEngine-Google"260    bot = True261 262    def get_version(self, agent):263        pass264 265class GoogleApps(Browser):266    look_for = "GoogleApps script"267    bot = True268 269    def get_version(self, agent):270        pass271 272class TwitterBot(Browser):273    look_for = "Twitterbot"274    bot = True275 276class TelegramBot(Browser):277    look_for = "TelegramBot"278    bot = True279 280class MJ12Bot(Browser):281    look_for = "MJ12bot"282    bot = True283 284class YandexBot(Browser):285    # http://help.yandex.com/search/robots/agent.xml286    look_for = "Yandex"287    bot = True288 289    def getVersion(self, agent, word):290        return agent[agent.index('Yandex'):].split('/')[-1].split(')')[0].strip()291 292class BingBot(Browser):293    look_for = "bingbot"294    version_markers = ["/", ";"]295    bot = True296 297 298class BaiduBot(Browser):299    # http://help.baidu.com/question?prod_en=master&class=1&id=1000973300    look_for = ["Baiduspider", "Baiduspider-image", "Baiduspider-video",301                "Baiduspider-news", "Baiduspider-favo", "Baiduspider-cpro",302                "Baiduspider-ads"]303    bot = True304    version_markers = ('/', ';')305 306 307class LinkedInBot(Browser):308    look_for = "LinkedInBot"309    bot = True310 311class ArchiveDotOrgBot(Browser):312    look_for = "archive.org_bot"313    bot = True314 315class YoudaoBot(Browser):316    look_for = "YoudaoBot"317    bot = True318 319class YoudaoBotImage(Browser):320    look_for = "YodaoBot-Image"321    bot = True322 323class RogerBot(Browser):324    look_for = "rogerbot"325    bot = True326 327class TweetmemeBot(Browser):328    look_for = "TweetmemeBot"329    bot = True330 331class WebshotBot(Browser):332    look_for = "WebshotBot"333    bot = True334 335class SensikaBot(Browser):336    look_for = "SensikaBot"337    bot = True338 339class YesupBot(Browser):340    look_for = "YesupBot"341    bot = True342 343class DotBot(Browser):344    look_for = "DotBot"345    bot = True346 347class PhantomJS(Browser):348    look_for = "Browser/Phantom"349    bot = True350 351class FacebookExternalHit(Browser):352    look_for = 'facebookexternalhit'353    bot = True354 355 356class NokiaOvi(Browser):357    look_for = "S40OviBrowser"358 359class UCBrowser(Browser):360    look_for = "UCBrowser"361 362class BrowserNG(Browser):363    look_for = "BrowserNG"364 365class Dolfin(Browser):366    look_for = 'Dolfin'367 368class NetFront(Browser):369    look_for = 'NetFront'370 371class Jasmine(Browser):372    look_for = 'Jasmine'373 374class Openwave(Browser):375    look_for = 'Openwave'376 377class UPBrowser(Browser):378    look_for = 'UP.Browser'379 380class OneBrowser(Browser):381    look_for = 'OneBrowser'382 383class ObigoInternetBrowser(Browser):384    look_for = 'ObigoInternetBrowser'385 386class TelecaBrowser(Browser):387    look_for = 'TelecaBrowser'388 389class MAUI(Browser):390    look_for = 'Browser/MAUI'391 392    def getVersion(self, agent, word):393        version = agent.split("Release/")[-1][:10]394        return version395 396 397class NintendoBrowser(Browser):398    look_for = 'NintendoBrowser'399 400 401class AndroidBrowser(Browser):402    look_for = "Android"403    skip_if_found = ['Chrome', 'Windows Phone', 'Opera', 'Firefox']404 405    # http://decadecity.net/blog/2013/11/21/android-browser-versions406    def getVersion(self, agent, word):407        pass408 409 410class Firefox(Browser):411    look_for = ["Firefox", "FxiOS"]412    version_markers = [('/', '')]413    skip_if_found = ["SeaMonkey", "web/snippet"]414 415 416class SeaMonkey(Browser):417    look_for = "SeaMonkey"418    version_markers = [('/', '')]419 420 421class Linux(OS):422    look_for = 'Linux'423    platform = 'Linux'424 425    def getVersion(self, agent, word):426        pass427 428 429class Blackberry(OS):430    look_for = 'BlackBerry'431    platform = 'BlackBerry'432 433    def getVersion(self, agent, word):434        pass435 436 437class BlackberryPlaybook(Dist):438    look_for = 'PlayBook'439    platform = 'BlackBerry'440 441    def getVersion(self, agent, word):442        pass443 444 445class WindowsPhone(OS):446    name = "Windows Phone"447    platform = 'Windows'448    look_for = ["Windows Phone OS", "Windows Phone"]449    version_markers = [(" ", ";"), (" ", ")")]450 451 452class iOS(OS):453    look_for = ('iPhone', 'iPad')454    skip_if_found = ['like iPhone']455 456 457class iPhone(Dist):458    look_for = 'iPhone'459    platform = 'iOS'460    skip_if_found = ['like iPhone']461 462    def getVersion(self, agent, word):463        version_end_chars = [' ']464        if not "iPhone OS" in agent:465            return None466        part = agent.split('iPhone OS')[-1].strip()467        for c in version_end_chars:468            if c in part:469                version = part.split(c)[0]470                return version.replace('_', '.')471        return None472 473 474class IPad(Dist):475    look_for = 'iPad;'476    platform = 'iOS'477 478    def getVersion(self, agent, word):479        version_end_chars = [' ']480        if not "CPU OS " in agent:481            return None482        part = agent.split('CPU OS ')[-1].strip()483        for c in version_end_chars:484            if c in part:485                version = part.split(c)[0]486                return version.replace('_', '.')487        return None488 489 490class Macintosh(OS):491    look_for = 'Macintosh'492 493    def getVersion(self, agent, word):494        pass495 496 497class MacOS(Flavor):498    look_for = 'Mac OS'499    platform = 'Mac OS'500    skip_if_found = ['iPhone', 'iPad']501 502    def getVersion(self, agent, word):503        version_end_chars = [';', ')']504        part = agent.split('Mac OS')[-1].strip()505        for c in version_end_chars:506            if c in part:507                version = part.split(c)[0]508                return version.replace('_', '.')509        return ''510 511 512class Windows(Dist):513    look_for = 'Windows'514    platform = 'Windows'515 516 517class Windows(OS):518    look_for = 'Windows'519    platform = 'Windows'520    skip_if_found = ["Windows Phone"]521    win_versions = {522                    "NT 10.0": "10",523                    "NT 6.3": "8.1",524                    "NT 6.2": "8",525                    "NT 6.1": "7",526                    "NT 6.0": "Vista",527                    "NT 5.2": "Server 2003 / XP x64",528                    "NT 5.1": "XP",529                    "NT 5.01": "2000 SP1",530                    "NT 5.0": "2000",531                    "98; Win 9x 4.90": "Me"532    }533 534    def getVersion(self, agent, word):535        v = agent.split('Windows')[-1].split(';')[0].strip()536        if ')' in v:537            v = v.split(')')[0]538        v = self.win_versions.get(v, v)539        return v540 541 542class Ubuntu(Dist):543    look_for = 'Ubuntu'544    version_markers = ["/", " "]545 546 547class Debian(Dist):548    look_for = 'Debian'549    version_markers = ["/", " "]550 551class Chrome(Browser):552    look_for = "Chrome"553    version_markers = ["/", " "]554    skip_if_found = [" OPR", "Edge", "YaBrowser", "Edg/"]555 556    def getVersion(self, agent, word):557        part = agent.split(word + self.version_markers[0])[-1]558        version = part.split(self.version_markers[1])[0]559        if '+' in version:560            version = version.split('+')[0]561        return version.strip()562 563class YaBrowser(Browser):564    look_for = "YaBrowser"565    name = "Yandex.Browser"566    version_markers = ["/", " "]567 568    def getVersion(self, agent, word):569        part = agent.split(word + self.version_markers[0])[-1]570        version = part.split(self.version_markers[1])[0]571        if '+' in version:572            version = version.split('+')[0]573        return version.strip()574 575class ChromeiOS(Browser):576    look_for = "CriOS"577    version_markers = ["/", " "]578 579 580class ChromeOS(OS):581    look_for = "CrOS"582    platform = ' ChromeOS'583    version_markers = [" ", " "]584 585    def getVersion(self, agent, word):586        version_markers = self.version_markers587        if word + '+' in agent:588            version_markers = ['+', '+']589        return agent.split(word + version_markers[0])[-1].split(version_markers[1])[1].strip()[:-1]590 591 592class Android(Dist):593    look_for = 'Android'594    platform = 'Android'595    skip_if_found = ['Windows Phone']596 597    def getVersion(self, agent, word):598        return agent.split(word)[-1].replace(')', ';').split(';')[0].strip()599 600 601class WebOS(Dist):602    look_for = 'hpwOS'603 604    def getVersion(self, agent, word):605        return agent.split('hpwOS/')[-1].split(';')[0].strip()606 607 608class NokiaS40(OS):609    look_for = 'Series40'610    platform = 'Nokia S40'611 612    def getVersion(self, agent, word):613        pass614 615 616class Symbian(OS):617    look_for = ['Symbian', 'SymbianOS']618    platform = 'Symbian'619 620 621class PlayStation(OS):622    look_for = ['PlayStation', 'PLAYSTATION']623    platform = 'PlayStation'624    version_markers = [" ", ")"]625 626 627class prefs:  # experimental628    os = dict(629        Linux=dict(dict(browser=[Firefox, Chrome], dist=[Ubuntu, Android])),630        BlackBerry=dict(dist=[BlackberryPlaybook]),631        Macintosh=dict(flavor=[MacOS]),632        Windows=dict(browser=[MSIE, Firefox]),633        ChromeOS=dict(browser=[Chrome]),634        Debian=dict(browser=[Firefox])635    )636    dist = dict(637        Ubuntu=dict(browser=[Firefox]),638        Android=dict(browser=[Safari]),639        IPhone=dict(browser=[Safari]),640        IPad=dict(browser=[Safari]),641    )642    flavor = dict(643        MacOS=dict(browser=[Opera, Chrome, Firefox, MSIE])644    )645 646 647detectorshub = DetectorsHub()648 649 650def detect(agent, fill_none=False):651    """652    fill_none: if name/version is not detected respective key is still added to the result with value None653    """654    result = dict(platform=dict(name=None, version=None))655    _suggested_detectors = []656 657    for info_type in detectorshub:658        detectors = _suggested_detectors or detectorshub[info_type]659        for detector in detectors:660            try:661                detector.detect(agent, result)662            except Exception as _err:663                pass664 665    if fill_none:666        for outer_key in ('os', 'browser'):667            outer_value = result.setdefault(outer_key, dict())668            for inner_key in ('name', 'version'):669                outer_value.setdefault(inner_key, None)670 671    return result672 673 674UNKNOWN_OS_NAME = 'Unknown OS'675UNKNOWN_BROWSER_NAME = 'Unknown Browser'676 677 678def simple_detect_tuple(agent, parsed_agent=None):679    """680    @params:681        agent::str682        parsed_agent::dict683            The result of detect, used to save calculations684 685    @return:686        (os_name, os_version, browser_name, browser_version)::Tuple(str)687    """688    result = parsed_agent or detect(agent)689    os_list = []690    if 'flavor' in result:691        os_list.append(result['flavor']['name'])692    if 'dist' in result:693        os_list.append(result['dist']['name'])694    if 'os' in result:695        os_list.append(result['os']['name'])696 697    os = os_list and " ".join(os_list) or UNKNOWN_OS_NAME698    os_version = os_list and (result.get('flavor') and result['flavor'].get('version')) or \699        (result.get('dist') and result['dist'].get('version')) or (result.get('os') and result['os'].get('version')) or ""700    browser = 'browser' in result and result['browser'].get('name') or UNKNOWN_BROWSER_NAME701    browser_version = 'browser' in result and result['browser'].get('version') or ""702 703    return os, os_version, browser, browser_version704 705 706def simple_detect(agent, parsed_agent=None):707    """708    @params:709        agent::str710        parsed_agent::dict711            The result of detect, used to save calculations712 713    @return:714        (os_name_version, browser_name_version)::Tuple(str)715    """716    os, os_version, browser, browser_version = simple_detect_tuple(agent, parsed_agent=parsed_agent)717    if browser_version:718        browser = " ".join((browser, browser_version))719    if os_version:720        os = " ".join((os, os_version))721    return os, browser722 
codekingpro/portable-devtools · Team Ai