Skip to content

Commit 08c06de

Browse files
authoredJul 19, 2017
Merge pull request #4846 from rldhont/server-wms-configparser-getfeatureinfo
[Server] WMS GetFeatureInfo refactoring
2 parents 744fbc5 + 349c996 commit 08c06de

File tree

11 files changed

+1020
-473
lines changed

11 files changed

+1020
-473
lines changed
 

‎python/server/qgsserverprojectutils.sip

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,62 @@ namespace QgsServerProjectUtils
145145
:rtype: bool
146146
%End
147147

148+
bool wmsFeatureInfoAddWktGeometry( const QgsProject &project );
149+
%Docstring
150+
Returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
151+
\param project the QGIS project
152+
:return: if the geometry is displayed as Well Known Text in GetFeatureInfo request.
153+
:rtype: bool
154+
%End
155+
156+
bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
157+
%Docstring
158+
Returns if the geometry has to be segmentize in GetFeatureInfo request.
159+
\param project the QGIS project
160+
:return: if the geometry has to be segmentize in GetFeatureInfo request.
161+
:rtype: bool
162+
%End
163+
164+
int wmsFeatureInfoPrecision( const QgsProject &project );
165+
%Docstring
166+
Returns the geometry precision for GetFeatureInfo request.
167+
\param project the QGIS project
168+
:return: the geometry precision for GetFeatureInfo request.
169+
:rtype: int
170+
%End
171+
172+
QString wmsFeatureInfoDocumentElement( const QgsProject &project );
173+
%Docstring
174+
Returns the document element name for XML GetFeatureInfo request.
175+
\param project the QGIS project
176+
:return: the document element name for XML GetFeatureInfo request.
177+
:rtype: str
178+
%End
179+
180+
QString wmsFeatureInfoDocumentElementNs( const QgsProject &project );
181+
%Docstring
182+
Returns the document element namespace for XML GetFeatureInfo request.
183+
\param project the QGIS project
184+
:return: the document element namespace for XML GetFeatureInfo request.
185+
:rtype: str
186+
%End
187+
188+
QString wmsFeatureInfoSchema( const QgsProject &project );
189+
%Docstring
190+
Returns the schema URL for XML GetFeatureInfo request.
191+
\param project the QGIS project
192+
:return: the schema URL for XML GetFeatureInfo request.
193+
:rtype: str
194+
%End
195+
196+
QHash<QString, QString> wmsFeatureInfoLayerAliasMap( const QgsProject &project );
197+
%Docstring
198+
Returns the mapping between layer name and wms layer name for GetFeatureInfo request.
199+
\param project the QGIS project
200+
:return: the mapping between layer name and wms layer name for GetFeatureInfo request.
201+
:rtype: QHash<str, QString>
202+
%End
203+
148204
bool wmsInspireActivate( const QgsProject &project );
149205
%Docstring
150206
Returns if Inspire is activated.

‎src/server/qgsserverprojectutils.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,77 @@ bool QgsServerProjectUtils::wmsInfoFormatSia2045( const QgsProject &project )
117117
return false;
118118
}
119119

