U
    0bˆhª=  ã                   @   sì   d Z dZdZddlZddlZddl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 ddlmZ dd	lmZ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 ddl m!Z! ddl"m#Z#m$Z$ G dd„ de%ƒZ&G dd„ deƒZ'dS )zCopyright 2021, 3LizzGPL version 3zinfo@3liz.orgé    N)ÚlistdirÚmakedirsÚremove)ÚbasenameÚexistsÚjoinÚsplitext)ÚPath)Úminidom)ÚQgsCoordinateReferenceSystemÚQgsCoordinateTransformÚ
QgsProjectÚQgsVectorFileWriterÚQgsVectorLayer)ÚQFileÚQTemporaryFile)ÚQgsServerFilterÚQgsBufferServerRequestÚQgsServerRequestÚQgsBufferServerResponse)ÚOutputFormats)ÚLoggerÚlog_functionc                   @   s   e Zd ZdZdS )ÚProcessingRequestExceptionz,When an exception occurs during the process.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   ú?/var/www/lizmap/lizmap/plugins/wfsOutputExtension/wfs_filter.pyr      s   r   c                       sb   e Zd Ze‡ fdd„ƒZedd„ ƒZdd„ Zedd„ ƒZeee	e
d	œd
d„ƒZedd„ ƒZ‡  ZS )Ú	WFSFilterc                    s†   t ƒ  |¡ || _tƒ | _d | _d| _d| _d | _d| _	t
t ¡ dƒ| _tj dd¡ ¡ dk| _t| jdd | j d	| j› ¡ d S )
NÚ FZQGIS_WfsOutputExtensionZDEBUG_WFSOUTPUTEXTENSIONÚfalse)ZTRUEÚ1T)Úexist_okzTemporary directory is )ÚsuperÚ__init__Úserver_ifacer   ÚloggerÚformatÚtypenameÚfilenameÚbase_name_targetÚall_gmlr   ÚtempfileÚ
gettempdirÚtemp_dirÚosÚenvironÚgetÚupperÚ
debug_moder   Úinfo)Úselfr'   ©Ú	__class__r   r   r&   "   s"     ÿÿzWFSFilter.__init__c                 C   s   d | _ d| _|  ¡  ¡ }| ¡ }| dd¡ ¡ }|dkr<d S | dd¡ ¡ }|dkrXd S | dd¡ ¡ }t 	|¡}|szd S | 
dd¡ || _ | d	d¡| _d
t ¡ › | _| ¡  | d|j¡ |jrÞ| dd| j› d¡ n| dd| j› d|j› d¡ d S )NFÚSERVICEr!   ÚWFSÚREQUESTÚ
GETFEATUREZOUTPUTFORMATZGML2ÚTYPENAMEZgml_features_zContent-TypeúContent-Dispositionúattachment; filename="ú.zip"Ú.ú")r)   r-   ÚserverInterfaceÚrequestHandlerÚparameterMapr3   r4   Úlowerr   ÚfindÚsetParameterr*   Útimer+   ÚclearÚsetResponseHeaderÚcontent_typeÚzipÚfilename_ext)r7   ÚhandlerÚparamsÚserviceÚrequestÚoutput_formatÚformat_definitionr   r   r   ÚrequestReady8   s:    
 ÿþzWFSFilter.requestReadyc              	   C   s*  | j s
