U
    8ÄT_úa  ã                   @   s4  d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZmZmZ ddlmZmZmZ ddlmZ ddlmZ d	ZG d
d„ deƒZG dd„ deƒZdZdZdZG dd„ dƒZG dd„ dƒZG dd„ dƒZ G dd„ dƒZ!G dd„ dƒZ"dd„ Z#dd„ Z$G dd „ d ƒZ%d!d"„ Z&d#d$„ Z'dS )%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)ÚRequestDataTooBigÚSuspiciousMultipartFormÚTooManyFieldsSent)ÚSkipFileÚStopFutureHandlersÚ
StopUpload)ÚMultiValueDict)Ú	force_str)ÚMultiPartParserÚMultiPartParserErrorÚInputStreamExhaustedc                   @   s   e Zd ZdS )r   N)Ú__name__Ú
__module__Ú__qualname__© r   r   ú?/tmp/pip-unpacked-wheel-dv63caxw/django/http/multipartparser.pyr      s   r   c                   @   s   e Zd ZdZdS )r   z5
    No more reads are allowed from this device.
    N)r   r   r   Ú__doc__r   r   r   r   r       s   r   ÚrawÚfileÚfieldc                   @   s:   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )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              	   C   s.  |  dd¡}| d¡s"td| ƒ‚zt| d¡ƒ\}}W n$ tk
r\   tdt|ƒ ƒ‚Y nX |  d¡}|rvt |¡s†tdt|ƒ ƒ‚zt	|  d	d
¡ƒ}	W n t
tfk
r¶   d
}	Y nX |	d
k rÌtd|	 ƒ‚t|tƒrà| d¡}|| _|| _dd„ |D ƒ}
tdg|
 ƒ| _|| _|�ptj| _|	| _|| _dS )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_TYPEÚ z
multipart/zInvalid Content-Type: %sÚasciiz/Invalid non-ASCII Content-Type in multipart: %sÚboundaryz!Invalid boundary in multipart: %sÚCONTENT_LENGTHr   zInvalid content length: %rc                 S   s   g | ]}|j r|j ‘qS r   )Ú
chunk_size)Ú.0Úxr   r   r   Ú
<listcomp>a   s      z,MultiPartParser.__init__.<locals>.<listcomp>iüÿÿN)ÚgetÚ
startswithr   Úparse_headerÚencodeÚUnicodeEncodeErrorr   ÚcgiÚvalid_boundaryÚintÚ
ValueErrorÚ	TypeErrorÚ
isinstanceÚstrÚ	_boundaryÚ_input_dataÚminÚ_chunk_sizeÚ_metar   ÚDEFAULT_CHARSETÚ	_encodingÚ_content_lengthÚ_upload_handlers)ÚselfZMETAZ
input_dataZupload_handlersÚencodingÚcontent_typeÚctypesÚoptsr   Úcontent_lengthZpossible_sizesr   r   r   Ú__init__3   s4    




zMultiPartParser.__init__c           !      C   sî  ddl m} | j}| j}| jdkr4|| jd�tƒ fS |D ]:}| | j| j| j| j	|¡}|dk	r8|d |d f  S q8|dd�| _
tƒ | _tt| j| jƒƒ}d}dgt|ƒ }d}	d}
d}�zÄt|| j	ƒD �]°\}}}|rè|  ||¡ d}z|d d }|d	  ¡ }W n  tttfk
�r$   Y qÈY nX | d
¡}|dk	�rF|d  ¡ }t||dd�}|tk�rN|
d7 }
tjdk	�r†tj|
k �r†tdƒ‚tjdk	�rœtj|	 }|dk�rì|j|d�}|	t|ƒ7 }	zt |¡}W n t j!k
�rè   |}Y nX n|j|d�}|	t|ƒ7 }	|	t|ƒd 7 }	tjdk	�r4|	tjk�r4t"dƒ‚| j
 #|t||dd�¡ qÈ|t$k�rr| d¡}|�r’t%j& '|¡}t||dd�}|  (t) *|¡¡}|�sšqÈ| ddi f¡\}}| ¡ }| d¡}zt+| d¡d ƒ}W n  tt,t-fk
