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 ) )
291 || ( aUri.contains(
"ODBC:"_L1 ) ) )
293 regexp.setPattern( u
"/.*@"_s );
297 safeName.replace( regexp, u
"/%1@"_s.arg(
HIDING_TOKEN ) );
301 safeName.replace( regexp, u
"/@"_s );
304 else if ( aUri.contains(
"postgresql:"_L1 ) )
307 regexp.setPattern( u
"/.*@"_s );
308 const QString matched = regexp.match( aUri ).captured();
310 QString anonymised = matched;
311 const QStringList items = matched.split( u
":"_s );
312 if ( items.size() > 1 )
314 anonymised = matched.split( u
":"_s )[0];
319 anonymised.append( u
"@"_s );
322 safeName.replace( regexp, anonymised );
324 else if ( aUri.contains(
"SDE:"_L1 ) )
326 QStringList strlist = aUri.split(
',' );
327 safeName = strlist[0] +
',' + strlist[1] +
',' + strlist[2] +
',' + strlist[3];
334 return mAuthConfigId;
419 return mGeometryColumn;
442 mUseEstimatedMetadata = flag;
447 return mUseEstimatedMetadata;
452 mSelectAtIdDisabledSet =
true;
453 mSelectAtIdDisabled = flag;
458 return mSelectAtIdDisabled;
481QString QgsDataSourceUri::escape(
const QString &val, QChar delim =
'\'' )
const
483 QString escaped = val;
485 escaped.replace(
'\\',
"\\\\"_L1 );
486 escaped.replace( delim, u
"\\%1"_s.arg( delim ) );
501void QgsDataSourceUri::skipBlanks(
const QString &uri,
int &i )
504 while ( i <
uri.length() &&
uri[i].isSpace() )
508QString QgsDataSourceUri::getValue(
const QString &uri,
int &i )
510 skipBlanks(
uri, i );
514 if ( i <
uri.length() && (
uri[i] ==
'\'' ||
uri[i] ==
'"' ) )
516 const QChar delim =
uri[i];
523 if ( i ==
uri.length() )
525 QgsDebugError( u
"unterminated quoted string in connection info string"_s );
529 if (
uri[i] ==
'\\' )
532 if ( i ==
uri.length() )
534 if (
uri[i] != delim &&
uri[i] !=
'\\' )
537 else if (
uri[i] == delim )
549 while ( i <
uri.length() )
551 if (
uri[i].isSpace() )
557 if (
uri[i] ==
'\\' )
560 if ( i ==
uri.length() )
562 if (
uri[i] !=
'\\' &&
uri[i] !=
'\'' )
570 skipBlanks(
uri, i );
577 QStringList connectionItems;
579 if ( !mDatabase.isEmpty() )
581 connectionItems <<
"dbname='" + escape( mDatabase ) +
'\'';
584 if ( !mService.isEmpty() )
586 connectionItems <<
"service='" + escape( mService ) +
'\'';
588 else if ( !mHost.isEmpty() )
590 connectionItems <<
"host=" + mHost;
593 if ( mService.isEmpty() )
595 if ( !mPort.isEmpty() )
596 connectionItems <<
"port=" + mPort;
599 if ( !mDriver.isEmpty() )
601 connectionItems <<
"driver='" + escape( mDriver ) +
'\'';
604 if ( !mUsername.isEmpty() )
606 connectionItems <<
"user='" + escape( mUsername ) +
'\'';
608 if ( !mPassword.isEmpty() )
610 connectionItems <<
"password='" + escape( mPassword ) +
'\'';
616 connectionItems << u
"sslmode="_s +
encodeSslMode( mSSLmode );
619 if ( !mAuthConfigId.isEmpty() )
621 if ( expandAuthConfig )
625 QgsDebugError( u
"Data source URI FAILED to update via loading configuration ID '%1'"_s.arg( mAuthConfigId ) );
630 connectionItems <<
"authcfg=" + mAuthConfigId;
634 return connectionItems.join(
' '_L1 );
641 if ( !mKeyColumn.isEmpty() )
643 uri += u
" key='%1'"_s.arg( escape( mKeyColumn ) );
646 if ( mUseEstimatedMetadata )
648 uri +=
" estimatedmetadata=true"_L1;
651 if ( !mSrid.isEmpty() )
653 uri += u
" srid=%1"_s.arg( mSrid );
662 if ( mSelectAtIdDisabled )
664 uri +=
" selectatid=false"_L1;
667 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
669 if ( it.key().contains(
'=' ) || it.key().contains(
' ' ) )
671 QgsDebugError( u
"invalid uri parameter %1 skipped"_s.arg( it.key() ) );
675 uri +=
' ' + it.key() +
"='" + escape( it.value() ) +
'\'';
678 uri += mHttpHeaders.toSpacedString();
680 QString columnName( mGeometryColumn );
681 columnName.replace(
'\\',
"\\\\"_L1 );
682 columnName.replace(
')',
"\\)"_L1 );
684 if ( !mTable.isEmpty() )
686 uri += u
" table=%1%2"_s
688 mGeometryColumn.isEmpty() ? QString() : u
" (%1)"_s.arg( columnName ) );
690 else if ( !mSchema.isEmpty() )
692 uri += u
" schema='%1'"_s.arg( escape( mSchema ) );
695 if ( !mSql.isEmpty() )
697 uri += u
" sql="_s + mSql;
706 if (
string.isEmpty() )
707 return string.isNull() ? QByteArray() : QByteArray(
"" );
708 return string.toLatin1();
714 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
716 url.addQueryItem( it.key(), QUrl::toPercentEncoding( it.value() ) );
719 if ( !mUsername.isEmpty() )
720 url.addQueryItem( u
"username"_s, QUrl::toPercentEncoding( mUsername ) );
722 if ( !mPassword.isEmpty() )
723 url.addQueryItem( u
"password"_s, QUrl::toPercentEncoding( mPassword ) );
725 if ( !mAuthConfigId.isEmpty() )
726 url.addQueryItem( u
"authcfg"_s, QUrl::toPercentEncoding( mAuthConfigId ) );
728 mHttpHeaders.updateUrlQuery( url );
738 mAuthConfigId.clear();
741 url.setQuery( QString::fromLatin1(
uri ) );
742 const QUrlQuery query( url );
744 mHttpHeaders.setFromUrlQuery( query );
746 const auto constQueryItems = query.queryItems( QUrl::ComponentFormattingOption::FullyDecoded );
747 for (
const QPair<QString, QString> &item : constQueryItems )
751 if ( item.first ==
"username"_L1 )
752 mUsername = query.queryItemValue( u
"username"_s, QUrl::ComponentFormattingOption::FullyDecoded );
753 else if ( item.first ==
"password"_L1 )
754 mPassword = query.queryItemValue( u
"password"_s, QUrl::ComponentFormattingOption::FullyDecoded );
755 else if ( item.first ==
"authcfg"_L1 )
756 mAuthConfigId = query.queryItemValue( u
"authcfg"_s, QUrl::ComponentFormattingOption::FullyDecoded );
758 mParams.insert( item.first, item.second );
767 setEncodedUri( url.query( QUrl::EncodeUnicode ).toLatin1() );
772 if ( !mSchema.isEmpty() )
773 return u
"\"%1\".\"%2\""_s
774 .arg( escape( mSchema,
'"' ),
775 escape( mTable,
'"' ) );
778 .arg( escape( mTable,
'"' ) );
814 const QString &
table,
828 mAuthConfigId = authcfg;
860 else if (
sslMode ==
"disable"_L1 )
862 else if (
sslMode ==
"allow"_L1 )
864 else if (
sslMode ==
"require"_L1 )
866 else if (
sslMode ==
"verify-ca"_L1 )
868 else if (
sslMode ==
"verify-full"_L1 )
891 if ( key ==
"username"_L1 )
893 else if ( key ==
"password"_L1 )
895 else if ( key ==
"authcfg"_L1 )
896 mAuthConfigId = value;
900 mParams.insert( key, value );
906 for (
const QString &val : value )
914 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
919 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
924 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
926 mAuthConfigId.clear();
930 return mParams.remove( key );
936 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
938 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
940 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
941 return mAuthConfigId;
943 return mParams.value( key );
949 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
950 return QStringList() << mUsername;
951 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
952 return QStringList() << mPassword;
953 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
954 return QStringList() << mAuthConfigId;
956 return mParams.values( key );
962 if ( key ==
"username"_L1 && !mUsername.isEmpty() )
964 else if ( key ==
"password"_L1 && !mPassword.isEmpty() )
966 else if ( key ==
"authcfg"_L1 && !mAuthConfigId.isEmpty() )
969 return mParams.contains( key );
974 QSet<QString> paramKeys;
975 for (
auto it = mParams.constBegin(); it != mParams.constEnd(); it++ )
976 paramKeys.insert( it.key() );
978 if ( !mHost.isEmpty() )
979 paramKeys.insert(
"host"_L1 );
980 if ( !mPort.isEmpty() )
981 paramKeys.insert(
"port"_L1 );
982 if ( !mDriver.isEmpty() )
983 paramKeys.insert(
"driver"_L1 );
984 if ( !mService.isEmpty() )
985 paramKeys.insert(
"service"_L1 );
986 if ( !mDatabase.isEmpty() )
987 paramKeys.insert(
"dbname"_L1 );
988 if ( !mSchema.isEmpty() )
989 paramKeys.insert(
"schema"_L1 );
990 if ( !mTable.isEmpty() )
991 paramKeys.insert(
"table"_L1 );
993 if ( !mSql.isEmpty() )
994 paramKeys.insert(
"sql"_L1 );
995 if ( !mAuthConfigId.isEmpty() )
996 paramKeys.insert(
"authcfg"_L1 );
997 if ( !mUsername.isEmpty() )
998 paramKeys.insert(
"username"_L1 );
999 if ( !mPassword.isEmpty() )
1000 paramKeys.insert(
"password"_L1 );
1002 paramKeys.insert(
"sslmode"_L1 );
1003 if ( !mKeyColumn.isEmpty() )
1004 paramKeys.insert(
"key"_L1 );
1005 if ( mUseEstimatedMetadata )
1006 paramKeys.insert(
"estimatedmetadata"_L1 );
1007 if ( mSelectAtIdDisabledSet )
1008 paramKeys.insert(
"selectatid"_L1 );
1010 paramKeys.insert(
"type"_L1 );
1011 if ( !mSrid.isEmpty() )
1012 paramKeys.insert(
"srid"_L1 );
1019 if ( mUseEstimatedMetadata != other.mUseEstimatedMetadata ||
1020 mSelectAtIdDisabled != other.mSelectAtIdDisabled ||
1021 mSelectAtIdDisabledSet != other.mSelectAtIdDisabledSet ||
1022 mSSLmode != other.mSSLmode ||
1023 mWkbType != other.mWkbType )
1028 if ( mHost != other.mHost ||
1029 mPort != other.mPort ||
1030 mDriver != other.mDriver ||
1031 mService != other.mService ||
1032 mDatabase != other.mDatabase ||
1033 mSchema != other.mSchema ||
1034 mTable != other.mTable ||
1035 mGeometryColumn != other.mGeometryColumn ||
1036 mSql != other.mSql ||
1037 mAuthConfigId != other.mAuthConfigId ||
1038 mUsername != other.mUsername ||
1039 mPassword != other.mPassword ||
1040 mKeyColumn != other.mKeyColumn ||
1041 mSrid != other.mSrid ||
1042 mParams != other.mParams ||
1043 mHttpHeaders != other.mHttpHeaders )
1053 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)