26#include <QRegularExpression>
32#include "moc_qgsdatasourceuri.cpp"
34using namespace Qt::StringLiterals;
36#define HIDING_TOKEN u"XXXXXXXX"_s
47 while ( i <
uri.length() )
60 while ( i <
uri.length() &&
uri[i] !=
'=' && !
uri[i].isSpace() )
63 const QString pname =
uri.mid( start, i - start );
67 if ( i ==
uri.length() ||
uri[i] !=
'=' )
75 if ( pname ==
"sql"_L1 )
84 if ( mSql ==
"''"_L1 || mSql ==
"\"\""_L1 )
90 const QString pval = getValue(
uri, i );
92 if ( pname ==
"table"_L1 )
94 if ( i <
uri.length() &&
uri[i] ==
'.' )
99 mTable = getValue(
uri, i );
106 if ( i <
uri.length() &&
uri[i] ==
'(' )
111 while ( i <
uri.length() &&
uri[i] !=
')' )
113 if (
uri[i] ==
'\\' )
118 if ( i ==
uri.length() )
123 mGeometryColumn =
uri.mid( start, i - start );
124 mGeometryColumn.replace(
"\\)"_L1,
")"_L1 );
125 mGeometryColumn.replace(
"\\\\"_L1,
"\\"_L1 );
131 mGeometryColumn = QString();
134 else if ( pname ==
"schema"_L1 )
138 else if ( pname ==
"key"_L1 )
142 else if ( pname ==
"estimatedmetadata"_L1 )
144 mUseEstimatedMetadata = pval ==
"true"_L1;
146 else if ( pname ==
"srid"_L1 )
150 else if ( pname ==
"type"_L1 )
154 else if ( pname ==
"selectatid"_L1 )
156 mSelectAtIdDisabledSet =
true;
157 mSelectAtIdDisabled = pval ==
"false"_L1;
159 else if ( pname ==
"service"_L1 )
163 else if ( pname ==
"authcfg"_L1 )
165 mAuthConfigId = pval;
167 else if ( pname ==
"user"_L1 || pname ==
"username"_L1 )
171 else if ( pname ==
"password"_L1 )
175 else if ( pname ==
"connect_timeout"_L1 )
179 else if ( pname ==
"dbname"_L1 )
183 else if ( pname ==
"host"_L1 )
187 else if ( pname ==
"hostaddr"_L1 )
191 else if ( pname ==
"port"_L1 )
195 else if ( pname ==
"driver"_L1 )
199 else if ( pname ==
"tty"_L1 )
203 else if ( pname ==
"options"_L1 )
207 else if ( pname ==
"sslmode"_L1 )
211 else if ( pname ==
"requiressl"_L1 )
213 if ( pval ==
"0"_L1 )
218 else if ( pname ==
"krbsrvname"_L1 )
222 else if ( pname ==
"gsslib"_L1 )
228 mHttpHeaders.insert( pname, pval );
232 QgsDebugMsgLevel(
"parameter \"" + pname +
"\":\"" + pval +
"\" added", 4 );
241 QRegularExpression regexp;
242 regexp.setPatternOptions( QRegularExpression::InvertedGreedinessOption );
243 QString safeName( aUri );
244 if ( aUri.contains(
" password="_L1 ) )
246 regexp.setPattern( u
" password=.* "_s );
250 safeName.replace( regexp, u
" password=%1 "_s.arg(
HIDING_TOKEN ) );
254 safeName.replace( regexp, u
" "_s );
257 else if ( aUri.contains(
",password="_L1 ) )
259 regexp.setPattern( u
",password=.*,"_s );
263 safeName.replace( regexp, u
",password=%1,"_s.arg(
HIDING_TOKEN ) );
267 safeName.replace( regexp, u
","_s );
270 else if ( aUri.contains(
"IDB:"_L1 ) )
272 regexp.setPattern( u
" pass=.* "_s );
276 safeName.replace( regexp, u
" pass=%1 "_s.arg(
HIDING_TOKEN ) );
280 safeName.replace( regexp, u
" "_s );
283 else if ( ( aUri.contains(
"OCI:"_L1 ) )
284 || ( aUri.contains(
"ODBC:"_L1 ) ) )
286 regexp.setPattern( u
"/.*@"_s );
290 safeName.replace( regexp, u
"/%1@"_s.arg(
HIDING_TOKEN ) );
294 safeName.replace( regexp, u
"/@"_s );
297 else if ( aUri.contains(
"postgresql:"_L1 ) )
300 regexp.setPattern( u
"/.*@"_s );
301 const QString matched = regexp.match( aUri ).captured();
303 QString anonymised = matched;
304 const QStringList items = matched.split( u
":"_s );
305 if ( items.size() > 1 )
307 anonymised = matched.split( u
":"_s )[0];
312 anonymised.append( u
"@"_s );
315 safeName.replace( regexp, anonymised );
317 else if ( aUri.contains(
"SDE:"_L1 ) )
319 QStringList strlist = aUri.split(
',' );
320 safeName = strlist[0] +
',' + strlist[1] +
',' + strlist[2] +
',' + strlist[3];
327 return mAuthConfigId;
412 return mGeometryColumn;
435 mUseEstimatedMetadata = flag;
440 return mUseEstimatedMetadata;
445 mSelectAtIdDisabledSet =
true;
446 mSelectAtIdDisabled = flag;
451 return mSelectAtIdDisabled;
474QString QgsDataSourceUri::escape(
const QString &val, QChar delim =
'\'' )
const
476 QString escaped = val;
478 escaped.replace(
'\\',
"\\\\"_L1 );
479 escaped.replace( delim, u
"\\%1"_s.arg( delim ) );
494void QgsDataSourceUri::skipBlanks(
const QString &uri,
int &i )
497 while ( i <
uri.length() &&
uri[i].isSpace() )
501QString QgsDataSourceUri::getValue(
const QString &uri,
int &i )
503 skipBlanks(
uri, i );
507 if ( i <
uri.length() && (
uri[i] ==
'\'' ||
uri[i] ==
'"' ) )
509 const QChar delim =
uri[i];
516 if ( i ==
uri.length() )
518 QgsDebugError( u
"unterminated quoted string in connection info string"_s );
522 if (
uri[i] ==
'\\' )
525 if ( i ==
uri.length() )
527 if (
uri[i] != delim &&
uri[i] !=
'\\' )
530 else if (
uri[i] == delim )
542 while ( i <
uri.length() )
544 if (
uri[i].isSpace() )
550 if (
uri[i] ==
'\\' )
553 if ( i ==
uri.length() )
555 if (
uri[i] !=
'\\' &&
uri[i] !=
'\'' )
563 skipBlanks(
uri, i );
570 QStringList connectionItems;
572 if ( !mDatabase.isEmpty() )
574 connectionItems <<
"dbname='" + escape( mDatabase ) +
'\'';
577 if ( !mService.isEmpty() )
579 connectionItems <<
"service='" + escape( mService ) +
'\'';
581 else if ( !mHost.isEmpty() )
583 connectionItems <<
"host=" + mHost;
586 if ( mService.isEmpty() )
588 if ( !mPort.isEmpty() )
589 connectionItems <<
"port=" + mPort;
592 if ( !mDriver.isEmpty() )
594 connectionItems <<
"driver='" + escape( mDriver ) +
'\'';
597 if ( !mUsername.isEmpty() )
599 connectionItems <<
"user='" + escape( mUsername ) +
'\'';
601 if ( !mPassword.isEmpty() )
603 connectionItems <<
"password='" + escape( mPassword ) +
'\'';
609 connectionItems << u
"sslmode="_s +
encodeSslMode( mSSLmode );
612 if ( !mAuthConfigId.isEmpty() )
614 if ( expandAuthConfig )
618 QgsDebugError( u
"Data source URI FAILED to update via loading configuration ID '%1'"_s.arg( mAuthConfigId ) );
623 connectionItems <<
"authcfg=" + mAuthConfigId;
627 return connectionItems.join(
' '_L1 );
634 if ( !mKeyColumn.isEmpty() )
636 uri += u
" key='%1'"_s.arg( escape( mKeyColumn ) );
639 if ( mUseEstimatedMetadata )
641 uri +=
" estimatedmetadata=true"_L1;
644 if ( !mSrid.isEmpty() )
646 uri += u
" srid=%1"_s.arg( mSrid );
655 if ( mSelectAtIdDisabled )
657 uri +=
" selectatid=false"_L1;
660 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
662 if ( it.key().contains(
'=' ) || it.key().contains(
' ' ) )
664 QgsDebugError( u
"invalid uri parameter %1 skipped"_s.arg( it.key() ) );
668 uri +=
' ' + it.key() +
"='" + escape( it.value() ) +
'\'';
671 uri += mHttpHeaders.toSpacedString();
673 QString columnName( mGeometryColumn );
674 columnName.replace(
'\\',
"\\\\"_L1 );
675 columnName.replace(
')',
"\\)"_L1 );
677 if ( !mTable.isEmpty() )
679 uri += u
" table=%1%2"_s
681 mGeometryColumn.isEmpty() ? QString() : u
" (%1)"_s.arg( columnName ) );
683 else if ( !mSchema.isEmpty() )
685 uri += u
" schema='%1'"_s.arg( escape( mSchema ) );
688 if ( !mSql.isEmpty() )
690 uri += u
" sql="_s + mSql;
699 if (
string.isEmpty() )
700 return string.isNull() ? QByteArray() : QByteArray(
"" );
701 return string.toLatin1();
707 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
709 url.addQueryItem( it.key(), QUrl::toPercentEncoding( it.value() ) );
712 if ( !mUsername.isEmpty() )
713 url.addQueryItem( u
"username"_s, QUrl::toPercentEncoding( mUsername ) );
715 if ( !mPassword.isEmpty() )
716 url.addQueryItem( u
"password"_s, QUrl::toPercentEncoding( mPassword ) );
718 if ( !mAuthConfigId.isEmpty() )
719 url.addQueryItem( u
"authcfg"_s, QUrl::toPercentEncoding( mAuthConfigId ) );
721 mHttpHeaders.updateUrlQuery( url );
731 mAuthConfigId.clear();
734 url.setQuery( QString::fromLatin1(
uri ) );
735 const QUrlQuery query( url );
737 mHttpHeaders.setFromUrlQuery( query );
739 const auto constQueryItems = query.queryItems( QUrl::ComponentFormattingOption::FullyDecoded );
740 for (
const QPair<QString, QString> &item : constQueryItems )
744 if ( item.first ==
"username"_L1 )
745 mUsername = query.queryItemValue( u
"username"_s, QUrl::ComponentFormattingOption::FullyDecoded );
746 else if ( item.first ==
"password"_L1 )
747 mPassword = query.queryItemValue( u
"password"_s, QUrl::ComponentFormattingOption::FullyDecoded );
748 else if ( item.first ==
"authcfg"_L1 )
749 mAuthConfigId = query.queryItemValue( u
"authcfg"_s, QUrl::ComponentFormattingOption::FullyDecoded );
751 mParams.insert( item.first, item.second );
760 setEncodedUri( url.query( QUrl::EncodeUnicode ).toLatin1() );
765 if ( !mSchema.isEmpty() )
766 return u
"\"%1\".\"%2\""_s
767 .arg( escape( mSchema,
'"' ),
768 escape( mTable,
'"' ) );
771 .arg( escape( mTable,
'"' ) );
807 const QString &
table,
821 mAuthConfigId = authcfg;
853 else if (
sslMode ==
"disable"_L1 )
855 else if (
sslMode ==
"allow"_L1 )
857 else if (
sslMode ==
"require"_L1 )
859 else if (
sslMode ==
"verify-ca"_L1 )
861 else if (
sslMode ==
"verify-full"_L1 )
884 if ( key ==
"username"_L1 )
886 else if ( key ==
"password"_L1 )
888 else if ( key ==
"authcfg"_L1 )
889 mAuthConfigId = value;
893 mParams.insert( key, value );
899 for (
const QString &val : value )
907 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
912 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
917 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
919 mAuthConfigId.clear();
923 return mParams.remove( key );
929 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
931 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
933 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
934 return mAuthConfigId;
936 return mParams.value( key );
942 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
943 return QStringList() << mUsername;
944 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
945 return QStringList() << mPassword;
946 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
947 return QStringList() << mAuthConfigId;
949 return mParams.values( key );
955 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
957 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
959 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
962 return mParams.contains( key );
967 QSet<QString> paramKeys;
968 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); it++ )
969 paramKeys.insert( it.key() );
971 if ( !mHost.isEmpty() )
972 paramKeys.insert(
"host"_L1 );
973 if ( !mPort.isEmpty() )
974 paramKeys.insert(
"port"_L1 );
975 if ( !mDriver.isEmpty() )
976 paramKeys.insert(
"driver"_L1 );
977 if ( !mService.isEmpty() )
978 paramKeys.insert(
"service"_L1 );
979 if ( !mDatabase.isEmpty() )
980 paramKeys.insert(
"dbname"_L1 );
981 if ( !mSchema.isEmpty() )
982 paramKeys.insert(
"schema"_L1 );
983 if ( !mTable.isEmpty() )
984 paramKeys.insert(
"table"_L1 );
986 if ( !mSql.isEmpty() )
987 paramKeys.insert(
"sql"_L1 );
988 if ( !mAuthConfigId.isEmpty() )
989 paramKeys.insert(
"authcfg"_L1 );
990 if ( !mUsername.isEmpty() )
991 paramKeys.insert(
"username"_L1 );
992 if ( !mPassword.isEmpty() )
993 paramKeys.insert(
"password"_L1 );
995 paramKeys.insert(
"sslmode"_L1 );
996 if ( !mKeyColumn.isEmpty() )
997 paramKeys.insert(
"key"_L1 );
998 if ( mUseEstimatedMetadata )
999 paramKeys.insert(
"estimatedmetadata"_L1 );
1000 if ( mSelectAtIdDisabledSet )
1001 paramKeys.insert(
"selectatid"_L1 );
1003 paramKeys.insert(
"type"_L1 );
1004 if ( !mSrid.isEmpty() )
1005 paramKeys.insert(
"srid"_L1 );
1012 if ( mUseEstimatedMetadata != other.mUseEstimatedMetadata ||
1013 mSelectAtIdDisabled != other.mSelectAtIdDisabled ||
1014 mSelectAtIdDisabledSet != other.mSelectAtIdDisabledSet ||
1015 mSSLmode != other.mSSLmode ||
1016 mWkbType != other.mWkbType )
1021 if ( mHost != other.mHost ||
1022 mPort != other.mPort ||
1023 mDriver != other.mDriver ||
1024 mService != other.mService ||
1025 mDatabase != other.mDatabase ||
1026 mSchema != other.mSchema ||
1027 mTable != other.mTable ||
1028 mGeometryColumn != other.mGeometryColumn ||
1029 mSql != other.mSql ||
1030 mAuthConfigId != other.mAuthConfigId ||
1031 mUsername != other.mUsername ||
1032 mPassword != other.mPassword ||
1033 mKeyColumn != other.mKeyColumn ||
1034 mSrid != other.mSrid ||
1035 mParams != other.mParams ||
1036 mHttpHeaders != other.mHttpHeaders )
1046 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)