
    Wwg                    @   d Z 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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mZmZmZmZ ddlmZmZmZmZmZmZmZmZm Z m!Z!m"Z" ejF                  rdd	l$m%Z% g d
Z&dZ'dZ( ejR                  djU                  d            Z+ ejX                  e-      Z. G d dej^                        Z0de0fdZ1 G d d      Z2 G d de2      Z3 e
d       G d de2             Z4	 dWddde5ddfdZ6 G d  d      Z7 G d! d"e7      Z8 G d# d$e7      Z9 G d% d&e:e7      Z; G d' d(e7e2      Z< G d) d*ejz                  e7      Z> G d+ d,e?e7      Z@d-eeAeBeCf   ded.   fd/ZDd0ZEded.   fd1ZFdeBfd2ZGded.   fd3ZH G d4 d5eBe7      ZI G d6 d7ej^                        ZJd8eeBeCf   deJfd9ZK G d: d;eAe7      ZLd< ZMd=eBdd>fd?ZN G d@ d>eAe7      ZOdA ZP G dB dCeQe7      ZR G dD dEeR      ZSdF ZTdG ZUdHZV eWeV      dIk(  sJ  eXeV      D  ci c]  \  } }|| 
 c}} ZYeOZZeLeIeRe;fZ[dJ Z\ G dK dLe7      Z]dMZ^dNedeLfdOZ_ ejR                  dP      Z` ejR                  dQ      Za ejR                  dR      Zb ejR                  dS      ZcdXdTeAdUe5defdVZdyc c}} w )Yz
Implementation of PDF object types and other generic functionality.
The internals were imported from PyPDF2, with modifications.

See :ref:`here <pypdf2-license>` for the original license
of the PyPDF2 project.
    N)	dataclassfield)datetime	timedeltatimezone)BytesIO)AnyCallableIteratorOptionalTupleUnion   )IndirectObjectExpectedPdfErrorPdfReadErrorPdfStreamErrorPdfStrictReadErrorPdfWriteErroris_regular_characterread_non_whitespaceread_until_delimiterread_until_regexskip_over_whitespaceSecurityHandler)Dereferenceable	ReferenceTrailerReference	PdfObjectIndirectObject
NullObjectBooleanObjectFloatObjectNumberObjectByteStringObjectTextStringObject
NameObjectArrayObjectDictionaryObjectStreamObjectread_objectpdf_name
pdf_stringpdf_dateTextStringEncodingEncryptedObjAccessDecryptedObjectProxys   /<[tf(n%s   +-z(\d+)\s+(\d+)\s+R[^a-zA-Z]asciic                        e Zd ZdZdZ	 dZ	 dZy)r1   zt
    Defines what to do when an encrypted object is encountered when retrieving
    an object from a container.
    r   r      N)__name__
__module____qualname____doc__PROXYTRANSPARENTRAW     P/var/www/horilla/myenv/lib/python3.12/site-packages/pyhanko/pdf_utils/generic.pyr1   r1   G   s+    
 E
 K	 Cr>   r1   eoac                     t        | t              r>|t        j                  k(  r| j                  S |t        j
                  k(  r| j                  S | S N)
isinstancer2   r1   r;   	decryptedr<   
raw_object)objr@   s     r?   _deproxy_decryptrG   f   sD    #+,$000== &***>>!Jr>   c                       e Zd ZdZddZd Zy)r   aD  
    Represents an opaque reference to a PDF object associated with
    a PDF Handler (see :class:`PdfHandler <.rw_common.PdfHandler>`).

    This can either be a reference to an object with an object ID
    (see :class:`.Reference`) or a reference to the trailer of a PDF document
    (see :class:`.TrailerReference`).
    c                     t         )zgRetrieve the PDF object backing this dereferenceable.

        :return: A :class:`.PdfObject`.
        NotImplementedErrorselfs    r?   
get_objectzDereferenceable.get_objecty   
    
 "!r>   c                     t         )zzReturn the PDF handler associated with this dereferenceable.

        :return: a :class:`~.rw_common.PdfHandler`.
        rJ   rL   s    r?   get_pdf_handlerzDereferenceable.get_pdf_handler   rO   r>   Nreturnr    )r6   r7   r8   r9   rN   rQ   r=   r>   r?   r   r   o   s    ""r>   r   c                   $    e Zd ZdZd ZddZd Zy)r   ao  
    A reference to the trailer of a PDF document.

    .. warning::
       Since the trailer does not have a well-defined object ID in files with
       "classical" cross-reference tables (as opposed to cross-reference
       streams), this is not a subclass of :class:`.Reference`.

    :param reader:
        a :class:`~pyhanko.pdf_utils.reader.PdfFileReader`
    c                     || _         y rB   reader)rM   rW   s     r?   __init__zTrailerReference.__init__   s	    r>   c                 .    | j                   j                  S rB   )rW   trailerrL   s    r?   rN   zTrailerReference.get_object   s    {{"""r>   c                     | j                   S rB   rV   rL   s    r?   rQ   z TrailerReference.get_pdf_handler   s    {{r>   NrR   )r6   r7   r8   r9   rX   rN   rQ   r=   r>   r?   r   r      s    
#r>   r   T)frozenc                   `    e Zd ZU dZeed<   	 dZeed<   	  edddd      Ze	ed<   	 dd	Z
d
 Zy)r   a  
    A reference to an object with a certain ID and generation number, with
    a PDF handler attached to it.

    .. warning::
       Contrary to what one might expect, the generation number does *not*
       indicate the document revision in which the object was modified. In fact,
       nonzero generation numbers are exceedingly rare these days; in most
       real-world PDF files, objects are simply overridden without ever
       increasing the generation number.

       Except in very specific circumstances, dereferencing a
       :class:`.Reference` will return the most recent version of the object
       with the stated object ID and generation number.
    idnumr   
generationFN)reprhashcomparedefaultpdfc                     | j                   
t               S ddlm} t	        | j                   |      sJ | j                   j                  |       j                         S )Nr   
PdfHandler)rd   r"   pyhanko.pdf_utils.rw_commonrg   rC   rN   )rM   rg   s     r?   rN   zReference.get_object   sI    88<:$((J///xx""4(3355r>   c                     | j                   S rB   )rd   rL   s    r?   rQ   zReference.get_pdf_handler   s    xxr>   rR   )r6   r7   r8   r9   int__annotations__r_   r   rd   objectrN   rQ   r=   r>   r?   r   r      sJ      J J UtLCL6r>   r   container_refas_metadata_streamrS   r    c                 T   | j                  d      }| j                  dt        j                         t        j                  |      }|dk(  rt        j                  |       }n|dk(  r]| j                  d      }| j                  dt        j                         |dk(  rt        j                  | ||      }nit        |       }n\|dk(  rt        j                  | |      }n?|dk(  s|d	k(  rt        j                  |       }n|d
k(  rt        |       }n|dk(  rt        j                  |       }n|dk(  rR|dvr| j                  d      }|dvrt        |        | j                  dt        j                         t        | |      }n|t         v rt"        j                  |       }n|| j                  d      }| j                  t%        |       t        j                         t&        j)                  |      t*        j                  | |      }nt"        j                  |       }||_        |S )a  
    Read a PDF object from an input stream.

    .. note::
       The `container_ref` parameter tells the API which reference to register
       when the returned object is modified in an incremental update.
       See also here :ref:`here <container-ref-example>` for further
       information.

    :param stream:
        An input stream.
    :param container_ref:
        A reference to an object containing this one.

        *Note:* It is perfectly possible (and common) for `container_ref` to
        resolve to the return value of this function.
    :param as_metadata_stream:
        Whether to dereference the object as an XMP metadata stream.
    :return:
        A :class:`.PdfObject`.
    r   r   r5      <<rn                  )      
   )readseekosSEEK_CUROBJECT_PREFIXESfindr(   read_from_streamr*   read_hex_string_from_streamr)   r#   read_string_from_streamr"   r   r,   NUMBER_SIGNSr%   lenINDIRECT_PATTERNmatchr!   rm   )streamrm   rn   tokidxresultpeeks          r?   r,   r,      s   2 ++a.C
