o
    hX                     @   s  d Z ddlZddlmZmZ ddlmZmZ ddlm	Z	m
Z
mZ ddlmZ ddlmZmZ dd	lmZ dd
lmZmZ eeZdZdZdZdd edD ZzeZW n eya   e e!fZY nw dZ"dd Z#dd Z$dd Z%dd Z&dd Z'G dd de(Z)G dd de(Z*dS ) ze
hpack/hpack
~~~~~~~~~~~

Implements the HPACK header compression algorithm as detailed by the IETF.
    N   )HeaderTabletable_entry_size)to_byteto_bytes)HPACKDecodingErrorOversizedHeaderListErrorInvalidTableSizeError)HuffmanEncoder)REQUEST_CODESREQUEST_CODES_LENGTH)decode_huffman)HeaderTupleNeverIndexedHeaderTuple          @c                 C   s   g | ]}d | d qS )   r    ).0ir   r   S/var/www/html/magazine_api/magazine_env/lib/python3.10/site-packages/hpack/hpack.py
<listcomp>   s    r   	   i   c                 C   s<   t | d }t | d }|s|d}|d}| ||S )zj
    Provides a header as a unicode string if raw is False, otherwise returns
    it as a bytestring.
    r   r   utf-8)r   decode	__class__)headerrawnamevaluer   r   r   _unicode_if_needed,   s   

r!   c                 C   s   t d| | | dk rtd|  |dk s|dkrtd| t| }| |k r,t| gS |g}| |8 } | dkrH|| d@ d  | d	L } | dks7||  t|S )
zn
    This encodes an integer according to the wacky integer encoding rules
    defined in the HPACK spec.
    zEncoding %d with %d bitsr   z)Can only encode positive integers, got %sr      +Prefix bits must be between 1 and 8, got %s         )logdebug
ValueError_PREFIX_BIT_MAX_NUMBERS	bytearrayappend)integerprefix_bits
max_numberelementsr   r   r   encode_integer9   s(   

r1   c                 C   s   |dk s|dkrt d| t| }d}d}dd| ? }z2t| d |@ }||krM	 t| | }|d7 }|dkrA||d |> 7 }n|||> 7 }n|d7 }q*W n ty[   td	|  w td
|| ||fS )z
    This decodes an integer according to the wacky integer encoding rules
    defined in the HPACK spec. Returns a tuple of the decoded integer and the
    number of bytes that were consumed from ``data`` in order to get that
    integer.
    r   r"   r#   r      Tr$   r&   z5Unable to decode HPACK integer representation from %rzDecoded %d, consumed %d bytes)r)   r*   r   
IndexErrorr   r'   r(   )datar.   r/   indexshiftmasknumberZ	next_byter   r   r   decode_integer[   s8   r9   c                 c   s@    t | tsJ t|  dd d}|D ]	}|| | fV  qdS )z
    This converts a dictionary to an iterable of two-tuples. This is a
    HPACK-specific function becuase it pulls "special-headers" out first and
    then emits them.
    c                 S   s   t | d S )N   :)	_to_bytes
startswith)kr   r   r   <lambda>   s    z#_dict_to_iterable.<locals>.<lambda>)keyN)
isinstancedictsortedkeys)Zheader_dictrC   r?   r   r   r   _dict_to_iterable   s   rD   c                 C   s*   t | ts	t| } t | tr| S | dS )z"
    Convert string to bytes.
    r   )r@   
basestringstrbytesencode)stringr   r   r   r;      s   
r;   c                   @   sj   e Zd ZdZdd Zedd Zejdd Zddd	ZdddZ	dd Z
dddZdddZdd ZdS )Encoderzm
    An HPACK encoder object. This object takes HTTP headers and emits encoded
    HTTP/2 header blocks.
    c                 C   s   t  | _ttt| _g | _d S N)r   header_tabler
   r   r   huffman_codertable_size_changesselfr   r   r   __init__   s
   
zEncoder.__init__c                 C      | j jS z>
        Controls the size of the HPACK header table.
        rL   maxsizerO   r   r   r   header_table_size      zEncoder.header_table_sizec                 C   s$   || j _| j jr| j| d S d S rK   )rL   rU   resizedrN   r,   rP   r    r   r   r   rV      s   Tc                 C   s   t d| g }t|trt|}| jjr ||   d| j_|D ].}d}t|t	r0|j
 }n
