
    Wwg              
          d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
mZmZmZmZmZ ddlmZmZ ddlmZmZmZmZmZmZ dd	lmZ dd
l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'm(Z(m)Z)  ejT                  e+      Z,g dZ- ej\                  d      Z/ ej\                  d      Z0deee1e1f      fdZ2d Z3de1fdZ4de	dee1e1f   fdZ5de	de#de6dee(e'f   fdZ7 G d de#      Z8 G d d      Z9 G d d e#      Z:y)!a  
Utility to read PDF files.
Contains code from the PyPDF2 project; see :ref:`here <pypdf2-license>`
for the original license.

The implementation was tweaked with the express purpose of facilitating
historical inspection and auditing of PDF files with multiple revisions
through incremental updates.
This comes at a cost, and future iterations of this module may offer more
flexibility in terms of the level of detail with which file size is scrutinised.
    N)defaultdict)BytesIO)BinaryIODict	GeneratorOptionalSetTupleUnion   )genericmisc)
AuthResult
AuthStatusEnvelopeKeyDecrypterPubKeySecurityHandlerSecurityHandlerStandardSecurityHandler)PdfMacStatus)view_from_info_dict)DocumentMetadata)PdfReadErrorPdfStrictReadError)
PdfHandler)ObjStreamRefTrailerDictionaryXRefBuilder	XRefCacheread_object_header)PdfFileReaderHistoricalResolverparse_catalog_version
RawPdfPathprocess_data_at_eofs   %PDF-(\d).(\d)z
/(\d).(\d)returnc                     t         j                  t        |             }|8t        |j	                  d            }t        |j	                  d            }||fS y )Nr      )catalog_version_regexmatchstrintgroup)version_strmmajorminors       O/var/www/horilla/myenv/lib/python3.12/site-packages/pyhanko/pdf_utils/reader.pyr"   r"   8   sK    ##C$45A}AGGAJAGGAJe|    c                 R      fd}t        t        t         |                         S )Nc               3   R  K   	 j                         dk(  rt        d      j                  d      } j                         dk  s| st        d      j                  dt        j
                         | dk(  s| d	k(  rnt        |        d
}| dk(  s| d	k(  rij                  d      } | dk(  s| d	k(  r"j                  dt        j
                         d}j                  dt        j
                         | dk(  rc| d	k(  rij                  |rdndt        j
                         y w)NTr   z!Could not read malformed PDF filer   r'   zEOL marker not found   
   F)tellr   readseekosSEEK_CURord)xcrlfstreams     r1   _buildz"read_next_end_line.<locals>._buildH   s     {{}!"#FGGAA{{}q "#9::KKBKK(EzQ%Za&L  5jAJAAEzQ%ZB,KKBKK( 5jAJ 	A1bkk2s   C8D'<D'%D')bytesreversedtuple)rA   rB   s   ` r1   read_next_end_linerF   G   s     3, %/*++r2   c                    | j                         dz
  dz   }d}|dd dk7  r2| j                         |k  rt        d      t        |       }|dd dk7  r2t        |       }	 t        |      }t        |       }|dd d	k7  rt        d
      |S # t        $ rQ |j                  d	      st        d
      t        |dd j                               }t        j                  d       Y |S w xY w)aB  
    Auxiliary function that reads backwards from the current position
    in a stream to find the EOF marker and startxref value

    This is internal API.

    :param stream:
        A stream to read from
    :return:
        The value of the startxref pointer, if found.
        Otherwise a PdfReadError is raised.
    i   r   r2   N   s   %%EOFzEOF marker not found	   s	   startxrefzstartxref not foundz startxref on same line as offset)	r9   r   rF   r+   
