o
    [h                    @   s8  d dl mZmZmZ d dlmZmZmZ ddlT ddl	T zd dl
mZ W n ey3   d dlmZ Y nw 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 e Zd ZdZd	Zd ZdZd	Zd
Z dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(g dZ)dZ*d	Z+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3dZ4d Z5erdd Z6dd Z7dd Z8nd d Z6d!d Z7d"d Z8e9d#Z:d$Z;d%e: d& e; d' Z<d(e: d) e< d' Z=e>e=Z?d*Z@d+d, ZAG d-d. d.eZBG d/d0 d0eZCG d1d2 d2eZDG d3d4 d4eDZEG d5d6 d6eDZFG d7d8 d8eDZGG d9d: d:eZHd;i fd<d=ZIdAd?d@ZJdS )B    )with_statementabsolute_importprint_function)binary_type	text_typePY3   )*)parse_qsN)BytesIO)Number                     	   
      )ZSTARTZSTART_BOUNDARYZHEADER_FEILD_STARTZHEADER_FIELDZHEADER_VALUE_STARTZHEADER_VALUEZHEADER_VALUE_ALMOST_DONEZHEADRES_ALMOST_DONEZPART_DATA_STARTZ	PART_DATAZPART_DATA_ENDEND   :       -   &   ;   a   z   c                 C   s   | dB S )Nr    cr    r    z/home/ubuntu/experiments/live_experiments/Pythonexperiments/Otree/venv/lib/python3.10/site-packages/multipart/multipart.py<lambda>N       r$   c                 C   s   | S Nr    r!   r    r    r#   r$   O   s    c                 C   s   t t| S r&   )byteslistbr    r    r#   r$   P   s    c                 C   s   |   S r&   )lowerr!   r    r    r#   r$   R   r%   c                 C   s   t | S r&   )ordr!   r    r    r#   r$   S   r%   c                 C   s   d t| S N    )joinr(   r)   r    r    r#   r$   T   s    s   ()<>@,;:\"/[]?={} 	s   "(?:\\.|[^"])*"s   (?:[^s   ]+|   )s   (?:;|^)\s*([^s   ]+)\s*=\s*("   c                 C   s   | sdi fS t | tr| d} d| vr|   i fS | dd\}}i }t|D ]I}|d }|d} | d t	krU| d t	krU| dd } | 
dd	
d
d} |dkrp| dd dksi| dd dkrp| d	d } | ||< q+||fS )zq
    Parses a Content-Type header into a value in the following format:
        (content_type, {parameters})
    r.   latin-1   ;r   r   r   s   \\   \s   \"   "   filenamer   s   :\N)
isinstancer   encoder+   stripsplit	OPTION_REfinditergroupQUOTEreplace)valuectyperestoptionsmatchkeyr    r    r#   parse_options_headera   s&   


 
rG   c                   @   s|   e Zd ZdZdd Zedd Zdd Zdd	 Zd
d Z	dd Z
dd Zdd Zedd Zedd Zdd Zdd ZdS )Fielda  A Field object represents a (parsed) form field.  It represents a single
    field with a corresponding name and value.

    The name that a :class:`Field` will be instantiated with is the same name
    that would be found in the following HTML::

        <input name="name_goes_here" type="text"/>

    This class defines two methods, :meth:`on_data` and :meth:`on_end`, that
    will be called when data is written to the Field, and when the Field is
    finalized, respectively.

    :param name: the name of the form field
    c                 C   s   || _ g | _t| _d S r&   )_name_value_missing_cache)selfnamer    r    r#   __init__   s   
zField.__init__c                 C   s0   | |}|du r|   n|| |  |S )aK  Create an instance of a :class:`Field`, and set the corresponding
        value - either None or an actual value.  This method will also
        finalize the Field itself.

        :param name: the name of the form field
        :param value: the value of the form field - either a bytestring or
                      None
        N)set_nonewritefinalize)klassrN   rA   fr    r    r#   
from_value   s   

zField.from_valuec                 C   
   |  |S )zPWrite some data into the form field.

        :param data: a bytestring
        on_datarM   datar    r    r#   rQ         
zField.writec                 C   s   | j | t| _t|S )zThis method is a callback that will be called whenever data is
        written to the Field.

        :param data: a bytestring
        )rJ   appendrK   rL   lenrY   r    r    r#   rX      s   zField.on_datac                 C   s    | j tu rd| j| _ dS dS )?This method is called whenever the Field is finalized.
        r.   NrL   rK   r/   rJ   rM   r    r    r#   on_end   s   
zField.on_endc                 C      |    dS )z!Finalize the form field.
        Nra   r`   r    r    r#   rR      s   zField.finalizec                 C   s    | j tu rd| j| _ | `dS )zFClose the Field object.  This will free any underlying cache.
        r.   Nr_   r`   r    r    r#   close   s   
zField.closec                 C   s
   d| _ dS )a  Some fields in a querystring can possibly have a value of None - for
        example, the string "foo&bar=&baz=asdf" will have a field with the
        name "foo" and value None, one with name "bar" and value "", and one
        with name "baz" and value "asdf".  Since the write() interface doesn't
        support writing None, this function will set the field value to None.
        N)rL   r`   r    r    r#   rP      s   
