
    Wwg                     `   d Z ddl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 ddlmZmZ dd	lmZ  ej.                  e      Zg d
Zeeej                     eej                     f   Zd Zdedeeddf   fdZdedej<                  dej<                  deedef   fdZ e	dd      Z  e	dd      Z! e	de      Z" e	ded      Z#dedee"de f   deeee"f   de f   fdZ$dedee!de f   dee!ge#f   deeee#f   de f   fdZ% e&       dfdee   dee   d ee'   de(fd!Z)y)"z
Module defining common helpers for use by rules and policies.

In principle, these aren't relevant to the high-level validation API.
    N)Callable	FrozenSet	GeneratorOptionalSetTupleTypeVar)genericmisc)	PdfObject	Reference)HistoricalResolver   )ModificationLevelSuspiciousModification)ReferenceUpdate)qualifyqualify_transformingsafe_whitelistcompare_key_refscompare_dictsassert_not_streamc                 j    t        | t        j                        rt        d| j                   d      y)zT
    Throw :class:`.SuspiciousModification` if the argument is a stream object.
    z!Unexpected stream encountered at !N)
isinstancer
   StreamObjectr   container_ref)objs    Y/var/www/horilla/myenv/lib/python3.12/site-packages/pyhanko/sign/diff_analysis/commons.pyr   r      s9     #w++,$/0A0A/B!D
 	
 -    oldreturnc              #      K   |rt        |j                                ||k(  rt        |j                                | y| j                  |      r| yt        d| d      w)a~  
    Checks whether an indirect reference in a PDF structure
    can be updated without clobbering an older object in a way
    that causes ramifications at the PDF syntax level.

    The following are verified:

     - Does the old reference point to a non-stream object?
     - If the new reference is equal to the old one, does the new reference point
       to a non-stream object?
     - If the new reference is not equal to the old one,
       is the new reference a newly defined object?

    This is a generator for syntactical convenience and integration
    with internal APIs, but it will always yield at most one element.
    zUpdate clobbers or reuses z in an unexpected way.N)r   
get_objectis_ref_availabler   )r!   old_refnew_refs      r   r   r   )   sg     ( ',,./'',,./			g	&$(	1GH
 	
s   A$A&old_dictnew_dictc              #     K   	 |j                  |       }t        |t        j                        r|j                  }|j                         }nd}	 |j                  |       }t        |t        j                        r|j                  }|j                         }nd}|t        |||      E d{    ||fS # t        $ r dx}}Y uw xY w# t        $ r |t        d|  d      Y yw xY w7 ;w)a  
    Ensure that updating a key in a dictionary has no undesirable side effects.
    The following scenarios are allowed:

    0. replacing a direct value with another direct value
    1. adding a key in new_dict
    2. replacing a direct value in old_dict with a reference in new_dict
    3. the reverse (allowed by default)
    4. replacing a reference with another reference (that doesn't override
       anything else)

    The restrictions of `safe_whitelist` apply to this function as well.

    Note: this routine is only safe to use if the structure of the resulting
    values is also checked. Otherwise, it can lead to reference leaks if
    one is not careful.
    NzKey z was deleted from dictionary)NN)	raw_getr   r
   IndirectObject	referencer$   KeyErrorr   r   )keyr!   r(   r)   	old_valueold_value_ref	new_valuenew_value_refs           r   r   r   K   s    0)$$S)	i!7!78%//M!,,.I M$$S)	i!7!78%//M!,,.I M  !#}mDDDi)  )$((	)   (se78   	EsT   C)A
B4 A
C C)+C',C)4CC)CC)C$!C)#C$$C)RT)	covariant	QualifyIn)contravariantRefToUpd)bound	OutRefUpd)r9   r5   levelrule_resultc                      t        | |d       S )a  
    This is a helper function for rule implementors.
    It attaches a fixed modification level to an existing reference update
    generator, respecting the original generator's return value (if relevant).

    A prototypical use would be of the following form:

    .. code-block:: python

        def some_generator_function():
            # do stuff
            for ref in some_list:
                # do stuff
                yield ref

            # do more stuff
            return summary_value

        # ...

        def some_qualified_generator_function():
            summary_value = yield from qualify(
                ModificationLevel.FORM_FILLING,
                some_generator_function()
            )

    Provided that ``some_generator_function`` yields
    :class:`~.generic.ReferenceUpdate` objects, the yield type of the resulting
    generator will be tuples of the form ``(level, ref)``.

    :param level:
        The modification level to set.
    :param rule_result:
        A generator that outputs references to be whitelisted.
    :return:
        A converted generator that outputs references qualified at the
        modification level specified.
    c                     | S N )xs    r   <lambda>zqualify.<locals>.<lambda>   s     r    )	transform)r   )r;   r<   s     r   r   r      s    T  {kJJr    rC   c                 :     t        j                  | fd      S )a  
    This is a version of :func:`.qualify` that additionally allows
    a transformation to be applied to the output of the rule.

    :param level:
        The modification level to set.
    :param rule_result:
        A generator that outputs references to be whitelisted.
    :param transform:
        Function to apply to the reference object before appending
        the modification level and yielding it.
    :return:
        A converted generator that outputs references qualified at the
        modification level specified.
    c                      |       fS r?   r@   )refr;   rC   s    r   rB   z&qualify_transforming.<locals>.<lambda>   s    %3!8 r    )r   map_with_return)r;   r<   rC   s   ` `r   r   r      s    ( 8 r    ignoredc           	         t        | t        j                        st        j                  d      t        |t        j                        st        d      t        |        t        |       t        |j                               |z
  }t        | j                               |z
  }||k7  r|rt        d| d| d      y|D ]A  }|j                  |      }| j                  |      }||k7  s+|rt        d| d| d	|        y y
)zP
    Compare entries in two dictionaries, optionally ignoring certain keys.
    z?Encountered unexpected non-dictionary object in prior revision.z.Dict is overridden by non-dict in new revisionzDict keys differ: z vs. .FzValues for dict key z differ:z changed to T)
r   r
   DictionaryObjectr   PdfReadErrorr   r   setkeysr+   )	r(   r)   rH   	raise_excnew_dict_keysold_dict_keysknew_valold_vals	            r   r   r      s!    h 8 89M
 	
 h 8 89$<
 	
 hh(72M(72M%($]O5]O1M   
""1%""1%g,*1#Xi|G96 
 
 r    )*__doc__loggingtypingr   r   r   r   r   r   r	   pyhanko.pdf_utilsr
   r   pyhanko.pdf_utils.genericr   r   pyhanko.pdf_utils.readerr   
policy_apir   r   	rules_apir   	getLogger__name__logger__all__TwoVersionsr   r   rK   r   r4   r6   r8   r:   r   r   	frozensetstrboolr   r@   r    r   <module>re      s    P P P + : 7 A &			8	$ HW../':K:K1LLM

	
y$$%
D3 	3  &&3  &&	3 
 y$+,3 l C4 Kt4	:_5K$G	*K*K8T1,-*K u&014:;*KZ9dA-. Y./ u&	12D!;<	8 (k	+y!+y!+ s^+
 
+r    