~ubuntu-branches/ubuntu/oneiric/moin/oneiric-security

« back to all changes in this revision

Viewing changes to MoinMoin/support/werkzeug/useragents.py

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2010-03-30 12:55:34 UTC
  • mfrom: (0.1.17 sid)
  • Revision ID: james.westby@ubuntu.com-20100330125534-4c2ufc1rok24447l
Tags: 1.9.2-2ubuntu1
* Merge from Debian testing (LP: #521834). Based on work by Stefan Ebner.
  Remaining changes:
 - Remove python-xml from Suggests field, the package isn't anymore in
   sys.path.
 - Demote fckeditor from Recommends to Suggests; the code was previously
   embedded in moin, but it was also disabled, so there's no reason for us
   to pull this in by default currently. Note: This isn't necessary anymore
   but needs a MIR for fckeditor, so postpone dropping this change until
   lucid+1
* debian/rules:
  - Replace hardcoded python2.5 with python* and hardcore python2.6 for ln
* debian/control.in: drop versioned depends on cdbs

Show diffs side-by-side

added added

removed removed

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