26#include <QRegularExpression>
31#include "moc_qgsdatasourceuri.cpp"
33#define HIDING_TOKEN QStringLiteral( "XXXXXXXX" )
44 while ( i <
uri.length() )
50 QgsDebugError( QStringLiteral(
"parameter name expected before =" ) );
57 while ( i <
uri.length() &&
uri[i] !=
'=' && !
uri[i].isSpace() )
60 const QString pname =
uri.mid( start, i - start );
64 if ( i ==
uri.length() ||
uri[i] !=
'=' )
72 if ( pname == QLatin1String(
"sql" ) )
81 if ( mSql == QLatin1String(
"''" ) || mSql == QLatin1String(
"\"\"" ) )
87 const QString pval = getValue(
uri, i );
89 if ( pname == QLatin1String(
"table" ) )
91 if ( i <
uri.length() &&
uri[i] ==
'.' )
96 mTable = getValue(
uri, i );
103 if ( i <
uri.length() &&
uri[i] ==
'(' )
108 while ( i <
uri.length() &&
uri[i] !=
')' )
110 if (
uri[i] ==
'\\' )
115 if ( i ==
uri.length() )
117 QgsDebugError( QStringLiteral(
"closing parenthesis missing" ) );
120 mGeometryColumn =
uri.mid( start, i - start );
121 mGeometryColumn.replace( QLatin1String(
"\\)" ), QLatin1String(
")" ) );
122 mGeometryColumn.replace( QLatin1String(
"\\\\" ), QLatin1String(
"\\" ) );
128 mGeometryColumn = QString();
131 else if ( pname == QLatin1String(
"schema" ) )
135 else if ( pname == QLatin1String(
"key" ) )
139 else if ( pname == QLatin1String(
"estimatedmetadata" ) )
141 mUseEstimatedMetadata = pval == QLatin1String(
"true" );
143 else if ( pname == QLatin1String(
"srid" ) )
147 else if ( pname == QLatin1String(
"type" ) )
151 else if ( pname == QLatin1String(
"selectatid" ) )
153 mSelectAtIdDisabledSet =
true;
154 mSelectAtIdDisabled = pval == QLatin1String(
"false" );
156 else if ( pname == QLatin1String(
"service" ) )
160 else if ( pname == QLatin1String(
"authcfg" ) )
162 mAuthConfigId = pval;
164 else if ( pname == QLatin1String(
"user" ) || pname == QLatin1String(
"username" ) )
168 else if ( pname == QLatin1String(
"password" ) )
172 else if ( pname == QLatin1String(
"connect_timeout" ) )
176 else if ( pname == QLatin1String(
"dbname" ) )
180 else if ( pname == QLatin1String(
"host" ) )
184 else if ( pname == QLatin1String(
"hostaddr" ) )
186 QgsDebugMsgLevel( QStringLiteral(
"database host ip address ignored" ), 2 );
188 else if ( pname == QLatin1String(
"port" ) )
192 else if ( pname == QLatin1String(
"driver" ) )
196 else if ( pname == QLatin1String(
"tty" ) )
200 else if ( pname == QLatin1String(
"options" ) )
204 else if ( pname == QLatin1String(
"sslmode" ) )
208 else if ( pname == QLatin1String(
"requiressl" ) )
210 if ( pval == QLatin1String(
"0" ) )
215 else if ( pname == QLatin1String(
"krbsrvname" ) )
219 else if ( pname == QLatin1String(
"gsslib" ) )
225 mHttpHeaders.insert( pname, pval );
229 QgsDebugMsgLevel(
"parameter \"" + pname +
"\":\"" + pval +
"\" added", 4 );
238 QRegularExpression regexp;
239 regexp.setPatternOptions( QRegularExpression::InvertedGreedinessOption );
240 QString safeName( aUri );
241 if ( aUri.contains( QLatin1String(
" password=" ) ) )
243 regexp.setPattern( QStringLiteral(
" password=.* " ) );
247 safeName.replace( regexp, QStringLiteral(
" password=%1 " ).arg(
HIDING_TOKEN ) );
251 safeName.replace( regexp, QStringLiteral(
" " ) );
254 else if ( aUri.contains( QLatin1String(
",password=" ) ) )
256 regexp.setPattern( QStringLiteral(
",password=.*," ) );
260 safeName.replace( regexp, QStringLiteral(
",password=%1," ).arg(
HIDING_TOKEN ) );
264 safeName.replace( regexp, QStringLiteral(
"," ) );
267 else if ( aUri.contains( QLatin1String(
"IDB:" ) ) )
269 regexp.setPattern( QStringLiteral(
" pass=.* " ) );
273 safeName.replace( regexp, QStringLiteral(
" pass=%1 " ).arg(
HIDING_TOKEN ) );
277 safeName.replace( regexp, QStringLiteral(
" " ) );
280 else if ( ( aUri.contains( QLatin1String(
"OCI:" ) ) )
281 || ( aUri.contains( QLatin1String(
"ODBC:" ) ) ) )
283 regexp.setPattern( QStringLiteral(
"/.*@" ) );
287 safeName.replace( regexp, QStringLiteral(
"/%1@" ).arg(
HIDING_TOKEN ) );
291 safeName.replace( regexp, QStringLiteral(
"/@" ) );
294 else if ( aUri.contains( QLatin1String(
"postgresql:" ) ) )
297 regexp.setPattern( QStringLiteral(
"/.*@" ) );
298 const QString matched = regexp.match( aUri ).captured();
300 QString anonymised = matched;
301 const QStringList items = matched.split( QStringLiteral(
":" ) );
302 if ( items.size() > 1 )
304 anonymised = matched.split( QStringLiteral(
":" ) )[0];
307 anonymised.append( QStringLiteral(
":%1" ).arg(
HIDING_TOKEN ) );
309 anonymised.append( QStringLiteral(
"@" ) );
312 safeName.replace( regexp, anonymised );
314 else if ( aUri.contains( QLatin1String(
"SDE:" ) ) )
316 QStringList strlist = aUri.split(
',' );
317 safeName = strlist[0] +
',' + strlist[1] +
',' + strlist[2] +
',' + strlist[3];
324 return mAuthConfigId;
409 return mGeometryColumn;
432 mUseEstimatedMetadata = flag;
437 return mUseEstimatedMetadata;
442 mSelectAtIdDisabledSet =
true;
443 mSelectAtIdDisabled = flag;
448 return mSelectAtIdDisabled;
471QString QgsDataSourceUri::escape(
const QString &val, QChar delim =
'\'' )
const
473 QString escaped = val;
475 escaped.replace(
'\\', QLatin1String(
"\\\\" ) );
476 escaped.replace( delim, QStringLiteral(
"\\%1" ).arg( delim ) );
491void QgsDataSourceUri::skipBlanks(
const QString &uri,
int &i )
494 while ( i <
uri.length() &&
uri[i].isSpace() )
498QString QgsDataSourceUri::getValue(
const QString &uri,
int &i )
500 skipBlanks(
uri, i );
504 if ( i <
uri.length() && (
uri[i] ==
'\'' ||
uri[i] ==
'"' ) )
506 const QChar delim =
uri[i];
513 if ( i ==
uri.length() )
515 QgsDebugError( QStringLiteral(
"unterminated quoted string in connection info string" ) );
519 if (
uri[i] ==
'\\' )
522 if ( i ==
uri.length() )
524 if (
uri[i] != delim &&
uri[i] !=
'\\' )
527 else if (
uri[i] == delim )
539 while ( i <
uri.length() )
541 if (
uri[i].isSpace() )
547 if (
uri[i] ==
'\\' )
550 if ( i ==
uri.length() )
552 if (
uri[i] !=
'\\' &&
uri[i] !=
'\'' )
560 skipBlanks(
uri, i );
567 QStringList connectionItems;
569 if ( !mDatabase.isEmpty() )
571 connectionItems <<
"dbname='" + escape( mDatabase ) +
'\'';
574 if ( !mService.isEmpty() )
576 connectionItems <<
"service='" + escape( mService ) +
'\'';
578 else if ( !mHost.isEmpty() )
580 connectionItems <<
"host=" + mHost;
583 if ( mService.isEmpty() )
585 if ( !mPort.isEmpty() )
586 connectionItems <<
"port=" + mPort;
589 if ( !mDriver.isEmpty() )
591 connectionItems <<
"driver='" + escape( mDriver ) +
'\'';
594 if ( !mUsername.isEmpty() )
596 connectionItems <<
"user='" + escape( mUsername ) +
'\'';
598 if ( !mPassword.isEmpty() )
600 connectionItems <<
"password='" + escape( mPassword ) +
'\'';
606 connectionItems << QStringLiteral(
"sslmode=" ) +
encodeSslMode( mSSLmode );
609 if ( !mAuthConfigId.isEmpty() )
611 if ( expandAuthConfig )
615 QgsDebugError( QStringLiteral(
"Data source URI FAILED to update via loading configuration ID '%1'" ).arg( mAuthConfigId ) );
620 connectionItems <<
"authcfg=" + mAuthConfigId;
624 return connectionItems.join( QLatin1Char(
' ' ) );
631 if ( !mKeyColumn.isEmpty() )
633 uri += QStringLiteral(
" key='%1'" ).arg( escape( mKeyColumn ) );
636 if ( mUseEstimatedMetadata )
638 uri += QLatin1String(
" estimatedmetadata=true" );
641 if ( !mSrid.isEmpty() )
643 uri += QStringLiteral(
" srid=%1" ).arg( mSrid );
648 uri += QLatin1String(
" type=" );
652 if ( mSelectAtIdDisabled )
654 uri += QLatin1String(
" selectatid=false" );
657 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
659 if ( it.key().contains(
'=' ) || it.key().contains(
' ' ) )
661 QgsDebugError( QStringLiteral(
"invalid uri parameter %1 skipped" ).arg( it.key() ) );
665 uri +=
' ' + it.key() +
"='" + escape( it.value() ) +
'\'';
668 uri += mHttpHeaders.toSpacedString();
670 QString columnName( mGeometryColumn );
671 columnName.replace(
'\\', QLatin1String(
"\\\\" ) );
672 columnName.replace(
')', QLatin1String(
"\\)" ) );
674 if ( !mTable.isEmpty() )
676 uri += QStringLiteral(
" table=%1%2" )
678 mGeometryColumn.isEmpty() ? QString() : QStringLiteral(
" (%1)" ).arg( columnName ) );
680 else if ( !mSchema.isEmpty() )
682 uri += QStringLiteral(
" schema='%1'" ).arg( escape( mSchema ) );
685 if ( !mSql.isEmpty() )
687 uri += QStringLiteral(
" sql=" ) + mSql;
696 if (
string.isEmpty() )
697 return string.isNull() ? QByteArray() : QByteArray(
"" );
698 return string.toLatin1();
704 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
706 url.addQueryItem( it.key(), QUrl::toPercentEncoding( it.value() ) );
709 if ( !mUsername.isEmpty() )
710 url.addQueryItem( QStringLiteral(
"username" ), QUrl::toPercentEncoding( mUsername ) );
712 if ( !mPassword.isEmpty() )
713 url.addQueryItem( QStringLiteral(
"password" ), QUrl::toPercentEncoding( mPassword ) );
715 if ( !mAuthConfigId.isEmpty() )
716 url.addQueryItem( QStringLiteral(
"authcfg" ), QUrl::toPercentEncoding( mAuthConfigId ) );
718 mHttpHeaders.updateUrlQuery( url );
728 mAuthConfigId.clear();
731 url.setQuery( QString::fromLatin1(
uri ) );
732 const QUrlQuery query( url );
734 mHttpHeaders.setFromUrlQuery( query );
736 const auto constQueryItems = query.queryItems( QUrl::ComponentFormattingOption::FullyDecoded );
737 for (
const QPair<QString, QString> &item : constQueryItems )
741 if ( item.first == QLatin1String(
"username" ) )
742 mUsername = query.queryItemValue( QStringLiteral(
"username" ), QUrl::ComponentFormattingOption::FullyDecoded );
743 else if ( item.first == QLatin1String(
"password" ) )
744 mPassword = query.queryItemValue( QStringLiteral(
"password" ), QUrl::ComponentFormattingOption::FullyDecoded );
745 else if ( item.first == QLatin1String(
"authcfg" ) )
746 mAuthConfigId = query.queryItemValue( QStringLiteral(
"authcfg" ), QUrl::ComponentFormattingOption::FullyDecoded );
748 mParams.insert( item.first, item.second );
757 setEncodedUri( url.query( QUrl::EncodeUnicode ).toLatin1() );
762 if ( !mSchema.isEmpty() )
763 return QStringLiteral(
"\"%1\".\"%2\"" )
764 .arg( escape( mSchema,
'"' ),
765 escape( mTable,
'"' ) );
767 return QStringLiteral(
"\"%1\"" )
768 .arg( escape( mTable,
'"' ) );
804 const QString &
table,
818 mAuthConfigId = authcfg;
848 if (
sslMode == QLatin1String(
"prefer" ) )
850 else if (
sslMode == QLatin1String(
"disable" ) )
852 else if (
sslMode == QLatin1String(
"allow" ) )
854 else if (
sslMode == QLatin1String(
"require" ) )
856 else if (
sslMode == QLatin1String(
"verify-ca" ) )
858 else if (
sslMode == QLatin1String(
"verify-full" ) )
868 case SslPrefer:
return QStringLiteral(
"prefer" );
869 case SslDisable:
return QStringLiteral(
"disable" );
870 case SslAllow:
return QStringLiteral(
"allow" );
871 case SslRequire:
return QStringLiteral(
"require" );
872 case SslVerifyCa:
return QStringLiteral(
"verify-ca" );
881 if ( key == QLatin1String(
"username" ) )
883 else if ( key == QLatin1String(
"password" ) )
885 else if ( key == QLatin1String(
"authcfg" ) )
886 mAuthConfigId = value;
890 mParams.insert( key, value );
896 for (
const QString &val : value )
904 if ( key == QLatin1String(
"username" ) && !mUsername.isEmpty() )
909 else if ( key == QLatin1String(
"password" ) && !mPassword.isEmpty() )
914 else if ( key == QLatin1String(
"authcfg" ) && !mAuthConfigId.isEmpty() )
916 mAuthConfigId.clear();
920 return mParams.remove( key );
926 if ( key == QLatin1String(
"username" ) && !mUsername.isEmpty() )
928 else if ( key == QLatin1String(
"password" ) && !mPassword.isEmpty() )
930 else if ( key == QLatin1String(
"authcfg" ) && !mAuthConfigId.isEmpty() )
931 return mAuthConfigId;
933 return mParams.value( key );
939 if ( key == QLatin1String(
"username" ) && !mUsername.isEmpty() )
940 return QStringList() << mUsername;
941 else if ( key == QLatin1String(
"password" ) && !mPassword.isEmpty() )
942 return QStringList() << mPassword;
943 else if ( key == QLatin1String(
"authcfg" ) && !mAuthConfigId.isEmpty() )
944 return QStringList() << mAuthConfigId;
946 return mParams.values( key );
952 if ( key == QLatin1String(
"username" ) && !mUsername.isEmpty() )
954 else if ( key == QLatin1String(
"password" ) && !mPassword.isEmpty() )
956 else if ( key == QLatin1String(
"authcfg" ) && !mAuthConfigId.isEmpty() )
959 return mParams.contains( key );
964 QSet<QString> paramKeys;
965 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); it++ )
966 paramKeys.insert( it.key() );
968 if ( !mHost.isEmpty() )
969 paramKeys.insert( QLatin1String(
"host" ) );
970 if ( !mPort.isEmpty() )
971 paramKeys.insert( QLatin1String(
"port" ) );
972 if ( !mDriver.isEmpty() )
973 paramKeys.insert( QLatin1String(
"driver" ) );
974 if ( !mService.isEmpty() )
975 paramKeys.insert( QLatin1String(
"service" ) );
976 if ( !mDatabase.isEmpty() )
977 paramKeys.insert( QLatin1String(
"dbname" ) );
978 if ( !mSchema.isEmpty() )
979 paramKeys.insert( QLatin1String(
"schema" ) );
980 if ( !mTable.isEmpty() )
981 paramKeys.insert( QLatin1String(
"table" ) );
983 if ( !mSql.isEmpty() )
984 paramKeys.insert( QLatin1String(
"sql" ) );
985 if ( !mAuthConfigId.isEmpty() )
986 paramKeys.insert( QLatin1String(
"authcfg" ) );
987 if ( !mUsername.isEmpty() )
988 paramKeys.insert( QLatin1String(
"username" ) );
989 if ( !mPassword.isEmpty() )
990 paramKeys.insert( QLatin1String(
"password" ) );
992 paramKeys.insert( QLatin1String(
"sslmode" ) );
993 if ( !mKeyColumn.isEmpty() )
994 paramKeys.insert( QLatin1String(
"key" ) );
995 if ( mUseEstimatedMetadata )
996 paramKeys.insert( QLatin1String(
"estimatedmetadata" ) );
997 if ( mSelectAtIdDisabledSet )
998 paramKeys.insert( QLatin1String(
"selectatid" ) );
1000 paramKeys.insert( QLatin1String(
"type" ) );
1001 if ( !mSrid.isEmpty() )
1002 paramKeys.insert( QLatin1String(
"srid" ) );
1009 if ( mUseEstimatedMetadata != other.mUseEstimatedMetadata ||
1010 mSelectAtIdDisabled != other.mSelectAtIdDisabled ||
1011 mSelectAtIdDisabledSet != other.mSelectAtIdDisabledSet ||
1012 mSSLmode != other.mSSLmode ||
1013 mWkbType != other.mWkbType )
1018 if ( mHost != other.mHost ||
1019 mPort != other.mPort ||
1020 mDriver != other.mDriver ||
1021 mService != other.mService ||
1022 mDatabase != other.mDatabase ||
1023 mSchema != other.mSchema ||
1024 mTable != other.mTable ||
1025 mGeometryColumn != other.mGeometryColumn ||
1026 mSql != other.mSql ||
1027 mAuthConfigId != other.mAuthConfigId ||
1028 mUsername != other.mUsername ||
1029 mPassword != other.mPassword ||
1030 mKeyColumn != other.mKeyColumn ||
1031 mSrid != other.mSrid ||
1032 mParams != other.mParams ||
1033 mHttpHeaders != other.mHttpHeaders )
1043 return !( *
this == other );
WkbType
The WKB type describes the number of dimensions a geometry has.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
QString srid() const
Returns the spatial reference ID associated with the URI.
SslMode
Available SSL connection modes.
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SslMode sslmode=SslPrefer, const QString &authConfigId=QString())
Sets all connection related members at once.
QByteArray encodedUri() const
Returns the complete encoded URI as a byte array.
QStringList params(const QString &key) const
Returns multiple generic parameter values corresponding to the specified key.
void setSchema(const QString &schema)
Sets the scheme for the URI.
bool hasParam(const QString &key) const
Returns true if a parameter with the specified key exists.
int removeParam(const QString &key)
Removes a generic parameter by key.
static SslMode decodeSslMode(const QString &sslMode)
Decodes SSL mode string into enum value.
void setSql(const QString &sql)
Sets the sql filter for the URI.
void setEncodedUri(const QByteArray &uri)
Sets the complete encoded uri.
QString table() const
Returns the table name stored in the URI.
void setTable(const QString &table)
Sets table to table.
void setAuthConfigId(const QString &authcfg)
Sets the authentication configuration ID for the URI.
QString quotedTablename() const
Returns the URI's table name, escaped and quoted.
void setGeometryColumn(const QString &geometryColumn)
Sets geometry column name to geometryColumn.
QString schema() const
Returns the schema stored in the URI.
void setUseEstimatedMetadata(bool flag)
Sets whether estimated metadata should be used for the connection.
QString connectionInfo(bool expandAuthConfig=true) const
Returns the connection part of the URI.
QString uri(bool expandAuthConfig=true) const
Returns the complete URI as a string.
void setUsername(const QString &username)
Sets the username for the URI.
QString param(const QString &key) const
Returns a generic parameter value corresponding to the specified key.
void disableSelectAtId(bool flag)
Set to true to disable selection by feature ID.
bool selectAtIdDisabled() const
Returns whether the selection by feature ID is disabled.
void setHost(const QString &host)
Sets the host name stored in the URI.
void setDataSource(const QString &aSchema, const QString &aTable, const QString &aGeometryColumn, const QString &aSql=QString(), const QString &aKeyColumn=QString())
Sets all data source related members at once.
QString username() const
Returns the username stored in the URI.
void setService(const QString &service)
Sets the service name associated with the URI.
static QString encodeSslMode(SslMode sslMode)
Encodes SSL mode enum value into a string.
Qgis::WkbType wkbType() const
Returns the WKB type associated with the URI.
void setSslMode(SslMode mode)
Sets the SSL mode associated with the URI.
void setWkbType(Qgis::WkbType type)
Sets the WKB type associated with the URI.
QString driver() const
Returns the driver name stored in the URI.
QString host() const
Returns the host name stored in the URI.
void setPort(const QString &port)
Sets the port stored in the URI.
bool operator==(const QgsDataSourceUri &other) const
void setParam(const QString &key, const QString &value)
Sets a generic parameter value on the URI.
QString service() const
Returns the service name associated with the URI.
void setKeyColumn(const QString &column)
Sets the name of the (primary) key column.
bool useEstimatedMetadata() const
Returns true if estimated metadata should be used for the connection.
SslMode sslMode() const
Returns the SSL mode associated with the URI.
QString password() const
Returns the password stored in the URI.
QString keyColumn() const
Returns the name of the (primary) key column for the referenced table.
QString authConfigId() const
Returns any associated authentication configuration ID stored in the URI.
QString port() const
Returns the port stored in the URI.
QSet< QString > parameterKeys() const
Returns parameter keys used in the uri: specialized ones ("table", "schema", etc.) or generic paramet...
QString database() const
Returns the database name stored in the URI.
void clearSchema()
Clears the schema stored in the URI.
void setDriver(const QString &driver)
Sets the driver name stored in the URI.
static QString removePassword(const QString &aUri, bool hide=false)
Removes the password element from a URI.
void setDatabase(const QString &database)
Sets the URI database name.
bool operator!=(const QgsDataSourceUri &other) const
QString geometryColumn() const
Returns the name of the geometry column stored in the URI, if set.
void setSrid(const QString &srid)
Sets the spatial reference ID associated with the URI.
QString sql() const
Returns the SQL filter stored in the URI, if set.
void setPassword(const QString &password)
Sets the password for the URI.
static Qgis::WkbType parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
static Q_INVOKABLE QString displayString(Qgis::WkbType type)
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
QByteArray toLatin1_helper(const QString &string)
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)