zField.set_nonec                 C      | j S )z,This property returns the name of the field.)rI   r`   r    r    r#   
field_name   s   zField.field_namec                 C   s   | j tu rd| j| _ | j S )z2This property returns the value of the form field.r.   r_   r`   r    r    r#   rA      s   
zField.valuec                 C   s&   t |tr| j|jko| j|jkS tS r&   )r8   rH   rf   rA   NotImplemented)rM   otherr    r    r#   __eq__   s
   

zField.__eq__c                 C   sL   t | jdkrt| jd d d d d }nt| j}d| jj| j|f S )Nr   r4   z...'z%s(field_name=%r, value=%s))r]   rA   repr	__class____name__rf   )rM   vr    r    r#   __repr__   s    
zField.__repr__N)rl   
__module____qualname____doc__rO   classmethodrU   rQ   rX   ra   rR   rd   rP   propertyrf   rA   ri   rn   r    r    r    r#   rH      s"    

		

	rH   c                   @   s   e Zd ZdZdi fddZedd Zedd Zed	d
 Zedd Z	edd Z
edd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  ZdS )!Filea	  This class represents an uploaded file.  It handles writing file data to
    either an in-memory file or a temporary file on-disk, if the optional
    threshold is passed.

    There are some options that can be passed to the File to change behavior
    of the class.  Valid options are as follows:

    .. list-table::
       :widths: 15 5 5 30
       :header-rows: 1

       * - Name
         - Type
         - Default
         - Description
       * - UPLOAD_DIR
         - `str`
         - None
         - The directory to store uploaded files in.  If this is None, a
           temporary file will be created in the system's standard location.
       * - UPLOAD_DELETE_TMP
         - `bool`
         - True
         - Delete automatically created TMP file
       * - UPLOAD_KEEP_FILENAME
         - `bool`
         - False
         - Whether or not to keep the filename of the uploaded file.  If True,
           then the filename will be converted to a safe representation (e.g.
           by removing any invalid path segments), and then saved with the
           same name).  Otherwise, a temporary name will be used.
       * - UPLOAD_KEEP_EXTENSIONS
         - `bool`
         - False
         - Whether or not to keep the uploaded file's extension.  If False, the
           file will be saved with the default temporary extension (usually
           ".tmp").  Otherwise, the file's extension will be maintained.  Note
           that this will properly combine with the UPLOAD_KEEP_FILENAME
           setting.
       * - MAX_MEMORY_FILE_SIZE
         - `int`
         - 1 MiB
         - The maximum number of bytes of a File to keep in memory.  By
           default, the contents of a File are kept into memory until a certain
           limit is reached, after which the contents of the File are written
           to a temporary file.  This behavior can be disabled by setting this
           value to an appropriately large value (or, for example, infinity,
           such as `float('inf')`.

    :param file_name: The name of the file that this :class:`File` represents

    :param field_name: The field name that uploaded this file.  Note that this
                       can be None, if, for example, the file was uploaded
                       with Content-Type application/octet-stream

    :param config: The configuration for this File.  See above for valid
                   configuration keys and their corresponding values.
    Nc                 C   sd   t t| _|| _d| _d| _t | _|| _	|| _
d | _|d ur0tj|\}}|| _|| _d S d S )NTr   )logging	getLoggerrl   logger_config
_in_memory_bytes_writtenr   _fileobj_field_name
_file_name_actual_file_nameospathsplitext
_file_base_ext)rM   	file_namerf   configbaseextr    r    r#   rO   A  s   
zFile.__init__c                 C   re   )zThe form field associated with this file.  May be None if there isn't
        one, for example when we have an application/octet-stream upload.
        )r|   r`   r    r    r#   rf   W     zFile.field_namec                 C   re   )z3The file name given in the upload request.
        )r}   r`   r    r    r#   r   ^  s   zFile.file_namec                 C   re   )zmThe file name that this file is saved as.  Will be None if it's not
        currently saved on disk.
        )r~   r`   r    r    r#   actual_file_named  r   zFile.actual_file_namec                 C   re   )zThe file object that we're currently writing to.  Note that this
        will either be an instance of a :class:`io.BytesIO`, or a regular file
        object.
        )r{   r`   r    r    r#   file_objectk  s   zFile.file_objectc                 C   re   )zzThe total size of this file, counted as the number of bytes that
        currently have been written to the file.
        )rz   r`   r    r    r#   sizes  r   z	File.sizec                 C   re   )zqA boolean representing whether or not this file object is currently
        stored in-memory or on-disk.
        )ry   r`   r    r    r#   	in_memoryz  r   zFile.in_memoryc                 C   sb   | j s| jd dS | jd |  }t| j| || j | j}|| _d| _ |	  dS )aF  If the file is already on-disk, do nothing.  Otherwise, copy from
        the in-memory buffer to a disk file, and then reassign our internal
        file object to this new disk file.

        Note that if you attempt to flush a file that is already on-disk, a
        warning will be logged to this module's logger.
        z0Trying to flush to disk when we're not in memoryNr   F)
ry   rw   warningr{   seek_get_disk_fileshutilcopyfileobjrz   rd   )rM   new_fileZold_fileobjr    r    r#   flush_to_disk  s   zFile.flush_to_diskc              
   C   s  | j d | jd}| jdd}| jdd}| jdd}|durj|rj| j d	| | j}|r8|| j }tj||}z| j d
| t	|d}W n t
tfyi } zd}| j d td| d}~ww i }	|r| j}
t|
tr}|
t }
|
|	d< |dur|}t|tr|t }||	d< ||	d< | j d|	 z
tjdi |	}W n t
tfy   | j d tdw |j}t|tr|t }|| _|S )zOThis function is responsible for getting a file object on-disk for us.
        zOpening a file on disk
UPLOAD_DIRUPLOAD_KEEP_FILENAMEFUPLOAD_KEEP_EXTENSIONSZUPLOAD_DELETE_TMPTNzSaving with filename in: %rzOpening file: %rzw+bzError opening temporary filez Error opening temporary file: %rsuffixdirdeletez*Creating a temporary file with options: %rz#Error creating named temporary filer    )rw   inforx   getr   r   r   r   r/   openIOErrorOSError	exceptionZ	FileErrorr8   r   decodesysgetfilesystemencodingtempfileNamedTemporaryFilerN   r   r9   r~   )rM   Zfile_dirZkeep_filenameZkeep_extensionsZ
delete_tmpfnamer   Ztmp_fileerD   r   dr    r    r#   r     s\   
	


zFile._get_disk_filec                 C   rV   )zHWrite some data to the File.

        :param data: a bytestring
        rW   rY   r    r    r#   rQ     r[   z
File.writec                 C   s   | j  }| j |}|du r| j  | }|t|kr(| jd|t| |S |  j|7  _| jrM| j	ddurM| j| j	dkrM| j
d |   |S )zThis method is a callback that will be called whenever data is
        written to the File.

        :param data: a bytestring
        Nz bwritten != len(data) (%d != %d)MAX_MEMORY_FILE_SIZEzFlushing to disk)r{   tellrQ   r]   rw   r   rz   ry   rx   r   r   r   )rM   rZ   posZbwrittenr    r    r#   rX     s$   


zFile.on_datac                 C      | j   dS )r^   N)r{   flushr`   r    r    r#   ra        zFile.on_endc                 C   rb   )zFinalize the form file.  This will not close the underlying file,
        but simply signal that we are finished writing to the File.
        Nrc   r`   r    r    r#   rR     s   zFile.finalizec                 C   r   )zClose the File object.  This will actually close the underlying
        file object (whether it's a :class:`io.BytesIO` or an actual file
        object).
        N)r{   rd   r`   r    r    r#   rd     s   z
File.closec                 C      d| j j| j| jf S )Nz%s(file_name=%r, field_name=%r))rk   rl   r   rf   r`   r    r    r#   rn   !  
   zFile.__repr__)rl   ro   rp   rq   rO   rs   rf   r   r   r   r   r   r   r   rQ   rX   ra   rR   rd   rn   r    r    r    r#   rt     s.    :





$B rt   c                   @   sB   e Zd ZdZdd ZdddZdd Zd	d
 Zdd Zdd Z	dS )
