QGIS API Documentation 3.43.0-Master (32433f7016e)
qgswmsrendercontext.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgswmsrendercontext.cpp
3 ---------------------
4 begin : March 22, 2019
5 copyright : (C) 2019 by Paul Blottiere
6 email : paul.blottiere@oslandia.com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgslayertree.h"
19
20#include "qgsrasterlayer.h"
21#include "qgswmsrendercontext.h"
24
25using namespace QgsWms;
26
27const double OGC_PX_M = 0.00028; // OGC reference pixel size in meter
29 : mProject( project )
30 , mInterface( interface )
31 , mFlags()
32{
33}
34
36{
37 qDeleteAll( mExternalLayers );
38 mExternalLayers.clear();
39}
40
42{
43 mParameters = parameters;
44
45 initRestrictedLayers();
46 initNicknameLayers();
47
48 searchLayersToRender();
49 removeUnwantedLayers();
50
51 std::reverse( mLayersToRender.begin(), mLayersToRender.end() );
52}
53
54bool QgsWmsRenderContext::addLayerToRender( QgsMapLayer *layer )
55{
56 const bool allowed = checkLayerReadPermissions( layer );
57 if ( allowed )
58 {
59 mLayersToRender.append( layer );
60 }
61 return allowed;
62}
63
64
65void QgsWmsRenderContext::setFlag( const Flag flag, const bool on )
66{
67 if ( on )
68 {
69 mFlags |= flag;
70 }
71 else
72 {
73 mFlags &= ~flag;
74 }
75}
76
78{
79 return mFlags.testFlag( flag );
80}
81
83{
84 return mParameters;
85}
86
88{
89 return *mInterface->serverSettings();
90}
91
93{
94 return mProject;
95}
96
97QDomElement QgsWmsRenderContext::sld( const QgsMapLayer &layer ) const
98{
99 QDomElement sld;
100
101 const QString nickname = layerNickname( layer );
102 if ( mSlds.contains( nickname ) )
103 {
104 sld = mSlds[nickname];
105 }
106
107 return sld;
108}
109
110QString QgsWmsRenderContext::style( const QgsMapLayer &layer ) const
111{
112 QString style;
113
114 const QString nickname = layerNickname( layer );
115 if ( mStyles.contains( nickname ) )
116 {
117 style = mStyles[nickname];
118 }
119
120 return style;
121}
122
124{
126
127 const QList<QgsWmsParametersLayer> cLayerParams { mParameters.layersParameters() };
128
129 for ( const auto &params : std::as_const( cLayerParams ) )
130 {
131 if ( params.mNickname == layerNickname( layer ) )
132 {
133 parameters = params;
134 break;
135 }
136 }
137
138 return parameters;
139}
140
142{
144
145 if ( !mParameters.imageQuality().isEmpty() )
146 {
147 imageQuality = mParameters.imageQualityAsInt();
148 }
149
150 return imageQuality;
151}
152
154{
155 int tileBuffer = 0;
156
157 if ( mParameters.tiledAsBool() )
158 {
160 }
161
162 return tileBuffer;
163}
164
169
171{
173
174 if ( mParameters.wmsPrecisionAsInt() > -1 )
175 {
176 precision = mParameters.wmsPrecisionAsInt();
177 }
178
179 return precision;
180}
181
183{
184 // Apply DPI parameter if present. This is an extension of QGIS Server
185 // compared to WMS 1.3.
186 // Because of backwards compatibility, this parameter is optional
187 qreal dpm = 1 / OGC_PX_M;
188
189 if ( !mParameters.dpi().isEmpty() )
190 {
191 dpm = mParameters.dpiAsDouble() / 0.0254;
192 }
193
194 return dpm / 1000.0;
195}
196
197QStringList QgsWmsRenderContext::flattenedQueryLayers( const QStringList &layerNames ) const
198{
199 QStringList result;
200 std::function<QStringList( const QString &name )> findLeaves = [&]( const QString &name ) -> QStringList {
201 QStringList _result;
202 if ( mLayerGroups.contains( name ) )
203 {
204 const auto &layers { mLayerGroups[name] };
205 for ( const auto &l : layers )
206 {
207 // Only add allowed layers
208 if ( checkLayerReadPermissions( l ) )
209 {
210 const auto nick { layerNickname( *l ) };
211 // This handles the case for root (fake) group
212 if ( mLayerGroups.contains( nick ) )
213 {
214 _result.append( name );
215 }
216 else
217 {
218 _result.append( findLeaves( nick ) );
219 }
220 }
221 }
222 }
223 else
224 {
225 _result.append( name );
226 }
227 return _result;
228 };
229
230 for ( const auto &name : std::as_const( layerNames ) )
231 {
232 result.append( findLeaves( name ) );
233 }
234 return result;
235}
236
237QList<QgsMapLayer *> QgsWmsRenderContext::layersToRender() const
238{
239 return mLayersToRender;
240}
241
242QList<QgsMapLayer *> QgsWmsRenderContext::layers() const
243{
244 return mNicknameLayers.values();
245}
246
248{
249 double denominator = -1;
250
251 if ( mScaleDenominator >= 0 )
252 {
253 denominator = mScaleDenominator;
254 }
255 else if ( mFlags & UseScaleDenominator && !mParameters.scale().isEmpty() )
256 {
257 denominator = mParameters.scaleAsDouble();
258 }
259
260 return denominator;
261}
262
263void QgsWmsRenderContext::setScaleDenominator( double scaleDenominator )
264{
265 mScaleDenominator = scaleDenominator;
266 removeUnwantedLayers();
267}
268
270{
271 bool update = false;
272
273 if ( mFlags & UpdateExtent && !mParameters.bbox().isEmpty() )
274 {
275 update = true;
276 }
277
278 return update;
279}
280
282{
283 QString name = layer.serverProperties()->shortName();
284 // For external layers we cannot use the layer id because it's not known to the client, use layer name instead.
285 if ( QgsServerProjectUtils::wmsUseLayerIds( *mProject ) && std::find_if( mExternalLayers.cbegin(), mExternalLayers.cend(), [&layer]( const QgsMapLayer *l ) {
286 return l->id() == layer.id();
287 } )
288 == mExternalLayers.cend() )
289 {
290 name = layer.id();
291 }
292 else if ( name.isEmpty() )
293 {
294 name = layer.name();
295 }
296
297 return name;
298}
299
300QgsMapLayer *QgsWmsRenderContext::layer( const QString &nickname ) const
301{
302 QgsMapLayer *mlayer = nullptr;
303
304 for ( auto layer : mLayersToRender )
305 {
306 if ( layerNickname( *layer ).compare( nickname ) == 0 )
307 {
308 mlayer = layer;
309 break;
310 }
311 }
312
313 return mlayer;
314}
315
316bool QgsWmsRenderContext::isValidLayer( const QString &nickname ) const
317{
318 return layer( nickname );
319}
320
321QList<QgsMapLayer *> QgsWmsRenderContext::layersFromGroup( const QString &nickname ) const
322{
323 return mLayerGroups.value( nickname );
324}
325
326bool QgsWmsRenderContext::isValidGroup( const QString &name ) const
327{
328 return mLayerGroups.contains( name );
329}
330
331void QgsWmsRenderContext::initNicknameLayers()
332{
333 for ( QgsMapLayer *ml : mProject->mapLayers() )
334 {
335 mNicknameLayers.insert( layerNickname( *ml ), ml );
336 }
337
338 // init groups
339 const QString rootName { QgsServerProjectUtils::wmsRootName( *mProject ) };
340 const QgsLayerTreeGroup *root = mProject->layerTreeRoot();
341
342 initLayerGroupsRecursive( root, rootName.isEmpty() ? mProject->title() : rootName );
343}
344
345void QgsWmsRenderContext::initLayerGroupsRecursive( const QgsLayerTreeGroup *group, const QString &groupName )
346{
347 if ( !groupName.isEmpty() )
348 {
349 QList<QgsMapLayer *> layerGroup;
350 const auto projectLayerTreeRoot { mProject->layerTreeRoot() };
351 const auto treeGroupLayers { group->findLayers() };
352 // Fast track if there is no custom layer order,
353 // otherwise reorder layers.
354 if ( !projectLayerTreeRoot->hasCustomLayerOrder() )
355 {
356 for ( const auto &tl : treeGroupLayers )
357 {
358 layerGroup.push_back( tl->layer() );
359 }
360 }
361 else
362 {
363 const auto projectLayerOrder { projectLayerTreeRoot->layerOrder() };
364 // Flat list containing the layers from the tree nodes
365 QList<QgsMapLayer *> groupLayersList;
366 for ( const auto &tl : treeGroupLayers )
367 {
368 groupLayersList << tl->layer();
369 }
370 for ( const auto &l : projectLayerOrder )
371 {
372 if ( groupLayersList.contains( l ) )
373 {
374 layerGroup.push_back( l );
375 }
376 }
377 }
378
379 if ( !layerGroup.empty() )
380 {
381 mLayerGroups[groupName] = layerGroup;
382 }
383 }
384
385 for ( const QgsLayerTreeNode *child : group->children() )
386 {
387 if ( child->nodeType() == QgsLayerTreeNode::NodeGroup )
388 {
389 auto group = static_cast<const QgsLayerTreeGroup *>( child );
390 QString name = group ? group->serverProperties()->shortName() : QString();
391
392 if ( name.isEmpty() )
393 name = child->name();
394
395 initLayerGroupsRecursive( group, name );
396 }
397 }
398}
399
400void QgsWmsRenderContext::initRestrictedLayers()
401{
402 mRestrictedLayers.clear();
403
404 // get name of restricted layers/groups in project
405 const QStringList restricted = QgsServerProjectUtils::wmsRestrictedLayers( *mProject );
406
407 // extract restricted layers from excluded groups
408 QStringList restrictedLayersNames;
409 QgsLayerTreeGroup *root = mProject->layerTreeRoot();
410
411 for ( const QString &l : std::as_const( restricted ) )
412 {
413 const QgsLayerTreeGroup *group = root->findGroup( l );
414 if ( group )
415 {
416 const QList<QgsLayerTreeLayer *> groupLayers = group->findLayers();
417 for ( QgsLayerTreeLayer *treeLayer : groupLayers )
418 {
419 restrictedLayersNames.append( treeLayer->name() );
420 }
421 }
422 else
423 {
424 restrictedLayersNames.append( l );
425 }
426 }
427
428 // build output with names, ids or short name according to the configuration
429 const QList<QgsLayerTreeLayer *> layers = root->findLayers();
431 {
432 if ( restrictedLayersNames.contains( layer->name() ) )
433 {
434 mRestrictedLayers.append( layerNickname( *layer->layer() ) );
435 }
436 }
437}
438
439void QgsWmsRenderContext::searchLayersToRender()
440{
441 mLayersToRender.clear();
442 mStyles.clear();
443 mSlds.clear();
444
445 if ( !mParameters.sldBody().isEmpty() )
446 {
447 searchLayersToRenderSld();
448 }
449 else
450 {
451 searchLayersToRenderStyle();
452 }
453
454 if ( mFlags & AddQueryLayers )
455 {
456 const QStringList queryLayerNames = flattenedQueryLayers( mParameters.queryLayersNickname() );
457 for ( const QString &layerName : queryLayerNames )
458 {
459 const QList<QgsMapLayer *> layers = mNicknameLayers.values( layerName );
460 for ( QgsMapLayer *lyr : layers )
461 {
462 if ( !mLayersToRender.contains( lyr ) )
463 {
464 if ( !addLayerToRender( lyr ) )
465 {
466 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
467 }
468 }
469 }
470 }
471 }
472
473 if ( mFlags & AddAllLayers )
474 {
475 const QStringList queryLayerNames = flattenedQueryLayers( mParameters.allLayersNickname() );
476 for ( const QString &layerName : queryLayerNames )
477 {
478 const QList<QgsMapLayer *> layers = mNicknameLayers.values( layerName );
479 for ( QgsMapLayer *lyr : layers )
480 {
481 if ( !mLayersToRender.contains( lyr ) )
482 {
483 if ( !addLayerToRender( lyr ) )
484 {
485 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
486 }
487 }
488 }
489 }
490 }
491}
492
493void QgsWmsRenderContext::searchLayersToRenderSld()
494{
495 const QString sld = mParameters.sldBody();
496
497 if ( sld.isEmpty() )
498 {
499 return;
500 }
501
502 QDomDocument doc;
503 ( void ) doc.setContent( sld, true );
504 QDomElement docEl = doc.documentElement();
505
506 QDomElement root = doc.firstChildElement( "StyledLayerDescriptor" );
507 QDomElement namedElem = root.firstChildElement( "NamedLayer" );
508
509 if ( docEl.isNull() )
510 {
511 return;
512 }
513
514 QDomNodeList named = docEl.elementsByTagName( "NamedLayer" );
515 for ( int i = 0; i < named.size(); ++i )
516 {
517 QDomNodeList names = named.item( i ).toElement().elementsByTagName( "Name" );
518 if ( !names.isEmpty() )
519 {
520 QString lname = names.item( 0 ).toElement().text();
521 if ( mNicknameLayers.contains( lname ) )
522 {
523 mSlds[lname] = namedElem;
524 for ( const auto layer : mNicknameLayers.values( lname ) )
525 {
526 if ( !addLayerToRender( layer ) )
527 {
528 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( layer->name() ) );
529 }
530 }
531 }
532 else if ( mLayerGroups.contains( lname ) )
533 {
535 {
537 param.mValue = lname;
539 }
540
541 bool layerAdded = false;
542 for ( QgsMapLayer *layer : mLayerGroups[lname] )
543 {
544 // Insert only allowed layers
545 if ( checkLayerReadPermissions( layer ) )
546 {
547 const QString name = layerNickname( *layer );
548 mSlds[name] = namedElem;
549 mLayersToRender.insert( 0, layer );
550 layerAdded = true;
551 }
552 }
553 // No layers have been added, consider the group
554 // as non-existent.
555 if ( !layerAdded )
556 {
558 param.mValue = lname;
560 }
561 }
562 else
563 {
565 param.mValue = lname;
567 }
568 }
569 }
570}
571
572void QgsWmsRenderContext::searchLayersToRenderStyle()
573{
574 for ( const QgsWmsParametersLayer &param : mParameters.layersParameters() )
575 {
576 const QString nickname = param.mNickname;
577 const QString style = param.mStyle;
578
579 if ( !param.mExternalUri.isEmpty() && ( mFlags & AddExternalLayers ) )
580 {
581 std::unique_ptr<QgsMapLayer> layer = std::make_unique<QgsRasterLayer>( param.mExternalUri, param.mNickname, QStringLiteral( "wms" ) );
582
583 if ( layer->isValid() )
584 {
585 // to delete later
586 mExternalLayers.append( layer.release() );
587 auto lyr = mExternalLayers.last();
588 if ( !addLayerToRender( lyr ) )
589 {
590 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
591 }
592 }
593 }
594 else if ( mNicknameLayers.contains( nickname ) )
595 {
596 if ( !style.isEmpty() )
597 {
598 mStyles[nickname] = style;
599 }
600
601 for ( const auto layer : mNicknameLayers.values( nickname ) )
602 {
603 if ( !addLayerToRender( layer ) )
604 {
605 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( layer->name() ) );
606 }
607 }
608 }
609 else if ( mLayerGroups.contains( nickname ) )
610 {
612 {
614 param.mValue = nickname;
616 }
617 // Reverse order of layers from a group
618 QList<QString> layersFromGroup;
619 for ( QgsMapLayer *layer : mLayerGroups[nickname] )
620 {
621 const QString nickname = layerNickname( *layer );
622 if ( !style.isEmpty() )
623 {
624 mStyles[nickname] = style;
625 }
626 layersFromGroup.push_front( nickname );
627 }
628
629 bool layerAdded = false;
630 for ( const auto &name : layersFromGroup )
631 {
632 for ( const auto layer : mNicknameLayers.values( name ) )
633 {
634 if ( addLayerToRender( layer ) )
635 {
636 layerAdded = true;
637 }
638 }
639 }
640 // No layers have been added, consider the group
641 // as non-existent.
642 if ( !layerAdded )
643 {
645 param.mValue = nickname;
647 }
648 }
649 else
650 {
652 param.mValue = nickname;
654 }
655 }
656}
657
658bool QgsWmsRenderContext::layerScaleVisibility( const QString &name ) const
659{
660 bool visible = false;
661
662 if ( !mNicknameLayers.contains( name ) )
663 {
664 return visible;
665 }
666
667 const QList<QgsMapLayer *> layers = mNicknameLayers.values( name );
668 for ( QgsMapLayer *layer : layers )
669 {
670 bool scaleBasedVisibility = layer->hasScaleBasedVisibility();
671 bool useScaleConstraint = ( scaleDenominator() > 0 && scaleBasedVisibility );
672
673 if ( !useScaleConstraint || layer->isInScaleRange( scaleDenominator() ) )
674 {
675 visible = true;
676 }
677 }
678
679 return visible;
680}
681
682QMap<QString, QList<QgsMapLayer *>> QgsWmsRenderContext::layerGroups() const
683{
684 return mLayerGroups;
685}
686
688{
689 int width = mParameters.widthAsInt();
690
691 // May use SRCWIDTH to define image map size
692 if ( ( mFlags & UseSrcWidthHeight ) && mParameters.srcWidthAsInt() > 0 )
693 {
694 width = mParameters.srcWidthAsInt();
695 }
696
697 return width;
698}
699
701{
702 int height = mParameters.heightAsInt();
703
704 // May use SRCHEIGHT to define image map size
705 if ( ( mFlags & UseSrcWidthHeight ) && mParameters.srcHeightAsInt() > 0 )
706 {
707 height = mParameters.srcHeightAsInt();
708 }
709
710 return height;
711}
712
717
718bool QgsWmsRenderContext::isValidWidthHeight( int width, int height ) const
719{
720 if ( width <= 0 || height <= 0 )
721 return false;
722
723 //test if maxWidth / maxHeight are set in the project or as an env variable
724 //and WIDTH / HEIGHT parameter is in the range allowed range
725 //WIDTH
726 const int wmsMaxWidthProj = QgsServerProjectUtils::wmsMaxWidth( *mProject );
727 const int wmsMaxWidthEnv = settings().wmsMaxWidth();
728 int wmsMaxWidth;
729 if ( wmsMaxWidthEnv != -1 && wmsMaxWidthProj != -1 )
730 {
731 // both are set, so we take the more conservative one
732 wmsMaxWidth = std::min( wmsMaxWidthProj, wmsMaxWidthEnv );
733 }
734 else
735 {
736 // none or one are set, so we take the bigger one which is the one set or -1
737 wmsMaxWidth = std::max( wmsMaxWidthProj, wmsMaxWidthEnv );
738 }
739
740 if ( wmsMaxWidth != -1 && width > wmsMaxWidth )
741 {
742 return false;
743 }
744
745 //HEIGHT
746 const int wmsMaxHeightProj = QgsServerProjectUtils::wmsMaxHeight( *mProject );
747 const int wmsMaxHeightEnv = settings().wmsMaxHeight();
748 int wmsMaxHeight;
749 if ( wmsMaxHeightEnv != -1 && wmsMaxHeightProj != -1 )
750 {
751 // both are set, so we take the more conservative one
752 wmsMaxHeight = std::min( wmsMaxHeightProj, wmsMaxHeightEnv );
753 }
754 else
755 {
756 // none or one are set, so we take the bigger one which is the one set or -1
757 wmsMaxHeight = std::max( wmsMaxHeightProj, wmsMaxHeightEnv );
758 }
759
760 if ( wmsMaxHeight != -1 && height > wmsMaxHeight )
761 {
762 return false;
763 }
764
765 // Sanity check from internal QImage checks
766 // (see QImageData::calculateImageParameters() in qimage_p.h)
767 // this is to report a meaningful error message in case of
768 // image creation failure and to differentiate it from out
769 // of memory conditions.
770
771 // depth for now it cannot be anything other than 32, but I don't like
772 // to hardcode it: I hope we will support other depths in the future.
773 int depth = 32;
774 switch ( mParameters.format() )
775 {
778 default:
779 depth = 32;
780 }
781
782 if ( width > ( std::numeric_limits<int>::max() - 31 ) / depth )
783 return false;
784
785 const int bytes_per_line = ( ( width * depth + 31 ) >> 5 ) << 2; // bytes per scanline (must be multiple of 4)
786
787 if ( std::numeric_limits<int>::max() / bytes_per_line < height
788 || std::numeric_limits<int>::max() / sizeof( uchar * ) < static_cast<uint>( height ) )
789 {
790 return false;
791 }
792
793 return true;
794}
795
796double QgsWmsRenderContext::mapTileBuffer( const int mapWidth ) const
797{
798 double buffer;
799 if ( mFlags & UseTileBuffer )
800 {
801 const QgsRectangle extent = mParameters.bboxAsRectangle();
802 if ( !mParameters.bbox().isEmpty() && extent.isEmpty() )
803 {
805 }
806 buffer = tileBuffer() * ( extent.width() / mapWidth );
807 }
808 else
809 {
810 buffer = 0;
811 }
812 return buffer;
813}
814
815QSize QgsWmsRenderContext::mapSize( const bool aspectRatio ) const
816{
817 int width = mapWidth();
818 int height = mapHeight();
819
820 // Adapt width / height if the aspect ratio does not correspond with the BBOX.
821 // Required by WMS spec. 1.3.
822 if ( aspectRatio
823 && mParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) )
824 {
825 QgsRectangle extent = mParameters.bboxAsRectangle();
826 if ( !mParameters.bbox().isEmpty() && extent.isEmpty() )
827 {
829 }
830
831 QString crs = mParameters.crs();
832 if ( crs.compare( "CRS:84", Qt::CaseInsensitive ) == 0 )
833 {
834 crs = QString( "EPSG:4326" );
835 extent.invert();
836 }
837
840 {
841 extent.invert();
842 }
843
844 if ( !extent.isEmpty() && height > 0 && width > 0 )
845 {
846 const double mapRatio = extent.width() / extent.height();
847 const double imageRatio = static_cast<double>( width ) / static_cast<double>( height );
848 if ( !qgsDoubleNear( mapRatio, imageRatio, 0.0001 ) )
849 {
850 // inspired by MapServer, mapdraw.c L115
851 const double cellsize = ( extent.width() / static_cast<double>( width ) ) * 0.5 + ( extent.height() / static_cast<double>( height ) ) * 0.5;
852 width = extent.width() / cellsize;
853 height = extent.height() / cellsize;
854 }
855 }
856 }
857
858 if ( width <= 0 )
859 {
861 }
862 else if ( height <= 0 )
863 {
865 }
866
867 return QSize( width, height );
868}
869
870void QgsWmsRenderContext::removeUnwantedLayers()
871{
872 QList<QgsMapLayer *> layers;
873
874 for ( QgsMapLayer *layer : mLayersToRender )
875 {
876 const QString nickname = layerNickname( *layer );
877
878 if ( !isExternalLayer( nickname ) )
879 {
880 if ( !layerScaleVisibility( nickname ) )
881 continue;
882
883 if ( mRestrictedLayers.contains( nickname ) )
884 continue;
885
886 if ( mFlags & UseWfsLayersOnly )
887 {
889 {
890 continue;
891 }
892
893 const QStringList wfsLayers = QgsServerProjectUtils::wfsLayerIds( *mProject );
894 if ( !wfsLayers.contains( layer->id() ) )
895 {
896 continue;
897 }
898 }
899 }
900
901 layers.append( layer );
902 }
903
904 mLayersToRender = layers;
905}
906
907bool QgsWmsRenderContext::isExternalLayer( const QString &name ) const
908{
909 for ( const auto &layer : mExternalLayers )
910 {
911 if ( layerNickname( *layer ).compare( name ) == 0 )
912 return true;
913 }
914
915 return false;
916}
917
918bool QgsWmsRenderContext::checkLayerReadPermissions( QgsMapLayer *layer ) const
919{
920#ifdef HAVE_SERVER_PYTHON_PLUGINS
921 if ( !accessControl()->layerReadPermission( layer ) )
922 {
923 QString msg = QStringLiteral( "Checking forbidden access for layer: %1" ).arg( layer->name() );
925 return false;
926 }
927#endif
928 Q_UNUSED( layer )
929 return true;
930}
931
932#ifdef HAVE_SERVER_PYTHON_PLUGINS
933QgsAccessControl *QgsWmsRenderContext::accessControl() const
934{
935 return mInterface->accessControls();
936}
937#endif
938
940{
941 mSocketFeedback = feedback;
942}
943
945{
946 return mSocketFeedback;
947}
@ Info
Information message.
Definition qgis.h:155
@ Vector
Vector layer.
A helper class that centralizes restrictions given by all the access control filter plugins.
Exception thrown in case of malformed requests.
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.
Definition qgsfeedback.h:44
Layer tree group node serves as a container for layers and further groups.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the layer tree group.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
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.
Definition qgsmaplayer.h:77
QString name
Definition qgsmaplayer.h:81
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.
QString id
Definition qgsmaplayer.h:80
Qgis::LayerType type
Definition qgsmaplayer.h:87
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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Describes the version of a project.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
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.
Defines 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.
static int wmsTileBuffer(const QgsProject &project)
Returns the tile buffer in pixels for WMS images defined in a QGIS project.
static QString wmsRootName(const QgsProject &project)
Returns the WMS root layer name defined in a QGIS project.
static bool wmsSkipNameForGroup(const QgsProject &project)
Returns if name attribute should be skipped for groups in WMS capabilities document.
static int wmsFeatureInfoPrecision(const QgsProject &project)
Returns the geometry precision for GetFeatureInfo request.
static bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
static QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
static bool wmsRenderMapTiles(const QgsProject &project)
Returns true if WMS requests should use the QgsMapSettings::RenderMapTile flag, so that no visible ar...
static QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
static int wmsImageQuality(const QgsProject &project)
Returns the quality for WMS images defined in a QGIS project.
static int wmsMaxWidth(const QgsProject &project)
Returns the maximum width for WMS images defined in a QGIS project.
static int wmsMaxHeight(const QgsProject &project)
Returns the maximum height for WMS images defined in a QGIS project.
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.
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 &parameters)
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.
Median cut implementation.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6286
const QgsCoordinateReferenceSystem & outputCrs
const QgsCoordinateReferenceSystem & crs
const double OGC_PX_M