
    Wwg                        d Z ddl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
 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 dd	lmZmZmZ dd
lmZ g dZ ej@                  e!      Z"ejF                   G d dejH                               Z% ed       G d d             Z& ed       G d d             Z'dee'   fdZ(	 d;dejR                  de*dee'   fdZ+ejF                   G d dejH                               Z, ed       G d d             Z- G d d      Z. ed       G d d              Z/d!e0d"e/d#ee/   fd$Z1d%ee/   fd&Z2d#ee/   fd'Z3 G d( d)      Z4 G d* d+ej4                        Z5d, Z6d- Z7 G d. d/ejp                        Z9d0 Z:d1 Z; G d2 d3      Z<eee0e0f   ee0ee0e0f   f   f   Z=ej|                  ejR                  fZ? G d4 d5      Z@d6 ZAd7eee0e0f   e0f   fd8ZB G d9 d:ejR                        ZCy)<z
Internal utilities to handle the processing of cross-reference data and
document trailer data.

This entire module is considered internal API.
    N)	dataclass)BytesIO)chain)DictIteratorListOptionalSetTupleUnion)genericmisc)EncryptedObjAccesspdf_name)PdfReadErrorPdfStrictReadErrorpeek)
PdfHandler)	XRefCacheXRefBuilderXRefType	XRefEntryObjStreamRefObjectHeaderReadErrorXRefSectionXRefSectionDataXRefSectionTypeXRefSectionMetaInfoTrailerDictionaryread_object_headerparse_xref_streamparse_xref_tablewrite_xref_tableObjectStream
XRefStreamOBJSTREAM_FORBIDDENPositionDictc                   z    e Zd ZdZ ej
                         Z	  ej
                         Z	  ej
                         Zy)r   z5
    Different types of cross-reference entries.
    N)	__name__
__module____qualname____doc__enumautoFREESTANDARDIN_OBJ_STREAM     M/var/www/horilla/myenv/lib/python3.12/site-packages/pyhanko/pdf_utils/xref.pyr   r   /   sC     499;D tyy{H DIIKMr3   r   T)frozenc                   (    e Zd ZU dZeed<   	 eed<   y)r   z?
    Identifies an object that's part of an object stream.
    obj_stream_idix_in_streamN)r)   r*   r+   r,   int__annotations__r2   r3   r4   r   r   E   s!      r3   r   c                   T    e Zd ZU dZeed<   	 eeee	f      ed<   	 eed<   	 dZ
eed<   y)r   zA
    Value type representing a single cross-reference entry.
    	xref_typelocationidnumr   
generationN)r)   r*   r+   r,   r   r:   r	   r   r9   r   r?   r2   r3   r4   r   r   V   sM      uS,./00 J Jr3   r   returnc           	   #      K   t        j                  |        | j                  dt        j                         	 t
        j                  j                  |       }t        j                  |        | j                  dt        j                         t
        j                  j                  |       }t        j                  |        | j                  dt        j                         t        d|      D ]  }| j                  d      }|d   dv r9| j                  dt        j                         | j                  d      }|d   dv r9|d   dv r | j                  dt        j                         |dd j                  d	      \  }}}|d
k(  r2t        t        j                  t        |      |t        |             n-|dk(  r(t        t        j                  d|t        |             |dz  } t        j                  |        | j                  dt        j                         | j                  d      }|dk(  r6t        j                  |        | j                  dt        j                         y| j                  dt        j                         Uw)a  
    Parse a single cross-reference table and yield its entries one by one.

    This is internal API.

    :param stream:
        A file-like object pointed to the start of the cross-reference table.
    :return:
        A generator object yielding :class:`.XRefEntry` objects.
    r      s   
is   0123456789tN          n)r<   r=   r>   r?      f      s   traileri)r   read_non_whitespaceseekosSEEK_CURr   NumberObjectread_from_streamrangereadsplitr   r   r0   r9   r/   )	streamnumsizecntlineoffsetr?   marker
trailertags	            r4   r"   r"   q   s     	V$
KKBKK 
""33F;  (B$##44V<  (B$D> %	C;;r?D q'[(GR[[1{{2 q'[( Bx>)B,)-cr)>&FJ~&// [":	  4&mm!":	  1HCK%	L 	  (B$[[^
#$$V,KKBKK( KKBKK(o s   D>JEJxref_streamstrictc              #     K   t        | j                        | j                  dd| j                  d      g      }| j                  d      fd}d}t        j                  |      D ]  \  }}||k\  sJ ||z   }t        |||z         D ]  } |d      }|dk(  r0 |d      }	 |d      }
t        t        j                  ||	|
       @|dk(  r; |d      } |d      }t        ||      }	t        t        j                  ||		       |dk(  r0 |d        |d      }t        t        j                  ||d
        |d        |d         t        j                  d            dkD  rrt        j                  d      y