ValueError
startswithstriploggerwarning)rA   last_1kline	startxrefs       r1   r$   r$   a   s     kkmd"Q&GD
r(h
;;=7"566!&) r(h
 f%D6I	 "&)8|#455  ;|,455QR()	9: ;s   B
 
AC$#C$rA   c                    | j                  d       d }t        j                  | d      }t        j	                  |      }|8t        |j                  d            }t        |j                  d            }||f}|t        d      |S )Nr      )maxcharsr   r'   zIllegal PDF header)r;   r   read_until_whitespaceheader_regexr)   r+   r,   r   )rA   input_versionheaderr.   r/   r0   s         r1   _read_header_versionrY      s|    
KKNM''<F6"A}AGGAJAGGAJ/00r2   handler_refstrictc                     | j                  dt        j                         t        |       }t	        || ||      }|j                         }t        ||      }||fS )Nr8   )handlerrA   r[   last_startxref)r;   r<   SEEK_ENDr$   r   
read_xrefsr   )rA   rZ   r[   r^   xref_builderxref_sections
xref_caches          r1   _read_xrefs_and_trailerrd      s_     KKBKK (0N %	L !++-M;6J|##r2   c            	       &   e Zd ZU dZdZdZeed<   d(defdZ	e
d        Zdee   fd	Ze
defd
       Ze
d        Zd Ze
deej&                     fd       Ze
dej&                  fd       Ze
dej,                  fd       Ze
deeef   fd       ZdefdZe
defd       Z	 	 	 	 d)dZ	 	 d*dej,                  deee df   dedefdZ!d Z"d Z#de$fdZ%dee&ef   de$fdZ'd e(de$fd!Z)e
d"        Z*dedd#fd$Z+e
d%        Z,e
d&        Z-e
d'        Z.y)+r    zXClass implementing functionality to read a PDF file and cache
    certain data about it.NFxrefsr[   c                 $   d| _         || _        i | _        d| _        d| _        i | _        || _        t        |      | _        t        || |      \  | _	        }|j                  | _
        |j                  | _        |j                  | _        d| _        y)a  
        Initializes a PdfFileReader object.  This operation can take some time,
        as the PDF stream's cross-reference tables are read into memory.

        :param stream: A File object or an object that supports the standard
            read and seek methods similar to a File object.
        :param bool strict: Determines whether user should be warned of all
            problems and also causes some correctable problems to be fatal.
            Defaults to ``True``.
        N)_security_handlerr[   resolved_objects_header_version_input_version_historical_resolver_cacherA   rY   rd   rf   r^   trailerhas_xref_stream_embedded_signatures)selfrA   r[   ra   s       r1   __init__zPdfFileReader.__init__   s     =AJL#"IK'  4F;#:64#P 
L*99#+++;;$(!r2   c                     | j                   r0| j                  s$t        j                  | j                         | _        | j                  S N)encrypt_dictrh   r   buildrp   s    r1   security_handlerzPdfFileReader.security_handler   s8    T%;%;%4%:%:4;L;L%MD"%%%r2   r%   c                     	 ddl m} | j                  d   }t        ||j                        r|j                  |j                        S y # t        t        f$ r Y y w xY w)Nr   )xmp_xmlz	/Metadata)	pyhanko.pdf_utils.metadatary   rootImportErrorKeyError
isinstanceMetadataStreammeta_from_xmpxmp)rp   ry   meta_objs      r1   _xmp_meta_viewzPdfFileReader._xmp_meta_view   s[    	:yy-H h 6 67((66 X& 		s   A	 	AAc                     | j                         }||S 	 | j                  d   }t	        || j
                        S # t        $ r t               cY S w xY wNz/Infor[   )r   trailer_viewr}   r   r   r[   )rp   xmp_view	info_dicts      r1   document_meta_viewz PdfFileReader.document_meta_view   s]    &&(O	&))'2I #9T[[AA  	&#%%	&s   < AAc                     | j                   }||S | j                  }	 | j                  d   }t        |      xs |}|| _         |S # t        $ r |}Y w xY w)Nz/Version)rk   rj   r{   r"   r}   )rp   rW   header_versionversions       r1   rW   zPdfFileReader.input_version   sl    ++$  --	+ii
+G1':LnM ,	  	+*M	+s   A AAc           
         t        j                  |d|       }|j                         }t        |t         j                        sJ |d   dk(  sJ d|cxk  r|d   k  s-n | j
                  rt        d      t        j                         S t        |j                        }|d   }t        |d         D ]J  }	 t        j                  |d       t         j                  j                  |      }	t        j                  |d       t         j                  j                  |      }
t        j                  |d       |	|k7  r| j
                  r||k7  rt        d
      ||
z   }|j!                  |       	 t        j"                  |t        j                  |d|             }t        |t         j                  t         j,                  f      r| j
                  rt        d      |c S t        j                  |dd       |c S  | j
                  rt        d      t        j                         S # t        $ r0 | j
                  rt        d	      t        j                         cY c S w xY w# t        j$                  t        j&                  f$ rW}t(        j+                  d| d| d|        | j
                  rt        d|z        t        j                         }Y d }~>d }~ww xY w)Nr   /Typez/ObjStmz/Nz$Object stream does not contain indexz/FirstT	seek_backz'Object stream header possibly corruptedzObject is in wrong index.zInvalid stream (index z) within object z 0: zCan't read object stream: %sz2Encountered forbidden object type in object stream)r   	allow_eofz@Object not found in stream, this is a fatal error in strict mode)r   	Reference