BaseParsera  This class is the base class for all parsers.  It contains the logic for
    calling and adding callbacks.

    A callback can be one of two different forms.  "Notification callbacks" are
    callbacks that are called when something happens - for example, when a new
    part of a multipart message is encountered by the parser.  "Data callbacks"
    are called when we get some sort of data - for example, part of the body of
    a multipart chunk.  Notification callbacks are called with no parameters,
    whereas data callbacks are called with three, as follows::

        data_callback(data, start, end)

    The "data" parameter is a bytestring (i.e. "foo" on Python 2, or b"foo" on
    Python 3).  "start" and "end" are integer indexes into the "data" string
    that represent the data of interest.  Thus, in a data callback, the slice
    `data[start:end]` represents the data that the callback is "interested in".
    The callback is not passed a copy of the data, since copying severely hurts
    performance.
    c                 C   s   t t| _d S r&   )ru   rv   rl   rw   r`   r    r    r#   rO   =  s   zBaseParser.__init__Nc                 C   sv   d| }| j |}|du rdS |dur/|dur||krdS | jd||| |||| dS | jd| |  dS )a  This function calls a provided callback with some data.  If the
        callback is not set, will do nothing.

        :param name: The name of the callback to call (as a string).

        :param data: Data to pass to the callback.  If None, then it is
                     assumed that the callback is a notification callback,
                     and no parameters are given.

        :param end: An integer that is passed to the data callback.

        :param start: An integer that is passed to the data callback.
        on_NzCalling %s with data[%d:%d]zCalling %s with no data)	callbacksr   rw   debug)rM   rN   rZ   startendfuncr    r    r#   callback@  s   
zBaseParser.callbackc                 C   s0   |du r| j d| d dS || j d| < dS )aq  Update the function for a callback.  Removes from the callbacks dict
        if new_func is None.

        :param name: The name of the callback to call (as a string).

        :param new_func: The new function for the callback.  If None, then the
                         callback will be removed (with no error if it does not
                         exist).
        Nr   )r   pop)rM   rN   new_funcr    r    r#   set_callback_  s   
zBaseParser.set_callbackc                 C      d S r&   r    r`   r    r    r#   rd   n     zBaseParser.closec                 C   r   r&   r    r`   r    r    r#   rR   q  r   zBaseParser.finalizec                 C      d| j j S Nz%s()rk   rl   r`   r    r    r#   rn   t     zBaseParser.__repr__)NNN)
rl   ro   rp   rq   rO   r   r   rd   rR   rn   r    r    r    r#   r   )  s    
r   c                       sB   e Zd ZdZi edf fdd	Zdd Zdd Zd	d
 Z  Z	S )OctetStreamParsera  This parser parses an octet-stream request body and calls callbacks when
    incoming data is received.  Callbacks are as follows:

    .. list-table::
       :widths: 15 10 30
       :header-rows: 1

       * - Callback Name
         - Parameters
         - Description
       * - on_start
         - None
         - Called when the first data is parsed.
       * - on_data
         - data, start, end
         - Called for each data chunk that is parsed.
       * - on_end
         - None
         - Called when the parser is finished parsing all data.

    :param callbacks: A dictionary of callbacks.  See the documentation for
                      :class:`BaseParser`.

    :param max_size: The maximum size of body to parse.  Defaults to infinity -
                     i.e. unbounded.
    infc                    sH   t t|   || _d| _t|tr|dk rtd| || _d| _	d S NFr   *max_size must be a positive number, not %rr   )
superr   rO   r   _startedr8   r   
ValueErrormax_size_current_size)rM   r   r   rk   r    r#   rO     s   
zOctetStreamParser.__init__c                 C   s|   | j s| d d| _ t|}| j| | jkr-t| j| j }| jd| j| j|| |}|  j|7  _| d|d| |S )zWrite some data to the parser, which will perform size verification,
        and then pass the data to the underlying callback.

        :param data: a bytestring
        r   TDCurrent size is %d (max %d), so truncating data length from %d to %drZ   r   )r   r   r]   r   r   intrw   r   )rM   rZ   data_lennew_sizer    r    r#   rQ     s   

zOctetStreamParser.writec                 C   s   |  d dS )ztFinalize this parser, which signals to that we are finished parsing,
        and sends the on_end callback.
        r   N)r   r`   r    r    r#   rR     r   zOctetStreamParser.finalizec                 C   r   r   r   r`   r    r    r#   rn     r   zOctetStreamParser.__repr__)
rl   ro   rp   rq   floatrO   rQ   rR   rn   __classcell__r    r    r   r#   r   x  s    r   c                       sL   e Zd ZdZi dedf fdd	Zdd Zdd	 Zd
d Zdd Z	  Z
S )QuerystringParsera	  This is a streaming querystring parser.  It will consume data, and call
    the callbacks given when it has data.

    .. list-table::
       :widths: 15 10 30
       :header-rows: 1

       * - Callback Name
         - Parameters
         - Description
       * - on_field_start
         - None
         - Called when a new field is encountered.
       * - on_field_name
         - data, start, end
         - Called when a portion of a field's name is encountered.
       * - on_field_data
         - data, start, end
         - Called when a portion of a field's data is encountered.
       * - on_field_end
         - None
         - Called when the end of a field is encountered.
       * - on_end
         - None
         - Called when the parser is finished parsing all data.

    :param callbacks: A dictionary of callbacks.  See the documentation for
                      :class:`BaseParser`.

    :param strict_parsing: Whether or not to parse the body strictly.  Defaults
                           to False.  If this is set to True, then the behavior
                           of the parser changes as the following: if a field
                           has a value with an equal sign (e.g. "foo=bar", or
                           "foo="), it is always included.  If a field has no
                           equals sign (e.g. "...&name&..."), it will be
                           treated as an error if 'strict_parsing' is True,
                           otherwise included.  If an error is encountered,
                           then a
                           :class:`multipart.exceptions.QuerystringParseError`
                           will be raised.

    :param max_size: The maximum size of body to parse.  Defaults to infinity -
                     i.e. unbounded.
    Fr   c                    sT   t t|   t| _d| _|| _t|tr|dk rt	d| || _
d| _|| _d S r   )r   r   rO   STATE_BEFORE_FIELDstate
_found_sepr   r8   r   r   r   r   strict_parsing)rM   r   r   r   r   r    r#   rO     s   
zQuerystringParser.__init__c              	   C   z   t |}| j| | jkr"t| j| j }| jd| j| j|| |}d}z| ||}W |  j|7  _|S |  j|7  _w )a  Write some data to the parser, which will perform size verification,
        parse into either a field name or value, and then pass the
        corresponding data to the underlying callback.  If an error is
        encountered while parsing, a QuerystringParseError will be raised.  The
        "offset" attribute of the raised exception will be set to the offset in
        the input data chunk (NOT the overall stream) that caused the error.

        :param data: a bytestring
        r   r   r]   r   r   r   rw   r   _internal_writerM   rZ   r   r   lr    r    r#   rQ        