y
w)aQ  
    Parse a single cross-reference stream and yield its entries one by one.

    This is internal API.

    :param xref_stream:
        A :class:`~generic.StreamObject`.
    :param strict:
        Boolean indicating whether we're running in strict mode.
    :return:
        A generator object yielding :class:`.XRefEntry` objects.
    /Indexr   /Size/Wc                     |    }|dkD  rRj                  |      }t        |      |k\  rt        ||      S r%t        j                  d| dt        |       d      | dk(  ryy)Nr   zBXRef stream ended prematurely; incomplete entry: expected to read z bytes, but only got .rH   )rQ   lenconvert_to_intr   r   )ixentry_widthdentry_sizesstream_datar\   s      r4   	get_entryz$parse_xref_stream.<locals>.get_entry   s     ""o?  -A1v$%a55--((3}4I1vha!  7r3   rH      )r<   r>   r=   r?   )r<   r>   r=   N)r<   r>   r?   r=   z'Trailing data in cross-reference stream)r   datagetr   	pair_iterrP   r   r   r0   r   r1   r/   rc   rQ   r   )r[   r\   	idx_pairsrj   last_endstartrU   rT   r<   r=   r?   
objstr_num
objstr_idxnext_generationrh   ri   s    `            @@r4   r!   r!      s      +**+K 1koog.F*GHI//$'K. H~~i0 *t   4<- &	C!!IA~$Q<&q\
&//%)	  a&q\
&q\
'
J?&44% 
 a !"+A,&mm.!	  !!M&		*X ;A!#%%&OPP )/#s   FFc                       e Zd Z ej                         Z ej                         Z ej                         Z ej                         Zy)r   N)	r)   r*   r+   r-   r.   r0   STREAMHYBRID_MAINHYBRID_STREAMr2   r3   r4   r   r     s6    tyy{HTYY[F$))+KDIIKMr3   r   c                   n    e Zd ZU eed<   	 eed<   	 eed<   	 eed<   	 eed<   	 eej                     ed<   y)r   xref_section_typerU   declared_startxrefstart_locationend_location
stream_refN)	r)   r*   r+   r   r:   r9   r	   r   	Referencer2   r3   r4   r   r     sX    && I  
  **++r3   r   c                       e Zd ZdZddZdeej                  ej                  f   de	ee
ef      fdZdee   defdZdee   d	edefd
Zd Zy)r   zn
    Internal class for bookkeeping on a single cross-reference section,
    independently of the others.
    c                 x    i | _         i | _        i | _        t               | _        t               | _        d | _        y N)freedstandard_xrefsxrefs_in_objstmsetexplicit_refs_in_revisionobj_streams_usedhybridselfs    r4   __init__zXRefSectionData.__init__G  s6     &(
:<8:?Bu&*-%-1r3   refr@   c                    |j                   dk(  r	 | j                  |j                     S | j                  j                  |j                  d       }|"|d   |j                   k(  r|d   S t        |      | j                  j                  |j                  d       }||j                   |dz
  k(  ry | j                  %| j                  j                  j                  |      S t        |      # t        $ r Y w xY w)Nr   rH   )
r?   r   r>   KeyErrorr   rm   r   r   	xref_datatry_resolve)r   r   std_reffreed_next_generations       r4   r   zXRefSectionData.try_resolveQ  s     >>Q++CII66 %%))#))T:qzS^^+qz!sm# $

syy$ ?
 "-"7!";;
  ;;";;((44S993-;  s   C+ +	C76C7entriesr\   c                 R   d}|D ]  }|j                   }|j                  }t        ||      }|dkD  r|rt        d| d| d      B|j                   dk(  rR|j                  t
        j                  k(  rM|j                  }t        |t              sJ ||f| j                  |<   | j                  j                  ||f       |j                  t
        j                  k(  rx|dk(  sJ |j                  }t        |t              sJ || j                  |<   | j                   j                  |j"                         | j                  j                  |df       Q|j                  t
        j$                  k(  sp|| j&                  |<   | j                  j                  ||dz
  f        |S )Nr   i  zIllegal generation z for object ID rb   rH   )r>   r?   maxr   r<   r   r0   r=   
isinstancer9   r   r   addr1   r   r   r   r7   r/   r   )	r   r   r\   
highest_id
xref_entryr>   r?   rX   locs	            r4   process_entrieszXRefSectionData.process_entries~  s   
! 	LJ$$E#..JUJ/JF",-j\ :%%*G1.  1$##x'8'88#,,!&#....8&-A##E*..22E:3FG%%)?)??!Q& ))!#|444.1$$U+%%))#*;*;<..22E1:>%%6$.

5! ..22E:>3JK;	L< r3   xref_meta_infoc                 `    t               }|j                  ||       t        ||      | _        y )Nr\   )r   r   r   r   )r   r   r   r\   r   s        r4   process_hybrid_entriesz&XRefSectionData.process_hybrid_entries  s-     !"wv6!.&9r3   c              #   n   K   | j                   j                         D ]  \  }\  }}|dkD  s||f  y w)Nr   )r   items)r   r>   r?   _s       r4   higher_generation_refsz&XRefSectionData.higher_generation_refs  s?     &*&9&9&?&?&A 	("E?JA~Z''	(s   )5	5N)r   r   )r)   r*   r+   r,   r   r   r   r   IndirectObjectr	   r9   r   r   r   r   boolr   r   r   r   r2   r3   r4   r   r   A  s    
2+ **G,B,BBC+ 	%\)*	++ Z x	':  D  D:)$: ,: 	:(r3   r   c                   (    e Zd ZU dZeed<   	 eed<   y)r   zg
    Describes a cross-reference section and describes how it is serialised into
    the PDF file.
    	meta_infor   N)r)   r*   r+   r,   r   r:   r   r2   r3   r4   r   r     s!    
 #" r3   r   re   sectionall_sectionsc                    |j                   j                  }|rT|j                  |j                  f}|| dz   d  D ]1  }|j                  }||j
                  v st        j                  d       |j                  j                  j                         D ]%  \  }}|dk(  r| dkD  rt        j                  d      | t        |      dz
  k  r_|| dz      }	|	j                  j                   |	j                  j                  j                  nd }