get_objectr~   StreamObjectr[   r   
NullObjectr   dataranger   read_non_whitespaceNumberObjectread_from_streamrJ   r;   read_objectPdfStreamErrorr   rM   rN   IndirectObject)rp   idnumstmnumidx
stream_refrA   stream_datafirst_objectiobjnumoffset	obj_startobjes                 r1   _get_object_from_streamz%PdfFileReader._get_object_from_stream   s    &&vq$7
&&(&'"6"6777g)+++S'6$<'{{()OPP))++fkk*h'vd|$ 0	A0((E -->>{K((E -->>{K((E {{sax()DEE$v-IY'+))%%eQ5 # 4 4g6L6LMN;;,L  J''tt Ja0	d ;;$7 
 %%''c  0;;,A  #--//0& ''):):; 
+ ,QC/?wd1#N ;;,-Ka-OPP((*
+s,   6BH*2+I&*4I#"I#&#K 	AKK c                 r   	 | j                   j                  d      }t        |t        j
                        r| j                  |j                  d      }n$| j                  s|}nt        j                  d      t        |t        j                        st        j                  d      |S # t        $ r Y y w xY w)Nz/EncryptT)never_decryptz1Encryption settings must be an indirect referencez(Encryption settings must be a dictionary)rm   raw_getr}   r~   r   r   r   	referencer[   r   r   DictionaryObject)rp   encrypt_refrt   s      r1   rt   zPdfFileReader.encrypt_dictI  s    	,,..z:K k7#9#9:??%%T + L &L##C  ,(@(@A##$NOO  		s   B* *	B65B6c                 6    | j                   j                         S rs   )rm   flattenrv   s    r1   r   zPdfFileReader.trailer_view]  s    ||##%%r2   c                     | j                   j                  dt        j                  j                        j
                  S )N/Root)decrypt)rm   r   r   EncryptedObjAccessRAWr   rv   s    r1   root_refzPdfFileReader.root_refa  s4    ||##W77;; $ 

)	r2   c                 \    | j                   d   }|d   j                  |d   j                  fS Nz/IDr   r   )rm   original_bytesrp   id_arrs     r1   document_idzPdfFileReader.document_idg  s/    e$ay'')A)AAAr2   revisionc                 8    | j                  |      j                  S )z
        Get the document catalog for a specific revision.

        :param revision:
            The revision to query, the oldest one being `0`.
        :return:
            The value of the document catalog dictionary for that revision.
        )get_historical_resolverr{   )rp   r   s     r1   get_historical_rootz!PdfFileReader.get_historical_rootl  s     ++H5:::r2   c                 .    | j                   j                  S )zW
        :return:
            The total number of revisions made to this file.
        )rf   total_revisionsrv   s    r1   r   zPdfFileReader.total_revisionsw  s     zz)))r2   c           	      >   || j                   j                  v rd}|r| j                  |j                  |j                        }|| j                  || j                   |   ||      }| j                  |j                  |j                  |       nf| j                   j                  ||      }|3t        j                  d|j                   d|j                   d| d       | j                  ||||      }|r&t        |t        j                        r|j                  }|S )a  
        Read an object from the input stream.

        :param ref:
            :class:`~.generic.Reference` to the object.
        :param revision:
            Revision number, to return the historical value of a reference.
            This always bypasses the cache.
            The oldest revision is numbered `0`.
            See also :class:`.HistoricalResolver`.
        :param never_decrypt:
            Skip decryption step (only needed for parsing ``/Encrypt``)
        :param transparent_decrypt:
            If ``True``, all encrypted objects are transparently decrypted by
            default (in the sense that a user of the API in a PyPDF2 compatible
            way would only "see" decrypted objects).
            If ``False``, this method may return a proxy object that still
            allows access to the "original".

            .. danger::
                The encryption parameters are considered internal,
                undocumented API, and subject to change without notice.
        :param as_metadata_stream:
            Whether to dereference the object as an XMP metadata stream.
        :return:
            A :class:`~.generic.PdfObject`.
        :raises PdfReadError:
            Raised if there is an issue reading the object from the file.
        T)r   as_metadata_streamzCould not find object ( z) in history at revision .)rf   xref_stream_refscache_get_indirect_object
generationr   _read_objectcache_indirect_objectget_historical_refrM   rN   r~   r   DecryptedObjectProxy	decrypted)rp   refr   r   transparent_decryptr   r   markers           r1   r   zPdfFileReader.get_object  s!   N $**--- M00KC{''JJsO"/'9	 (  **3>>399cJ ZZ223AF~-cii[#..9I J..6Zq: ##+#5	 $ C :--$
 --C
r2   r   r   r   r   c                    |Q| j                   rt        d| d      t        j                  d| d       t	        j
                         }||_        |S t        |t              r3| j                  |j                  |j                  |j                        }ng|}| j                  j                  |       t        | j                  | j                         \  }}	||j                  k7  s|	|j                   k7  r,t#        d|j                   d|j                    d| d|	 d	      t	        j$                  | j                  t	        j&                  ||	|       |	      }t	        j(                  | j                  d
       | j                  j+                         dz
  }
