U
    gG                     @   s  d dl 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mZ d dlmZ d dlZd dlmZ d dl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dddZ e !dZ"ee
ej dddZ#ej$e
ej dddZ%ej$eeejef  dddZ&ej$ej'dddZ(ej$eej'ej)ej*ef dddZ+ej$ej,dd d!Z-ej'ejd"d#d$Z.e	ej' ed%d&d'Z/G d(d) d)ej0Z1ej23ej4e,d*fZ5daej6e
ej, d,d-d.Z7eejej,f ejej6d/d0d1Z8eejej,f ejej6d/d2d3Z9eejej,f ejeeedf e:d4d5d6Z;dbej<eej' d8d9d:Z=ej<eejej,f e	ej' d;d<d=Z>ej,d>d?d@Z?ej,ej6dAdBdCZ@e	ej' dDdEdFZAe !dGZBdHdI dJD ZCG dKdL dLeDZEej$e
e ddMdNZFej$e
e ej'dOdPdQZGej$e
e ej)dOdRdSZHej$e
e ej2dOdTdUZIej$e
e dVdWdXZJe !dYZKej$e
e ej,dOdZd[ZLee	ej' d\d]d^ZMd_d` ZNeN  dS )c    N)datetime)BytesIO)BinaryIODictIterableIteratorListOptionalTupleUnion)ElementTree)	XMLParser)parse)genericmisc   )SecurityHandler)get_and_applyisoparse   )model)namereturnc                 C   s   d| j | jf S )Nz{%s}%sns
local_name)r    r   F/tmp/pip-unpacked-wheel-owvgwkas/pyhanko/pdf_utils/metadata/xmp_xml.py_tag   s    r   z\{(.*)}(.*))tagr   c                 C   s0   t | }|d k	r,tj|d|ddS d S )Nr   r   r   )TAG_REmatchr   ExpandedNamegroup)r   mr   r   r   _untag"   s    
r%   )elemr   c                 C   s
   t | jS N)r%   r   r&   r   r   r   _name)   s    r)   c                 c   s.   | j  D ]\}}t|}|r
||fV  q
d S r'   )attribitemsr%   )r&   	attr_namevaluer   r   r   r   
iter_attrs-   s    r.   )descriptionr-   c                 C   sN   |D ]D\}}t |jtr2|js2| t||j qtt| t|| qd S r'   )	
isinstancer-   str
qualifierssetr   add_xmp_valuer   
SubElement)r/   r-   kvr   r   r   _xmp_struct_to_xml6   s    r8   )	containerr-   c                 C   s   t |tr|| _d S t |tjr:| ttjt| d S t |tjrft	
| ttj}t|| d S t |tjrt	
| t|j }|jD ]}tt	
|ttj| qd S ttt|d S r'   )r0   r1   textr   XmpUrir3   r   RDF_RESOURCEXmpStructurer   r5   RDF_DESCRIPTIONr8   XmpArrayZ
array_typeZas_rdfentriesr4   RDF_LINotImplementedErrortype)r9   r-   r/   Zarrr7   r   r   r   _add_inner_valueB   s,    


rD   c                 C   s   |j }|jrft| ttj}|jddD ]\}}tt|t|| q*t	t|ttj
|j nt	| |j |jd k	r| ttj|j d S )NF)Z	with_lang)r2   Zhas_non_lang_qualsr   r5   r   r   r>   Z
iter_qualsr4   rD   	RDF_VALUEr-   langr3   XML_LANG)r9   r-   qualsr/   r6   r7   r   r   r   r4   ^   s    
r4   )rootr   c                 C   s6   t ttj}t||  |ttjd t  |S )N )r   Elementr   r   r>   r8   r3   Z	RDF_ABOUT)rI   r/   r   r   r   _xmp_root_as_xml_trees   s    
rL   )rootsoutc                 C   s   | dd | dtjd  dtj dd | dtjd  dd | D ]}t|}|j |d	dd
 qX| d | d | d d S )Nu6   <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?>
utf-8z<x:xmpmeta xmlns:x="xz" x:xmptk="z">
z<rdf:RDF xmlns:rdf="rdfF)xml_declarationencodings   
</rdf:RDF>s   
</x:xmpmeta>s   
<?xpacket end="r"?>)writeencoder   NSVENDORrL   )rM   rN   rI   Zxmp_datar   r   r   serialise_xmp{   s"    	

rX   c                       s   e Zd Zdee ee ee ee d fddZee	e
j d dddZee	e
j dd	d
Ze
jdddZedddZ  ZS )MetadataStreamN	dict_datastream_dataencoded_datahandlerc                    s:   d | _ t j||||d td| d< td| d< d S )NrZ   z	/Metadataz/Typez/XMLz/Subtype)_xmpsuper__init__r   Zpdf_name)selfr[   r\   r]   r^   	__class__r   r   ra      s    zMetadataStream.__init__)xmpr   c                 C   s   |  }||_ |  |S r'   )r_   _reserialise)clsre   stmr   r   r   from_xmp   s    zMetadataStream.from_xmp)r   c                 C   s    | j d krtt| j| _ | j S r'   )r_   	parse_xmpr   data)rb   r   r   r   re      s    
zMetadataStream.xmp)metac                 C   s"   t || jd| _|   d | _d S )NrM   )update_xmp_with_metare   r_   rf   Z_encoded_data)rb   rl   r   r   r   rn      s    z#MetadataStream.update_xmp_with_metac                 C   s2   t  }| jd k	stt| j| |  | _}|S r'   )r   r_   AssertionErrorrX   getvalue_data)rb   rh   rk   r   r   r   rf      s
    zMetadataStream._reserialise)NNNN)__name__
