
    Wwg+                         d Z ddlZddlmZmZ ddl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gZ G d de      Zy)z@
Utility for writing incremental updates to existing PDF files.
    N)OptionalUnion   )genericmisc)EnvelopeKeyDecrypter)pdf_name)DocumentMetadata)PdfFileReaderparse_catalog_version)BasePdfFileWriterIncrementalPdfFileWriterc                       e Zd ZdZdZdZ	 d dee   f fdZe	dedd fd       Z
d	 Ze	d
        Zd!def fdZdeej"                  ej$                  f   fdZdej(                  fdZd Zd Zdeeej$                  ej0                  f      f fdZ fdZdej6                  dej(                  fdZ fdZedefd       Z d Z!d Z"d Z#de$fdZ% xZ&S )"r   a!  Class to incrementally update existing files.

    This :class:`~.writer.BasePdfFileWriter` subclass encapsulates a
    :class:`~.reader.PdfFileReader` instance in addition to exposing an
    interface to add and modify PDF objects.

    Incremental updates to a PDF file append modifications to the end of the
    file. This is critical when the original file contents are not to be
    modified directly (e.g. when it contains digital signatures).
    It has the additional advantage of providing an automatic audit trail of
    sorts.

    :param input_stream:
        Input stream to read current revision from.
    :param strict:
        Ingest the source file in strict mode. The default is ``True``.
    :param prev:
        Explicitly pass in a PDF reader. This parameter is internal API.
    i   Fprevc                    || _         |t        ||      }|| _        |j                  x| _        }|j	                  d      }	 |j	                  d      }| j                  j                  |      }t        	| %  ||||d   |j                         | j                  | j                  | j                  d<   | |f| _        | j                  j                  }|| j                  kD  r|| _        | j                  | j                  j                         |j                   | _        | j                   !|j                  j	                  d      | _        y y # t
        $ r d }Y w xY w)N)strictz/Root/Infoz/Size)obj_id_startstream_xrefs/Encrypt)input_streamr   r   trailerraw_getKeyError	__class__
_handle_idsuper__init__has_xref_stream_info_resolves_objs_frominput_versionoutput_versionensure_output_versionsecurity_handler_encrypt)
selfr   r   r   r   root_refinfo_refdocument_id	input_verr   s
            [/var/www/horilla/myenv/lib/python3.12/site-packages/pyhanko/pdf_utils/incremental_writer.pyr   z!IncrementalPdfFileWriter.__init__*   sJ    )< f=D	!%-w??7+	w/H nn//5 )-- 	 	
 ::!$(JJDLL!$($< II++	t***"+D""4>>#@#@A $ 5 5  , LL00<DM -)  	H	s   E EEreaderreturnc                 *     | |j                   |      S )z
        Instantiate an incremental writer from a PDF file reader.

        :param reader:
            A :class:`.PdfFileReader` object with a PDF to extend.
        )r   )stream)clsr-   s     r,   from_readerz$IncrementalPdfFileWriter.from_readerL   s     6==v..    c                 .   | j                   j                  |k\  ry | j                  }	 |t        d         }t	        |      }|||k\  ry t        d|z        }||t        d      <   | j                          || _	        y # t
        t        t        f$ r Y Jw xY w)Nz/Versionz/%d.%d)
r   r"   rootr	   r   r   
ValueError	TypeErrorupdate_rootr#   )r'   versionr5   vercur_versionversion_strs         r,   r$   z.IncrementalPdfFileWriter.ensure_output_versionW   s    99""g-yy	x
+,C/4K&;'+A x'12%0Xj!"% *i0 		s    A= =BBc                    t        j                  t        j                  d            }	 |j                  d   \  }}t        |t         j                        rt        j                  |j                        }t        j                  ||g      S # t        $ r+ t        j                  t        j                  d            }Y Jw xY w)N   z/ID)
r   ByteStringObjectosurandomr   
isinstanceTextStringObjectoriginal_bytesr   ArrayObject)r1   r   id2id1_s        r,   r   z#IncrementalPdfFileWriter._handle_idi   s      &&rzz"~6		;\\%(FC#w778..s/A/AB
 ""C:..	  	; **2::b>:C	;s   AB 1C ?C as_metadata_streamc                     	 t         |   ||      S # t        $ r  | j                  j                  ||      cY S w xY w)N)rI   )r   
get_objectr   r   )r'   idorI   r   s      r,   rK   z#IncrementalPdfFileWriter.get_object   sX    	7%(: &    	99''(: (  	s    &==obj_refc                 n    |j                   |j                  f}|j                         | j                  |<   y N)
generationidnumrK   objects)r'   rM   ixs      r,   mark_updatez$IncrementalPdfFileWriter.mark_update   s/       '--0"--/Rr3   objc                     |j                   }|y t        |t        j                        ry t        |t        j                        r| j                  |       y t        rO   )container_refrB   r   TrailerReference	ReferencerT   r7   )r'   rU   rW   s      r,   update_containerz)IncrementalPdfFileWriter.update_container   sQ    ))  mW%=%=>w'8'89]+r3   c                 :    | j                  | j                         y rO   )rT   _rootr'   s    r,   r8   z$IncrementalPdfFileWriter.update_root   s    $r3   c                    | j                   j                         }| j                   j                  d       t        j                  t        | j                        | j                   |       | j                   j                  |       y )Nr   )r   tellseekr   chunked_write	bytearrayIO_CHUNK_SIZE)r'   r0   	input_poss      r,   _write_headerz&IncrementalPdfFileWriter._write_header   sf    %%**,	q!d(()4+<+<f	
 	y)r3   infoc                 f    t         |   |      }||| j                  d<   |S | j                  d= |S )Nr   )r   set_infor   )r'   rf   r   s     r,   rh   z!IncrementalPdfFileWriter.set_info   sB     w%$(DLL!  W%r3   c                 l   |j                  | j                  j                                t        |   |       t        j                  | j                  j                        |t        d      <   | j                  j                  r0| j                  j                         st        j                  d      y y )Nz/PrevzCannot update this document without encryption credentials from the original. Please call encrypt() with the password of the original file before calling write().)updater   flattenr   _populate_trailerr   NumberObjectr   last_startxrefr	   	encryptedr%   is_authenticatedr   PdfWriteError)r'   r   r   s     r,   rl   z*IncrementalPdfFileWriter._populate_trailer   s    t||++-.!'*%,%9%9II$$&