| j                  j-                  d      }|dk7  r&| j                   r;t        d|
 dt/        |             t	        j(                  | j                  d
       |sBt        |t              s2| j0                  r&| j2                  }|J t	        j4                  ||      }|S )NzObject addressed by zC not found in the current context. This is an error in strict mode.zH not found in the current context, substituting null in non-strict mode.r   zExpected object ID (r   z) does not match actual (z).)r   Tr   r      s   endobjz#Expected endobj marker at position z but found )r[   r   rM   infor   r   container_refr~   r   r   r   obj_stream_idix_in_streamrA   r;   r   r   r   r   r   r   r9   r:   repr	encryptedrw   proxy_encrypted_obj)rp   r   r   r   r   r   retvalr   r   r   obj_data_endendobjshs                r1   r   zPdfFileReader._read_object  s)    >{{(*3% 0@ A 
 *3% 0E F ((*$'!
-11		6//1D1DF IKKY' 2DKK!E: 		!Z3>>%A"*399+Qs~~6F G..3WAj\E  ((!!%T:#5F
 ''tD;;++-1L[[%%a(F";;,=l^ L%%)&\N4 
 ++DKK4H
 v|4,0,A,AB>!> 00<Fr2   c                 @    | j                   j                  ||f      }|S rs   )ri   get)rp   r   r   outs       r1   r   z'PdfFileReader.cache_get_indirect_object  s"    ##''U(;<
r2   c                 (    || j                   ||f<   |S rs   )ri   )rp   r   r   r   s       r1   r   z#PdfFileReader.cache_indirect_object  s    58z512
r2   prelim_auth_resultc                 b   | j                   }|J d| j                  v xs |j                  }|j                  }|d uxr |j	                         }|j
                  t        j                  k7  rN|s|rJddlm	} 	 |j                  |        t        |j
                  |j                  t        j                        }|S |S # |j                  $ rc}t        j!                  d|j"                   |       t        t        j                  t        j                  |j"                        }Y d }~|S d }~ww xY w)Nz	/AuthCoder   )pdfmac)statuspermission_flags
mac_statuszFailed to validate MAC: )exc_info)r   r   mac_failure_reason)rw   rm   pdf_mac_enabledr   mac_requiredr   r   FAILEDpyhanko.pdf_utils.cryptr   validate_pdf_macr   r   
SUCCESSFULPdfMacValidationErrorrM   rN   failure_message)	rp   r   r   traces_of_macpermsr   r   auth_resultr   s	            r1   _validate_pdf_maczPdfFileReader._validate_pdf_mac  s"   ""~~ $t||3Ir7I7I"33D(AU-?-?-A$$
(9(99\6''-(-44%7%H%H+66 %% // .q/@/@.ABQ   )%,,+22'('8'8
 s   7AB< <D.AD))D.passwordc                     | j                   }t        |t              s"t        j                  dt        |       d      |j                  || j                  d         }| j                  |      S )a  
        When using an encrypted PDF file with the standard PDF encryption
        handler, this function will allow the file to be decrypted.
        It checks the given password against the document's user password and
        owner password, and then stores the resulting decryption key if either
        password is correct.

        Both legacy encryption schemes and PDF 2.0 encryption (based on AES-256)
        are supported.

        .. danger::
            Supplying either user or owner password will work.
            Cryptographically, both allow the decryption key to be computed,
            but processors are expected to adhere to the ``/P`` flags in the
            encryption dictionary when accessing a file with the user password.
            Currently, pyHanko does not enforce these restrictions, but it
            may in the future.

        .. danger::
            One should also be aware that the legacy encryption schemes used
            prior to PDF 2.0 are (very) weak, and we only support them for
            compatibility reasons.
            Under no circumstances should these still be used to encrypt new
            files.

        :param password: The password to match.
        Security handler is of type 'z', not StandardSecurityHandlerr   )id1)	rw   r~   r   r   r   typeauthenticater   r   )rp   r   r   r   s       r1   r   zPdfFileReader.decrypt>  sr    8 """56##/Rz :. / 
 oohD4D4DQ4GoH%%k22r2   
credentialc                     | j                   }t        |t              s"t        j                  dt        |       d      |j                  |      }| j                  |      S )a  
        Decrypt a PDF file encrypted using public-key encryption by providing
        a credential representing the private key of one of the recipients.

        .. danger::
            The same caveats as in :meth:`.decrypt` w.r.t. permission handling
            apply to this method.

        .. danger::
            The robustness of the public key cipher being used is not the only
            factor in the security of public-key encryption in PDF.
            The standard still permits weak schemes to encrypt the actual file
            data and file keys.
            PyHanko uses sane defaults everywhere, but other software may not.

        :param credential:
            The :class:`.EnvelopeKeyDecrypter` handling the recipient's
            private key.
        r   z', not PubKeySecurityHandler)rw   r~   r   r   r   r   r   r   )rp   r   r   r   s       r1   decrypt_pubkeyzPdfFileReader.decrypt_pubkeyd  sc    ( """34##/Rz :, -  ooj1%%k22r2   c                     | j                   duS )zT
        :return: ``True`` if a document is encrypted, ``False`` otherwise.
        N)rw   rv   s    r1   r   zPdfFileReader.encrypted  s    
 $$D00r2   r!   c                 j    | j                   }	 ||   S # t        $ r t        | |      }|||<   |cY S w xY w)a,  
        Return a :class:`~.rw_common.PdfHandler` instance that provides a view
        on the file at a specific revision.

        :param revision:
            The revision number to use, with `0` being the oldest.
        :return:
            An instance of :class:`~.HistoricalResolver`.
        )rl   r}   r!   )rp   r   cacheress       r1   r   z%PdfFileReader.get_historical_resolver  sG     //	?" 	$T84C!E(OJ	s    22c                       j                    j                   S ddlm} ddlm  | d      }t         fd|D        d 	      }| _         |S )