�rö   d}Y nX dgt|ƒ }�z<|D ]>}z| .||||||¡ W n t/k
�rH   Y  �qNY nX �q|D ]î}|dk�ròd 0| 1¡ ¡}t|ƒd }|dk�r´| d| ¡}|d 0| 1¡ ¡7 }t|ƒd }�qzzt |¡}W n. t2k
�rð } zt3dƒ|‚W 5 d}~X Y nX t4|ƒD ]B\}}t|ƒ}| 5||| ¡}||  |7  < |dk�rú �qR�qú�qRW n& t6k
�rj   |  7¡  t8|ƒ Y nX |}qÈt8|ƒ qÈW n> t9k
�r¼ }  z|  7¡  | j:�s¬t8| jƒ W 5 d} ~ X Y nX t8| jƒ t;dd„ |D ƒƒ d| j
_<| j
| jfS )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   )Ú	QueryDict©r7   Né   T)Zmutableúcontent-dispositionÚnamezcontent-transfer-encodingÚreplace©ÚerrorszRThe number of GET/POST parameters exceeded settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.Úbase64)Úsizeé   z;Request body exceeded settings.DATA_UPLOAD_MAX_MEMORY_SIZE.Úfilenamezcontent-typer   Úcharsetzcontent-lengthó    é   zCould not decode base64 data.c                 s   s   | ]}|  ¡ V  qd S ©N)Zupload_complete)r   Úhandlerr   r   r   Ú	<genexpr>  s     z(MultiPartParser.parse.<locals>.<genexpr>F)=Zdjango.httpr=   r3   r5   r4   r
   Zhandle_raw_inputr.   r1   r-   Ú_postÚ_filesÚ
LazyStreamÚ	ChunkIterr0   ÚlenÚParserÚhandle_file_completeÚstripÚKeyErrorÚ
IndexErrorÚAttributeErrorr!   r   ÚFIELDr   ZDATA_UPLOAD_MAX_NUMBER_FIELDSr   ZDATA_UPLOAD_MAX_MEMORY_SIZEÚreadrE   Ú	b64decodeÚbinasciiÚErrorr   Ú
appendlistÚFILEÚosÚpathÚbasenameÚIE_sanitizeÚhtmlÚunescaper(   r*   r)   Znew_filer   ÚjoinÚsplitÚ	Exceptionr   Ú	enumerateZreceive_data_chunkr   Ú_close_filesÚexhaustr	   Zconnection_resetÚanyZ_mutable)!r6   r=   r7   ÚhandlersrM   ÚresultÚstreamÚold_field_nameÚcountersZnum_bytes_readZnum_post_keysÚ	read_sizeZ	item_typeZ	meta_dataZfield_streamÚdispositionÚ
field_nameZtransfer_encodingÚraw_dataÚdataÚ	file_namer8   Zcontent_type_extrarI   r;   ÚchunkZstripped_chunkÚ	remainingZ
over_chunkÚexcÚiZchunk_lengthÚer   r   r   Úparsei   sô    
û



ÿÿ

ÿ



    þ



zMultiPartParser.parsec                 C   sH   t | jƒD ]8\}}| || ¡}|r
| j t|| jdd�|¡  qDq
dS )zT
        Handle all the signaling that takes place when a file is complete.
        rB   rC   N)rj   r5   Zfile_completerP   r_   r   r3   )r6   rq   rr   r|   rM   Zfile_objr   r   r   rU   #  s
    z$MultiPartParser.handle_file_completec                 C   s   |o||  d¡d d…  ¡ S )z3Cleanup filename from Internet Explorer full paths.ú\r?   N)ÚrfindrV   )r6   rH   r   r   r   rd   .  s    zMultiPartParser.IE_sanitizec                 C   s$   | j D ]}t|dƒr|j ¡  qd S )Nr   )r5   Úhasattrr   Úclose)r6   rM   r   r   r   rk   2  s    

zMultiPartParser._close_files)N)	r   r   r   r   r<   r~   rU   rd   rk   r   r   r   r   r   ,   s   
6 ;r   c                   @   sT   e Zd ZdZddd„Zdd„ Zddd„Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ ZdS )rQ   a!  
    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.
    Nc                 C   s.   || _ d| _d| _|| _d| _|| _g | _dS )z£
        Every LazyStream must have a producer when instantiated.

        A producer is an iterable that returns a string each time it
        is called.
        FrJ   r   N)Ú	_producerÚ_emptyÚ	_leftoverÚlengthÚpositionÚ