|
||
j                  v s||
j                  v rd }|| dz   d  D ]  }|j                  }||j                  v rd}n	 |j                  |   \  }}|dk(  s||k  r|}|B|dk(  rt        j                  d| d| d      t        j                  d| d| d	|dz
   d
       ( y # t        $ r Y Vw xY w)NrH   z9XRef stream objects must not be clobbered in strict mode.r   ztIn strict mode, a free xref with next generation 0 is onlypermitted in an initial revision due to unclear semantics.Object with id zA was listed as dead, but is reused later, with generation number rb   z and generation z was found after z was freed.)r   r~   r>   r?   r   r   r   r   r   r   rc   r   r   r   r   )re   r   r   xstream_refas_tuplesection_rl   r>   expected_next_generationnext_sectionr   improper_generationsuccrt   r   s                  r4   _check_freed_refsr     sK    ##..K%%{'='=>$R!VX. 	H%%D4999-- 	 ,3+<+<+B+B+H+H+J U''* $q(R!V))M  L!A%%'Q/L  ))00< &&--77 
 !V222 6 66 " a* !	D>>D,,,&'#)-)<)<U)C&OQ 1A5*-EE.=+ #.+q011)% 1""5!6a9  11)%0@.//@3a78E ;!	iUL   s   F;;	GGsectionsc              #   ~   K   | D ]4  }|j                   j                  |j                   j                   | 6 y wr   )r   r   )r   r   s     r4   _with_hybridsr   /  s>      ##/##***s   ;=c                 4   t        |       D ]  \  }}t        |||         t        t        |             }d}t        |      D ]D  \  }}t	        |j
                  j                               }|j                  j                  }|j                  j                  }||k  r/|t        j                  k7  rt        j                  d| d| d      t        ||      }|j                  j                  t        j                  k(  }|D ]  \  }	}
t        |d |       }|r%t!        |      }|	|j
                  j"                  v r |D ]#  }	 |j
                  j"                  |	   }||
k(  r a% t        j                  d|	 d|
 d|
dz
   d       G y # t$        $ r Y Xw xY w)	Nr   zEXRef section sizes must be nondecreasing; found XRef section of size z after section of size rb   r   z( has an orphaned generation: generation z7 was not preceded by a free instruction for generation rH   )	enumerater   listr   r   r   r   r   rU   rz   r   rx   r   r   r   reversednextr   r   )r   re   r   expanded_sections	prev_size
higher_genszr<   is_hybrid_streamr>   r?   	precedingprecrt   s                 r4   _check_xref_consistencyr   6  s    !. 5G"g|45 ]<89I !23 2G**AACD
##%%77		>i?+H+HH ))$5i[C  I&	 //?3P3PP 	 ", 	E: !23B!78I  I DNN000! &*nn&:&:5&AO&*4 5 --%eW -..8\ :"",q.!14 '	52T   s   F	F	F	c                   H    e Zd ZdZdededefdZd ZdefdZ	defd	Z
d
 Zy)r   
   handlerr\   last_startxrefc                     || _         || _        || _        || _        g | _        t               | _        t        j                  |      | j                  _	        d| _
        y )NF)r   rS   r\   r   r   r   trailerr   TrailerReferencecontainer_refhas_xref_stream)r   r   rS   r\   r   s        r4   r   zXRefBuilder.__init__z  sQ     ,+-(*%,%=%=g%F"$r3   c                    | j                   }t        || j                        \  }}t        j                  ||| j
                        }t        j                  j                  ||      }||_        |j                  d      dk(  sJ ||fS )Nr   pdf/Type/XRef)
