U
    c37                     @   s  d Z ddlZddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
mZmZmZmZ dd	d
dddddddddddddddddddddd d!d"d#d$gZddlZdd%lmZ d&Zd'd( Zd)d Zd*d+ Zdad,dZd-Zd.Zed/d0dZdbd2dZdced3d4dZed3d5dZddd6dZ ed7d8G d9d dZ!G d:d de"Z#G d;d	 d	e#Z$G d<d
 d
e$Z%G d=d de$Z&G d>d de#Z'G d?d de$Z(d@d Z)G dAd deZ*G dBdC dCeZ+G dDdE dEZ,ddFe-e
dGdHdZ.edIZ/edJZ0edKZ1ee/de1f e
e/ge0f ee0de1f dLdMdNZ2ee/ ee/ddf dOdPdQZ3dee4dRdSdZ5dfe4dRdTdZ6dge4dRdUdZ7G dVd! d!e8Z9ed7d8G dWd  d Z:dXd Z;dYd Z<dZd Z=e>ed[d\d#Z?G d]d^ d^ee/ Z@ee/ ee/ d_d`d$ZAdS )hz
Utility functions for PDF library.
Taken from PyPDF2 with modifications and additions, see
:ref:`here <pypdf2-license>` for the original license of the PyPDF2 project.

Generally, all of these constitute internal API, except for the exception
classes.
    N)	dataclass)datetime)Enum)BytesIO)Callable	GeneratorIterableOptionalTypeVarPdfErrorPdfReadErrorPdfStrictReadErrorPdfWriteErrorPdfStreamErrorIndirectObjectExpectedget_and_applyOrderedEnumStringWithLanguageis_regular_characterread_non_whitespaceread_until_whitespaceread_until_regexskip_over_whitespaceskip_over_commentinstance_testpeek!assert_writable_and_random_accessprepare_rw_output_streamfinalise_outputDEFAULT_CHUNK_SIZEchunked_writechunked_digestchunk_streamConsList	Singletonrdisoparselift_iterable_async)CancelableAsyncIteratori   c                 C   s
   t | dS )N   )roundx r-   :/tmp/pip-unpacked-wheel-0kb_yl26/pyhanko/pdf_utils/misc.py<lambda>'       r/   c                    s    fddS )Nc                    s
   t |  S N)
isinstancer+   clsr-   r.   r/   ,   r0   zinstance_test.<locals>.<lambda>r-   r3   r-   r3   r.   r   *   s    c                 c   sf   t | }zt|}W n tk
r*   Y d S X zt|}W n tk
rT   tdY nX ||fV  qd S )NzList has odd number of elements)iternextStopIteration
ValueError)lstix1Zx2r-   r-   r.   	pair_iter/   s    r<   c                    s&    dkrdS  fdd}d | S )z
    Reads non-whitespace characters and returns them.
    Stops upon encountering whitespace or when maxchars is reached.
    r   r0   c                  3   sP    d krd n
    }  d ks,  | k rLd}| sL|sDqL|V  qd S )N   )tellreadisspace)Zstop_attokmaxcharsstreamr-   r.   _buildE   s    
z%read_until_whitespace.<locals>._build)join)rD   rC   rE   r-   rB   r.   r   =   s    s    
	 s
   ()<>[]{}/%Z
byte_valuec                 C   s   | t ko| tkS r1   )PDF_WHITESPACEPDF_DELIMITERSrG   r-   r-   r.   r   S   s    Fc                 C   sr   t d }|t kr0|s$|rdS td| d}q|dkr<q\q| dtj t|  t d }q|rn| dtj |S )zQ
    Finds and reads the next non-whitespace character (ignores whitespace).
    r   r0   zStream ended prematurelyr=      %)rH   r   r?   seekosSEEK_CURr   )rD   Z	seek_backZ	allow_eofrA   r-   r-   r.   r   W   s    
returnc                 C   sr   t d }d}|t kr\| d}|d7 }|r|dkr:|dkS |dkr| ddkr\|dkS q\q| dtj |dkS )a
  
    Similar to readNonWhitespace, but returns a Boolean if more than
    one whitespace character was read.

    Will return the cursor to before the first non-whitespace character
    encountered, or after the first end-of-line sequence if one is encountered.
    r   r=      
   rK   )rH   r?   rL   rM   rN   )rD   Zstop_after_eolrA   Zcntr-   r-   r.   r   p   s    
c                 C   s:   |  d}| dd |dkr6|dkr2|  d}qdS dS )Nr=   rK   rJ   )rQ   rR   TF)r?   rL   )rD   rA   r-   r-   r.   r      s    
c                 C   sp   d}|  d}|s"|r|S td||}|dk	rb||d|  7 }| | t| d ql||7 }q|S )a  
    Reads until the regular expression pattern matched (ignore the match)
    Raise PdfStreamError on premature end-of-file.
    :param bool ignore_eof: If true, ignore end-of-line and return immediately
    :param regex: regex to match
    :param stream: stream to search
    r0      zStream has ended unexpectedlyNr=   )r?   r   searchstartrL   len)rD   regexZ
