1b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom datetime import (
2b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    date,
3b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    datetime,
4b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
5b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
6b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport re
7b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
8b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.byterange import (
9b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ContentRange,
10b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Range,
11b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
12b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
13b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.compat import (
14b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    PY3,
15b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    text_type,
16b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
17b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
18b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.datetime_utils import (
19b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    parse_date,
20b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    serialize_date,
21b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
22b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
23b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.util import (
24b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    header_docstring,
25b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    warn_deprecation,
26b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
27b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
28b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
29b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikCHARSET_RE = re.compile(r';\s*charset=([^;]*)', re.I)
30b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikSCHEME_RE = re.compile(r'^[a-z]+:', re.I)
31b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
32b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
33b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_not_given = object()
34b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
35b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef environ_getter(key, default=_not_given, rfc_section=None):
36b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if rfc_section:
37b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doc = header_docstring(key, rfc_section)
38b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
39b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doc = "Gets and sets the ``%s`` key in the environment." % key
40b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if default is _not_given:
41b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fget(req):
42b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return req.environ[key]
43b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fset(req, val):
44b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            req.environ[key] = val
45b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        fdel = None
46b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
47b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fget(req):
48b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return req.environ.get(key, default)
49b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fset(req, val):
50b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if val is None:
51b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                if key in req.environ:
52b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    del req.environ[key]
53b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            else:
54b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                req.environ[key] = val
55b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fdel(req):
56b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            del req.environ[key]
57b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return property(fget, fset, fdel, doc=doc)
58b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
59b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
60b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef environ_decoder(key, default=_not_given, rfc_section=None,
61b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    encattr=None):
62b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if rfc_section:
63b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doc = header_docstring(key, rfc_section)
64b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
65b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doc = "Gets and sets the ``%s`` key in the environment." % key
66b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if default is _not_given:
67b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fget(req):
68b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return req.encget(key, encattr=encattr)
69b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fset(req, val):
70b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return req.encset(key, val, encattr=encattr)
71b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        fdel = None
72b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
73b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fget(req):
74b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return req.encget(key, default, encattr=encattr)
75b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fset(req, val):
76b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if val is None:
77b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                if key in req.environ:
78b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    del req.environ[key]
79b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            else:
80b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                return req.encset(key, val, encattr=encattr)
81b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fdel(req):
82b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            del req.environ[key]
83b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return property(fget, fset, fdel, doc=doc)
84b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
85b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef upath_property(key):
86b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if PY3: # pragma: no cover
87b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fget(req):
88b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            encoding = req.url_encoding
89b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return req.environ.get(key, '').encode('latin-1').decode(encoding)
90b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fset(req, val):
91b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            encoding = req.url_encoding
92b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            req.environ[key] = val.encode(encoding).decode('latin-1')
93b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
94b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fget(req):
95b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            encoding = req.url_encoding
96b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return req.environ.get(key, '').decode(encoding)
97b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        def fset(req, val):
98b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            encoding = req.url_encoding
99b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if isinstance(val, text_type):
100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                val = val.encode(encoding)
101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            req.environ[key] = val
102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return property(fget, fset, doc='upath_property(%r)' % key)
103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef deprecated_property(attr, name, text, version): # pragma: no cover
106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Wraps a descriptor, with a deprecation warning or error
108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def warn():
110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        warn_deprecation('The attribute %s is deprecated: %s'
111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            % (name, text),
112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            version,
113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            3
114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        )
115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fget(self):
116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        warn()
117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return attr.__get__(self, type(self))
118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fset(self, val):
119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        warn()
120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attr.__set__(self, val)
121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fdel(self):
122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        warn()
123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attr.__delete__(self)
124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return property(fget, fset, fdel,
125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        '<Deprecated attribute %s>' % name
126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef header_getter(header, rfc_section):
130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    doc = header_docstring(header, rfc_section)
131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    key = header.lower()
132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fget(r):
134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        for k, v in r._headerlist:
135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if k.lower() == key:
136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                return v
137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fset(r, value):
139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        fdel(r)
140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if value is not None:
141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if isinstance(value, text_type) and not PY3:
142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                value = value.encode('latin-1')
143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            r._headerlist.append((header, value))
144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fdel(r):
146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        items = r._headerlist
147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        for i in range(len(items)-1, -1, -1):
148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if items[i][0].lower() == key:
149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                del items[i]
150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return property(fget, fset, fdel, doc)
152b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
153b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
154b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
155b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
156b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef converter(prop, parse, serialize, convert_name=None):
157b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    assert isinstance(prop, property)
158b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    convert_name = convert_name or "``%s`` and ``%s``" % (parse.__name__,
159b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                                                  serialize.__name__)
160b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    doc = prop.__doc__ or ''
161b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    doc += "  Converts it using %s." % convert_name
162b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    hget, hset = prop.fget, prop.fset
163b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fget(r):
164b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return parse(hget(r))
165b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def fset(r, val):
166b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if val is not None:
167b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            val = serialize(val)
168b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        hset(r, val)
169b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return property(fget, fset, prop.fdel, doc)
170b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
171b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
172b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
173b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef list_header(header, rfc_section):
174b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    prop = header_getter(header, rfc_section)
175b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return converter(prop, parse_list, serialize_list, 'list')
176b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
177b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_list(value):
178b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not value:
179b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
180b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return tuple(filter(None, [v.strip() for v in value.split(',')]))
181b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
182b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef serialize_list(value):
183b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if isinstance(value, (text_type, bytes)):
184b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return str(value)
185b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
186b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return ', '.join(map(str, value))
187b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
188b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
189b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
190b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
191b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef converter_date(prop):
192b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return converter(prop, parse_date, serialize_date, 'HTTP date')
193b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
194b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef date_header(header, rfc_section):
195b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return converter_date(header_getter(header, rfc_section))
196b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
197b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
198b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
199b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
200b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
201b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
202b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
203b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
204b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
205b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik########################
206b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik## Converter functions
207b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik########################
208b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
209b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
210b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_rx_etag = re.compile(r'(?:^|\s)(W/)?"((?:\\"|.)*?)"')
211b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
212b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_etag_response(value, strong=False):
213b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
214b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Parse a response ETag.
215b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    See:
216b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19
217b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11
218b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
219b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not value:
220b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
221b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    m = _rx_etag.match(value)
222b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not m:
223b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        # this etag is invalid, but we'll just return it anyway
224b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return value
225b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    elif strong and m.group(1):
226b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        # this is a weak etag and we want only strong ones
227b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
228b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
229b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return m.group(2).replace('\\"', '"')
230b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
231b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef serialize_etag_response(value): #return '"%s"' % value.replace('"', '\\"')
232b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    strong = True
233b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if isinstance(value, tuple):
234b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        value, strong = value
235b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    elif _rx_etag.match(value):
236b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        # this is a valid etag already
237b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return value
238b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # let's quote the value
239b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    r = '"%s"' % value.replace('"', '\\"')
240b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not strong:
241b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        r = 'W/' + r
242b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return r
243b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
244b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef serialize_if_range(value):
245b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if isinstance(value, (datetime, date)):
246b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return serialize_date(value)
247b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    value = str(value)
248b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return value or None
249b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
250b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_range(value):
251b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not value:
252b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
253b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # Might return None too:
254b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return Range.parse(value)
255b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
256b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef serialize_range(value):
257b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not value:
258b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
259b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    elif isinstance(value, (list, tuple)):
260b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return str(Range(*value))
261b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else:
262b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        assert isinstance(value, str)
263b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return value
264b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
265b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_int(value):
266b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if value is None or value == '':
267b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
268b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return int(value)
269b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
270b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_int_safe(value):
271b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if value is None or value == '':
272b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
273b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    try:
274b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return int(value)
275b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    except ValueError:
276b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
277b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
278b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikserialize_int = str
279b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
280b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_content_range(value):
281b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not value or not value.strip():
282b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
283b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # May still return None
284b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return ContentRange.parse(value)
285b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
286b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef serialize_content_range(value):
287b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if isinstance(value, (tuple, list)):
288b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if len(value) not in (2, 3):
289b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            raise ValueError(
290b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                "When setting content_range to a list/tuple, it must "
291b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                "be length 2 or 3 (not %r)" % value)
292b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if len(value) == 2:
293b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            begin, end = value
294b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            length = None
295b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        else:
296b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            begin, end, length = value
297b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        value = ContentRange(begin, end, length)
298b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    value = str(value).strip()
299b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not value:
300b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return None
301b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return value
302b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
303b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
304b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
305b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
306b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_rx_auth_param = re.compile(r'([a-z]+)[ \t]*=[ \t]*(".*?"|[^,]*?)[ \t]*(?:\Z|, *)')
307b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
308b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_auth_params(params):
309b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    r = {}
310b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    for k, v in _rx_auth_param.findall(params):
311b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        r[k] = v.strip('"')
312b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return r
313b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
314b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# see http://lists.w3.org/Archives/Public/ietf-http-wg/2009OctDec/0297.html
315b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikknown_auth_schemes = ['Basic', 'Digest', 'WSSE', 'HMACDigest', 'GoogleLogin',
316b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                      'Cookie', 'OpenID']
317b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikknown_auth_schemes = dict.fromkeys(known_auth_schemes, None)
318b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
319b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef parse_auth(val):
320b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if val is not None:
321b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        authtype, params = val.split(' ', 1)
322b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if authtype in known_auth_schemes:
323b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if authtype == 'Basic' and '"' not in params:
324b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                # this is the "Authentication: Basic XXXXX==" case
325b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                pass
326b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            else:
327b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                params = parse_auth_params(params)
328b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return authtype, params
329b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return val
330b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
331b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef serialize_auth(val):
332b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if isinstance(val, (tuple, list)):
333b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        authtype, params = val
334b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if isinstance(params, dict):
335b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            params = ', '.join(map('%s="%s"'.__mod__, params.items()))
336b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        assert isinstance(params, str)
337b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return '%s %s' % (authtype, params)
338b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return val
339