rS   r    r\   r   r   r   StreamObjectrO   r   raw_get)r   rS   r>   r?   xrefstream_ref
xrefstreams         r4   _read_xref_stream_objectz$XRefBuilder._read_xref_stream_object  s    .vdkkJz **5*$,,O))::N

 $2
 !!'*g555z))r3   r{   c                    | j                   }|j                         }| j                         \  }}t               }|j	                  t        || j                        | j                         t        t        j                  t        |j                  d            |||j                         |      }| j                  j                  t        ||             | j                  j!                  |       |j#                  d      S )Nr   r_   rz   rU   r{   r|   r}   r~   /Prev)rS   tellr   r   r   r!   r\   r   r   rv   r9   r   r   appendr   r   add_trailer_revisionrm   )r   r{   rS   r|   r   r   xref_section_datar   s           r4   _read_xref_streamzXRefBuilder._read_xref_stream  s    %)%B%B%D"
+-))j=;; 	* 	
 --44 Z''011)%	
 	[9JKL))*5~~g&&r3   c                    | j                   }|j                         }t               }|j                  t	        |      | j
                        }|j                         }t        j                  j                  |t        j                  | j                              }t        |t        j                        sJ t        |j                  d            }| j
                  r$||k\  rt        j                  d| d|dz
   d      	 t        |j                  d            }	|	|j                         }
|j%                  |	       | j'                         \  }}t)        t*        j,                  t        |j                  d            |	|	|j                         |      }|j/                  t1        |      || j
                         |j%                  |
       t*        j2                  }nd }t*        j4                  }t)        ||||||      }| j6                  j9                  t;        ||             | j<                  j?                  |       |jA                  d	      S # t         t"        f$ r d }	Y Lw xY w)
Nr   r_   z9Xref table size mismatch: table allocated object with id z, but according to the trailer rH   z" is the maximal allowed object id./XRefStmr   r   )!rS   r   r   r   r"   r\   r   DictionaryObjectrO   r   r   r   r9   r   r   r   r   
ValueErrorrK   r   r   r   rx   r   r!   rw   r0   r   r   r   r   r   rm   )r   r{   rS   
xref_startr   highestxref_endnew_trailerdeclared_sizehybrid_xref_stm_loc
stream_posr~   r   hybrid_stream_metar<   r   s                   r4   _read_xref_tablezXRefBuilder._read_xref_table  s8   [[]
+-#33V$T[[ 4 
 ;;=..??G,,T\\:
 +w'?'?@@@K//89;;7m3))K):=1;L:M N45 	'"%k&9&9*&E"F *J
 KK+,%)%B%B%D"J
 "5"1"?"?++G45#62#[[]%" 44!*-"{{ 5 
 KK
#'33IJ'00I,'1%!!
 	[9JKL))+6w''W *% 	'"&	's   I I('I(c                 x   | j                   }| j                  x}}d}|&| j                  r|s|| j                  kD  rt	        d      |s|}|j                  |       t        j                  |      r%t        j                  d       |j                         }|j                  d      }|dk(  r6|j                  d      }|d d dk7  rt        d	      | j                  |      }n]|j                         r:|j                  d
t        j                          	 | j#                  |      }d| _        nt'        ||      }|dz  }#d}|&t+        t-        | j.                              }| j                  rt1        |       |S # t$        $ r3}t        j                  d|       t'        ||      }|dz  }Y d }~d }~ww xY w)Nr   zFailed to locate xref sectionz>Encountered unexpected whitespace when looking for xref streamrH      x      s   refzxref table read errorrB   z;Failed to read xref stream header, attempting to correct...)exc_infoT)rS   r   r\   	err_limitr   rK   r   skip_over_whitespaceloggerdebugr   rQ   r   r   isdigitrL   rM   r   r   _attempt_startxref_correctionr   r   r   r   r   )	r   rS   r{   	startxref	err_countxr   echrono_sectionss	            r4   
read_xrefszXRefBuilder.read_xrefs  s   )-)<)<<Y 	#	i$...H()HII%."KK	"((0 & #KKM	AADykk!nr7f$&'>?? 112DE	B, $ 6 67I JI (,$9&)L	Q	IS #Z x67;;#O4- - 	LL%!" !  !>fi PINI	s   E= =	F9(F44F9N)r)   r*   r+   r   r   r   r9   r   r   r   r   r   r2   r3   r4   r   r   w  sI    I%!%37%IL%	*'C '2C(3 C(J7r3   r   c                       e Zd Zy)r   N)r)   r*   r+   r2   r3   r4   r   r   *  s    r3   r   c                    d}t        j                  |        |t        j                  |       z  }t        j                  |       }t	        |      }|t        j                  |       z  }t        j                  |       }t	        |      }| j                  d       t        j                  | d       |r|rt        j                  d| d|        ||fS )NFr   T)	seek_backz.Superfluous whitespace found in object header  )	r   skip_over_commentr   read_until_whitespacer9   rQ   rJ   r   warning)rS   r\   extraidnum_bytesr>   generation_bytesr?   s          r4   _read_object_headerr  .  s    
 E6"	T&&v..E,,V4KE	T&&v..E11&9%&J
