Ticket #1484: 1484.trunk.5.diff

File 1484.trunk.5.diff, 6.5 KB (added by Maniac <Maniac@…>, 18 years ago)

Patch 5 for trunk: updated for line count

  • django/utils/httpwrappers.py

     
    22from pprint import pformat
    33from urllib import urlencode
    44from django.utils.datastructures import MultiValueDict
     5import cgi
     6from StringIO import StringIO
    57
    68try:
    79    # The mod_python version is more efficient, so try importing it first.
     
    3234    def get_full_path(self):
    3335        return ''
    3436
    35 def parse_file_upload(header_dict, post_data):
     37class FileDict(dict):
     38    "Keeps uploaded file as a file-like object and reads its content on demand"
     39    def __getitem__(self, name):
     40        if name=='content' and not 'content' in self:
     41            self['file'].seek(0, 2)
     42            size = self['file'].tell()
     43            self['file'].seek(0, 0)
     44            self['content']=self['file'].read(size)
     45        return dict.__getitem__(self, name)
     46
     47    def __deepcopy__(self, memo={}):
     48        self['content'] # make sure file content is loaded
     49        import copy
     50        result = self.__class__()
     51        memo[id(self)] = result
     52        for key, value in dict.items(self):
     53            dict.__setitem__(result, copy.deepcopy(key, memo), copy.deepcopy(value, memo))
     54        return result
     55
     56class FieldStorage(cgi.FieldStorage):
     57    "cgi.FieldStorage with ability to store files on disk or in memory"
     58    def make_file(self, binary=None):
     59        from django.conf.settings import STORE_UPLOAD_ON_DISK
     60        if STORE_UPLOAD_ON_DISK:
     61            return cgi.FieldStorage.make_file(self, binary)
     62        else:
     63            return StringIO()
     64
     65def parse_file_upload(post_stream, environ):
    3666    "Returns a tuple of (POST MultiValueDict, FILES MultiValueDict)"
    37     import email, email.Message
    38     from cgi import parse_header
    39     raw_message = '\r\n'.join(['%s:%s' % pair for pair in header_dict.items()])
    40     raw_message += '\r\n\r\n' + post_data
    41     msg = email.message_from_string(raw_message)
     67    fs = FieldStorage(post_stream, environ=environ)
    4268    POST = MultiValueDict()
    4369    FILES = MultiValueDict()
    44     for submessage in msg.get_payload():
    45         if isinstance(submessage, email.Message.Message):
    46             name_dict = parse_header(submessage['Content-Disposition'])[1]
    47             # name_dict is something like {'name': 'file', 'filename': 'test.txt'} for file uploads
    48             # or {'name': 'blah'} for POST fields
    49             # We assume all uploaded files have a 'filename' set.
    50             if name_dict.has_key('filename'):
    51                 assert type([]) != type(submessage.get_payload()), "Nested MIME messages are not supported"
    52                 if not name_dict['filename'].strip():
     70    for key in fs.keys():
     71        # We can't use FieldStorage.getlist to get contents of a
     72        # field as a list because for file fields it returns only filenames
     73        if type(fs[key]) == type([]):
     74            field_list = fs[key]
     75        else:
     76            field_list = [fs[key]]
     77        for field in field_list:
     78            if hasattr(field, 'filename') and field.filename is not None:
     79                if not field.filename.strip():
    5380                    continue
    5481                # IE submits the full path, so trim everything but the basename.
    5582                # (We can't use os.path.basename because it expects Linux paths.)
    56                 filename = name_dict['filename'][name_dict['filename'].rfind("\\")+1:]
    57                 FILES.appendlist(name_dict['name'], {
     83                filename = field.filename[field.filename.rfind("\\") + 1:]
     84                FILES.appendlist(key, FileDict({
    5885                    'filename': filename,
    59                     'content-type': (submessage.has_key('Content-Type') and submessage['Content-Type'] or None),
    60                     'content': submessage.get_payload(),
    61                 })
     86                    'content-type': field.type,
     87                    'file': field.file,
     88                }))
    6289            else:
    63                 POST.appendlist(name_dict['name'], submessage.get_payload())
     90                POST.appendlist(key, field.value)
    6491    return POST, FILES
    6592
    6693class QueryDict(MultiValueDict):
  • django/conf/global_settings.py

     
    202202# http://psyco.sourceforge.net/
    203203ENABLE_PSYCO = False
    204204
     205# Whether to store uploaded files in temp files rather than in memory.
     206# Storing files on disk may be necessary for accepting large files.
     207STORE_UPLOAD_ON_DISK = False
     208
    205209##############
    206210# MIDDLEWARE #
    207211##############
  • django/core/handlers/wsgi.py

     
    6666        # Populates self._post and self._files
    6767        if self.environ['REQUEST_METHOD'] == 'POST':
    6868            if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
    69                 header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')])
    70                 header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
    71                 self._post, self._files = httpwrappers.parse_file_upload(header_dict, self.raw_post_data)
     69                self._post, self._files = httpwrappers.parse_file_upload(self.environ['wsgi.input'], self.environ)
    7270            else:
    7371                self._post, self._files = httpwrappers.QueryDict(self.raw_post_data), datastructures.MultiValueDict()
    7472        else:
  • django/core/handlers/modpython.py

     
    2323    def _load_post_and_files(self):
    2424        "Populates self._post and self._files"
    2525        if self._req.headers_in.has_key('content-type') and self._req.headers_in['content-type'].startswith('multipart'):
    26             self._post, self._files = httpwrappers.parse_file_upload(self._req.headers_in, self.raw_post_data)
     26            environ = dict(self.META)
     27            environ['CONTENT_LENGTH'] = environ['HTTP_CONTENT_LENGTH']
     28            environ['CONTENT_TYPE'] = environ['HTTP_CONTENT_TYPE']
     29            self._post, self._files = httpwrappers.parse_file_upload(self._req, environ)
    2730        else:
    2831            self._post, self._files = httpwrappers.QueryDict(self.raw_post_data), datastructures.MultiValueDict()
    2932
Back to Top