Skip to content

Instantly share code, notes, and snippets.

@mahmoudajawad
Last active May 23, 2018 12:36
Show Gist options
  • Save mahmoudajawad/dd976910aa727a6c813658637a05139b to your computer and use it in GitHub Desktop.
Save mahmoudajawad/dd976910aa727a6c813658637a05139b to your computer and use it in GitHub Desktop.
Alternative parse_multipart function (to replace python cgi default implementation) that can read additional attributes.
def parse_multipart(rfile, boundary):
boundary = b'--' + boundary
rfile = re.compile(boundary+b'(?:\r\n|\n)').split(rfile.replace(b'\r\n'+boundary+b'--', b'').replace(b'\n'+boundary+b'--', b''))
pattern = b'Content-Disposition: form-data; name="?([\$a-zA-Z0-9\.\-_\\\:]+)"?(?:; filename="?([a-zA-Z0-9\.\-_]+)"?(?:\r\n|\n)Content-Type: ([a-zA-Z0-9\.\-_]+\/[a-zA-Z0-9\.\-_]+)(?:\r\n|\n)|(?:\r\n|\n))(?:\r\n|\n)(.+)'
multipart = {}
for part in rfile:
try:
multipart_key = re.match(pattern, part, re.DOTALL).group(1)
multipart[multipart_key] = [group for group in re.match(pattern, part, re.DOTALL).groups()]
if multipart[multipart_key][3][-2] == 13 and multipart[multipart_key][3][-1] == 10:
multipart[multipart_key][3] = multipart[multipart_key][3][:-2]
elif multipart[multipart_key][3][-1] == 10:
multipart[multipart_key][3][:-1]
except:
continue
return multipart
@mahmoudajawad
Copy link
Author

The problem with the builtin #Python cgi parse_multipart function (which is used by most of the networking and web frameworks) is that it doesn't read the additional attributes of a multipart request body, which could be carrying additional information when uploading a file.

This function however, does read the additional filename and Content-Type attributes if present and returns a dict with key being the request part name with its value being a group holding the next values [name, filename, Content-Type, content].

The second and third list values would be None if not present, meaning it's a key, value part, where if second and third values are not None we can expect a file in the forth value. I've already implemented this function in my own framework and it's working, however, I welcome any additional real, nasty world tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment