<s> """<STR_LIT>""" <EOL> import cgi <EOL> from django . conf import settings <EOL> from django . core . exceptions import SuspiciousOperation <EOL> from django . utils . datastructures import MultiValueDict <EOL> from django . utils . encoding import force_unicode <EOL> from django . utils . text import unescape_entities <EOL> from django . core . files . uploadhandler import StopUpload , SkipFile , StopFutureHandlers <EOL> __all__ = ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) <EOL> class MultiPartParserError ( Exception ) : <EOL> pass <EOL> class InputStreamExhausted ( Exception ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> RAW = "<STR_LIT>" <EOL> FILE = "<STR_LIT:file>" <EOL> FIELD = "<STR_LIT>" <EOL> class MultiPartParser ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , META , input_data , upload_handlers , encoding = None ) : <EOL> """<STR_LIT>""" <EOL> content_type = META . get ( '<STR_LIT>' , META . get ( '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> if not content_type . startswith ( '<STR_LIT>' ) : <EOL> raise MultiPartParserError ( '<STR_LIT>' % content_type ) <EOL> ctypes , opts = parse_header ( content_type ) <EOL> boundary = opts . get ( '<STR_LIT>' ) <EOL> if not boundary or not cgi . valid_boundary ( boundary ) : <EOL> raise MultiPartParserError ( '<STR_LIT>' % boundary ) <EOL> try : <EOL> content_length = int ( META . get ( '<STR_LIT>' , META . get ( '<STR_LIT>' , <NUM_LIT:0> ) ) ) <EOL> except ( ValueError , TypeError ) : <EOL> content_length = <NUM_LIT:0> <EOL> if content_length <= <NUM_LIT:0> : <EOL> raise MultiPartParserError ( "<STR_LIT>" % content_length ) <EOL> self . _boundary = boundary <EOL> self . _input_data = input_data <EOL> self . _chunk_size = min ( <NUM_LIT:2> ** <NUM_LIT> - <NUM_LIT:4> , * [ x . chunk_size for x in upload_handlers if x . chunk_size ] ) <EOL> self . _meta = META <EOL> self . _encoding = encoding or settings . DEFAULT_CHARSET <EOL> self . _content_length = content_length <EOL> self . _upload_handlers = upload_handlers <EOL> def parse ( self ) : <EOL> """<STR_LIT>""" <EOL> from django . http import QueryDict <EOL> encoding = self . _encoding <EOL> handlers = self . _upload_handlers <EOL> limited_input_data = LimitBytes ( self . _input_data , self . _content_length ) <EOL> for handler in handlers : <EOL> result = handler . handle_raw_input ( limited_input_data , <EOL> self . _meta , <EOL> self . _content_length , <EOL> self . _boundary , <EOL> encoding ) <EOL> if result is not None : <EOL> return result [ <NUM_LIT:0> ] , result [ <NUM_LIT:1> ] <EOL> self . _post = QueryDict ( '<STR_LIT>' , mutable = True ) <EOL> self . _files = MultiValueDict ( ) <EOL> stream = LazyStream ( ChunkIter ( limited_input_data , self . _chunk_size ) ) <EOL> old_field_name = None <EOL> counters = [ <NUM_LIT:0> ] * len ( handlers ) <EOL> try : <EOL> for item_type , meta_data , field_stream in Parser ( stream , self . _boundary ) : <EOL> if old_field_name : <EOL> self . handle_file_complete ( old_field_name , counters ) <EOL> old_field_name = None <EOL> try : <EOL> disposition = meta_data [ '<STR_LIT>' ] [ <NUM_LIT:1> ] <EOL> field_name = disposition [ '<STR_LIT:name>' ] . strip ( ) <EOL> except ( KeyError , IndexError , AttributeError ) : <EOL> continue <EOL> transfer_encoding = meta_data . get ( '<STR_LIT>' ) <EOL> field_name = force_unicode ( field_name , encoding , errors = '<STR_LIT:replace>' ) <EOL> if item_type == FIELD : <EOL> if transfer_encoding == '<STR_LIT>' : <EOL> raw_data = field_stream . read ( ) <EOL> try : <EOL> data = str ( raw_data ) . decode ( '<STR_LIT>' ) <EOL> except : <EOL> data = raw_data <EOL> else : <EOL> data = field_stream . read ( ) <EOL> self . _post . appendlist ( field_name , <EOL> force_unicode ( data , encoding , errors = '<STR_LIT:replace>' ) ) <EOL> elif item_type == FILE : <EOL> file_name = disposition . get ( '<STR_LIT:filename>' ) <EOL> if not file_name : <EOL> continue <EOL> file_name = force_unicode ( file_name , encoding , errors = '<STR_LIT:replace>' ) <EOL> file_name = self . IE_sanitize ( unescape_entities ( file_name ) ) <EOL> content_type = meta_data . get ( '<STR_LIT>' , ( '<STR_LIT>' , ) ) [ <NUM_LIT:0> ] . strip ( ) <EOL> try : <EOL> charset = meta_data . get ( '<STR_LIT>' , ( <NUM_LIT:0> , { } ) ) [ <NUM_LIT:1> ] . get ( '<STR_LIT>' , None ) <EOL> except : <EOL> charset = None <EOL> try : <EOL> content_length = int ( meta_data . get ( '<STR_LIT>' ) [ <NUM_LIT:0> ] ) <EOL> except ( IndexError , TypeError , ValueError ) : <EOL> content_length = None <EOL> counters = [ <NUM_LIT:0> ] * len ( handlers ) <EOL> try : <EOL> for handler in handlers : <EOL> try : <EOL> handler . new_file ( field_name , file_name , <EOL> content_type , content_length , <EOL> charset ) <EOL> except StopFutureHandlers : <EOL> break <EOL> for chunk in field_stream : <EOL> if transfer_encoding == '<STR_LIT>' : <EOL> try : <EOL> chunk = str ( chunk ) . decode ( '<STR_LIT>' ) <EOL> except Exception , e : <EOL> raise MultiPartParserError ( "<STR_LIT>" % e ) <EOL> for i , handler in enumerate ( handlers ) : <EOL> chunk_length = len ( chunk ) <EOL> chunk = handler . receive_data_chunk ( chunk , <EOL> counters [ i ] ) <EOL> counters [ i ] += chunk_length <EOL> if chunk is None : <EOL> break <EOL> except SkipFile , e : <EOL> exhaust ( field_stream ) <EOL> else : <EOL> old_field_name = field_name <EOL> else : <EOL> exhaust ( stream ) <EOL> except StopUpload , e : <EOL> if not e . connection_reset : <EOL> exhaust ( limited_input_data ) <EOL> else : <EOL> exhaust ( limited_input_data ) <EOL> for handler in handlers : <EOL> retval = handler . upload_complete ( ) <EOL> if retval : <EOL> break <EOL> return self . _post , self . _files <EOL> def handle_file_complete ( self , old_field_name , counters ) : <EOL> """<STR_LIT>""" <EOL> for i , handler in enumerate ( self . _upload_handlers ) : <EOL> file_obj = handler . file_complete ( counters [ i ] ) <EOL> if file_obj : <EOL> self . _files . appendlist ( force_unicode ( old_field_name , <EOL> self . _encoding , <EOL> errors = '<STR_LIT:replace>' ) , <EOL> file_obj ) <EOL> break <EOL> def IE_sanitize ( self , filename ) : <EOL> """<STR_LIT>""" <EOL> return filename and filename [ filename . rfind ( "<STR_LIT:\\>" ) + <NUM_LIT:1> : ] . strip ( ) <EOL> class LazyStream ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , producer , length = None ) : <EOL> """<STR_LIT>""" <EOL> self . _producer = producer <EOL> self . _empty = False <EOL> self . _leftover = '<STR_LIT>' <EOL> self . length = length <EOL> self . position = <NUM_LIT:0> <EOL> self . _remaining = length <EOL> self . _unget_history = [ ] <EOL> def tell ( self ) : <EOL> return self . position <EOL> def read ( self , size = None ) : <EOL> def parts ( ) : <EOL> remaining = ( size is not None and [ size ] or [ self . _remaining ] ) [ <NUM_LIT:0> ] <EOL> if remaining is None : <EOL> yield '<STR_LIT>' . join ( self ) <EOL> return <EOL> while remaining != <NUM_LIT:0> : <EOL> assert remaining > <NUM_LIT:0> , '<STR_LIT>' <EOL> chunk = self . next ( ) <EOL> emitting = chunk [ : remaining ] <EOL> self . unget ( chunk [ remaining : ] ) <EOL> remaining -= len ( emitting ) <EOL> yield emitting <EOL> out = '<STR_LIT>' . join ( parts ( ) ) <EOL> return out <EOL> def next ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . _leftover : <EOL> output = self . _leftover <EOL> self . _leftover = '<STR_LIT>' <EOL> else : <EOL> output = self . _producer . next ( ) <EOL> self . _unget_history = [ ] <EOL> self . position += len ( output ) <EOL> return output <EOL> def close ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _producer = [ ] <EOL> def __iter__ ( self ) : <EOL> return self <EOL> def unget ( self , bytes ) : <EOL> """<STR_LIT>""" <EOL> if not bytes : <EOL> return <EOL> self . _update_unget_history ( len ( bytes ) ) <EOL> self . position -= len ( bytes ) <EOL> self . _leftover = '<STR_LIT>' . join ( [ bytes , self . _leftover ] ) <EOL> def _update_unget_history ( self , num_bytes ) : <EOL> """<STR_LIT>""" <EOL> self . _unget_history = [ num_bytes ] + self . _unget_history [ : <NUM_LIT> ] <EOL> number_equal = len ( [ current_number for current_number in self . _unget_history <EOL> if current_number == num_bytes ] ) <EOL> if number_equal > <NUM_LIT> : <EOL> raise SuspiciousOperation ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) <EOL> class ChunkIter ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , flo , chunk_size = <NUM_LIT:64> * <NUM_LIT> ) : <EOL> self . flo = flo <EOL> self . chunk_size = chunk_size <EOL> def next ( self ) : <EOL> try : <EOL> data = self . flo . read ( self . chunk_size ) <EOL> except InputStreamExhausted : <EOL> raise StopIteration ( ) <EOL> if data : <EOL> return data <EOL> else : <EOL> raise StopIteration ( ) <EOL> def __iter__ ( self ) : <EOL> return self <EOL> class LimitBytes ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , fileobject , length ) : <EOL> self . _file = fileobject <EOL> self . remaining = length <EOL> def read ( self , num_bytes = None ) : <EOL> """<STR_LIT>""" <EOL> if self . remaining <= <NUM_LIT:0> : <EOL> raise InputStreamExhausted ( ) <EOL> if num_bytes is None : <EOL> num_bytes = self . remaining <EOL> else : <EOL> num_bytes = min ( num_bytes , self . remaining ) <EOL> self . remaining -= num_bytes <EOL> return self . _file . read ( num_bytes ) <EOL> class InterBoundaryIter ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , stream , boundary ) : <EOL> self . _stream = stream <EOL> self . _boundary = boundary <EOL> def __iter__ ( self ) : <EOL> return self <EOL> def next ( self ) : <EOL> try : <EOL> return LazyStream ( BoundaryIter ( self . _stream , self . _boundary ) ) <EOL> except InputStreamExhausted : <EOL> raise StopIteration ( ) <EOL> class BoundaryIter ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , stream , boundary ) : <EOL> self . _stream = stream <EOL> self . _boundary = boundary <EOL> self . _done = False <EOL> self . _rollback = len ( boundary ) + <NUM_LIT:6> <EOL> unused_char = self . _stream . read ( <NUM_LIT:1> ) <EOL> if not unused_char : <EOL> raise InputStreamExhausted ( ) <EOL> self . _stream . unget ( unused_char ) <EOL> try : <EOL> from mx . TextTools import FS <EOL> self . _fs = FS ( boundary ) . find <EOL> except ImportError : <EOL> self . _fs = lambda data : data . find ( boundary ) <EOL> def __iter__ ( self ) : <EOL> return self <EOL> def next ( self ) : <EOL> if self . _done : <EOL> raise StopIteration ( ) <EOL> stream = self . _stream <EOL> rollback = self . _rollback <EOL> bytes_read = <NUM_LIT:0> <EOL> chunks = [ ] <EOL> for bytes in stream : <EOL> bytes_read += len ( bytes ) <EOL> chunks . append ( bytes ) <EOL> if bytes_read > rollback : <EOL> break <EOL> if not bytes : <EOL> break <EOL> else : <EOL> self . _done = True <EOL> if not chunks : <EOL> raise StopIteration ( ) <EOL> chunk = '<STR_LIT>' . join ( chunks ) <EOL> boundary = self . _find_boundary ( chunk , len ( chunk ) < self . _rollback ) <EOL> if boundary : <EOL> end , next = boundary <EOL> stream . unget ( chunk [ next : ] ) <EOL> self . _done = True <EOL> return chunk [ : end ] <EOL> else : <EOL> if not chunk [ : - rollback ] : <EOL> self . _done = True <EOL> return chunk <EOL> else : <EOL> stream . unget ( chunk [ - rollback : ] ) <EOL> return chunk [ : - rollback ] <EOL> def _find_boundary ( self , data , eof = False ) : <EOL> """<STR_LIT>""" <EOL> index = self . _fs ( data ) <EOL> if index < <NUM_LIT:0> : <EOL> return None <EOL> else : <EOL> end = index <EOL> next = index + len ( self . _boundary ) <EOL> if data [ max ( <NUM_LIT:0> , end - <NUM_LIT:1> ) ] == '<STR_LIT:\n>' : <EOL> end -= <NUM_LIT:1> <EOL> if data [ max ( <NUM_LIT:0> , end - <NUM_LIT:1> ) ] == '<STR_LIT:\r>' : <EOL> end -= <NUM_LIT:1> <EOL> return end , next <EOL> def exhaust ( stream_or_iterable ) : <EOL> """<STR_LIT>""" <EOL> iterator = None <EOL> try : <EOL> iterator = iter ( stream_or_iterable ) <EOL> except TypeError : <EOL> iterator = ChunkIter ( stream_or_iterable , <NUM_LIT> ) <EOL> if iterator is None : <EOL> raise MultiPartParserError ( '<STR_LIT>' ) <EOL> for __ in iterator : <EOL> pass <EOL> def parse_boundary_stream ( stream , max_header_size ) : <EOL> """<STR_LIT>""" <EOL> chunk = stream . read ( max_header_size ) <EOL> header_end = chunk . find ( '<STR_LIT>' ) <EOL> def _parse_header ( line ) : <EOL> main_value_pair , params = parse_header ( line ) <EOL> try : <EOL> name , value = main_value_pair . split ( '<STR_LIT::>' , <NUM_LIT:1> ) <EOL> except : <EOL> raise ValueError ( "<STR_LIT>" % line ) <EOL> return name , ( value , params ) <EOL> if header_end == - <NUM_LIT:1> : <EOL> stream . unget ( chunk ) <EOL> return ( RAW , { } , stream ) <EOL> header = chunk [ : header_end ] <EOL> stream . unget ( chunk [ header_end + <NUM_LIT:4> : ] ) <EOL> TYPE = RAW <EOL> outdict = { } <EOL> for line in header . split ( '<STR_LIT:\r\n>' ) : <EOL> try : <EOL> name , ( value , params ) = _parse_header ( line ) <EOL> except : <EOL> continue <EOL> if name == '<STR_LIT>' : <EOL> TYPE = FIELD <EOL> if params . get ( '<STR_LIT:filename>' ) : <EOL> TYPE = FILE <EOL> outdict [ name ] = value , params <EOL> if TYPE == RAW : <EOL> stream . unget ( chunk ) <EOL> return ( TYPE , outdict , stream ) <EOL> class Parser ( object ) : <EOL> def __init__ ( self , stream , boundary ) : <EOL> self . _stream = stream <EOL> self . _separator = '<STR_LIT>' + boundary <EOL> def __iter__ ( self ) : <EOL> boundarystream = InterBoundaryIter ( self . _stream , self . _separator ) <EOL> for sub_stream in boundarystream : <EOL> yield parse_boundary_stream ( sub_stream , <NUM_LIT> ) <EOL> def parse_header ( line ) : <EOL> """<STR_LIT>""" <EOL> plist = _parse_header_params ( '<STR_LIT:;>' + line ) <EOL> key = plist . pop ( <NUM_LIT:0> ) . lower ( ) <EOL> pdict = { } <EOL> for p in plist : <EOL> i = p . find ( '<STR_LIT:=>' ) <EOL> if i >= <NUM_LIT:0> : <EOL> name = p [ : i ] . strip ( ) . lower ( ) <EOL> value = p [ i + <NUM_LIT:1> : ] . strip ( ) <EOL> if len ( value ) >= <NUM_LIT:2> and value [ <NUM_LIT:0> ] == value [ - <NUM_LIT:1> ] == '<STR_LIT:">' : <EOL> value = value [ <NUM_LIT:1> : - <NUM_LIT:1> ] <EOL> value = value . replace ( '<STR_LIT>' , '<STR_LIT:\\>' ) . replace ( '<STR_LIT>' , '<STR_LIT:">' ) <EOL> pdict [ name ] = value <EOL> return key , pdict <EOL> def _parse_header_params ( s ) : <EOL> plist = [ ] <EOL> while s [ : <NUM_LIT:1> ] == '<STR_LIT:;>' : <EOL> s = s [ <NUM_LIT:1> : ] <EOL> end = s . find ( '<STR_LIT:;>' ) <EOL> while end > <NUM_LIT:0> and s . count ( '<STR_LIT:">' , <NUM_LIT:0> , end ) % <NUM_LIT:2> : <EOL> end = s . find ( '<STR_LIT:;>' , end + <NUM_LIT:1> ) <EOL> if end < <NUM_LIT:0> : <EOL> end = len ( s ) <EOL> f = s [ : end ] <EOL> plist . append ( f . strip ( ) ) <EOL> s = s [ end : ] <EOL> return plist </s>
