U
    cF                     @   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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j.Z/ej01ej2e*d)fZ3d`ej4e
ej* d+d,d-Z5eejej*f ejej4d.d/d0Z6eejej*f ejej4d.d1d2Z7eejej*f ejeeedf e8d3d4d5Z9daej:eej% d7d8d9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j4d@dAdBZ>e	ej% dCdDdEZ?e dFZ@dGdH dID ZAG dJdK dKeBZCej"e
e ddLdMZDej"e
e ej%dNdOdPZEej"e
e ej'dNdQdRZFej"e
e ej0dNdSdTZGej"e
e dUdVdWZHe dXZIej"e
e ej*dNdYdZZJee	ej% d[d\d]ZKd^d_ ZLeL  dS )b    N)datetime)BytesIO)BinaryIODictIterableIteratorListOptionalTupleUnion)ElementTree)	XMLParser)parse)genericmisc   )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-0kb_yl26/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_xml3   s    r7   )	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&   )r/   r0   textr   XmpUrir2   r   RDF_RESOURCEXmpStructurer   r4   RDF_DESCRIPTIONr7   XmpArrayZ
array_typeZas_rdfentriesr3   RDF_LINotImplementedErrortype)r8   r,   r.   Zarrr6   r   r   r   _add_inner_valueA   s2    
 
 
rC   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)r1   Zhas_non_lang_qualsr   r4   r   r   r=   Z
iter_qualsr3   rC   	RDF_VALUEr,   langr2   XML_LANG)r8   r,   qualsr.   r5   r6   r   r   r   r3   ]   s     
r3   )rootr   c                 C   s6   t ttj}t||  |ttjd t  |S )N )r   Elementr   r   r=   r7   r2   Z	RDF_ABOUT)rH   r.   r   r   r   _xmp_root_as_xml_treeq   s    
rK   )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VENDORrK   )rL   rM   rH   Zxmp_datar   r   r   serialise_xmpy   s&    

rW   c                       sn   e Zd Z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 )MetadataStreamNc                    s:   d | _ t j||||d td| d< td| d< d S )N)	dict_datastream_dataencoded_datahandlerz	/Metadataz/Typez/XMLz/Subtype)_xmpsuper__init__r   Zpdf_name)selfrY   rZ   r[   r\   	__class__r   r   r_      s    zMetadataStream.__init__)xmpr   c                 C   s   |  }||_ |  |S r&   )r]   _reserialise)clsrc   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)r`   r   r   r   rc      s    
zMetadataStream.xmp)metac                 C   s"   t || jd| _|   d | _d S )NrL   )update_xmp_with_metarc   r]   rd   Z_encoded_data)r`   rj   r   r   r   rl      s    z#MetadataStream.update_xmp_with_metac                 C   s$   t  }t| j| |  | _}|S r&   )r   rW   r]   getvalue_data)r`   rf   ri   r   r   r   rd      s    zMetadataStream._reserialise)NNNN)__name__
__module____qualname__r_   classmethodr   r   r<   rg   propertyrc   DocumentMetadatarl   bytesrd   __classcell__r   r   ra   r   rX      s     rX   	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-rI   )r/   r   StringWithLanguage	lang_codeLANG_X_DEFAULTr   
Qualifiersofcountry_coderF   XmpValuer,   r0   )rx   lang_xdefaultrG   ccr   r   r   _meta_string_as_value   s    

r   )fieldskeyrx   c                 C   s    t |dd}|d k	r|| |< d S )NFr   )r   r   r   rx   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)	r/   r   r   tzlocalZget_localzoner   r   replace	isoformat)r   r   r   r,   r   r   r   _write_meta_date   s    
r   r   )rj   rL   c                 C   s   dd |D }t | |S )Nc                 S   s    i | ]}|D ]\}}||qqS r   r   .0rH   r5   r6   r   r   r   
<dictcomp>   s
     z(update_xmp_with_meta.<locals>.<dictcomp>)_populate_xmp_with_meta)rj   rL   r   r   r   r   rl      s    rl   )rj   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_PRODUCERrV   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)rj   r   r   r   r   r   r      s0      
  
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)r/   r,   r0   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   rw   ry   )r|   rz   r   )r|   r   )r/   r,   r   r>   lenr?   r0   r1   rE   r{   split)r   resultZfocusZval_strrG   rE   
componentsr   r   r   _simplify_meta_str$  s*    r   rk   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   C  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   r/   r,   r0   r   r   rt   )
rL   Z
all_fieldskwargsZmod_dateZcreate_dater   r   r   r   r   r   r   r   meta_from_xmpB  s4    
r   sC   \s*<\?\s?xpacket begin="(...?)" id="W5M0MpCehiHzreSzNTczkc9d"\s?\?>c                 C   s   i | ]}d  ||qS )u   ﻿)rT   )r   encr   r   r   r   k  s    r   )rN   zutf-16bezutf-16leutf32c                   @   s   e Zd ZdS )r   N)ro   rp   rq   r   r   r   r   r   q  s   r   c                 C   s   |  ttjd S r&   )r   r   r   rF   r'   r   r   r   _check_langu  s    r   )r%   rE   r   c                 C   s   i }| D ]<}t |}|d k	r||kr4td| dt||d||< qt| D ]4\}}|tjkrNt|rtt|}t	|||< qNt
|S )NzDuplicate field z in XMP structure valuerE   )r(   r   _proc_xmp_valuer-   r   rF   HTTP_URI_REr    r:   r   r<   )r%   rE   r   childr   r,   r   r   r   _proc_xmp_structy  s    



r   c                    sF   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   r@   r   )lir%   rE   r   r   _entries  s    z_proc_xmp_arr.<locals>._entries)	r(   r   ZXmpArrayTypeZORDERED	UNORDEREDZALTERNATIVEr   r>   list)r%   rE   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   rF   r   r(   rD   r   )Zq_xmlZq_namer   r   r   _quals  s    
z#_extract_qualifiers.<locals>._quals)r   r~   r   )r%   rE   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   rD   r   cr   r   r   	<genexpr>  s      z#_unwrap_resource.<locals>.<genexpr>)	nextStopIterationr   r,   r   r   r   r~   lang_as_qual)r%   rE   Z	rdf_valueinner_valuerG   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   rI   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:   r9   r~   r   r)   r   r(   ZRDF_SEQZRDF_ALTZRDF_BAGr   r=   )	r%   rE   Z
parse_typer   rG   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   rN   r   r   )rR   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_matchrR   Zstart_offsetbomtreerH   	root_nameZrdf_rootr   r   r   rh     s8    



 

rh   c                  C   s$   t j D ]\} }t| | q
d S r&   )r   rU   r*   r   register_namespace)prefixurir   r   r   register_namespaces'  s    r   )F)r   )M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   r   r   rI   r   r!   r0   r   compiler   r$   rJ   r(   r-   r<   r7   r>   r:   rC   r   r3   rK   rW   ZStreamObjectrX   r~   r   rF   r}   Z
MetaStringr   r   r   boolr   rt   rl   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rh   r   r   r   r   r   <module>   s   (

' 	 	  %




1,