_remainingÚ_unget_history)r6   Zproducerr†   r   r   r   r<   C  s    zLazyStream.__init__c                 C   s   | j S rL   )r‡   ©r6   r   r   r   ÚtellR  s    zLazyStream.tellc                    s   ‡ ‡fdd„}d  |ƒ ¡S )Nc                  3   sœ   ˆd krˆ j nˆ} | d kr*d ˆ ¡V  d S | dkr˜| dksBtdƒ‚ztˆ ƒ}W n tk
rd   Y d S X |d | … }ˆ  || d … ¡ | t|ƒ8 } |V  q*d S )NrJ   r   z0remaining bytes to read should never go negative)rˆ   rg   ÚAssertionErrorÚnextÚStopIterationÚungetrS   )rz   ry   Zemitting©r6   rF   r   r   ÚpartsV  s    zLazyStream.read.<locals>.partsrJ   )rg   )r6   rF   r‘   r   r�   r   r[   U  s    zLazyStream.readc                 C   s:   | j r| j }d| _ nt| jƒ}g | _|  jt|ƒ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.
        rJ   )r…   r�   rƒ   r‰   r‡   rS   )r6   Úoutputr   r   r   Ú__next__o  s    
zLazyStream.__next__c                 C   s
   g | _ dS )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)rƒ   rŠ   r   r   r   r‚     s    zLazyStream.closec                 C   s   | S rL   r   rŠ   r   r   r   Ú__iter__ˆ  s    zLazyStream.__iter__c                 C   s8   |sdS |   t|ƒ¡ |  jt|ƒ8  _|| j | _dS )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_historyrS   r‡   r…   )r6   Úbytesr   r   r   r�   ‹  s
    zLazyStream.ungetc                    sB   ˆ g| j dd…  | _ t‡ fdd„| j D ƒƒ}|dkr>tdƒ‚dS )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.
        Né1   c                    s   g | ]}|ˆ kr|‘qS r   r   )r   Zcurrent_number©Ú	num_bytesr   r   r    ¡  s   ÿz4LazyStream._update_unget_history.<locals>.<listcomp>é(   z¯The 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.)r‰   rS   r   )r6   r™   Znumber_equalr   r˜   r   r•   ˜  s    ÿÿz LazyStream._update_unget_history)N)N)r   r   r   r   r<   r‹   r[   r“   r‚   r”   r�   r•   r   r   r   r   rQ   ;  s   

	rQ   c                   @   s*   e Zd ZdZd
dd„Zdd„ Zdd„ Zd	S )rR   z˜
    An iterable that will yield chunks of data. Given a file-like object as the
    constructor, yield chunks of read operations from that object.
    é   c                 C   s   || _ || _d S rL   )Úflor   )r6   rœ   r   r   r   r   r<   ³  s    zChunkIter.__init__c                 C   s@   z| j  | j¡}W n tk
r,   tƒ ‚Y nX |r6|S tƒ ‚d S rL   )rœ   r[   r   r   rŽ   )r6   rw   r   r   r   r“   ·  s    zChunkIter.__next__c                 C   s   | S rL   r   rŠ   r   r   r   r”   Á  s    zChunkIter.__iter__N)r›   )r   r   r   r   r<   r“   r”   r   r   r   r   rR   ®  s   

rR   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚInterBoundaryIterz7
    A Producer that will iterate over boundaries.
    c                 C   s   || _ || _d S rL   )Ú_streamr-   ©r6   rp   r   r   r   r   r<   É  s    zInterBoundaryIter.__init__c                 C   s   | S rL   r   rŠ   r   r   r   r”   Í  s    zInterBoundaryIter.__iter__c                 C   s4   zt t| j| jƒƒW S  tk
r.   tƒ ‚Y nX d S rL   )rQ   ÚBoundaryIterrž   r-   r   rŽ   rŠ   r   r   r   r“   Ð  s    zInterBoundaryIter.__next__N)r   r   r   r   r<   r”   r“   r   r   r   r   r�   Å  s   r�   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )r    ae  
    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.
    c                 C   sF   || _ || _d| _t|ƒd | _| j  d¡}|s6tƒ ‚| j  |¡ d S )NFé   r?   )rž   r-   Ú_donerS   Ú	_rollbackr[   r   r�   )r6   rp   r   Zunused_charr   r   r   r<   ã  s    zBoundaryIter.__init__c                 C   s   | S rL   r   rŠ   r   r   r   r”   ò  s    zBoundaryIter.__iter__c           
      C   sæ   | j rtƒ ‚| j}| j}d}g }|D ].}|t|ƒ7 }| |¡ ||krJ qZ|s$ qZq$d| _ |sdtƒ ‚d |¡}|  |¡}|r¨|\}}	| ||	d … ¡ d| _ |d |… S |d | … sÀd| _ |S | || d … ¡ |d | … S d S )Nr   TrJ   )	r¢   rŽ   rž   r£   rS   Úappendrg   Ú_find_boundaryr�   )
r6   rp   ÚrollbackÚ
bytes_readÚchunksr–   ry   r   Úendr�   r   r   r   r“   õ  s8    