d S |  ¡  ¡ }| ¡  ¡  d¡}t| j| j› dƒ}t	|dƒJ}| 
d¡dkrf| | ¡ ¡ n&dd l}| dd|¡}| | d¡¡ W 5 Q R X t 
| j ¡}| ¡ sþ| ¡  | d	|j¡ |jrÞ| d
d| j› d¡ n| d
d| j› d|j› d¡ n| ¡  | ¡  d¡r&d| _|  |¡ d S )NÚutf8ú.gmlÚabzxsi:schemaLocationéÿÿÿÿr   zxsi:schemaLocation=\".*\"zxsi:schemaLocation=""zContent-typer?   r@   rA   rB   rC   ú</wfs:FeatureCollection>T)r)   rD   rE   ÚbodyÚdataÚdecoder   r0   r+   ÚopenrH   ÚwriteÚreÚsubÚencoder   ZheadersSentrK   rL   rM   rN   r*   rO   Ú	clearBodyÚrstripÚendswithr-   Úsend_output_file)r7   rP   r]   Úoutput_fileÚfra   rU   r   r   r   ÚsendResponsea   s8     ÿþzWFSFilter.sendResponsec              	   C   s  t  | j¡}| j d|j› ¡ | ¡  dd¡}| ¡ }|  	||¡}t
| j| j› dƒ}|rd|d7 }t|ddƒ}| j d|› ¡ | ¡ s¤| d	¡ td
|› dƒ‚tt
| jd| j› d|j› ƒƒ}| ¡  | ¡ }	| ¡  | j d|j› d|	› ¡ tt|	ƒd ƒ| _z–t ¡ }
|j|
_d|
_|jrDt| ¡ t |jƒt! "¡ ƒ|
_#|j$rT|j$|
_%t &||	t! "¡  '¡ |
¡\}}}}|tj(krœ| d	¡ | j )|¡ W dS W n" t*k
rÀ   | d	¡ ‚ Y nX |t j+krt,| jƒ -| jd ¡}t|ddd}| .|
j› d¡ W 5 Q R X |j/r>ddl0}zddl1}|j2}W n t3k
rN   |j4}Y nX t|	ƒd }t
| j|› dƒ}| j d|› ¡ | 5|d¡~}| j6› d|j› }|j.|	||d |j7D ]F}t
| j|› d|› ƒ}t8|ƒr¶| j6› d|› }|j.|||d q¶| 9¡  W 5 Q R X t:|ƒ}| t:j;¡rv| <¡ }| |¡ dS n8| j d¡ t:|	ƒ}| t:j;¡rv| <¡ }| |¡ dS | d	¡ | j )d¡ dS ) z` Process the request.

        :raise ProcessingRequestException when there is an error
        zWFS request to get format r>   r!   rX   z|option:FORCE_SRS_DETECTION=YESZqgis_server_wfs_featuresÚogrzTemporary GML file is ó    zOutput layer z is not valid.zto-z-XXXXXX.z
Temporary z	 file is r   úutf-8Fz.cpgÚwrW   )ÚencodingÚ
Nz.zipzZipping the output in rB   )Zcompress_typeZarcnameTzSending the output filezError no output file)=r   rH   r)   r(   r6   Úogr_providerrF   r3   ÚrequestHeadersÚxsd_for_layerr   r0   r+   r   ÚisValidÚ
appendBodyr   r   rO   r_   ÚfileNamer   r   r   r,   r   ZSaveVectorOptionsZ
driverNameZfileEncodingÚ	force_crsr   Úcrsr   r   ÚinstanceÚctÚogr_datasource_optionsZdatasourceOptionsZwriteAsVectorFormatV3ÚtransformContextÚNoErrorÚcriticalÚ	ExceptionÚShpr	   Újoinpathr`   rN   ÚzipfileÚzlibÚZIP_DEFLATEDÚImportErrorZ
ZIP_STOREDÚZipFiler*   Ú
ext_to_zipr   Úcloser   ÚReadOnlyÚreadAll)r7   rP   rU   Ú	type_nameÚheadersÚresultZgml_pathZoutput_layerZ	temporaryrh   ÚoptionsZwrite_resultZerror_messageÚ_Zcpg_fileri   r‚   rƒ   ÚcompressionÚbase_filenameZzip_file_pathÚzfZarc_filenameÚ	extensionÚ	file_pathÚbar   r   r   rg   ‹   s¶    
ÿý
ü



ý

ý



zWFSFilter.send_output_file)r‹   rŒ   Úreturnc              	   C   s  t  ¡ }| ¡ ddd|ddœ}dd dd	„ | ¡ D ƒ¡ }t|tj|d
ƒ}| j 	¡  
dd¡}tƒ }| |||¡ | ¡  | j d| ¡ › d|› ¡ t| ¡ ƒ d¡}	|	dkr¾| j d¡ dS | ¡ dkrä| j d| ¡ › ¡ dS tt| j| j› dƒdƒ}
|
 |	¡ W 5 Q R X dS )z# Get the XSD describing the layer. r;   ú1.0.0ZDescribeFeatureTypeZ	XMLSCHEMA)ÚMAPr:   ÚVERSIONr<   r>   ZOUTPUTú?ú&c                 s   s    | ]\}}|› d |› V  qdS )ú=Nr   )Ú.0ÚkeyÚvaluer   r   r   Ú	<genexpr>  s     z*WFSFilter.xsd_for_layer.<locals>.<genexpr>NzFetching XSD : HTTP code z