KKBKK 


s
#C
ax,,V4	{{1~B$5=%66:L 7 F 18F	--fmD	SAX//7	(0	,,V4	'++a.C 'F#B$V]3 ,!226:F;;r?DKKT
BKK0%%d+7'88O%66v>(FMr>   c                   \    e Zd ZU dZdZee   ed<   	 defdZd Z		 	 d
ded   dee
   fd	Zy)r    zSuperclass for all PDF objects.Nrm   rS   c                 8    | j                   }|t        d      |S )z
        Return a reference to the closest parent object containing this object.
        Raises an error if no such reference can be found.
        zONo container reference available. This object probably wasn't read from a file.)rm   r   )rM   refs     r?   get_container_refzPdfObject.get_container_ref=  s-    
   ;,  
r>   c                     | S )zpResolves indirect references.

        :return: `self`, unless an instance of :class:`.IndirectObject`.
        r=   rL   s    r?   rN   zPdfObject.get_objectJ  s	    
 r>   handlerr   c                     t         )z
        Abstract method to render this object to an output stream.

        :param stream:
            An output stream.
        :param container_ref:
            Local encryption key.
        :param handler:
            Security handler
        rJ   rM   r   r   rm   s       r?   write_to_streamzPdfObject.write_to_streamQ  s
      "!r>   NN)r6   r7   r8   r9   rm   r   r   rk   r   rN   r   r   r=   r>   r?   r    r      sV    )/3M8O,34?  04-1	" +,"  	*	"r>   c                   J    e Zd ZdZ	 	 d
ded   fdZed        Zd Zd Z	d	 Z
y)r"   zO
    PDF `null` object.

    All instances are treated as equal and falsy.
    Nr   r   c                 &    |j                  d       y )N   null)writer   s       r?   r   zNullObject.write_to_streamk  s     	Wr>   c                 X    | j                  d      }|dk7  rt        d      t               S )Nru   r   zCould not read Null object)r|   r   r"   )r   nulltxts     r?   r   zNullObject.read_from_streams  s+    ++a.g;<<|r>   c                 .    | |u xs t        |t              S rB   )rC   r"   rM   others     r?   __eq__zNullObject.__eq__z  s    u}=
5* ==r>   c                     t        d       S rB   )ra   rL   s    r?   __hash__zNullObject.__hash__}  s    Dzr>   c                      y)NFr=   rL   s    r?   __bool__zNullObject.__bool__  s    r>   r   )r6   r7   r8   r9   r   r   staticmethodr   r   r   r   r=   r>   r?   r"   r"   d  sG     04	 +,  >r>   r"   c                   V    e Zd ZdZd Z	 	 dded   fdZed        Zd Z	d	 Z
d
 Zd Zy)r#   zPDF boolean value.c                     || _         y rB   )value)rM   r   s     r?   rX   zBooleanObject.__init__  s	    
r>   Nr   r   c                 b    | j                   r|j                  d       y |j                  d       y )N   trues   false)r   r   r   s       r?   r   zBooleanObject.write_to_stream  s#     ::LL!LL"r>   c                     | j                  d      }|dk(  rt        d      S |dk(  r| j                  d      dk(  rt        d      S t        d      )	Nru   r   Ts   falsr      eFzCould not read Boolean object)r|   r#   r   )r   words     r?   r   zBooleanObject.read_from_stream  sO    {{1~7? &&W_{{1~%$U++:;;r>   c                 ,    t        | j                        S rB   )boolr   rL   s    r?   r   zBooleanObject.__bool__  s    DJJr>   c                 `    t        |t        t        f      xr t        |       t        |      k(  S rB   )rC   r#   r   r   s     r?   r   zBooleanObject.__eq__  s1    %-!67 
DJ$K
 =
 	
r>   c                 *    t        t        |             S rB   )strr   rL   s    r?   __str__zBooleanObject.__str__  s    4:r>   c                     t        |       S rB   )r   rL   s    r?   __repr__zBooleanObject.__repr__  s    4yr>   r   )r6   r7   r8   r9   rX   r   r   r   r   r   r   r   r   r=   r>   r?   r#   r#     sO     04		# +,	# < < 

r>   r#   c                   b    e Zd ZdZd Zej                  fdefdZ	 	 d
ded   fdZ	e
d	        Zy)r)   a  
    PDF array object. This class extends from Python's list class,
    and supports its interface.

    .. warning::
        Contrary to the case of dictionary objects, PyPDF2 does not
        transparently dereference array entries when accessed using
        :meth:`__getitem__`.
        For usability & consistency reasons, I decided to depart from that
        and dereference automatically.
        This makes the behaviour of :class:`.ArrayObject` consistent with
        :class:`.DictionaryObject`.

        That said, some vestiges of the old PyPDF2 behaviour may linger in
        the codebase. I'll fix those as I get to them.
    c                 @    | j                  |      j                         S rB   )raw_getrN   )rM   indexs     r?   __getitem__zArrayObject.__getitem__  s    ||E"--//r>   decryptc                 F    t         j                  | |      }t        ||      S )ay  
        .. versionchanged:: 0.14.0

            ``decrypt`` parameter is no longer boolean

        Get a value from an array without dereferencing.
        In other words, if the value corresponding to the given key is of type
        :class:`.IndirectObject`, the indirect reference will not be resolved.

        :param index:
            Key to look up in the dictionary.
        :param decrypt:
            What to do when retrieving encrypted objects; see
            :class:`.EncryptedObjAccess`. The default is
            :attr:`.EncryptedObjAccess.TRANSPARENT`.
        :return:
            A :class:`.PdfObject`.
        )listr   rG   )rM   r   r   vals       r?   r   zArrayObject.raw_get  s#    0 tU+W--r>   Nr   r   c                     |j                  d       | D ]'  }|j                  d       |j                  |||       ) |j                  d       y )N   [    )r   rm   s    ])r   r   )rM   r   r   rm   datas        r?   r   zArrayObject.write_to_stream  sS     	T 	DLL  } ! 	
 	Ur>   c                     t               }| j                  d      }|dk7  rt        d      	 t        |       }|dk(  r	 |S | j	                  dt
        j                         |j                  t        | |             O)Nr   r   zCould not read array   ]rp   )	r)   r|   r   r   r}   r~   r   appendr,   )r   rm   arrtmp	peekaheads        r?   r   zArrayObject.read_from_stream  st    mkk!n$;566+F3ID  
 KKBKK(JJ{6=9: r>   r   )r6   r7   r8   r9   r   r1   r;   r   r   r   r   r   r=   r>   r?   r)   r)     sW    "0 '9&D&D. $.< 04	 +,  r>   r)   c                       e Zd ZdZd Zd Zd Zedefd       Z	ed        Z