__module____qualname__r	   dictbytesr   ra   classmethodr   r   r=   ri   propertyre   DocumentMetadatarn   rf   __classcell__r   r   rc   r   rY      s        rY   	x-defaultF)meta_strr   c                 C   s   t | tjrn| jdkr*|rtntj }n6| jr:d| j nd}tjtj	t
| j | f}t
| j|S t | tr|rtntj }t
| |S d S )NDEFAULT-rJ   )r0   r   StringWithLanguage	lang_codeLANG_X_DEFAULTr   
Qualifiersofcountry_coderG   XmpValuer-   r1   )r|   lang_xdefaultrH   ccr   r   r   _meta_string_as_value   s    

r   )fieldskeyr|   c                 C   s    t |dd}|d k	r|| |< d S )NFr   )r   r   r   r|   valr   r   r   _write_meta_string   s    r   c                 C   s0   t |dd}|d k	r,ttj|g| |< d S )NTr   )r   r   r   r?   alternativer   r   r   r   _write_lang_alternative   s    r   )r   r   	meta_dater   c                 C   sL   t |tr|}n|dkr*tjt d}ndS t|jdd | |< dS )Nnow)tzFr   )microsecondT)	r0   r   r   tzlocalZget_localzoner   r   replace	isoformat)r   r   r   r-   r   r   r   _write_meta_date   s    
r   r   )rl   rM   c                 C   s   dd |D }t | |S )Nc                 S   s    i | ]}|D ]\}}||qqS r   r   .0rI   r6   r7   r   r   r   
<dictcomp>  s
       z(update_xmp_with_meta.<locals>.<dictcomp>)_populate_xmp_with_meta)rl   rM   r   r   r   r   rn      s    rn   )rl   r   r   c                 C   s   t |tj| j t|tjtj | jr8t|f| j	S t |tj
| j t|tj| j t| jdd}|d k	rttj|g|tj< t|tj| j t|tj| j | jrt|tjd| j t|f| j	S )NFr   ,)r   r   XMP_MODDATElast_modifiedr   ZPDF_PRODUCERrW   Zxmp_unmanagedr=   Z	xmp_extraXMP_CREATEDATEcreatedr   DC_TITLEtitler   authorr   r?   Zordered
DC_CREATORDC_DESCRIPTIONsubjectXMP_CREATORTOOLcreatorkeywordsPDF_KEYWORDSjoin)rl   r   r   r   r   r   r     s     
r   )xmp_valc                 C   sR   t | jtr| j}ntdzt|}W n$ tk
rL   td|dY nX |S )NzWrong type for XMP datezFailed to parse z
 as a date)r0   r-   r1   XmpXmlProcessingErrorr   
ValueError)r   Zdt_strdtr   r   r   	_parse_dt   s    r   )r   r   c                 C   s   d }| }t | jtjr2t| jjdkr2| jjd }t |jtr|j}|j}|j}|sZ|}nL|dkrrtj	|dd}n4|
dd}tj	||d t|dkr|d nd d}|S )Nr   r{   r}   )r   r~   r   )r   r   )r0   r-   r   r?   lenr@   r1   r2   rF   r   split)r   resultZfocusZval_strrH   rF   
componentsr   r   r   _simplify_meta_str,  s&    r   rm   c           
      C   s  dd | D }i }| tjd }|d k	r4t||d< | tjd }|d k	rVt||d< t|tjt}|d k	rt||d< t|tjt}|d k	r||d< t|tj	t}|d k	r||d< | tj
d }|d k	rt|jtr|jd|d	< | tjd }	|	d k	rt|	jtr|	j|d
< tjf |S )Nc                 S   s    i | ]}|D ]\}}||qqS r   r   r   r   r   r   r   H  s
       z!meta_from_xmp.<locals>.<dictcomp>r   r   r   r   r   r   r   r   )getr   r   r   r   r   r   r   r   r   r   r0   r-   r1   r   r   ry   )