ignore_eofnamerA   mr-   r-   r.   r      s    


T)frozenc                   @   sB   e Zd ZU dZeed< dZee ed< dZee ed< dd Z	dS )r   z2
    A string with a language attached to it.
    valueN	lang_codecountry_codec                 C   s   | j S r1   r[   selfr-   r-   r.   __str__   s    zStringWithLanguage.__str__)
__name__
__module____qualname____doc__str__annotations__r\   r	   r]   ra   r-   r-   r-   r.   r      s
   
c                       s"   e Zd Zed fddZ  ZS )r   msgc                    s   || _ t j|f|  d S r1   )ri   super__init__)r`   ri   args	__class__r-   r.   rk      s    zPdfError.__init__)rb   rc   rd   rf   rk   __classcell__r-   r-   rm   r.   r      s   c                   @   s   e Zd ZdS )r   Nrb   rc   rd   r-   r-   r-   r.   r      s   c                   @   s   e Zd ZdS )r   Nrp   r-   r-   r-   r.   r      s   c                       s(   e Zd Zdee d fddZ  ZS )r   Nrh   c                    s   t  j|pdd d S )Nzindirect object expectedrh   )rj   rk   )r`   ri   rm   r-   r.   rk      s    zIndirectObjectExpected.__init__)N)rb   rc   rd   r	   rf   rk   ro   r-   r-   rm   r.   r      s   c                   @   s   e Zd ZdS )r   Nrp   r-   r-   r-   r.   r      s   c                   @   s   e Zd ZdS )r   Nrp   r-   r-   r-   r.   r      s   c                    s(   t t  fdd} | fS )Nc                   3   s    V  E d H  d S r1   r-   r-   firstitrr-   r.   _itr   s    zpeek.<locals>._itr)r5   r6   )rs   rt   r-   rq   r.   r      s    c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )r   z6
    Ordered enum (from the Python documentation)
    c                 C   s    | j |j kr| j|jkS td S r1   rn   r[   NotImplementedErrorr`   otherr-   r-   r.   __ge__   s    zOrderedEnum.__ge__c                 C   s    | j |j kr| j|jkS td S r1   ru   rw   r-   r-   r.   __gt__   s    zOrderedEnum.__gt__c                 C   s    | j |j kr| j|jkS td S r1   ru   rw   r-   r-   r.   __le__   s    zOrderedEnum.__le__c                 C   s    | j |j kr| j|jk S td S r1   ru   rw   r-   r-   r.   __lt__   s    zOrderedEnum.__lt__Nrb   rc   rd   re   ry   rz   r{   r|   r-   r-   r-   r.   r      s
   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )VersionEnumz
    Ordered enum with support for ``None``, for future-proofing version-based
    enums. In such enums, the value ``None`` can be used as a stand-in for
    "any future version".
    c                 C   s@   | j |j kr8| j}|j}|d kr$dS |d kr0dS ||kS td S NTFru   r`   rx   valZ	other_valr-   r-   r.   ry     s    zVersionEnum.__ge__c                 C   sD   | j |j kr<| j}|j}|d kr(|d k	S |d kr4dS ||kS td S NFru   r   r-   r-   r.   rz     s    zVersionEnum.__gt__c                 C   s@   | j |j kr8| j}|j}|d kr$dS |d kr0dS ||kS td S r   ru   r   r-   r-   r.   r{     s    zVersionEnum.__le__c                 C   sD   | j |j kr<| j}|j}|d kr(|d k	S |d kr4dS ||k S td S r   ru   r   r-   r-   r.   r|   *  s    zVersionEnum.__lt__Nr}   r-   r-   r-   r.   r~      s
   r~   c                   @   s   e Zd Zdd Zdd ZdS )LazyJoinc                 C   s   || _ || _d S r1   )sepiterator)r`   r   r   r-   r-   r.   rk   9  s    zLazyJoin.__init__c                 C   s   | j | jS r1   )r   rF   r   r_   r-   r-   r.   ra   =  s    zLazyJoin.__str__N)rb   rc   rd   rk   ra   r-   r-   r-   r.   r   7  s   r   )default)
dictionaryfunctionc                C   s.   z| | }W n t k
r$   | Y S X ||S r1   )KeyError)r   keyr   r   r[   r-   r-   r.   r   A  s
    
XYR)genfuncrP   c              
   c   sF   z|t | V  W q  tk
r> } z|j W Y S d }~X Y q X q d S r1   )r6   r7   r[   )r   r   er-   r-   r.   map_with_returnN  s    r   )r,   rP   c                 c   s   | E d H  d S r1   r-   r+   r-   r-   r.   _as_genX  s    r   )temp_bufferc                 c   s   d}|d ks||k r| }|d k	rD|| }|t | k rDt| d | }||}||7 }|s^d S |t |k r|t|d | }n|}|V  qd S )Nr   )rV   
memoryviewreadinto)r   rD   max_readZ
total_readZread_bufferZto_read
bytes_readZto_feedr-   r-   r.   r"   \  s    
c                 C   s"   t | ||dD ]}|| qd S N)r   )r"   update)r   rD   Zmdr   chunkr-   r-   r.   r!   r  s    c                 C   s"   t | ||dD ]}|| qd S r   )r"   write)r   rD   outputr   r   r-   r-   r.   r    w  s    c                   @   s   e Zd Zdd ZdS )r$   c                    s,   t | |||}t |  fdd|_|S )Nc                    s    S r1   r-   )_instancer-   r.   r/     r0   z#Singleton.__new__.<locals>.<lambda>)type__new____call__)ZmcsrX   basesdctr4   r-   r   r.   r   ~  s    
zSingleton.__new__N)rb   rc   rd   r   r-   r-   r-   r.   r$   |  s   c                   @   s^   e Zd ZU eed< dZd ed< ed dddZed dddZd	d
 Z	dd Z
dd ZdS )r#   headNtailrO   c                   C   s
   t d dS )N)r   r#   r-   r-   r-   r.   empty  s    zConsList.emptyc                 C   s   t | t  S r1   )r#   r   r^   r-   r-   r.   sing  s    zConsList.singc                 c   s"   | }|j d k	r|j V  |j}qd S r1   )r   r   )r`   curr-   r-   r.   __iter__  s    