d Zd	 Zd
 Zd Z	 	 dded   fdZedd       Zy)r!   a  
    Thin wrapper around a :class:`.Reference`, implementing both the
    :class:`.Dereferenceable` and :class:`.PdfObject` interfaces.

    .. warning::
        For many purposes, this class is functionally interchangeable with
        :class:`.Reference`, with one important exception:
        :class:`.IndirectObject` instances pointing to the same reference
        but occurring at different locations in the file may have distinct
        `container_ref` values.
    c                 (    t        |||      | _        y rB   )r   	reference)rM   r^   r_   rd   s       r?   rX   zIndirectObject.__init__
  s    "5*c:r>   c                 z    | j                   j                         }t        |t              r|j                         S |S )zC
        :return: The PDF object this reference points to.
        )r   rN   rC   r!   )rM   rF   s     r?   rN   zIndirectObject.get_object  s3     nn'')
 $.c>#Bs~~KKr>   c                 6    | j                   j                         S rB   )r   rQ   rL   s    r?   rQ   zIndirectObject.get_pdf_handler  s    ~~--//r>   rS   c                 .    | j                   j                  S )z;
        :return: the object ID of this reference.
        )r   r^   rL   s    r?   r^   zIndirectObject.idnum  s    
 ~~###r>   c                 .    | j                   j                  S )zC
        :return: the generation number of this reference.
        )r   r_   rL   s    r?   r_   zIndirectObject.generation"  s    
 ~~(((r>   c                 <    d| j                   d| j                  dS )NzIndirectObject(z, ))r^   r_   rL   s    r?   r   zIndirectObject.__repr__)  s    +/::tGGr>   c                 D    t        | j                  | j                  f      S rB   )ra   r^   r_   rL   s    r?   r   zIndirectObject.__hash__/  s    TZZ122r>   c                 d    |d uxr+ t        |t              xr | j                  |j                  k(  S rB   )rC   r!   r   r   s     r?   r   zIndirectObject.__eq__2  s3     25.12%//1	
r>   c                 &    | j                  |       S rB   )r   r   s     r?   __ne__zIndirectObject.__ne__9  s    ;;u%%%r>   Nr   r   c                 X    |j                  d| j                  | j                  fz         y )Ns   %d %d R)r   r^   r_   r   s       r?   r   zIndirectObject.write_to_stream<  s"     	Z4::t"??@r>   c                 n   d}	 | j                  d      }|st        d      |j                         r|s2n||z  }8d}	 | j                  d      }|st        d      |j                         r|s2n||z  }8t        |       }|dk7  r't	        | j                               }t        d|z        	 t        |      t        |      }}|dkD  r|dk\  st        	 t        t        |      t        |      |j                               S # t        $ r( t	        | j                               }t        d|       w xY w)Nr>   r   Stream has ended unexpectedly   Rz2Error reading indirect object reference at byte %sr   z0Parse error on indirect object reference around )r|   r   isspacer   hextellr   rj   
ValueErrorr!   rQ   )	r   rm   	idnum_strr   generation_strrposr^   r_   s	            r?   r   zIndirectObject.read_from_streamD  sU   	++a.C$%DEE{{} I  ++a.C$%DEE{{}%c!N   '9fkkm$CDsJ 	 #IN0C:EAI*/   #2 	NC/1N1N1P
 	
  	fkkm$CB3%H 	s   /&D 1D4r   )rm   r   )r6   r7   r8   r9   rX   rN   rQ   propertyrj   r^   r_   r   r   r   r   r   r   r   r   r=   r>   r?   r!   r!     s    
;	L0 $s $ $ ) )H3
& 04	A +,A (
 (
r>   r!   c                   <    e Zd ZdZd	dZd Zd Z	 	 d
ded   fdZy)r$   z
    PDF Float object.

    Internally, these are treated as decimals (and therefore actually
    fixed-point objects, to be precise).
    c                 T    t         j                  j                  | t        |            S rB   )decimalDecimal__new__r   )clsr   s     r?   r   zFloatObject.__new__x  s    &&sCJ77r>   c                     | | j                         k(  r-t        | j                  t        j                  d                  S t        |       S )Nr   )to_integralr   quantizer   r   rL   s    r?   r   zFloatObject.__repr__{  s:    4##%%t}}W__Q%7899t9r>   c                     t        |       S )zD
        :return: a Python ``float`` value for this object.
        )floatrL   s    r?   
