Issue #1146 resolved

Problems handling uploaded files which contain commas and spaces in filename

Allan Crooks
created an issue

If you try uploading a file to CherryPy which contains a comma followed by space, it can have problems handling the uploaded content because of the filename.

Using the example found here:

1) Uploading a simple file called "boop.csv", I get this: {{{ myFile length: 7007 myFile filename: boop.csv myFile mime-type: text/csv }}}

2) Uploading a file called "foo, bar.csv", I get this: {{{ myFile length: 325 myFile filename: "foo myFile mime-type: text/csv }}}

3) Uploading a file called "bar, xxxx.csv", I get this: {{{ 404 Not Found

Missing parameters: myFile

Traceback (most recent call last): <snip> HTTPError: (404, 'Missing parameters: myFile') }}}

The behaviour does seem somewhat arbitrary, but some filenames seem to result in a truncated filename being submitted (ilke in the second case) or a broken request altogether.

(Recreated with Python 2.6.6 on a 64 bit install of Linux using CherryPy 3.2.2.)

Comments (4)

  1. Joel Rivera

    I spend some times on this, and I found out that the problem reside in the function cherrypy.lib.httputil.header_elements called from cherrypy._cpreqbody.Entity.init

    This is just the same method with some lines of plain printing, to show the problem, but it is preatty obvious because of the fieldvalue.split(","), I'm not sure what is the original intent to have this split, but I do know that if you change that , to ;, is going to blow up.

    def header_elements(fieldname, fieldvalue):
        """Return a sorted HeaderElement list from a comma-separated header string."""
        import sys
        print >>sys.stderr, "CALLING header_element with params %r %r"  % \
                            (fieldname,  fieldvalue)
        if not fieldvalue:
            return []
        result = []
        for element in fieldvalue.split(","):
            print >>sys.stderr, "ELEMENT IS %r" % element
            if fieldname.startswith("Accept") or fieldname == 'TE':
                hv = AcceptElement.from_str(element)
                hv = HeaderElement.from_str(element)
        return list(reversed(sorted(result)))

    any suggestions?

  2. Joel Rivera

    This simple patch, should make the trick, I'm not so sure about the hardcode list of one element, on the other side when that header is fetched it always use only the fist element, I couldn't find any RFC that specify that "Content-Disposition" should have only one element at a time.

    The other approximation is to handle the special case outside the cherrypy.lib.httputil but that involve introspection in the headers in cherrypy._cpreqbody around line 438 at the current changeset 3378:b0c48210b250.

  3. Log in to comment