Skip to content

Commit

Permalink
Improve parsing of multipart/form-data headers.
Browse files Browse the repository at this point in the history
This change was motivated by google app engine's xmpp support,
which uses different spacing in the header than other common clients
and quotes its boundary string.

Based on changes by jehiah:
http://github.com/jehiah/tornado/commit/18cb45ca73859fa81883bd10c9cd8e051865096a
http://github.com/jehiah/tornado/commit/9d67963466878550368b932746bb4a244a593905
  • Loading branch information
Ben Darnell committed May 31, 2010
1 parent 982554e commit 2b06840
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
14 changes: 12 additions & 2 deletions tornado/httpserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,11 +305,21 @@ def _on_request_body(self, data):
self._request.arguments.setdefault(name, []).extend(
values)
elif content_type.startswith("multipart/form-data"):
boundary = content_type[30:]
if boundary: self._parse_mime_body(boundary, data)
if 'boundary=' in content_type:
boundary = content_type.split('boundary=',1)[1]
if boundary: self._parse_mime_body(boundary, data)
else:
logging.warning("Invalid multipart/form-data")
self.request_callback(self._request)

def _parse_mime_body(self, boundary, data):
# The standard allows for the boundary to be quoted in the header,
# although it's rare (it happens at least for google app engine
# xmpp). I think we're also supposed to handle backslash-escapes
# here but I'll save that until we see a client that uses them
# in the wild.
if boundary.startswith('"') and boundary.endswith('"'):
boundary = boundary[1:-1]
if data.endswith("\r\n"):
footer_length = len(boundary) + 6
else:
Expand Down
9 changes: 7 additions & 2 deletions tornado/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,11 @@ def __init__(self, environ):
for name, values in cgi.parse_qs(self.body).iteritems():
self.arguments.setdefault(name, []).extend(values)
elif content_type.startswith("multipart/form-data"):
boundary = content_type[30:]
if boundary: self._parse_mime_body(boundary)
if 'boundary=' in content_type:
boundary = content_type.split('boundary=',1)[1]
if boundary: self._parse_mime_body(boundary)
else:
logging.warning("Invalid multipart/form-data")

self._start_time = time.time()
self._finish_time = None
Expand All @@ -148,6 +151,8 @@ def request_time(self):
return self._finish_time - self._start_time

def _parse_mime_body(self, boundary):
if boundary.startswith('"') and boundary.endswith('"'):
boundary = boundary[1:-1]
if self.body.endswith("\r\n"):
footer_length = len(boundary) + 6
else:
Expand Down

0 comments on commit 2b06840

Please sign in to comment.