KKNVt4<gQzl$	
 *r3   c                 |    | j                         }	 t        | |      S # t        $ r}t        d|       |d }~ww xY w)Nz Failed to read object header at )r   r  r   r   )rS   r\   posr   s       r4   r    r    F  sI    
++-C"6622 #.se4
	s    	;6;c                       e Zd ZdZh dZddZdej                  fdZd Z	e
j                  dfde
fd	Zd
 Zd Zddej                  fdZd Zd Zd Zd ZddZy)r   z
    The standard mandates that each trailer shall contain
    at least all keys used in the preceding trailer, even if unmodified.
    Of course, we cannot trust documents to actually follow this rule, so
    this class implements fallbacks.
    >   /Filter/Length/DecodeParmsr`   r   r^   r   c                 D    g | _         t        j                         | _        y r   )_trailer_revisionsr   r   _new_changesr   s    r4   r   zTrailerDictionary.__init__d  s     CE#446r3   trailer_dictc                 :    | j                   j                  |       y r   )r  r   )r   r  s     r4   r   z&TrailerDictionary.add_trailer_revisionj  s    &&|4r3   c                 @    | j                  |      j                         S r   )r   
get_objectr   items     r4   __getitem__zTrailerDictionary.__getitem__m  s     ||D!,,..r3   Ndecryptc                 R   | j                   }|	 | j                  j                  ||      S t	        |      dz
  |z
  }||d  }|| j
                  v r|d   j                  ||      S |D ]  }	 |j                  ||      c S  t        |      # t        $ r Y Tw xY w# t        $ r Y >w xY w)NrH   r   )r  r  r   r   rc   non_trailer_keys)r   keyr  revision	revisionsr   s         r4   r   zTrailerDictionary.raw_getr  s     ++	((00g>>
 )nq(83G!'(+I$''' Q<''W55! 	H''W55	
 sm#    s#   B +B	BB	B&%B&c                 "    || j                   |<   y r   )r  )r   r  values      r4   __setitem__zTrailerDictionary.__setitem__  s    "'$r3   c                 d    	 | j                   |= y # t        $ r t        j                  d      w xY w)NzICannot remove existing entries from trailer dictionary, only update them.)r  r   r   PdfErrorr  s     r4   __delitem__zTrailerDictionary.__delitem__  s:    	!!$' 	-- 	s    /r@   c           
      T   | j                   }|	|| dz
  d  }t        j                  t        |      D ci c]  }|j	                         D ]  \  }}||
  c}}}      }|j                  | j                         | j                  D ]  }|j                  |d         |S c c}}}w NrH   )	r  r   r   r   r   updater  r  pop)r   r  relevant_revisionskvr   r  s          r4   flattenzTrailerDictionary.flatten  s    !44!3XIMO!D** !)); < $NN, Aq 1
 NN4,,- (( 	#CKKT"	#s   "B#c                 f    	 | j                  |t        j                         y# t        $ r Y yw xY w)N)r  TF)r   r   PROXYr   r  s     r4   __contains__zTrailerDictionary.__contains__  s3    	LL'9'?'?L@ 		s   !$ 	00c                 T    t        t        | j                  g| j                         S r   )	frozensetr   r  r  r   s    r4   keyszTrailerDictionary.keys  s#    t00K43J3JKLLr3   c                 4    t        | j                               S r   )iterr2  r   s    r4   __iter__zTrailerDictionary.__iter__  s    DIIK  r3   c                 >    | j                         j                         S r   )r,  r   r   s    r4   r   zTrailerDictionary.items  s    ||~##%%r3   c                     t        d      )Nz3TrailerDictionary object cannot be written directly)NotImplementedError)r   rS   r   r   s       r4   write_to_streamz!TrailerDictionary.write_to_stream  s    !A
 	
r3   )r   r   r   NN)r)   r*   r+   r,   r  r   r   r   r   r  r   TRANSPARENTr   r!  r$  r,  r/  r2  r5  r   r9  r2   r3   r4   r   r   P  s~    751I1I 5/ '9&D&D	 $:((@(@ (M!&
r3   r   c                     | j                  dt        j                         | j                  d      }|j	                  d      }|dk7  r|d|z
  z
  S d}| j                  ||z
         | j                  d|z        }|j                  d      }|dk7  ru| j                  ||z
  |z   d	z
         t        j                  |        | j                         }t        d      D ](  }| j                  d	      j                         s#||z   c S  t        d
      )NirC   s   xrefrB   r      rk      
rH   z/Could not find xref table at specified location)rK   rL   rM   rQ   findrfindr   r   r   rP   r   r   )rS   r   tmpxref_locxrefstm_readbacknewline_loc
line_startlooks           r4   r   r     s     KKR[[!
++b/Cxx H2~BM** 
KK	,,-
++a**
+C))E"KbI 00;>BC!!&)[[]
!H 	)D{{1~%%'!D((	) H
IIr3   c                     dk  r*t        dz
        }t        j                  d|| z         d   S t        fdt	        |       D              S )N   z>qr   c              3   @   K   | ]  \  }}|d |z
  dz
  z  z    yw)   rH   Nr2   ).0re   digitrU   s      r4   	<genexpr>z!convert_to_int.<locals>.<genexpr>  s'     Pib%534"9q=11Ps   )bytesstructunpacksumr   )rg   rU   paddings    ` r4   rd   rd     sF    qyD/}}T7Q;/22P9Q<PPPr3   c                       e Zd ZdZdee   fdZed        Zde	j                  fdZd Zde	j                  fdZd	efd