z
        :return:
            The signature objects embedded in this document, in signing order;
            see :class:`~pyhanko.sign.validation.EmbeddedPdfSignature`.
        r   )enumerate_sig_fieldsr'   )EmbeddedPdfSignatureT)filled_statusc              3   :   K   | ]  \  }}} ||        y wrs    ).0fq_namesig_obj	sig_fieldr	  rp   s       r1   	<genexpr>z4PdfFileReader.embedded_signatures.<locals>.<genexpr>  s(      /GWi %T9g>s   c                     | j                   S rs   )signed_revision)embs    r1   <lambda>z3PdfFileReader.embedded_signatures.<locals>.<lambda>  s    C// r2   )key)ro   pyhanko.sign.fieldsr  sign.validationr	  sorted)rp   r  
sig_fieldsresultr	  s   `   @r1   embedded_signaturesz!PdfFileReader.embedded_signatures  sZ     $$0,,,<:)$dC
3= 0
 %+!r2   c                 ^    | j                   D cg c]  }|j                  dk(  r| c}S c c}w )z
        :return:
            The signature objects of type ``/Sig`` embedded in this document,
            in signing order;
            see :class:`~pyhanko.sign.validation.EmbeddedPdfSignature`.
        z/Sigr  sig_object_typerp   emb_sigs     r1   embedded_regular_signaturesz)PdfFileReader.embedded_regular_signatures  s8      33
&&&0 
 	
 
   *c                 ^    | j                   D cg c]  }|j                  dk(  r| c}S c c}w )z
        :return:
            The signature objects of type ``/DocTimeStamp`` embedded in
            this document, in signing order;
            see :class:`~pyhanko.sign.validation.EmbeddedPdfSignature`.
        z/DocTimeStampr  r   s     r1   embedded_timestamp_signaturesz+PdfFileReader.embedded_timestamp_signatures  s8      33
&&/9 
 	
 
r#  T)NFTF)FF)/__name__
__module____qualname____doc__r^   rn   r   __annotations__boolrq   propertyrw   r   r   r   r   rW   r   r   r   rt   r   r   r   r
   rC   r   r+   r   r   r   r   r   r   r   r   r   r   r*   r   r   r  r   r   r  r"  r%  r  r2   r1   r    r       sG    NO)t )8 & &

)9 : 
 
B$4 
B 
B  H(T hw'?'?@  & &g66 & & '++  
 BU5%<0 B B	;C 	; * * *   H\ $#(CC c<-.C 	C
 !CJ&&J &&P$3c5j 1 $3j $3L3)= 3* 3: 1 1 8L $  0 
 
 
 
r2   r    c                       e Zd ZdZdeeef   fdZd Zd Z	d Z
d Zd Z	 dd	eeeeed
f   ej                   f   d
d
f   fdZdd	ej                   fdZd	ej&                  fdZed        Zd Zd Zd Zy
)r#   zN
    Class to model raw paths in a file.

    This class is internal API.
    pathc                     || _         y rs   )r/  )rp   r/  s     r1   rq   zRawPdfPath.__init__  s	    	r2   c                 ,    t        | j                        S rs   )lenr/  rv   s    r1   __len__zRawPdfPath.__len__  s    499~r2   c                 ,    t        | j                        S rs   )iterr/  rv   s    r1   __iter__zRawPdfPath.__iter__  s    DIIr2   c                 B    t        t        d | j                              S )Nc                 &    t        | t              | fS rs   r~   r+   )r?   s    r1   r  z!RawPdfPath._tag.<locals>.<lambda>  s    Jq#$6#: r2   )rE   mapr/  rv   s    r1   _tagzRawPdfPath._tag  s    S:DIIFGGr2   c                 4    t        | j                               S rs   )hashr;  rv   s    r1   __hash__zRawPdfPath.__hash__  s    DIIK  r2   c                 t    t        |t              xr' | |u xs! | j                         |j                         k(  S rs   )r~   r#   r;  rp   others     r1   __eq__zRawPdfPath.__eq__  s3    %, 
EM8TYY[EJJL8	
r2   r%   Nc              #   <  K   |}d }t        | j                        D ]  \  }}|s||f t        |t        j                        r|j                         }|r||f t        |t              r5t        |t        j                  t        f      r	 |j                  |      }|}t        |t              rft        |t        j                        rLd|cxk  rt        |      k  s$n t        j                  d| d| d|  d| d	      |j                  |      }|}t        j                  d|  d| d       t        |t        j                        r|r||j                         f y ||f y # t        $ r# t        j                  d| d| d|  d| d	      w xY ww)	Nz%Encountered missing dictionary entry z at position z	 in path z from r   r   z%Encountered out-of-range array index zType error in path )	enumerater/  r~   r   r   r   r*   r   r   r   r}   r   r   r+   ArrayObjectr2  )rp   from_objtransparent_dereferencecurrent_objelemixentrys          r1   
walk_nodeszRawPdfPath.walk_nodes  s     &*"499- #	IB*K''+w'='=>)446&K''%%'":":<M!N	&1&9&9%&@$  E3'k7+>+>?:#k*::"//C$g]2$iv F$$,:Q0 
 #."5"5e"<K D##%dV=A> C#	J {G$:$:;'..000##7 $ "//%%*G=IdV L$$,:Q0 s   BFE-!CF-,FFc                 p    | j                  ||      }|}	 	 t        |      \  }}# t        $ r |cY S w xY w)N)rG  )rL  nextStopIteration)rp   rF  dereference_lastwalkr   _s         r1   	access_onzRawPdfPath.access_on  sP    .>  
 	d3  	J	s   ' 55c                     | j                  |d      }t        |t        j                        st	        j
                  d|  d| d      |j                  S )NF)rP  zFinal entity on path z starting from z is not an indirect object.)rS  r~   r   r   r   IndirectObjectExpectedr   )rp   rF  ind_objs      r1   access_reference_onzRawPdfPath.access_reference_on(  s]    ..E.B'7#9#9:--'v_XJ G& '     r2   c                 <    t        | t              rd| z  S d| dd  z   S )Nz[%d]r   r   r9  )nodes    r1   	_fmt_nodezRawPdfPath._fmt_node1  s&    dC D= ab>!r2   c                     t        |t              r!t        g | j                  |j                   S t        |t        t        f      rt        g | j                  | S t
        rs   )r~   r#   r/  r+   r*   	TypeErrorr@  s     r1   __add__zRawPdfPath.__add__8  sQ    eZ(6tyy65::66Sz*0tyy0%00Or2   c                 h    dj                  t        t        j                  | j                              S )N )joinr:  r#   rZ  r/  rv   s    r1   __str__zRawPdfPath.__str__@  s"    wws://;<<r2   c                      dt        |        dS )NzPathInRevision('z'))r*   rv   s    r1   __repr__zRawPdfPath.__repr__C  s    !#d)B//r2   r&  )r'  r(  r)  r*  r   r*   r+   rq   r3  r6  r;  r>  rB  r   r
   r   	PdfObjectrL  rS  r   rW  staticmethodrZ  r]  ra  rc  r  r2   r1   r#   r#     s    eCHo H!
 15/$	5sC~.0A0AABD$N	O/$b	G<M<M 	!w/@/@ ! " "=0r2   r#   c                      e Zd ZdZedefd       Zedeeef   fd       Z	de
fdZedej                  fd       Z	 ddej                  d	efd
Zd Zedej                  fd       Zdej                  fdZd Zd Zd Zdej                  defdZ	 ddej2                  deej                     fdZddZdej                  dee   fdZd Zy)r!   aE  
    :class:`~.rw_common.PdfHandler` implementation that provides a view
    on a particular revision of a PDF file.

    Instances of :class:`.HistoricalResolver` should be created by calling the
    :meth:`~.PdfFileReader.get_historical_resolver` method on a
    :class:`~.PdfFileReader` object.

    Instances of this class cache the result of :meth:`get_object` calls.

    .. danger::
        This class is documented, but is nevertheless considered internal API,
        and easy to misuse.

        In particular, the `container_ref` attribute must *not* be relied upon
        for objects retrieved from a :class:`.HistoricalResolver`.
        Internally, it is only used to make lazy decryption work in historical
        revisions.

    .. note::
        Be aware that instances of this class transparently rewrite the PDF
        handler associated with any reference objects returned from the reader,
        so calling :meth:`~.generic.Reference.get_object` on an indirect
        reference object will cause the reference to be resolved within the
        selected revision.
    r%   c                     	 | j                   d   }t        || j                  j
                        S # t        $ r t               cY S w xY wr   )r   r}   r   r   readerr[   )rp   r   s     r1   r   z%HistoricalResolver.document_meta_viewc  sJ    	&))'2I #9T[[5G5GHH  	&#%%	&s   2 AAc                 \    | j                   d   }|d   j                  |d   j                  fS r   )_trailerr   r   s     r1   r   zHistoricalResolver.document_idl  s/    u%ay'')A)AAAr2   rh  c                     i | _         || _        || _        | j                  j                  j	                  | j                        | _        t        j                  |       | j
                  _        d | _	        y rs   )
r  rh  r   rm   r   rj  r   TrailerReferencer   _indirect_object_access_cache)rp   rh  r   s      r1   rq   zHistoricalResolver.__init__q  s[    AC
 ++33DMMB&-&>&>t&D#  	*r2   c                     | j                   S rs   )rj  rv   s    r1   r   zHistoricalResolver.trailer_view{  s    }}r2   r   r   c                    | j                   }	 ||   }t        |t        j                        r|j                  S |S # t        $ r | j                  }| j                  }	 |j                  j                  |      }n*# t        $ r t        j                  d| d       d }Y nw xY w|||k  r|j                  |d|      }n|j                  ||d|      }| j                  |      x||<   }Y w xY w)NzCould not determine history of z in xref sectionsF)r   r   )r  r}   rh  r   rf   get_last_changerM   rN   r   _subsume_objectr~   r   r   r   )rp   r   r   r  r   rh  r   last_changes           r1   r   zHistoricalResolver.get_object  s    

	9*C> c7778== 
A  	9 [[F}}H#$ll::3? #5cU:KL #	#
 &;(+B''(-'9 (  ''(-'9	 (   $33C88E#J;	9s4   ; !C-A98C-9$B C-B  A
C-,C-c           
          |j                         }t        j                  |j                  |j                         }t        |t        j                        rE j                  |j                        }t        j                  ||j                        }||_
        |S t        |t        j                        r,t        j                  |j                  |j                         S t        |t        j                        rSt        j                  |j                         D ci c]  \  }}| j                  |       c}}|j                        }nt        |t        j                        rGt        j                  |j                         D ci c]  \  }}| j                  |       c}}      }n;t        |t        j                         rt        j                    fd|D              }n|S ||_
        |S c c}}w c c}}w )Nr   r   pdf)
raw_objectr]   )encoded_datac              3   @   K   | ]  }j                  |        y wrs   )rq  )r  vrp   s     r1   r  z5HistoricalResolver._subsume_object.<locals>.<genexpr>  s     (NQ)=)=a)@(Ns   )get_container_refr   r   r   r   r~   r   rq  rv  r]   r   r   r   itemsrw  r   rE  )rp   r   r   raw_obj_replacementr  kry  s   `      r1   rq  z"HistoricalResolver._subsume_object  s   ( --/))%%$//
 c7778"&"6"6s~~"F
 11.F 1>-Mc7112))iiCNN  W112))8;		D1D((++D --F W556--8;		D1D((++DF W001(((N#(NNF J, E
 Es   G5
G;
c                     | j                   j                  j                  d| j                        }t	        j
                  |j                  |j                  |       S )Nr   )r   rt  )rh  rm   r   r   r   r   r   r   rp   r   s     r1   r   zHistoricalResolver.root_ref  sO    &*kk&9&9&A&Admm 'B '
   ))D
 	
r2   c                 $    | j                  |      S rs   )r   r  s     r1   __call__zHistoricalResolver.__call__  s    s##r2   c                 `    | j                   j                  j                  | j                        S rs   )rh  rf   explicit_refs_in_revisionr   rv   s    r1   r  z,HistoricalResolver.explicit_refs_in_revision  s!    {{  ::4==IIr2   c                 `    | j                   j                  j                  | j                        S rs   )rh  rf   refs_freed_in_revisionr   rv   s    r1   r  z)HistoricalResolver.refs_freed_in_revision  !    {{  77FFr2   c                 `    | j                   j                  j                  | j                        S rs   )rh  rf   object_streams_used_inr   rv   s    r1   object_streams_usedz&HistoricalResolver.object_streams_used  r  r2   c                     | j                   j                  }|j                  | j                        }|j                  |j
                  k\  S )a  
        Check if the reference in question was in scope for this revision.
        This call doesn't care about the specific semantics of free vs. used
        objects; it conservatively answers 'no' in any situation where
        the object ID _could_ have been assigned by the revision in question.

        :param ref:
            A reference object (usually one written to by a newer revision)
        :return:
            ``True`` if the reference is unassignable, ``False`` otherwise.
        )rh  rf   get_xref_container_infor   r   size)rp   r   rc   metas       r1   is_ref_availablez#HistoricalResolver.is_ref_available  s<     [[&&
