
    WwgH              
           d Z ddlZddlmZ ddl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 dd	lmZ dd
lmZmZmZmZ ddlmZmZmZ ddl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)  ejT                  e+      Z,g dZ-defdZ.de
j^                  de
j^                  fdZ0 G d de      Z1 e1 e        e#       je                  ejf                         e       je                  ejf                         e       je                  ejf                         e       je                  ejf                         e$       je                  ejf                        g e e         e!        e       g            Z4	  e1g d      Z5y)zF
Module defining pyHanko's standard difference policy implementation.
    N)defaultdict)IteratorListOptionalUnion)genericmisc)HistoricalResolverPdfFileReader)FieldMDPSpecMDPPerm   )FormUpdatingRule)
DiffPolicy
DiffResultModificationLevelSuspiciousModification)CatalogModificationRuleObjectStreamRuleXrefStreamRule)DSSCompareRuleGenericFieldModificationRuleSigFieldCreationRuleSigFieldModificationRule)DocInfoRuleMetadataUpdateRule)ApprovalTypeContextQualifiedWhitelistRuleReferenceUpdate)StandardDiffPolicyDEFAULT_DIFF_POLICYNO_CHANGES_DIFF_POLICYhist_revc                      j                         } j                  j                   j                  dz
        }t	               t	               }|D ]6  }|j                  |      r|j                  |       &j                  |       8 dt        t        j                     f fd} |       }|r/	 t        |      }| j                  | j                        z  }|r/|S # t        $ r Y |S w xY w)za
    Within a revision, find new refs that can't be reached from refs in the
    older ones.
    r   returnc               3   L   K   j                    D ]  }  |         y wN)trailer_view)_refr$   updated_old_refss    Z/var/www/horilla/myenv/lib/python3.12/site-packages/pyhanko/sign/diff_analysis/policies.py_objs_to_checkz%_find_orphans.<locals>._objs_to_checkR   s,     ###$ 	!D4. 	!s   !$)since_revision)explicit_refs_in_revisionreaderget_historical_resolverrevisionsetis_ref_availableaddr   r   	PdfObjectnextStopIterationcollect_dependencies)	r$   new_refspreviouscandidate_orphansrefr-   obj_iterobjr+   s	   `       @r,   _find_orphansr@   1   s   " 113H66x7H7H17LMH u &$$S)!!#&  %&!HW%6%67 ! H
	x.C 	X:: 1 1 ; 
 	
    	 	s   2C" "	C/.C/
old_object
new_objectc                 $    t         j                  t         j                  t         j                  t         j                  t         j
                  t         j                  f}|D ]#  }t         |      st        |      xr  k(  c S  t         j                  t         j                  f}t         |      r't        |      xr  j                  j                  k(  S t         t         j                        rQt        t         j                        xr5 t              t               k(  xr t        d t               D              S t         t         j                        r4t        t         j                        rj                    j                   k(  syt         t         j"                        r_t        t         j"                        r!j%                          j%                         k(  syt         fdj%                         D              S t&        )Nc              3   :   K   | ]  \  }}t        ||        y wr(   )_is_id).0xys      r,   	<genexpr>z_is_id.<locals>.<genexpr>}   s     ITQF1aLIs   Fc              3   r   K   | ].  }t        j                  |      j                  |             0 y wr(   )rE   raw_get)rF   krB   rA   s     r,   rI   z_is_id.<locals>.<genexpr>   s6      
 :%%a(**<*<Q*?@
s   47)r   NumberObjectFloatObjectBooleanObject
NameObject
NullObjectIndirectObject
isinstanceTextStringObjectByteStringObjectoriginal_bytesArrayObjectlenallzipStreamObjectencoded_dataDictionaryObjectkeysNotImplementedError)rA   rB   
primitivesprimstringss   ``   r,   rE   rE   e   s   J  Mj$'j$/LJ*4LLM '')A)ABG*g&z7+ G))Z-F-FF	

 *g112z7#6#67 JJ3z?2JISZ-HII	
 *g223 z7#7#78'':+B+BB*g667z7#;#;<!Z__%66 
__&
 
 	
     c                       e Zd ZdZ	 	 	 ddee   dee   fdZ	 	 dde	de	dee
   d	ee   d
ef
dZ	 	 ddedeee	f   dee
   d	ee   d