zQuerystringParser.writec                 C   s:  | j }| j}| j}d}||k r|| }|tkrH|tks |tkr:|r7|r/td| }||_|| j	d| nd}n| 
d |d8 }t}d}n|tkr|d|}	|	dkr\|d	|}	|	dkrh|d
||	}
n|d
|}
|
dkr| 
d|||
 |
}t}n|s|	dkr| 
d|||	 | 
d |	d }t}nr| 
d||| |}ng|	dkrtd|f }||_|| 
d||| |}nL|tkr|d|}	|	dkr|d	|}	|	dkr| 
d|||	 | 
d |	d }t}n | 
d||| |}nd||f }| j| t|}||_||d7 }||k s|| _ || _t|S )Nr   z,Skipping duplicate ampersand/semicolon at %dTZfield_startr   F   &r4   r3      =rf   	field_endz{When strict_parsing is True, we require an equals sign in all field chunks. Did not find one in the chunk that starts at %dZ
field_data!Reached an unknown state %d at %d)r   r   r   r   	AMPERSAND	SEMICOLONZQuerystringParseErroroffsetrw   r   r   STATE_FIELD_NAMEfindSTATE_FIELD_DATAr   r]   )rM   rZ   lengthr   r   Z	found_sepichr   Zsep_posZ
equals_posmsgr    r    r#   r     s   



  z!QuerystringParser._internal_writec                 C   s"   | j tkr
| d | d dS )zFinalize this parser, which signals to that we are finished parsing,
        if we're still in the middle of a field, an on_field_end callback, and
        then the on_end callback.
        r   r   N)r   r   r   r`   r    r    r#   rR     s   

zQuerystringParser.finalizec                 C   s   d| j j| j| j| jf S )Nz8%s(keep_blank_values=%r, strict_parsing=%r, max_size=%r))rk   rl   keep_blank_valuesr   r   r`   r    r    r#   rn     s   zQuerystringParser.__repr__rl   ro   rp   rq   r   rO   rQ   r   rR   rn   r   r    r    r   r#   r     s    , 
r   c                       sJ   e Zd ZdZi edf fdd	Zdd Zdd Zd	d
 Zdd Z	  Z
S )MultipartParsera#  This class is a streaming multipart/form-data parser.

    .. list-table::
       :widths: 15 10 30
       :header-rows: 1

       * - Callback Name
         - Parameters
         - Description
       * - on_part_begin
         - None
         - Called when a new part of the multipart message is encountered.
       * - on_part_data
         - data, start, end
         - Called when a portion of a part's data is encountered.
       * - on_part_end
         - None
         - Called when the end of a part is reached.
       * - on_header_begin
         - None
         - Called when we've found a new header in a part of a multipart
           message
       * - on_header_field
         - data, start, end
         - Called each time an additional portion of a header is read (i.e. the
           part of the header that is before the colon; the "Foo" in
           "Foo: Bar").
       * - on_header_value
         - data, start, end
         - Called when we get data for a header.
       * - on_header_end
         - None
         - Called when the current header is finished - i.e. we've reached the
           newline at the end of the header.
       * - on_headers_finished
         - None
         - Called when all headers are finished, and before the part data
           starts.
       * - on_end
         - None
         - Called when the parser is finished parsing all data.


    :param boundary: The multipart boundary.  This is required, and must match
                     what is given in the HTTP request - usually in the
                     Content-Type header.

    :param callbacks: A dictionary of callbacks.  See the documentation for
                      :class:`BaseParser`.

    :param max_size: The maximum size of body to parse.  Defaults to infinity -
                     i.e. unbounded.
    r   c                    s   t t|   t| _d | _| _|| _t|t	r|dk r"t
d| || _d| _i | _t|tr5|d}d| | _t| j| _dd tt|d D | _d S )	Nr   r   r   r2   s   
--c                 S   s   g | ]}t qS r    )NULL).0xr    r    r#   
<listcomp>  s    z,MultipartParser.__init__.<locals>.<listcomp>r   )r   r   rO   STATE_STARTr   indexflagsr   r8   r   r   r   r   marksr   r9   boundary	frozensetboundary_charsranger]   
lookbehind)rM   r   r   r   r   r    r#   rO     s    


 zMultipartParser.__init__c              	   C   r   )a  Write some data to the parser, which will perform size verification,
        and then parse the data into the appropriate location (e.g. header,
        data, etc.), and pass this on to the underlying callback.  If an error
        is encountered, a MultipartParseError will be raised.  The "offset"
        attribute on the raised exception will be set to the offset of the byte
        in the input chunk that caused the error.

        :param data: a bytestring
        r   r   r   r   r    r    r#   rQ     r   zMultipartParser.writec                    s*  j }j}j}j}dfdd}dfdd	}d fdd	}	k r  }