120+
bool QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( const QgsProject &project )
121+
{
122+
QString wktGeom = project.readEntry( QStringLiteral( "WMSAddWktGeometry" ), QStringLiteral( "/" ), "" );
123+
124+
if ( wktGeom.compare( QLatin1String( "enabled" ), Qt::CaseInsensitive ) == 0
125+
|| wktGeom.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
126+
{
127+
return true;
128+
}
129+
return false;
130+
}
131+
132+
bool QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project )
133+
{
134+
QString segmGeom = project.readEntry( QStringLiteral( "WMSSegmentizeFeatureInfoGeometry" ), QStringLiteral( "/" ), "" );
135+
136+
if ( segmGeom.compare( QLatin1String( "enabled" ), Qt::CaseInsensitive ) == 0
137+
|| segmGeom.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
138+
{
139+
return true;
140+
}
141+
return false;
142+
}
143+
144+
int QgsServerProjectUtils::wmsFeatureInfoPrecision( const QgsProject &project )
145+
{
146+
return project.readNumEntry( QStringLiteral( "WMSPrecision" ), QStringLiteral( "/" ), 6 );
147+
}
148+
149+
QString QgsServerProjectUtils::wmsFeatureInfoDocumentElement( const QgsProject &project )
150+
{
151+
return project.readEntry( QStringLiteral( "WMSFeatureInfoDocumentElement" ), QStringLiteral( "/" ), "" );
152+
}
153+
154+
QString QgsServerProjectUtils::wmsFeatureInfoDocumentElementNs( const QgsProject &project )
155+
{
156+
return project.readEntry( QStringLiteral( "WMSFeatureInfoDocumentElementNS" ), QStringLiteral( "/" ), "" );
157+
}
158+
159+
QString QgsServerProjectUtils::wmsFeatureInfoSchema( const QgsProject &project )
160+
{
161+
return project.readEntry( QStringLiteral( "WMSFeatureInfoSchema" ), QStringLiteral( "/" ), "" );
162+
}
163+
164+
QHash<QString, QString> QgsServerProjectUtils::wmsFeatureInfoLayerAliasMap( const QgsProject &project )
165+
{
166+
QHash<QString, QString> aliasMap;
167+
168+
//WMSFeatureInfoAliasLayers
169+
QStringList aliasLayerStringList = project.readListEntry( QStringLiteral( "WMSFeatureInfoAliasLayers" ), QStringLiteral( "/value" ), QStringList() );
170+
if ( aliasLayerStringList.isEmpty() )
171+
{
172+
return aliasMap;
173+
}
174+
175+
//WMSFeatureInfoLayerAliases
176+
QStringList layerAliasStringList = project.readListEntry( QStringLiteral( "WMSFeatureInfoLayerAliases" ), QStringLiteral( "/value" ), QStringList() );
177+
if ( layerAliasStringList.isEmpty() )
178+
{
179+
return aliasMap;
180+
}
181+
182+
int nMapEntries = qMin( aliasLayerStringList.size(), layerAliasStringList.size() );
183+
for ( int i = 0; i < nMapEntries; ++i )
184+
{
185+
aliasMap.insert( aliasLayerStringList.at( i ), layerAliasStringList.at( i ) );
186+
}
187+
188+
return aliasMap;
189+
}
190+
120191
bool QgsServerProjectUtils::wmsInspireActivate( const QgsProject &project )
121192
{
122193
return project.readBoolEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/activated" ) );

‎src/server/qgsserverprojectutils.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,48 @@ namespace QgsServerProjectUtils
132132
*/
133133
SERVER_EXPORT bool wmsInfoFormatSia2045( const QgsProject &project );
134134

135+
/** Returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
136+
* \param project the QGIS project
137+
* \returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
138+
*/
139+
SERVER_EXPORT bool wmsFeatureInfoAddWktGeometry( const QgsProject &project );
140+
141+
/** Returns if the geometry has to be segmentize in GetFeatureInfo request.
142+
* \param project the QGIS project
143+
* \returns if the geometry has to be segmentize in GetFeatureInfo request.
144+
*/
145+
SERVER_EXPORT bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
146+
147+
/** Returns the geometry precision for GetFeatureInfo request.
148+
* \param project the QGIS project
149+
* \returns the geometry precision for GetFeatureInfo request.
150+
*/
151+
SERVER_EXPORT int wmsFeatureInfoPrecision( const QgsProject &project );
152+
153+
/** Returns the document element name for XML GetFeatureInfo request.
154+
* \param project the QGIS project
155+
* \returns the document element name for XML GetFeatureInfo request.
156+
*/
157+
SERVER_EXPORT QString wmsFeatureInfoDocumentElement( const QgsProject &project );
158+
159+
/** Returns the document element namespace for XML GetFeatureInfo request.
160+
* \param project the QGIS project
161+
* \returns the document element namespace for XML GetFeatureInfo request.
162+
*/
163+
SERVER_EXPORT QString wmsFeatureInfoDocumentElementNs( const QgsProject &project );
164+
165+
/** Returns the schema URL for XML GetFeatureInfo request.
166+
* \param project the QGIS project
167+
* \returns the schema URL for XML GetFeatureInfo request.
168+
*/
169+
SERVER_EXPORT QString wmsFeatureInfoSchema( const QgsProject &project );
170+
171+
/** Returns the mapping between layer name and wms layer name for GetFeatureInfo request.
172+
* \param project the QGIS project
173+
* \returns the mapping between layer name and wms layer name for GetFeatureInfo request.
174+
*/
175+
SERVER_EXPORT QHash<QString, QString> wmsFeatureInfoLayerAliasMap( const QgsProject &project );
176+
135177
/** Returns if Inspire is activated.
136178
* \param project the QGIS project
137179
* \returns if Inspire is activated.

‎src/server/services/wms/qgswmsgetfeatureinfo.cpp

Lines changed: 5 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -25,136 +25,6 @@
2525
namespace QgsWms
2626
{
2727

28-
void writeInfoResponse( QDomDocument &infoDoc, QgsServerResponse &response, const QString &infoFormat )
29-
{
30-
QByteArray ba;
31-
QgsMessageLog::logMessage( "Info format is:" + infoFormat );
32-
33-
if ( infoFormat == QLatin1String( "text/xml" ) || infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
34-
{
35-
ba = infoDoc.toByteArray();
36-
}
37-
else if ( infoFormat == QLatin1String( "text/plain" ) || infoFormat == QLatin1String( "text/html" ) )
38-
{
39-
//create string
40-
QString featureInfoString;
41-
42-
if ( infoFormat == QLatin1String( "text/plain" ) )
43-
{
44-
featureInfoString.append( "GetFeatureInfo results\n" );
45-
featureInfoString.append( "\n" );
46-
}
47-
else if ( infoFormat == QLatin1String( "text/html" ) )
48-
{
49-
featureInfoString.append( "<HEAD>\n" );
50-
featureInfoString.append( "<TITLE> GetFeatureInfo results </TITLE>\n" );
51-
featureInfoString.append( "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n" );
52-
featureInfoString.append( "</HEAD>\n" );
53-
featureInfoString.append( "<BODY>\n" );
54-
}
55-
56-
QDomNodeList layerList = infoDoc.elementsByTagName( QStringLiteral( "Layer" ) );
57-
58-
//layer loop
59-
for ( int i = 0; i < layerList.size(); ++i )
60-
{
61-
QDomElement layerElem = layerList.at( i ).toElement();
62-
if ( infoFormat == QLatin1String( "text/plain" ) )
63-
{
64-
featureInfoString.append( "Layer '" + layerElem.attribute( QStringLiteral( "name" ) ) + "'\n" );
65-
}
66-
else if ( infoFormat == QLatin1String( "text/html" ) )
67-
{
68-
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
69-
featureInfoString.append( "<TR><TH width=25%>Layer</TH><TD>" + layerElem.attribute( QStringLiteral( "name" ) ) + "</TD></TR>\n" );
70-
featureInfoString.append( "</BR>" );
71-
}
72-
73-
//feature loop (for vector layers)
74-
QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral( "Feature" ) );
75-
QDomElement currentFeatureElement;
76-
77-
if ( featureNodeList.isEmpty() ) //raster layer?
78-
{
79-
QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
80-
for ( int j = 0; j < attributeNodeList.size(); ++j )
81-
{
82-
QDomElement attributeElement = attributeNodeList.at( j ).toElement();
83-
if ( infoFormat == QLatin1String( "text/plain" ) )
84-
{
85-
featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
86-
attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" );
87-
}
88-
else if ( infoFormat == QLatin1String( "text/html" ) )
89-
{
90-
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) + "</TH><TD>" +
91-
attributeElement.attribute( QStringLiteral( "value" ) ) + "</TD></TR>\n" );
92-
}
93-
}
94-
}
95-
else //vector layer
96-
{
97-
for ( int j = 0; j < featureNodeList.size(); ++j )
98-
{
99-
QDomElement featureElement = featureNodeList.at( j ).toElement();
100-
if ( infoFormat == QLatin1String( "text/plain" ) )
101-
{
102-
featureInfoString.append( "Feature " + featureElement.attribute( QStringLiteral( "id" ) ) + "\n" );
103-
}
104-
else if ( infoFormat == QLatin1String( "text/html" ) )
105-
{
106-
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
107-
featureInfoString.append( "<TR><TH>Feature</TH><TD>" + featureElement.attribute( QStringLiteral( "id" ) ) + "</TD></TR>\n" );
108-
}
109-
//attribute loop
110-
QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral( "Attribute" ) );
111-
for ( int k = 0; k < attributeNodeList.size(); ++k )
112-
{
113-
QDomElement attributeElement = attributeNodeList.at( k ).toElement();
114-
if ( infoFormat == QLatin1String( "text/plain" ) )
115-
{
116-
featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
117-
attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" );
118-
}
119-
else if ( infoFormat == QLatin1String( "text/html" ) )
120-
{
121-
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) + "</TH><TD>" + attributeElement.attribute( QStringLiteral( "value" ) ) + "</TD></TR>\n" );
122-
}
123-
}
124-
125-
if ( infoFormat == QLatin1String( "text/html" ) )
126-
{
127-
featureInfoString.append( "</TABLE>\n</BR>\n" );
128-
}
129-
}
130-
}
131-
if ( infoFormat == QLatin1String( "text/plain" ) )
132-
{
133-
featureInfoString.append( "\n" );
134-
}
135-
else if ( infoFormat == QLatin1String( "text/html" ) )
136-
{
137-
featureInfoString.append( "</TABLE>\n<BR></BR>\n" );
138-
139-
}
140-
}
141-
if ( infoFormat == QLatin1String( "text/html" ) )
142-
{
143-
featureInfoString.append( "</BODY>\n" );
144-
}
145-
ba = featureInfoString.toUtf8();
146-
}
147-
else //unsupported format, set exception
148-
{
149-
throw QgsServiceException( QStringLiteral( "InvalidFormat" ),
150-
QString( "Feature info format '%1' is not supported. Possibilities are 'text/plain', 'text/html' or 'text/xml'." ).arg( infoFormat ) );
151-
}
152-
153-
response.setHeader( QStringLiteral( "Content-Type" ), infoFormat + QStringLiteral( "; charset=utf-8" ) );
154-
response.write( ba );
155-
}
156-
157-
15828
void writeGetFeatureInfo( QgsServerInterface *serverIface, const QgsProject *project,
15929
const QString &version, const QgsServerRequest &request,
16030
QgsServerResponse &response )
@@ -163,9 +33,11 @@ namespace QgsWms
16333
QgsServerRequest::Parameters params = request.parameters();
16434
QgsRenderer renderer( serverIface, project, params, getConfigParser( serverIface ) );
16535

166-
QDomDocument doc = renderer.getFeatureInfo( version );
167-
QString outputFormat = params.value( QStringLiteral( "INFO_FORMAT" ), QStringLiteral( "text/plain" ) );
168-
writeInfoResponse( doc, response, outputFormat );
36+
std::unique_ptr<QByteArray> result( renderer.getFeatureInfo( version ) );
37+
QString infoFormat = params.value( QStringLiteral( "INFO_FORMAT" ), QStringLiteral( "text/plain" ) );
38+
39+
response.setHeader( QStringLiteral( "Content-Type" ), infoFormat + QStringLiteral( "; charset=utf-8" ) );
40+
response.write( *result );
16941
}
17042

17143

‎src/server/services/wms/qgswmsparameters.cpp

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,41 @@ namespace QgsWms
191191
};
192192
save( pFormat );
193193

194+
const Parameter pInfoFormat = { ParameterName::INFO_FORMAT,
195+
QVariant::String,
196+
QVariant( "" ),
197+
QVariant()
198+
};
199+
save( pInfoFormat );
200+
201+
const Parameter pI = { ParameterName::I,
202+
QVariant::Int,
203+
QVariant( -1 ),
204+
QVariant()
205+
};
206+
save( pI );
207+
208+
const Parameter pJ = { ParameterName::J,
209+
QVariant::Int,
210+
QVariant( -1 ),
211+
QVariant()
212+
};
213+
save( pJ );
214+
215+
const Parameter pX = { ParameterName::X,
216+
QVariant::Int,
217+
QVariant( -1 ),
218+
QVariant()
219+
};
220+
save( pX );
221+
222+
const Parameter pY = { ParameterName::Y,
223+
QVariant::Int,
224+
QVariant( -1 ),
225+
QVariant()
226+
};
227+
save( pY );
228+
194229
const Parameter pRule = { ParameterName::RULE,
195230
QVariant::String,
196231
QVariant( "" ),
@@ -254,6 +289,20 @@ namespace QgsWms
254289
};
255290
save( pLayers );
256291

292+
const Parameter pQueryLayers = { ParameterName::QUERY_LAYERS,
293+
QVariant::String,
294+
QVariant( "" ),
295+
QVariant()
296+
};
297+
save( pQueryLayers );
298+
299+
const Parameter pFeatureCount = { ParameterName::FEATURE_COUNT,
300+
QVariant::Int,
301+
QVariant( 1 ),
302+
QVariant()
303+
};
304+
save( pFeatureCount );
305+
257306
const Parameter pLayerTitle = { ParameterName::LAYERTITLE,
258307
QVariant::Bool,
259308
QVariant( true ),
@@ -324,12 +373,26 @@ namespace QgsWms
324373
};
325374
save( pFilter );
326375

376+
const Parameter pFilterGeom = { ParameterName::FILTER_GEOM,
377+
QVariant::String,
378+
QVariant( "" ),
379+
QVariant()
380+
};
381+
save( pFilterGeom );
382+
327383
const Parameter pSelection = { ParameterName::SELECTION,
328384
QVariant::String,
329385
QVariant( "" ),
330386
QVariant()
331387
};
332388
save( pSelection );
389+
390+
const Parameter pWmsPrecision = { ParameterName::WMS_PRECISION,
391+
QVariant::Int,
392+
QVariant( -1 ),
393+
QVariant()
394+
};
395+
save( pWmsPrecision );
333396
}
334397

335398
QgsWmsParameters::QgsWmsParameters( const QgsServerRequest::Parameters &parameters )
@@ -628,9 +691,12 @@ namespace QgsWms
628691

629692
QgsWmsParameters::Format QgsWmsParameters::format() const
630693
{
631-
Format f = Format::PNG;
632694
QString fStr = formatAsString();
633695

696+
if ( fStr.isEmpty() )
697+
return Format::NONE;
698+
699+
Format f = Format::PNG;
634700
if ( fStr.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0
635701
|| fStr.compare( QLatin1String( "jpeg" ), Qt::CaseInsensitive ) == 0
636702
|| fStr.compare( QLatin1String( "image/jpeg" ), Qt::CaseInsensitive ) == 0 )
@@ -639,6 +705,81 @@ namespace QgsWms
639705
return f;
640706
}
641707

708+
QString QgsWmsParameters::infoFormatAsString() const
709+
{
710+
return value( ParameterName::INFO_FORMAT ).toString();
711+
}
712+
713+
QgsWmsParameters::Format QgsWmsParameters::infoFormat() const
714+
{
715+
QString fStr = infoFormatAsString();
716+
717+
Format f = Format::TEXT;
718+
if ( fStr.isEmpty() )
719+
return f;
720+
721+
if ( fStr.startsWith( QLatin1String( "text/xml" ), Qt::CaseInsensitive ) )
722+
f = Format::XML;
723+
else if ( fStr.startsWith( QLatin1String( "text/html" ), Qt::CaseInsensitive ) )
724+
f = Format::HTML;
725+
else if ( fStr.startsWith( QLatin1String( "application/vnd.ogc.gml" ), Qt::CaseInsensitive ) )
726+
f = Format::GML;
727+
728+
return f;
729+
}
730+
731+
int QgsWmsParameters::infoFormatVersion() const
732+
{
733+
if ( infoFormat() != Format::GML )
734+
return -1;
735+
736+
QString fStr = infoFormatAsString();
737+
if ( fStr.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ), Qt::CaseInsensitive ) )
738+
return 3;
739+
else
740+
return 2;
741+
}
742+
743+
QString QgsWmsParameters::i() const
744+
{
745+
return value( ParameterName::I ).toString();
746+
}
747+
748+
QString QgsWmsParameters::j() const
749+
{
750+
return value( ParameterName::J ).toString();
751+
}
752+
753+
int QgsWmsParameters::iAsInt() const
754+
{
755+
return toInt( ParameterName::I );
756+
}
757+
758+
int QgsWmsParameters::jAsInt() const
759+
{
760+
return toInt( ParameterName::J );
761+
}
762+
763+
QString QgsWmsParameters::x() const
764+
{
765+
return value( ParameterName::X ).toString();
766+
}
767+
768+
QString QgsWmsParameters::y() const
769+
{
770+
return value( ParameterName::Y ).toString();
771+
}
772+
773+
int QgsWmsParameters::xAsInt() const
774+
{
775+
return toInt( ParameterName::X );
776+
}
777+
778+
int QgsWmsParameters::yAsInt() const
779+
{
780+
return toInt( ParameterName::Y );
781+
}
782+
642783
QString QgsWmsParameters::rule() const
643784
{
644785
return value( ParameterName::RULE ).toString();
@@ -674,6 +815,16 @@ namespace QgsWms
674815
return toBool( ParameterName::SHOWFEATURECOUNT );
675816
}
676817

818+
QString QgsWmsParameters::featureCount() const
819+
{
820+
return value( ParameterName::FEATURE_COUNT ).toString();
821+
}
822+
823+
int QgsWmsParameters::featureCountAsInt() const
824+
{
825+
return toInt( ParameterName::FEATURE_COUNT );
826+
}
827+
677828
QString QgsWmsParameters::boxSpace() const
678829
{
679830
return value( ParameterName::BOXSPACE ).toString();
@@ -960,6 +1111,16 @@ namespace QgsWms
9601111
return toFloatList( highlightLabelBufferSize(), ParameterName::HIGHLIGHT_LABELBUFFERSIZE );
9611112
}
9621113

1114+
QString QgsWmsParameters::wmsPrecision() const
1115+
{
1116+
return value( ParameterName::WMS_PRECISION ).toString();
1117+
}
1118+
1119+
int QgsWmsParameters::wmsPrecisionAsInt() const
1120+
{
1121+
return toInt( ParameterName::WMS_PRECISION );
1122+
}
1123+
9631124
QString QgsWmsParameters::sld() const
9641125
{
9651126
return value( ParameterName::SLD ).toString();
@@ -970,6 +1131,11 @@ namespace QgsWms
9701131
return toStringList( ParameterName::FILTER, ';' );
9711132
}
9721133

1134+
QString QgsWmsParameters::filterGeom() const
1135+
{
1136+
return value( ParameterName::FILTER_GEOM ).toString();
1137+
}
1138+
9731139
QStringList QgsWmsParameters::selections() const
9741140
{
9751141
return toStringList( ParameterName::SELECTION );
@@ -992,6 +1158,11 @@ namespace QgsWms
9921158
return layer << layers;
9931159
}
9941160

1161+
QStringList QgsWmsParameters::queryLayersNickname() const
1162+
{
1163+
return toStringList( ParameterName::QUERY_LAYERS );
1164+
}
1165+
9951166
QStringList QgsWmsParameters::allStyles() const
9961167
{
9971168
QStringList style = value( ParameterName::STYLE ).toString().split( ",", QString::SkipEmptyParts );

‎src/server/services/wms/qgswmsparameters.h

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ namespace QgsWms
8686
LAYERS,
8787
LAYERSPACE,
8888
LAYERTITLESPACE,
89+
QUERY_LAYERS,
90+
FEATURE_COUNT,
8991
SHOWFEATURECOUNT,
9092
STYLE,
9193
STYLES,
@@ -95,7 +97,13 @@ namespace QgsWms
9597
OPACITIES,
9698
SLD,
9799
FILTER,
100+
FILTER_GEOM,
98101
FORMAT,
102+
INFO_FORMAT,
103+
I,
104+
J,
105+
X,
106+
Y,
99107
RULE,
100108
RULELABEL,
101109
SCALE,
@@ -108,15 +116,20 @@ namespace QgsWms
108116
HIGHLIGHT_LABELWEIGHT,
109117
HIGHLIGHT_LABELCOLOR,
110118
HIGHLIGHT_LABELBUFFERCOLOR,
111-
HIGHLIGHT_LABELBUFFERSIZE
119+
HIGHLIGHT_LABELBUFFERSIZE,
120+
WMS_PRECISION
112121
};
113122
Q_ENUM( ParameterName )
114123

115124
enum Format
116125
{
117126
NONE,
118127
JPG,
119-
PNG
128+
PNG,
129+
TEXT,
130+
XML,
131+
HTML,
132+
GML
120133
};
121134

122135
struct Parameter
@@ -203,6 +216,11 @@ namespace QgsWms
203216
*/
204217
QStringList filters() const;
205218

219+
/** Returns the filter geometry found in FILTER_GEOM parameter.
220+
* \returns the filter geometry as Well Known Text.
221+
*/
222+
QString filterGeom() const;
223+
206224
/** Returns the list of opacities found in OPACITIES parameter.
207225
* \returns the list of opacities in string
208226
*/
@@ -221,6 +239,11 @@ namespace QgsWms
221239
*/
222240
QStringList allLayersNickname() const;
223241

242+
/** Returns nickname of layers found in QUERY_LAYERS parameter.
243+
* \returns nickname of layers
244+
*/
245+
QStringList queryLayersNickname() const;
246+
224247
/** Returns styles found in STYLE and STYLES parameters.
225248
* \returns name of styles
226249
*/
@@ -242,6 +265,75 @@ namespace QgsWms
242265
*/
243266
Format format() const;
244267

268+
/** Returns INFO_FORMAT parameter as a string.
269+
* \returns INFO_FORMAT parameter as string
270+
*/
271+
QString infoFormatAsString() const;
272+
273+
/** Returns infoFormat. If the INFO_FORMAT parameter is not used, then the
274+
* default value is text/plain.
275+
* \returns infoFormat
276+
*/
277+
Format infoFormat() const;
278+
279+
/** Returns the infoFormat version for GML. If the INFO_FORMAT is not GML,
280+
* then the default value is -1.
281+
* \returns infoFormat version
282+
*/
283+
int infoFormatVersion() const;
284+
285+
/** Returns I parameter or an empty string if not defined.
286+
* \returns i parameter
287+
*/
288+
QString i() const;
289+
290+
/** Returns I parameter as an int or its default value if not
291+
* defined. An exception is raised if I is defined and cannot be
292+
* converted.
293+
* \returns i parameter
294+
* \throws QgsBadRequestException
295+
*/
296+
int iAsInt() const;
297+
298+
/** Returns J parameter or an empty string if not defined.
299+
* \returns j parameter
300+
*/
301+
QString j() const;
302+
303+
/** Returns J parameter as an int or its default value if not
304+
* defined. An exception is raised if J is defined and cannot be
305+
* converted.
306+
* \returns j parameter
307+
* \throws QgsBadRequestException
308+
*/
309+
int jAsInt() const;
310+
311+
/** Returns X parameter or an empty string if not defined.
312+
* \returns x parameter
313+
*/
314+
QString x() const;
315+
316+
/** Returns X parameter as an int or its default value if not
317+
* defined. An exception is raised if X is defined and cannot be
318+
* converted.
319+
* \returns x parameter
320+
* \throws QgsBadRequestException
321+
*/
322+
int xAsInt() const;
323+
324+
/** Returns Y parameter or an empty string if not defined.
325+
* \returns y parameter
326+
*/
327+
QString y() const;
328+
329+
/** Returns Y parameter as an int or its default value if not
330+
* defined. An exception is raised if Y is defined and cannot be
331+
* converted.
332+
* \returns j parameter
333+
* \throws QgsBadRequestException
334+
*/
335+
int yAsInt() const;
336+
245337
/** Returns RULE parameter or an empty string if none is defined
246338
* \returns RULE parameter or an empty string if none is defined
247339
*/
@@ -271,6 +363,18 @@ namespace QgsWms
271363
*/
272364
bool showFeatureCountAsBool() const;
273365

366+
/** Returns FEATURE_COUNT parameter or an empty string if none is defined
367+
* \returns FEATURE_COUNT parameter or an empty string if none is defined
368+
*/
369+
QString featureCount() const;
370+
371+
/** Returns FEATURE_COUNT as an integer. An exception is raised if an invalid
372+
* parameter is found.
373+
* \returns FeatureCount
374+
* \throws QgsBadRequestException
375+
*/
376+
int featureCountAsInt() const;
377+
274378
/** Returns SCALE parameter or an empty string if none is defined
275379
* \returns SCALE parameter or an empty string if none is defined
276380
*/
@@ -595,6 +699,19 @@ namespace QgsWms
595699
*/
596700
QList<QColor> highlightLabelBufferColorAsColor() const;
597701

702+
/** Returns WMS_PRECISION parameter or an empty string if not defined.
703+
* \returns wms precision parameter
704+
*/
705+
QString wmsPrecision() const;
706+
707+
/** Returns WMS_PRECISION parameter as an int or its default value if not
708+
* defined. An exception is raised if WMS_PRECISION is defined and cannot be
709+
* converted.
710+
* \returns wms precision parameter
711+
* \throws QgsBadRequestException
712+
*/
713+
int wmsPrecisionAsInt() const;
714+
598715
private:
599716
QString name( ParameterName name ) const;
600717
void raiseError( ParameterName name ) const;

‎src/server/services/wms/qgswmsrenderer.cpp

Lines changed: 461 additions & 330 deletions
Large diffs are not rendered by default.

‎src/server/services/wms/qgswmsrenderer.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ namespace QgsWms
116116
/** Creates an xml document that describes the result of the getFeatureInfo request.
117117
* May throw an exception
118118
*/
119-
QDomDocument getFeatureInfo( const QString &version = "1.3.0" );
119+
QByteArray *getFeatureInfo( const QString &version = "1.3.0" );
120120

121121
private:
122122

@@ -140,6 +140,9 @@ namespace QgsWms
140140
// Remove unwanted layers (restricted, not visible, etc)
141141
void removeUnwantedLayers( QList<QgsMapLayer *> &layers, double scaleDenominator = -1 ) const;
142142

143+
// Remove non identifiable layers (restricted, not visible, etc)
144+
void removeNonIdentifiableLayers( QList<QgsMapLayer *> &layers ) const;
145+
143146
// Rendering step for layers
144147
QPainter *layersRendering( const QgsMapSettings &mapSettings, QImage &image, HitTest *hitTest = nullptr ) const;
145148

@@ -211,6 +214,9 @@ namespace QgsWms
211214
*/
212215
void initializeSLDParser( QStringList &layersList, QStringList &stylesList );
213216

217+
QDomDocument featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings,
218+
const QImage *outputImage, const QString &version ) const;
219+
214220
/** Appends feature info xml for the layer to the layer element of the feature info dom document
215221
\param featureBBox the bounding box of the selected features in output CRS
216222
\returns true in case of success*/
@@ -222,7 +228,6 @@ namespace QgsWms
222228
const QgsMapSettings &mapSettings,
223229
QgsRenderContext &renderContext,
224230
const QString &version,
225-
const QString &infoFormat,
226231
QgsRectangle *featureBBox = nullptr,
227232
QgsGeometry *filterGeom = nullptr ) const;
228233
//! Appends feature info xml for the layer to the layer element of the dom document
@@ -231,8 +236,7 @@ namespace QgsWms
231236
const QgsPointXY *infoPoint,
232237
QDomDocument &infoDocument,
233238
QDomElement &layerElement,
234-
const QString &version,
235-
const QString &infoFormat ) const;
239+
const QString &version ) const;
236240

237241
/** Creates a layer set and returns a stringlist with layer ids that can be passed to a renderer. Usually used in conjunction with readLayersAndStyles
238242
\param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
@@ -291,7 +295,13 @@ namespace QgsWms
291295
bool checkMaximumWidthHeight() const;
292296

293297
//! Converts a feature info xml document to SIA2045 norm
294-
void convertFeatureInfoToSIA2045( QDomDocument &doc );
298+
void convertFeatureInfoToSia2045( QDomDocument &doc ) const;
299+
300+
//! Converts a feature info xml document to HTML
301+
QByteArray convertFeatureInfoToHtml( const QDomDocument &doc ) const;
302+
303+
//! Converts a feature info xml document to Text
304+
QByteArray convertFeatureInfoToText( const QDomDocument &doc ) const;
295305

296306
QDomElement createFeatureGML(
297307
QgsFeature *feat,
@@ -334,7 +344,7 @@ namespace QgsWms
334344
int getImageQuality() const;
335345

336346
//! Return precision to use for GetFeatureInfo request
337-
int getWMSPrecision( int defaultValue ) const;
347+
int getWMSPrecision() const;
338348

339349
};
340350

‎tests/src/python/test_qgsserver_accesscontrol.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,33 @@ def test_wms_getfeatureinfo_hello(self):
453453
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
454454
"No color in result of GetFeatureInfo\n%s" % response)
455455

456+
response, headers = self._get_restricted(query_string)
457+
self.assertEqual(
458+
headers.get("Content-Type"), "text/xml; charset=utf-8",
459+
"Content type for GetFeatureInfo is wrong: %s" % headers.get("Content-Type"))
460+
self.assertTrue(
461+
str(response).find('<ServiceException code="Security">') != -1,
462+
"Not allowed do a GetFeatureInfo on Country"
463+
)
464+
465+
query_string = "&".join(["%s=%s" % i for i in list({
466+
"MAP": urllib.parse.quote(self.projectPath),
467+
"SERVICE": "WMS",
468+
"VERSION": "1.1.1",
469+
"REQUEST": "GetFeatureInfo",
470+
"LAYERS": "Hello",
471+
"QUERY_LAYERS": "Hello",
472+
"STYLES": "",
473+
"FORMAT": "image/png",
474+
"BBOX": "-16817707,-6318936.5,5696513,16195283.5",
475+
"HEIGHT": "500",
476+
"WIDTH": "500",
477+
"SRS": "EPSG:3857",
478+
"FEATURE_COUNT": "10",
479+
"INFO_FORMAT": "application/vnd.ogc.gml",
480+
"X": "56",
481+
"Y": "144"
482+
}.items())])
456483
response, headers = self._get_restricted(query_string)
457484
self.assertTrue(
458485
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
@@ -1053,6 +1080,33 @@ def test_wms_getfeatureinfo_subsetstring(self):
10531080
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
10541081
"No good result in GetFeatureInfo Hello/1\n%s" % response)
10551082

1083+
response, headers = self._get_restricted(query_string)
1084+
self.assertEqual(
1085+
headers.get("Content-Type"), "text/xml; charset=utf-8",
1086+
"Content type for GetFeatureInfo is wrong: %s" % headers.get("Content-Type"))
1087+
self.assertTrue(
1088+
str(response).find('<ServiceException code="Security">') != -1,
1089+
"Not allowed do a GetFeatureInfo on Country"
1090+
)
1091+
1092+
query_string = "&".join(["%s=%s" % i for i in list({
1093+
"SERVICE": "WMS",
1094+
"VERSION": "1.1.1",
1095+
"REQUEST": "GetFeatureInfo",
1096+
"LAYERS": "Hello_SubsetString",
1097+
"QUERY_LAYERS": "Hello_SubsetString",
1098+
"STYLES": "",
1099+
"FORMAT": "image/png",
1100+
"BBOX": "-16817707,-6318936.5,5696513,16195283.5",
1101+
"HEIGHT": "500",
1102+
"WIDTH": "500",
1103+
"SRS": "EPSG:3857",
1104+
"FEATURE_COUNT": "10",
1105+
"INFO_FORMAT": "application/vnd.ogc.gml",
1106+
"X": "56",
1107+
"Y": "144",
1108+
"MAP": urllib.parse.quote(self.projectPath)
1109+
}.items())])
10561110
response, headers = self._get_restricted(query_string)
10571111
self.assertTrue(
10581112
str(response).find("<qgs:pk>") != -1,

‎tests/src/python/test_qgsserver_wms.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,16 @@ def test_project_wms(self):
6969
for request in ('GetCapabilities', 'GetProjectSettings', 'GetContext'):
7070
self.wms_request_compare(request)
7171

72-
# Test getfeatureinfo response
72+
# Test getfeatureinfo response xml
73+
self.wms_request_compare('GetFeatureInfo',
74+
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
75+
'info_format=text%2Fxml&transparent=true&' +
76+
'width=600&height=400&srs=EPSG%3A3857&bbox=913190.6389747962%2C' +
77+
'5606005.488876367%2C913235.426296057%2C5606035.347090538&' +
78+
'query_layers=testlayer%20%C3%A8%C3%A9&X=190&Y=320',
79+
'wms_getfeatureinfo-text-xml')
80+
81+
# Test getfeatureinfo response html
7382
self.wms_request_compare('GetFeatureInfo',
7483
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
7584
'info_format=text%2Fhtml&transparent=true&' +
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
*****
2+
Content-Type: text/xml; charset=utf-8
3+
4+
<GetFeatureInfoResponse>
5+
<Layer name="testlayer èé">
6+
<Feature id="2">
7+
<Attribute value="3" name="id"/>
8+
<Attribute value="three" name="name"/>
9+
<Attribute value="three èé↓" name="utf8nameè"/>
10+
<BoundingBox maxy="5606011.4565" maxx="913204.9128" miny="5606011.4565" CRS="EPSG:3857" minx="913204.9128"/>
11+
<Attribute type="derived" value="Point (913204.9128 5606011.4565)" name="geometry"/>
12+
</Feature>
13+
</Layer>
14+
</GetFeatureInfoResponse>

0 commit comments

Comments
 (0)
Please sign in to comment.