
     h                        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)dS )"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          dS )zT
    Throw :class:`.SuspiciousModification` if the argument is a stream object.
    z!Unexpected stream encountered at !N)
isinstancer
   StreamObjectr   container_ref)objs    ^/var/www/html/Sam_Eipo/venv/lib/python3.11/site-packages/pyhanko/sign/diff_analysis/commons.pyr   r       sF     #w+,, 
$D0ADDD
 
 	

 
    oldreturnc              #     K   |r!t          |                                           ||k    r't          |                                           |V  dS |                     |          r|V  dS t          d| d          )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   *   s      (  0',,..///'',,..///			g	&	& 
$HHHH
 
 	
r    old_dictnew_dictc              #     K   	 |                     |           }t          |t          j                  r|j        }|                                }nd}n# t          $ r dx}}Y nw xY w	 |                     |           }t          |t          j                  r|j        }|                                }nd}n&# t          $ r |t          d|  d          Y dS w xY w|t          |||          E d{V  ||fS )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   L   sL     0)$$S))	i!788 	!%/M!,,..II M ) ) )$((			)$$S))	i!788 	!%/M!,,..II M    (8s888   zz  !#}mDDDDDDDDDis%   AA A#"A#'AB5 5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  {kkJJJJr    rC   c                 8     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8888  r    ignoredc           	      d   t          | t          j                  st          j        d          t          |t          j                  st          d          t          |            t          |           t          |                                          |z
  }t          |                                           |z
  }||k    r|rt          d| d| d          dS |D ]O}|	                    |          }| 	                    |          }||k    r|rt          d| d| d	|            dS Pd
S )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99 
M
 
 	
 h 899 
$<
 
 	
 hh((72M((72M%% 	(M]MM]MMM   5 
 
""1%%""1%%g ,61 6 66 6,36 6  
 uu  4r    )*__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 P P P P P P P P P P P P P P P + + + + + + + + : : : : : : : : 7 7 7 7 7 7 A A A A A A A A & & & & & &		8	$	$   HW./':K1LLM
 
 

	
y$$%
 
 
 
D3 	3  &3  &	3 
 y$+,3  3  3  3 l GC4   GKt444	7:_555GK$GGG	*K*K8T1,-*K u&014:;*K *K *K *KZ9dA-. Y./ u&	12D!;<	   8 (ikk	+ +y!+y!+ s^+
 
+ + + + + +r    