QGIS API Documentation  2.99.0-Master (19b062c)
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  int i = 0;
37  while ( i < uri.length() )
38  {
39  skipBlanks( uri, i );
40 
41  if ( uri[i] == '=' )
42  {
43  QgsDebugMsg( "parameter name expected before =" );
44  i++;
45  continue;
46  }
47 
48  int start = i;
49 
50  while ( i < uri.length() && uri[i] != '=' && !uri[i].isSpace() )
51  i++;
52 
53  QString pname = uri.mid( start, i - start );
54 
55  skipBlanks( uri, i );
56 
57  if ( i == uri.length() || uri[i] != '=' )
58  {
59  QgsDebugMsg( QString( "= expected after parameter name, skipping text '%1'" ).arg( pname ) );
60  continue;
61  }
62 
63  i++;
64 
65  if ( pname == QLatin1String( "sql" ) )
66  {
67  // rest of line is a sql where clause
68  skipBlanks( uri, i );
69  mSql = uri.mid( i );
70  break;
71  }
72  else
73  {
74  QString pval = getValue( uri, i );
75 
76  if ( pname == QLatin1String( "table" ) )
77  {
78  if ( uri[i] == '.' )
79  {
80  i++;
81 
82  mSchema = pval;
83  mTable = getValue( uri, i );
84  }
85  else
86  {
87  mSchema.clear();
88  mTable = pval;
89  }
90 
91  if ( uri[i] == '(' )
92  {
93  i++;
94 
95  int start = i;
96  while ( i < uri.length() && uri[i] != ')' )
97  {
98  if ( uri[i] == '\\' )
99  i++;
100  i++;
101  }
102 
103  if ( i == uri.length() )
104  {
105  QgsDebugMsg( "closing parenthesis missing" );
106  }
107 
108  mGeometryColumn = uri.mid( start, i - start );
109  mGeometryColumn.replace( QLatin1String( "\\)" ), QLatin1String( ")" ) );
110  mGeometryColumn.replace( QLatin1String( "\\\\" ), QLatin1String( "\\" ) );
111 
112  i++;
113  }
114  else
115  {
116  mGeometryColumn = QString();
117  }
118  }
119  else if ( pname == QLatin1String( "key" ) )
120  {
121  mKeyColumn = pval;
122  }
123  else if ( pname == QLatin1String( "estimatedmetadata" ) )
124  {
125  mUseEstimatedMetadata = pval == QLatin1String( "true" );
126  }
127  else if ( pname == QLatin1String( "srid" ) )
128  {
129  mSrid = pval;
130  }
131  else if ( pname == QLatin1String( "type" ) )
132  {
133  mWkbType = QgsWkbTypes::parseType( pval );
134  }
135  else if ( pname == QLatin1String( "selectatid" ) )
136  {
137  mSelectAtIdDisabled = pval == QLatin1String( "false" );
138  }
139  else if ( pname == QLatin1String( "service" ) )
140  {
141  mService = pval;
142  }
143  else if ( pname == QLatin1String( "authcfg" ) )
144  {
145  mAuthConfigId = pval;
146  }
147  else if ( pname == QLatin1String( "user" ) || pname == QLatin1String( "username" ) ) // Also accepts new WFS provider naming
148  {
149  mUsername = pval;
150  }
151  else if ( pname == QLatin1String( "password" ) )
152  {
153  mPassword = pval;
154  }
155  else if ( pname == QLatin1String( "connect_timeout" ) )
156  {
157  QgsDebugMsg( "connection timeout ignored" );
158  }
159  else if ( pname == QLatin1String( "dbname" ) )
160  {
161  mDatabase = pval;
162  }
163  else if ( pname == QLatin1String( "host" ) )
164  {
165  mHost = pval;
166  }
167  else if ( pname == QLatin1String( "hostaddr" ) )
168  {
169  QgsDebugMsg( "database host ip address ignored" );
170  }
171  else if ( pname == QLatin1String( "port" ) )
172  {
173  mPort = pval;
174  }
175  else if ( pname == QLatin1String( "driver" ) )
176  {
177  mDriver = pval;
178  }
179  else if ( pname == QLatin1String( "tty" ) )
180  {
181  QgsDebugMsg( "backend debug tty ignored" );
182  }
183  else if ( pname == QLatin1String( "options" ) )
184  {
185  QgsDebugMsg( "backend debug options ignored" );
186  }
187  else if ( pname == QLatin1String( "sslmode" ) )
188  {
189  if ( pval == QLatin1String( "disable" ) )
190  mSSLmode = SslDisable;
191  else if ( pval == QLatin1String( "allow" ) )
192  mSSLmode = SslAllow;
193  else if ( pval == QLatin1String( "prefer" ) )
194  mSSLmode = SslPrefer;
195  else if ( pval == QLatin1String( "require" ) )
196  mSSLmode = SslRequire;
197  else if ( pval == QLatin1String( "verify-ca" ) )
198  mSSLmode = SslVerifyCa;
199  else if ( pval == QLatin1String( "verify-full" ) )
200  mSSLmode = SslVerifyFull;
201  }
202  else if ( pname == QLatin1String( "requiressl" ) )
203  {
204  if ( pval == QLatin1String( "0" ) )
205  mSSLmode = SslDisable;
206  else
207  mSSLmode = SslPrefer;
208  }
209  else if ( pname == QLatin1String( "krbsrvname" ) )
210  {
211  QgsDebugMsg( "kerberos server name ignored" );
212  }
213  else if ( pname == QLatin1String( "gsslib" ) )
214  {
215  QgsDebugMsg( "gsslib ignored" );
216  }
217  else
218  {
219  QgsDebugMsgLevel( "parameter \"" + pname + "\":\"" + pval + "\" added", 4 );
220  setParam( pname, pval );
221  }
222  }
223  }
224 }
225 
226 QString QgsDataSourceUri::removePassword( const QString &aUri )
227 {
228  QRegExp regexp;
229  regexp.setMinimal( true );
230  QString safeName( aUri );
231  if ( aUri.contains( QLatin1String( " password=" ) ) )
232  {
233  regexp.setPattern( QStringLiteral( " password=.* " ) );
234  safeName.replace( regexp, QStringLiteral( " " ) );
235  }
236  else if ( aUri.contains( QLatin1String( ",password=" ) ) )
237  {
238  regexp.setPattern( QStringLiteral( ",password=.*," ) );
239  safeName.replace( regexp, QStringLiteral( "," ) );
240  }
241  else if ( aUri.contains( QLatin1String( "IDB:" ) ) )
242  {
243  regexp.setPattern( QStringLiteral( " pass=.* " ) );
244  safeName.replace( regexp, QStringLiteral( " " ) );
245  }
246  else if ( ( aUri.contains( QLatin1String( "OCI:" ) ) )
247  || ( aUri.contains( QLatin1String( "ODBC:" ) ) ) )
248  {
249  regexp.setPattern( QStringLiteral( "/.*@" ) );
250  safeName.replace( regexp, QStringLiteral( "/@" ) );
251  }
252  else if ( aUri.contains( QLatin1String( "SDE:" ) ) )
253  {
254  QStringList strlist = aUri.split( ',' );
255  safeName = strlist[0] + ',' + strlist[1] + ',' + strlist[2] + ',' + strlist[3];
256  }
257  return safeName;
258 }
259 
261 {
262  return mAuthConfigId;
263 }
264 
266 {
267  return mUsername;
268 }
269 
271 {
272  mUsername = username;
273 }
274 
276 {
277  return mService;
278 }
279 
280 QString QgsDataSourceUri::host() const
281 {
282  return mHost;
283 }
284 
286 {
287  return mDatabase;
288 }
289 
291 {
292  return mPassword;
293 }
294 
296 {
297  mPassword = password;
298 }
299 
300 QString QgsDataSourceUri::port() const
301 {
302  return mPort;
303 }
304 
306 {
307  return mDriver;
308 }
309 
311 {
312  return mSSLmode;
313 }
314 
316 {
317  return mSchema;
318 }
319 
320 QString QgsDataSourceUri::table() const
321 {
322  return mTable;
323 }
324 
325 QString QgsDataSourceUri::sql() const
326 {
327  return mSql;
328 }
329 
331 {
332  return mGeometryColumn;
333 }
334 
336 {
337  return mKeyColumn;
338 }
339 
340 
341 void QgsDataSourceUri::setDriver( const QString &driver )
342 {
343  mDriver = driver;
344 }
345 
346 
347 void QgsDataSourceUri::setKeyColumn( const QString &column )
348 {
349  mKeyColumn = column;
350 }
351 
352 
354 {
355  mUseEstimatedMetadata = flag;
356 }
357 
359 {
360  return mUseEstimatedMetadata;
361 }
362 
364 {
365  mSelectAtIdDisabled = flag;
366 }
367 
369 {
370  return mSelectAtIdDisabled;
371 }
372 
373 void QgsDataSourceUri::setSql( const QString &sql )
374 {
375  mSql = sql;
376 }
377 
379 {
380  mSchema.clear();
381 }
382 
383 void QgsDataSourceUri::setSchema( const QString &schema )
384 {
385  mSchema = schema;
386 }
387 
388 QString QgsDataSourceUri::escape( const QString &val, QChar delim = '\'' ) const
389 {
390  QString escaped = val;
391 
392  escaped.replace( '\\', QLatin1String( "\\\\" ) );
393  escaped.replace( delim, QStringLiteral( "\\%1" ).arg( delim ) );
394 
395  return escaped;
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( "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 == SslDisable )
512  connectionItems << QStringLiteral( "sslmode=disable" );
513  else if ( mSSLmode == SslAllow )
514  connectionItems << QStringLiteral( "sslmode=allow" );
515  else if ( mSSLmode == SslRequire )
516  connectionItems << QStringLiteral( "sslmode=require" );
517 #if 0
518  else if ( mSSLmode == SSLprefer ) // no need to output the default
519  connectionItems << "sslmode=prefer";
520 #endif
521  else if ( mSSLmode == SslVerifyCa )
522  connectionItems << QStringLiteral( "sslmode=verify-ca" );
523  else if ( mSSLmode == SslVerifyFull )
524  connectionItems << QStringLiteral( "sslmode=verify-full" );
525 
526  if ( !mAuthConfigId.isEmpty() )
527  {
528  if ( expandAuthConfig )
529  {
530  if ( !QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, mAuthConfigId ) )
531  {
532  QgsDebugMsg( QString( "Data source URI FAILED to update via loading configuration ID '%1'" ).arg( mAuthConfigId ) );
533  }
534  }
535  else
536  {
537  connectionItems << "authcfg=" + mAuthConfigId;
538  }
539  }
540 
541  return connectionItems.join( QStringLiteral( " " ) );
542 }
543 
544 QString QgsDataSourceUri::uri( bool expandAuthConfig ) const
545 {
546  QString uri = connectionInfo( expandAuthConfig );
547 
548  if ( !mKeyColumn.isEmpty() )
549  {
550  uri += QStringLiteral( " key='%1'" ).arg( escape( mKeyColumn ) );
551  }
552 
553  if ( mUseEstimatedMetadata )
554  {
555  uri += QStringLiteral( " estimatedmetadata=true" );
556  }
557 
558  if ( !mSrid.isEmpty() )
559  {
560  uri += QStringLiteral( " srid=%1" ).arg( mSrid );
561  }
562 
563  if ( mWkbType != QgsWkbTypes::Unknown && mWkbType != QgsWkbTypes::NoGeometry )
564  {
565  uri += QLatin1String( " type=" );
566  uri += QgsWkbTypes::displayString( mWkbType );
567  }
568 
569  if ( mSelectAtIdDisabled )
570  {
571  uri += QStringLiteral( " selectatid=false" );
572  }
573 
574  for ( QMap<QString, QString>::const_iterator it = mParams.begin(); it != mParams.end(); ++it )
575  {
576  if ( it.key().contains( '=' ) || it.key().contains( ' ' ) )
577  {
578  QgsDebugMsg( QString( "invalid uri parameter %1 skipped" ).arg( it.key() ) );
579  continue;
580  }
581 
582  uri += ' ' + it.key() + "='" + escape( it.value() ) + '\'';
583  }
584 
585  QString columnName( mGeometryColumn );
586  columnName.replace( '\\', QLatin1String( "\\\\" ) );
587  columnName.replace( ')', QLatin1String( "\\)" ) );
588 
589  uri += QStringLiteral( " table=%1%2 sql=%3" )
590  .arg( quotedTablename(),
591  mGeometryColumn.isNull() ? QString() : QStringLiteral( " (%1)" ).arg( columnName ),
592  mSql );
593 
594  return uri;
595 }
596 
598 {
599  QUrl url;
600  for ( auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
601  {
602  url.addQueryItem( it.key(), it.value() );
603  }
604  return url.encodedQuery();
605 }
606 
607 void QgsDataSourceUri::setEncodedUri( const QByteArray &uri )
608 {
609  mParams.clear();
610  QUrl url;
611  url.setEncodedQuery( uri );
612  QPair<QString, QString> item;
613  Q_FOREACH ( item, url.queryItems() )
614  {
615  mParams.insertMulti( item.first, item.second );
616  }
617 }
618 
619 void QgsDataSourceUri::setEncodedUri( const QString &uri )
620 {
621  setEncodedUri( uri.toLatin1() );
622 }
623 
625 {
626  if ( !mSchema.isEmpty() )
627  return QStringLiteral( "\"%1\".\"%2\"" )
628  .arg( escape( mSchema, '"' ),
629  escape( mTable, '"' ) );
630  else
631  return QStringLiteral( "\"%1\"" )
632  .arg( escape( mTable, '"' ) );
633 }
634 
636  const QString &port,
637  const QString &database,
638  const QString &username,
639  const QString &password,
640  SslMode sslmode,
641  const QString &authConfigId )
642 {
643  mHost = host;
644  mDatabase = database;
645  mPort = port;
646  mUsername = username;
647  mPassword = password;
648  mSSLmode = sslmode;
649  mAuthConfigId = authConfigId;
650 }
651 
653  const QString &database,
654  const QString &username,
655  const QString &password,
656  SslMode sslmode,
657  const QString &authConfigId )
658 {
659  mService = service;
660  mDatabase = database;
661  mUsername = username;
662  mPassword = password;
663  mSSLmode = sslmode;
664  mAuthConfigId = authConfigId;
665 }
666 
668  const QString &table,
669  const QString &geometryColumn,
670  const QString &sql,
671  const QString &keyColumn )
672 {
673  mSchema = schema;
674  mTable = table;
675  mGeometryColumn = geometryColumn;
676  mSql = sql;
677  mKeyColumn = keyColumn;
678 }
679 
680 void QgsDataSourceUri::setAuthConfigId( const QString &authcfg )
681 {
682  mAuthConfigId = authcfg;
683 }
684 
686 {
687  mDatabase = database;
688 }
689 
691 {
692  return mWkbType;
693 }
694 
696 {
697  mWkbType = wkbType;
698 }
699 
700 QString QgsDataSourceUri::srid() const
701 {
702  return mSrid;
703 }
704 
705 void QgsDataSourceUri::setSrid( const QString &srid )
706 {
707  mSrid = srid;
708 }
709 
710 void QgsDataSourceUri::setParam( const QString &key, const QString &value )
711 {
712  // may be multiple
713  mParams.insertMulti( key, value );
714 }
715 
716 void QgsDataSourceUri::setParam( const QString &key, const QStringList &value )
717 {
718  Q_FOREACH ( const QString &val, value )
719  {
720  mParams.insertMulti( key, val );
721  }
722 }
723 
724 int QgsDataSourceUri::removeParam( const QString &key )
725 {
726  return mParams.remove( key );
727 }
728 
729 QString QgsDataSourceUri::param( const QString &key ) const
730 {
731  return mParams.value( key );
732 }
733 
734 QStringList QgsDataSourceUri::params( const QString &key ) const
735 {
736  return mParams.values( key );
737 }
738 
739 bool QgsDataSourceUri::hasParam( const QString &key ) const
740 {
741  return mParams.contains( key );
742 }
QString param(const QString &key) const
Get generic param (generic mode)
QgsWkbTypes::Type wkbType() const
The wkb type.
QString table() const
Returns the table.
bool useEstimatedMetadata() const
Returns true if estimated metadata are used.
void setUsername(const QString &username)
set username
bool hasParam(const QString &key) const
Test if param exists (generic mode)
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
void clearSchema()
Clears the schema.
QString authConfigId() const
Any associated authentication configuration ID.
SslMode sslMode() const
Returns the SSL mode.
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.
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SslMode sslmode=SslPrefer, const QString &authConfigId=QString())
Set all connection related members at once.
QString connectionInfo(bool expandAuthConfig=true) const
return connection part of URI
QString username() const
Returns the username.
QString host() const
Returns the host.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:67
QgsDataSourceUri()
default constructor
QStringList params(const QString &key) const
Get multiple generic param (generic mode)
void setDriver(const QString &driver)
Sets the driver name.
int removeParam(const QString &key)
Remove generic param (generic mode)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:38
QString geometryColumn() const
Return the name of the geometry column.
void setKeyColumn(const QString &column)
Sets the name of the (primary) key column.
bool selectAtIdDisabled() const
Returns whether the selection by id is disabled.
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)
set complete encoded uri (generic mode)
QString quotedTablename() const
quoted table name
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
QString port() const
Returns the port.
void setAuthConfigId(const QString &authcfg)
Set authentication configuration ID.
void setSrid(const QString &srid)
Sets the srid.
void setWkbType(QgsWkbTypes::Type type)
Sets the wkb type.
QString uri(bool expandAuthConfig=true) const
return complete uri
static QgsAuthManager * authManager()
Returns the application&#39;s authentication manager instance.
void disableSelectAtId(bool flag)
Set to true to disable selection by id.
QString driver() const
Returns the driver.
void setDataSource(const QString &aSchema, const QString &aTable, const QString &aGeometryColumn, const QString &aSql=QString(), const QString &aKeyColumn=QString())
Set all data source related members at once.
void setSql(const QString &sql)
Sets the SQL query.
void setPassword(const QString &password)
set password
QByteArray encodedUri() const
return complete encoded uri (generic mode)
QString sql() const
Returns the SQL query.
QString service() const
Returns the service name.
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.
void setSchema(const QString &schema)
set the table schema
QString schema() const
Returns the schema.
void setUseEstimatedMetadata(bool flag)
set use Estimated Metadata
QString database() const
Returns the database.
void setDatabase(const QString &database)
Set database.
QString srid() const
Returns the srid.
static QString removePassword(const QString &aUri)
Removes password element from uris.