QGIS API Documentation 3.39.0-Master (d85f3c2a281)
Loading...
Searching...
No Matches
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
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
200 QStringList result;
201 std::function <QStringList( const QString &name )> findLeaves = [ & ]( const QString & name ) -> QStringList
202 {
203 QStringList _result;
204 if ( mLayerGroups.contains( name ) )
205 {
206 const auto &layers { mLayerGroups[ name ] };
207 for ( const auto &l : layers )
208 {
209 const auto nick { layerNickname( *l ) };
210 // This handles the case for root (fake) group
211 if ( mLayerGroups.contains( nick ) )
212 {
213 _result.append( name );
214 }
215 else
216 {
217 _result.append( findLeaves( nick ) );
218 }
219 }
220 }
221 else
222 {
223 _result.append( name );
224 }
225 return _result;
226 };
227
228 for ( const auto &name : std::as_const( layerNames ) )
229 {
230 result.append( findLeaves( name ) );
231 }
232 return result;
233}
234
235QList<QgsMapLayer *> QgsWmsRenderContext::layersToRender() const
236{
237 return mLayersToRender;
238}
239
240QList<QgsMapLayer *> QgsWmsRenderContext::layers() const
241{
242 return mNicknameLayers.values();
243}
244
246{
247 double denominator = -1;
248
249 if ( mScaleDenominator >= 0 )
250 {
251 denominator = mScaleDenominator;
252 }
253 else if ( mFlags & UseScaleDenominator && ! mParameters.scale().isEmpty() )
254 {
255 denominator = mParameters.scaleAsDouble();
256 }
257
258 return denominator;
259}
260
261void QgsWmsRenderContext::setScaleDenominator( double scaleDenominator )
262{
263 mScaleDenominator = scaleDenominator;
264 removeUnwantedLayers();
265}
266
268{
269 bool update = false;
270
271 if ( mFlags & UpdateExtent && ! mParameters.bbox().isEmpty() )
272 {
273 update = true;
274 }
275
276 return update;
277}
278
280{
281 QString name = layer.serverProperties()->shortName();
282 // For external layers we cannot use the layer id because it's not known to the client, use layer name instead.
283 if ( QgsServerProjectUtils::wmsUseLayerIds( *mProject ) &&
284 std::find_if( mExternalLayers.cbegin(), mExternalLayers.cend(),
285 [ &layer ]( const QgsMapLayer * l )
286{
287 return l->id() == layer.id();
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 auto layer = tl->layer();
359 if ( checkLayerReadPermissions( layer ) )
360 {
361 layerGroup.push_back( layer );
362 }
363 }
364 }
365 else
366 {
367 const auto projectLayerOrder { projectLayerTreeRoot->layerOrder() };
368 // Flat list containing the layers from the tree nodes
369 QList<QgsMapLayer *> groupLayersList;
370 for ( const auto &tl : treeGroupLayers )
371 {
372 auto layer = tl->layer();
373 if ( checkLayerReadPermissions( layer ) )
374 {
375 groupLayersList << layer;
376 }
377 }
378 for ( const auto &l : projectLayerOrder )
379 {
380 if ( groupLayersList.contains( l ) )
381 {
382 layerGroup.push_back( l );
383 }
384 }
385 }
386
387 if ( !layerGroup.empty() )
388 {
389 mLayerGroups[groupName] = layerGroup;
390 }
391 }
392
393 for ( const QgsLayerTreeNode *child : group->children() )
394 {
395 if ( child->nodeType() == QgsLayerTreeNode::NodeGroup )
396 {
397 QString name = child->customProperty( QStringLiteral( "wmsShortName" ) ).toString();
398
399 if ( name.isEmpty() )
400 name = child->name();
401
402 initLayerGroupsRecursive( static_cast<const QgsLayerTreeGroup *>( child ), name );
403
404 }
405 }
406}
407
408void QgsWmsRenderContext::initRestrictedLayers()
409{
410 mRestrictedLayers.clear();
411
412 // get name of restricted layers/groups in project
413 const QStringList restricted = QgsServerProjectUtils::wmsRestrictedLayers( *mProject );
414
415 // extract restricted layers from excluded groups
416 QStringList restrictedLayersNames;
417 QgsLayerTreeGroup *root = mProject->layerTreeRoot();
418
419 for ( const QString &l : std::as_const( restricted ) )
420 {
421 const QgsLayerTreeGroup *group = root->findGroup( l );
422 if ( group )
423 {
424 const QList<QgsLayerTreeLayer *> groupLayers = group->findLayers();
425 for ( QgsLayerTreeLayer *treeLayer : groupLayers )
426 {
427 restrictedLayersNames.append( treeLayer->name() );
428 }
429 }
430 else
431 {
432 restrictedLayersNames.append( l );
433 }
434 }
435
436 // build output with names, ids or short name according to the configuration
437 const QList<QgsLayerTreeLayer *> layers = root->findLayers();
439 {
440 if ( restrictedLayersNames.contains( layer->name() ) )
441 {
442 mRestrictedLayers.append( layerNickname( *layer->layer() ) );
443 }
444 }
445}
446
447void QgsWmsRenderContext::searchLayersToRender()
448{
449 mLayersToRender.clear();
450 mStyles.clear();
451 mSlds.clear();
452
453 if ( ! mParameters.sldBody().isEmpty() )
454 {
455 searchLayersToRenderSld();
456 }
457 else
458 {
459 searchLayersToRenderStyle();
460 }
461
462 if ( mFlags & AddQueryLayers )
463 {
464 const QStringList queryLayerNames = flattenedQueryLayers( mParameters.queryLayersNickname() );
465 for ( const QString &layerName : queryLayerNames )
466 {
467 const QList<QgsMapLayer *> layers = mNicknameLayers.values( layerName );
468 for ( QgsMapLayer *lyr : layers )
469 {
470 if ( !mLayersToRender.contains( lyr ) )
471 {
472 if ( !addLayerToRender( lyr ) )
473 {
474 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
475
476 }
477 }
478 }
479 }
480 }
481
482 if ( mFlags & AddAllLayers )
483 {
484 const QStringList queryLayerNames = flattenedQueryLayers( mParameters.allLayersNickname() );
485 for ( const QString &layerName : queryLayerNames )
486 {
487 const QList<QgsMapLayer *> layers = mNicknameLayers.values( layerName );
488 for ( QgsMapLayer *lyr : layers )
489 {
490 if ( !mLayersToRender.contains( lyr ) )
491 {
492 if ( !addLayerToRender( lyr ) )
493 {
494 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
495
496 }
497 }
498 }
499 }
500 }
501}
502
503void QgsWmsRenderContext::searchLayersToRenderSld()
504{
505 const QString sld = mParameters.sldBody();
506
507 if ( sld.isEmpty() )
508 {
509 return;
510 }
511
512 QDomDocument doc;
513 ( void )doc.setContent( sld, true );
514 QDomElement docEl = doc.documentElement();
515
516 QDomElement root = doc.firstChildElement( "StyledLayerDescriptor" );
517 QDomElement namedElem = root.firstChildElement( "NamedLayer" );
518
519 if ( docEl.isNull() )
520 {
521 return;
522 }
523
524 QDomNodeList named = docEl.elementsByTagName( "NamedLayer" );
525 for ( int i = 0; i < named.size(); ++i )
526 {
527 QDomNodeList names = named.item( i ).toElement().elementsByTagName( "Name" );
528 if ( !names.isEmpty() )
529 {
530 QString lname = names.item( 0 ).toElement().text();
531 if ( mNicknameLayers.contains( lname ) )
532 {
533 mSlds[lname] = namedElem;
534 for ( const auto layer : mNicknameLayers.values( lname ) )
535 {
536 if ( !addLayerToRender( layer ) )
537 {
538 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( layer->name() ) );
539 }
540 }
541 }
542 else if ( mLayerGroups.contains( lname ) )
543 {
545 {
547 param.mValue = lname;
549 param );
550 }
551 for ( QgsMapLayer *layer : mLayerGroups[lname] )
552 {
553 const QString name = layerNickname( *layer );
554 mSlds[name] = namedElem;
555 mLayersToRender.insert( 0, layer );
556 }
557 }
558 else
559 {
561 param.mValue = lname;
563 param );
564 }
565 }
566 }
567}
568
569void QgsWmsRenderContext::searchLayersToRenderStyle()
570{
571 for ( const QgsWmsParametersLayer &param : mParameters.layersParameters() )
572 {
573 const QString nickname = param.mNickname;
574 const QString style = param.mStyle;
575
576 if ( ! param.mExternalUri.isEmpty() && ( mFlags & AddExternalLayers ) )
577 {
578
579 std::unique_ptr<QgsMapLayer> layer = std::make_unique< QgsRasterLayer >( param.mExternalUri, param.mNickname, QStringLiteral( "wms" ) );
580
581 if ( layer->isValid() )
582 {
583 // to delete later
584 mExternalLayers.append( layer.release() );
585 auto lyr = mExternalLayers.last();
586 if ( !addLayerToRender( lyr ) )
587 {
588 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
589
590 }
591 }
592 }
593 else if ( mNicknameLayers.contains( nickname ) )
594 {
595 if ( !style.isEmpty() )
596 {
597 mStyles[nickname] = style;
598 }
599
600 for ( const auto layer : mNicknameLayers.values( nickname ) )
601 {
602 if ( !addLayerToRender( layer ) )
603 {
604 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( layer->name() ) );
605 }
606 }
607 }
608 else if ( mLayerGroups.contains( nickname ) )
609 {
611 {
613 param.mValue = nickname;
615 param );
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 for ( const auto &name : layersFromGroup )
630 {
631 for ( const auto layer : mNicknameLayers.values( name ) )
632 {
633 addLayerToRender( layer );
634 }
635 }
636 }
637 else
638 {
640 param.mValue = nickname;
642 param );
643 }
644 }
645}
646
647bool QgsWmsRenderContext::layerScaleVisibility( const QString &name ) const
648{
649 bool visible = false;
650
651 if ( ! mNicknameLayers.contains( name ) )
652 {
653 return visible;
654 }
655
656 const QList<QgsMapLayer *>layers = mNicknameLayers.values( name );
657 for ( QgsMapLayer *layer : layers )
658 {
659 bool scaleBasedVisibility = layer->hasScaleBasedVisibility();
660 bool useScaleConstraint = ( scaleDenominator() > 0 && scaleBasedVisibility );
661
662 if ( !useScaleConstraint || layer->isInScaleRange( scaleDenominator() ) )
663 {
664 visible = true;
665 }
666 }
667
668 return visible;
669}
670
671QMap<QString, QList<QgsMapLayer *> > QgsWmsRenderContext::layerGroups() const
672{
673 return mLayerGroups;
674}
675
677{
678 int width = mParameters.widthAsInt();
679
680 // May use SRCWIDTH to define image map size
681 if ( ( mFlags & UseSrcWidthHeight ) && mParameters.srcWidthAsInt() > 0 )
682 {
683 width = mParameters.srcWidthAsInt();
684 }
685
686 return width;
687}
688
690{
691 int height = mParameters.heightAsInt();
692
693 // May use SRCHEIGHT to define image map size
694 if ( ( mFlags & UseSrcWidthHeight ) && mParameters.srcHeightAsInt() > 0 )
695 {
696 height = mParameters.srcHeightAsInt();
697 }
698
699 return height;
700}
701
706
707bool QgsWmsRenderContext::isValidWidthHeight( int width, int height ) const
708{
709 if ( width <= 0 || height <= 0 )
710 return false;
711
712 //test if maxWidth / maxHeight are set in the project or as an env variable
713 //and WIDTH / HEIGHT parameter is in the range allowed range
714 //WIDTH
715 const int wmsMaxWidthProj = QgsServerProjectUtils::wmsMaxWidth( *mProject );
716 const int wmsMaxWidthEnv = settings().wmsMaxWidth();
717 int wmsMaxWidth;
718 if ( wmsMaxWidthEnv != -1 && wmsMaxWidthProj != -1 )
719 {
720 // both are set, so we take the more conservative one
721 wmsMaxWidth = std::min( wmsMaxWidthProj, wmsMaxWidthEnv );
722 }
723 else
724 {
725 // none or one are set, so we take the bigger one which is the one set or -1
726 wmsMaxWidth = std::max( wmsMaxWidthProj, wmsMaxWidthEnv );
727 }
728
729 if ( wmsMaxWidth != -1 && width > wmsMaxWidth )
730 {
731 return false;
732 }
733
734 //HEIGHT
735 const int wmsMaxHeightProj = QgsServerProjectUtils::wmsMaxHeight( *mProject );
736 const int wmsMaxHeightEnv = settings().wmsMaxHeight();
737 int wmsMaxHeight;
738 if ( wmsMaxHeightEnv != -1 && wmsMaxHeightProj != -1 )
739 {
740 // both are set, so we take the more conservative one
741 wmsMaxHeight = std::min( wmsMaxHeightProj, wmsMaxHeightEnv );
742 }
743 else
744 {
745 // none or one are set, so we take the bigger one which is the one set or -1
746 wmsMaxHeight = std::max( wmsMaxHeightProj, wmsMaxHeightEnv );
747 }
748
749 if ( wmsMaxHeight != -1 && height > wmsMaxHeight )
750 {
751 return false;
752 }
753
754 // Sanity check from internal QImage checks
755 // (see QImageData::calculateImageParameters() in qimage_p.h)
756 // this is to report a meaningful error message in case of
757 // image creation failure and to differentiate it from out
758 // of memory conditions.
759
760 // depth for now it cannot be anything other than 32, but I don't like
761 // to hardcode it: I hope we will support other depths in the future.
762 int depth = 32;
763 switch ( mParameters.format() )
764 {
767 default:
768 depth = 32;
769 }
770
771 if ( width > ( std::numeric_limits<int>::max() - 31 ) / depth )
772 return false;
773
774 const int bytes_per_line = ( ( width * depth + 31 ) >> 5 ) << 2; // bytes per scanline (must be multiple of 4)
775
776 if ( std::numeric_limits<int>::max() / bytes_per_line < height
777 || std::numeric_limits<int>::max() / sizeof( uchar * ) < static_cast<uint>( height ) )
778 {
779 return false;
780 }
781
782 return true;
783}
784
785double QgsWmsRenderContext::mapTileBuffer( const int mapWidth ) const
786{
787 double buffer;
788 if ( mFlags & UseTileBuffer )
789 {
790 const QgsRectangle extent = mParameters.bboxAsRectangle();
791 if ( !mParameters.bbox().isEmpty() && extent.isEmpty() )
792 {
794 mParameters[QgsWmsParameter::BBOX] );
795 }
796 buffer = tileBuffer() * ( extent.width() / mapWidth );
797 }
798 else
799 {
800 buffer = 0;
801 }
802 return buffer;
803}
804
805QSize QgsWmsRenderContext::mapSize( const bool aspectRatio ) const
806{
807 int width = mapWidth();
808 int height = mapHeight();
809
810 // Adapt width / height if the aspect ratio does not correspond with the BBOX.
811 // Required by WMS spec. 1.3.
812 if ( aspectRatio
813 && mParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) )
814 {
815 QgsRectangle extent = mParameters.bboxAsRectangle();
816 if ( !mParameters.bbox().isEmpty() && extent.isEmpty() )
817 {
819 mParameters[QgsWmsParameter::BBOX] );
820 }
821
822 QString crs = mParameters.crs();
823 if ( crs.compare( "CRS:84", Qt::CaseInsensitive ) == 0 )
824 {
825 crs = QString( "EPSG:4326" );
826 extent.invert();
827 }
828
831 {
832 extent.invert();
833 }
834
835 if ( !extent.isEmpty() && height > 0 && width > 0 )
836 {
837 const double mapRatio = extent.width() / extent.height();
838 const double imageRatio = static_cast<double>( width ) / static_cast<double>( height );
839 if ( !qgsDoubleNear( mapRatio, imageRatio, 0.0001 ) )
840 {
841 // inspired by MapServer, mapdraw.c L115
842 const double cellsize = ( extent.width() / static_cast<double>( width ) ) * 0.5 + ( extent.height() / static_cast<double>( height ) ) * 0.5;
843 width = extent.width() / cellsize;
844 height = extent.height() / cellsize;
845 }
846 }
847 }
848
849 if ( width <= 0 )
850 {
852 mParameters[QgsWmsParameter::WIDTH] );
853 }
854 else if ( height <= 0 )
855 {
857 mParameters[QgsWmsParameter::HEIGHT] );
858 }
859
860 return QSize( width, height );
861}
862
863void QgsWmsRenderContext::removeUnwantedLayers()
864{
865 QList<QgsMapLayer *> layers;
866
867 for ( QgsMapLayer *layer : mLayersToRender )
868 {
869 const QString nickname = layerNickname( *layer );
870
871 if ( ! isExternalLayer( nickname ) )
872 {
873 if ( !layerScaleVisibility( nickname ) )
874 continue;
875
876 if ( mRestrictedLayers.contains( nickname ) )
877 continue;
878
879 if ( mFlags & UseWfsLayersOnly )
880 {
882 {
883 continue;
884 }
885
886 const QStringList wfsLayers = QgsServerProjectUtils::wfsLayerIds( *mProject );
887 if ( ! wfsLayers.contains( layer->id() ) )
888 {
889 continue;
890 }
891 }
892 }
893
894 layers.append( layer );
895 }
896
897 mLayersToRender = layers;
898}
899
900bool QgsWmsRenderContext::isExternalLayer( const QString &name ) const
901{
902 for ( const auto &layer : mExternalLayers )
903 {
904 if ( layerNickname( *layer ).compare( name ) == 0 )
905 return true;
906 }
907
908 return false;
909}
910
911bool QgsWmsRenderContext::checkLayerReadPermissions( QgsMapLayer *layer )
912{
913#ifdef HAVE_SERVER_PYTHON_PLUGINS
914 if ( !accessControl()->layerReadPermission( layer ) )
915 {
916 QString msg = QStringLiteral( "Checking forbidden access for layer: %1" ).arg( layer->name() );
918 return false;
919 }
920#endif
921 Q_UNUSED( layer )
922 return true;
923}
924
925#ifdef HAVE_SERVER_PYTHON_PLUGINS
926QgsAccessControl *QgsWmsRenderContext::accessControl() const
927{
928 return mInterface->accessControls();
929}
930#endif
931
933{
934 mSocketFeedback = feedback;
935}
936
938{
939 return mSocketFeedback;
940}
@ 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 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.
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.
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.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
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:79
Qgis::LayerType type
Definition qgsmaplayer.h:86
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,...
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.
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.
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.
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)
Definition qgis.h:5857
const QgsCoordinateReferenceSystem & outputCrs
const QgsCoordinateReferenceSystem & crs
const double OGC_PX_M