eeef   f
dZy)r!   a  
    Run a list of rules to analyse the differences between two revisions.

    :param global_rules:
        The :class:`.QualifiedWhitelistRule` objects encoding the rules to
        apply.
    :param form_rule:
        The :class:`.FormUpdatingRule` that adjudicates changes to form fields
        and their values.
    :param reject_object_freeing:
        Always fail revisions that free objects that existed prior to signing.

        .. note::
            PyHanko resolves freed references to the ``null`` object in PDF,
            and a freeing instruction in a cross-reference section is
            always registered as a change that needs to be approved, regardless
            of the value of this setting.

            It is theoretically possible for a rule to permit deleting content,
            in which case allowing objects to be freed might be reasonable.
            That said, pyHanko takes the conservative default position to reject
            all object freeing instructions as suspect.
    :param ignore_orphaned_objects:
        Some PDF writers create objects that aren't used anywhere (tsk tsk).
        Since those don't affect the "actual" document content, they can usually
        be ignored. If ``True``, newly created orphaned objects will be
        cleared at level :attr:`.ModificationLevel.LTA_UPDATES`.
        Default is ``True``.
    :param ignore_orphaned_objects:
        Some PDF writers overwrite objects with identical copies.
        Pointless and annoying, but also more or less harmless.
    global_rules	form_rulec                 J    || _         || _        || _        || _        || _        y r(   )re   rf   reject_object_freeingignore_orphaned_objectsignore_identical_objects)selfre   rf   rh   ri   rj   s         r,   __init__zStandardDiffPolicy.__init__   s+     )"%:"'>$(@%rc   Noldnewfield_mdp_specdoc_mdpr&   c                 (   |t         j                  k(  rt        j                  d       | j                  r!j                         }|rt        d| d      j                         t        t              fd}| j                  r2t              D ]$  }t        j                     j                  |       & t         |             dt        dt         ffd}| j"                  D ]%  }	|	j%                        D ]  \  }
} ||
|        ' t               }| j&                  r| j&                  j)                        }fd}|D ]  \  }
} ||
|       |j*                  }|A|j,                  s5 ||      rt        d	|j.                   d
| d      |j                  |       |a|j0                  rnt        d	|j.                   d       t        j                     z
  }|t        j2                     z
  }|t        j4                     z
  }j6                  j8                  | j:                  r}t        fd|D              }|ret        j=                  dj>                   dj>                   d|        |jA                  |       |jA                  |       |jA                  |       |rtC        jD                  dd |D              }t        j=                  dj>                  |       jG                         D cg c]2  \  }\  }}|r(dtI        |       ddjK                  d |D               d4 }}}}dj>                   ddjK                  d |D               d}|rKdj>                   dj>                   ddjK                  |      z   }|d|}t        j=                  |       t        |      |rt        j4                  }
n#|rt        j2                  }
nt        j                  }
tM        |
|       S c c}}}w )!NzzStandardDiffPolicy was not designed to support DocMDP level 3 (MDPPerm.ANNOTATE). Unexpected validation results may occur.z	The refs zn were freed in the revision provided. The configured difference analysis policy does not allow object freeing.c               3      K   j                          D ]O  } j                  |       }|s|D ch c]  }t        j                  |       }}| t        j
                  |ff Q y c c}w wr(   )_load_reverse_xref_cache_get_usages_of_refr   from_absoluter   NONE)new_refusagespcontexts	new_xrefsrm   s       r,   _init_multi_lutz1StandardDiffPolicy.apply.<locals>._init_multi_lut   st     ((*$ F//8GMN! 5 5c1 =NHN!$5$:$:H#EEE	F  Os   )A.A.A) A._level_updc                    j                   }	 |   \  }}j                  }|t        j                  k(  rt	               }nC|t        j
                  k(  rt	        fd|D              }n|j                  j                         t        ||       } | |f|<   |ry 	 |    j                  |       y # t        $ r Y  w xY w)Nc              3   T   K   | ]  }|j                   j                  k7  r| ! y wr(   )relative_viewcontext_checked)rF   ctxr~   s     r,   rI   z?StandardDiffPolicy.apply.<locals>.ingest_ref.<locals>.<genexpr>  s-      !,,0D0DD !s   %()updated_refapproval_typer   BLANKET_APPROVEr3   APPROVE_RELATIVE_CONTEXTdiscardr   maxKeyErrorr5   )r}   r~   r=   current_max_levelrx   upd_type	explainedold_usages_to_clears    `    r,   
ingest_refz,StandardDiffPolicy.apply.<locals>.ingest_ref   s    ""C,?,D)!6--|;;; UF!F!FF ! !#)! F NN4#7#78.7+16>#C(   f!!#&  s   B
B1 1	B=<B=c                 2    d uxr j                  |       S r(   )	is_locked)fq_namero   s    r,   r   z+StandardDiffPolicy.apply.<locals>.is_locked!  s%    %T1 n6N6N7 rc   z
Update of z' is not allowed because the form field z is locked.zL is only allowed after an approval signature, not a certification signature.c              3      K   | ];  }j                  |j                        	 t         |       |            r| = y wr(   )get_historical_refr2   rE   )rF   unex_refrn   rm   
xref_caches     r,   rI   z+StandardDiffPolicy.apply.<locals>.<genexpr>A  sG      !003<<H3x=#h-8	 !s   AAz5Found identical overridden objects between revisions  and z+; following no-op changes will be ignored: 
c              3   r   K   | ]/  }t        |      d t        |j                               dd d 1 yw):Ni,  z...)repr
get_objectrF   rG   s     r,   rI   z+StandardDiffPolicy.apply.<locals>.<genexpr>U  s3       #'q'4+?+EFs   57z$Unexplained xrefs in revision %d:
%sz - z is also used in z, c              3   2   K   | ]  }t        |        y wr(   )str)rF   ry   s     r,   rI   z+StandardDiffPolicy.apply.<locals>.<genexpr>_  s     =SV=   z in the prior revision.z(There are unexplained xrefs in revision z: c              3   2   K   | ]  }t        |        y wr(   )r   r   s     r,   rI   z+StandardDiffPolicy.apply.<locals>.<genexpr>f  s     @T!W@r   .zSome objects from revision z were replaced in revision z  without precise justification:
)modification_levelchanged_form_fields)'r   ANNOTATEloggerwarningrh   refs_freed_in_revisionr   r/   r   r3   ri   r@   r   LTA_UPDATESr5   dictr    re   apply_qualifiedrf   apply
field_namevalid_when_lockedr   valid_when_certifyingFORM_FILLINGANNOTATIONSr0   xrefsrj   debugr2   difference_updater	   LazyJoinitemsr   joinr   ) rk   rm   rn   ro   rp   freedr|   r*   r   rulelevelupdr   form_changesr   fur   unexplained_ltaunexplained_formfillunexplained_annotidentical_objsmsgr=   _paths_remainingunexplained_overrideserr_msgunchecked_paths_msgr   r{   r   r   s     ```                        @@@@r,   r   zStandardDiffPolicy.apply   sN    g&&&NN% %%..0E,w '& &  113	$	
	F ''%c* C+778<<TBC #?#45	'0 	' 	'@ %% 	'D"223< '
s5#&'	' "e>>>>//S9L
 * 	r5"%]]
)"2F2F ,4((8 966@\N  (++J7&r/G/G0$R^^$4 5% & " $i0A0M0M&NNi(9(F(FGG 	 !9->-J-J#KK 	 ZZ%%
((  ! /! N K||nE#,, 800>/?A
 "33NC$66~F11.A--.C LL7s 2E1J1J1L	% % .C-!_"	 d3i[ 199=_==> ?%! % ;3<<.99@.?@@AD  %1#,, @##&<<. 1'')-3H)IJ $
 './BC01(11!%11E%22E%11E$:M
 	
9%s   7Pr0   base_revisionc                    t               }|j                  j                  }t        j                  }t        |t              r|j                  |      }|}	n|}|j                  }	t        |	dz   |      D ]L  }
	 | j                  ||j                  |
      ||      }t        ||j                        }||j                   z  }N t#        ||      S # t        $ r+}t        j                  d|	 d|
 |       |cY d}~c S d}~ww xY w)z
        Implementation of :meth:`.DiffPolicy.review_file` that reviews
        each intermediate revision between the base revision and the current one
        individually.
        r   )rm   rn   ro   rp   z)Error in diff operation between revision r   )exc_infoN)r3   r   total_revisionsr   rv   rS   intr1   r2   ranger   r   r   r   r   r   r   r   )rk   r0   r   ro   rp   r   	rev_countcurrent_maxbase_rev_resolverbase_revision_nor2   diff_resultes                r,   review_filezStandardDiffPolicy.review_file}  s    "eLL00	',,mS) & > >} M, -099" .2I> 	CH"jj)66x@#1#	 )  k;+I+IJK;#B#BB!	C" +':;; * ?'(hZ9  
 s   6$C	DC<4D<D)TTT)NN)__name__
__module____qualname____doc__r   r   r   r   rl   r
   r   r   r   r   r   r   r   r   r    rc   r,   r!   r!      s    J # $!%A12A ,-A$ 26%)v
v
  v
 !.	v

 '"v
 
v
x 26%)8<8< S"4458< !.	8<
 '"8< 
z11	28<rc   r!   )field_rules)re   rf   )6r   loggingcollectionsr   typingr   r   r   r   pyhanko.pdf_utilsr   r	   pyhanko.pdf_utils.readerr
   r   pyhanko.sign.fieldsr   r   form_rules_apir   
policy_apir   r   r   r   rules.file_structure_rulesr   r   r   rules.form_field_rulesr   r   r   r   rules.metadata_rulesr   r   	rules_apir   r   r   r    	getLoggerr   r   __all__r@   r6   rE   r!   as_qualifiedr   r"   r#   r   rc   r,   <module>r      ss    # 2 2 + F 5 ,  
  B  
		8	$1. 1h-w(( -g6G6G -``< `<F	 )!""#4#@#@A%%&7&C&CD''(9(E(EF%%&7&C&CD))*;*G*GH  "$&(*
 "* ,tL rc   