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() )
200 std::function<QStringList(
const QString &name )> findLeaves = [&](
const QString &name ) -> QStringList {
202 if ( mLayerGroups.contains( name ) )
204 const auto &
layers { mLayerGroups[name] };
205 for (
const auto &l :
layers )
208 if ( checkLayerReadPermissions( l ) )
212 if ( mLayerGroups.contains( nick ) )
214 _result.append( name );
218 _result.append( findLeaves( nick ) );
225 _result.append( name );
230 for (
const auto &name : std::as_const( layerNames ) )
232 result.append( findLeaves( name ) );
239 return mLayersToRender;
244 return mNicknameLayers.values();
249 double denominator = -1;
251 if ( mScaleDenominator >= 0 )
253 denominator = mScaleDenominator;
266 removeUnwantedLayers();
286 return l->id() == layer.id();
288 == mExternalLayers.cend() )
292 else if ( name.isEmpty() )
304 for (
auto layer : mLayersToRender )
318 return layer( nickname );
323 return mLayerGroups.value( nickname );
328 return mLayerGroups.contains( name );
331void QgsWmsRenderContext::initNicknameLayers()
342 initLayerGroupsRecursive( root, rootName.isEmpty() ? mProject->
title() : rootName );
345void QgsWmsRenderContext::initLayerGroupsRecursive(
const QgsLayerTreeGroup *group,
const QString &groupName )
347 if ( !groupName.isEmpty() )
349 QList<QgsMapLayer *> layerGroup;
350 const auto projectLayerTreeRoot { mProject->
layerTreeRoot() };
351 const auto treeGroupLayers { group->
findLayers() };
354 if ( !projectLayerTreeRoot->hasCustomLayerOrder() )
356 for (
const auto &tl : treeGroupLayers )
358 layerGroup.push_back( tl->layer() );
363 const auto projectLayerOrder { projectLayerTreeRoot->layerOrder() };
365 QList<QgsMapLayer *> groupLayersList;
366 for (
const auto &tl : treeGroupLayers )
368 groupLayersList << tl->layer();
370 for (
const auto &l : projectLayerOrder )
372 if ( groupLayersList.contains( l ) )
374 layerGroup.push_back( l );
379 if ( !layerGroup.empty() )
381 mLayerGroups[groupName] = layerGroup;
389 QString name = child->customProperty( QStringLiteral(
"wmsShortName" ) ).toString();
391 if ( name.isEmpty() )
392 name = child->name();
394 initLayerGroupsRecursive(
static_cast<const QgsLayerTreeGroup *
>( child ), name );
399void QgsWmsRenderContext::initRestrictedLayers()
401 mRestrictedLayers.clear();
407 QStringList restrictedLayersNames;
410 for (
const QString &l : std::as_const( restricted ) )
415 const QList<QgsLayerTreeLayer *> groupLayers = group->
findLayers();
418 restrictedLayersNames.append( treeLayer->name() );
423 restrictedLayersNames.append( l );
431 if ( restrictedLayersNames.contains(
layer->
name() ) )
438void QgsWmsRenderContext::searchLayersToRender()
440 mLayersToRender.clear();
444 if ( !mParameters.
sldBody().isEmpty() )
446 searchLayersToRenderSld();
450 searchLayersToRenderStyle();
456 for (
const QString &layerName : queryLayerNames )
458 const QList<QgsMapLayer *>
layers = mNicknameLayers.values( layerName );
461 if ( !mLayersToRender.contains( lyr ) )
463 if ( !addLayerToRender( lyr ) )
465 throw QgsSecurityException( QStringLiteral(
"Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
475 for (
const QString &layerName : queryLayerNames )
477 const QList<QgsMapLayer *>
layers = mNicknameLayers.values( layerName );
480 if ( !mLayersToRender.contains( lyr ) )
482 if ( !addLayerToRender( lyr ) )
484 throw QgsSecurityException( QStringLiteral(
"Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
492void QgsWmsRenderContext::searchLayersToRenderSld()
502 ( void ) doc.setContent(
sld,
true );
503 QDomElement docEl = doc.documentElement();
505 QDomElement root = doc.firstChildElement(
"StyledLayerDescriptor" );
506 QDomElement namedElem = root.firstChildElement(
"NamedLayer" );
508 if ( docEl.isNull() )
513 QDomNodeList named = docEl.elementsByTagName(
"NamedLayer" );
514 for (
int i = 0; i < named.size(); ++i )
516 QDomNodeList names = named.item( i ).toElement().elementsByTagName(
"Name" );
517 if ( !names.isEmpty() )
519 QString lname = names.item( 0 ).toElement().text();
520 if ( mNicknameLayers.contains( lname ) )
522 mSlds[lname] = namedElem;
523 for (
const auto layer : mNicknameLayers.values( lname ) )
525 if ( !addLayerToRender(
layer ) )
531 else if ( mLayerGroups.contains( lname ) )
536 param.mValue = lname;
540 bool layerAdded =
false;
544 if ( checkLayerReadPermissions(
layer ) )
547 mSlds[name] = namedElem;
548 mLayersToRender.insert( 0,
layer );
557 param.mValue = lname;
564 param.mValue = lname;
571void QgsWmsRenderContext::searchLayersToRenderStyle()
575 const QString nickname = param.mNickname;
576 const QString
style = param.mStyle;
580 std::unique_ptr<QgsMapLayer>
layer = std::make_unique<QgsRasterLayer>( param.mExternalUri, param.mNickname, QStringLiteral(
"wms" ) );
585 mExternalLayers.append(
layer.release() );
586 auto lyr = mExternalLayers.last();
587 if ( !addLayerToRender( lyr ) )
589 throw QgsSecurityException( QStringLiteral(
"Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
593 else if ( mNicknameLayers.contains( nickname ) )
595 if ( !
style.isEmpty() )
597 mStyles[nickname] =
style;
600 for (
const auto layer : mNicknameLayers.values( nickname ) )
602 if ( !addLayerToRender(
layer ) )
608 else if ( mLayerGroups.contains( nickname ) )
613 param.mValue = nickname;
621 if ( !
style.isEmpty() )
623 mStyles[nickname] =
style;
628 bool layerAdded =
false;
631 for (
const auto layer : mNicknameLayers.values( name ) )
633 if ( addLayerToRender(
layer ) )
644 param.mValue = nickname;
651 param.mValue = nickname;
657bool QgsWmsRenderContext::layerScaleVisibility(
const QString &name )
const
659 bool visible =
false;
661 if ( !mNicknameLayers.contains( name ) )
666 const QList<QgsMapLayer *>
layers = mNicknameLayers.values( name );
670 bool useScaleConstraint = (
scaleDenominator() > 0 && scaleBasedVisibility );
719 if ( width <= 0 || height <= 0 )
728 if ( wmsMaxWidthEnv != -1 && wmsMaxWidthProj != -1 )
731 wmsMaxWidth = std::min( wmsMaxWidthProj, wmsMaxWidthEnv );
736 wmsMaxWidth = std::max( wmsMaxWidthProj, wmsMaxWidthEnv );
739 if ( wmsMaxWidth != -1 && width > wmsMaxWidth )
748 if ( wmsMaxHeightEnv != -1 && wmsMaxHeightProj != -1 )
751 wmsMaxHeight = std::min( wmsMaxHeightProj, wmsMaxHeightEnv );
756 wmsMaxHeight = std::max( wmsMaxHeightProj, wmsMaxHeightEnv );
759 if ( wmsMaxHeight != -1 && height > wmsMaxHeight )
773 switch ( mParameters.
format() )
781 if ( width > ( std::numeric_limits<int>::max() - 31 ) / depth )
784 const int bytes_per_line = ( ( width * depth + 31 ) >> 5 ) << 2;
786 if ( std::numeric_limits<int>::max() / bytes_per_line < height
787 || std::numeric_limits<int>::max() /
sizeof( uchar * ) <
static_cast<uint
>( height ) )
801 if ( !mParameters.
bbox().isEmpty() && extent.
isEmpty() )
825 if ( !mParameters.
bbox().isEmpty() && extent.
isEmpty() )
830 QString
crs = mParameters.
crs();
831 if (
crs.compare(
"CRS:84", Qt::CaseInsensitive ) == 0 )
833 crs = QString(
"EPSG:4326" );
843 if ( !extent.
isEmpty() && height > 0 && width > 0 )
845 const double mapRatio = extent.
width() / extent.
height();
846 const double imageRatio =
static_cast<double>( width ) /
static_cast<double>( height );
850 const double cellsize = ( extent.
width() /
static_cast<double>( width ) ) * 0.5 + ( extent.
height() /
static_cast<double>( height ) ) * 0.5;
851 width = extent.
width() / cellsize;
852 height = extent.
height() / cellsize;
861 else if ( height <= 0 )
866 return QSize( width, height );
869void QgsWmsRenderContext::removeUnwantedLayers()
871 QList<QgsMapLayer *>
layers;
879 if ( !layerScaleVisibility( nickname ) )
882 if ( mRestrictedLayers.contains( nickname ) )
893 if ( !wfsLayers.contains(
layer->
id() ) )
908 for (
const auto &
layer : mExternalLayers )
917bool QgsWmsRenderContext::checkLayerReadPermissions(
QgsMapLayer *layer )
const
919#ifdef HAVE_SERVER_PYTHON_PLUGINS
920 if ( !accessControl()->layerReadPermission(
layer ) )
922 QString msg = QStringLiteral(
"Checking forbidden access for layer: %1" ).arg(
layer->
name() );
931#ifdef HAVE_SERVER_PYTHON_PLUGINS
940 mSocketFeedback = feedback;
945 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.
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