11$--@ yyDII%%r2   Nr   c                 @    t               }| j                  |||       |S )a1  
        Collect all indirect references used by an object and its descendants.

        :param obj:
            The object to inspect.
        :param since_revision:
            Optionally specify a revision number that tells the scanner to only
            include objects IDs that were added in that revision or later.

            .. warning::
                In particular, this means that the scanner will not recurse
                into older objects either.

        :return:
            A :class:`set` of :class:`~.generic.Reference` objects.
        )set_collect_indirect_references)rp   r   since_revision
result_sets       r1   collect_dependenciesz'HistoricalResolver.collect_dependencies  s#    & .1U
))#z>Jr2   c                    t        |t        j                        r`|j                  }||v ry | j                  j
                  }|d u xs |j                  |      |k\  }|r|j                  |       n|y  | |      }t        |t        j                        r)|j                         D ]  }| j                  |||        y t        |t        j                        r|D ]  }| j                  |||        y y rs   )r~   r   r   r   rh  rf   get_introducing_revisionaddr   valuesr  rE  )rp   r   seenr  r   rf   relevantry  s           r1   r  z/HistoricalResolver._collect_indirect_references#  s    c7112--Cd{KK%%E$& I11#6.H  + s)Cc7334ZZ\ K11!T>JKW001 K11!T>JK 2r2   c                 `    | j                   xs i }	 ||   S # t        $ r t               cY S w xY wrs   )rm  r}   r  )rp   r   r  s      r1   _get_usages_of_refz%HistoricalResolver._get_usages_of_ref<  s7    228b	: 	5L	s    --c                     	
  j                   y t        t              dt        j                  t
        t        t        f      dt        j                  t        j                     f fd	fd	