|tkrQ|
tks;|
tkrGd	7 jd
 q&d}t	}d	8 n|t	kr|t
|d kr{|
tkrudf }j| t|}|_||d	7 }nx|t
|d d	 kr|
tkrdf }j| t|}|_|d}d t}nK|
||d  krd|
|d f }j| t|}|_||d	7 }n&|tkrd}|d t}d	8 n|tkrH|
tkr|d t}d	7 q&|d	7 }|
tkrn|
tkr#|d	krdf }j| t|}|_||	d t}nt|
}|tk s1|tkrFd|
f }j| t|}|_|n|tkrc|
tkrWd	7 q&|d t}d	8 n|tkrz|
tkrx|	d d t}ny|tkr|
tkrd|
f }j| t|}|_|t}nW|tkr|
tkrd|
f }j| t|}|_|d t}n0|tkr|d t}d	8 n|tkr|}t
|}|d	 }}j}|dkr|7 |d	 k r  |vr|7 |d	 k r  |vs|8   }
||k r6|| |
kr3|dkr.|	d |d	7 }nmd}nj||krV|d	7 }|
tkrI|tO }nW|
tkrS|tO }nMd}nJ||d	 kr|t@ r|
tkr|t M }d d d}t}d	7 q&d}|t M }n|t@ r|
tkrd d t }nd}|dkr|
j!|d	 < nF|dkrt"j!}d|d| d}|d d	8 n)|t kr|
ttfvr݈jd|
 nd|f }j| t|}|_|d	7 k s+|	dd |	dd |	dd |_|_|_S )Nr   c                    s    j | < d S r&   )r   )rN   )r   rM   r    r#   set_markH  s   z1MultipartParser._internal_write.<locals>.set_markFc                    s    j | d  d S r&   )r   r   )rN   resetr`   r    r#   delete_markL     z4MultipartParser._internal_write.<locals>.delete_markc                    s\   j | }|d u rd S |r|  | dj | < d S |  | j | d  d S )Nr   )r   r   r   r   )rN   	remainingZmarked_indexrZ   r   r   rM   r    r#   data_callbackT  s   z6MultipartParser._internal_write.<locals>.data_callbackr   zSkipping leading CR/LF at %dr   z'Did not find CR at end of boundary (%d)z'Did not find LF at end of boundary (%d)Z
part_beginz.Did not find boundary character %r at index %dZheader_fieldzFound 0-length header at %dz3Found non-alphanumeric character %r in header at %dheader_valueZ
header_endz5Did not find LF character at end of header (found %r)z,Did not find LF at end of headers (found %r)Zheaders_finishedZ	part_dataZpart_endr   z(Consuming a byte '0x%x' in the end stater   T)F)#r   r   r   r   r   CRLFrw   r   STATE_START_BOUNDARYr]   r   ZMultipartParseErrorr   r   STATE_HEADER_FIELD_STARTSTATE_HEADER_FIELDSTATE_HEADERS_ALMOST_DONEHYPHENCOLONSTATE_HEADER_VALUE_START
lower_charLOWER_ALOWER_ZSPACESTATE_HEADER_VALUESTATE_HEADER_VALUE_ALMOST_DONESTATE_PART_DATA_STARTSTATE_PART_DATAr   FLAG_PART_BOUNDARYFLAG_LAST_BOUNDARY	STATE_ENDr   
join_bytes)rM   rZ   r   r   r   r   r   r   r   r   r"   r   r   clZ
prev_indexZboundary_lengthZboundary_endZdata_lengthr   Zlb_datar    r   r#   r   :  s|  












































    
Q

zMultipartParser._internal_writec                 C   s   dS )a'  Finalize this parser, which signals to that we are finished parsing.

        Note: It does not currently, but in the future, it will verify that we
        are in the final state of the parser (i.e. the end of the multipart
        message is well-formed), and, if not, throw an error.
        Nr    r`   r    r    r#   rR     s   	zMultipartParser.finalizec                 C   s   d| j j| jf S )Nz%s(boundary=%r))rk   rl   r   r`   r    r    r#   rn     r   zMultipartParser.__repr__r   r    r    r   r#   r     s    6(   r   c                   @   s\   e Zd ZdZedddddddZdddeei fddZd	d
 Z	dd Z
