o
    "=jÂ_  ã                   @  s  d Z ddlmZ ddl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mZ ddlmZmZ erLddlmZ e e¡ZdZdZdZ dd„ e!dƒD ƒZ"dZ#d4dd„Z$d5d d!„Z%d6d%d&„Z&d7d*d+„Z'd8d.d/„Z(G d0d1„ d1ƒZ)G d2d3„ d3ƒZ*dS )9zL
Implements the HPACK header compression algorithm as detailed by RFC 7541.
é    )ÚannotationsN)ÚTYPE_CHECKINGÚAnyé   )ÚHPACKDecodingErrorÚInvalidTableSizeErrorÚOversizedHeaderListError)ÚHuffmanEncoder)ÚREQUEST_CODESÚREQUEST_CODES_LENGTH)Údecode_huffman)ÚHeaderTupleÚHeaderWeaklyTypedÚNeverIndexedHeaderTuple)ÚHeaderTableÚtable_entry_size)ÚIterableó    ó   ó   @c                 C  s   g | ]}d | d ‘qS )é   r   © )Ú.0Úir   r   úUC:\Users\psant\Downloads\Anu Raj Backend\school\venv\Lib\site-packages\hpack/hpack.pyÚ
<listcomp>   s    r   é	   i   Úheaderr   ÚrawÚboolÚreturnr   c                 C  s@   t | d ƒ}t | d ƒ}|s|  | d¡| d¡¡S |  ||¡S )zj
    Provides a header as a unicode string if raw is False, otherwise returns
    it as a bytestring.
    r   r   úutf-8N)ÚbytesÚ	__class__Údecode)r   r   ÚnameÚvaluer   r   r   Ú_unicode_if_needed#   s
   r'   ÚintegerÚintÚprefix_bitsÚ	bytearrayc                 C  s®   t  d| |¡ | dk rd| › �}t|ƒ‚|dk s|dkr%d|› �}t|ƒ‚t| }| |k r2t| gƒS |g}| |8 } | dkrN| | d@ d ¡ | d	L } | dks=| | ¡ t|ƒS )zi
    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 r   é   ú)Prefix bits must be between 1 and 8, got é€   é   é   N)ÚlogÚdebugÚ
ValueErrorÚ_PREFIX_BIT_MAX_NUMBERSr+   Úappend)r(   r*   ÚmsgÚ
max_numberÚelementsr   r   r   Úencode_integer0   s$   


þ
r9   Údatar"   útuple[int, int]c           
   
   C  sÞ   |dk s|dkrd|› �}t |ƒ‚t| }d}d}dd| ? }z.| d |@ }||krL	 | | }|d7 }|dkr@||d |> 7 }n|||> 7 }qL|d7 }q+W n tyc }	 z
d	| ›�}t|ƒ|	‚d
}	~	ww t d||¡ ||fS )zï
    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.   r0   z3Unable to decode HPACK integer representation from NzDecoded %d, consumed %d bytes)r3   r4   Ú
IndexErrorr   r1   r2   )
r:   r*   r6   r7   ÚindexÚshiftÚmaskÚnumberZ	next_byteÚerrr   r   r   Údecode_integerO   s6   
÷€

€þrC   Úheader_dictúdict[bytes | str, bytes | str]ú)Iterable[tuple[bytes | str, bytes | str]]c                 c  sR   � t | tƒsdt| ƒ› �}t|ƒ‚t|  ¡ dd„ d�}|D ]	}|| | fV  qdS )z¯
    Converts a dictionary to an iterable of key-value tuples. This is a
    HPACK-specific function because it pulls "special-headers" out first and
    then emits them.
    zheader_dict not a dict, but c                 S  s   t | ƒ d¡ S )Nó   :)Ú	_to_bytesÚ
startswith)Úkr   r   r   Ú<lambda>ƒ   s    z#_dict_to_iterable.<locals>.<lambda>)ÚkeyN)Ú
isinstanceÚdictÚtypeÚ	TypeErrorÚsortedÚkeys)rD   r6   rR   rL   r   r   r   Ú_dict_to_iterablev   s   €
þÿrS   r&   úbytes | str | Anyc                 C  s.   t | ƒ}|tu r
| S |turt| ƒ} |  d¡S )zB
    Convert anything to bytes through a UTF-8 encoded string
    r!   N)rO   r"   ÚstrÚencode)r&   Útr   r   r   rH   ‰   s   
