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 );
252 regexp.setPattern( u
" password=.* "_s );
257 safeName.replace( regexp, u
" password=%1 "_s.arg(
HIDING_TOKEN ) );
261 safeName.replace( regexp, u
" "_s );
264 else if ( aUri.contains(
",password="_L1 ) )
266 regexp.setPattern( u
",password=.*,"_s );
270 safeName.replace( regexp, u
",password=%1,"_s.arg(
HIDING_TOKEN ) );
274 safeName.replace( regexp, u
","_s );
277 else if ( aUri.contains(
"IDB:"_L1 ) )
279 regexp.setPattern( u
" pass=.* "_s );
283 safeName.replace( regexp, u
" pass=%1 "_s.arg(
HIDING_TOKEN ) );
287 safeName.replace( regexp, u
" "_s );
290 else if ( ( aUri.contains(
"OCI:"_L1 ) ) || ( aUri.contains(
"ODBC:"_L1 ) ) )
292 regexp.setPattern( u
"/.*@"_s );
296 safeName.replace( regexp, u
"/%1@"_s.arg(
HIDING_TOKEN ) );
300 safeName.replace( regexp, u
"/@"_s );
303 else if ( aUri.contains(
"postgresql:"_L1 ) )
306 regexp.setPattern( u
"/.*@"_s );
307 const QString matched = regexp.match( aUri ).captured();
309 QString anonymised = matched;
310 const QStringList items = matched.split( u
":"_s );
311 if ( items.size() > 1 )
313 anonymised = matched.split( u
":"_s )[0];
318 anonymised.append( u
"@"_s );
321 safeName.replace( regexp, anonymised );
323 else if ( aUri.contains(
"SDE:"_L1 ) )
325 QStringList strlist = aUri.split(
',' );
326 safeName = strlist[0] +
',' + strlist[1] +
',' + strlist[2] +
',' + strlist[3];
333 return mAuthConfigId;
418 return mGeometryColumn;
441 mUseEstimatedMetadata = flag;
446 return mUseEstimatedMetadata;
451 mSelectAtIdDisabledSet =
true;
452 mSelectAtIdDisabled = flag;
457 return mSelectAtIdDisabled;
480QString QgsDataSourceUri::escape(
const QString &val, QChar delim =
'\'' )
const
482 QString escaped = val;
484 escaped.replace(
'\\',
"\\\\"_L1 );
485 escaped.replace( delim, u
"\\%1"_s.arg( delim ) );
500void QgsDataSourceUri::skipBlanks(
const QString &uri,
int &i )
503 while ( i <
uri.length() &&
uri[i].isSpace() )
507QString QgsDataSourceUri::getValue(
const QString &uri,
int &i )
509 skipBlanks(
uri, i );
513 if ( i <
uri.length() && (
uri[i] ==
'\'' ||
uri[i] ==
'"' ) )
515 const QChar delim =
uri[i];
522 if ( i ==
uri.length() )
524 QgsDebugError( u
"unterminated quoted string in connection info string"_s );
528 if (
uri[i] ==
'\\' )
531 if ( i ==
uri.length() )
533 if (
uri[i] != delim &&
uri[i] !=
'\\' )
536 else if (
uri[i] == delim )
548 while ( i <
uri.length() )
550 if (
uri[i].isSpace() )
556 if (
uri[i] ==
'\\' )
559 if ( i ==
uri.length() )
561 if (
uri[i] !=
'\\' &&
uri[i] !=
'\'' )
569 skipBlanks(
uri, i );
576 QStringList connectionItems;
578 if ( !mDatabase.isEmpty() )
580 connectionItems <<
"dbname='" + escape( mDatabase ) +
'\'';
583 if ( !mService.isEmpty() )
585 connectionItems <<
"service='" + escape( mService ) +
'\'';
587 else if ( !mHost.isEmpty() )
589 connectionItems <<
"host=" + mHost;
592 if ( mService.isEmpty() )
594 if ( !mPort.isEmpty() )
595 connectionItems <<
"port=" + mPort;
598 if ( !mDriver.isEmpty() )
600 connectionItems <<
"driver='" + escape( mDriver ) +
'\'';
603 if ( !mUsername.isEmpty() )
605 connectionItems <<
"user='" + escape( mUsername ) +
'\'';
607 if ( !mPassword.isEmpty() )
609 connectionItems <<
"password='" + escape( mPassword ) +
'\'';
615 connectionItems << u
"sslmode="_s +
encodeSslMode( mSSLmode );
618 if ( !mAuthConfigId.isEmpty() )
620 if ( expandAuthConfig )
624 QgsDebugError( u
"Data source URI FAILED to update via loading configuration ID '%1'"_s.arg( mAuthConfigId ) );
629 connectionItems <<
"authcfg=" + mAuthConfigId;
633 return connectionItems.join(
' '_L1 );
640 if ( !mKeyColumn.isEmpty() )
642 uri += u
" key='%1'"_s.arg( escape( mKeyColumn ) );
645 if ( mUseEstimatedMetadata )
647 uri +=
" estimatedmetadata=true"_L1;
650 if ( !mSrid.isEmpty() )
652 uri += u
" srid=%1"_s.arg( mSrid );
661 if ( mSelectAtIdDisabled )
663 uri +=
" selectatid=false"_L1;
666 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
668 if ( it.key().contains(
'=' ) || it.key().contains(
' ' ) )
670 QgsDebugError( u
"invalid uri parameter %1 skipped"_s.arg( it.key() ) );
674 uri +=
' ' + it.key() +
"='" + escape( it.value() ) +
'\'';
677 uri += mHttpHeaders.toSpacedString();
679 QString columnName( mGeometryColumn );
680 columnName.replace(
'\\',
"\\\\"_L1 );
681 columnName.replace(
')',
"\\)"_L1 );
683 if ( !mTable.isEmpty() )
685 uri += u
" table=%1%2"_s.arg(
quotedTablename(), mGeometryColumn.isEmpty() ? QString() : u
" (%1)"_s.arg( columnName ) );
687 else if ( !mSchema.isEmpty() )
689 uri += u
" schema='%1'"_s.arg( escape( mSchema ) );
692 if ( !mSql.isEmpty() )
694 uri += u
" sql="_s + mSql;
703 if (
string.isEmpty() )
704 return string.isNull() ? QByteArray() : QByteArray(
"" );
705 return string.toLatin1();
711 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
713 url.addQueryItem( it.key(), QUrl::toPercentEncoding( it.value() ) );
716 if ( !mUsername.isEmpty() )
717 url.addQueryItem( u
"username"_s, QUrl::toPercentEncoding( mUsername ) );
719 if ( !mPassword.isEmpty() )
720 url.addQueryItem( u
"password"_s, QUrl::toPercentEncoding( mPassword ) );
722 if ( !mAuthConfigId.isEmpty() )
723 url.addQueryItem( u
"authcfg"_s, QUrl::toPercentEncoding( mAuthConfigId ) );
725 mHttpHeaders.updateUrlQuery( url );
735 mAuthConfigId.clear();
738 url.setQuery( QString::fromLatin1(
uri ) );
739 const QUrlQuery query( url );
741 mHttpHeaders.setFromUrlQuery( query );
743 const auto constQueryItems = query.queryItems( QUrl::ComponentFormattingOption::FullyDecoded );
744 for (
const QPair<QString, QString> &item : constQueryItems )
748 if ( item.first ==
"username"_L1 )
749 mUsername = query.queryItemValue( u
"username"_s, QUrl::ComponentFormattingOption::FullyDecoded );
750 else if ( item.first ==
"password"_L1 )
751 mPassword = query.queryItemValue( u
"password"_s, QUrl::ComponentFormattingOption::FullyDecoded );
752 else if ( item.first ==
"authcfg"_L1 )
753 mAuthConfigId = query.queryItemValue( u
"authcfg"_s, QUrl::ComponentFormattingOption::FullyDecoded );
755 mParams.insert( item.first, item.second );
764 setEncodedUri( url.query( QUrl::EncodeUnicode ).toLatin1() );
769 if ( !mSchema.isEmpty() )
770 return u
"\"%1\".\"%2\""_s.arg( escape( mSchema,
'"' ), escape( mTable,
'"' ) );
772 return u
"\"%1\""_s.arg( escape( mTable,
'"' ) );
807 mAuthConfigId = authcfg;
839 else if (
sslMode ==
"disable"_L1 )
841 else if (
sslMode ==
"allow"_L1 )
843 else if (
sslMode ==
"require"_L1 )
845 else if (
sslMode ==
"verify-ca"_L1 )
847 else if (
sslMode ==
"verify-full"_L1 )
866 return u
"verify-ca"_s;
868 return u
"verify-full"_s;
876 if ( key ==
"username"_L1 )
878 else if ( key ==
"password"_L1 )
880 else if ( key ==
"authcfg"_L1 )
881 mAuthConfigId = value;
885 mParams.insert( key, value );
891 for (
const QString &val : value )
899 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
904 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
909 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
911 mAuthConfigId.clear();
915 return mParams.remove( key );
921 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
923 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
925 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
926 return mAuthConfigId;
928 return mParams.value( key );
934 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
935 return QStringList() << mUsername;
936 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
937 return QStringList() << mPassword;
938 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
939 return QStringList() << mAuthConfigId;
941 return mParams.values( key );
947 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
949 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
951 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
954 return mParams.contains( key );
959 QSet<QString> paramKeys;
960 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); it++ )
961 paramKeys.insert( it.key() );
963 if ( !mHost.isEmpty() )
964 paramKeys.insert(
"host"_L1 );
965 if ( !mPort.isEmpty() )
966 paramKeys.insert(
"port"_L1 );
967 if ( !mDriver.isEmpty() )
968 paramKeys.insert(
"driver"_L1 );
969 if ( !mService.isEmpty() )
970 paramKeys.insert(
"service"_L1 );
971 if ( !mDatabase.isEmpty() )
972 paramKeys.insert(
"dbname"_L1 );
973 if ( !mSchema.isEmpty() )
974 paramKeys.insert(
"schema"_L1 );
975 if ( !mTable.isEmpty() )
976 paramKeys.insert(
"table"_L1 );
978 if ( !mSql.isEmpty() )
979 paramKeys.insert(
"sql"_L1 );
980 if ( !mAuthConfigId.isEmpty() )
981 paramKeys.insert(
"authcfg"_L1 );
982 if ( !mUsername.isEmpty() )
983 paramKeys.insert(
"username"_L1 );
984 if ( !mPassword.isEmpty() )
985 paramKeys.insert(
"password"_L1 );
987 paramKeys.insert(
"sslmode"_L1 );
988 if ( !mKeyColumn.isEmpty() )
989 paramKeys.insert(
"key"_L1 );
990 if ( mUseEstimatedMetadata )
991 paramKeys.insert(
"estimatedmetadata"_L1 );
992 if ( mSelectAtIdDisabledSet )
993 paramKeys.insert(
"selectatid"_L1 );
995 paramKeys.insert(
"type"_L1 );
996 if ( !mSrid.isEmpty() )
997 paramKeys.insert(
"srid"_L1 );
1004 if ( mUseEstimatedMetadata != other.mUseEstimatedMetadata
1005 || mSelectAtIdDisabled != other.mSelectAtIdDisabled
1006 || mSelectAtIdDisabledSet != other.mSelectAtIdDisabledSet
1007 || mSSLmode != other.mSSLmode
1008 || mWkbType != other.mWkbType )
1013 if ( mHost != other.mHost
1014 || mPort != other.mPort
1015 || mDriver != other.mDriver
1016 || mService != other.mService
1017 || mDatabase != other.mDatabase
1018 || mSchema != other.mSchema
1019 || mTable != other.mTable
1020 || mGeometryColumn != other.mGeometryColumn
1021 || mSql != other.mSql
1022 || mAuthConfigId != other.mAuthConfigId
1023 || mUsername != other.mUsername
1024 || mPassword != other.mPassword
1025 || mKeyColumn != other.mKeyColumn
1026 || mSrid != other.mSrid
1027 || mParams != other.mParams
1028 || mHttpHeaders != other.mHttpHeaders )
1038 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)