Skip to content
Permalink
Browse files

[FEATURE]

- make wms dpi mode configurable (fixes #8929)
- enum for tile request attributes
- allow setting of User-Agent (fixes #7361)
- show error messages on WMS GetCapabilities
  • Loading branch information
jef-n committed Oct 22, 2013
1 parent fa90fc9 commit aa256b8c33343e834aae0755950ab891007b483c
@@ -247,11 +247,11 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :

//Network timeout
mNetworkTimeoutSpinBox->setValue( settings.value( "/qgis/networkAndProxy/networkTimeout", "60000" ).toInt() );
leUserAgent->setText( settings.value( "/qgis/networkAndProxy/userAgent", "Mozilla/5.0" ).toString() );

This comment has been minimized.

Copy link
@Komzpa

Komzpa Sep 5, 2016

hello,
fake User-Agent Mozilla/5.0 is now banned on tile.openstreetmap.org.
this should default to real non-faked user-agent string, i.e. QGIS/2.17.0 or similar, to get passed through and properly managed.

This comment has been minimized.

Copy link
@jef-n

jef-n Sep 5, 2016

Author Member

This mimics Qt's default user-agent.

This comment has been minimized.

Copy link
@Komzpa

Komzpa Sep 5, 2016

@jef-n unfortunately, this renders QGIS/QuickMapServices unusable now - default "Mozilla/5.0" is banned, as it is used by too many different applications that don't bother to identify themselves so that osm.org sysadmins can contact them in case of problems.

This comment has been minimized.

Copy link
@Komzpa

This comment has been minimized.

Copy link
@jef-n

jef-n Sep 5, 2016

Author Member

QGIS uses "User-Agent: Mozilla/5.0 QGIS/2.17.0" by default (the "Mozilla/5.0" part can be overridden in settings)

This comment has been minimized.

Copy link
@Komzpa

Komzpa Sep 5, 2016

@jef-n thanks! we'll continue investigation.

This comment has been minimized.

Copy link
@Komzpa

// WMS/WMS-C tile expiry time
mDefaultTileExpirySpinBox->setValue( settings.value( "/qgis/defaultTileExpiry", "24" ).toInt() );

// Feature funded by Regione Toscana - SITA
// WMS/WMS-C default max retry in case of tile request errors
mDefaultTileMaxRetrySpinBox->setValue( settings.value( "/qgis/defaultTileMaxRetry", "3" ).toInt() );

@@ -903,11 +903,11 @@ void QgsOptions::saveOptions()

//Network timeout
settings.setValue( "/qgis/networkAndProxy/networkTimeout", mNetworkTimeoutSpinBox->value() );
settings.setValue( "/qgis/networkAndProxy/userAgent", leUserAgent->text() );

// WMS/WMS-C tile expiry time
settings.setValue( "/qgis/defaultTileExpiry", mDefaultTileExpirySpinBox->value() );

// Feature funded by Regione Toscana - SITA
// WMS/WMS-C default max retry in case of tile request errors
settings.setValue( "/qgis/defaultTileMaxRetry", mDefaultTileMaxRetrySpinBox->value() );

@@ -126,8 +126,14 @@ void QgsNetworkAccessManager::setFallbackProxyAndExcludes( const QNetworkProxy &

QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData )
{
QSettings s;

QNetworkRequest *pReq(( QNetworkRequest * ) &req ); // hack user agent
pReq->setRawHeader( "User-Agent", s.value( "/qgis/networkAndProxy/userAgent", "Mozilla/5.0" ).toByteArray() );

emit requestAboutToBeCreated( op, req, outgoingData );
QNetworkReply *reply = QNetworkAccessManager::createRequest( op, req, outgoingData );

connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( connectionProgress() ) );
connect( reply, SIGNAL( uploadProgress( qint64, qint64 ) ), this, SLOT( connectionProgress() ) );
connect( reply, SIGNAL( destroyed( QObject* ) ), this, SLOT( connectionDestroyed( QObject* ) ) );
@@ -136,7 +142,6 @@ QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Op
// abort request, when network timeout happens
QTimer *timer = new QTimer( reply );
connect( timer, SIGNAL( timeout() ), this, SLOT( abortRequest() ) );
QSettings s;
timer->setSingleShot( true );
timer->start( s.value( "/qgis/networkAndProxy/networkTimeout", "20000" ).toInt() );

@@ -347,6 +347,7 @@ QDomDocument QgsManageConnectionsDialog::saveOWSConnections( const QStringList &
el.setAttribute( "invertAxisOrientation", settings.value( path + connections[i] + "/invertAxisOrientation", false ).toBool() ? "true" : "false" );
el.setAttribute( "referer", settings.value( path + connections[ i ] + "/referer", "" ).toString() );
el.setAttribute( "smoothPixmapTransform", settings.value( path + connections[i] + "/smoothPixmapTransform", false ).toBool() ? "true" : "false" );
el.setAttribute( "dpiMode", settings.value( path + connections[i] + "/dpiMode", "7" ).toInt() );
}

path = "/Qgis/" + service.toUpper() + "/";
@@ -582,6 +583,7 @@ void QgsManageConnectionsDialog::loadOWSConnections( const QDomDocument &doc, co
settings.setValue( QString( "/" + connectionName + "/invertAxisOrientation" ), child.attribute( "invertAxisOrientation" ) == "true" );
settings.setValue( QString( "/" + connectionName + "/referer" ), child.attribute( "referer" ) );
settings.setValue( QString( "/" + connectionName + "/smoothPixmapTransform" ), child.attribute( "smoothPixmapTransform" ) == "true" );
settings.setValue( QString( "/" + connectionName + "/dpiMode" ), child.attribute( "dpiMode", "7" ).toInt() );
settings.endGroup();

if ( !child.attribute( "username" ).isEmpty() )
@@ -57,6 +57,33 @@ QgsNewHttpConnection::QgsNewHttpConnection(
cbxIgnoreGetFeatureInfoURI->setChecked( settings.value( key + "/ignoreGetFeatureInfoURI", false ).toBool() );
cbxSmoothPixmapTransform->setChecked( settings.value( key + "/smoothPixmapTransform", false ).toBool() );

cmbDpiMode->clear();
cmbDpiMode->addItem( tr( "all" ) );
cmbDpiMode->addItem( tr( "off" ) );
cmbDpiMode->addItem( tr( "QGIS" ) );
cmbDpiMode->addItem( tr( "UMN" ) );
cmbDpiMode->addItem( tr( "GeoServer" ) );
int dpiIdx;
switch ( settings.value( key + "/dpiMode", 7 ).toInt() )
{
case 0: // off
dpiIdx = 1;
break;
case 1: // QGIS
dpiIdx = 2;
break;
case 2: // UMN
dpiIdx = 3;
break;
case 4: // GeoServer
dpiIdx = 4;
break;
default: // other => all
dpiIdx = 0;
break;
}
cmbDpiMode->setCurrentIndex( dpiIdx );

txtReferer->setText( settings.value( key + "/referer" ).toString() );

txtUserName->setText( settings.value( credentialsKey + "/username" ).toString() );
@@ -85,6 +112,9 @@ QgsNewHttpConnection::QgsNewHttpConnection(
cbxIgnoreGetFeatureInfoURI->setVisible( false );
mGroupBox->layout()->removeWidget( cbxIgnoreGetFeatureInfoURI );

cmbDpiMode->setVisible( false );
mGroupBox->layout()->removeWidget( cmbDpiMode );

txtReferer->setVisible( false );
mGroupBox->layout()->removeWidget( txtReferer );
lblReferer->setVisible( false );
@@ -170,6 +200,28 @@ void QgsNewHttpConnection::accept()
settings.setValue( key + "/ignoreAxisOrientation", cbxIgnoreAxisOrientation->isChecked() );
settings.setValue( key + "/invertAxisOrientation", cbxInvertAxisOrientation->isChecked() );
settings.setValue( key + "/smoothPixmapTransform", cbxSmoothPixmapTransform->isChecked() );

int dpiMode;
switch ( cmbDpiMode->currentIndex() )
{
case 0: // all => QGIS|UMN|GeoServer
dpiMode = 7;
break;
case 1: // off
dpiMode = 0;
break;
case 2: // QGIS
dpiMode = 1;
break;
case 3: // UMN
dpiMode = 2;
break;
case 4: // GeoServer
dpiMode = 4;
break;
}

settings.setValue( key + "/dpiMode", dpiMode );
}
if ( mBaseKey == "/Qgis/connections-wms/" )
{
@@ -1178,7 +1178,7 @@ QImage* QgsWMSServer::createImage( int width, int height ) const

//apply DPI parameter if present. This is an extension of QGIS mapserver compared to WMS 1.3.
//Because of backwards compatibility, this parameter is optional
double OGC_PX_M = 0.00028; // OGC referance pixel size in meter, also used by qgis
double OGC_PX_M = 0.00028; // OGC reference pixel size in meter, also used by qgis
int dpm = 1 / OGC_PX_M;
if ( mParameterMap.contains( "DPI" ) )
{
@@ -78,10 +78,10 @@ QgsWMSConnection::QgsWMSConnection( QString theConnName ) :
bool ignoreAxisOrientation = settings.value( key + "/ignoreAxisOrientation", false ).toBool();
bool invertAxisOrientation = settings.value( key + "/invertAxisOrientation", false ).toBool();
bool smoothPixmapTransform = settings.value( key + "/smoothPixmapTransform", false ).toBool();
QString dpiMode = settings.value( key + "/dpiMode", "all" ).toString();

QString connArgs, delim;


if ( ignoreGetMap )
{
connArgs += delim + "GetMap";
@@ -117,6 +117,13 @@ QgsWMSConnection::QgsWMSConnection( QString theConnName ) :
mUri.setParam( "SmoothPixmapTransform", "1" );
}

if ( !dpiMode.isEmpty() )
{
connArgs += delim + "dpiMode=" + dpiMode;
delim = ";";
mUri.setParam( "dpiMode", dpiMode );
}

if ( !connArgs.isEmpty() )
{
connArgs.prepend( "ignoreUrl=" );
@@ -8,6 +8,9 @@
wms-c/wmts support : Jürgen E. Fischer < jef at norbit dot de >, norBIT GmbH
tile retry support : Luigi Pirelli < luipir at gmail dot com >
(funded by Regione Toscana-SITA)
***************************************************************************/

/***************************************************************************
@@ -159,6 +162,8 @@ bool QgsWmsProvider::parseUri( QString uriString )
mInvertAxisOrientation = uri.hasParam( "InvertAxisOrientation" ); // must be before parsing!
mSmoothPixmapTransform = uri.hasParam( "SmoothPixmapTransform" );

mDpiMode = uri.hasParam( "dpiMode" ) ? ( QgsWmsDpiMode ) uri.param( "dpiMode" ).toInt() : dpiAll;

mUserName = uri.param( "username" );
QgsDebugMsg( "set username to " + mUserName );

@@ -645,15 +650,14 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
setQueryItem( url, "STYLES", styles );
setQueryItem( url, "FORMAT", mImageMimeType );

//DPI parameter is accepted by QGIS mapserver (and ignored by the other WMS servers)
//map_resolution parameter works for UMN mapserver

//Different WMS servers have DPI parameters:
if ( mDpi != -1 )
{
setQueryItem( url, "DPI", QString::number( mDpi ) ); //QGIS server
setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) ); //UMN mapserver
setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) ); //geoserver
if ( mDpiMode & dpiQGIS )
setQueryItem( url, "DPI", QString::number( mDpi ) );
if ( mDpiMode & dpiUMN )
setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) );
if ( mDpiMode & dpiGeoServer )
setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) );
}

//MH: jpeg does not support transparency and some servers complain if jpg and transparent=true
@@ -830,9 +834,12 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i

if ( mDpi != -1 )
{
setQueryItem( url, "DPI", QString::number( mDpi ) ); //QGIS server
setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) ); //UMN mapserver
setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) ); //geoserver
if ( mDpiMode & dpiQGIS )
setQueryItem( url, "DPI", QString::number( mDpi ) );
if ( mDpiMode & dpiUMN )
setQueryItem( url, "MAP_RESOLUTION", QString::number( mDpi ) );
if ( mDpiMode & dpiGeoServer )
setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( mDpi ) );
}

if ( mImageMimeType == "image/x-jpegorpng" ||
@@ -860,12 +867,11 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 0 ), mTileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ), i );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ),
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ), mTileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileIndex ), i );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRect ),
QRectF( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap ) );
int retry = 0; // just for readability
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), retry );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), 0 );

QgsDebugMsg( QString( "gettile: %1" ).arg( turl ) );
QNetworkReply *reply = QgsNetworkAccessManager::instance()->get( request );
@@ -915,12 +921,11 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 0 ), mTileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ), i );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ),
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ), mTileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileIndex ), i );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRect ),
QRectF( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap ) );
int retry = 0; // just for readability
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), retry );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), 0 );

QgsDebugMsg( QString( "gettile: %1" ).arg( turl ) );
QNetworkReply *reply = QgsNetworkAccessManager::instance()->get( request );
@@ -957,12 +962,11 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 0 ), mTileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ), i );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ),
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ), mTileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileIndex ), i );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRect ),
QRectF( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap ) );
int retry = 0; // just for readability
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), retry );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), 0 );

QgsDebugMsg( QString( "gettile: %1" ).arg( turl ) );
QNetworkReply *reply = QgsNetworkAccessManager::instance()->get( request );
@@ -1039,7 +1043,6 @@ void QgsWmsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
//delete image;
}

// tile retry management developed with funding from Regione Toscana-SITA
void QgsWmsProvider::repeatTileRequest( QNetworkRequest const &oldRequest )
{
if ( mErrors == 100 )
@@ -1050,9 +1053,9 @@ void QgsWmsProvider::repeatTileRequest( QNetworkRequest const &oldRequest )
QNetworkRequest request( oldRequest );

QString url = request.url().toString();
int tileReqNo = request.attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 0 ) ).toInt();
int tileNo = request.attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ) ).toInt();
int retry = request.attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ) ).toInt();
int tileReqNo = request.attribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ) ).toInt();
int tileNo = request.attribute( static_cast<QNetworkRequest::Attribute>( TileIndex ) ).toInt();
int retry = request.attribute( static_cast<QNetworkRequest::Attribute>( TileRetry ) ).toInt();
retry++;

QSettings s;
@@ -1074,7 +1077,7 @@ void QgsWmsProvider::repeatTileRequest( QNetworkRequest const &oldRequest )
.arg( tileReqNo ).arg( tileNo ).arg( retry ), tr( "WMS" ), QgsMessageLog::INFO );
}
QgsDebugMsg( QString( "repeat tileRequest %1 %2(retry %3) for url: %4" ).arg( tileReqNo ).arg( tileNo ).arg( retry ).arg( url ) );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), retry );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), retry );

QNetworkReply *reply = QgsNetworkAccessManager::instance()->get( request );
mTileReplies << reply;
@@ -1124,10 +1127,10 @@ void QgsWmsProvider::tileReplyFinished()
QgsNetworkAccessManager::instance()->cache()->updateMetaData( cmd );
}

int tileReqNo = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 0 ) ).toInt();
int tileNo = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ) ).toInt();
QRectF r = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ) ).toRectF();
int retry = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ) ).toInt();
int tileReqNo = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ) ).toInt();
int tileNo = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( TileIndex ) ).toInt();
QRectF r = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( TileRect ) ).toRectF();
int retry = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( TileRetry ) ).toInt();

#if QT_VERSION >= 0x40500
QgsDebugMsg( QString( "tile reply %1 (%2) tile:%3(retry %4) rect:%5,%6 %7,%8) fromcache:%9 error:%10 url:%11" )
@@ -1155,10 +1158,10 @@ void QgsWmsProvider::tileReplyFinished()
setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 0 ), tileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ), tileNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ), r );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), retry );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ), tileReqNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileIndex ), tileNo );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRect ), r );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), 0 );

mTileReplies.removeOne( reply );
reply->deleteLater();
@@ -1496,7 +1499,7 @@ bool QgsWmsProvider::retrieveServerCapabilities( bool forceRefresh )

QgsDebugMsg( "exiting." );

return true;
return mError.isEmpty();
}

void QgsWmsProvider::capabilitiesReplyFinished()

0 comments on commit aa256b8

Please sign in to comment.
You can’t perform that action at this time.