30 , mInterface( interface )
37 qDeleteAll( mExternalLayers );
38 mExternalLayers.clear();
45 initRestrictedLayers();
48 searchLayersToRender();
49 removeUnwantedLayers();
51 std::reverse( mLayersToRender.begin(), mLayersToRender.end() );
54bool QgsWmsRenderContext::addLayerToRender(
QgsMapLayer *layer )
56 const bool allowed = checkLayerReadPermissions(
layer );
59 mLayersToRender.append(
layer );
79 return mFlags.testFlag( flag );
102 if ( mSlds.contains( nickname ) )
104 sld = mSlds[ nickname ];
115 if ( mStyles.contains( nickname ) )
117 style = mStyles[ nickname ];
127 const QList<QgsWmsParametersLayer> cLayerParams { mParameters.
layersParameters() };
129 for (
const auto ¶ms : std::as_const( cLayerParams ) )
189 if ( !mParameters.
dpi().isEmpty() )
201 std::function <QStringList(
const QString &name )> findLeaves = [ & ](
const QString & name ) -> QStringList
204 if ( mLayerGroups.contains( name ) )
206 const auto &
layers { mLayerGroups[ name ] };
207 for (
const auto &l :
layers )
210 if ( checkLayerReadPermissions( l ) )
214 if ( mLayerGroups.contains( nick ) )
216 _result.append( name );
220 _result.append( findLeaves( nick ) );
227 _result.append( name );
232 for (
const auto &name : std::as_const( layerNames ) )
234 result.append( findLeaves( name ) );
241 return mLayersToRender;
246 return mNicknameLayers.values();
251 double denominator = -1;
253 if ( mScaleDenominator >= 0 )
255 denominator = mScaleDenominator;
268 removeUnwantedLayers();
288 std::find_if( mExternalLayers.cbegin(), mExternalLayers.cend(),
291 return l->id() == layer.id();
292 } ) == mExternalLayers.cend() )
296 else if ( name.isEmpty() )
308 for (
auto layer : mLayersToRender )
322 return layer( nickname );
327 return mLayerGroups.value( nickname );
332 return mLayerGroups.contains( name );
335void QgsWmsRenderContext::initNicknameLayers()
346 initLayerGroupsRecursive( root, rootName.isEmpty() ? mProject->
title() : rootName );
349void QgsWmsRenderContext::initLayerGroupsRecursive(
const QgsLayerTreeGroup *group,
const QString &groupName )
351 if ( !groupName.isEmpty() )
353 QList<QgsMapLayer *> layerGroup;
354 const auto projectLayerTreeRoot { mProject->
layerTreeRoot() };
355 const auto treeGroupLayers { group->
findLayers() };
358 if ( ! projectLayerTreeRoot->hasCustomLayerOrder() )
360 for (
const auto &tl : treeGroupLayers )
362 layerGroup.push_back( tl->layer() );
367 const auto projectLayerOrder { projectLayerTreeRoot->layerOrder() };
369 QList<QgsMapLayer *> groupLayersList;
370 for (
const auto &tl : treeGroupLayers )
372 groupLayersList << tl->layer();
374 for (
const auto &l : projectLayerOrder )
376 if ( groupLayersList.contains( l ) )
378 layerGroup.push_back( l );
383 if ( !layerGroup.empty() )
385 mLayerGroups[groupName] = layerGroup;
393 QString name = child->customProperty( QStringLiteral(
"wmsShortName" ) ).toString();
395 if ( name.isEmpty() )
396 name = child->name();
398 initLayerGroupsRecursive(
static_cast<const QgsLayerTreeGroup *
>( child ), name );
404void QgsWmsRenderContext::initRestrictedLayers()
406 mRestrictedLayers.clear();
412 QStringList restrictedLayersNames;
415 for (
const QString &l : std::as_const( restricted ) )
420 const QList<QgsLayerTreeLayer *> groupLayers = group->
findLayers();
423 restrictedLayersNames.append( treeLayer->name() );
428 restrictedLayersNames.append( l );
436 if ( restrictedLayersNames.contains(
layer->
name() ) )
443void QgsWmsRenderContext::searchLayersToRender()
445 mLayersToRender.clear();
449 if ( ! mParameters.
sldBody().isEmpty() )
451 searchLayersToRenderSld();
455 searchLayersToRenderStyle();
461 for (
const QString &layerName : queryLayerNames )
463 const QList<QgsMapLayer *>
layers = mNicknameLayers.values( layerName );
466 if ( !mLayersToRender.contains( lyr ) )
468 if ( !addLayerToRender( lyr ) )
470 throw QgsSecurityException( QStringLiteral(
"Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
481 for (
const QString &layerName : queryLayerNames )
483 const QList<QgsMapLayer *>
layers = mNicknameLayers.values( layerName );
486 if ( !mLayersToRender.contains( lyr ) )
488 if ( !addLayerToRender( lyr ) )
490 throw QgsSecurityException( QStringLiteral(
"Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
499void QgsWmsRenderContext::searchLayersToRenderSld()
509 ( void )doc.setContent(
sld,
true );
510 QDomElement docEl = doc.documentElement();
512 QDomElement root = doc.firstChildElement(
"StyledLayerDescriptor" );
513 QDomElement namedElem = root.firstChildElement(
"NamedLayer" );
515 if ( docEl.isNull() )
520 QDomNodeList named = docEl.elementsByTagName(
"NamedLayer" );
521 for (
int i = 0; i < named.size(); ++i )
523 QDomNodeList names = named.item( i ).toElement().elementsByTagName(
"Name" );
524 if ( !names.isEmpty() )
526 QString lname = names.item( 0 ).toElement().text();
527 if ( mNicknameLayers.contains( lname ) )
529 mSlds[lname] = namedElem;
530 for (
const auto layer : mNicknameLayers.values( lname ) )
532 if ( !addLayerToRender(
layer ) )
538 else if ( mLayerGroups.contains( lname ) )
543 param.mValue = lname;
548 bool layerAdded =
false;
552 if ( checkLayerReadPermissions(
layer ) )
555 mSlds[name] = namedElem;
556 mLayersToRender.insert( 0,
layer );
565 param.mValue = lname;
574 param.mValue = lname;
582void QgsWmsRenderContext::searchLayersToRenderStyle()
586 const QString nickname = param.mNickname;
587 const QString
style = param.mStyle;
592 std::unique_ptr<QgsMapLayer>
layer = std::make_unique< QgsRasterLayer >( param.mExternalUri, param.mNickname, QStringLiteral(
"wms" ) );
597 mExternalLayers.append(
layer.release() );
598 auto lyr = mExternalLayers.last();
599 if ( !addLayerToRender( lyr ) )
601 throw QgsSecurityException( QStringLiteral(
"Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
606 else if ( mNicknameLayers.contains( nickname ) )
608 if ( !
style.isEmpty() )
610 mStyles[nickname] =
style;
613 for (
const auto layer : mNicknameLayers.values( nickname ) )
615 if ( !addLayerToRender(
layer ) )
621 else if ( mLayerGroups.contains( nickname ) )
626 param.mValue = nickname;
635 if ( !
style.isEmpty() )
637 mStyles[ nickname ] =
style;
642 bool layerAdded =
false;
645 for (
const auto layer : mNicknameLayers.values( name ) )
647 if ( addLayerToRender(
layer ) )
658 param.mValue = nickname;
666 param.mValue = nickname;
673bool QgsWmsRenderContext::layerScaleVisibility(
const QString &name )
const
675 bool visible =
false;
677 if ( ! mNicknameLayers.contains( name ) )
682 const QList<QgsMapLayer *>
layers = mNicknameLayers.values( name );
686 bool useScaleConstraint = (
scaleDenominator() > 0 && scaleBasedVisibility );
735 if ( width <= 0 || height <= 0 )
744 if ( wmsMaxWidthEnv != -1 && wmsMaxWidthProj != -1 )
747 wmsMaxWidth = std::min( wmsMaxWidthProj, wmsMaxWidthEnv );
752 wmsMaxWidth = std::max( wmsMaxWidthProj, wmsMaxWidthEnv );
755 if ( wmsMaxWidth != -1 && width > wmsMaxWidth )
764 if ( wmsMaxHeightEnv != -1 && wmsMaxHeightProj != -1 )
767 wmsMaxHeight = std::min( wmsMaxHeightProj, wmsMaxHeightEnv );
772 wmsMaxHeight = std::max( wmsMaxHeightProj, wmsMaxHeightEnv );
775 if ( wmsMaxHeight != -1 && height > wmsMaxHeight )
789 switch ( mParameters.
format() )
797 if ( width > ( std::numeric_limits<int>::max() - 31 ) / depth )
800 const int bytes_per_line = ( ( width * depth + 31 ) >> 5 ) << 2;
802 if ( std::numeric_limits<int>::max() / bytes_per_line < height
803 || std::numeric_limits<int>::max() /
sizeof( uchar * ) <
static_cast<uint
>( height ) )
817 if ( !mParameters.
bbox().isEmpty() && extent.
isEmpty() )
842 if ( !mParameters.
bbox().isEmpty() && extent.
isEmpty() )
848 QString
crs = mParameters.
crs();
849 if (
crs.compare(
"CRS:84", Qt::CaseInsensitive ) == 0 )
851 crs = QString(
"EPSG:4326" );
861 if ( !extent.
isEmpty() && height > 0 && width > 0 )
863 const double mapRatio = extent.
width() / extent.
height();
864 const double imageRatio =
static_cast<double>( width ) /
static_cast<double>( height );
868 const double cellsize = ( extent.
width() /
static_cast<double>( width ) ) * 0.5 + ( extent.
height() /
static_cast<double>( height ) ) * 0.5;
869 width = extent.
width() / cellsize;
870 height = extent.
height() / cellsize;
880 else if ( height <= 0 )
886 return QSize( width, height );
889void QgsWmsRenderContext::removeUnwantedLayers()
891 QList<QgsMapLayer *>
layers;
899 if ( !layerScaleVisibility( nickname ) )
902 if ( mRestrictedLayers.contains( nickname ) )
913 if ( ! wfsLayers.contains(
layer->
id() ) )
928 for (
const auto &
layer : mExternalLayers )
937bool QgsWmsRenderContext::checkLayerReadPermissions(
QgsMapLayer *layer )
const
939#ifdef HAVE_SERVER_PYTHON_PLUGINS
940 if ( !accessControl()->layerReadPermission(
layer ) )
942 QString msg = QStringLiteral(
"Checking forbidden access for layer: %1" ).arg(
layer->
name() );
951#ifdef HAVE_SERVER_PYTHON_PLUGINS
960 mSocketFeedback = feedback;
965 return mSocketFeedback;
@ Info
Information message.
A helper class that centralizes restrictions given by all the access control filter plugins.
Exception thrown in case of malformed request.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool hasAxisInverted() const
Returns whether the axis order is inverted for the CRS compared to the order east/north (longitude/la...
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Layer tree group node serves as a container for layers and further groups.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
This class is a base class for nodes in a layer tree.
@ NodeGroup
Container of other groups and layers.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Base class for all map layer types.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A class to describe the version of a project.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QString title() const
Returns the project's title.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
A rectangle specified with double values.
double width() const
Returns the width of the rectangle.
bool isEmpty() const
Returns true if the rectangle has no area.
double height() const
Returns the height of the rectangle.
void invert()
Swap x/y coordinates in the rectangle.
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
virtual QgsServerSettings * serverSettings()=0
Returns the server settings.
Provides a way to retrieve settings by prioritizing according to environment variables,...
int wmsMaxWidth() const
Returns the server-wide max width of a WMS GetMap request.
int wmsMaxHeight() const
Returns the server-wide max height of a WMS GetMap request.
Exception thrown in case of malformed request.
Exception thrown when data access violates access controls.
@ QGIS_InvalidParameterValue
WMS parameter received from the client.
Provides an interface to retrieve and manipulate WMS parameters received from the client.
int wmsPrecisionAsInt() const
Returns WMS_PRECISION parameter as an int or its default value if not defined.
QStringList allLayersNickname() const
Returns nickname of layers found in LAYER and LAYERS parameters.
QgsProjectVersion versionAsNumber() const
Returns VERSION parameter if defined or its default value.
QString scale() const
Returns SCALE parameter or an empty string if none is defined.
double scaleAsDouble() const
Returns SCALE as a double.
QgsRectangle bboxAsRectangle() const
Returns BBOX as a rectangle if defined and valid.
double dpiAsDouble() const
Returns DPI parameter as an int or its default value if not defined.
QList< QgsWmsParametersLayer > layersParameters() const
Returns parameters for each layer found in LAYER/LAYERS.
QString bbox() const
Returns BBOX if defined or an empty string.
int heightAsInt() const
Returns HEIGHT parameter as an int or its default value if not defined.
Format format() const
Returns format.
int widthAsInt() const
Returns WIDTH parameter as an int or its default value if not defined.
QString sldBody() const
Returns SLD_body if defined or an empty string.
int imageQualityAsInt() const
Returns IMAGE_QUALITY parameter as an integer.
int srcHeightAsInt() const
Returns SRCHEIGHT parameter as an int or its default value if not defined.
QString imageQuality() const
Returns IMAGE_QUALITY parameter or an empty string if not defined.
QString crs() const
Returns CRS or an empty string if none is defined.
bool tiledAsBool() const
Returns TILED parameter as a boolean.
QString dpi() const
Returns DPI parameter or an empty string if not defined.
QStringList queryLayersNickname() const
Returns nickname of layers found in QUERY_LAYERS parameter.
int srcWidthAsInt() const
Returns SRCWIDTH parameter as an int or its default value if not defined.
QSize mapSize(bool aspectRatio=true) const
Returns the size (in pixels) of the map to render, according to width and height WMS parameters as we...
bool isExternalLayer(const QString &name) const
Returns true if the layer is an external layer, false otherwise.
bool isValidGroup(const QString &name) const
Returns true if name is a group.
QStringList flattenedQueryLayers(const QStringList &layerNames) const
Returns a list of query layer names where group names are replaced by the names of their layer compon...
QgsFeedback * socketFeedback() const
Returns the response feedback if any.
QgsWmsRenderContext(const QgsProject *project, QgsServerInterface *interface)
Constructor for QgsWmsRenderContext.
QList< QgsMapLayer * > layers() const
Returns a list of all layers read from the project.
void setParameters(const QgsWmsParameters ¶meters)
Sets WMS parameters.
QList< QgsMapLayer * > layersToRender() const
Returns a list of all layers to actually render according to the current configuration.
int mapWidth() const
Returns WIDTH or SRCWIDTH according to UseSrcWidthHeight flag.
QgsMapLayer * layer(const QString &nickname) const
Returns the layer corresponding to the nickname, or a nullptr if not found or if the layer do not nee...
int tileBuffer() const
Returns the tile buffer value to use for rendering according to the current configuration.
bool updateExtent() const
Returns true if the extent has to be updated before the rendering, false otherwise.
const QgsServerSettings & settings() const
Returns settings of the server.
void setFlag(Flag flag, bool on=true)
Sets or unsets a rendering flag according to the on value.
bool isValidWidthHeight() const
Returns true if width and height are valid according to the maximum values defined within the project...
QList< QgsMapLayer * > layersFromGroup(const QString &nickname) const
Returns the group's layers list corresponding to the nickname, or an empty list if not found.
QgsWmsParameters parameters() const
Returns WMS parameters.
void setScaleDenominator(double scaleDenominator)
Sets a custom scale denominator.
QString style(const QgsMapLayer &layer) const
Returns a style's name for a specific layer.
QMap< QString, QList< QgsMapLayer * > > layerGroups() const
Returns a map having layer group names as keys and a list of layers as values.
double mapTileBuffer(int mapWidth) const
Returns the tile buffer in geographical units for the given map width in pixels.
QString layerNickname(const QgsMapLayer &layer) const
Returns the nickname (short name, id or name) of the layer according to the current configuration.
void setSocketFeedback(QgsFeedback *feedback)
Sets the response feedback.
double scaleDenominator() const
Returns the scale denominator to use for rendering according to the current configuration.
qreal dotsPerMm() const
Returns default dots per mm according to the current configuration.
bool testFlag(Flag flag) const
Returns the status of a rendering flag.
QDomElement sld(const QgsMapLayer &layer) const
Returns a SLD document for a specific layer.
bool isValidLayer(const QString &nickname) const
Returns true if the layer has to be rendered, false otherwise.
const QgsProject * project() const
Returns the project.
int precision() const
Returns the precision to use according to the current configuration.
int imageQuality() const
Returns the image quality to use for rendering according to the current configuration.
int mapHeight() const
Returns HEIGHT or SRCHEIGHT according to UseSrcWidthHeight flag.
bool renderMapTiles() const
Returns true if WMS requests should use the QgsMapSettings::RenderMapTile flag, so that no visible ar...
Flag
Available rendering options.
@ AddAllLayers
For GetPrint: add layers from LAYER(S) parameter.
SERVER_EXPORT int wmsTileBuffer(const QgsProject &project)
Returns the tile buffer in pixels for WMS images defined in a QGIS project.
SERVER_EXPORT QString wmsRootName(const QgsProject &project)
Returns the WMS root layer name defined in a QGIS project.
SERVER_EXPORT bool wmsSkipNameForGroup(const QgsProject &project)
Returns if name attribute should be skipped for groups in WMS capabilities document.
SERVER_EXPORT int wmsFeatureInfoPrecision(const QgsProject &project)
Returns the geometry precision for GetFeatureInfo request.
SERVER_EXPORT bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
SERVER_EXPORT bool wmsRenderMapTiles(const QgsProject &project)
Returns true if WMS requests should use the QgsMapSettings::RenderMapTile flag, so that no visible ar...
SERVER_EXPORT QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
SERVER_EXPORT int wmsImageQuality(const QgsProject &project)
Returns the quality for WMS images defined in a QGIS project.
SERVER_EXPORT int wmsMaxWidth(const QgsProject &project)
Returns the maximum width for WMS images defined in a QGIS project.
SERVER_EXPORT int wmsMaxHeight(const QgsProject &project)
Returns the maximum height for WMS images defined in a QGIS project.
Median cut implementation.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
const QgsCoordinateReferenceSystem & outputCrs
const QgsCoordinateReferenceSystem & crs