o xgrm@s<dZddlZddlZddlZddlZddlZddlmZddlm Z ddl m Z m Z m Z mZddlmZmZmZddlmZddlmZd ZGd d d eZGd d d eZdZdZdZeeegZGdddZ GdddZ!GdddZ"GdddZ#GdddZ$ddZ%ddZ&Gdd d Z'd!d"Z(d#d$Z)dS)%z Multi-part parsing for file uploads. Exposes one class, ``MultiPartParser``, which feeds chunks of uploaded data to file upload handlers for processing. N)unquote)settings)RequestDataTooBigSuspiciousMultipartFormTooManyFieldsSentTooManyFilesSent)SkipFileStopFutureHandlers StopUpload)MultiValueDict) force_str)MultiPartParserMultiPartParserErrorInputStreamExhaustedc@s eZdZdS)rN)__name__ __module__ __qualname__rr=/usr/lib/python3/dist-packages/django/http/multipartparser.pyrsrc@seZdZdZdS)rz5 No more reads are allowed from this device. N)rrr__doc__rrrrr srrawfilefieldc@sFeZdZdZdddZddZddZd d Zd d ZeZ d dZ dS)r z A rfc2388 multipart/form-data parser. ``MultiValueDict.parse()`` reads the input stream in ``chunk_size`` chunks and returns a tuple of ``(MultiValueDict(POST), MultiValueDict(FILES))``. Nc Cs$|dd}|dstd|z t|d\}}Wnty+tdt|w|d}|r8t|s@tdt|z t |d d } Wn t t fyWd } Ynw| d krbtd | t |t rl|d}||_||_d d |D} tdg| |_||_|ptj|_| |_||_dS)a Initialize the MultiPartParser object. :META: The standard ``META`` dictionary in Django request objects. :input_data: The raw post data, as a file-like object. :upload_handlers: A list of UploadHandler instances that perform operations on the uploaded data. :encoding: The encoding with which to treat the incoming data. CONTENT_TYPEz multipart/zInvalid Content-Type: %sasciiz/Invalid non-ASCII Content-Type in multipart: %sboundaryz!Invalid boundary in multipart: %sCONTENT_LENGTHrzInvalid content length: %rcSsg|]}|jr|jqSr) chunk_size).0xrrr bsz,MultiPartParser.__init__..iN)get startswithr parse_headerencodeUnicodeEncodeErrorr cgivalid_boundaryint ValueError TypeError isinstancestr _boundary _input_datamin _chunk_size_metarDEFAULT_CHARSET _encoding_content_length_upload_handlers) selfMETA input_dataupload_handlersencoding content_typectypesoptsrcontent_lengthpossible_sizesrrr__init__4s8          zMultiPartParser.__init__cCsLz|WSty%t|dr$|jD] \}}|D]}|qqw)N_files)_parse ExceptionhasattrrBlistsclose)r7_filesfileobjrrrparsejs    zMultiPartParser.parsec# Csddlm}|j}|j}|jdkr||jdtfS|D]}||j|j|j|j |}|dur9|d|dfSq|dd|_ t|_ t t |j|j}d}dgt|}d} d} d} d} d} zt||j D]\}}}|rz|||d}d} |tvrtjdur| d7} tjd| krtd z|d d}|d }Wn tttfyYqhw|d }|dur|d}t||d d}|tkr'tjdurtj| } |dkr|j| d}| t|7} zt |}Wnt!j"y|}Yn w|j| d}| t|7} | t|d7} tjdur| tjkrt#d|j $|t||d dqh|t%kr?| d7} tj&dur@| tj&kr@t'd|d}|rTt||d d}|(|}|sXqh|ddif\}}|}|d}z t)|dd}Wntt*t+fyd}Ynwdgt|}d} z|D]}z |,||||||Wqt-yYnw|D]x}|dkrd.|/}t|d}|dkr|d|}|sn|d.|/7}t|d}|dkszt |}Wnt0y}zt1d|d}~wwt2|D] \} }t|}!|3||| }|| |!7<|dur$nqqWnt4y;|5t6|Yqhw|}qht6|qhWn t7ye}"z|5|"j8s[t6|jWYd}"~"nd}"~"ww| ss|D]}|9qkt6|jt:dd|Dd|j _;|j |j fS)z Parse the POST data and break it into a FILES MultiValueDict and a POST MultiValueDict. Return a tuple containing the POST and FILES dictionary, respectively. r) QueryDictr;NT)mutablezRThe number of GET/POST parameters exceeded settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.content-dispositionnamezcontent-transfer-encodingreplaceerrorsbase64)sizez;Request body exceeded settings.DATA_UPLOAD_MAX_MEMORY_SIZE.zCThe number of files exceeded settings.DATA_UPLOAD_MAX_NUMBER_FILES.filenamez content-typercharsetzcontent-lengthFzCould not decode base64 data.css|]}|VqdSN)upload_complete)rhandlerrrr Nsz)MultiPartParser._parse..)< django.httprLr4r6r5r handle_raw_inputr/r2r._postrB LazyStream ChunkIterr1lenParserhandle_file_complete FIELD_TYPESrDATA_UPLOAD_MAX_NUMBER_FIELDSrstripKeyError IndexErrorAttributeErrorr"r FIELDDATA_UPLOAD_MAX_MEMORY_SIZEreadrV b64decodebinasciiErrorr appendlistFILEDATA_UPLOAD_MAX_NUMBER_FILESrsanitize_file_namer)r+r*new_filer joinsplitrDr enumeratereceive_data_chunkr _close_filesexhaustr connection_resetupload_interruptedany_mutable)#r7rLr;handlersr^resultstreamold_field_namecountersnum_bytes_read num_post_keys num_files read_size uploaded_file item_type meta_data field_stream disposition field_nametransfer_encodingraw_datadata file_namer<content_type_extrarYr?chunkstripped_chunk remaining over_chunkexci chunk_lengtherrrrCzs(                                     zMultiPartParser._parsecCsJt|jD]\}}|||}|r"|jt||jdd|dSqdS)zT Handle all the signaling that takes place when a file is complete. rSrTN)r{r6 file_completerBrtr r4)r7rrrr^file_objrrrrgRsz$MultiPartParser.handle_file_completecCs6t|}|dd}|dd}|dvrdS|S)aT Sanitize the filename of an upload. Remove all possible path separators, even though that might remove more than actually required by the target system. Filenames that could potentially cause problems (current/parent dir) are also discarded. It should be noted that this function could still return a "filepath" like "C:some_file.txt" which is handled later on by the storage layer. So while this function does sanitize filenames to some extent, the resulting filename should still be considered as untrusted user input. /\>..r.N)htmlunescapersplit)r7rrrrrw]s z"MultiPartParser.sanitize_file_namecCs$|jD] }t|dr|jqdS)Nr)r6rErrG)r7r^rrrr}ts   zMultiPartParser._close_filesr\) rrrrrArKrCrgrw IE_sanitizer}rrrrr -s 6Y  r c@sTeZdZdZdddZddZdddZd d Zd d Zd dZ ddZ ddZ dS)rca! The LazyStream wrapper allows one to get and "unget" bytes from a stream. Given a producer object (an iterator that yields bytestrings), the LazyStream object will support iteration, reading, and keeping a "look-back" variable in case you need to "unget" some bytes. NcCs.||_d|_d|_||_d|_||_g|_dS)z Every LazyStream must have a producer when instantiated. A producer is an iterable that returns a string each time it is called. FrZrN) _producer_empty _leftoverlengthposition _remaining_unget_history)r7producerrrrrrAs zLazyStream.__init__cCs|jSr\)rr7rrrtellszLazyStream.tellcsfdd}d|S)Nc3sdurjn}|durdVdS|dkrQ|dks"Jdzt}Wn ty2YdSw|d|}||d|t|8}|V|dksdSdS)NrZrz0remaining bytes to read should never go negative)rrynext StopIterationungetre)rremittingr7rWrrpartss"     zLazyStream.read..partsrZ)ry)r7rWrrrrrps zLazyStream.readcCs:|jr |j}d|_nt|j}g|_|jt|7_|S)z Used when the exact number of bytes to read is unimportant. Return whatever chunk is conveniently returned from the iterator. Useful to avoid unnecessary bookkeeping if performance is an issue. rZ)rrrrrre)r7outputrrr__next__s zLazyStream.__next__cCs g|_dS)z Used to invalidate/disable this lazy stream. Replace the producer with an empty list. Any leftover bytes that have already been read will still be reported upon read() and/or next(). N)rrrrrrGs zLazyStream.closecC|Sr\rrrrr__iter__zLazyStream.__iter__cCs8|sdS|t||jt|8_||j|_dS)z Place bytes back onto the front of the lazy stream. Future calls to read() will return those bytes first. The stream position and thus tell() will be rewound. N)_update_unget_historyrerr)r7bytesrrrrs zLazyStream.ungetcsBg|jdd|_tfdd|jD}|dkrtddS)aZ Update the unget history as a sanity check to see if we've pushed back the same number of bytes in one chunk. If we keep ungetting the same number of bytes many times (here, 50), we're mostly likely in an infinite loop of some sort. This is usually caused by a maliciously-malformed MIME request. N1csg|]}|kr|qSrr)rcurrent_number num_bytesrrr!s z4LazyStream._update_unget_history..(zThe multipart parser got stuck, which shouldn't happen with normal uploaded files. Check for malicious upload activity; if there is none, report this to the Django developers.)rrer)r7r number_equalrrrrs z LazyStream._update_unget_historyr\) rrrrrArrprrGrrrrrrrrc}s    rcc@s*eZdZdZd ddZddZddZd S) rdz An iterable that will yield chunks of data. Given a file-like object as the constructor, yield chunks of read operations from that object. cC||_||_dSr\)flor)r7rrrrrrA zChunkIter.__init__cCs6z |j|j}Wn tytw|r|Str\)rrprrr)r7rrrrrs zChunkIter.__next__cCrr\rrrrrrrzChunkIter.__iter__N)r)rrrrrArrrrrrrds   rdc@s(eZdZdZddZddZddZdS) InterBoundaryIterz7 A Producer that will iterate over boundaries. cCrr\)_streamr.r7rrrrrrA rzInterBoundaryIter.__init__cCrr\rrrrrrrzInterBoundaryIter.__iter__cCs*z tt|j|jWStytwr\)rc BoundaryIterrr.rrrrrrrs  zInterBoundaryIter.__next__N)rrrrrArrrrrrrs  rc@s0eZdZdZddZddZddZdd Zd S) rae A Producer that is sensitive to boundaries. Will happily yield bytes until a boundary is found. Will yield the bytes before the boundary, throw away the boundary bytes themselves, and push the post-boundary bytes back on the stream. The future calls to next() after locating the boundary will raise a StopIteration exception. cCsF||_||_d|_t|d|_|jd}|st|j|dS)NFrN)rr._donere _rollbackrprr)r7rr unused_charrrrrA%s zBoundaryIter.__init__cCrr\rrrrrr4rzBoundaryIter.__iter__c Cs|jrt|j}|j}d}g}|D]}|t|7}||||kr%n|s)nqd|_|s2td|}||}|rT|\}} ||| dd|_|d|S|d| s`d|_|S||| d|d| S)NrTrZ) rrrrreappendry_find_boundaryr) r7rrollback bytes_readchunksrrrendrrrrr7s:     zBoundaryIter.__next__cCs||j}|dkr dS|}|t|j}td|d}|||ddkr*|d8}td|d}|||ddkr?|d8}||fS)a Find a multipart boundary in data. Should no boundary exist in the data, return None. Otherwise, return a tuple containing the indices of the following: * the end of current encapsulation * the start of the next encapsulation rNrN  )findr.remax)r7rindexrrlastrrrr`s zBoundaryIter._find_boundaryN)rrrrrArrrrrrrrs   )rcCs<zt|}Wntyt|d}Ynwtj|dddS)zExhaust an iterator or stream.i@r)maxlenN)iterr+rd collectionsdeque)stream_or_iterableiteratorrrrr~ys   r~c Cs||}|d}dd}|dkr||ti|fS|d|}|||ddt}i}|dD])}z ||\} \} } Wn tyKYq6w| dkrYt}| d rYt}| | f|| <q6|tkri|||||fS) zH Parse one and exactly one stream that encapsulates a boundary. s cSsHt|\}}z |dd\}}Wn tytd|w|||ffS)N:rNzInvalid header: %r)r$rzr*)linemain_value_pairparamsrRvaluerrr _parse_headers    z,parse_boundary_stream.._parse_headerrNr[s rQrX) rprrRAWrzr*rnr"ru) rmax_header_sizer header_endrheaderTYPEoutdictrrRrrrrrparse_boundary_streams0         rc@seZdZddZddZdS)rfcCs||_d||_dS)Ns--)r _separatorrrrrrAszParser.__init__ccs*t|j|j}|D]}t|dVq dS)Ni)rrrr)r7boundarystream sub_streamrrrrs zParser.__iter__N)rrrrArrrrrrfs rfc Cs&td|}|dd}i}|D]z}|d}|dkrd}|d|d}|drB|dd}|d d krBd }||d d}t|d krv|dd |ddkrdd krvnn|d d}| dd dd }|r| d \} } }t || d}|||<q||fS)z Parse the header into a key-value. Input (line): bytes, output: str for key/name, bytes for values which will be decoded later. ;rr=FN*r'rPTrN"s\\\s\"rM) _parse_header_paramspoplowerdecoderrjendswithcountrerSrzr) rplistkeypdictpr has_encodingrRrr;langrrrr$s,    4 r$cCsg}|dddkrZ|dd}|d}|dkr7|dd|dr7|d|d}|dkr7|dd|ds"|dkr?t|}|d|}||||d}|dddks |S)NrNrrrrP)rrrerrj)srrfrrrrs     r)*rrVrrr'rr urllib.parser django.confrdjango.core.exceptionsrrrrdjango.core.files.uploadhandlerrr r django.utils.datastructuresr django.utils.encodingr __all__rDrrrrurn frozensetrhr rcrdrrr~rrfr$rrrrrs>     Rs` ;