dd Zdd ZdS )
FormParsera
  This class is the all-in-one form parser.  Given all the information
    necessary to parse a form, it will instantiate the correct parser, create
    the proper :class:`Field` and :class:`File` classes to store the data that
    is parsed, and call the two given callbacks with each field and file as
    they become available.

    :param content_type: The Content-Type of the incoming request.  This is
                         used to select the appropriate parser.

    :param on_field: The callback to call when a field has been parsed and is
                     ready for usage.  See above for parameters.

    :param on_file: The callback to call when a file has been parsed and is
                    ready for usage.  See above for parameters.

    :param on_end: An optional callback to call when all fields and files in a
                   request has been parsed.  Can be None.

    :param boundary: If the request is a multipart/form-data request, this
                     should be the boundary of the request, as given in the
                     Content-Type header, as a bytestring.

    :param file_name: If the request is of type application/octet-stream, then
                      the body of the request will not contain any information
                      about the uploaded file.  In such cases, you can provide
                      the file name of the uploaded file manually.

    :param FileClass: The class to use for uploaded files.  Defaults to
                      :class:`File`, but you can provide your own class if you
                      wish to customize behaviour.  The class will be
                      instantiated as FileClass(file_name, field_name), and it
                      must provide the folllowing functions::
                          file_instance.write(data)
                          file_instance.finalize()
                          file_instance.close()

    :param FieldClass: The class to use for uploaded fields.  Defaults to
                       :class:`Field`, but you can provide your own class if
                       you wish to customize behaviour.  The class will be
                       instantiated as FieldClass(field_name), and it must
                       provide the folllowing functions::
                           field_instance.write(data)
                           field_instance.finalize()
                           field_instance.close()

    :param config: Configuration to use for this FormParser.  The default
                   values are taken from the DEFAULT_CONFIG value, and then
                   any keys present in this dictionary will overwrite the
                   default values.

    r      NF)MAX_BODY_SIZEr   r   r   r   UPLOAD_ERROR_ON_BAD_CTEc
              	      sL  t t	_|	_|	_d	_d 	_	_	_	|	_
t	_t	_	j 	_	j|	 |dkr`G dd dt
	
fdd}

fdd}	
fd	d
}|
||d}t|	jd d}n|dksh|dkrg G dd dt
dd }fdd} 
fdd} 
fdd}	fdd
}|||||d}t|	jd d}n||dkr|d u r	jd tdg g i G dd dt
dd  }
fd!d"}
fd#d$}fd%d&}fd'd(}fd)d*} 	
fd+d,}	
fd-d
}||||||||d.}t||	jd d}n	jd/| td0||	_d S )1Nr   zapplication/octet-streamc                   @      e Zd ZdZdS !FormParser.__init__.<locals>.varsNrl   ro   rp   rT   r    r    r    r#   vars.      r   c                      s    d j d_d S )Nr   )r   rT   r    )	FileClassr   rM   r   r    r#   on_start1     z%FormParser.__init__.<locals>.on_startc                    s    j | ||  d S r&   )rT   rQ   rZ   r   r   r   r    r#   rX   4  s   z$FormParser.__init__.<locals>.on_datac                      s.   j    j  jd ur  d S d S r&   )rT   rR   ra   r    )on_filerM   r   r    r#   ra   7  s
   


z#FormParser.__init__.<locals>.on_end)r$  rX   ra   r  )r   z!application/x-www-form-urlencodedzapplication/x-url-encodedc                   @   r  r  r  r    r    r    r#   r   Q  r!  c                   S   r   r&   r    r    r    r    r#   on_field_startT  r   z+FormParser.__init__.<locals>.on_field_startc                         | ||  d S r&   r\   r&  )name_bufferr    r#   on_field_nameW  r%  z*FormParser.__init__.<locals>.on_field_namec                    s<   j d u r d_ d d = j | ||  d S r-   )rT   r/   rQ   r&  )
FieldClassr,  r   r    r#   on_field_dataZ  s   

z*FormParser.__init__.<locals>.on_field_datac                      sL   j d u r d_ d d = j   j   j  d _ d S r-   )rT   r/   rP   rR   r    )r.  r,  on_fieldr   r    r#   on_field_end`  s   





