Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

221 рядки
5.8KB

  1. # -*- coding: utf-8 -*-
  2. """
  3. werkzeug.useragents
  4. ~~~~~~~~~~~~~~~~~~~
  5. This module provides a helper to inspect user agent strings. This module
  6. is far from complete but should work for most of the currently available
  7. browsers.
  8. :copyright: 2007 Pallets
  9. :license: BSD-3-Clause
  10. """
  11. import re
  12. import warnings
  13. class UserAgentParser(object):
  14. """A simple user agent parser. Used by the `UserAgent`."""
  15. platforms = (
  16. ("cros", "chromeos"),
  17. ("iphone|ios", "iphone"),
  18. ("ipad", "ipad"),
  19. (r"darwin|mac|os\s*x", "macos"),
  20. ("win", "windows"),
  21. (r"android", "android"),
  22. ("netbsd", "netbsd"),
  23. ("openbsd", "openbsd"),
  24. ("freebsd", "freebsd"),
  25. ("dragonfly", "dragonflybsd"),
  26. ("(sun|i86)os", "solaris"),
  27. (r"x11|lin(\b|ux)?", "linux"),
  28. (r"nintendo\s+wii", "wii"),
  29. ("irix", "irix"),
  30. ("hp-?ux", "hpux"),
  31. ("aix", "aix"),
  32. ("sco|unix_sv", "sco"),
  33. ("bsd", "bsd"),
  34. ("amiga", "amiga"),
  35. ("blackberry|playbook", "blackberry"),
  36. ("symbian", "symbian"),
  37. )
  38. browsers = (
  39. ("googlebot", "google"),
  40. ("msnbot", "msn"),
  41. ("yahoo", "yahoo"),
  42. ("ask jeeves", "ask"),
  43. (r"aol|america\s+online\s+browser", "aol"),
  44. ("opera", "opera"),
  45. ("edge", "edge"),
  46. ("chrome|crios", "chrome"),
  47. ("seamonkey", "seamonkey"),
  48. ("firefox|firebird|phoenix|iceweasel", "firefox"),
  49. ("galeon", "galeon"),
  50. ("safari|version", "safari"),
  51. ("webkit", "webkit"),
  52. ("camino", "camino"),
  53. ("konqueror", "konqueror"),
  54. ("k-meleon", "kmeleon"),
  55. ("netscape", "netscape"),
  56. (r"msie|microsoft\s+internet\s+explorer|trident/.+? rv:", "msie"),
  57. ("lynx", "lynx"),
  58. ("links", "links"),
  59. ("Baiduspider", "baidu"),
  60. ("bingbot", "bing"),
  61. ("mozilla", "mozilla"),
  62. )
  63. _browser_version_re = r"(?:%s)[/\sa-z(]*(\d+[.\da-z]+)?"
  64. _language_re = re.compile(
  65. r"(?:;\s*|\s+)(\b\w{2}\b(?:-\b\w{2}\b)?)\s*;|"
  66. r"(?:\(|\[|;)\s*(\b\w{2}\b(?:-\b\w{2}\b)?)\s*(?:\]|\)|;)"
  67. )
  68. def __init__(self):
  69. self.platforms = [(b, re.compile(a, re.I)) for a, b in self.platforms]
  70. self.browsers = [
  71. (b, re.compile(self._browser_version_re % a, re.I))
  72. for a, b in self.browsers
  73. ]
  74. def __call__(self, user_agent):
  75. for platform, regex in self.platforms: # noqa: B007
  76. match = regex.search(user_agent)
  77. if match is not None:
  78. break
  79. else:
  80. platform = None
  81. for browser, regex in self.browsers: # noqa: B007
  82. match = regex.search(user_agent)
  83. if match is not None:
  84. version = match.group(1)
  85. break
  86. else:
  87. browser = version = None
  88. match = self._language_re.search(user_agent)
  89. if match is not None:
  90. language = match.group(1) or match.group(2)
  91. else:
  92. language = None
  93. return platform, browser, version, language
  94. class UserAgent(object):
  95. """Represents a user agent. Pass it a WSGI environment or a user agent
  96. string and you can inspect some of the details from the user agent
  97. string via the attributes. The following attributes exist:
  98. .. attribute:: string
  99. the raw user agent string
  100. .. attribute:: platform
  101. the browser platform. The following platforms are currently
  102. recognized:
  103. - `aix`
  104. - `amiga`
  105. - `android`
  106. - `blackberry`
  107. - `bsd`
  108. - `chromeos`
  109. - `dragonflybsd`
  110. - `freebsd`
  111. - `hpux`
  112. - `ipad`
  113. - `iphone`
  114. - `irix`
  115. - `linux`
  116. - `macos`
  117. - `netbsd`
  118. - `openbsd`
  119. - `sco`
  120. - `solaris`
  121. - `symbian`
  122. - `wii`
  123. - `windows`
  124. .. attribute:: browser
  125. the name of the browser. The following browsers are currently
  126. recognized:
  127. - `aol` *
  128. - `ask` *
  129. - `baidu` *
  130. - `bing` *
  131. - `camino`
  132. - `chrome`
  133. - `edge`
  134. - `firefox`
  135. - `galeon`
  136. - `google` *
  137. - `kmeleon`
  138. - `konqueror`
  139. - `links`
  140. - `lynx`
  141. - `mozilla`
  142. - `msie`
  143. - `msn`
  144. - `netscape`
  145. - `opera`
  146. - `safari`
  147. - `seamonkey`
  148. - `webkit`
  149. - `yahoo` *
  150. (Browsers marked with a star (``*``) are crawlers.)
  151. .. attribute:: version
  152. the version of the browser
  153. .. attribute:: language
  154. the language of the browser
  155. """
  156. _parser = UserAgentParser()
  157. def __init__(self, environ_or_string):
  158. if isinstance(environ_or_string, dict):
  159. environ_or_string = environ_or_string.get("HTTP_USER_AGENT", "")
  160. self.string = environ_or_string
  161. self.platform, self.browser, self.version, self.language = self._parser(
  162. environ_or_string
  163. )
  164. def to_header(self):
  165. return self.string
  166. def __str__(self):
  167. return self.string
  168. def __nonzero__(self):
  169. return bool(self.browser)
  170. __bool__ = __nonzero__
  171. def __repr__(self):
  172. return "<%s %r/%s>" % (self.__class__.__name__, self.browser, self.version)
  173. # DEPRECATED
  174. from .wrappers import UserAgentMixin as _UserAgentMixin
  175. class UserAgentMixin(_UserAgentMixin):
  176. @property
  177. def user_agent(self, *args, **kwargs):
  178. warnings.warn(
  179. "'werkzeug.useragents.UserAgentMixin' should be imported"
  180. " from 'werkzeug.wrappers.UserAgentMixin'. This old import"
  181. " will be removed in version 1.0.",
  182. DeprecationWarning,
  183. stacklevel=2,
  184. )
  185. return super(_UserAgentMixin, self).user_agent