fd
 j                  j                  d      }t               } 	|j                               D ],  }||v rt        j                  d      |j                  |       . t               }	  j                  j                  d	      }|j                         } 
|      D ],  }||v rt        j                  d
      |j                  |       . 	   j                   t        j                  j#                         t        j                  j#                         d|d|       j%                         D ci c].  \  }}||D ch c]  }t'        t)        t+        |              c}0 c}}} _         y # t        $ r Y w xY wc c}w c c}}}w )Ncur_pathseen_in_pathc                <   t        | t        j                        rL| j                  }||v ry |   j	                  |       |j                  |      } |      } |s||v ry |s||v ry t        | t        j                        r| j                         D ]  \  }}	|dk(  s|r|dk(  r |	|j                  |      ||xsC |j                  dk(  xr2 |dk(  xr+ |j                  t        j                  j                         k(  ||xsD |j                  dk(  xr3 |dk(  xr, |j                  t        j                  j                  d      k(  |        y t        | t        j                        r2t        |       D ]#  \  }
}	 |	|j                  |
      |||||       % y y )Nz/Parentz/Pr   /Pages/StructTreeRoot/Kis_page_treepage_tree_objsis_struct_treestruct_tree_objs)r~   r   r   r   r  consr   r{  headtailr   ConsListemptysingrE  rD  )r   r  r  r  r  r  r  obj_refr}  ry  rJ  _compute_paths_to_refs	collectedrp   s              r1   r  zKHistoricalResolver._load_reverse_xref_cache.<locals>._compute_paths_to_refsL  s   , #w556--l*'"&&x0+0097m#>(A%'5E*E#w778IIK DAq I~.Q$Y * a($%1 &$MMW4 G !XG (1D1D1F F'5 (6 ($MM->> M !T	M (1C1CG1L L)91@ C!4!45&s^ 	EB* b)$%1'5'5)9	 6r2   c              3      K   | d   D ]`  }t        |t        j                        r|j                   |j	                         }|j                  dd       dk(  sQ |      E d {    b y 7 w)Nz/Kidsr   r  )r~   r   r   r   r   r   )	pages_objkid_collect_page_tree_refss     r1   r  zLHistoricalResolver._load_reverse_xref_cache.<locals>._collect_page_tree_refs  sg      ) <c7#9#9:--'nn&777D)X56s;;;< <s   AA/A/%A-&A/c              3     K   	 | d   }t        |t        j                        s|f}|D ]v  }d }t        |t        j                        r|j
                  }|j                         }t        |t        j                        sV	 |d   dk7  r`	 ||  |      E d {    x y # t         $ r Y y w xY w# t         $ r Y 3w xY w7 %w)Nr  r   z/StructElem)r}   r~   r   rE  r   r   r   r   )struct_elemchildrenchild	child_ref_collect_struct_tree_refss       r1   r  zNHistoricalResolver._load_reverse_xref_cache.<locals>._collect_struct_tree_refs  s     &t,
 h(;(;<$;! < 	eW%;%;< %I!,,.E "%)A)ABW~6  7 (#O4U;;;+<  (     <sX   CB# A5C B2CCC#	B/,C.B//C2	B>;C=B>>Cr  )r  z0Circular reference in page tree in mapping stager  z5Circular reference in structure tree in mapping stageFr  )rm  r   r  r   r  r   r*   r+   r   r   r{   r   r   r   r  r}   r   r  r{  r#   rD   list)rp   	pages_refpage_tree_nodesr   struct_tree_nodesstruct_tree_root_refstruct_tree_rootpathspr  r  r  r  s   `        @@@@r1   _load_reverse_xref_cachez+HistoricalResolver._load_reverse_xref_cacheC  s   --9$	
