void writeGetMap( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request, QgsServerResponse& response ) { Q_UNUSED( version ); QgsServerRequest::Parameters params = request.parameters(); QgsWmsConfigParser* parser = getConfigParser( serverIface ); QgsWmsServer server( serverIface->configFilePath(), *serverIface->serverSettings(), params, parser, serverIface->accessControls() ); QScopedPointer<QImage> result( server.getMap() ); if ( !result.isNull() ) { QString format = params.value( QStringLiteral( "FORMAT" ), QStringLiteral( "PNG" ) ); writeImage( response, *result, format, server.getImageQuality() ); } else { throw QgsServiceException( QStringLiteral( "UnknownError" ), QStringLiteral( "Failed to compute GetMap image" ) ); } }
void writeGetCapabilities( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request, QgsServerResponse& response, bool projectSettings ) { QgsServerRequest::Parameters params = request.parameters(); QString configFilePath = serverIface->configFilePath(); QgsServerSettings* serverSettings = serverIface->serverSettings(); QgsAccessControl* accessControl = serverIface->accessControls(); QgsCapabilitiesCache* capabilitiesCache = serverIface->capabilitiesCache(); QStringList cacheKeyList; cacheKeyList << ( projectSettings ? QStringLiteral( "projectSettings" ) : version ); cacheKeyList << getenv( "SERVER_NAME" ); bool cache = true; if ( accessControl ) cache = accessControl->fillCacheKey( cacheKeyList ); QString cacheKey = cacheKeyList.join( QStringLiteral( "-" ) ); const QDomDocument* capabilitiesDocument = capabilitiesCache->searchCapabilitiesDocument( configFilePath, cacheKey ); if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one { QgsMessageLog::logMessage( QStringLiteral( "Capabilities document not found in cache" ) ); QDomDocument doc; QgsWmsServer server( configFilePath, *serverSettings, params, getConfigParser( serverIface ), accessControl ); doc = server.getCapabilities( version, projectSettings ); if ( cache ) { capabilitiesCache->insertCapabilitiesDocument( configFilePath, cacheKey, &doc ); capabilitiesDocument = capabilitiesCache->searchCapabilitiesDocument( configFilePath, cacheKey ); } else { doc = doc.cloneNode().toDocument(); capabilitiesDocument = &doc; } } else { QgsMessageLog::logMessage( QStringLiteral( "Found capabilities document in cache" ) ); } response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) ); response.write( capabilitiesDocument->toByteArray() ); }
void writeGetSchemaExtension( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request, QgsServerResponse& response ) { Q_UNUSED( version ); QgsServerRequest::Parameters params = request.parameters(); QgsWmsServer server( serverIface->configFilePath(), *serverIface->serverSettings(), params, getConfigParser( serverIface ), serverIface->accessControls() ); QDomDocument doc = server.getSchemaExtension(); response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) ); response.write( doc.toByteArray() ); }
void writeGetLegendGraphics( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request, QgsServerResponse& response ) { Q_UNUSED( version ); QgsServerRequest::Parameters params = request.parameters(); QgsRenderer renderer( serverIface, params, getConfigParser( serverIface ) ); QScopedPointer<QImage> result( renderer.getLegendGraphics() ); if ( !result.isNull() ) { QString format = params.value( QStringLiteral( "FORMAT" ), QStringLiteral( "PNG" ) ); writeImage( response, *result, format, renderer.getImageQuality() ); } else { throw QgsServiceException( QStringLiteral( "UnknownError" ), QStringLiteral( "Failed to compute GetLegendGraphics image" ) ); } }
QDomDocument createTransactionDocument( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request ) { Q_UNUSED( version ); QDomDocument doc; QgsWfsProjectParser* configParser = getConfigParser( serverIface ); #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsAccessControl* accessControl = serverIface->accessControls(); #endif const QString requestBody = request.getParameter( QStringLiteral( "REQUEST_BODY" ) ); QString errorMsg; if ( !doc.setContent( requestBody, true, &errorMsg ) ) { throw QgsRequestNotWellFormedException( errorMsg ); } QDomElement docElem = doc.documentElement(); QDomNodeList docChildNodes = docElem.childNodes(); // Re-organize the transaction document QDomDocument mDoc; QDomElement mDocElem = mDoc.createElement( QStringLiteral( "myTransactionDocument" ) ); mDocElem.setAttribute( QStringLiteral( "xmlns" ), QGS_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:wfs" ), WFS_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:qgs" ), QGS_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) ); mDoc.appendChild( mDocElem ); QDomElement actionElem; QString actionName; QDomElement typeNameElem; QString typeName; for ( int i = docChildNodes.count(); 0 < i; --i ) { actionElem = docChildNodes.at( i - 1 ).toElement(); actionName = actionElem.localName(); if ( actionName == QLatin1String( "Insert" ) ) { QDomElement featureElem = actionElem.firstChild().toElement(); typeName = featureElem.localName(); } else if ( actionName == QLatin1String( "Update" ) ) { typeName = actionElem.attribute( QStringLiteral( "typeName" ) ); } else if ( actionName == QLatin1String( "Delete" ) ) { typeName = actionElem.attribute( QStringLiteral( "typeName" ) ); } if ( typeName.contains( QLatin1String( ":" ) ) ) typeName = typeName.section( QStringLiteral( ":" ), 1, 1 ); QDomNodeList typeNameList = mDocElem.elementsByTagName( typeName ); if ( typeNameList.count() == 0 ) { typeNameElem = mDoc.createElement( typeName ); mDocElem.appendChild( typeNameElem ); } else typeNameElem = typeNameList.at( 0 ).toElement(); typeNameElem.appendChild( actionElem ); } // It's time to make the transaction // Create the response document QDomDocument resp; //wfs:WFS_TransactionRespone element QDomElement respElem = resp.createElement( QStringLiteral( "WFS_TransactionResponse" )/*wfs:WFS_TransactionResponse*/ ); respElem.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE ); respElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) ); respElem.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WFS_NAMESPACE + " http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" ); respElem.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE ); respElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) ); resp.appendChild( respElem ); // Store the created feature id for WFS QStringList insertResults; // Get the WFS layers id QStringList wfsLayersId = configParser->wfsLayers();; QList<QgsMapLayer*> layerList; QgsMapLayer* currentLayer = nullptr; // Loop through the layer transaction elements docChildNodes = mDocElem.childNodes(); for ( int i = 0; i < docChildNodes.count(); ++i ) { // Get the vector layer typeNameElem = docChildNodes.at( i ).toElement(); typeName = typeNameElem.tagName(); layerList = configParser->mapLayerFromTypeName( typeName ); // Could be empty! if ( layerList.count() > 0 ) { currentLayer = layerList.at( 0 ); } else { throw QgsRequestNotWellFormedException( QStringLiteral( "Wrong TypeName: %1" ).arg( typeName ) ); } QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer ); // it's a vectorlayer and defined by the administrator as a WFS layer if ( layer && wfsLayersId.contains( layer->id() ) ) { #ifdef HAVE_SERVER_PYTHON_PLUGINS if ( actionName == QLatin1String( "Insert" ) ) { if ( !accessControl->layerInsertPermission( layer ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature insert permission denied" ) ); } } else if ( actionName == QLatin1String( "Update" ) ) { if ( !accessControl->layerUpdatePermission( layer ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature update permission denied" ) ); } } else if ( actionName == QLatin1String( "Delete" ) ) { if ( !accessControl->layerDeletePermission( layer ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature delete permission denied" ) ); } } #endif // Get the provider and it's capabilities QgsVectorDataProvider* provider = layer->dataProvider(); if ( !provider ) { continue; } int cap = provider->capabilities(); // Start the update transaction layer->startEditing(); if (( cap & QgsVectorDataProvider::ChangeAttributeValues ) && ( cap & QgsVectorDataProvider::ChangeGeometries ) ) { // Loop through the update elements for this layer QDomNodeList upNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Update" ) ); for ( int j = 0; j < upNodeList.count(); ++j ) { if ( !configParser->wfstUpdateLayers().contains( layer->id() ) ) { //no wfs permissions to do updates QString errorMsg = "No permissions to do WFS updates on layer '" + layer->name() + "'"; QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL ); addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Update" ), errorMsg ); return resp; } actionElem = upNodeList.at( j ).toElement(); // Get the Feature Ids for this filter on the layer QDomElement filterElem = actionElem.elementsByTagName( QStringLiteral( "Filter" ) ).at( 0 ).toElement(); QgsFeatureIds fids = getFeatureIdsFromFilter( filterElem, layer ); // Loop through the property elements // Store properties and the geometry element QDomNodeList propertyNodeList = actionElem.elementsByTagName( QStringLiteral( "Property" ) ); QMap<QString, QString> propertyMap; QDomElement propertyElem; QDomElement nameElem; QDomElement valueElem; QDomElement geometryElem; for ( int l = 0; l < propertyNodeList.count(); ++l ) { propertyElem = propertyNodeList.at( l ).toElement(); nameElem = propertyElem.elementsByTagName( QStringLiteral( "Name" ) ).at( 0 ).toElement(); valueElem = propertyElem.elementsByTagName( QStringLiteral( "Value" ) ).at( 0 ).toElement(); if ( nameElem.text() != QLatin1String( "geometry" ) ) { propertyMap.insert( nameElem.text(), valueElem.text() ); } else { geometryElem = valueElem; } } // Update the features QgsFields fields = provider->fields(); QMap<QString, int> fieldMap = provider->fieldNameMap(); QMap<QString, int>::const_iterator fieldMapIt; QString fieldName; bool conversionSuccess; QgsFeatureIds::const_iterator fidIt = fids.constBegin(); for ( ; fidIt != fids.constEnd(); ++fidIt ) { #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) ); QgsFeature feature; while ( fit.nextFeature( feature ) ) { if ( !accessControl->allowToEdit( layer, feature ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } } #endif QMap< QString, QString >::const_iterator it = propertyMap.constBegin(); for ( ; it != propertyMap.constEnd(); ++it ) { fieldName = it.key(); fieldMapIt = fieldMap.find( fieldName ); if ( fieldMapIt == fieldMap.constEnd() ) { continue; } QgsField field = fields.at( fieldMapIt.value() ); if ( field.type() == 2 ) layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value().toInt( &conversionSuccess ) ); else if ( field.type() == 6 ) layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value().toDouble( &conversionSuccess ) ); else layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value() ); } if ( !geometryElem.isNull() ) { QgsGeometry g = QgsOgcUtils::geometryFromGML( geometryElem ); if ( !layer->changeGeometry( *fidIt, g ) ) { throw QgsRequestNotWellFormedException( QStringLiteral( "Error in change geometry" ) ); } } #ifdef HAVE_SERVER_PYTHON_PLUGINS fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) ); while ( fit.nextFeature( feature ) ) { if ( !accessControl->allowToEdit( layer, feature ) ) { layer->rollBack(); throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } } #endif } } } // Commit the changes of the update elements if ( !layer->commitChanges() ) { addTransactionResult( resp, respElem, QStringLiteral( "PARTIAL" ), QStringLiteral( "Update" ), layer->commitErrors().join( QStringLiteral( "\n " ) ) ); return resp; } // Start the delete transaction layer->startEditing(); if (( cap & QgsVectorDataProvider::DeleteFeatures ) ) { // Loop through the delete elements QDomNodeList delNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Delete" ) ); for ( int j = 0; j < delNodeList.count(); ++j ) { if ( !configParser->wfstDeleteLayers().contains( layer->id() ) ) { //no wfs permissions to do updates QString errorMsg = "No permissions to do WFS deletes on layer '" + layer->name() + "'"; QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL ); addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Delete" ), errorMsg ); return resp; } actionElem = delNodeList.at( j ).toElement(); QDomElement filterElem = actionElem.firstChild().toElement(); // Get Feature Ids for the Filter element QgsFeatureIds fids = getFeatureIdsFromFilter( filterElem, layer ); #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsFeatureIds::const_iterator fidIt = fids.constBegin(); for ( ; fidIt != fids.constEnd(); ++fidIt ) { QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) ); QgsFeature feature; while ( fit.nextFeature( feature ) ) { if ( !accessControl->allowToEdit( layer, feature ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } } } #endif layer->selectByIds( fids ); layer->deleteSelectedFeatures(); } } // Commit the changes of the delete elements if ( !layer->commitChanges() ) { addTransactionResult( resp, respElem, QStringLiteral( "PARTIAL" ), QStringLiteral( "Delete" ), layer->commitErrors().join( QStringLiteral( "\n " ) ) ); return resp; } // Store the inserted features QgsFeatureList inFeatList; if ( cap & QgsVectorDataProvider::AddFeatures ) { // Get Layer Field Information QgsFields fields = provider->fields(); QMap<QString, int> fieldMap = provider->fieldNameMap(); QMap<QString, int>::const_iterator fieldMapIt; // Loop through the insert elements QDomNodeList inNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Insert" ) ); for ( int j = 0; j < inNodeList.count(); ++j ) { if ( !configParser->wfstInsertLayers().contains( layer->id() ) ) { //no wfs permissions to do updates QString errorMsg = "No permissions to do WFS inserts on layer '" + layer->name() + "'"; QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL ); addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Insert" ), errorMsg ); return resp; } actionElem = inNodeList.at( j ).toElement(); // Loop through the feature element QDomNodeList featNodes = actionElem.childNodes(); for ( int l = 0; l < featNodes.count(); l++ ) { // Add the feature to the layer // and store it to put it's Feature Id in the response inFeatList << QgsFeature( fields ); // Create feature for this layer QDomElement featureElem = featNodes.at( l ).toElement(); QDomNode currentAttributeChild = featureElem.firstChild(); while ( !currentAttributeChild.isNull() ) { QDomElement currentAttributeElement = currentAttributeChild.toElement(); QString attrName = currentAttributeElement.localName(); if ( attrName != QLatin1String( "boundedBy" ) ) { if ( attrName != QLatin1String( "geometry" ) ) //a normal attribute { fieldMapIt = fieldMap.find( attrName ); if ( fieldMapIt == fieldMap.constEnd() ) { continue; } QgsField field = fields.at( fieldMapIt.value() ); QString attrValue = currentAttributeElement.text(); int attrType = field.type(); QgsMessageLog::logMessage( QStringLiteral( "attr: name=%1 idx=%2 value=%3" ).arg( attrName ).arg( fieldMapIt.value() ).arg( attrValue ) ); if ( attrType == QVariant::Int ) inFeatList.last().setAttribute( fieldMapIt.value(), attrValue.toInt() ); else if ( attrType == QVariant::Double ) inFeatList.last().setAttribute( fieldMapIt.value(), attrValue.toDouble() ); else inFeatList.last().setAttribute( fieldMapIt.value(), attrValue ); } else //a geometry attribute { QgsGeometry g = QgsOgcUtils::geometryFromGML( currentAttributeElement ); inFeatList.last().setGeometry( g ); } } currentAttributeChild = currentAttributeChild.nextSibling(); } } } } #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsFeatureList::iterator featureIt = inFeatList.begin(); while ( featureIt != inFeatList.end() ) { if ( !accessControl->allowToEdit( layer, *featureIt ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } featureIt++; } #endif // add the features if ( !provider->addFeatures( inFeatList ) ) { addTransactionResult( resp, respElem, QStringLiteral( "Partial" ), QStringLiteral( "Insert" ), layer->commitErrors().join( QStringLiteral( "\n " ) ) ); if ( provider->hasErrors() ) { provider->clearErrors(); } return resp; } // Get the Feature Ids of the inserted feature for ( int j = 0; j < inFeatList.size(); j++ ) { insertResults << typeName + "." + QString::number( inFeatList[j].id() ); } } } // Put the Feature Ids of the inserted feature if ( !insertResults.isEmpty() ) { Q_FOREACH ( const QString &fidStr, insertResults ) { QDomElement irElem = doc.createElement( QStringLiteral( "InsertResult" ) ); QDomElement fiElem = doc.createElement( QStringLiteral( "ogc:FeatureId" ) ); fiElem.setAttribute( QStringLiteral( "fid" ), fidStr ); irElem.appendChild( fiElem ); respElem.appendChild( irElem ); }
QDomDocument createGetCapabilitiesDocument( QgsServerInterface* serverIface, const QgsProject* project, const QString& version, const QgsServerRequest& request ) { Q_UNUSED( version ); QDomDocument doc; QgsWfsProjectParser* configParser = getConfigParser( serverIface ); //wfs:WFS_Capabilities element QDomElement wfsCapabilitiesElement = doc.createElement( QStringLiteral( "WFS_Capabilities" )/*wms:WFS_Capabilities*/ ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WFS_NAMESPACE + " http://schemas.opengis.net/wfs/1.0.0/WFS-capabilities.xsd" ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:ows" ), QStringLiteral( "http://www.opengis.net/ows" ) ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "version" ), implementationVersion() ); wfsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) ); doc.appendChild( wfsCapabilitiesElement ); configParser->serviceCapabilities( wfsCapabilitiesElement, doc ); //wfs:Capability element QDomElement capabilityElement = doc.createElement( QStringLiteral( "Capability" )/*wfs:Capability*/ ); wfsCapabilitiesElement.appendChild( capabilityElement ); //wfs:Request element QDomElement requestElement = doc.createElement( QStringLiteral( "Request" )/*wfs:Request*/ ); capabilityElement.appendChild( requestElement ); //wfs:GetCapabilities QDomElement getCapabilitiesElement = doc.createElement( QStringLiteral( "GetCapabilities" )/*wfs:GetCapabilities*/ ); requestElement.appendChild( getCapabilitiesElement ); QDomElement dcpTypeElement = doc.createElement( QStringLiteral( "DCPType" )/*wfs:DCPType*/ ); getCapabilitiesElement.appendChild( dcpTypeElement ); QDomElement httpElement = doc.createElement( QStringLiteral( "HTTP" )/*wfs:HTTP*/ ); dcpTypeElement.appendChild( httpElement ); //Prepare url QString hrefString = serviceUrl( request, project ); //only Get supported for the moment QDomElement getElement = doc.createElement( QStringLiteral( "Get" )/*wfs:Get*/ ); httpElement.appendChild( getElement ); getElement.setAttribute( QStringLiteral( "onlineResource" ), hrefString ); QDomElement getCapabilitiesDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' getCapabilitiesDhcTypePostElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) ); getCapabilitiesElement.appendChild( getCapabilitiesDhcTypePostElement ); //wfs:DescribeFeatureType QDomElement describeFeatureTypeElement = doc.createElement( QStringLiteral( "DescribeFeatureType" )/*wfs:DescribeFeatureType*/ ); requestElement.appendChild( describeFeatureTypeElement ); QDomElement schemaDescriptionLanguageElement = doc.createElement( QStringLiteral( "SchemaDescriptionLanguage" )/*wfs:SchemaDescriptionLanguage*/ ); describeFeatureTypeElement.appendChild( schemaDescriptionLanguageElement ); QDomElement xmlSchemaElement = doc.createElement( QStringLiteral( "XMLSCHEMA" )/*wfs:XMLSCHEMA*/ ); schemaDescriptionLanguageElement.appendChild( xmlSchemaElement ); QDomElement describeFeatureTypeDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' describeFeatureTypeElement.appendChild( describeFeatureTypeDhcTypeElement ); QDomElement describeFeatureTypeDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' describeFeatureTypeDhcTypePostElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) ); describeFeatureTypeElement.appendChild( describeFeatureTypeDhcTypePostElement ); //wfs:GetFeature QDomElement getFeatureElement = doc.createElement( QStringLiteral( "GetFeature" )/*wfs:GetFeature*/ ); requestElement.appendChild( getFeatureElement ); QDomElement getFeatureFormatElement = doc.createElement( QStringLiteral( "ResultFormat" ) );/*wfs:ResultFormat*/ getFeatureElement.appendChild( getFeatureFormatElement ); QDomElement gmlFormatElement = doc.createElement( QStringLiteral( "GML2" ) );/*wfs:GML2*/ getFeatureFormatElement.appendChild( gmlFormatElement ); QDomElement gml3FormatElement = doc.createElement( QStringLiteral( "GML3" ) );/*wfs:GML3*/ getFeatureFormatElement.appendChild( gml3FormatElement ); QDomElement geojsonFormatElement = doc.createElement( QStringLiteral( "GeoJSON" ) );/*wfs:GeoJSON*/ getFeatureFormatElement.appendChild( geojsonFormatElement ); QDomElement getFeatureDhcTypeGetElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' getFeatureElement.appendChild( getFeatureDhcTypeGetElement ); QDomElement getFeatureDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' getFeatureDhcTypePostElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) ); getFeatureElement.appendChild( getFeatureDhcTypePostElement ); //wfs:Transaction QDomElement transactionElement = doc.createElement( QStringLiteral( "Transaction" )/*wfs:Transaction*/ ); requestElement.appendChild( transactionElement ); QDomElement transactionDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' transactionDhcTypeElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) ); transactionElement.appendChild( transactionDhcTypeElement ); //wfs:FeatureTypeList element QDomElement featureTypeListElement = doc.createElement( QStringLiteral( "FeatureTypeList" )/*wfs:FeatureTypeList*/ ); wfsCapabilitiesElement.appendChild( featureTypeListElement ); //wfs:Operations element QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ ); featureTypeListElement.appendChild( operationsElement ); //wfs:Query element QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ ); operationsElement.appendChild( queryElement ); /* * Adding layer liste in featureTypeListElement */ configParser->featureTypeList( featureTypeListElement, doc ); /* * Adding ogc:Filter_Capabilities in capabilityElement */ //ogc:Filter_Capabilities element QDomElement filterCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Filter_Capabilities" )/*ogc:Filter_Capabilities*/ ); wfsCapabilitiesElement.appendChild( filterCapabilitiesElement ); QDomElement spatialCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Spatial_Capabilities" )/*ogc:Spatial_Capabilities*/ ); filterCapabilitiesElement.appendChild( spatialCapabilitiesElement ); QDomElement spatialOperatorsElement = doc.createElement( QStringLiteral( "ogc:Spatial_Operators" )/*ogc:Spatial_Operators*/ ); spatialCapabilitiesElement.appendChild( spatialOperatorsElement ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:BBOX" )/*ogc:BBOX*/ ) ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Disjoint" )/*ogc:Disjoint*/ ) ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Intersect" )/*ogc:Intersects*/ ) ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Touches" )/*ogc:Touches*/ ) ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Crosses" )/*ogc:Crosses*/ ) ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Contains" )/*ogc:Contains*/ ) ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Overlaps" )/*ogc:Overlaps*/ ) ); spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Within" )/*ogc:Within*/ ) ); QDomElement scalarCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Scalar_Capabilities" )/*ogc:Scalar_Capabilities*/ ); filterCapabilitiesElement.appendChild( scalarCapabilitiesElement ); QDomElement comparisonOperatorsElement = doc.createElement( QStringLiteral( "ogc:Comparison_Operators" )/*ogc:Comparison_Operators*/ ); scalarCapabilitiesElement.appendChild( comparisonOperatorsElement ); comparisonOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Simple_Comparisons" )/*ogc:Simple_Comparisons*/ ) ); comparisonOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Between" )/*ogc:Between*/ ) ); comparisonOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Like" )/*ogc:Like*/ ) ); return doc; }
QDomDocument getCapabilities( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request, bool projectSettings ) { QDomDocument doc; QDomElement wmsCapabilitiesElement; QgsWmsConfigParser* configParser = getConfigParser( serverIface ); QgsServerRequest::Parameters parameters = request.parameters(); // Get service URL QUrl href = serviceUrl( request, configParser ); //href needs to be a prefix QString hrefString = href.toString( QUrl::FullyDecoded ); hrefString.append( href.hasQuery() ? "&" : "?" ); // XML declaration QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"utf-8\"" ) ); // Append format helper std::function < void ( QDomElement&, const QString& ) > appendFormat = [&doc]( QDomElement & elem, const QString & format ) { QDomElement formatElem = doc.createElement( QStringLiteral( "Format" )/*wms:Format*/ ); formatElem.appendChild( doc.createTextNode( format ) ); elem.appendChild( formatElem ); }; if ( version == QLatin1String( "1.1.1" ) ) { doc = QDomDocument( QStringLiteral( "WMT_MS_Capabilities SYSTEM 'http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd'" ) ); //WMS 1.1.1 needs DOCTYPE "SYSTEM http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd" doc.appendChild( xmlDeclaration ); wmsCapabilitiesElement = doc.createElement( QStringLiteral( "WMT_MS_Capabilities" )/*wms:WMS_Capabilities*/ ); } else // 1.3.0 as default { doc.appendChild( xmlDeclaration ); wmsCapabilitiesElement = doc.createElement( QStringLiteral( "WMS_Capabilities" )/*wms:WMS_Capabilities*/ ); wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns" ), QStringLiteral( "http://www.opengis.net/wms" ) ); wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:sld" ), QStringLiteral( "http://www.opengis.net/sld" ) ); wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:qgs" ), QStringLiteral( "http://www.qgis.org/wms" ) ); wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) ); QString schemaLocation = QStringLiteral( "http://www.opengis.net/wms" ); schemaLocation += QLatin1String( " http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd" ); schemaLocation += QLatin1String( " http://www.opengis.net/sld" ); schemaLocation += QLatin1String( " http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd" ); schemaLocation += QLatin1String( " http://www.qgis.org/wms" ); if ( configParser && configParser->wmsInspireActivated() ) { wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:inspire_common" ), QStringLiteral( "http://inspire.ec.europa.eu/schemas/common/1.0" ) ); wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:inspire_vs" ), QStringLiteral( "http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" ) ); schemaLocation += QLatin1String( " http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" ); schemaLocation += QLatin1String( " http://inspire.ec.europa.eu/schemas/inspire_vs/1.0/inspire_vs.xsd" ); } schemaLocation += " " + hrefString + "SERVICE=WMS&REQUEST=GetSchemaExtension"; wmsCapabilitiesElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), schemaLocation ); } wmsCapabilitiesElement.setAttribute( QStringLiteral( "version" ), version ); doc.appendChild( wmsCapabilitiesElement ); configParser->serviceCapabilities( wmsCapabilitiesElement, doc ); //wms:Capability element QDomElement capabilityElement = doc.createElement( QStringLiteral( "Capability" )/*wms:Capability*/ ); wmsCapabilitiesElement.appendChild( capabilityElement ); //wms:Request element QDomElement requestElement = doc.createElement( QStringLiteral( "Request" )/*wms:Request*/ ); capabilityElement.appendChild( requestElement ); QDomElement dcpTypeElement = doc.createElement( QStringLiteral( "DCPType" )/*wms:DCPType*/ ); QDomElement httpElement = doc.createElement( QStringLiteral( "HTTP" )/*wms:HTTP*/ ); dcpTypeElement.appendChild( httpElement ); QDomElement elem; //wms:GetCapabilities elem = doc.createElement( QStringLiteral( "GetCapabilities" )/*wms:GetCapabilities*/ ); appendFormat( elem, ( version == QLatin1String( "1.1.1" ) ? "application/vnd.ogc.wms_xml" : "text/xml" ) ); elem.appendChild( dcpTypeElement ); requestElement.appendChild( elem ); // SOAP platform //only give this information if it is not a WMS request to be in sync with the WMS capabilities schema // XXX Not even sure that cam be ever true if ( parameters.value( QStringLiteral( "SERVICE" ) ).compare( QLatin1String( "WMS" ), Qt::CaseInsensitive ) != 0 ) { QDomElement soapElement = doc.createElement( QStringLiteral( "SOAP" )/*wms:SOAP*/ ); httpElement.appendChild( soapElement ); QDomElement soapResourceElement = doc.createElement( QStringLiteral( "OnlineResource" )/*wms:OnlineResource*/ ); soapResourceElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); soapResourceElement.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) ); soapResourceElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString ); soapElement.appendChild( soapResourceElement ); } //only Get supported for the moment QDomElement getElement = doc.createElement( QStringLiteral( "Get" )/*wms:Get*/ ); httpElement.appendChild( getElement ); QDomElement olResourceElement = doc.createElement( QStringLiteral( "OnlineResource" )/*wms:OnlineResource*/ ); olResourceElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); olResourceElement.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) ); olResourceElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString ); getElement.appendChild( olResourceElement ); //wms:GetMap elem = doc.createElement( QStringLiteral( "GetMap" )/*wms:GetMap*/ ); appendFormat( elem, QStringLiteral( "image/jpeg" ) ); appendFormat( elem, QStringLiteral( "image/png" ) ); appendFormat( elem, QStringLiteral( "image/png; mode=16bit" ) ); appendFormat( elem, QStringLiteral( "image/png; mode=8bit" ) ); appendFormat( elem, QStringLiteral( "image/png; mode=1bit" ) ); appendFormat( elem, QStringLiteral( "application/dxf" ) ); elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' requestElement.appendChild( elem ); //wms:GetFeatureInfo elem = doc.createElement( QStringLiteral( "GetFeatureInfo" ) ); appendFormat( elem, QStringLiteral( "text/plain" ) ); appendFormat( elem, QStringLiteral( "text/html" ) ); appendFormat( elem, QStringLiteral( "text/xml" ) ); appendFormat( elem, QStringLiteral( "application/vnd.ogc.gml" ) ); appendFormat( elem, QStringLiteral( "application/vnd.ogc.gml/3.1.1" ) ); elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' requestElement.appendChild( elem ); //wms:GetLegendGraphic elem = doc.createElement(( version == QLatin1String( "1.1.1" ) ? "GetLegendGraphic" : "sld:GetLegendGraphic" )/*wms:GetLegendGraphic*/ ); appendFormat( elem, QStringLiteral( "image/jpeg" ) ); appendFormat( elem, QStringLiteral( "image/png" ) ); elem.appendChild( dcpTypeElement.cloneNode().toElement() ); // this is the same as for 'GetCapabilities' requestElement.appendChild( elem ); //wms:DescribeLayer elem = doc.createElement(( version == QLatin1String( "1.1.1" ) ? "DescribeLayer" : "sld:DescribeLayer" )/*wms:GetLegendGraphic*/ ); appendFormat( elem, QStringLiteral( "text/xml" ) ); elem.appendChild( dcpTypeElement.cloneNode().toElement() ); // this is the same as for 'GetCapabilities' requestElement.appendChild( elem ); //wms:GetStyles elem = doc.createElement(( version == QLatin1String( "1.1.1" ) ? "GetStyles" : "qgs:GetStyles" )/*wms:GetStyles*/ ); appendFormat( elem, QStringLiteral( "text/xml" ) ); elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' requestElement.appendChild( elem ); if ( projectSettings ) //remove composer templates from GetCapabilities in the long term { //wms:GetPrint elem = doc.createElement( QStringLiteral( "GetPrint" ) /*wms:GetPrint*/ ); appendFormat( elem, QStringLiteral( "svg" ) ); appendFormat( elem, QStringLiteral( "png" ) ); appendFormat( elem, QStringLiteral( "pdf" ) ); elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' requestElement.appendChild( elem ); } //Exception element is mandatory elem = doc.createElement( QStringLiteral( "Exception" ) ); appendFormat( elem, ( version == QLatin1String( "1.1.1" ) ? "application/vnd.ogc.se_xml" : "XML" ) ); capabilityElement.appendChild( elem ); //UserDefinedSymbolization element if ( version == QLatin1String( "1.3.0" ) ) { elem = doc.createElement( QStringLiteral( "sld:UserDefinedSymbolization" ) ); elem.setAttribute( QStringLiteral( "SupportSLD" ), QStringLiteral( "1" ) ); elem.setAttribute( QStringLiteral( "UserLayer" ), QStringLiteral( "0" ) ); elem.setAttribute( QStringLiteral( "UserStyle" ), QStringLiteral( "1" ) ); elem.setAttribute( QStringLiteral( "RemoteWFS" ), QStringLiteral( "0" ) ); elem.setAttribute( QStringLiteral( "InlineFeature" ), QStringLiteral( "0" ) ); elem.setAttribute( QStringLiteral( "RemoteWCS" ), QStringLiteral( "0" ) ); capabilityElement.appendChild( elem ); if ( configParser->wmsInspireActivated() ) { configParser->inspireCapabilities( capabilityElement, doc ); } } if ( projectSettings ) { //Insert <ComposerTemplate> elements derived from wms:_ExtendedCapabilities configParser->printCapabilities( capabilityElement, doc ); //WFS layers QStringList wfsLayers = configParser->wfsLayerNames(); if ( !wfsLayers.isEmpty() ) { QDomElement wfsLayersElem = doc.createElement( QStringLiteral( "WFSLayers" ) ); for ( auto wfsIt = wfsLayers.constBegin() ; wfsIt != wfsLayers.constEnd(); ++wfsIt ) { QDomElement wfsLayerElem = doc.createElement( QStringLiteral( "WFSLayer" ) ); wfsLayerElem.setAttribute( QStringLiteral( "name" ), *wfsIt ); wfsLayersElem.appendChild( wfsLayerElem ); } capabilityElement.appendChild( wfsLayersElem ); } } //add the xml content for the individual layers/styles configParser->layersAndStylesCapabilities( capabilityElement, doc, version, projectSettings ); return doc; }