as_numericzFloatObject.as_numeric  s     T{r>   Nr   r   c                 V    |j                  t        |       j                  d             y Nr3   r   r`   encoder   s       r?   r   zFloatObject.write_to_stream       	T$Z&&w/0r>   )0r   )	r6   r7   r8   r9   r   r   r   r   r   r=   r>   r?   r$   r$   p  s3    8 04	1 +,1r>   r$   c                   l    e Zd ZdZ ej
                  d      ZdZd Zd Z		 	 dde
d   fd	Zed
        Zy)r%   zE
    PDF number object. This is the PDF type for integer values.
    s	   [^+-.0-9]   .c                 D    t        |      }t         j                  | |      S rB   )rj   r   )r   r   r   s      r?   r   zNumberObject.__new__  s    %j{{3$$r>   c                     t        |       S )zB
        :return: a Python ``int`` value for this object.
        )rj   rL   s    r?   r   zNumberObject.as_numeric  s     4yr>   Nr   r   c                 V    |j                  t        |       j                  d             y r   r   r   s       r?   r   zNumberObject.write_to_stream  r   r>   c                     t        | t        j                  d      }|j                  t        j                        dk7  rt        |j                  d            S t        |j                  d            S )NT)regex
ignore_eofrp   r3   )r   r%   NumberPatternr   ByteDotr$   decode)r   nums     r?   r   zNumberObject.read_from_stream  s\    ,,	
 88L(()R/szz'233

7 344r>   r   )r6   r7   r8   r9   recompiler   r   r   r   r   r   r   r   r=   r>   r?   r%   r%     sY     BJJ|,MG% 04	1 +,1 
5 
5r>   r%   string)r&   r'   c                    t        | t              rt        |       S t        | t        t        f      r/t        |       }	 t        |j                  |             }||_        |S t        d      # t        $ r t        |       cY S w xY w)z
    Encode a string as a :class:`.TextStringObject` if possible,
    or a :class:`.ByteStringObject` otherwise.

    :param string:
        A Python string.
    z'pdf_string should have str or bytes arg)rC   r   r'   bytes	bytearray_guess_enc_by_bomr   autodetected_encodingUnicodeDecodeErrorr&   	TypeError)r  guessedretvals      r?   r.   r.     s     &#''	FUI.	/#F+	,%gnnV&<=F+2F(M ABB " 	,#F++	,s   "A, ,BBs   0123456789abcdefABCDEFc                       j                  d       d fd}t        j                  dj                   |             rdndz         }t	        |      S )zp
    Read a hex string from a stream into a PDF string object.

    :param stream:
        An input stream.
    r   Fc               3   ~   K   	 t              } | dk(  ry | t        vrt        dt        |       z         |   8w)N   >z Unexpected token in hex string: )r   
HEX_DIGITSr   r`   )r   oddr   s    r?   read_tokensz0read_hex_string_from_stream.<locals>.read_tokens  sR     %f-Cd{J&$6cB  I'C s   :=r>      0)r|   binascii	unhexlifyjoinr.   )r   r  r   r  s   `  @r?   r   r     sP     KKN
C 34C8F fr>   c                 ,   | j                  d       d}t               }	 | j                  d      }|st        d      |dk(  r|dz  }n:|dk(  r|dz  }|dk(  r*	 |j                         S |dk(  r| j                  d      }|dv rn|dk(  rd	}n|d
k(  rd}n|dk(  rd}n|dk(  rd}n|dk(  rd}n|j                         rrt	        d      D ]J  }| j                  d      }|j                         r||z  }*| j                  dt        j                          n t        |d      }t        |f      }nS|dv r8| j                  d      }|dvr | j                  dt        j                         d}nt        dt        |      z         |j                  |       w)Nr   r      (   )r      \s   () /%<>[]#_&$\   nrz      rry      t   	   b      f   r5   rp      )bases   
r>   zUnexpected escaped string: )r|   r   r   isdigitranger}   r~   r   rj   r  r   r`   r   getvalue)r   parenstxtr   intokoctals          r?   _read_string_literal_bytesr.    s   
KKNF
)C
kk!n !@AA$;aKFD[aKF{Z <<>Y E\++a.C(( q A!;;q>D||~t B4 Ca(UHo kk!ng%KKBKK0 "#@49#LMM		#m r>   c                 *    t        t        |             S )z
    Read a PDF string literal from a stream. Attempt to decode it into a text
    string by autodetecting the encoding, or failing that, return it as a byte
    string instead.

    :param stream:
        An input stream.
    )r.   r.  )r   s    r?   r   r   5  s     0899r>   c                   <    e Zd ZdZ ed       Z	 	 	 dded   fdZy)r&   zPDF bytestring class.c                     | S rB   r=   rL   s    r?   <lambda>zByteStringObject.<lambda>G  s    4 r>   Nr   r   c                 ,   | }|J|H|j                         }|j                  |j                  |j                        }|j	                  ||      }|j                  d       |j                  t        j                  |             |j                  d       y )N   <r  )get_string_filterderive_object_keyr^   r_   encryptr   r  hexlify)rM   r   r   rm   bytearrcf	local_keys          r?   r   z ByteStringObject.write_to_streamL  s     =#<**,B,,##]%=%=I jjG4GTX%%g./Tr>   r   )r6   r7   r8   r9   r   original_bytesr   r   r=   r>   r?   r&   r&   D  s2    /0N 04	 +,r>   r&   c                       e Zd ZdZdZ	 ej                  dfZ	 ej                  dfZ		 ej                  dfZ	 dedefdZdeeef   defd	Zy)
r0   z)
    Encodings for PDF text strings.
    Nutf-16bezutf-8zutf-16ler  rS   c                     | t         j                  k(  rt        |      S | j                  \  }}||j	                  |      z   S )z
        Encode a string with BOM.

        :param string:
            The string to encode.
        :return:
            The encoded string.
        )r0   PDF_DOCencode_pdfdocencodingr   r   )rM   r  bomencs       r?   r   zTextStringEncoding.encode|  s?     %---(00zzHCs+++r>   c                     | t         j                  k(  rt        |      S | t         j                  k(  r|j	                  d      S |j	                  d      S )z
        Decode a string with BOM.

        :param string:
            The string to encode.
        :return:
            The encoded string.
        :raise UnicodeDecodeError:
            Raised if decoding fails.
        z	utf-8-sigzutf-16)r0   r@  decode_pdfdocencodingUTF8r   )rM   r  s     r?   r   zTextStringEncoding.decode  sK     %---(00',,,==--==**r>   )r6   r7   r8   r9   r@  codecsBOM_UTF16_BEUTF16BEBOM_UTF8rF  BOM_UTF16_LEUTF16LEr   r  r   r   r  r   r=   r>   r?   r0   r0   ^  s     G ""J/G OOW%D ""J/G,S ,U ,+U5)#34 + +r>   r0   encodedc                 <   | j                  t        j                        rt        j                  S | j                  t        j
                        rt        j                  S | j                  t        j                        rt        j                  S t        j                  S rB   )

startswithrG  rH  r0   rI  rK  rL  rJ  rF  r@  )rM  s    r?   r  r    sn    &--.!)))			F//	0!)))			FOO	,!&&& ")))r>   c                   f    e Zd ZU dZdZee   ed<   	 dZee   ed<   	 e	d        Z
	 	 d	ded   fdZy)
r'   z!
    PDF text string object.
    Nr	  force_output_encodingc                 f    | j                   r| j                   j                  |       S t        d      )z
        Retrieve the original bytes of the string as specified in the
        source file.

        This may be necessary if this string was misidentified as a text string.
        z#No information about original bytes)r	  r   r   rL   s    r?   r<  zTextStringObject.original_bytes  s0     %%--44T::@AAr>   r   r   c                    | j                   | j                   j                  |       }n	 t        |       }d }|/|-|j                  j                  }|dk(  rd n|j                         }|U|j                  |j                  |j                        }|j                  ||      }t        |      }|j                  |       y |j                  d       |D ]I  }	t!        |	g      }
|
j#                         s|	dk7  r|j                  d|	z         9|j                  |
       K |j                  d       y # t        $ r& t        j
                  | j                  d      z   }Y )w xY w)Nr>  	/Identityr      s   \%03or  )rQ  r   rA  UnicodeEncodeErrorrG  rH  crypt_filter_configstring_filter_namer5  r6  r^   r_   r7  r&   r   r   r  isalnum)rM   r   r   rm   rM  r:  cf_namer;  rF   cc_s              r?   r   z TextStringObject.write_to_stream  sM    %%10077=G
H/5 =#<11DDG K/W5N5N5PB>,,##]%=%=I jjG4G"7+C'LL %A3Zzz|T	LLQ/LL$% LL5 & H !--J0GGHs   D0 0+EEr   )r6   r7   r8   r9   r	  r   r0   rk   rQ  r   r<  r   r=   r>   r?   r'   r'     sj     ;?8$67> ;?8$67>
 B B* 04	) +,)r>   r'   c                     d| cxk  r	dk  r| dz
  S  d| cxk  r	dk  r| dz
  S  d| cxk  r	dk  r| dz
  S  t        d	      t        d	      )
N0   9   A   F   7   a   f   W   z6Numeric escape in PDF name must use hexadecimal digits)r   )
ascii_chars    r?   _as_hex_digitrg    sz    z!T!D   "		#t	#D   
$		#t	#D   
$ D
 	
lD
 	
r>   
name_bytesr(   c                 ^   t               }|j                  d       t        |       }	 	 t        |      }|dk(  r2	 t        |      }t        |      }t        |      dz  t        |      z   }n)d|cxk  rdk  rn nt        |      st        d|dd	      |j                  t        |f             # t        $ r t        dt        |              w xY w# t        $ r Y nw xY w|j                         } d
}d}|D ]$  }	 | j                  |      } n# t        $ r Y "w xY w |J t        |      S )zu
    Decode the bytes that make up a name object (minus the initial /), expanding
    all escapes along the way.
       /#   z!Unterminated escape in PDF name /   !   ~   zByte (0x02xz) must be escaped in a PDF name)utf8latin1N)r   r   iternextStopIterationr   r`   rg  r   r  r(  r   r   r(   )	rh  r   	name_itercur_bytedigit1digit2encodings_to_tryname_strrC  s	            r?   _decode_namer{  	  sj   
 YF
LLZ IIH4!)_F!)_F )025f8MMh.$.7K8 #xn,KL  LL{+,'  % &;D<L;MN   "J * H 	!((-H 			 hs;   C B0 A C 0!CC 	C C =D	DDc                   8    e Zd ZdZ	 	 dded   fdZed        Zy)r(   z
    PDF name object. These are valid Python strings, but names and strings
    are treated differently in the PDF specification, so proper care is
    required.
    Nr   r   c                    t        | j                  d            }t        |      dk(  st        dt	        |        d      |j                  d       |D ]m  }|dk(  sd|cxk  rdk  rn nt        |      s0|j                  d	j                  |      j                  d
             Qt        |f      }|j                  |       o y )Nrp  /   z Could not serialise name object z, must start with /rj  rk  rm  rn  z#{:X}r3   )	rr  r   rs  r   r`   r   r   formatr  )rM   r   r   rm   	byte_iterrv  as_bytess          r?   r   zNameObject.write_to_streamF  s     V,-	I$&24:, ?$ %  	T! 
	'HD 0D0+H5W^^H5<<WEF !(-X&
	'r>   c                 p    | j                  d      }|dk7  rt        d      t        |       }t        |      S )Nr   rj  zName object should start with /)r|   r   r   r{  )r   