z)FormParser.__init__.<locals>.on_field_endc                      s    j d ur    d S d S r&   rc   r    r`   r    r#   ra   m  s   
)r)  r-  r/  r1  ra   )r   r   zmultipart/form-datazNo boundary givenc                   @   s   e Zd ZdZdZdZdS )r  NF)rl   ro   rp   rT   writeris_filer    r    r    r#   r     s    c                   S   r   r&   r    r    r    r    r#   on_part_begin  r   z*FormParser.__init__.<locals>.on_part_beginc                    s    j | || }|S r&   )r2  rQ   )rZ   r   r   Zbytes_processedr'  r    r#   on_part_data  s   z)FormParser.__init__.<locals>.on_part_datac                      s,   j   jrj  d S  j  d S r&   )rT   rR   r3  r    )r0  r(  r   r    r#   on_part_end  s   
z(FormParser.__init__.<locals>.on_part_endc                    r*  r&   r+  r&  )header_namer    r#   on_header_field  r%  z,FormParser.__init__.<locals>.on_header_fieldc                    r*  r&   r+  r&  )r  r    r#   on_header_value  r%  z,FormParser.__init__.<locals>.on_header_valuec                      s,   d d  <  d d = d d = d S r-   )r/   r    )r7  r  headersr    r#   on_header_end  s   
z*FormParser.__init__.<locals>.on_header_endc                     s   d_ d} t| \}}|d}|d}|d u r" |_n||jd_d_ dd}|d	ks@|d
ks@|dkrFj_d S |dkrRtj_d S |dkr^tj_d S j	d| jd rqt
d|j_d S )NFs   Content-Dispositions   namer7   r"  Ts   Content-Transfer-Encodings   7bits   binarys   8bits   base64s   quoted-printablez%Unknown Content-Transfer-Encoding: %rr  z'Unknown Content-Transfer-Encoding "{0}")r3  r   rG   rT   r   r2  ZBase64DecoderZQuotedPrintableDecoderrw   r   FormParserErrorformat)Zcontent_dispZdisprD   rf   r   Ztransfer_encoding)r.  r#  r:  rM   r   r    r#   on_headers_finished  s<   



z0FormParser.__init__.<locals>.on_headers_finishedc                      s$   j    jd ur   d S d S r&   )r2  rR   ra   r    )rM   r   r    r#   ra     s   

)r4  r5  r6  r8  r9  r;  r>  ra   zUnknown Content-Type: %rzUnknown Content-Type: {0})ru   rv   rl   rw   content_typer   bytes_receivedparserr0  r(  ra   rt   r#  rH   r.  DEFAULT_CONFIGcopyr   updateobjectr   r   errorr<  r   r   r=  )rM   r?  r0  r(  ra   r   r   r#  r.  r   r$  rX   r   rA  r)  r-  r/  r1  r4  r5  r6  r8  r9  r;  r>  r    )r.  r#  r   r7  r  r:  r,  r0  r(  rM   r   r#   rO     s   	
4
zFormParser.__init__c                 C   s   |  j t|7  _ | j|S )zWrite some data.  The parser will forward this to the appropriate
        underlying parser.

        :param data: a bytestring
        )r@  r]   rA  rQ   rY   r    r    r#   rQ     s   zFormParser.writec                 C   ,   | j durt| j dr| j   dS dS dS )zFinalize the parser.NrR   )rA  hasattrrR   r`   r    r    r#   rR        zFormParser.finalizec                 C   rG  )zClose the parser.Nrd   )rA  rH  rd   r`   r    r    r#   rd   	  rI  zFormParser.closec                 C   r   )Nz%s(content_type=%r, parser=%r))rk   rl   r?  rA  r`   r    r    r#   rn     r   zFormParser.__repr__)rl   ro   rp   rq   r   rB  rt   rH   rO   rQ   rR   rd   rn   r    r    r    r#   r    s$    6
 i
r  Fc           
      C   sl   |  d}|du rttd tdt|\}}| d}|d}|  d}t||||||d}	|	S )	a:  This function is a helper function to aid in creating a FormParser
    instances.  Given a dictionary-like headers object, it will determine
    the correct information needed, instantiate a FormParser with the
    appropriate values and given callbacks, and then return the corresponding
    parser.

    :param headers: A dictionary-like object of HTTP headers.  The only
                    required header is Content-Type.

    :param on_field: Callback to call with each parsed field.

    :param on_file: Callback to call with each parsed file.

    :param trust_x_headers: Whether or not to trust information received from
                            certain X-Headers - for example, the file name from
                            X-File-Name.

    :param config: Configuration variables to pass to the FormParser.
    zContent-TypeNzNo Content-Type header givenzNo Content-Type header given!s   boundaryr2   zX-File-Name)r   r   r   )	r   ru   rv   rl   r   r   rG   r   r  )
r:  r0  r(  Ztrust_x_headersr   r?  paramsr   r   Zform_parserr    r    r#   create_form_parser  s    



rK  r  c                 K   s   t | ||}| d}|durt|}ntd}d}	 t|| d}	||	}
||
 |t|
7 }t|
|	ks<||kr=nq|  dS )aH  This function is useful if you just want to parse a request body,
    without too much work.  Pass it a dictionary-like object of the request's
    headers, and a file-like object for the input stream, along with two
    callbacks that will get called whenever a field or file is parsed.

    :param headers: A dictionary-like object of HTTP headers.  The only
                    required header is Content-Type.

    :param input_stream: A file-like object that represents the request body.
                         The read() method must return bytestrings.

    :param on_field: Callback to call with each parsed field.

    :param on_file: Callback to call with each parsed file.

    :param chunk_size: The maximum size to read from the input stream and write
                       to the parser at one time.  Defaults to 1 MiB.
    zContent-LengthNr   r   Tr  )	rK  r   r   r   minreadrQ   r]   rR   )r:  Zinput_streamr0  r(  
chunk_sizekwargsrA  content_lengthZ
bytes_readZmax_readableZbuffr    r    r#   
parse_formG  s   



rQ  )r  )K
__future__r   r   r   sixr   r   r   Zdecoders
exceptionsurlparser
   ImportErrorurllib.parser   rer   r   ru   r   ior   numbersr   rE  rK   r   r   r   r   r  r  r  r
  r  r  r  r  r  ZSTATE_PART_DATA_ENDr  ZSTATESr  r  r  r  r	  r  r  r   r   r  r  r   r  Zord_charr  escapeSPECIAL_CHARSZ
QUOTED_STRZ	VALUE_STRZOPTION_RE_STRcompiler<   r?   rG   rH   rt   r   r   r   r   r  rK  rQ  r    r    r    r#   <module>   s    


)|  %OJ }      G
1