L	mmE#s(O4L	 --(9(9:L	\	<	<B II%%h/	%*Y5I5I5KL 	%Co%''F  $	%  E
	#'99#4#45F#G 3>>@01AB +++++O  "%%c*+ 	MM!MM!* .	
 (oo/.
 .
U %@Q*htAw/0@@.
*  		 A.
s+   /A"G5 7H	!H%H	5	H HH	)Frs   ) r'  r(  r)  r*  r-  r   r   r
   rC   r   r    rq   r   r   r   r   r,  r   rq  r   r  r  r  r  r  rd  r	   r  r  r#   r  r  r  r2   r1   r!   r!   G  sU   6 I$4 I I BU5%<0 B B}  g66   BG&$$&:>&P;z 
'++ 
 
$G-- $JGG&G$5$5 &$ &( 6:$$	W	.K2g&7&7 C
O b
r2   r!   );r*  loggingr<   recollectionsr   ior   typingr   r   r   r   r	   r
   r   r_  r   r   cryptr   r   r   r   r   r   	crypt.apir   metadata.infor   metadata.modelr   r   r   	rw_commonr   xrefr   r   r   r   r   	getLoggerr'  rM   __all__compilerV   r(   r+   r"   rF   r$   rY   r,  rd   r    r#   r!   r  r2   r1   <module>r     s*  
  	 	 #  I I I   $ . , 2 !  
		8	$ rzz-."

=1 (5c?*C ,4%3 %P eCHo $$#-$7;$
9k!"$(a
J a
Ht0 t0n^
 ^
r2   