name_startrh  s      r?   r   zNameObject.read_from_stream_  s8    [[^
@AA)&1
J''r>   r   )r6   r7   r8   r9   r   r   r   r   r=   r>   r?   r(   r(   ?  s8     04	' +,'2 ( (r>   c                 r    t        | t              s&t        | t              rt        |       S t        d      | S )Nzkey must be a name object)rC   r(   r   r   )keys    r?   _normalise_keyr  h  s1    c:&c3c?"899Jr>   c                        e Zd ZdZd fd	Zej                  fdeee	f   defdZ
d ZddZd	 Zd
dddeegef   fdZddefdZ	 	 dded   fdZe	 ddddefd       Z xZS )r*   z
    A PDF dictionary object.

    Keys in a PDF dictionary are PDF names, and values are PDF objects.

    When accessing a key using the standard :meth:`__getitem__` syntax,
    :class:`.IndirectObject` references will be resolved.
    Nc           	          |;t         |   |j                         D ci c]  \  }}t        |      | c}}       y t         |           y c c}}w rB   )superrX   itemsr  )rM   	dict_datakv	__class__s       r?   rX   zDictionaryObject.__init__{  sL     G2;//2CD$!Q"A%D G Es   A
r  r   c                 F    t         j                  | |      }t        ||      S )a{  
        .. versionchanged:: 0.14.0

            ``decrypt`` parameter is no longer boolean

        Get a value from a dictionary without dereferencing.
        In other words, if the value corresponding to the given key is of type
        :class:`.IndirectObject`, the indirect reference will not be resolved.

        :param key:
            Key to look up in the dictionary.
        :param decrypt:
            What to do when retrieving encrypted objects; see
            :class:`.EncryptedObjAccess`. The default is
            :attr:`.EncryptedObjAccess.TRANSPARENT`.
        :return:
            A :class:`.PdfObject`.
        )dictr   rG   )rM   r  r   r   s       r?   r   zDictionaryObject.raw_get  s#    . tS)W--r>   c                     t        |      }t        |t              st        d      | j                  | j                  |_        t
        j                  | ||      S Nzvalue must be PdfObject)r  rC   r    r   rm   r  __setitem__rM   r  r   s      r?   r  zDictionaryObject.__setitem__  sQ    S!%+677)"&"4"4Ec511r>   c                     t        |      }t        |t              st        d      | j                  | j                  |_        t
        j                  | ||      S r  )r  rC   r    r   rm   r  
setdefaultr  s      r?   r  zDictionaryObject.setdefault  sO    S!%+677)"&"4"4EtS%00r>   c                 4   t         j                  | |      }|dk(  rQt        |t              rAddlm} |j                         }t        ||      sJ |j                  |j                  d      S |j                         }t        |t              rt        |      |S )Nz	/Metadatar   rf   Trs   )r  r   rC   r!   rh   rg   rQ   rN   r   r"   KeyError)rM   r  raw_objrg   r   	deref_objs         r?   r   zDictionaryObject.__getitem__  s    ""4-+*Wn"E>--/Ggz222%%!!d &    **,I)Z0sm#  r>   F)rawrc   functionc                f    	 |r| j                  |      n| |   } ||      S # t        $ r |cY S w xY wrB   r   r  )rM   r  r  r  rc   r   s         r?   get_and_applyzDictionaryObject.get_and_apply  s?    	),DLL%$s)E   	N	s   " 00rS   c                 H    d }| j                  ||d      }||st        |S )Nc                 F    t        | t              r| j                  S t        rB   )rC   r!   r   r   )rF   s    r?   as_refz7DictionaryObject.get_value_as_reference.<locals>.as_ref  s    #~.}}$((r>   T)r  )r  r  )rM   r  optionalr  r   s        r?   get_value_as_referencez'DictionaryObject.get_value_as_reference  s1    	)
 ""3D"9=Nr>   r   r   c                    |j                  d       t        | j                               D ]M  \  }}|j                  |||       |j                  d       |j                  |||       |j                  d       O |j                  d       y )Ns   <<
r   rz   s   >>)r   r   r  r   )rM   r   r   rm   r  r   s         r?   r   z DictionaryObject.write_to_stream  sx     	Wtzz|, 	 JC?LL!!&'=ALL		 
 	Ur>   rm   r   rn   c                    | j                  d      }|dk7  r%t        dt        | j                               z        i }|j	                         }	 t        |       }|dk(  r| j                  d       n| j                  dt        j                         	 t        j                  |       }t        |        | j                  dt        j                         t        | |      }	||vr|	||<   nKd	t        | j                               d