t|dkr:|d }t|d t|d f}|| ||| q"d|}t d| |S )a	  
        Takes a set of headers and encodes them into a HPACK-encoded header
        block.

        :param headers: The headers to encode. Must be either an iterable of
                        tuples, an iterable of :class:`HeaderTuple
                        <hpack.struct.HeaderTuple>`, or a ``dict``.

                        If an iterable of tuples, the tuples may be either
                        two-tuples or three-tuples. If they are two-tuples, the
                        tuples must be of the format ``(name, value)``. If they
                        are three-tuples, they must be of the format
                        ``(name, value, sensitive)``, where ``sensitive`` is a
                        boolean value indicating whether the header should be
                        added to header tables anywhere. If not present,
                        ``sensitive`` defaults to ``False``.

                        If an iterable of :class:`HeaderTuple
                        <hpack.struct.HeaderTuple>`, the tuples must always be
                        two-tuples. Instead of using ``sensitive`` as a third
                        tuple entry, use :class:`NeverIndexedHeaderTuple
                        <hpack.struct.NeverIndexedHeaderTuple>` to request that
                        the field never be indexed.

                        .. warning:: HTTP/2 requires that all special headers
                            (headers whose names begin with ``:`` characters)
                            appear at the *start* of the header block. While
                            this method will ensure that happens for ``dict``
                            subclasses, callers using any other iterable of
                            tuples **must** ensure they place their special
                            headers at the start of the iterable.

                            For efficiency reasons users should prefer to use
                            iterables of two-tuples: fixing the ordering of
                            dictionary headers is an expensive operation that
                            should be avoided if possible.

        :param huffman: (optional) Whether to Huffman-encode any header sent as
                        a literal value. Except for use when debugging, it is
                        recommended that this be left enabled.

        :returns: A bytestring containing the HPACK-encoded header block.
        zHPACK encoding %sFr   r   r       zEncoded header block to %s)r'   r(   r@   rA   rD   rL   rX   r,   _encode_table_size_changer   Z	indexablelenr;   addjoin)rP   headershuffmanZheader_blockr   	sensitiver   r   r   rH      s$   2



zEncoder.encodeFc                 C   s   t d| |\}}|stnt}| j||}|du r.| ||||}|s,| j|| |S |\}	}}
|
r<| |	}|S | 	|	|||}|sM| j|| |S )zQ
        This function takes a header key-value tuple and serializes it.
        zAdding %s to the header tableN)
r'   r(   INDEX_INCREMENTALINDEX_NEVERrL   search_encode_literalr]   _encode_indexed_encode_indexed_literal)rP   Zto_addra   r`   r   r    indexbitmatchencodedr5   Zperfectr   r   r   r]   	  s&   

zEncoder.addc                 C   s"   t |d}|d  dO  < t|S )zD
        Encodes a header using the indexed representation.
        r&   r   r$   )r1   rG   )rP   r5   fieldr   r   r   rf   5  s   
zEncoder._encode_indexedc                 C   sx   |r| j |}| j |}tt|d}tt|d}|r.|d  dO  < |d  dO  < d|t||t||gS )z
        Encodes a header with a literal name and literal value. If ``indexing``
        is True, the header will be added to the header table: otherwise it
        will not.
        r&   r   r$   rZ   )rM   rH   r1   r\   r^   rG   )rP   r   r    rh   r`   name_len	value_lenr   r   r   re   =  s   zEncoder._encode_literalc                 C   s|   |t kr
t|d}nt|d}|d  t|O  < |r!| j|}tt|d}|r2|d  dO  < dt|t||gS )zv
        Encodes a header with an indexed name and a literal value and performs
        incremental indexing.
              r   r&   r$   rZ   )rb   r1   ordrM   rH   r\   r^   rG   )rP   r5   r    rh   r`   prefixrm   r   r   r   rg   R  s   
zEncoder._encode_indexed_literalc                 C   s@   d}| j D ]}t|d}|d  dO  < |t|7 }qg | _ |S )zd
        Produces the encoded form of all header table size change context
        updates.
        rZ      r       )rN   r1   rG   )rP   blockZ
size_bytesr   r   r   r[   h  s   

z!Encoder._encode_table_size_changeN)TF)__name__
__module____qualname____doc__rQ   propertyrV   setterrH   r]   rf   re   rg   r[   r   r   r   r   rJ      s    



R,

rJ   c                   @   sp   e Zd ZdZefddZedd Zejdd Zddd	Z	d
d Z
dd Zdd Zdd Zdd Zdd ZdS )Decodera  
    An HPACK decoder object.

    .. versionchanged:: 2.3.0
       Added ``max_header_list_size`` argument.

    :param max_header_list_size: The maximum decompressed size we will allow
        for any single header block. This is a protection against DoS attacks
        that attempt to force the application to expand a relatively small
        amount of data into a really large header list, allowing enormous
        amounts of memory to be allocated.

        If this amount of data is exceeded, a `OversizedHeaderListError
        <hpack.OversizedHeaderListError>` exception will be raised. At this
        point the connection should be shut down, as the HPACK state will no
        longer be useable.

        Defaults to 64kB.
    :type max_header_list_size: ``int``
    c                 C   s   t  | _|| _| jj| _d S rK   )r   rL   max_header_list_sizerU   max_allowed_table_size)rP   r}   r   r   r   rQ     s   	zDecoder.__init__c                 C   rR   rS   rT   rO   r   r   r   rV     rW   zDecoder.header_table_sizec                 C   s   || j _d S rK   rT   rY   r   r   r   rV     s   Fc                    sX  t d| t|}g }t|}d}d}||k rt|| }|d@ r$dnd}	|d@ r,dnd}