Zd	efdZd	ee	j                     fdZd	ee	j                     fdZd	efdZd	eeeef      fdZd Zed	efd       Zy)r   a/  
    Internal class to parse & store information from the xref section(s) of a
    PDF document.

    Stores both the most recent status of all xrefs in addition to their
    historical values.

    All members of this class are considered internal API and are subject
    to change without notice.
    xref_sectionsc                     || _         || _        |D ch c].  }|j                  j                  |j                  j                  0 c}| _        y c c}w r   )reader_xref_sectionsr   r~   xref_stream_refs)r   rV  rT  r   s       r4   r   zXRefCache.__init__  sQ    + )!
  ++7 ((!
 !
s   3Ac                 ,    t        | j                        S r   )rc   rW  r   s    r4   total_revisionszXRefCache.total_revisions  s    4&&''r3   r   c                     t        t        | j                              D ]=  \  }}	 |j                  j	                  |       t        | j                        dz
  |z
  c S  t        |      # t        $ r Y Vw xY wr&  )r   r   rW  r   r   rc   r   )r   r   re   r   s       r4   get_last_changezXRefCache.get_last_change
  sy    $Xd.A.A%BC 	KB!!--c24../!3b88	 sm  s   5A**	A65A6c                     | j                   |   }|j                  j                  D ch c]#  }t        j                  || j
                        % c}S c c}w )Nr   )rW  r   r   r   r   rV  )r   r  r   	objstm_ids       r4   object_streams_used_inz XRefCache.object_streams_used_in  sQ    %%h/ %..??
 iT[[9
 	
 
s   (Ac                     t        | j                        D ]'  \  }}	 |j                  j                  |      }||c S ) t	        |      # t        $ r Y @w xY wr   )r   rW  r   r   r   )r   r   re   r   results        r4   get_introducing_revisionz"XRefCache.get_introducing_revision  sk    $T%8%89 	KB **66s;%I &	 sm  s   A	AAr@   c                 8    | j                   |   }|j                  S r   )rW  r   r   r  r   s      r4   get_xref_container_infoz!XRefCache.get_xref_container_info&      %%h/   r3   c                 8    | j                   |   }|j                  S r   )rW  r   rd  s      r4   get_xref_datazXRefCache.get_xref_data*  rf  r3   c           
         | j                   |   }|j                  j                  D ch c]'  \  }}t        j                  ||| j
                        ) }}}|j                  j                  }|L||j                  j                  D ch c]'  \  }}t        j                  ||| j
                        ) c}}z  }|S c c}}w c c}}w )a  
        Look up the object refs for all objects explicitly added or overwritten
        in a given revision.

        :param revision:
            A revision number. The oldest revision is zero.
        :return:
            A set of Reference objects.
        r   )rW  r   r   r   r   rV  r   )r   r  r   r>   r?   ra  r   s          r4   r   z#XRefCache.explicit_refs_in_revision.  s     %%h/ &-%6%6%P%P
!z eZT[[A
 
 "")))/)9)9)S)S%E: !!%E F 
s   ,B>
,Cc           	          | j                   |   }|j                  j                  j                         D ch c]/  \  }}|dkD  r%t	        j
                  ||dz
  | j                        1 c}}S c c}}w )z
        Look up the object refs for all objects explicitly freed
        in a given revision.

        :param revision:
            A revision number. The oldest revision is zero.
        :return:
            A set of Reference objects.
        r   rH   r   )rW  r   r   r   r   r   rV  )r   r  r   r>   gens        r4   refs_freed_in_revisionz XRefCache.refs_freed_in_revisionF  sm     %%h/ &//55;;=
