o
    /h_                     @  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   D/var/www/html/govbot/env/lib/python3.10/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-8)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          )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 }n|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number	next_byteerrr   r   r   decode_integerO   s6   


rD   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)rE   r6   rS   rM   r   r   r   _dict_to_iterablev   s   
rT   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!   )rP   r"   strencode)r&   tr   r   r   rI      s   
rI   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.
        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 r[   )r\   re   resizedr^   r5   r`   r&   r   r   r   rf      s   TheadersIterable[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 %s)r\   rh   r5   _encode_table_size_changerN   rO   rT   iterr   	indexablelenrI   addjoinr1   r2   )	r`   rj   rl   header_blockhpack_headersr   	sensitive
new_headerencodedr   r   r   rW      s&   8




zEncoder.encodeFto_addtuple[bytes, bytes]rv   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_literalrr   _encode_indexed_encode_indexed_literal)r`   ry   rv   rl   r%   r&   indexbitmatchrx   r>   perfectr   r   r   rr     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.   )r9   r"   )r`   r>   fieldr   r   r   r   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.   rm   )r]   rW   r9   rq   rs   r"   )r`   r%   r&   r   rl   name_len	value_lenr   r   r   r~   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.   rm   )r{   r9   ordr]   rW   rq   rs   r"   )r`   r>   r&   r   rl   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.
        rm      r       )r^   r9   r"   )r`   block
size_bytesbr   r   r   rn     s   

z!Encoder._encode_table_size_changeNr    rZ   r    r)   r&   r)   r    rZ   )T)rj   rk   rl   r   r    r"   F)ry   rz   rv   r   rl   r   r    r"   )r>   r)   r    r"   )
r%   r"   r&   r"   r   r"   rl   r   r    r"   )
r>   r)   r&   r"   r   r"   rl   r   r    r"   )r    r"   )__name__
__module____qualname____doc__ra   propertyrf   setterrW   rr   r   r~   r   rn   r   r   r   r   rY      s    
m
1rY   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    rZ   c                 C  s   t  | _|| _| jj| _d S r[   )r   r\   r   re   max_allowed_table_size)r`   r   r   r   r   ra     s   	zDecoder.__init__c                 C  rb   rc   rd   r_   r   r   r   rf     rg   zDecoder.header_table_sizer&   c                 C  s   || j _d S r[   rd   ri   r   r   r   rf     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rd	| 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   
memoryviewrq   r   _decode_indexed_decode_literal_indexr   _update_encoding_context_decode_literal_no_indexr5   r   r   r   _assert_valid_table_sizeUnicodeDecodeError)r`   r:   r   data_memrj   data_leninflated_sizecurrent_indexcurrentindexedliteral_indexencoding_updater   consumedr6   rC   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)rf   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 size)rD   r   r   rf   )r`   r:   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 %d)rD   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rd}t||d d@ rt|}|||	 7 }|rt|
|}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   rD   r\   r   rq   r   r   r   r   rr   r1   r2   )r`   r:   r   total_consumedindexed_namer   not_indexable	high_byter>   r   r%   lengthr6   r&   r   r   r   r   r   B  sX   
zDecoder._decode_literalN)r   r)   r    rZ   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_SIZEra   r   rf   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;   )rE   rF   r    rG   )r&   rU   r    r"   )+r   
__future__r   loggingtypingr   r   
exceptionsr   r   r   rl   r	   huffman_constantsr
   r   huffman_tabler   structr   r   r   tabler   r   collections.abcr   	getLoggerr   r1   
INDEX_NONEr|   r{   ranger4   r   r'   r9   rD   rT   rI   rY   r   r   r   r   r   <module>   s4    




'
 z