, request rW   r!   z%Content for the XSD request is empty.FéÈ   z,HTTP error when requesting the XSD : return z.xsdrn   T)r   ry   rv   r   Úitemsr   r   Ú	GetMethodr'   ÚserviceRegistryÚ
getServicer   ÚexecuteRequestÚflushr(   r6   Z
statusCodeÚbytesr\   r^   r~   r_   r0   r+   r`   )r7   r‹   rŒ   ÚprojectÚ
parametersZquery_stringrS   rR   ÚresponseÚcontentri   r   r   r   rs     s<    ú	üzWFSFilter.xsd_for_layerc                 C   s  |   ¡  ¡ }| ¡ }| dd¡ ¡ }|dkr0d S | dd¡ ¡ }|dkrLd S |dkr–| jr–| jszz†zF| ¡  tt| j| j
› dƒd	ƒ}| d
¡ W 5 Q R X |  |¡ W n: tk
rè } z| j d¡ | j |¡ W 5 d }~X Y nX W 5 t| jƒD ]~}| 	| j
¡r:t| j|ƒ}| jr2| j d|› ¡ nt|ƒ | 	| j¡røt| j|ƒ}| jrn| j d|› ¡ qøt|ƒ qøX d | _d| _d | _
d | _d S |dkr| ¡  ¡ }	t |	¡}
d}|
jjd jdkr|
 d¡D ]B}|
 d¡D ]0}d}t D ] }|
 !|j" ¡ ¡}| #|¡ qòqæqØnÀ|
 d¡D ]´}| d¡D ]¢}d|jkrJq6|jd jdkr`q6| d¡D ]j}d|jkr~qj|jd jdkr”qjd}t D ]4}|
 !d¡}|
 $|j" ¡ ¡}| #|¡ | #|¡ qœqjq6q(|rò| j d¡ n| j d¡ | ¡  | %|
 &d¡¡ d S d S )Nr:   r!   r;   r<   )ÚGETCAPABILITIESr=   r=   z-DEBUG_WFSOUTPUTEXTENSION is on, not removing rX   Úar[   z0Critical exception when processing the request :Fr­   Úversionr—   Ú
GetFeatureZResultFormatTzows:OperationsMetadatazows:OperationÚnamezows:ParameterZoutputFormatz	ows:Valuez2All formats have been added in the GetCapabilitiesz1No formats have been added in the GetCapabilitiesrm   )'rD   rE   rF   r3   r4   r)   r-   r   r0   Ú
startswithr+   r   r5   r(   r6   r   r,   rd   r_   r`   rg   r   r~   Úlog_exceptionr\   r]   r
   ZparseStringZdocumentElementÚ
attributesrŸ   ZgetElementsByTagNamer   ÚcreateElementrO   ÚappendChildÚcreateTextNoderu   Ztoxml)r7   rP   rQ   rR   rS   Úfiler”   ri   Úer]   ÚdomZformats_addedr   Zresult_format_nodeÚoutputZformat_nodeZoperation_metadata_nodeZoperation_nodeZ
param_nodeZ
value_nodeZ	text_noder   r   r   ÚresponseComplete;  s    "ÿÿ



zWFSFilter.responseComplete)r   r   r   r   r&   rV   rj   rg   ÚstrÚdictÚboolrs   r¼   Ú__classcell__r   r   r8   r   r    !   s   
(*
 *r    )(Ú__copyright__Ú__license__Ú	__email__r1   r.   rJ   r   r   r   Zos.pathr   r   r   r   Úpathlibr	   Zxml.domr
   Ú	qgis.corer   r   r   r   r   Zqgis.PyQt.QtCorer   r   Úqgis.serverr   r   r   r   ÚwfsOutputExtension.definitionsr   ÚwfsOutputExtension.loggingr   r   r   r   r    r   r   r   r   Ú<module>   s    