QGIS API Documentation 3.41.0-Master (3440c17df1d)
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 // Only add allowed layers
210 if ( checkLayerReadPermissions( l ) )
211 {
212 const auto nick { layerNickname( *l ) };
213 // This handles the case for root (fake) group
214 if ( mLayerGroups.contains( nick ) )
215 {
216 _result.append( name );
217 }
218 else
219 {
220 _result.append( findLeaves( nick ) );
221 }
222 }
223 }
224 }
225 else
226 {
227 _result.append( name );
228 }
229 return _result;
230 };
231
232 for ( const auto &name : std::as_const( layerNames ) )
233 {
234 result.append( findLeaves( name ) );
235 }
236 return result;
237}
238
239QList<QgsMapLayer *> QgsWmsRenderContext::layersToRender() const
240{
241 return mLayersToRender;
242}
243
244QList<QgsMapLayer *> QgsWmsRenderContext::layers() const
245{
246 return mNicknameLayers.values();
247}
248
250{
251 double denominator = -1;
252
253 if ( mScaleDenominator >= 0 )
254 {
255 denominator = mScaleDenominator;
256 }
257 else if ( mFlags & UseScaleDenominator && ! mParameters.scale().isEmpty() )
258 {
259 denominator = mParameters.scaleAsDouble();
260 }
261
262 return denominator;
263}
264
265void QgsWmsRenderContext::setScaleDenominator( double scaleDenominator )
266{
267 mScaleDenominator = scaleDenominator;
268 removeUnwantedLayers();
269}
270
272{
273 bool update = false;
274
275 if ( mFlags & UpdateExtent && ! mParameters.bbox().isEmpty() )
276 {
277 update = true;
278 }
279
280 return update;
281}
282
284{
285 QString name = layer.serverProperties()->shortName();
286 // For external layers we cannot use the layer id because it's not known to the client, use layer name instead.
287 if ( QgsServerProjectUtils::wmsUseLayerIds( *mProject ) &&
288 std::find_if( mExternalLayers.cbegin(), mExternalLayers.cend(),
289 [ &layer ]( const QgsMapLayer * l )
290{
291 return l->id() == layer.id();
292 } ) == mExternalLayers.cend() )
293 {
294 name = layer.id();
295 }
296 else if ( name.isEmpty() )
297 {
298 name = layer.name();
299 }
300
301 return name;
302}
303
304QgsMapLayer *QgsWmsRenderContext::layer( const QString &nickname ) const
305{
306 QgsMapLayer *mlayer = nullptr;
307
308 for ( auto layer : mLayersToRender )
309 {
310 if ( layerNickname( *layer ).compare( nickname ) == 0 )
311 {
312 mlayer = layer;
313 break;
314 }
315 }
316
317 return mlayer;
318}
319
320bool QgsWmsRenderContext::isValidLayer( const QString &nickname ) const
321{
322 return layer( nickname );
323}
324
325QList<QgsMapLayer *> QgsWmsRenderContext::layersFromGroup( const QString &nickname ) const
326{
327 return mLayerGroups.value( nickname );
328}
329
330bool QgsWmsRenderContext::isValidGroup( const QString &name ) const
331{
332 return mLayerGroups.contains( name );
333}
334
335void QgsWmsRenderContext::initNicknameLayers()
336{
337 for ( QgsMapLayer *ml : mProject->mapLayers() )
338 {
339 mNicknameLayers.insert( layerNickname( *ml ), ml );
340 }
341
342 // init groups
343 const QString rootName { QgsServerProjectUtils::wmsRootName( *mProject ) };
344 const QgsLayerTreeGroup *root = mProject->layerTreeRoot();
345
346 initLayerGroupsRecursive( root, rootName.isEmpty() ? mProject->title() : rootName );
347}
348
349void QgsWmsRenderContext::initLayerGroupsRecursive( const QgsLayerTreeGroup *group, const QString &groupName )
350{
351 if ( !groupName.isEmpty() )
352 {
353 QList<QgsMapLayer *> layerGroup;
354 const auto projectLayerTreeRoot { mProject->layerTreeRoot() };
355 const auto treeGroupLayers { group->findLayers() };
356 // Fast track if there is no custom layer order,
357 // otherwise reorder layers.
358 if ( ! projectLayerTreeRoot->hasCustomLayerOrder() )
359 {
360 for ( const auto &tl : treeGroupLayers )
361 {
362 layerGroup.push_back( tl->layer() );
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 groupLayersList << tl->layer();
373 }
374 for ( const auto &l : projectLayerOrder )
375 {
376 if ( groupLayersList.contains( l ) )
377 {
378 layerGroup.push_back( l );
379 }
380 }
381 }
382
383 if ( !layerGroup.empty() )
384 {
385 mLayerGroups[groupName] = layerGroup;
386 }
387 }
388
389 for ( const QgsLayerTreeNode *child : group->children() )
390 {
391 if ( child->nodeType() == QgsLayerTreeNode::NodeGroup )
392 {
393 QString name = child->customProperty( QStringLiteral( "wmsShortName" ) ).toString();
394
395 if ( name.isEmpty() )
396 name = child->name();
397
398 initLayerGroupsRecursive( static_cast<const QgsLayerTreeGroup *>( child ), name );
399
400 }
401 }
402}
403
404void QgsWmsRenderContext::initRestrictedLayers()
405{
406 mRestrictedLayers.clear();
407
408 // get name of restricted layers/groups in project
409 const QStringList restricted = QgsServerProjectUtils::wmsRestrictedLayers( *mProject );
410
411 // extract restricted layers from excluded groups
412 QStringList restrictedLayersNames;
413 QgsLayerTreeGroup *root = mProject->layerTreeRoot();
414
415 for ( const QString &l : std::as_const( restricted ) )
416 {
417 const QgsLayerTreeGroup *group = root->findGroup( l );
418 if ( group )
419 {
420 const QList<QgsLayerTreeLayer *> groupLayers = group->findLayers();
421 for ( QgsLayerTreeLayer *treeLayer : groupLayers )
422 {
423 restrictedLayersNames.append( treeLayer->name() );
424 }
425 }
426 else
427 {
428 restrictedLayersNames.append( l );
429 }
430 }
431
432 // build output with names, ids or short name according to the configuration
433 const QList<QgsLayerTreeLayer *> layers = root->findLayers();
435 {
436 if ( restrictedLayersNames.contains( layer->name() ) )
437 {
438 mRestrictedLayers.append( layerNickname( *layer->layer() ) );
439 }
440 }
441}
442
443void QgsWmsRenderContext::searchLayersToRender()
444{
445 mLayersToRender.clear();
446 mStyles.clear();
447 mSlds.clear();
448
449 if ( ! mParameters.sldBody().isEmpty() )
450 {
451 searchLayersToRenderSld();
452 }
453 else
454 {
455 searchLayersToRenderStyle();
456 }
457
458 if ( mFlags & AddQueryLayers )
459 {
460 const QStringList queryLayerNames = flattenedQueryLayers( mParameters.queryLayersNickname() );
461 for ( const QString &layerName : queryLayerNames )
462 {
463 const QList<QgsMapLayer *> layers = mNicknameLayers.values( layerName );
464 for ( QgsMapLayer *lyr : layers )
465 {
466 if ( !mLayersToRender.contains( lyr ) )
467 {
468 if ( !addLayerToRender( lyr ) )
469 {
470 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
471
472 }
473 }
474 }
475 }
476 }
477
478 if ( mFlags & AddAllLayers )
479 {
480 const QStringList queryLayerNames = flattenedQueryLayers( mParameters.allLayersNickname() );
481 for ( const QString &layerName : queryLayerNames )
482 {
483 const QList<QgsMapLayer *> layers = mNicknameLayers.values( layerName );
484 for ( QgsMapLayer *lyr : layers )
485 {
486 if ( !mLayersToRender.contains( lyr ) )
487 {
488 if ( !addLayerToRender( lyr ) )
489 {
490 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
491
492 }
493 }
494 }
495 }
496 }
497}
498
499void QgsWmsRenderContext::searchLayersToRenderSld()
500{
501 const QString sld = mParameters.sldBody();
502
503 if ( sld.isEmpty() )
504 {
505 return;
506 }
507
508 QDomDocument doc;
509 ( void )doc.setContent( sld, true );
510 QDomElement docEl = doc.documentElement();
511
512 QDomElement root = doc.firstChildElement( "StyledLayerDescriptor" );
513 QDomElement namedElem = root.firstChildElement( "NamedLayer" );
514
515 if ( docEl.isNull() )
516 {
517 return;
518 }
519
520 QDomNodeList named = docEl.elementsByTagName( "NamedLayer" );
521 for ( int i = 0; i < named.size(); ++i )
522 {
523 QDomNodeList names = named.item( i ).toElement().elementsByTagName( "Name" );
524 if ( !names.isEmpty() )
525 {
526 QString lname = names.item( 0 ).toElement().text();
527 if ( mNicknameLayers.contains( lname ) )
528 {
529 mSlds[lname] = namedElem;
530 for ( const auto layer : mNicknameLayers.values( lname ) )
531 {
532 if ( !addLayerToRender( layer ) )
533 {
534 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( layer->name() ) );
535 }
536 }
537 }
538 else if ( mLayerGroups.contains( lname ) )
539 {
541 {
543 param.mValue = lname;
545 param );
546 }
547
548 bool layerAdded = false;
549 for ( QgsMapLayer *layer : mLayerGroups[lname] )
550 {
551 // Insert only allowed layers
552 if ( checkLayerReadPermissions( layer ) )
553 {
554 const QString name = layerNickname( *layer );
555 mSlds[name] = namedElem;
556 mLayersToRender.insert( 0, layer );
557 layerAdded = true;
558 }
559 }
560 // No layers have been added, consider the group
561 // as non-existent.
562 if ( !layerAdded )
563 {
565 param.mValue = lname;
567 param );
568
569 }
570 }
571 else
572 {
574 param.mValue = lname;
576 param );
577 }
578 }
579 }
580}
581
582void QgsWmsRenderContext::searchLayersToRenderStyle()
583{
584 for ( const QgsWmsParametersLayer &param : mParameters.layersParameters() )
585 {
586 const QString nickname = param.mNickname;
587 const QString style = param.mStyle;
588
589 if ( ! param.mExternalUri.isEmpty() && ( mFlags & AddExternalLayers ) )
590 {
591
592 std::unique_ptr<QgsMapLayer> layer = std::make_unique< QgsRasterLayer >( param.mExternalUri, param.mNickname, QStringLiteral( "wms" ) );
593
594 if ( layer->isValid() )
595 {
596 // to delete later
597 mExternalLayers.append( layer.release() );
598 auto lyr = mExternalLayers.last();
599 if ( !addLayerToRender( lyr ) )
600 {
601 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( lyr->name() ) );
602
603 }
604 }
605 }
606 else if ( mNicknameLayers.contains( nickname ) )
607 {
608 if ( !style.isEmpty() )
609 {
610 mStyles[nickname] = style;
611 }
612
613 for ( const auto layer : mNicknameLayers.values( nickname ) )
614 {
615 if ( !addLayerToRender( layer ) )
616 {
617 throw QgsSecurityException( QStringLiteral( "Your are not allowed to access the layer %1" ).arg( layer->name() ) );
618 }
619 }
620 }
621 else if ( mLayerGroups.contains( nickname ) )
622 {
624 {
626 param.mValue = nickname;
628 param );
629 }
630 // Reverse order of layers from a group
631 QList<QString> layersFromGroup;
632 for ( QgsMapLayer *layer : mLayerGroups[nickname] )
633 {
634 const QString nickname = layerNickname( *layer );
635 if ( !style.isEmpty() )
636 {
637 mStyles[ nickname ] = style;
638 }
639 layersFromGroup.push_front( nickname );
640 }
641
642 bool layerAdded = false;
643 for ( const auto &name : layersFromGroup )
644 {
645 for ( const auto layer : mNicknameLayers.values( name ) )
646 {
647 if ( addLayerToRender( layer ) )
648 {
649 layerAdded = true;
650 }
651 }
652 }
653 // No layers have been added, consider the group
654 // as non-existent.
655 if ( !layerAdded )
656 {
658 param.mValue = nickname;
660 param );
661 }
662 }
663 else
664 {
666 param.mValue = nickname;
668 param );
669 }
670 }
671}
672
673bool QgsWmsRenderContext::layerScaleVisibility( const QString &name ) const
674{
675 bool visible = false;
676
677 if ( ! mNicknameLayers.contains( name ) )
678 {
679 return visible;
680 }
681
682 const QList<QgsMapLayer *>layers = mNicknameLayers.values( name );
683 for ( QgsMapLayer *layer : layers )
684 {
685 bool scaleBasedVisibility = layer->hasScaleBasedVisibility();
686 bool useScaleConstraint = ( scaleDenominator() > 0 && scaleBasedVisibility );
687
688 if ( !useScaleConstraint || layer->isInScaleRange( scaleDenominator() ) )
689 {
690 visible = true;
691 }
692 }
693
694 return visible;
695}
696
697QMap<QString, QList<QgsMapLayer *> > QgsWmsRenderContext::layerGroups() const
698{
699 return mLayerGroups;
700}
701
703{
704 int width = mParameters.widthAsInt();
705
706 // May use SRCWIDTH to define image map size
707 if ( ( mFlags & UseSrcWidthHeight ) && mParameters.srcWidthAsInt() > 0 )
708 {
709 width = mParameters.srcWidthAsInt();
710 }
711
712 return width;
713}
714
716{
717 int height = mParameters.heightAsInt();
718
719 // May use SRCHEIGHT to define image map size
720 if ( ( mFlags & UseSrcWidthHeight ) && mParameters.srcHeightAsInt() > 0 )
721 {
722 height = mParameters.srcHeightAsInt();
723 }
724
725 return height;
726}
727
732
733bool QgsWmsRenderContext::isValidWidthHeight( int width, int height ) const
734{
735 if ( width <= 0 || height <= 0 )
736 return false;
737
738 //test if maxWidth / maxHeight are set in the project or as an env variable
739 //and WIDTH / HEIGHT parameter is in the range allowed range
740 //WIDTH
741 const int wmsMaxWidthProj = QgsServerProjectUtils::wmsMaxWidth( *mProject );
742 const int wmsMaxWidthEnv = settings().wmsMaxWidth();
743 int wmsMaxWidth;
744 if ( wmsMaxWidthEnv != -1 && wmsMaxWidthProj != -1 )
745 {
746 // both are set, so we take the more conservative one
747 wmsMaxWidth = std::min( wmsMaxWidthProj, wmsMaxWidthEnv );
748 }
749 else
750 {
751 // none or one are set, so we take the bigger one which is the one set or -1
752 wmsMaxWidth = std::max( wmsMaxWidthProj, wmsMaxWidthEnv );
753 }
754
755 if ( wmsMaxWidth != -1 && width > wmsMaxWidth )
756 {
757 return false;
758 }
759
760 //HEIGHT
761 const int wmsMaxHeightProj = QgsServerProjectUtils::wmsMaxHeight( *mProject );
762 const int wmsMaxHeightEnv = settings().wmsMaxHeight();
763 int wmsMaxHeight;
764 if ( wmsMaxHeightEnv != -1 && wmsMaxHeightProj != -1 )
765 {
766 // both are set, so we take the more conservative one
767 wmsMaxHeight = std::min( wmsMaxHeightProj, wmsMaxHeightEnv );
768 }
769 else
770 {
771 // none or one are set, so we take the bigger one which is the one set or -1
772 wmsMaxHeight = std::max( wmsMaxHeightProj, wmsMaxHeightEnv );
773 }
774
775 if ( wmsMaxHeight != -1 && height > wmsMaxHeight )
776 {
777 return false;
778 }
779
780 // Sanity check from internal QImage checks
781 // (see QImageData::calculateImageParameters() in qimage_p.h)
782 // this is to report a meaningful error message in case of
783 // image creation failure and to differentiate it from out
784 // of memory conditions.
785
786 // depth for now it cannot be anything other than 32, but I don't like
787 // to hardcode it: I hope we will support other depths in the future.
788 int depth = 32;
789 switch ( mParameters.format() )
790 {
793 default:
794 depth = 32;
795 }
796
797 if ( width > ( std::numeric_limits<int>::max() - 31 ) / depth )
798 return false;
799
800 const int bytes_per_line = ( ( width * depth + 31 ) >> 5 ) << 2; // bytes per scanline (must be multiple of 4)
801
802 if ( std::numeric_limits<int>::max() / bytes_per_line < height
803 || std::numeric_limits<int>::max() / sizeof( uchar * ) < static_cast<uint>( height ) )
804 {
805 return false;
806 }
807
808 return true;
809}
810
811double QgsWmsRenderContext::mapTileBuffer( const int mapWidth ) const
812{
813 double buffer;
814 if ( mFlags & UseTileBuffer )
815 {
816 const QgsRectangle extent = mParameters.bboxAsRectangle();
817 if ( !mParameters.bbox().isEmpty() && extent.isEmpty() )
818 {
820 mParameters[QgsWmsParameter::BBOX] );
821 }
822 buffer = tileBuffer() * ( extent.width() / mapWidth );
823 }
824 else
825 {
826 buffer = 0;
827 }
828 return buffer;
829}
830
831QSize QgsWmsRenderContext::mapSize( const bool aspectRatio ) const
832{
833 int width = mapWidth();
834 int height = mapHeight();
835
836 // Adapt width / height if the aspect ratio does not correspond with the BBOX.
837 // Required by WMS spec. 1.3.
838 if ( aspectRatio
839 && mParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) )
840 {
841 QgsRectangle extent = mParameters.bboxAsRectangle();
842 if ( !mParameters.bbox().isEmpty() && extent.isEmpty() )
843 {
845 mParameters[QgsWmsParameter::BBOX] );
846 }
847
848 QString crs = mParameters.crs();
849 if ( crs.compare( "CRS:84", Qt::CaseInsensitive ) == 0 )
850 {
851 crs = QString( "EPSG:4326" );
852 extent.invert();
853 }
854
857 {
858 extent.invert();
859 }
860
861 if ( !extent.isEmpty() && height > 0 && width > 0 )
862 {
863 const double mapRatio = extent.width() / extent.height();
864 const double imageRatio = static_cast<double>( width ) / static_cast<double>( height );
865 if ( !qgsDoubleNear( mapRatio, imageRatio, 0.0001 ) )
866 {
867 // inspired by MapServer, mapdraw.c L115
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;
871 }
872 }
873 }
874
875 if ( width <= 0 )
876 {
878 mParameters[QgsWmsParameter::WIDTH] );
879 }
880 else if ( height <= 0 )
881 {
883 mParameters[QgsWmsParameter::HEIGHT] );
884 }
885
886 return QSize( width, height );
887}
888
889void QgsWmsRenderContext::removeUnwantedLayers()
890{
891 QList<QgsMapLayer *> layers;
892
893 for ( QgsMapLayer *layer : mLayersToRender )
894 {
895 const QString nickname = layerNickname( *layer );
896
897 if ( ! isExternalLayer( nickname ) )
898 {
899 if ( !layerScaleVisibility( nickname ) )
900 continue;
901
902 if ( mRestrictedLayers.contains( nickname ) )
903 continue;
904
905 if ( mFlags & UseWfsLayersOnly )
906 {
908 {
909 continue;
910 }
911
912 const QStringList wfsLayers = QgsServerProjectUtils::wfsLayerIds( *mProject );
913 if ( ! wfsLayers.contains( layer->id() ) )
914 {
915 continue;
916 }
917 }
918 }
919
920 layers.append( layer );
921 }
922
923 mLayersToRender = layers;
924}
925
926bool QgsWmsRenderContext::isExternalLayer( const QString &name ) const
927{
928 for ( const auto &layer : mExternalLayers )
929 {
930 if ( layerNickname( *layer ).compare( name ) == 0 )
931 return true;
932 }
933
934 return false;
935}
936
937bool QgsWmsRenderContext::checkLayerReadPermissions( QgsMapLayer *layer ) const
938{
939#ifdef HAVE_SERVER_PYTHON_PLUGINS
940 if ( !accessControl()->layerReadPermission( layer ) )
941 {
942 QString msg = QStringLiteral( "Checking forbidden access for layer: %1" ).arg( layer->name() );
944 return false;
945 }
946#endif
947 Q_UNUSED( layer )
948 return true;
949}
950
951#ifdef HAVE_SERVER_PYTHON_PLUGINS
952QgsAccessControl *QgsWmsRenderContext::accessControl() const
953{
954 return mInterface->accessControls();
955}
956#endif
957
959{
960 mSocketFeedback = feedback;
961}
962
964{
965 return mSocketFeedback;
966}
@ 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.
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:5958
const QgsCoordinateReferenceSystem & outputCrs
const QgsCoordinateReferenceSystem & crs
const double OGC_PX_M