|}
|j                  rt        |
      t        j!                  |
       | j                         }t        | d      }d }|dk(  r	| j                  d      dk(  rt#        | d       |t%        d         }t'        |t(              r2| j                         }|j+                  |      }| j                  |       | j                  |      }t        |       }| j                  d      }||z   dk7  rt| j                         }| j                  dt        j                         | j                  d      }|dk(  r|d d }n(t        dt        |      z        | j                  |       |t,        }|r		 ddlm} |} |||      S t5        |      S # t        $ r+}t        dt        | j                               z        |d }~ww xY w# t2        $ r Y Ww xY w)Nr5   rr   z?Dictionary read error at byte 0x%s: stream must begin with '<<'Tr  r   rp   z=Failed to read dictionary key at byte 0x%s; expected PDF namez+Multiple definitions in dictionary at byte z	 for key )	allow_eof   srv   s   tream)stop_after_eol/Lengthr$  s	   endstreami	   z:Unable to find 'endstream' marker after stream at byte %s.r   )MetadataStream)encoded_data)r|   r   r   r   rQ   r   r}   r~   r   r(   r   	Exceptionr,   strictr   loggerwarningr   r-   rC   r!   rN   r+   "pyhanko.pdf_utils.metadata.xmp_xmlr  ImportErrorr*   )r   rm   rn   r   r   r   r   r  exr   errr   sstream_datalengthtendstreamorig_endstream_posendstm_clsr  s                         r?   r   z!DictionaryObject.read_from_stream  s    kk!n%<.03FKKM0BC  //1%f-Cd{AKKBKK( 11&9  'KKBKK(6E$!S	 
 (+6;;='93@  >>,S11NN3'5 8 kkm$79Q83 !=(9-.F&.1KKM ++F3A ++f-K#F+A{{1~HH- &,[[]"C-kk!n,&"-cr"2K&-/23E/FG 
 KK" #G! -G 4k::#D))S  "S&++-() J # s*   J >K 	K$&K

K	KKrB   Fr   )r6   r7   r8   r9   rX   r1   r;   r   r(   r   r   r  r  r   r
   r    r	   r  r   r  r   r   r   r   r   __classcell__r  s   @r?   r*   r*   q  s     '9&D&D.:s?#. $.421!,  I;+,	Y 	 04	 +,  $)^*(^* !^* ^*r>   r*   c            
       D    e Zd ZdZ	 	 	 	 ddee   dee   dee   ded   f fdZd	ed
efdZ	e
defd       Z ed      ddfded   fdZdeeeee   f      fdZd Zd Ze
defd       Ze
defd       Z	 ddee   fdZd Ze
d        Z	 	 dded   f fdZ xZS )r+   a  
    PDF stream object.

    Essentially, a PDF stream is a dictionary object with a binary blob of
    data attached. This data can be encoded by various filters (not all of which
    are currently supported, see :mod:`.filters`).

    A stream object can be initialised with encoded or decoded data.
    The former is used by :class:`.reader.PdfFileReader` to provide on-demand
    decoding, with :class:`.writer.BasePdfFileWriter` and its subclasses working
    the other way around.

    .. note::
        The :class:`.StreamObject` class manages some of its dictionary
        keys by itself. This is partly the case for the various ``/Filter``
        and ``/DecodeParms`` entries, but also for the ``/Length`` entry.
        The latter will be overwritten as necessary.

    :param dict_data:
        The dictionary data for this stream object.
    :param stream_data:
        The (unencoded) stream data.
    :param encoded_data:
        The encoded stream data.

        .. warning::
            Ordinarily, a stream can be initialised either from decoded and from
            encoded data.

            If both `stream_data` and `encoded_data` are provided, the caller
            is responsible for making sure that both are compatible given the
            currently relevant filter configuration.
    :param handler:
        A reference to the currently active
        :class:`.pyhanko.pdf_utils.crypt.SecurityHandler`.
        This is only necessary if the stream requires crypt filters.
    Nr  r  r  r   r   c                 N    t         |   |       || _        || _        || _        y rB   )r  rX   _data_encoded_data_handler)rM   r  r  r  r   r  s        r?   rX   zStreamObject.__init__n  s(     	# 
)r>   r   decrypted_entriesc                 L   ||| _         | j                  r| j                  }no| j                  r|j	                         }n|j                         }|j                  |j                  |j                        }|j                  || j                        }| j                  |||      S )aJ  
        Internal method to handle decrypting streams that are encrypted
        with the document's default encryption handler for streams and/or
        embedded files (i.e. not with any custom crypt filters).

        This routine is called deep in the object fetching stack, and you should
        never invoke it yourself. It's defined as a method in
        :class:`.StreamObject` because it needs to be able to preserve the
        type (subclass) of the stream object on which it is called, in order
        to properly feed into the logic surrounding metadata streams.
        )r  r   )r  _has_crypt_filterr  is_embedded_file_streamget_embedded_file_filterget_stream_filterr6  r^   r_   r   r  )rM   r   r   r  decrypted_datar:  r;  s          r?    _implicit_decrypt_stream_contentz-StreamObject._implicit_decrypt_stream_contentz  s     #DM!! "..N++557..0,,SYYGIZZ	43D3DEN~~NG  
 	
r>   rS   c                 4    dd | j                         D        v S )N/Cryptc              3   &   K   | ]	  \  }}|  y wrB   r=   ).0name_s      r?   	<genexpr>z1StreamObject._has_crypt_filter.<locals>.<genexpr>  s     @WT1D@s   )_filtersrL   s    r?   r  zStreamObject._has_crypt_filter  s    @@@@r>   rT  c                    ||| _         | j                   t        d      || j                   j                  vrt        d| d      |xs
 t               }t	        d      |d<   ||d<   | j                  t	        d      |d	       y )
Nz#There is no security handler aroundzThe crypt filter z& is not known to the security handler.z/CryptFilterDecodeParms/Type/Namer  T)paramsallow_duplicates)r  r   rW  r*   r-   apply_filter)rM   r  r  r   s       r?   add_crypt_filterzStreamObject.add_crypt_filter  s     #DM==  !FGGt}}888 #D6)OP  -+-"#<=wwXv 	 	
r>   c              #     K   	 | t        d         }t        |t              r|f}nt        |t              st        d      	 | t        d         }t        |t              r|g}t        |t              r-t        |      t        |      z
  }|dkD  r|t               g|z  z  }t        |d |D              E d {    y # t        $ r Y y w xY w# t        $ r t               gt        |      z  }Y Mw xY w7 :w)N/Filterz5/Filter should be a name object or an array of names./DecodeParmsr   c              3   <   K   | ]  }|j                           y wrB   )rN   )r  	param_sets     r?   r  z(StreamObject._filters.<locals>.<genexpr>  s     OI--/Os   )r-   r  rC   r(   r)   r   r*   r   r   r"   zip)rM   
filter_arrdecode_paramslendiffs       r?   r  zStreamObject._filters  s     	hy12J j*-$JJ4 G 	= .!9:M-)9:!.-.j/C,>>Q;!jl^g%==M OO
 	
 	
5  		*  	='\NS_<M	=
	
sX   C3B< /C3AC  C36C17C3<	CC3CC3 C.+C3-C..C3c              #   b  K   ddl m} | j                         D ]w  \  }}	 |t        |t              ri }|dk(  rA|j                  dd      dk(  r6| j                  }|t        d      |j                  |      }n|j                  |      }||f y y # t        $ r t        d|z        w xY ww)Nr   )filtersr  r  rT  zFPDF streams require a security handler to use explicit /Crypt filters.z%Filters of type %s are not supported.) r  r  rC   r"   getr  r   CryptFilterDecoderget_generic_decoderr  rK   )rM   r  filter_typer  shdecoders         r?   _stream_decoderszStreamObject._stream_decoders  s     #'==? 	K>Z
%CF(* zz';7;F  Bz,7  &88<G%99+FGvo%)	*  );kI s)   B/.BB/ABB/B,,B/c                     | j                   x| _        | _        | j                  t	        d      d       | j                  t	        d      d       y)zG
        Ensure the stream is decoded, and remove any filters.
        r  Nr  )r   r  r  popr-   rL   s    r?   strip_filterszStreamObject.strip_filters  s=    
 +/))3
T')$d+.)40r>   c                 "   | j                   j| j                  }|t        d      | j                         D ]  \  }}|j	                  ||      } t        |t              r|j                         }|| _         | j                   J | j                   S )z
        Return the decoded stream data as bytes.
        If the stream hasn't been decoded yet, it will be decoded on-the-fly.

        :raises .misc.PdfStreamError:
            If the stream could not be decoded.
        No data available.)r  r  r   r  r   rC   