sQw eS1W$++>
 	
 
s   4A/c                 L    | j                   |   }|j                  j                  S )a  
        Look up the location of the XRef table/stream associated with a specific
        revision, as indicated by startxref or /Prev.

        :param revision:
            A revision number. The oldest revision is zero.
        :return:
            An integer pointer
        )rW  r   r{   rd  s      r4   get_startxref_for_revisionz$XRefCache.get_startxref_for_revisionW  s&     %%h/  333r3   c                     t        | j                  d|dz          D ]!  }	 |j                  j                  |      }|c S  y# t        $ r Y 0w xY w)ab  
        Look up the location of the historical value of an object.

        .. note::
            This method is not suitable for determining whether or not
            a particular object ID is available in a given revision, since
            it treats unused objects and freed objects the same way.

        :param ref:
            An object reference.
        :param revision:
            A revision number. The oldest revision is zero.
        :return:
            An integer offset, an object stream reference, or ``None`` if
            the reference does not resolve in the specified revision.
        NrH   )r   rW  r   r   r   )r   r   r  r   ra  s        r4   get_historical_refzXRefCache.get_historical_refd  sb    &   3 3Nhl CD 	G **66s;	   s   A	AAc                 R    | j                  |t        | j                        dz
        S r&  )rp  rc   rW  )r   r   s     r4   r  zXRefCache.__getitem__  s'     &&sC0C0C,Dq,HIIr3   c                 :    t        d | j                  D              S )z
        Determine if a file uses hybrid references anywhere.

        :return:
            ``True`` if hybrid references were detected, ``False`` otherwise.
        c              3   j   K   | ]+  }|j                   j                  t        j                  k(   - y wr   )r   rz   r   rw   )rK  r   s     r4   rM  z1XRefCache.hybrid_xrefs_present.<locals>.<genexpr>  s/      
 //?3N3NN
s   13)anyrW  r   s    r4   hybrid_xrefs_presentzXRefCache.hybrid_xrefs_present  s$      
..
 
 	
r3   N)r)   r*   r+   r,   r   r   r   propertyrZ  r   r   r\  r_  rb  r   re  r   rh  r
   r   rl  r9   rn  r	   r   r   rp  r  r   ru  r2   r3   r4   r   r     s    	
d;.? 
 ( (7#4#4 
	G,=,= 	!3F !! !S9J9J5K 0
#g6G6G2H 
"4c 4	%\)*	+8J
 

d 

 

r3   r   c                   h    e Zd ZdZddZd Zd Zdedej                  fdZ
dej                  fd	Zy
)r$   u  
    Utility class to collect objects into a PDF object stream.

    Object streams are mainly useful for space efficiency reasons.
    They allow related objects to be grouped & compressed together in a
    more flexible manner.


    .. warning::
        Object streams can only be used in files with a cross-reference
        stream, as opposed to a classical XRef table.
        In particular, this means that incremental updates to files with a
        legacy XRef table cannot contain object streams either.
        See § 7.5.7 in ISO 32000-1 for further details.

    .. danger::
        Use :meth:`.BasePdfFileWriter.prepare_object_stream` to create instances
        of object streams. The `__init__` function is internal API.

    c                 .    i | _         || _        d | _        y r   )	_obj_refscompressr   )r   rz  s     r4   r   zObjectStream.__init__  s     r3   c                 ,    t        | j                        S r   )r   ry  r   s    r4   __bool__zObjectStream.__bool__  s    DNN##r3   c                 H    t        | j                  j                               S r   )r4  ry  r   r   s    r4   r5  zObjectStream.__iter__  s    DNN((*++r3   r>   objc                 X    t        |t              rt        d      || j                  |<   y)a  
        Add an object to an object stream.
        Note that objects in object streams always have their generation number
        set to `0` by definition.

        :param idnum:
            The object's ID number.
        :param obj:
            The object to embed into the object stream.
        :raise TypeError:
            Raised if ``obj`` is an instance of :class:`~.generic.StreamObject`
            or :class:`~.generic.IndirectObject`.
        zJStream objects and bare references cannot be embedded into object streams.N)r   r&   	TypeErrorry  )r   r>   r~  s      r4   
add_objectzObjectStream.add_object  s1     c./"  !$ur3   r@   c           
         t               }t               }| j                  j                         D ]=  \  }}|j                         }|j	                  |d       |j                  d||fz         ? |j                         }|j                  d       |j                  |      }||j                         z   }t        j                  t        d      t        d      t        d      t        j                  t        | j                              t        d      t        j                  |      i|      }	| j                  r|	j                          |	S )	z
        Render the object stream to a PDF stream object

        :return: An instance of :class:`~.generic.StreamObject`.
        Ns   %d %d r   r   z/ObjStmz/Nz/First)ri   )r   ry  r   r   r9  writerK   rQ   getvaluer   r   r   rN   rc   rz  )
r   stream_header	main_bodyr>   r~  rX   first_obj_offsetsh_bytesri   stream_objects
             r4   as_pdf_objectzObjectStream.as_pdf_object  s     	I	....0 	=JE3^^%F	40	UFO ;<	=
 )--/1 %%&67!3!3!55,,!8I#6 4 4S5H I"G$8$89I$J
 $
 ==""$r3   NT)r)   r*   r+   r,   r   r|  r5  r9   r   	PdfObjectr  r   r  r2   r3   r4   r$   r$     sA    *