rH   c                   @  s~   e Zd ZdZd%dd„Zed&dd„ƒZejd'd
d„ƒZ	d(d)dd„Zd*d+dd„Z	d,dd„Z
d*d-dd„Zd*d.d d!„Zd/d"d#„Zd$S )0ÚEncoderzm
    An HPACK encoder object. This object takes HTTP headers and emits encoded
    HTTP/2 header blocks.
    r    ÚNonec                 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__r)   c                 C  ó   | j jS ©z>
        Controls the size of the HPACK header table.
        N©r[   Úmaxsizer^   r   r   r   Úheader_table_size¢   ó   zEncoder.header_table_sizer&   c                 C  s$   || j _| j jr| j |¡ d S d S rZ   )r[   rd   Úresizedr]   r5   ©r_   r&   r   r   r   re   ©   s   ÿTÚheadersú‡Iterable[HeaderTuple | tuple[bytes | str, bytes | str] | tuple[bytes | str, bytes | str, bool | None]] | dict[bytes | str, bytes | str]Úhuffmanr   r"   c           	      C  s¼   g }| j jr| |  ¡ ¡ d| j _t|tƒrt|ƒ}n	 t|ƒ}|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.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.HeaderTuple>`, the tuples must always be
                        two-tuples. Instead of using ``sensitive`` as a third
                        tuple entry, use :class:`NeverIndexedHeaderTuple
                        <hpack.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.
        Fr   r   r   ó    zEncoded header block to %sN)r[   rg   r5   Ú_encode_table_size_changerM   rN   rS   Úiterr   Z	indexableÚlenrH   ÚaddÚjoinr1   r2   )	r_   ri   rk   Zheader_blockZhpack_headersr   Ú	sensitiveZ
new_headerÚencodedr   r   r   rV   ¯   s&   8




zEncoder.encodeFÚto_addútuple[bytes, bytes]rr   c                 C  s¢   t  d|||¡ |\}}|stnt}| j ||¡}|du r0|  ||||¡}|s.| j ||¡ |S |\}	}}
|
r>|  |	¡}|S |  	|	|||¡}|sO| j ||¡ |S )z6
        Serializes a header key-value tuple.
        z7Adding %s to the header table, sensitive:%s, huffman:%sN)
r1   r2   ÚINDEX_INCREMENTALÚINDEX_NEVERr[   ÚsearchÚ_encode_literalrp   Ú_encode_indexedÚ_encode_indexed_literal)r_   rt   rr   rk   r%   r&   ÚindexbitÚmatchrs   r>   Zperfectr   r   r   rp     s0   ü

úÿzEncoder.addr>   c                 C  s"   t |dƒ}|d  dO  < t|ƒS )zD
        Encodes a header using the indexed representation.
        r0   r   r.   N)r9   r"   )r_   r>   Úfieldr   r   r   rz   M  s   
zEncoder._encode_indexedr%   r|   c                 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.
        r0   r   r.   rl   N)r\   rV   r9   ro   rq   r"   )r_   r%   r&   r|   rk   Úname_lenÚ	value_lenr   r   r   ry   U  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   r0   r.   rl   N)rv   r9   Úordr\   rV   ro   rq   r"   )r_   r>   r&   r|   rk   Úprefixr€   r   r   r   r{   j  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.
        rl   é   r   é    N)r]   r9   r"   )r_   ÚblockZ
size_bytesÚbr   r   r   rm   €  s   

z!Encoder._encode_table_size_changeN©r    rY   ©r    r)   ©r&   r)   r    rY   )T)ri   rj   rk   r   r    r"   ©F)rt   ru   rr   r   rk   r   r    r"   )r>   r)   r    r"   )
r%   r"   r&   r"   r|   r"   rk   r   r    r"   )
r>   r)   r&   r"   r|   r"   rk   r   r    r"   )r    r"   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r`   Úpropertyre   ÚsetterrV   rp   rz   ry   r{   rm   r   r   r   r   rX   •   s    
úm
1rX   c                   @  s„   e Zd ZdZefd#dd„Zed$dd	„ƒZejd%dd	„ƒZd&d'dd„Z	d(dd„Z
d)dd„Zd*dd„Zd*dd„Zd*dd„Zd+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 usable.

        Defaults to 64kB.
    :type max_header_list_size: ``int``
    Úmax_header_list_sizer)   r    rY   c                 C  s   t ƒ | _|| _| jj| _d S rZ   )r   r[   r”   rd   Úmax_allowed_table_size)r_   r”   r   r   r   r`   ¤  s   	zDecoder.__init__c                 C  ra   rb   rc   r^   r   r   r   re   À  rf   zDecoder.header_table_sizer&   c                 C  s   || j _d S rZ   rc   rh   r   r   r   re   Ç  s   Fr:   r"   r   r   úIterable[HeaderTuple]c              
     sn  t  d|¡ t|ƒ}g }t|ƒ}d}d}||k r•|| }t|d@ ƒ}	t|d@ ƒ}
t|d@ ƒ}|	r<|  ||d… ¡\}}n/|
rJ|  ||d… ¡\}}n!|r`|rTd}t|ƒ‚|  ||d… ¡}d}n|  	||d… ¡\}}|r�| 
|¡ |t|d |d ƒ7 }|| jkr�d	| j› d
�}t|ƒ‚||7 }||k s|  ¡  z
‡ fdd„|D ƒW S  ty¶ } zd}t|ƒ|‚d}~w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.   é@   r†   Nz/Table size update not at the start of the blockr   zA header list larger than z 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)r1   r2   Ú
memoryviewro   r   Ú_decode_indexedÚ_decode_literal_indexr   Ú_update_encoding_contextÚ_decode_literal_no_indexr5   r   r”   r   Ú_assert_valid_table_sizeÚUnicodeDecodeError)r_   r:   r   Zdata_memri   Údata_lenZinflated_sizeZcurrent_indexÚcurrentZindexedZliteral_indexZencoding_updater   Úconsumedr6   rB   r   r™   r   r$   Ë  s\   