zBoundaryIter.__next__c                 C   sŠ   |  | j¡}|dk rdS |}|t| jƒ }td|d ƒ}|||d … dkrT|d8 }td|d ƒ}|||d … dkr~|d8 }||fS dS )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
        r   Nr?   ó   
ó   )Úfindr-   rS   Úmax)r6   rw   Úindexr©   r�   Úlastr   r   r   r¥     s    	zBoundaryIter._find_boundaryN)r   r   r   r   r<   r”   r“   r¥   r   r   r   r   r    ×  s
   )r    c                 C   s>   zt | ƒ}W n tk
r*   t| dƒ}Y nX tj|dd� dS )zExhaust an iterator or stream.i @  r   )ÚmaxlenN)Úiterr*   rR   ÚcollectionsÚdeque)Zstream_or_iterableÚiteratorr   r   r   rl   7  s
    rl   c              	   C   sâ   |   |¡}| d¡}dd„ }|dkr8|  |¡ ti | fS |d|… }|  ||d d… ¡ t}i }| d¡D ]X}z||ƒ\}	\}
}W n tk
rœ   Y qlY nX |	dkr¸t}| d	¡r¸t}|
|f||	< ql|tkrØ|  |¡ ||| fS )
zH
    Parse one and exactly one stream that encapsulates a boundary.
    s   

c                 S   sN   t | ƒ\}}z| dd¡\}}W n  tk
r@   td|  ƒ‚Y nX |||ffS )Nú:r?   zInvalid header: %r)r#   rh   r)   )ÚlineZmain_value_pairÚparamsrA   Úvaluer   r   r   Ú_parse_headerN  s    z,parse_boundary_stream.<locals>._parse_headeréÿÿÿÿNrK   s   
r@   rH   )	r[   r¬   r�   ÚRAWrh   r)   rZ   r!   r`   )rp   Zmax_header_sizery   Z
header_endr¹   ÚheaderZTYPEZoutdictr¶   rA   r¸   r·   r   r   r   Úparse_boundary_stream@  s.    






r½   c                   @   s   e Zd Zdd„ Zdd„ ZdS )rT   c                 C   s   || _ d| | _d S )Ns   --)rž   Ú
_separatorrŸ   r   r   r   r<   |  s    zParser.__init__c                 c   s(   t | j| jƒ}|D ]}t|dƒV  qd S )Ni   )r�   rž   r¾   r½   )r6   ZboundarystreamZ
sub_streamr   r   r   r”   €  s    zParser.__iter__N)r   r   r   r<   r”   r   r   r   r   rT   {  s   rT   c                 C   s(  t d|  ƒ}| d¡ ¡  d¡}i }|D ]ö}| d¡}|dkr(d}|d|…  ¡  ¡  d¡}| d¡r„|dd… }| d	¡d
kr„d}||d d…  ¡ }t|ƒd
krì|dd… |dd…   krÈdkrìn n |dd… }| 	dd¡ 	dd¡}|�r| 
d	¡\}	}
}t| ¡ |	 ¡ d�}|||< q(||fS )z’
    Parse the header into a key-value.

    Input (line): bytes, output: str for key/name, bytes for values which
    will be decoded later.
    ó   ;r   r   ó   =FNÚ*rº   ó   'rG   Tr?   ó   "s   \\ó   \s   \"r>   )Ú_parse_header_paramsÚpopÚlowerÚdecoder¬   rV   ÚendswithÚcountrS   rB   rh   r   )r¶   ÚplistÚkeyÚpdictÚpr|   Zhas_encodingrA   r¸   r7   Úlangr   r   r   r#   ‡  s*    

4
r#   c                 C   s’   g }| d d… dkrŽ| dd … } |   d¡}|dkrV|  dd|¡d rV|   d|d ¡}q*|dk rft| ƒ}| d |… }| | ¡ ¡ | |d … } q|S )Nr?   r¿   r   rÃ   rG   )r¬   rÊ   rS   r¤   rV   )ÚsrË   r©   Úfr   r   r   rÅ   §  s    
rÅ   )(r   rE   r]   r&   r²   re   ra   Úurllib.parser   Zdjango.confr   Zdjango.core.exceptionsr   r   r   Zdjango.core.files.uploadhandlerr   r   r	   Zdjango.utils.datastructuresr
   Zdjango.utils.encodingr   Ú__all__ri   r   r   r»   r`   rZ   r   rQ   rR   r�   r    rl   r½   rT   r#   rÅ   r   r   r   r   Ú<module>   s<     s`	; 