$,$ $'*;*; $,w33 r3   r$   c              #     K   d}g }| j                         syt        | j                         d       }t        |      \  \  }}}|D ]3  }|\  }}|r||dz   k7  r
||f g }|}|j                  | |   |f       |}5 ||f yw)zT
    Helper method to divide the XRef table (or stream) into contiguous chunks.
    Nc                     | d   S r&  r2   )ts    r4   <lambda>z)_contiguous_xref_chunks.<locals>.<lambda>  s
    !A$ r3   )r  rH   )r2  sortedr   r   )	position_dictprevious_idnumcurrent_chunkkey_iterr   first_idnumre   r?   r>   s	            r4   _contiguous_xref_chunksr    s      NM m((*?H!%hQh 
E Unq&88},,MK 	mB/<=  }
$$s   BBr  c                      j                         } j                  d       t        |      } fd} fd}	 t        |      \  }}d}|dk(  r/ |dt        |      dz           j                  |        ||       n< j                  d        j                  |        ||t        |              ||       |D ]  \  }} ||t        |              ||       ! |S # t        $ r  j                  d       |cY S w xY w)	Ns   xref
c                 T    d| |fz  }j                  |j                  d             y )Nz%d %d
asciir  encode)r>   lengthheaderrS   s      r4   write_headerz&write_xref_table.<locals>.write_header  s&    eV_,V]]7+,r3   c                 h    | D ],  \  }}d||fz  }j                  |j                  d             . y )Nz%010d %05d n 
r  r  )chunkpositionr?   entryrS   s       r4   write_subsectionz*write_xref_table.<locals>.write_subsection   s;    $) 	0 Hj%:(>>ELLg./	0r3   s   0 0
s   0000000000 65535 f 
rH   r   s   0 1
)r   r  r  r   StopIterationrc   )	rS   r  xref_locationsubsectionsr  r  r  
subsectionnull_obj_refs	   `        r4   r#   r#     s    KKMM
LL
 *-8K-0
"&{"3Z ,LaQJ!+,\"$ 	X\"[#j/2$#. %Z[#j/2$%
 5  Xs   C C>=C>c                   0     e Zd Zdef fdZd fd	Z xZS )r%   r  c                     t         |           || _        t        t        j
                  d      }| j                  t        d      t	        j                  |      t        d      t        d      i       y )N)rH   rH  rk   r`   r   r   )	superr   r  mapr   rN   r'  r   ArrayObject)r   r  widths	__class__s      r4   r   zXRefStream.__init__E  s^    *
 W))95 3 3F ;!8G#4	
r3   c                    ddg}t        | j                        }t               }|j                  d       |D ]  \  }}||t	        |      gz  }|D ]  \  }	}
t        |	t              rh|
dk(  sJ |	\  }}|j                  d       |j                  t        j                  d|             |j                  t        j                  d|             ~|j                  d       |j                  t        j                  d|	             |j                  t        j                  d|
               t        j                  t        t        j                  |            }|| t        d      <   |j                         | _        t         | E  |d        y )	Nr   rH   s               z>Qz>H   r^   )r  r  r   r  rc   r   tuplerO  packr   r  r  rN   r   	getbuffer_datar  r9  )r   rS   r   r   indexr  stream_contentr  r  r  r?   obj_stream_numre   index_entryr  s                 r4   r9  zXRefStream.write_to_streamT  s`    A-d.@.@A 67'2 	H#Kk3z?33E(2 H$*h.%?*?)1&NB"((1"((T>)JK"((T2)>?"((1"((T8)DE"((T:)FGH	H ))#g.B.BE*JK#.Xh #--/
-r3   r:  )r)   r*   r+   r'   r   r9  __classcell__)r  s   @r4   r%   r%   D  s    
l 
. .r3   r%   r  )Dr,   r-   loggingrL   rO  dataclassesr   ior   	itertoolsr   typingr   r   r   r	   r
   r   r   pyhanko.pdf_utilsr   r   pyhanko.pdf_utils.genericr   r   pyhanko.pdf_utils.miscr   r   r   pyhanko.pdf_utils.rw_commonr   __all__	getLoggerr)   r   uniqueEnumr   r   r   r"   r   r   r!   r   r   r   r   r9   r   r   r   r   r   r  r    r  r   r   rd   r   r'   r   r&   r$   r  r#   r%   r2   r3   r4   <module>r     s     	  !   D D D + B I I 2, 
		8	$ tyy  * $    $  4E) 3 E)R 7;[Q%%[Q/3[Qi[Q|  dii     $  Bl( l(^ $  "jj!j15k1BjZD- >${*; >Bp pf	D-- 	0s
)) s
lJ:Qe
 e
P E#s(OU3c3h+?%@@A --w/C/CD R Rj%B.DsCx#1E,F .b+.%% +.r3   