rM   Z
all_fieldskwargsZmod_dateZcreate_dater   r   r   r   r   r   r   r   meta_from_xmpG  s<      
r   sC   \s*<\?\s?xpacket begin="(...?)" id="W5M0MpCehiHzreSzNTczkc9d"\s?\?>c                 C   s   i | ]}d  ||qS )u   ﻿)rU   )r   encr   r   r   r   p  s    r   )rO   zutf-16bezutf-16leutf32c                   @   s   e Zd ZdS )r   N)rr   rs   rt   r   r   r   r   r   v  s   r   c                 C   s   |  ttjd S r'   )r   r   r   rG   r(   r   r   r   _check_langz  s    r   )r&   rF   r   c                 C   s   i }| D ]<}t |}|d k	r||kr4td| dt||d||< qt| D ]:\}}|tjkrNt|rvt|}n|}t	|||< qNt
|S )NzDuplicate field z in XMP structure valuerF   )r)   r   _proc_xmp_valuer.   r   rG   HTTP_URI_REr!   r;   r   r=   )r&   rF   r   childr   
attr_valuer-   r   r   r   _proc_xmp_struct~  s     


r   c                    sR   t  }|d krttjjtjjtjjd|j } fdd}t|t	| S )N)ZSeqZBagZAltc                  3   s*    D ] } t | tjkrt| dV  qd S Nr   )r)   r   rA   r   )lir&   rF   r   r   _entries  s    z_proc_xmp_arr.<locals>._entries)
r)   r   r   ZXmpArrayTypeZORDERED	UNORDEREDZALTERNATIVEr   r?   list)r&   rF   r   Zarr_typer   r   r   r   _proc_xmp_arr  s    r   c                    s    fdd}t jj|  S )Nc                  3   sF   rt jt fV   D ]&} t| }|t jkr|t| fV  qd S r'   )r   rG   r   r)   rE   r   )Zq_xmlZq_namer   r   r   _quals  s    
z#_extract_qualifiers.<locals>._quals)r   r   r   )r&   rF   r   r   r   r   _extract_qualifiers  s    r   r   c                 C   sn   zt dd | D }W n tk
r.   d }Y nX |d k	rPt||j}t| |}nt| |}tj|}||fS )Nc                 s   s    | ]}t |tjkr|V  qd S r'   )r)   r   rE   r   cr   r   r   	<genexpr>  s      z#_unwrap_resource.<locals>.<genexpr>)	nextStopIterationr   r-   r   r   r   r   lang_as_qual)r&   rF   Z	rdf_valueinner_valuerH   r   r   r   _unwrap_resource  s    

r   z
^https?://c           	      C   st  t | p
|}| ttjd }|dkrBt| |d\}}t||S |d k	rZtd|dt| }|dkr| ttj	d }|d k	rtt
|S | jrt| jtj|S | jrtt| |S tdtj|S n|dkr\| d }t|}|tjtjtjfkr$t||}tj|}n,|tjkr@t||\}}ntd| d	t||S td
t |  dd S )NResourcer   zParse type z is not supportedr   rJ   r   zCannot process tag with name z as an XMP value formzTag with name z has more than one child.)r   r   r   r   ZRDF_PARSE_TYPEr   r   r   r   r<   r;   r:   r   r   r*   r   r)   ZRDF_SEQZRDF_ALTZRDF_BAGr   r>   )	r&   rF   Z
parse_typer   rH   Zchild_countZuri_strr   r   r   r   r   r     sJ    
 



r   )inpr   c           
      C   s   |  d}t|}|s"d}d}n$|d}t|d}t|d}| | t| t	|d}|
 }t|}|tjkr|}	nH|tjkrztdd |D }	W q tk
r   tdY qX ntd	d
d |	D S )N   rO   r   r   )rS   c                 s   s    | ]}t |tjkr|V  qd S r'   )r)   r   RDF_RDFr   r   r   r   r   $  s      zparse_xmp.<locals>.<genexpr>zNo rdf:RDF node in x:xmpmetaz%XMP root must be rdf:RDF or x:xmpmetac                 S   s&   g | ]}t |tjkrt|d dqS r   )r)   r   r>   r   )r   noder   r   r   
<listcomp>*  s   zparse_xmp.<locals>.<listcomp>)readXMP_HEADER_PATTERNr!   r#   BOM_REGISTRYr   r   seekdefused_parseDefusedXMLParsergetrootr)   r   r   Z	X_XMPMETAr   r   r   )
r   headerZheader_matchrS   Zstart_offsetbomtreerI   	root_nameZrdf_rootr   r   r   rj     s4    



 

rj   c                  C   s$   t j D ]\} }t| | q
d S r'   )r   rV   r+   r   register_namespace)prefixurir   r   r   register_namespaces1  s    r   )F)r   )Orer   ior   typingr   r   r   r   r   r	   r
   r   Z	xml.etreer   r   Zdefusedxml.ElementTreer   r   r   r   Zpyhanko.pdf_utilsr   r   Z	crypt.apir   r   r   rJ   r   r"   r1   r   compiler    r%   rK   r)   r.   r=   r8   r?   r;   rD   r   r4   rL   rX   ZStreamObjectrY   r   r   rG   r   Z
MetaStringr   r   r   boolr   ry   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rj   r   r   r   r   r   <module>   s   (


 ,   %    
 1)