Commit fd1cd85e authored by Barry Warsaw's avatar Barry Warsaw

Oleg Broytmann's support for RFC 2231 encoded parameters, SF patch #549133

Specifically,

_formatparam(): Teach this about encoded `param' arguments, which are
a 3-tuple of items (charset, language, value).  language is ignored.

_unquotevalue(): Handle both 3-tuple RFC 2231 values and unencoded
values.

_get_params_preserve(): Decode the parameters before returning them.

get_params(), get_param(): Use _unquotevalue().

get_filename(), get_boundary(): Teach these about encoded (3-tuple)
parameters.
parent 6153b0c3
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import re import re
import warnings import warnings
from cStringIO import StringIO from cStringIO import StringIO
from types import ListType, StringType from types import ListType, TupleType, StringType
# Intrapackage imports # Intrapackage imports
from email import Errors from email import Errors
...@@ -27,13 +27,19 @@ tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') ...@@ -27,13 +27,19 @@ tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
# Helper function # Helper functions
def _formatparam(param, value=None, quote=1): def _formatparam(param, value=None, quote=1):
"""Convenience function to format and return a key=value pair. """Convenience function to format and return a key=value pair.
Will quote the value if needed or if quote is true. This will quote the value if needed or if quote is true.
""" """
if value is not None and len(value) > 0: if value is not None and len(value) > 0:
# TupleType is used for RFC 2231 encoded parameter values where items
# are (charset, language, value). charset is a string, not a Charset
# instance.
if isinstance(value, TupleType):
# Convert to ascii, ignore language
value = unicode(value[2], value[0]).encode("ascii")
# BAW: Please check this. I think that if quote is set it should # BAW: Please check this. I think that if quote is set it should
# force quoting even if not necessary. # force quoting even if not necessary.
if quote or tspecials.search(value): if quote or tspecials.search(value):
...@@ -44,6 +50,13 @@ def _formatparam(param, value=None, quote=1): ...@@ -44,6 +50,13 @@ def _formatparam(param, value=None, quote=1):
return param return param
def _unquotevalue(value):
if isinstance(value, TupleType):
return (value[0], value[1], Utils.unquote(value[2]))
else:
return Utils.unquote(value)
class Message: class Message:
"""Basic message object for use inside the object tree. """Basic message object for use inside the object tree.
...@@ -400,6 +413,7 @@ class Message: ...@@ -400,6 +413,7 @@ class Message:
name = p name = p
val = '' val = ''
params.append((name, val)) params.append((name, val))
params = Utils.decode_params(params)
return params return params
def get_params(self, failobj=None, header='content-type', unquote=1): def get_params(self, failobj=None, header='content-type', unquote=1):
...@@ -420,7 +434,7 @@ class Message: ...@@ -420,7 +434,7 @@ class Message:
if params is missing: if params is missing:
return failobj return failobj
if unquote: if unquote:
return [(k, Utils.unquote(v)) for k, v in params] return [(k, _unquotevalue(v)) for k, v in params]
else: else:
return params return params
...@@ -439,7 +453,7 @@ class Message: ...@@ -439,7 +453,7 @@ class Message:
for k, v in self._get_params_preserve(failobj, header): for k, v in self._get_params_preserve(failobj, header):
if k.lower() == param.lower(): if k.lower() == param.lower():
if unquote: if unquote:
return Utils.unquote(v) return _unquotevalue(v)
else: else:
return v return v
return failobj return failobj
...@@ -548,7 +562,13 @@ class Message: ...@@ -548,7 +562,13 @@ class Message:
filename = self.get_param('filename', missing, 'content-disposition') filename = self.get_param('filename', missing, 'content-disposition')
if filename is missing: if filename is missing:
return failobj return failobj
return Utils.unquote(filename.strip()) if isinstance(filename, TupleType):
# It's an RFC 2231 encoded parameter
newvalue = _unquotevalue(filename)
return unicode(newvalue[2], newvalue[0])
else:
newvalue = _unquotevalue(filename.strip())
return newvalue
def get_boundary(self, failobj=None): def get_boundary(self, failobj=None):
"""Return the boundary associated with the payload if present. """Return the boundary associated with the payload if present.
...@@ -560,7 +580,7 @@ class Message: ...@@ -560,7 +580,7 @@ class Message:
boundary = self.get_param('boundary', missing) boundary = self.get_param('boundary', missing)
if boundary is missing: if boundary is missing:
return failobj return failobj
return Utils.unquote(boundary.strip()) return _unquotevalue(boundary.strip())
def set_boundary(self, boundary): def set_boundary(self, boundary):
"""Set the boundary parameter in Content-Type: to 'boundary'. """Set the boundary parameter in Content-Type: to 'boundary'.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment