U
    gs                     @   s   d dl mZ d dl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 ddlmZmZmZ d	d
gZG dd	 d	eZG dd
 d
eZdS )    )BytesIO)Iterable)genericmisc)HistoricalResolver
RawPdfPath   )safe_whitelist)SuspiciousModification)ContextReferenceUpdateWhitelistRuleDocInfoRuleMetadataUpdateRulec                   @   s&   e Zd ZdZeeee dddZdS )r   zQ
    Rule that allows the ``/Info`` dictionary in the trailer to be updated.
    oldnewreturnc                 c   s\   |j jddd}|d krd S |j jddd}ttjt|tddt|||E d H  d S )Nz/InfoT)optionalZcontext_checked)	Ztrailer_viewget_value_as_referencemapr   Z	curry_refr   from_absoluter   r	   )selfr   r   Znew_infoZold_info r   S/tmp/pip-unpacked-wheel-owvgwkas/pyhanko/sign/diff_analysis/rules/metadata_rules.pyapply   s       
zDocInfoRule.applyN)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   r      s
    c                   @   sD   e Zd ZdZdddZeejdddZe	e	e
e d	d
dZdS )r   a  
    Rule to adjudicate updates to the XMP metadata stream.

    The content of the metadata isn't actually validated in any significant way;
    this class only checks whether the XML is well-formed.

    :param check_xml_syntax:
        Do a well-formedness check on the XML syntax. Default ``True``.
    :param always_refuse_stream_override:
        Always refuse to override the metadata stream if its object ID existed
        in a prior revision, including if the new stream overrides the old
        metadata stream and the syntax check passes. Default ``False``.

        .. note::
            In other situations, pyHanko will reject stream overrides on
            general principle, since combined with the fault-tolerance of some
            PDF readers, these can allow an attacker to manipulate parts of the
            signed content in subtle but significant ways.

            In case of the metadata stream, the risk is significantly mitigated
            thanks to the XML syntax check on both versions of the stream,
            but if you're feeling extra paranoid, you can turn the default
            behaviour back on by setting ``always_refuse_stream_override``
            to ``True``.
    TFc                 C   s   || _ || _d S )N)check_xml_syntaxalways_refuse_stream_override)r   r!   r"   r   r   r   __init__D   s    zMetadataUpdateRule.__init__)metadata_refc              
   C   s   |   }t|tjstdddlm} ddlm} | }|	|  z|
t|j W n, tk
r } ztd|W 5 d}~X Y nX dS )a  
        Checks whether the provided stream consists of well-formed XML data.
        Note that this does not perform any more advanced XML or XMP validation,
        the check is purely syntactic.

        :param metadata_ref:
            A reference to a (purported) metadata stream.
        :raises SuspiciousModification:
            if there are indications that the reference doesn't point to an XML
            stream.
        z2/Metadata should be a reference to a stream objectr   )make_parser)ContentHandlerz+/Metadata XML syntax could not be validatedN)Z
get_object
isinstancer   ZStreamObjectr
   Zxml.saxr%   Zxml.sax.handlerr&   setContentHandlerparser   data	Exception)r$   Zmetadata_streamr%   r&   parserer   r   r   is_well_formed_xmlJ   s      z%MetadataUpdateRule.is_well_formed_xmlr   c                 c   s   dd }||j }|d krd S | jr.t| ||j }| jrP|d k	rPt| ||ko^| j }|sn||rt|t|t	dddV  d S )Nc                 S   sD   z|  dW S  tjk
r*   tdY n tk
r>   Y d S X d S )N	/Metadataz)/Metadata should be an indirect reference)r   r   ZIndirectObjectExpectedr
   KeyError)rootr   r   r   grab_metadatar   s    z/MetadataUpdateRule.apply.<locals>.grab_metadataz/Rootr/   r   )
r1   r!   r   r.   r"   Zis_ref_availabler   r   r   r   )r   r   r   r2   Znew_metadata_refZold_metadata_refZsame_ref_okr   r   r   r   j   s(    




 zMetadataUpdateRule.applyN)TF)r   r   r   r    r#   staticmethodr   Z	Referencer.   r   r   r   r   r   r   r   r   r   )   s      
  N)ior   typingr   Zpyhanko.pdf_utilsr   r   Zpyhanko.pdf_utils.readerr   r   Zcommonsr	   Z
policy_apir
   Z	rules_apir   r   r   __all__r   r   r   r   r   r   <module>   s   