memoryviewtobytes)rM   r   
filter_clsr  s       r?   r   zStreamObject.data  s     ::%%D|$%9::-1-B-B-D >)
M!((}=>$
+||~DJzz%%%zzr>   c                 
   | j                   ^| j                  }|t        d      t        | j	                               }t        |      D ]  \  }}|j                  ||      } || _         | j                   J | j                   S )z
        Return the encoded stream data as bytes.
        If the stream hasn't been encoded yet, it will be encoded on-the-fly.

        :raises .misc.PdfStreamError:
            If the stream could not be encoded.
        r  )r  r  r   tupler  reversedr   )rM   r   decodersr  r  s        r?   r  zStreamObject.encoded_data  s     %::D|$%9::T2245H-5h-? >)
M!((}=>!%D!!---!!!r>   r  c                 2   | j                   }|| j                  | j                  }t        | j	                               }t        |t              st        |      }t        t              st              |s|| t        d      <   r~| t        d      <   not        | \  }|s||v r|du rt        d| d      yt        |f|z         | t        d      <   st              r"fd}t         |             | t        d      <   d| _        || _         y)a  
        Apply a new filter to this stream. This filter will be prepended
        to any existing filters.
        This means that is is placed *last* in the encoding order, but *first*
        in the decoding order.

        *Note:* Calling this method on an encoded stream will first cause the
        stream to be decoded using the filters already present.
        The cached value for the encoded stream data will be cleared.

        :param filter_name:
            Name of the filter
            (see :const:`~pyhanko.pdf_utils.filters.DECODERS`)
        :param params:
            Parameters to the filter (will be written to ``/DecodeParms`` if
            not ``None``)
        :param allow_duplicates:
            If ``None``, silently ignore duplicate filters.
            If ``False``, raise ValueError when attempting to add a duplicate
            filter. If ``True`` (default), duplicate filters are allowed.
        Nr  r  FzFilter z) has already been applied to this stream.c               3   \   K   xs
 t                D ]  } | xs
 t                 y wrB   )r"   )r  
param_setsr  s    r?   _paramsz*StreamObject.apply_filter.<locals>._paramsj  s0      0JL0%/ 8	'7:<78s   ),)r  r  r   r   r  rC   r(   r-   r*   r  r   r)   any)	rM   filter_namer  r  r   cur_filtersfilter_namesr   r  s	     `     @r?   r  zStreamObject.apply_filter+  s(   4 zz<D..:99D 4==?++z2";/Kj9I&J%f-F(3D)$%17Xn-. (+K'8$L*#|(C#u,'!+ /' (   )4-)D)$% Z8
 2=WY1GXn-.!
r>   c                 <    | j                  t        d      d       y)z
        Convenience method to add a ``/FlateDecode`` filter with default
        settings, if one is not already present.

        *Note:* compression is not actually applied until the stream is written.
        z/FlateDecodeN)r  )r  r-   rL   s    r?   compresszStreamObject.compresss  s     	(>2TJr>   c                 J    	 | j                  d      dk(  S # t        $ r Y yw xY w)Nr  z/EmbeddedFileFr  rL   s    r?   r  z$StreamObject.is_embedded_file_stream|  s-    	<<(O;; 		s    	""c                    | j                   }|V|T| j                  sH|j                         }|j                  |j                  |j
                        }|j                  ||      }t        t        |            | t        d      <   t        | -  |||       | d= |j                  d       |j                  |       |j                  d       y )Nr  s   
stream
s
   
endstream)r  r  r  r6  r^   r_   r7  r%   r   r(   r  r   r   )rM   r   r   rm   r   r:  r;  r  s          r?   r   zStreamObject.write_to_stream  s       )****,B,,##]%=%=I ::i.D&23t9&=Z	"#?O]#T^$r>   )NNNN)NTr   )r6   r7   r8   r9   r   r  r  rX   r   r  r   r   r  r(   r  r   r   r   r  r  r  r   r  r  r  r  r   r  r  s   @r?   r+   r+   G  sd   $P %)'+(,/3
 D>
  e_
  uo	
 
 +,
 $
%$
:>$
L A4 A A
 $/3	
 +,	
.
(5htn)<#=> 
B:1 e  ( "e " "( LPF:B4.FPK   04	% +,% %r>   r+   c                 .      fd}t         |             S )Nc            	   3   l   K   D ]  } 	 t         |      y # t        $ r t        d| ddd      w xY ww)Npdfdocencodingrp   #does not exist in translation table)_pdfDocEncoding_revr  rV  )r[  unicode_strings    r?   _buildz%encode_pdfdocencoding.<locals>._build  sR      
	A	)!,,
	  ($9 s   4414)r  )r  r  s   ` r?   rA  rA    s     ?r>   c                 :      fd}dj                   |             S )Nc               3   r   K   D ]-  } t         |    }|dk(  rt        dt        | f      ddd      | / y w)N r  rp   r  )_pdfDocEncodingr
  r  )br[  
byte_arrays     r?   r  z%decode_pdfdocencoding.<locals>._build  sP      
	A"AH}($1$K9  G
	s   47r  )r  )r  r  s   ` r?   rE  rE    s     7768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  u   ˘u   ˇu   ˆu   ˙u   ˝u   ˛u   ˚u   ˜ !"#$%&'(r   *+,-./r   123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^r  `ar  r[  dr  fghr+  jr  lmnopqr   r  r  ur  wxyz{|}~r  u   •u   †u   ‡u   …u   —u   –u   ƒu   ⁄u   ‹u   ›u   −u   ‰u   „u   “u   ”u   ‘u   ’u   ‚u   ™u   ﬁu   ﬂu   Łu   Œu   Šu   Ÿu   Žu   ıu   łu   œu   šu   žr  u   €   ¡   ¢   £   ¤   ¥   ¦   §   ¨   ©   ª   «   ¬r     ®   ¯   °   ±   ²   ³   ´   µ   ¶   ·   ¸   ¹   º   »   ¼   ½   ¾   ¿   À   Á   Â   Ã   Ä   Å   Æ   Ç   È   É   Ê   Ë   Ì   Í   Î   Ï   Ð   Ñ   Ò   Ó   Ô   Õ   Ö   ×   Ø   Ù   Ú   Û   Ü   Ý   Þ   ß   à   á   â   ã   ä   å   æ   ç   è   é   ê   ë   ì   í   î   ï   ð   ñ   ò   ó   ô   õ   ö   ÷   ø   ù   ú   û   ü   ý   þ   ÿ   c                 >    t        | t              rt        | |      S | S rB   )rC   	PROXYABLEr2   )encrypted_objr   s     r?   proxy_encrypted_objr    s    -+#M7;;r>   c                   t    e Zd ZU dZeed<   	 defdZedefd       Z	 	 dde	d   fd	Z
