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 if ( aUri.contains(
" password='"_L1 ) )
248 regexp.setPattern( u
" password='[^']*'"_s );
253 regexp.setPatternOptions( QRegularExpression::NoPatternOption );
254 regexp.setPattern( u
" password=[^ ]*"_s );
259 safeName.replace( regexp, u
" password=%1"_s.arg(
HIDING_TOKEN ) );
263 safeName.replace( regexp, u
""_s );
266 else if ( aUri.contains(
",password="_L1 ) )
268 regexp.setPattern( u
",password=.*,"_s );
272 safeName.replace( regexp, u
",password=%1,"_s.arg(
HIDING_TOKEN ) );
276 safeName.replace( regexp, u
","_s );
279 else if ( aUri.contains(
"IDB:"_L1 ) )
281 regexp.setPattern( u
" pass=.* "_s );
285 safeName.replace( regexp, u
" pass=%1 "_s.arg(
HIDING_TOKEN ) );
289 safeName.replace( regexp, u
" "_s );
292 else if ( ( aUri.contains(
"OCI:"_L1 ) ) || ( aUri.contains(
"ODBC:"_L1 ) ) )
294 regexp.setPattern( u
"/.*@"_s );
298 safeName.replace( regexp, u
"/%1@"_s.arg(
HIDING_TOKEN ) );
302 safeName.replace( regexp, u
"/@"_s );
305 else if ( aUri.contains(
"postgresql:"_L1 ) )
308 regexp.setPattern( u
"/.*@"_s );
309 const QString matched = regexp.match( aUri ).captured();
311 QString anonymised = matched;
312 const QStringList items = matched.split( u
":"_s );
313 if ( items.size() > 1 )
315 anonymised = matched.split( u
":"_s )[0];
320 anonymised.append( u
"@"_s );
323 safeName.replace( regexp, anonymised );
325 else if ( aUri.contains(
"SDE:"_L1 ) )
327 QStringList strlist = aUri.split(
',' );
328 safeName = strlist[0] +
',' + strlist[1] +
',' + strlist[2] +
',' + strlist[3];
335 return mAuthConfigId;
420 return mGeometryColumn;
443 mUseEstimatedMetadata = flag;
448 return mUseEstimatedMetadata;
453 mSelectAtIdDisabledSet =
true;
454 mSelectAtIdDisabled = flag;
459 return mSelectAtIdDisabled;
482QString QgsDataSourceUri::escape(
const QString &val, QChar delim =
'\'' )
const
484 QString escaped = val;
486 escaped.replace(
'\\',
"\\\\"_L1 );
487 escaped.replace( delim, u
"\\%1"_s.arg( delim ) );
502void QgsDataSourceUri::skipBlanks(
const QString &uri,
int &i )
505 while ( i <
uri.length() &&
uri[i].isSpace() )
509QString QgsDataSourceUri::getValue(
const QString &uri,
int &i )
511 skipBlanks(
uri, i );
515 if ( i <
uri.length() && (
uri[i] ==
'\'' ||
uri[i] ==
'"' ) )
517 const QChar delim =
uri[i];
524 if ( i ==
uri.length() )
526 QgsDebugError( u
"unterminated quoted string in connection info string"_s );
530 if (
uri[i] ==
'\\' )
533 if ( i ==
uri.length() )
535 if (
uri[i] != delim &&
uri[i] !=
'\\' )
538 else if (
uri[i] == delim )
550 while ( i <
uri.length() )
552 if (
uri[i].isSpace() )
558 if (
uri[i] ==
'\\' )
561 if ( i ==
uri.length() )
563 if (
uri[i] !=
'\\' &&
uri[i] !=
'\'' )
571 skipBlanks(
uri, i );
578 QStringList connectionItems;
580 if ( !mDatabase.isEmpty() )
582 connectionItems <<
"dbname='" + escape( mDatabase ) +
'\'';
585 if ( !mService.isEmpty() )
587 connectionItems <<
"service='" + escape( mService ) +
'\'';
589 else if ( !mHost.isEmpty() )
591 connectionItems <<
"host=" + mHost;
594 if ( mService.isEmpty() )
596 if ( !mPort.isEmpty() )
597 connectionItems <<
"port=" + mPort;
600 if ( !mDriver.isEmpty() )
602 connectionItems <<
"driver='" + escape( mDriver ) +
'\'';
605 if ( !mUsername.isEmpty() )
607 connectionItems <<
"user='" + escape( mUsername ) +
'\'';
609 if ( !mPassword.isEmpty() )
611 connectionItems <<
"password='" + escape( mPassword ) +
'\'';
617 connectionItems << u
"sslmode="_s +
encodeSslMode( mSSLmode );
620 if ( !mAuthConfigId.isEmpty() )
622 if ( expandAuthConfig )
626 QgsDebugError( u
"Data source URI FAILED to update via loading configuration ID '%1'"_s.arg( mAuthConfigId ) );
631 connectionItems <<
"authcfg=" + mAuthConfigId;
635 return connectionItems.join(
' '_L1 );
642 if ( !mKeyColumn.isEmpty() )
644 uri += u
" key='%1'"_s.arg( escape( mKeyColumn ) );
647 if ( mUseEstimatedMetadata )
649 uri +=
" estimatedmetadata=true"_L1;
652 if ( !mSrid.isEmpty() )
654 uri += u
" srid=%1"_s.arg( mSrid );
663 if ( mSelectAtIdDisabled )
665 uri +=
" selectatid=false"_L1;
668 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
670 if ( it.key().contains(
'=' ) || it.key().contains(
' ' ) )
672 QgsDebugError( u
"invalid uri parameter %1 skipped"_s.arg( it.key() ) );
676 uri +=
' ' + it.key() +
"='" + escape( it.value() ) +
'\'';
679 uri += mHttpHeaders.toSpacedString();
681 QString columnName( mGeometryColumn );
682 columnName.replace(
'\\',
"\\\\"_L1 );
683 columnName.replace(
')',
"\\)"_L1 );
685 if ( !mTable.isEmpty() )
687 uri += u
" table=%1%2"_s.arg(
quotedTablename(), mGeometryColumn.isEmpty() ? QString() : u
" (%1)"_s.arg( columnName ) );
689 else if ( !mSchema.isEmpty() )
691 uri += u
" schema='%1'"_s.arg( escape( mSchema ) );
694 if ( !mSql.isEmpty() )
696 uri += u
" sql="_s + mSql;
705 if (
string.isEmpty() )
706 return string.isNull() ? QByteArray() : QByteArray(
"" );
707 return string.toLatin1();
713 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
715 url.addQueryItem( it.key(), QUrl::toPercentEncoding( it.value() ) );
718 if ( !mUsername.isEmpty() )
719 url.addQueryItem( u
"username"_s, QUrl::toPercentEncoding( mUsername ) );
721 if ( !mPassword.isEmpty() )
722 url.addQueryItem( u
"password"_s, QUrl::toPercentEncoding( mPassword ) );
724 if ( !mAuthConfigId.isEmpty() )
725 url.addQueryItem( u
"authcfg"_s, QUrl::toPercentEncoding( mAuthConfigId ) );
727 mHttpHeaders.updateUrlQuery( url );
737 mAuthConfigId.clear();
740 url.setQuery( QString::fromLatin1(
uri ) );
741 const QUrlQuery query( url );
743 mHttpHeaders.setFromUrlQuery( query );
745 const auto constQueryItems = query.queryItems( QUrl::ComponentFormattingOption::FullyDecoded );
746 for (
const QPair<QString, QString> &item : constQueryItems )
750 if ( item.first ==
"username"_L1 )
751 mUsername = query.queryItemValue( u
"username"_s, QUrl::ComponentFormattingOption::FullyDecoded );
752 else if ( item.first ==
"password"_L1 )
753 mPassword = query.queryItemValue( u
"password"_s, QUrl::ComponentFormattingOption::FullyDecoded );
754 else if ( item.first ==
"authcfg"_L1 )
755 mAuthConfigId = query.queryItemValue( u
"authcfg"_s, QUrl::ComponentFormattingOption::FullyDecoded );
757 mParams.insert( item.first, item.second );
766 setEncodedUri( url.query( QUrl::EncodeUnicode ).toLatin1() );
771 if ( !mSchema.isEmpty() )
772 return u
"\"%1\".\"%2\""_s.arg( escape( mSchema,
'"' ), escape( mTable,
'"' ) );
774 return u
"\"%1\""_s.arg( escape( mTable,
'"' ) );
809 mAuthConfigId = authcfg;
841 else if (
sslMode ==
"disable"_L1 )
843 else if (
sslMode ==
"allow"_L1 )
845 else if (
sslMode ==
"require"_L1 )
847 else if (
sslMode ==
"verify-ca"_L1 )
849 else if (
sslMode ==
"verify-full"_L1 )
868 return u
"verify-ca"_s;
870 return u
"verify-full"_s;
878 if ( key ==
"username"_L1 )
880 else if ( key ==
"password"_L1 )
882 else if ( key ==
"authcfg"_L1 )
883 mAuthConfigId = value;
887 mParams.insert( key, value );
893 for (
const QString &val : value )
901 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
906 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
911 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
913 mAuthConfigId.clear();
917 return mParams.remove( key );
923 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
925 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
927 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
928 return mAuthConfigId;
930 return mParams.value( key );
936 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
937 return QStringList() << mUsername;
938 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
939 return QStringList() << mPassword;
940 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
941 return QStringList() << mAuthConfigId;
943 return mParams.values( key );
949 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
951 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
953 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
956 return mParams.contains( key );
961 QSet<QString> paramKeys;
962 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); it++ )
963 paramKeys.insert( it.key() );
965 if ( !mHost.isEmpty() )
966 paramKeys.insert(
"host"_L1 );
967 if ( !mPort.isEmpty() )
968 paramKeys.insert(
"port"_L1 );
969 if ( !mDriver.isEmpty() )
970 paramKeys.insert(
"driver"_L1 );
971 if ( !mService.isEmpty() )
972 paramKeys.insert(
"service"_L1 );
973 if ( !mDatabase.isEmpty() )
974 paramKeys.insert(
"dbname"_L1 );
975 if ( !mSchema.isEmpty() )
976 paramKeys.insert(
"schema"_L1 );
977 if ( !mTable.isEmpty() )
978 paramKeys.insert(
"table"_L1 );
980 if ( !mSql.isEmpty() )
981 paramKeys.insert(
"sql"_L1 );
982 if ( !mAuthConfigId.isEmpty() )
983 paramKeys.insert(
"authcfg"_L1 );
984 if ( !mUsername.isEmpty() )
985 paramKeys.insert(
"username"_L1 );
986 if ( !mPassword.isEmpty() )
987 paramKeys.insert(
"password"_L1 );
989 paramKeys.insert(
"sslmode"_L1 );
990 if ( !mKeyColumn.isEmpty() )
991 paramKeys.insert(
"key"_L1 );
992 if ( mUseEstimatedMetadata )
993 paramKeys.insert(
"estimatedmetadata"_L1 );
994 if ( mSelectAtIdDisabledSet )
995 paramKeys.insert(
"selectatid"_L1 );
997 paramKeys.insert(
"type"_L1 );
998 if ( !mSrid.isEmpty() )
999 paramKeys.insert(
"srid"_L1 );
1006 if ( mUseEstimatedMetadata != other.mUseEstimatedMetadata
1007 || mSelectAtIdDisabled != other.mSelectAtIdDisabled
1008 || mSelectAtIdDisabledSet != other.mSelectAtIdDisabledSet
1009 || mSSLmode != other.mSSLmode
1010 || mWkbType != other.mWkbType )
1015 if ( mHost != other.mHost
1016 || mPort != other.mPort
1017 || mDriver != other.mDriver
1018 || mService != other.mService
1019 || mDatabase != other.mDatabase
1020 || mSchema != other.mSchema
1021 || mTable != other.mTable
1022 || mGeometryColumn != other.mGeometryColumn
1023 || mSql != other.mSql
1024 || mAuthConfigId != other.mAuthConfigId
1025 || mUsername != other.mUsername
1026 || mPassword != other.mPassword
1027 || mKeyColumn != other.mKeyColumn
1028 || mSrid != other.mSrid
1029 || mParams != other.mParams
1030 || mHttpHeaders != other.mHttpHeaders )
1040 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)