QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsdatasourceuri.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdatasourceuri.h - Structure to contain the component parts
3  of a data source URI
4  -------------------
5  begin : Dec 5, 2004
6  copyright : (C) 2004 by Gary E.Sherman
7  email : sherman at mrcc.com
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "qgsdatasourceuri.h"
20 #include "qgsauthmanager.h"
21 #include "qgslogger.h"
22 #include "qgswkbtypes.h"
23 #include "qgsapplication.h"
24 
25 #include <QStringList>
26 #include <QRegExp>
27 #include <QUrl>
28 
30 {
31  // do nothing
32 }
33 
35 {
36  QString uri = u;
37  int i = 0;
38  while ( i < uri.length() )
39  {
40  skipBlanks( uri, i );
41 
42  if ( uri[i] == '=' )
43  {
44  QgsDebugMsg( QStringLiteral( "parameter name expected before =" ) );
45  i++;
46  continue;
47  }
48 
49  int start = i;
50 
51  while ( i < uri.length() && uri[i] != '=' && !uri[i].isSpace() )
52  i++;
53 
54  QString pname = uri.mid( start, i - start );
55 
56  skipBlanks( uri, i );
57 
58  if ( i == uri.length() || uri[i] != '=' )
59  {
60  QgsDebugMsg( QStringLiteral( "= expected after parameter name, skipping text '%1'" ).arg( pname ) );
61  continue;
62  }
63 
64  i++;
65 
66  if ( pname == QLatin1String( "sql" ) )
67  {
68  // rest of line is a sql where clause
69  skipBlanks( uri, i );
70  mSql = uri.mid( i );
71  break;
72  }
73  else
74  {
75  QString pval = getValue( uri, i );
76 
77  if ( pname == QLatin1String( "table" ) )
78  {
79  if ( uri[i] == '.' )
80  {
81  i++;
82 
83  mSchema = pval;
84  mTable = getValue( uri, i );
85  }
86  else
87  {
88  mSchema.clear();
89  mTable = pval;
90  }
91 
92  if ( uri[i] == '(' )
93  {
94  i++;
95 
96  int start = i;
97  while ( i < uri.length() && uri[i] != ')' )
98  {
99  if ( uri[i] == '\\' )
100  i++;
101  i++;
102  }
103 
104  if ( i == uri.length() )
105  {
106  QgsDebugMsg( QStringLiteral( "closing parenthesis missing" ) );
107  }
108 
109  mGeometryColumn = uri.mid( start, i - start );
110  mGeometryColumn.replace( QLatin1String( "\\)" ), QLatin1String( ")" ) );
111  mGeometryColumn.replace( QLatin1String( "\\\\" ), QLatin1String( "\\" ) );
112 
113  i++;
114  }
115  else
116  {
117  mGeometryColumn = QString();
118  }
119  }
120  else if ( pname == QLatin1String( "key" ) )
121  {
122  mKeyColumn = pval;
123  }
124  else if ( pname == QLatin1String( "estimatedmetadata" ) )
125  {
126  mUseEstimatedMetadata = pval == QLatin1String( "true" );
127  }
128  else if ( pname == QLatin1String( "srid" ) )
129  {
130  mSrid = pval;
131  }
132  else if ( pname == QLatin1String( "type" ) )
133  {
134  mWkbType = QgsWkbTypes::parseType( pval );
135  }
136  else if ( pname == QLatin1String( "selectatid" ) )
137  {
138  mSelectAtIdDisabled = pval == QLatin1String( "false" );
139  }
140  else if ( pname == QLatin1String( "service" ) )
141  {
142  mService = pval;
143  }
144  else if ( pname == QLatin1String( "authcfg" ) )
145  {
146  mAuthConfigId = pval;
147  }
148  else if ( pname == QLatin1String( "user" ) || pname == QLatin1String( "username" ) ) // Also accepts new WFS provider naming
149  {
150  mUsername = pval;
151  }
152  else if ( pname == QLatin1String( "password" ) )
153  {
154  mPassword = pval;
155  }
156  else if ( pname == QLatin1String( "connect_timeout" ) )
157  {
158  QgsDebugMsg( QStringLiteral( "connection timeout ignored" ) );
159  }
160  else if ( pname == QLatin1String( "dbname" ) )
161  {
162  mDatabase = pval;
163  }
164  else if ( pname == QLatin1String( "host" ) )
165  {
166  mHost = pval;
167  }
168  else if ( pname == QLatin1String( "hostaddr" ) )
169  {
170  QgsDebugMsg( QStringLiteral( "database host ip address ignored" ) );
171  }
172  else if ( pname == QLatin1String( "port" ) )
173  {
174  mPort = pval;
175  }
176  else if ( pname == QLatin1String( "driver" ) )
177  {
178  mDriver = pval;
179  }
180  else if ( pname == QLatin1String( "tty" ) )
181  {
182  QgsDebugMsg( QStringLiteral( "backend debug tty ignored" ) );
183  }
184  else if ( pname == QLatin1String( "options" ) )
185  {
186  QgsDebugMsg( QStringLiteral( "backend debug options ignored" ) );
187  }
188  else if ( pname == QLatin1String( "sslmode" ) )
189  {
190  mSSLmode = decodeSslMode( pval );
191  }
192  else if ( pname == QLatin1String( "requiressl" ) )
193  {
194  if ( pval == QLatin1String( "0" ) )
195  mSSLmode = SslDisable;
196  else
197  mSSLmode = SslPrefer;
198  }
199  else if ( pname == QLatin1String( "krbsrvname" ) )
200  {
201  QgsDebugMsg( QStringLiteral( "kerberos server name ignored" ) );
202  }
203  else if ( pname == QLatin1String( "gsslib" ) )
204  {
205  QgsDebugMsg( QStringLiteral( "gsslib ignored" ) );
206  }
207  else
208  {
209  QgsDebugMsgLevel( "parameter \"" + pname + "\":\"" + pval + "\" added", 4 );
210  setParam( pname, pval );
211  }
212  }
213  }
214 }
215 
216 QString QgsDataSourceUri::removePassword( const QString &aUri )
217 {
218  QRegExp regexp;
219  regexp.setMinimal( true );
220  QString safeName( aUri );
221  if ( aUri.contains( QLatin1String( " password=" ) ) )
222  {
223  regexp.setPattern( QStringLiteral( " password=.* " ) );
224  safeName.replace( regexp, QStringLiteral( " " ) );
225  }
226  else if ( aUri.contains( QLatin1String( ",password=" ) ) )
227  {
228  regexp.setPattern( QStringLiteral( ",password=.*," ) );
229  safeName.replace( regexp, QStringLiteral( "," ) );
230  }
231  else if ( aUri.contains( QLatin1String( "IDB:" ) ) )
232  {
233  regexp.setPattern( QStringLiteral( " pass=.* " ) );
234  safeName.replace( regexp, QStringLiteral( " " ) );
235  }
236  else if ( ( aUri.contains( QLatin1String( "OCI:" ) ) )
237  || ( aUri.contains( QLatin1String( "ODBC:" ) ) ) )
238  {
239  regexp.setPattern( QStringLiteral( "/.*@" ) );
240  safeName.replace( regexp, QStringLiteral( "/@" ) );
241  }
242  else if ( aUri.contains( QLatin1String( "SDE:" ) ) )
243  {
244  QStringList strlist = aUri.split( ',' );
245  safeName = strlist[0] + ',' + strlist[1] + ',' + strlist[2] + ',' + strlist[3];
246  }
247  return safeName;
248 }
249 
251 {
252  return mAuthConfigId;
253 }
254 
256 {
257  return mUsername;
258 }
259 
261 {
262  mUsername = username;
263 }
264 
266 {
267  return mService;
268 }
269 
270 QString QgsDataSourceUri::host() const
271 {
272  return mHost;
273 }
274 
276 {
277  return mDatabase;
278 }
279 
281 {
282  return mPassword;
283 }
284 
286 {
287  mPassword = password;
288 }
289 
290 QString QgsDataSourceUri::port() const
291 {
292  return mPort;
293 }
294 
296 {
297  return mDriver;
298 }
299 
301 {
302  return mSSLmode;
303 }
304 
306 {
307  return mSchema;
308 }
309 
310 QString QgsDataSourceUri::table() const
311 {
312  return mTable;
313 }
314 
315 QString QgsDataSourceUri::sql() const
316 {
317  return mSql;
318 }
319 
321 {
322  return mGeometryColumn;
323 }
324 
326 {
327  return mKeyColumn;
328 }
329 
330 
331 void QgsDataSourceUri::setDriver( const QString &driver )
332 {
333  mDriver = driver;
334 }
335 
336 
337 void QgsDataSourceUri::setKeyColumn( const QString &column )
338 {
339  mKeyColumn = column;
340 }
341 
342 
344 {
345  mUseEstimatedMetadata = flag;
346 }
347 
349 {
350  return mUseEstimatedMetadata;
351 }
352 
354 {
355  mSelectAtIdDisabled = flag;
356 }
357 
359 {
360  return mSelectAtIdDisabled;
361 }
362 
363 void QgsDataSourceUri::setSql( const QString &sql )
364 {
365  mSql = sql;
366 }
367 
369 {
370  mSchema.clear();
371 }
372 
373 void QgsDataSourceUri::setSchema( const QString &schema )
374 {
375  mSchema = schema;
376 }
377 
378 QString QgsDataSourceUri::escape( const QString &val, QChar delim = '\'' ) const
379 {
380  QString escaped = val;
381 
382  escaped.replace( '\\', QLatin1String( "\\\\" ) );
383  escaped.replace( delim, QStringLiteral( "\\%1" ).arg( delim ) );
384 
385  return escaped;
386 }
387 
389 {
390  mGeometryColumn = geometryColumn;
391 }
392 
393 void QgsDataSourceUri::setTable( const QString &table )
394 {
395  mTable = table;
396 }
397 
398 void QgsDataSourceUri::skipBlanks( const QString &uri, int &i )
399 {
400  // skip space before value
401  while ( i < uri.length() && uri[i].isSpace() )
402  i++;
403 }
404 
405 QString QgsDataSourceUri::getValue( const QString &uri, int &i )
406 {
407  skipBlanks( uri, i );
408 
409  // Get the parameter value
410  QString pval;
411  if ( i < uri.length() && ( uri[i] == '\'' || uri[i] == '"' ) )
412  {
413  QChar delim = uri[i];
414 
415  i++;
416 
417  // value is quoted
418  for ( ;; )
419  {
420  if ( i == uri.length() )
421  {
422  QgsDebugMsg( QStringLiteral( "unterminated quoted string in connection info string" ) );
423  return pval;
424  }
425 
426  if ( uri[i] == '\\' )
427  {
428  i++;
429  if ( i == uri.length() )
430  continue;
431  if ( uri[i] != delim && uri[i] != '\\' )
432  i--;
433  }
434  else if ( uri[i] == delim )
435  {
436  i++;
437  break;
438  }
439 
440  pval += uri[i++];
441  }
442  }
443  else
444  {
445  // value is not quoted
446  while ( i < uri.length() )
447  {
448  if ( uri[i].isSpace() )
449  {
450  // end of value
451  break;
452  }
453 
454  if ( uri[i] == '\\' )
455  {
456  i++;
457  if ( i == uri.length() )
458  break;
459  if ( uri[i] != '\\' && uri[i] != '\'' )
460  i--;
461  }
462 
463  pval += uri[i++];
464  }
465  }
466 
467  skipBlanks( uri, i );
468 
469  return pval;
470 }
471 
472 QString QgsDataSourceUri::connectionInfo( bool expandAuthConfig ) const
473 {
474  QStringList connectionItems;
475 
476  if ( !mDatabase.isEmpty() )
477  {
478  connectionItems << "dbname='" + escape( mDatabase ) + '\'';
479  }
480 
481  if ( !mService.isEmpty() )
482  {
483  connectionItems << "service='" + escape( mService ) + '\'';
484  }
485  else if ( !mHost.isEmpty() )
486  {
487  connectionItems << "host=" + mHost;
488  }
489 
490  if ( mService.isEmpty() )
491  {
492  if ( !mPort.isEmpty() )
493  connectionItems << "port=" + mPort;
494  }
495 
496  if ( !mDriver.isEmpty() )
497  {
498  connectionItems << "driver='" + escape( mDriver ) + '\'';
499  }
500 
501  if ( !mUsername.isEmpty() )
502  {
503  connectionItems << "user='" + escape( mUsername ) + '\'';
504 
505  if ( !mPassword.isEmpty() )
506  {
507  connectionItems << "password='" + escape( mPassword ) + '\'';
508  }
509  }
510 
511  if ( mSSLmode != SslPrefer ) // no need to output the default
512  {
513  connectionItems << QStringLiteral( "sslmode=" ) + encodeSslMode( mSSLmode );
514  }
515 
516  if ( !mAuthConfigId.isEmpty() )
517  {
518  if ( expandAuthConfig )
519  {
520  if ( !QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, mAuthConfigId ) )
521  {
522  QgsDebugMsg( QStringLiteral( "Data source URI FAILED to update via loading configuration ID '%1'" ).arg( mAuthConfigId ) );
523  }
524  }
525  else
526  {
527  connectionItems << "authcfg=" + mAuthConfigId;
528  }
529  }
530 
531  return connectionItems.join( QStringLiteral( " " ) );
532 }
533 
534 QString QgsDataSourceUri::uri( bool expandAuthConfig ) const
535 {
536  QString uri = connectionInfo( expandAuthConfig );
537 
538  if ( !mKeyColumn.isEmpty() )
539  {
540  uri += QStringLiteral( " key='%1'" ).arg( escape( mKeyColumn ) );
541  }
542 
543  if ( mUseEstimatedMetadata )
544  {
545  uri += QStringLiteral( " estimatedmetadata=true" );
546  }
547 
548  if ( !mSrid.isEmpty() )
549  {
550  uri += QStringLiteral( " srid=%1" ).arg( mSrid );
551  }
552 
553  if ( mWkbType != QgsWkbTypes::Unknown && mWkbType != QgsWkbTypes::NoGeometry )
554  {
555  uri += QLatin1String( " type=" );
556  uri += QgsWkbTypes::displayString( mWkbType );
557  }
558 
559  if ( mSelectAtIdDisabled )
560  {
561  uri += QStringLiteral( " selectatid=false" );
562  }
563 
564  for ( QMap<QString, QString>::const_iterator it = mParams.begin(); it != mParams.end(); ++it )
565  {
566  if ( it.key().contains( '=' ) || it.key().contains( ' ' ) )
567  {
568  QgsDebugMsg( QStringLiteral( "invalid uri parameter %1 skipped" ).arg( it.key() ) );
569  continue;
570  }
571 
572  uri += ' ' + it.key() + "='" + escape( it.value() ) + '\'';
573  }
574 
575  QString columnName( mGeometryColumn );
576  columnName.replace( '\\', QLatin1String( "\\\\" ) );
577  columnName.replace( ')', QLatin1String( "\\)" ) );
578 
579  uri += QStringLiteral( " table=%1%2 sql=%3" )
580  .arg( quotedTablename(),
581  mGeometryColumn.isNull() ? QString() : QStringLiteral( " (%1)" ).arg( columnName ),
582  mSql );
583 
584  return uri;
585 }
586 
588 {
589  QUrl url;
590  for ( auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
591  {
592  url.addQueryItem( it.key(), it.value() );
593  }
594  return url.encodedQuery();
595 }
596 
597 void QgsDataSourceUri::setEncodedUri( const QByteArray &uri )
598 {
599  mParams.clear();
600  QUrl url;
601  url.setEncodedQuery( uri );
602 
603  const auto constQueryItems = url.queryItems();
604  for ( const QPair<QString, QString> &item : constQueryItems )
605  {
606  mParams.insertMulti( item.first, item.second );
607  }
608 }
609 
610 void QgsDataSourceUri::setEncodedUri( const QString &uri )
611 {
612  setEncodedUri( uri.toLatin1() );
613 }
614 
616 {
617  if ( !mSchema.isEmpty() )
618  return QStringLiteral( "\"%1\".\"%2\"" )
619  .arg( escape( mSchema, '"' ),
620  escape( mTable, '"' ) );
621  else
622  return QStringLiteral( "\"%1\"" )
623  .arg( escape( mTable, '"' ) );
624 }
625 
627  const QString &port,
628  const QString &database,
629  const QString &username,
630  const QString &password,
631  SslMode sslmode,
632  const QString &authConfigId )
633 {
634  mHost = host;
635  mDatabase = database;
636  mPort = port;
637  mUsername = username;
638  mPassword = password;
639  mSSLmode = sslmode;
640  mAuthConfigId = authConfigId;
641 }
642 
644  const QString &database,
645  const QString &username,
646  const QString &password,
647  SslMode sslmode,
648  const QString &authConfigId )
649 {
650  mService = service;
651  mDatabase = database;
652  mUsername = username;
653  mPassword = password;
654  mSSLmode = sslmode;
655  mAuthConfigId = authConfigId;
656 }
657 
659  const QString &table,
660  const QString &geometryColumn,
661  const QString &sql,
662  const QString &keyColumn )
663 {
664  mSchema = schema;
665  mTable = table;
666  mGeometryColumn = geometryColumn;
667  mSql = sql;
668  mKeyColumn = keyColumn;
669 }
670 
671 void QgsDataSourceUri::setAuthConfigId( const QString &authcfg )
672 {
673  mAuthConfigId = authcfg;
674 }
675 
677 {
678  mDatabase = database;
679 }
680 
682 {
683  return mWkbType;
684 }
685 
687 {
688  mWkbType = wkbType;
689 }
690 
691 QString QgsDataSourceUri::srid() const
692 {
693  return mSrid;
694 }
695 
696 void QgsDataSourceUri::setSrid( const QString &srid )
697 {
698  mSrid = srid;
699 }
700 
702 {
703  if ( sslMode == QLatin1String( "prefer" ) )
704  return SslPrefer;
705  else if ( sslMode == QLatin1String( "disable" ) )
706  return SslDisable;
707  else if ( sslMode == QLatin1String( "allow" ) )
708  return SslAllow;
709  else if ( sslMode == QLatin1String( "require" ) )
710  return SslRequire;
711  else if ( sslMode == QLatin1String( "verify-ca" ) )
712  return SslVerifyCa;
713  else if ( sslMode == QLatin1String( "verify-full" ) )
714  return SslVerifyFull;
715  else
716  return SslPrefer; // default
717 }
718 
720 {
721  switch ( sslMode )
722  {
723  case SslPrefer: return QStringLiteral( "prefer" );
724  case SslDisable: return QStringLiteral( "disable" );
725  case SslAllow: return QStringLiteral( "allow" );
726  case SslRequire: return QStringLiteral( "require" );
727  case SslVerifyCa: return QStringLiteral( "verify-ca" );
728  case SslVerifyFull: return QStringLiteral( "verify-full" );
729  }
730  return QString();
731 }
732 
733 void QgsDataSourceUri::setParam( const QString &key, const QString &value )
734 {
735  // may be multiple
736  mParams.insertMulti( key, value );
737 }
738 
739 void QgsDataSourceUri::setParam( const QString &key, const QStringList &value )
740 {
741  const auto constValue = value;
742  for ( const QString &val : constValue )
743  {
744  mParams.insertMulti( key, val );
745  }
746 }
747 
748 int QgsDataSourceUri::removeParam( const QString &key )
749 {
750  return mParams.remove( key );
751 }
752 
753 QString QgsDataSourceUri::param( const QString &key ) const
754 {
755  return mParams.value( key );
756 }
757 
758 QStringList QgsDataSourceUri::params( const QString &key ) const
759 {
760  return mParams.values( key );
761 }
762 
763 bool QgsDataSourceUri::hasParam( const QString &key ) const
764 {
765  return mParams.contains( key );
766 }
QString param(const QString &key) const
Returns a generic parameter value corresponding to the specified key.
QgsWkbTypes::Type wkbType() const
Returns the WKB type associated with the URI.
QString table() const
Returns the table name stored in the URI.
bool useEstimatedMetadata() const
Returns true if estimated metadata should be used for the connection.
void setUsername(const QString &username)
Sets the username for the URI.
bool hasParam(const QString &key) const
Returns true if a parameter with the specified key exists.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
void clearSchema()
Clears the schema stored in the URI.
static SslMode decodeSslMode(const QString &sslMode)
Decodes SSL mode string into enum value.
QString authConfigId() const
Returns any associated authentication configuration ID stored in the URI.
SslMode sslMode() const
Returns the SSL mode associated with the URI.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
QString keyColumn() const
Returns the name of the (primary) key column for the referenced table.
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.
QString connectionInfo(bool expandAuthConfig=true) const
Returns the connection part of the URI.
QString username() const
Returns the username stored in the URI.
SslMode
Available SSQL connection modes.
void setGeometryColumn(const QString &geometryColumn)
Sets geometry column name to geometryColumn.
QString host() const
Returns the host name stored in the URI.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
QStringList params(const QString &key) const
Returns multiple generic parameter values corresponding to the specified key.
void setDriver(const QString &driver)
Sets the driver name stored in the URI.
int removeParam(const QString &key)
Removes a generic parameter by key.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QString geometryColumn() const
Returns the name of the geometry column stored in the URI, if set.
void setKeyColumn(const QString &column)
Sets the name of the (primary) key column.
bool selectAtIdDisabled() const
Returns whether the selection by feature ID is disabled.
void setTable(const QString &table)
Sets table to table.
bool updateDataSourceUriItems(QStringList &connectionItems, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QgsDataSourceUri with an authentication config.
void setEncodedUri(const QByteArray &uri)
Sets the complete encoded uri.
QString quotedTablename() const
Returns the URI&#39;s table name, escaped and quoted.
static QString encodeSslMode(SslMode sslMode)
Encodes SSL mode enum value into a string.
void setParam(const QString &key, const QString &value)
Sets a generic parameter value on the URI.
QString port() const
Returns the port stored in the URI.
void setAuthConfigId(const QString &authcfg)
Sets the authentication configuration ID for the URI.
void setSrid(const QString &srid)
Sets the spatial reference ID associated with the URI.
void setWkbType(QgsWkbTypes::Type type)
Sets the WKB type associated with the URI.
QString uri(bool expandAuthConfig=true) const
Returns the complete URI as a string.
static QgsAuthManager * authManager()
Returns the application&#39;s authentication manager instance.
void disableSelectAtId(bool flag)
Set to true to disable selection by feature ID.
QString driver() const
Returns the driver 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.
void setSql(const QString &sql)
Sets the SQL query for the URI.
void setPassword(const QString &password)
Sets the password for the URI.
QByteArray encodedUri() const
Returns the complete encoded URI as a byte array.
QString sql() const
Returns the SQL query stored in the URI, if set.
QString service() const
Returns the service name associated with the URI.
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
QString password() const
Returns the password stored in the URI.
void setSchema(const QString &schema)
Sets the scheme for the URI.
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 database() const
Returns the database name stored in the URI.
void setDatabase(const QString &database)
Sets the URI database name.
QString srid() const
Returns the spatial reference ID associated with the URI.
static QString removePassword(const QString &aUri)
Removes the password element from a URI.