Django

Code

Show
Ignore:
Timestamp:
07/13/08 09:31:09 (6 months ago)
Author:
jbronn
Message:

gis: Merged revisions 7837-7838,7842-7852,7856-7869,7871,7876-7877,7882-7891,7900-7917 via svnmerge from trunk.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis

    • Property svnmerge-integrated changed from /django/trunk:1-7835 to /django/trunk:1-7917
  • django/branches/gis/django/http/multipartparser.py

    r7836 r7918  
    137137                    # we hit the next boundary/part of the multipart content. 
    138138                    self.handle_file_complete(old_field_name, counters) 
     139                    old_field_name = None 
    139140 
    140141                try: 
     
    270271        self._leftover = '' 
    271272        self.length = length 
    272         self._position = 0 
     273        self.position = 0 
    273274        self._remaining = length 
    274  
    275         # These fields are to do sanity checking to make sure we don't 
    276         # have infinite loops getting/ungetting from the stream. The 
    277         # purpose overall is to raise an exception if we perform lots 
    278         # of stream get/unget gymnastics without getting 
    279         # anywhere. Naturally this is not sound, but most probably 
    280         # would indicate a bug if the exception is raised. 
    281  
    282         # largest position tell us how far this lazystream has ever 
    283         # been advanced 
    284         self._largest_position = 0 
    285  
    286         # "modifications since" will start at zero and increment every 
    287         # time the position is modified but a new largest position is 
    288         # not achieved. 
    289         self._modifications_since = 0 
     275        self._unget_history = [] 
    290276 
    291277    def tell(self): 
     
    329315        else: 
    330316            output = self._producer.next() 
     317            self._unget_history = [] 
    331318        self.position += len(output) 
    332319        return output 
     
    351338        stream position and thus tell() will be rewound. 
    352339        """ 
     340        if not bytes: 
     341            return 
     342        self._update_unget_history(len(bytes)) 
    353343        self.position -= len(bytes) 
    354344        self._leftover = ''.join([bytes, self._leftover]) 
    355345 
    356     def _set_position(self, value): 
    357         if value > self._largest_position: 
    358             self._modifications_since = 0 
    359             self._largest_position = value 
    360         else: 
    361             self._modifications_since += 1 
    362             if self._modifications_since > 500: 
    363                 raise SuspiciousOperation( 
    364                     "The multipart parser got stuck, which shouldn't happen with" 
    365                     " normal uploaded files. Check for malicious upload activity;" 
    366                     " if there is none, report this to the Django developers." 
    367                 ) 
    368  
    369         self._position = value 
    370  
    371     position = property(lambda self: self._position, _set_position) 
     346    def _update_unget_history(self, num_bytes): 
     347        """ 
     348        Updates the unget history as a sanity check to see if we've pushed 
     349        back the same number of bytes in one chunk. If we keep ungetting the 
     350        same number of bytes many times (here, 50), we're mostly likely in an 
     351        infinite loop of some sort. This is usually caused by a 
     352        maliciously-malformed MIME request. 
     353        """ 
     354        self._unget_history = [num_bytes] + self._unget_history[:49] 
     355        number_equal = len([current_number for current_number in self._unget_history 
     356                            if current_number == num_bytes]) 
     357 
     358        if number_equal > 40: 
     359            raise SuspiciousOperation( 
     360                "The multipart parser got stuck, which shouldn't happen with" 
     361                " normal uploaded files. Check for malicious upload activity;" 
     362                " if there is none, report this to the Django developers." 
     363            ) 
    372364 
    373365class ChunkIter(object): 
  • django/branches/gis/django/http/utils.py

    r7354 r7918  
    3232        response.content = '' 
    3333    return response 
     34 
     35def fix_IE_for_attach(request, response): 
     36    """ 
     37    This function will prevent Django from serving a Content-Disposition header 
     38    while expecting the browser to cache it (only when the browser is IE). This 
     39    leads to IE not allowing the client to download. 
     40    """ 
     41    if 'MSIE' not in request.META.get('HTTP_USER_AGENT', '').upper(): 
     42        return response 
     43 
     44    offending_headers = ('no-cache', 'no-store') 
     45    if response.has_header('Content-Disposition'): 
     46        try: 
     47            del response['Pragma'] 
     48        except KeyError: 
     49            pass 
     50        if response.has_header('Cache-Control'): 
     51            cache_control_values = [value.strip() for value in 
     52                    response['Cache-Control'].split(',') 
     53                    if value.strip().lower() not in offending_headers] 
     54 
     55            if not len(cache_control_values): 
     56                del response['Cache-Control'] 
     57            else: 
     58                response['Cache-Control'] = ', '.join(cache_control_values) 
     59 
     60    return response 
     61 
     62def fix_IE_for_vary(request, response): 
     63    """ 
     64    This function will fix the bug reported at 
     65    http://support.microsoft.com/kb/824847/en-us?spid=8722&sid=global 
     66    by clearing the Vary header whenever the mime-type is not safe 
     67    enough for Internet Explorer to handle.  Poor thing. 
     68    """ 
     69    if 'MSIE' not in request.META.get('HTTP_USER_AGENT', '').upper(): 
     70        return response 
     71 
     72    # These mime-types that are decreed "Vary-safe" for IE: 
     73    safe_mime_types = ('text/html', 'text/plain', 'text/sgml') 
     74 
     75    # The first part of the Content-Type field will be the MIME type, 
     76    # everything after ';', such as character-set, can be ignored. 
     77    if response['Content-Type'].split(';')[0] not in safe_mime_types: 
     78        try: 
     79            del response['Vary'] 
     80        except KeyError: 
     81            pass 
     82 
     83    return response 
     84