d
 Zed        Zd Zy)r2   a  
    Internal proxy class that allows transparent on-demand encryption
    of objects.

    .. warning::
        Most public-facing APIs won't leave you to deal with these *directly*
        (that's half the reason this class exists in the first place), and
        the API of this class is considered internal.

        However, for reasons related to the historical PyPDF2 codebase from
        which pyHanko's object handling code ultimately derives, there are
        some Python builtins that might cause these wrapper objects to
        inadvertently "leak". Please `tell us about such cases
        <https://github.com/MatthiasValvekens/pyHanko/discussions>`_ so we can
        make those types of access more convenient and robust.

    .. danger::
        The ``__eq__`` implementation on this class is not safe for general use,
        due to the fact that certain structures in PDF are exempt from
        encryption. Only compare proxy objects with ``==`` in areas of the
        document where these exemptions don't apply.

    :param raw_object:
        A raw object, typically as-parsed from a PDF file.
    :param handler:
        The security handler governing this object.
    rE   c                 .    || _         d | _        || _        y rB   )rE   
_decryptedr   )rM   rE   r   s      r?   rX   zDecryptedObjectProxy.__init__  s    $/3r>   rS   c           	      ^   | j                   | j                   S ddlm} | j                  }| j                  |j
                  }t        |t              st        d| d      t        |t              st        |t              r\j                         }|j                  |j                  |j                        }t        |j!                  ||j"                              }nt        |t$              r]|j'                         D ci c]  \  }}|t)        |       }	}}t        |t*              r|j-                  ||	      }nOt%        |	      }nCt        |t.              rt1        fd|      }
t/        |
      }nt3        dt5        |       d      |j
                  |_        || _         |S c c}}w )aG  
        The decrypted PDF object exposed as a property.

        If this object is a container object, its constituent parts will be
        wrapped in :class:`.DecryptedObjectProxy` as well, in order to defer
        further decryption until the values are requested through a getter
        method on the container.
        r   r   zPProxyable objects must have a container ref pointing to a numbered object, not 'z'.c                     t        |       S rB   )r  )r  r   s    r?   r2  z0DecryptedObjectProxy.decrypted.<locals>.<lambda>&  s    *=a*I r>   zObject of type z is not proxyable.)r  cryptr   rE   r   rm   rC   r   r   r&   r'   r5  r6  r^   r_   r.   r   r<  r*   r  r  r+   r  r)   mapr  type)rM   r   rF   rm   r:  r;  rD   dictkeyr   r  decrypted_mapr   s              @r?   rD   zDecryptedObjectProxy.decrypted  s    ??&??"* oo#'<<))-3))6r;  c+,
!1
 **,B,,##]%=%=I #2::i9K9K#LMI-. '*iik!"GU ,UG<<! ! #|,@@],=	 -->?	[) I3OM#M2Iod3i[8JKLL"%"3"3	##!s   F)Nr   r   c                 >    | j                   j                  |||       y rB   )rD   r   r   s       r?   r   z$DecryptedObjectProxy.write_to_stream.  s     	&&vwFr>   c                 6    | j                   j                         S rB   )rD   rN   rL   s    r?   rN   zDecryptedObjectProxy.get_object:  s    ~~((**r>   c                 .    | j                   j                  S rB   )rE   rm   rL   s    r?   rm   z"DecryptedObjectProxy.container_ref=  s    ,,,r>   c                 X    t        |t              xr |j                  | j                  k(  S rB   )rC   r2   rD   r   s     r?   r   zDecryptedObjectProxy.__eq__A  s)     u23 24>>1	
r>   r   )r6   r7   r8   r9   r    rk   rX   r   rD   r   r   rN   rm   r   r=   r>   r?   r2   r2     sy    8 9 
 39 3 3p 04	
G +,
G+ - -
r>   r2   zD:%Y%m%d%H%M%Sdtc                     | j                  t              }d}| j                         }|G|j                         }|sd}n2d}|dk  rd}t	        |      }t        |d      \  }}|dz  }|d||fz  z   }t        ||z         S )	a  
    Convert a datetime object into a PDF string.
    This function supports both timezone-aware and naive datetime objects.

    :param dt:
        The datetime object to convert.
    :return:
        A :class:`TextStringObject` representing the datetime passed in.
    r  rN  r   r   r"  i  <   z
%02d'%02d')strftimeASN_DT_FORMAT	utcoffsettotal_secondsabsdivmodr'   )r  base_dtutc_offset_string
utc_offset
tz_secondssignhrsminss           r?   r/   r/   O  s     kk-(GJ--/
 #DA~ _
$Z6OC#D
 !%T{(B CG&7788r>   z
^D:(\d{4})z^(?:D:)?(\d{4})z^(\d\d)z(\d\d)(?:'(\d\d))?'?date_strr  c           
      J   |rt         nt        j                  |       }|st        |  d      t	        |j                  d            }| |j                  d      d  }g d}t        d      D ]=  }t        j                  |      }|s n$t	        |j                  d            ||<   |dd  }? |\  }}}	}
}d }|r|d   }|dk(  rt        |      dk(  rt        d      }n|dv r{|dd  }t        j                  |      }|st        d	|  d
|       t	        |j                  d            }t	        |j                  d      xs d      }t        ||      }|dk(  r| }nt        d|  d      t        |      }	 t        ||||	|
|d|      S # t        $ r}t        d|      d }~ww xY w)Nz% does not appear to be a date string.r   r   )r   r   r   r   r   rv   r5   rN  )r   r"  z#Improper timezone specification in z: )hoursminutesr"  z Improper trailing characters in r#  )yearmonthdayhourminutesecondmicrosecondtzinfozImproper date value)MIN_DATE_REGEXMIN_DATE_REGEX_LENIENTr   r   rj   groupr  r'  TWO_DIGIT_STARTr   r   
UTC_OFFSET	fullmatchr   r   r   )r  r  r[  r  date_remaininglower_orderixr  r  r  r  r  tz_infosgn	tz_offsettz_spectz_matchtz_hours
tz_minutesr  s                       r?   parse_pdf_dater  y  s   !'=DDXNAhZ'LMNNqwwqz?D aeeAhj)N!KAh ,!!.1aggaj/B'+, (3$E3ff GQ#:#n-2!!IJ$QR(G!++G4H"9(2gYO  8>>!,-HX^^A.3!4J!*EIcz&J	!A(1MNN9%5	
 		
  50!445s   5F 	F"FF"r  )T)er9   r  rG  r   enumloggingr~   r  typingdataclassesr   r   r   r   r   ior   r	   r
   r   r   r   r   miscr   r   r   r   r   r   r   r   r   r   r   TYPE_CHECKING	crypt.apir   __all__r   r   r  r   r   	getLoggerr6   r  Enumr1   rG   r   r   r   r   r,   r    r"   r#   r   r)   r!   r   r$   rj   r%   r   r  r  r.   r  r   r.  r   r&   r0   r  r'   rg  r{  r(   r  r  r*   r+   rA  rE  r  r   	enumerater  r-   r  r  r2   r  r/   r  r  r  r  r  )r  chars   00r?   <module>r     st        	 	  ( 2 2  B B    
*2 2::;BB7KL 			8	$ >1 " "2 . $/ / /f JOJ,JBFJJZB" B"J @'I 'TL$	 L^p
Y p
f1'//9 1@&53	 &5XC#ui'(C
12C0 '

12@;% ;|:
12:ui 4=+ =+@*uUI%56 *;M *LsI L^

3 U 3 | 3 l&(i &(RS*tY S*lS%# S%l
""AF ?s" ""09/0JKHBtRxK /1A;O	x
9 x
v ! 9  9.  9H M*#$67 "**Z(RZZ/0
65S 65$ 65( 65k Ls   J