zConsList.__iter__c                 C   s
   t || S r1   r   )r`   r   r-   r-   r.   cons  s    zConsList.consc                 C   s   dt tt |  dS )Nz	ConsList())listreversedr_   r-   r-   r.   __repr__  s    zConsList.__repr__)rb   rc   rd   objectrg   r   staticmethodr   r   r   r   r   r-   r-   r-   r.   r#     s   
c                 C   s    |   std|  o|  S )z
    Raise an error if the buffer in question is not writable, and return
    a boolean to indicate whether it supports random-access reading.

    :param output:
    :return:
    zOutput buffer is not writable)writableIOErrorseekablereadabler   r-   r-   r.   r     s
    c                 C   s"   | dkrt  } nt| st  } | S )aB  
    Prepare an output stream that supports both reading and writing.
    Intended to be used for writing & updating signed files:
    when producing a signature, we render the PDF to a byte buffer with
    placeholder values for the signature data, or straight to the provided
    output stream if possible.

    More precisely: this function will return the original output stream
    if it is writable, readable and seekable.
    If the ``output`` parameter is ``None``, not readable or not seekable,
    this function will return a :class:`.BytesIO` instance instead.
    If the ``output`` parameter is not ``None`` and not writable,
    :class:`.IOError` will be raised.

    :param output:
        A writable file-like object, or ``None``.
    :return:
        A file-like object that supports reading, writing and seeking.
    N)r   r   r   r-   r-   r.   r     s
    c                 C   s@   | dk	r<| |k	r<t |tst| }| | |  | S |S )z
    Several internal APIs transparently replaces non-readable/seekable
    buffers with BytesIO for signing operations, but we don't want to
    expose that to the public API user.
    This internal API function handles the unwrapping.
    N)r2   r   AssertionError	getbufferr   release)Zorig_outputZreturned_outputZraw_bufr-   r-   r.   r     s    
)dt_strrP   c                 C   sP   zddl m} W n tk
r*   tj}Y nX || }|jd krL|jtjd}|S )Nr   )r&   )tzinfo)	Zdateutil.parserr&   ImportErrorr   fromisoformatr   replacepytzUTC)r   parsedtr-   r-   r.   r&     s    
c                   @   s4   e Zd ZedddZdd Zee dddZd	S )
_LiftedIterablerO   c                    s
   t | jS r1   )r6   r:   r_   r-   r-   r.   	__anext__  s    z_LiftedIterable.__anext__c                    s   d S r1   r-   r_   r-   r-   r.   cancel  s    z_LiftedIterable.cancelr:   c                 C   s   t || _d S r1   )r5   r:   )r`   r:   r-   r-   r.   rk     s    z_LiftedIterable.__init__N)rb   rc   rd   r   r   r   r   rk   r-   r-   r-   r.   r     s   r   )r:   rP   c                    s   t | S r1   )r   r   r-   r-   r.   r'     s    )N)FF)F)F)N)N)N)Bre   rM   Zdataclassesr   r   enumr   ior   typingr   r   r   r	   r
   __all__r   Zpyhanko_certvalidatorr(   r   r%   r   r<   r   rH   rI   intr   r   boolr   r   r   r   	Exceptionr   r   r   r   r   r   r   r   r~   r   dictr   r   r   r   r   r   	bytearrayr"   r!   r    r   r$   r#   r   r   r   rf   r&   r   r'   r-   r-   r-   r.   <module>   s   
                   



8

	