46 void addTransactionResult( QDomDocument &responseDoc, QDomElement &responseElem,
const QString &status,
47 const QString &locator,
const QString &message );
58 response.
setHeader(
"Content-Type",
"text/xml; charset=utf-8" );
59 response.
write( doc.toByteArray() );
73 if ( doc.setContent( request.
data(),
true, &errorMsg ) )
75 QDomElement docElem = doc.documentElement();
84 if ( actionCount == 0 )
95 QDomElement respElem = resp.createElement( QStringLiteral(
"WFS_TransactionResponse" ) );
96 respElem.setAttribute( QStringLiteral(
"xmlns" ),
WFS_NAMESPACE );
97 respElem.setAttribute( QStringLiteral(
"xmlns:xsi" ), QStringLiteral(
"http://www.w3.org/2001/XMLSchema-instance" ) );
98 respElem.setAttribute( QStringLiteral(
"xsi:schemaLocation" ),
WFS_NAMESPACE +
" http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" );
99 respElem.setAttribute( QStringLiteral(
"xmlns:ogc" ),
OGC_NAMESPACE );
100 respElem.setAttribute( QStringLiteral(
"version" ), QStringLiteral(
"1.0.0" ) );
101 resp.appendChild( respElem );
104 QStringList errorLocators;
105 QStringList errorMessages;
107 QList<transactionUpdate>::iterator tuIt = aRequest.
updates.begin();
108 for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
114 if ( action.
handle.isEmpty() )
116 errorLocators << QStringLiteral(
"Update:%1" ).arg( action.
typeName );
120 errorLocators << action.
handle;
126 QList<transactionDelete>::iterator tdIt = aRequest.
deletes.begin();
127 for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
133 if ( action.
handle.isEmpty() )
135 errorLocators << QStringLiteral(
"Delete:%1" ).arg( action.
typeName );
139 errorLocators << action.
handle;
145 QList<transactionInsert>::iterator tiIt = aRequest.
inserts.begin();
146 for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
152 if ( action.
handle.isEmpty() )
154 errorLocators << QStringLiteral(
"Insert:%1" ).arg( action.
typeName );
158 errorLocators << action.
handle;
167 QString fidStr = *fidIt;
168 QDomElement irElem = doc.createElement( QStringLiteral(
"InsertResult" ) );
169 if ( !action.
handle.isEmpty() )
171 irElem.setAttribute( QStringLiteral(
"handle" ), action.
handle );
173 QDomElement fiElem = doc.createElement( QStringLiteral(
"ogc:FeatureId" ) );
174 fiElem.setAttribute( QStringLiteral(
"fid" ), fidStr );
175 irElem.appendChild( fiElem );
176 respElem.appendChild( irElem );
182 if ( errorCount == 0 )
184 addTransactionResult( resp, respElem, QStringLiteral(
"SUCCESS" ), QString(), QString() );
188 QString locator = errorLocators.join( QLatin1String(
"; " ) );
189 QString message = errorMessages.join( QLatin1String(
"; " ) );
190 if ( errorCount != actionCount )
192 addTransactionResult( resp, respElem, QStringLiteral(
"PARTIAL" ), locator, message );
196 addTransactionResult( resp, respElem, QStringLiteral(
"ERROR" ), locator, message );
205 QStringList typeNameList;
207 QList<transactionInsert>::iterator tiIt = aRequest.
inserts.begin();
208 for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
210 QString name = ( *tiIt ).typeName;
211 if ( !typeNameList.contains( name ) )
212 typeNameList << name;
214 QList<transactionUpdate>::iterator tuIt = aRequest.
updates.begin();
215 for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
217 QString name = ( *tuIt ).typeName;
218 if ( !typeNameList.contains( name ) )
219 typeNameList << name;
221 QList<transactionDelete>::iterator tdIt = aRequest.
deletes.begin();
222 for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
224 QString name = ( *tdIt ).typeName;
225 if ( !typeNameList.contains( name ) )
226 typeNameList << name;
229 #ifdef HAVE_SERVER_PYTHON_PLUGINS
245 QMap<QString, QgsVectorLayer *> mapLayerMap;
256 if ( !typeNameList.contains( name ) )
289 #ifdef HAVE_SERVER_PYTHON_PLUGINS
302 mapLayerMap[name] = vlayer;
306 tuIt = aRequest.
updates.begin();
307 for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
312 if ( !mapLayerMap.keys().contains(
typeName ) )
315 action.
errorMsg = QStringLiteral(
"TypeName '%1' unknown" ).arg(
typeName );
326 action.
errorMsg = QStringLiteral(
"No permissions to do WFS updates on layer '%1'" ).arg(
typeName );
329 #ifdef HAVE_SERVER_PYTHON_PLUGINS
333 action.
errorMsg = QStringLiteral(
"No permissions to do WFS updates on layer '%1'" ).arg(
typeName );
345 action.
errorMsg = QStringLiteral(
"No capabilities to do WFS updates on layer '%1'" ).arg(
typeName );
368 #ifdef HAVE_SERVER_PYTHON_PLUGINS
378 QMap<QString, QString> propertyMap = action.
propertyMap;
382 const QMap<QString, int> fieldMap = provider->
fieldNameMap();
383 QMap<QString, int>::const_iterator fieldMapIt;
385 bool conversionSuccess;
389 #ifdef HAVE_SERVER_PYTHON_PLUGINS
390 if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
393 action.
errorMsg = QStringLiteral(
"Feature modify permission denied on layer '%1'" ).arg(
typeName );
398 QMap< QString, QString >::const_iterator it = propertyMap.constBegin();
399 for ( ; it != propertyMap.constEnd(); ++it )
401 fieldName = it.key();
402 fieldMapIt = fieldMap.find( fieldName );
403 if ( fieldMapIt == fieldMap.constEnd() )
408 QVariant value = it.value();
409 if ( value.isNull() )
421 if (
field.
type() == QVariant::Type::Int )
423 value = it.value().toInt( &conversionSuccess );
424 if ( !conversionSuccess )
427 action.
errorMsg = QStringLiteral(
"Property conversion error on layer '%1'" ).arg(
typeName );
432 else if (
field.
type() == QVariant::Type::Double )
434 value = it.value().toDouble( &conversionSuccess );
435 if ( !conversionSuccess )
438 action.
errorMsg = QStringLiteral(
"Property conversion error on layer '%1'" ).arg(
typeName );
443 else if (
field.
type() == QVariant::Type::LongLong )
445 value = it.value().toLongLong( &conversionSuccess );
446 if ( !conversionSuccess )
449 action.
errorMsg = QStringLiteral(
"Property conversion error on layer '%1'" ).arg(
typeName );
462 if ( !geometryElem.isNull() )
470 action.
errorMsg = QStringLiteral(
"Geometry from GML error on layer '%1'" ).arg(
typeName );
477 action.
errorMsg = QStringLiteral(
"Error in change geometry on layer '%1'" ).arg(
typeName );
487 #ifdef HAVE_SERVER_PYTHON_PLUGINS
494 if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
497 action.
errorMsg = QStringLiteral(
"Feature modify permission denied on layer '%1'" ).arg(
typeName );
513 action.
errorMsg = QStringLiteral(
"Error committing updates: %1" ).arg( vlayer->
commitErrors().join( QLatin1String(
"; " ) ) );
518 action.
error =
false;
523 tdIt = aRequest.
deletes.begin();
524 for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
529 if ( !mapLayerMap.keys().contains(
typeName ) )
532 action.
errorMsg = QStringLiteral(
"TypeName '%1' unknown" ).arg(
typeName );
543 action.
errorMsg = QStringLiteral(
"No permissions to do WFS deletes on layer '%1'" ).arg(
typeName );
546 #ifdef HAVE_SERVER_PYTHON_PLUGINS
550 action.
errorMsg = QStringLiteral(
"No permissions to do WFS deletes on layer '%1'" ).arg(
typeName );
562 action.
errorMsg = QStringLiteral(
"No capabilities to do WFS deletes on layer '%1'" ).arg(
typeName );
582 action.
errorMsg = QStringLiteral(
"No feature ids to do WFS deletes on layer '%1'" ).arg(
typeName );
589 #ifdef HAVE_SERVER_PYTHON_PLUGINS
603 #ifdef HAVE_SERVER_PYTHON_PLUGINS
604 if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
607 action.
errorMsg = QStringLiteral(
"Feature modify permission denied" );
612 fids << feature.
id();
622 action.
errorMsg = QStringLiteral(
"Delete features failed on layer '%1'" ).arg(
typeName );
631 action.
errorMsg = QStringLiteral(
"Error committing deletes: %1" ).arg( vlayer->
commitErrors().join( QLatin1String(
"; " ) ) );
636 action.
error =
false;
640 tiIt = aRequest.
inserts.begin();
641 for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
646 if ( !mapLayerMap.keys().contains(
typeName ) )
649 action.
errorMsg = QStringLiteral(
"TypeName '%1' unknown" ).arg(
typeName );
660 action.
errorMsg = QStringLiteral(
"No permissions to do WFS inserts on layer '%1'" ).arg(
typeName );
663 #ifdef HAVE_SERVER_PYTHON_PLUGINS
667 action.
errorMsg = QStringLiteral(
"No permissions to do WFS inserts on layer '%1'" ).arg(
typeName );
679 action.
errorMsg = QStringLiteral(
"No capabilities to do WFS inserts on layer '%1'" ).arg(
typeName );
699 if ( featureList.empty() )
702 action.
errorMsg = QStringLiteral(
"No features to insert in layer '%1'" ).arg(
typeName );
706 #ifdef HAVE_SERVER_PYTHON_PLUGINS
710 QgsFeatureList::iterator featureIt = featureList.begin();
711 while ( featureIt != featureList.end() )
713 if ( !accessControl->
allowToEdit( vlayer, *featureIt ) )
716 action.
errorMsg = QStringLiteral(
"Feature modify permission denied on layer '%1'" ).arg(
typeName );
733 action.
errorMsg = QStringLiteral(
"Insert features failed on layer '%1'" ).arg(
typeName );
734 if ( provider ->hasErrors() )
746 action.
errorMsg = QStringLiteral(
"Error committing inserts: %1" ).arg( vlayer->
commitErrors().join( QLatin1String(
"; " ) ) );
751 action.
error =
false;
755 for (
const QgsFeature &feat : qgis::as_const( featureList ) )
762 filterRestorer.reset();
772 const QMap<QString, int> fieldMap = provider->
fieldNameMap();
773 QMap<QString, int>::const_iterator fieldMapIt;
775 for (
int i = 0; i < featureNodeList.count(); i++ )
779 QDomElement featureElem = featureNodeList.at( i ).toElement();
780 QDomNode currentAttributeChild = featureElem.firstChild();
781 bool conversionSuccess =
true;
783 while ( !currentAttributeChild.isNull() )
785 QDomElement currentAttributeElement = currentAttributeChild.toElement();
786 QString attrName = currentAttributeElement.localName();
788 if ( attrName != QLatin1String(
"boundedBy" ) )
790 if ( attrName != QLatin1String(
"geometry" ) )
792 fieldMapIt = fieldMap.find( attrName );
793 if ( fieldMapIt == fieldMap.constEnd() )
799 QString attrValue = currentAttributeElement.text();
802 QgsMessageLog::logMessage( QStringLiteral(
"attr: name=%1 idx=%2 value=%3" ).arg( attrName ).arg( fieldMapIt.value() ).arg( attrValue ) );
804 if ( attrType == QVariant::Int )
805 feat.
setAttribute( fieldMapIt.value(), attrValue.toInt( &conversionSuccess ) );
806 else if ( attrType == QVariant::Double )
807 feat.
setAttribute( fieldMapIt.value(), attrValue.toDouble( &conversionSuccess ) );
811 if ( !conversionSuccess )
826 currentAttributeChild = currentAttributeChild.nextSibling();
836 if ( !parameters.contains( QStringLiteral(
"OPERATION" ) ) )
840 if ( parameters.value( QStringLiteral(
"OPERATION" ) ).toUpper() != QLatin1String(
"DELETE" ) )
846 if ( ( parameters.contains( QStringLiteral(
"FEATUREID" ) )
847 && ( parameters.contains( QStringLiteral(
"FILTER" ) ) || parameters.contains( QStringLiteral(
"BBOX" ) ) ) )
848 || ( parameters.contains( QStringLiteral(
"FILTER" ) )
849 && ( parameters.contains( QStringLiteral(
"FEATUREID" ) ) || parameters.contains( QStringLiteral(
"BBOX" ) ) ) )
850 || ( parameters.contains( QStringLiteral(
"BBOX" ) )
851 && ( parameters.contains( QStringLiteral(
"FEATUREID" ) ) || parameters.contains( QStringLiteral(
"FILTER" ) ) ) )
859 QStringList typeNameList;
861 if ( parameters.contains( QStringLiteral(
"FEATUREID" ) ) )
863 QStringList fidList = parameters.value( QStringLiteral(
"FEATUREID" ) ).split(
',' );
865 QMap<QString, QStringList> fidsMap;
867 QStringList::const_iterator fidIt = fidList.constBegin();
868 for ( ; fidIt != fidList.constEnd(); ++fidIt )
871 QString fid = *fidIt;
874 if ( !fid.contains(
'.' ) )
879 QString
typeName = fid.section(
'.', 0, 0 );
880 fid = fid.section(
'.', 1, 1 );
881 if ( !typeNameList.contains(
typeName ) )
895 QMap<QString, QStringList>::const_iterator fidsMapIt = fidsMap.constBegin();
896 while ( fidsMapIt != fidsMap.constEnd() )
904 request.
deletes.append( action );
909 if ( !parameters.contains( QStringLiteral(
"TYPENAME" ) ) )
914 typeNameList = parameters.value( QStringLiteral(
"TYPENAME" ) ).split(
',' );
917 QStringList::const_iterator typeNameIt = typeNameList.constBegin();
918 for ( ; typeNameIt != typeNameList.constEnd(); ++typeNameIt )
926 request.
deletes.append( action );
930 if ( parameters.contains( QStringLiteral(
"EXP_FILTER" ) ) )
932 QString expFilterName = parameters.value( QStringLiteral(
"EXP_FILTER" ) );
933 QStringList expFilterList;
934 QRegExp rx(
"\\(([^()]+)\\)" );
935 if ( rx.indexIn( expFilterName, 0 ) == -1 )
937 expFilterList << expFilterName;
942 while ( ( pos = rx.indexIn( expFilterName, pos ) ) != -1 )
944 expFilterList << rx.cap( 1 );
945 pos += rx.matchedLength();
950 if ( request.
deletes.size() == expFilterList.size() )
953 QList<transactionDelete>::iterator dIt = request.
deletes.begin();
954 QStringList::const_iterator expFilterIt = expFilterList.constBegin();
955 for ( ; dIt != request.
deletes.end(); ++dIt )
960 if ( expFilterIt != expFilterList.constEnd() )
962 expFilter = *expFilterIt;
964 std::shared_ptr<QgsExpression> filter(
new QgsExpression( expFilter ) );
967 if ( filter->hasParserError() )
973 if ( filter->needsGeometry() )
988 if ( parameters.contains( QStringLiteral(
"BBOX" ) ) )
991 QString bbox = parameters.value( QStringLiteral(
"BBOX" ) );
992 if ( bbox.isEmpty() )
998 QStringList corners = bbox.split(
',' );
999 if ( corners.size() != 4 )
1007 for (
int i = 0; i < 4; i++ )
1009 corners[i].replace(
' ',
'+' );
1010 d[i] = corners[i].toDouble( &ok );
1020 QList<transactionDelete>::iterator dIt = request.
deletes.begin();
1021 for ( ; dIt != request.
deletes.end(); ++dIt )
1028 else if ( parameters.contains( QStringLiteral(
"FILTER" ) ) )
1030 QString filterName = parameters.value( QStringLiteral(
"FILTER" ) );
1031 QStringList filterList;
1032 QRegExp rx(
"\\(([^()]+)\\)" );
1033 if ( rx.indexIn( filterName, 0 ) == -1 )
1035 filterList << filterName;
1040 while ( ( pos = rx.indexIn( filterName, pos ) ) != -1 )
1042 filterList << rx.cap( 1 );
1043 pos += rx.matchedLength();
1048 if ( request.
deletes.size() != filterList.size() )
1054 QList<transactionDelete>::iterator dIt = request.
deletes.begin();
1055 QStringList::const_iterator filterIt = filterList.constBegin();
1056 for ( ; dIt != request.
deletes.end(); ++dIt )
1061 QDomDocument filter;
1062 if ( filterIt != filterList.constEnd() )
1065 if ( !filter.setContent( *filterIt,
true, &errorMsg ) )
1071 QDomElement filterElem = filter.firstChildElement();
1072 QStringList serverFids;
1076 if ( filterIt != filterList.constEnd() )
1091 QDomNodeList docChildNodes = docElem.childNodes();
1093 QDomElement actionElem;
1096 for (
int i = docChildNodes.count(); 0 < i; --i )
1098 actionElem = docChildNodes.at( i - 1 ).toElement();
1099 actionName = actionElem.localName();
1101 if ( actionName == QLatin1String(
"Insert" ) )
1104 request.
inserts.append( action );
1106 else if ( actionName == QLatin1String(
"Update" ) )
1109 request.
updates.append( action );
1111 else if ( actionName == QLatin1String(
"Delete" ) )
1114 request.
deletes.append( action );
1123 QString
typeName = actionElem.attribute( QStringLiteral(
"typeName" ) );
1127 QDomElement filterElem = actionElem.firstChild().toElement();
1128 if ( filterElem.tagName() != QLatin1String(
"Filter" ) )
1133 QStringList serverFids;
1140 action.
error =
false;
1142 if ( actionElem.hasAttribute( QStringLiteral(
"handle" ) ) )
1144 action.
handle = actionElem.attribute( QStringLiteral(
"handle" ) );
1152 QString
typeName = actionElem.attribute( QStringLiteral(
"typeName" ) );
1156 QDomNodeList propertyNodeList = actionElem.elementsByTagName( QStringLiteral(
"Property" ) );
1157 if ( propertyNodeList.isEmpty() )
1162 QMap<QString, QString> propertyMap;
1163 QDomElement propertyElem;
1164 QDomElement nameElem;
1165 QDomElement valueElem;
1166 QDomElement geometryElem;
1168 for (
int l = 0; l < propertyNodeList.count(); ++l )
1170 propertyElem = propertyNodeList.at( l ).toElement();
1171 nameElem = propertyElem.elementsByTagName( QStringLiteral(
"Name" ) ).at( 0 ).toElement();
1172 valueElem = propertyElem.elementsByTagName( QStringLiteral(
"Value" ) ).at( 0 ).toElement();
1173 if ( nameElem.text() != QLatin1String(
"geometry" ) )
1175 propertyMap.insert( nameElem.text(), valueElem.text() );
1179 geometryElem = valueElem;
1183 QDomNodeList filterNodeList = actionElem.elementsByTagName( QStringLiteral(
"Filter" ) );
1185 QStringList serverFids;
1186 if ( filterNodeList.size() != 0 )
1188 QDomElement filterElem = filterNodeList.at( 0 ).toElement();
1198 action.
error =
false;
1200 if ( actionElem.hasAttribute( QStringLiteral(
"handle" ) ) )
1202 action.
handle = actionElem.attribute( QStringLiteral(
"handle" ) );
1210 QDomNodeList featureNodeList = actionElem.childNodes();
1211 if ( featureNodeList.size() != 1 )
1217 for (
int i = 0; i < featureNodeList.count(); ++i )
1219 QString tempTypeName = featureNodeList.at( i ).toElement().localName();
1220 if ( tempTypeName.contains(
':' ) )
1221 tempTypeName = tempTypeName.section(
':', 1, 1 );
1227 else if ( tempTypeName !=
typeName )
1236 action.
error =
false;
1238 if ( actionElem.hasAttribute( QStringLiteral(
"handle" ) ) )
1240 action.
handle = actionElem.attribute( QStringLiteral(
"handle" ) );
1249 void addTransactionResult( QDomDocument &responseDoc, QDomElement &responseElem,
const QString &status,
1250 const QString &locator,
const QString &message )
1252 QDomElement trElem = responseDoc.createElement( QStringLiteral(
"TransactionResult" ) );
1253 QDomElement stElem = responseDoc.createElement( QStringLiteral(
"Status" ) );
1254 QDomElement successElem = responseDoc.createElement( status );
1255 stElem.appendChild( successElem );
1256 trElem.appendChild( stElem );
1257 responseElem.appendChild( trElem );
1259 if ( !locator.isEmpty() )
1261 QDomElement locElem = responseDoc.createElement( QStringLiteral(
"Locator" ) );
1262 locElem.appendChild( responseDoc.createTextNode( locator ) );
1263 trElem.appendChild( locElem );
1266 if ( !message.isEmpty() )
1268 QDomElement mesElem = responseDoc.createElement( QStringLiteral(
"Message" ) );
1269 mesElem.appendChild( responseDoc.createTextNode( message ) );
1270 trElem.appendChild( mesElem );