|d@ r4dnd}|	rD| ||d \}}n-|
rR| ||d \}}n|rf|rZtd	| ||d }d}n| 	||d \}}|r|
| |t| 7 }|| jkrtd
| j ||7 }||k s|   z
 fdd|D W S  ty   tdw )a  
        Takes an HPACK-encoded header block and decodes it into a header set.

        :param data: A bytestring representing a complete HPACK-encoded header
                     block.
        :param raw: (optional) Whether to return the headers as tuples of raw
                    byte strings or to decode them as UTF-8 before returning
                    them. The default value is False, which returns tuples of
                    Unicode strings
        :returns: A list of two-tuples of ``(name, value)`` representing the
                  HPACK-encoded headers, in the order they were decoded.
        :raises HPACKDecodingError: If an error is encountered while decoding
                                    the header block.
        zDecoding %sr   r$   TF@   rs   Nz/Table size update not at the start of the blockz.A header list larger than %d has been receivedc                    s   g | ]}t | qS r   )r!   )r   hr   r   r   r     s    z"Decoder.decode.<locals>.<listcomp>z"Unable to decode headers as UTF-8.)r'   r(   
memoryviewr\   r   _decode_indexed_decode_literal_indexr   _update_encoding_context_decode_literal_no_indexr,   r   r}   r   _assert_valid_table_sizeUnicodeDecodeError)rP   r4   r   Zdata_memr_   Zdata_lenZinflated_sizeZcurrent_indexcurrentZindexedZliteral_indexZencoding_updater   consumedr   r   r   r     s`   







7zDecoder.decodec                 C   s   | j | jkr
tddS )zs
        Check that the table size set by the encoder is lower than the maximum
        we expect to have.
        z3Encoder did not shrink table size to within the maxN)rV   r~   r	   rO   r   r   r   r     s
   z Decoder._assert_valid_table_sizec                 C   s*   t |d\}}|| jkrtd|| _|S )zC
        Handles a byte that updates the encoding context.
        rr   z)Encoder exceeded max allowable table size)r9   r~   r	   rV   )rP   r4   new_sizer   r   r   r   r     s   
z Decoder._update_encoding_contextc                 C   s4   t |d\}}t| j| }td|| ||fS )zP
        Decodes a header represented using the indexed representation.
        r&   zDecoded %s, consumed %d)r9   r   rL   get_by_indexr'   r(   )rP   r4   r5   r   r   r   r   r   r     s   zDecoder._decode_indexedc                 C      |  |dS )NF_decode_literalrP   r4   r   r   r   r   '     z Decoder._decode_literal_no_indexc                 C   r   )NTr   r   r   r   r   r   *  r   zDecoder._decode_literal_indexc                 C   sz  d}|rt |d d@ }d}d}nt |d }|d@ }d}|d@ }|r7t||\}}	| j|d }
|	}d}n1|dd	 }t|d
\}}	||	|	|  }
t|
|krVtdt |d d@ rbt|
}
|	| d }||	| d	 }t|d
\}}	||	|	|  }t||krtdt |d d@ rt|}|||	 7 }|rt|
|}nt|
|}|r| j	|
| t
d||| ||fS )z>
        Decodes a header represented with a literal.
        r   ?   ro   F   rn      r   Nr&   zTruncated header blockr$   z/Decoded %s, total consumed %d bytes, indexed %s)r   r9   rL   r   r\   r   r   r   r   r]   r'   r(   )rP   r4   Zshould_indexZtotal_consumedZindexed_namerl   Znot_indexableZ	high_byter5   r   r   lengthr    r   r   r   r   r   -  sT   
zDecoder._decode_literalNru   )rv   rw   rx   ry   DEFAULT_MAX_HEADER_LIST_SIZErQ   rz   rV   r{   r   r   r   r   r   r   r   r   r   r   r   r|   v  s    


U
	r|   )+ry   loggingtabler   r   compatr   r   
exceptionsr   r   r	   r`   r
   Zhuffman_constantsr   r   Zhuffman_tabler   structr   r   	getLoggerrv   r'   Z
INDEX_NONErc   rb   ranger*   rE   	NameErrorrF   rG   r   r!   r1   r9   rD   r;   objectrJ   r|   r   r   r   r   <module>   s8   
")
 Z