ÿ

ÿ
ÿ
ÿ

Ñ4
€þzDecoder.decodec                 C  s   | j | jkrd}t|ƒ‚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)re   r•   r   )r_   r6   r   r   r   rŸ     s   þz Decoder._assert_valid_table_sizec                 C  s.   t |dƒ\}}|| jkrd}t|ƒ‚|| _|S )zC
        Handles a byte that updates the encoding context.
        r…   z)Encoder exceeded max allowable table sizeN)rC   r•   r   re   )r_   r:   Znew_sizer£   r6   r   r   r   r�   '  s   
z Decoder._update_encoding_contextútuple[HeaderTuple, int]c                 C  s4   t |dƒ\}}t| j |¡Ž }t d||¡ ||fS )zP
        Decodes a header represented using the indexed representation.
        r0   zDecoded %s, consumed %dN)rC   r   r[   Úget_by_indexr1   r2   )r_   r:   r>   r£   r   r   r   r   r›   3  s   zDecoder._decode_indexedc                 C  ó   | j |dd�S )NF©Úshould_index©Ú_decode_literal©r_   r:   r   r   r   rž   <  ó   z Decoder._decode_literal_no_indexc                 C  r¦   )NTr§   r©   r«   r   r   r   rœ   ?  r¬   zDecoder._decode_literal_indexr¨   c                 C  sv  d}|r|d d@ }d}d}n|d }|d@ }d}t |d@ ƒ}|r5t||ƒ\}}	| j |¡d }
|	}d}n1|dd	… }t|d
ƒ\}}	||	|	| … }
t|
ƒ|krVd}t|ƒ‚|d d@ r`t|
ƒ}
|	| d }||	| d	… }t|d
ƒ\}}	||	|	| … }t|ƒ|kr‰d}t|ƒ‚|d d@ r“t|ƒ}|||	 7 }|r¡t|
|ƒ}nt|
|ƒ}|r¯| j 	|
|¡ t
 d|||¡ ||fS )z>
        Decodes a header represented with a literal.
        r   é?   r‚   Fé   r�   é   r   Nr0   zTruncated header blockr.   z/Decoded %s, total consumed %d bytes, indexed %s)r   rC   r[   r¥   ro   r   r   r   r   rp   r1   r2   )r_   r:   r¨   Ztotal_consumedZindexed_namer   Znot_indexableZ	high_byter>   r£   r%   Úlengthr6   r&   r   r   r   r   rª   B  sX   
üzDecoder._decode_literalN)r”   r)   r    rY   rŠ   r‹   rŒ   )r:   r"   r   r   r    r–   r‰   )r:   r"   r    r)   )r:   r"   r    r¤   )r:   r"   r¨   r   r    r¤   )r�   rŽ   r�   r�   ÚDEFAULT_MAX_HEADER_LIST_SIZEr`   r‘   re   r’   r$   rŸ   r�   r›   rž   rœ   rª   r   r   r   r   r“   Ž  s    
S
	

	
r“   )r   r   r   r   r    r   )r(   r)   r*   r)   r    r+   )r:   r"   r*   r)   r    r;   )rD   rE   r    rF   )r&   rT   r    r"   )+r�   Ú
__future__r   ÚloggingÚtypingr   r   Ú
exceptionsr   r   r   rk   r	   Zhuffman_constantsr
   r   Zhuffman_tabler   Ústructr   r   r   Útabler   r   Úcollections.abcr   Ú	getLoggerr�   r1   Z
INDEX_NONErw   rv   Úranger4   r±   r'   r9   rC   rS   rH   rX   r“   r   r   r   r   Ú<module>   s4    




'
 z