!" 99t'<'<'M'M'O$$?  (Pr3   keyvaluec                 "    || j                   |<   y)a  
        Set a custom, unmanaged entry in the document trailer or cross-reference
        stream dictionary.

        .. warning::
            Calling this method to set an entry that is managed by pyHanko
            internally (info dictionary, document catalog, etc.) has undefined
            results.

        :param key:
            Dictionary key to use in the trailer.
        :param value:
            Value to set
        N)r   )r'   rr   rs   s      r,   set_custom_trailer_entryz1IncrementalPdfFileWriter.set_custom_trailer_entry   s    " "Sr3   c                     | j                   s| j                  s| j                  |       y | j                          t        |   |       y rO   )rR   _force_write_when_emptyre   _prep_dom_for_writingr   write)r'   r0   r   s     r,   ry   zIncrementalPdfFileWriter.write   s;    ||D$@$@v&""$fr3   c                 `    | j                   j                  | j                  j                        S rO   )_meta	view_overr   document_meta_viewr]   s    r,   r}   z+IncrementalPdfFileWriter.document_meta_view   s!    zz##DII$@$@AAr3   c                 *    | j                  |d       y)a  
        Only write the updated and new objects to the designated output stream.

        The new PDF file can then be put together by concatenating the original
        input with the generated output.

        .. danger::
            The offsets in this output will typically be wrong unless the missing
            previous section is somehow taken into account.

        .. danger::
            Object graph finalisation will not run.

        :param stream:
            Output stream to write to.
        T)skip_headerN)_write)r'   r0   s     r,   _write_updated_sectionz/IncrementalPdfFileWriter._write_updated_section   s    " 	F-r3   c                     | j                          | j                  rddlm} |j	                  | d       y| j
                  j                  }|j                  dt        j                         | j                  |       y)z
        Write the updated file contents in-place to the same stream as
        the input stream.
        This obviously requires a stream supporting both reading and writing
        operations.
        r   )pdfmacT)in_placeN)rx   _need_mac_on_writepyhanko.pdf_utils.cryptr   add_standalone_macr   r0   r`   r@   SEEK_ENDr   )r'   r   r0   s      r,   write_in_placez'IncrementalPdfFileWriter.write_in_place   s^     	""$""6%%dT%:YY%%FKK2;;'''/r3   c                     | j                   }|j                  |      }|j                  j                  d      | _        |S )a/  Method to handle updates to encrypted files.

        This method handles decrypting of the original file, and makes sure
        the resulting updated file is encrypted in a compatible way.
        The standard mandates that updates to encrypted files be effected using
        the same encryption settings. In particular, incremental updates
        cannot remove file encryption.

        :param user_pwd:
            The original file's user password.

        :raises PdfReadError:
            Raised when there is a problem decrypting the file.
        r   )r   decryptr   r   r&   )r'   user_pwdr   results       r,   encryptz IncrementalPdfFileWriter.encrypt  s8      yyh' ,,Z8r3   
credentialc                     | j                   }|j                  |      }|j                  j                  d      | _        |S )ao  Method to handle updates to files encrypted using public-key
        encryption.

        The same caveats as :meth:`encrypt` apply here.


        :param credential:
            The :class:`.EnvelopeKeyDecrypter` handling the recipient's
            private key.

        :raises PdfReadError:
            Raised when there is a problem decrypting the file.
        r   )r   decrypt_pubkeyr   r   r&   )r'   r   r   r   s       r,   encrypt_pubkeyz'IncrementalPdfFileWriter.encrypt_pubkey&  s8     yy$$Z0,,Z8r3   )NT)F)'__name__
__module____qualname____doc__rc   rw   r   r   r   classmethodr2   r$   r   boolrK   r   r   rY   IndirectObjectrT   	PdfObjectrZ   r8   re   DictionaryObjectrh   rl   
NameObjectru   ry   propertyr
   r}   r   r   r   r   r   __classcell__)r   s   @r,   r   r      sD   ( M# JN ="*="9 =D / /3M / /&$ / /8$ 0W..0F0FFG0G$5$5 %*
uW33W5M5MMNO
"%%".5.?.?"& B$4 B B.&0".)= r3   )r   r@   typingr   r    r   r   cryptr   r	   metadata.modelr
   r-   r   r   writerr   __all__r    r3   r,   <module>r      s;    
 "  '  , 8 %%
&f0 fr3   