Changeset 7918 for django/branches/gis/django/http
- Timestamp:
- 07/13/08 09:31:09 (6 months ago)
- Files:
-
- django/branches/gis (modified) (1 prop)
- django/branches/gis/django/http/multipartparser.py (modified) (4 diffs)
- django/branches/gis/django/http/utils.py (modified) (1 diff)
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 137 137 # we hit the next boundary/part of the multipart content. 138 138 self.handle_file_complete(old_field_name, counters) 139 old_field_name = None 139 140 140 141 try: … … 270 271 self._leftover = '' 271 272 self.length = length 272 self. _position = 0273 self.position = 0 273 274 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 = [] 290 276 291 277 def tell(self): … … 329 315 else: 330 316 output = self._producer.next() 317 self._unget_history = [] 331 318 self.position += len(output) 332 319 return output … … 351 338 stream position and thus tell() will be rewound. 352 339 """ 340 if not bytes: 341 return 342 self._update_unget_history(len(bytes)) 353 343 self.position -= len(bytes) 354 344 self._leftover = ''.join([bytes, self._leftover]) 355 345 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 ) 372 364 373 365 class ChunkIter(object): django/branches/gis/django/http/utils.py
r7354 r7918 32 32 response.content = '' 33 33 return response 34 35 def 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 62 def 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
