QGIS API Documentation  2.99.0-Master (f867b65)
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 
24 #include <QStringList>
25 #include <QRegExp>
26 #include <QUrl>
27 
29  : mSSLmode( SslPrefer )
30  , mKeyColumn( QLatin1String( "" ) )
31  , mUseEstimatedMetadata( false )
32  , mSelectAtIdDisabled( false )
33  , mWkbType( QgsWkbTypes::Unknown )
34 {
35  // do nothing
36 }
37 
39  : mSSLmode( SslPrefer )
40  , mKeyColumn( QLatin1String( "" ) )
41  , mUseEstimatedMetadata( false )
42  , mSelectAtIdDisabled( false )
43  , mWkbType( QgsWkbTypes::Unknown )
44 {
45  int i = 0;
46  while ( i < uri.length() )
47  {
48  skipBlanks( uri, i );
49 
50  if ( uri[i] == '=' )
51  {
52  QgsDebugMsg( "parameter name expected before =" );
53  i++;
54  continue;
55  }
56 
57  int start = i;
58 
59  while ( i < uri.length() && uri[i] != '=' && !uri[i].isSpace() )
60  i++;
61 
62  QString pname = uri.mid( start, i - start );
63 
64  skipBlanks( uri, i );
65 
66  if ( i == uri.length() || uri[i] != '=' )
67  {
68  QgsDebugMsg( QString( "= expected after parameter name, skipping text '%1'" ).arg( pname ) );
69  continue;
70  }
71 
72  i++;
73 
74  if ( pname == QLatin1String( "sql" ) )
75  {
76  // rest of line is a sql where clause
77  skipBlanks( uri, i );
78  mSql = uri.mid( i );
79  break;
80  }
81  else
82  {
83  QString pval = getValue( uri, i );
84 
85  if ( pname == QLatin1String( "table" ) )
86  {
87  if ( uri[i] == '.' )
88  {
89  i++;
90 
91  mSchema = pval;
92  mTable = getValue( uri, i );
93  }
94  else
95  {
96  mSchema = QLatin1String( "" );
97  mTable = pval;
98  }
99 
100  if ( uri[i] == '(' )
101  {
102  i++;
103 
104  int start = i;
105  while ( i < uri.length() && uri[i] != ')' )
106  {
107  if ( uri[i] == '\\' )
108  i++;
109  i++;
110  }
111 
112  if ( i == uri.length() )
113  {
114  QgsDebugMsg( "closing parenthesis missing" );
115  }
116 
117  mGeometryColumn = uri.mid( start, i - start );
118  mGeometryColumn.replace( QLatin1String( "\\)" ), QLatin1String( ")" ) );
119  mGeometryColumn.replace( QLatin1String( "\\\\" ), QLatin1String( "\\" ) );
120 
121  i++;
122  }
123  else
124  {
125  mGeometryColumn = QString();
126  }
127  }
128  else if ( pname == QLatin1String( "key" ) )
129  {
130  mKeyColumn = pval;
131  }
132  else if ( pname == QLatin1String( "estimatedmetadata" ) )
133  {
134  mUseEstimatedMetadata = pval == QLatin1String( "true" );
135  }
136  else if ( pname == QLatin1String( "srid" ) )
137  {
138  mSrid = pval;
139  }
140  else if ( pname == QLatin1String( "type" ) )
141  {
142  mWkbType = QgsWkbTypes::parseType( pval );
143  }
144  else if ( pname == QLatin1String( "selectatid" ) )
145  {
146  mSelectAtIdDisabled = pval == QLatin1String( "false" );
147  }
148  else if ( pname == QLatin1String( "service" ) )
149  {
150  mService = pval;
151  }
152  else if ( pname == QLatin1String( "authcfg" ) )
153  {
154  mAuthConfigId = pval;
155  }
156  else if ( pname == QLatin1String( "user" ) || pname == QLatin1String( "username" ) ) // Also accepts new WFS provider naming
157  {
158  mUsername = pval;
159  }
160  else if ( pname == QLatin1String( "password" ) )
161  {
162  mPassword = pval;
163  }
164  else if ( pname == QLatin1String( "connect_timeout" ) )
165  {
166  QgsDebugMsg( "connection timeout ignored" );
167  }
168  else if ( pname == QLatin1String( "dbname" ) )
169  {
170  mDatabase = pval;
171  }
172  else if ( pname == QLatin1String( "host" ) )
173  {
174  mHost = pval;
175  }
176  else if ( pname == QLatin1String( "hostaddr" ) )
177  {
178  QgsDebugMsg( "database host ip address ignored" );
179  }
180  else if ( pname == QLatin1String( "port" ) )
181  {
182  mPort = pval;
183  }
184  else if ( pname == QLatin1String( "driver" ) )
185  {
186  mDriver = pval;
187  }
188  else if ( pname == QLatin1String( "tty" ) )
189  {
190  QgsDebugMsg( "backend debug tty ignored" );
191  }
192  else if ( pname == QLatin1String( "options" ) )
193  {
194  QgsDebugMsg( "backend debug options ignored" );
195  }
196  else if ( pname == QLatin1String( "sslmode" ) )
197  {
198  if ( pval == QLatin1String( "disable" ) )
199  mSSLmode = SslDisable;
200  else if ( pval == QLatin1String( "allow" ) )
201  mSSLmode = SslAllow;
202  else if ( pval == QLatin1String( "prefer" ) )
203  mSSLmode = SslPrefer;
204  else if ( pval == QLatin1String( "require" ) )
205  mSSLmode = SslRequire;
206  else if ( pval == QLatin1String( "verify-ca" ) )
207  mSSLmode = SslVerifyCa;
208  else if ( pval == QLatin1String( "verify-full" ) )
209  mSSLmode = SslVerifyFull;
210  }
211  else if ( pname == QLatin1String( "requiressl" ) )
212  {
213  if ( pval == QLatin1String( "0" ) )
214  mSSLmode = SslDisable;
215  else
216  mSSLmode = SslPrefer;
217  }
218  else if ( pname == QLatin1String( "krbsrvname" ) )
219  {
220  QgsDebugMsg( "kerberos server name ignored" );
221  }
222  else if ( pname == QLatin1String( "gsslib" ) )
223  {
224  QgsDebugMsg( "gsslib ignored" );
225  }
226  else
227  {
228  QgsDebugMsg( "parameter \"" + pname + "\":\"" + pval + "\" added" );
229  setParam( pname, pval );
230  }
231  }
232  }
233 }
234 
235 QString QgsDataSourceUri::removePassword( const QString &aUri )
236 {
237  QRegExp regexp;
238  regexp.setMinimal( true );
239  QString safeName( aUri );
240  if ( aUri.contains( QLatin1String( " password=" ) ) )
241  {
242  regexp.setPattern( QStringLiteral( " password=.* " ) );
243  safeName.replace( regexp, QStringLiteral( " " ) );
244  }
245  else if ( aUri.contains( QLatin1String( ",password=" ) ) )
246  {
247  regexp.setPattern( QStringLiteral( ",password=.*," ) );
248  safeName.replace( regexp, QStringLiteral( "," ) );
249  }
250  else if ( aUri.contains( QLatin1String( "IDB:" ) ) )
251  {
252  regexp.setPattern( QStringLiteral( " pass=.* " ) );
253  safeName.replace( regexp, QStringLiteral( " " ) );
254  }
255  else if ( ( aUri.contains( QLatin1String( "OCI:" ) ) )
256  || ( aUri.contains( QLatin1String( "ODBC:" ) ) ) )
257  {
258  regexp.setPattern( QStringLiteral( "/.*@" ) );
259  safeName.replace( regexp, QStringLiteral( "/@" ) );
260  }
261  else if ( aUri.contains( QLatin1String( "SDE:" ) ) )
262  {
263  QStringList strlist = aUri.split( ',' );
264  safeName = strlist[0] + ',' + strlist[1] + ',' + strlist[2] + ',' + strlist[3];
265  }
266  return safeName;
267 }
268 
270 {
271  return mAuthConfigId;
272 }
273 
275 {
276  return mUsername;
277 }
278 
280 {
281  mUsername = username;
282 }
283 
285 {
286  return mService;
287 }
288 
289 QString QgsDataSourceUri::host() const
290 {
291  return mHost;
292 }
293 
295 {
296  return mDatabase;
297 }
298 
300 {
301  return mPassword;
302 }
303 
305 {
306  mPassword = password;
307 }
308 
309 QString QgsDataSourceUri::port() const
310 {
311  return mPort;
312 }
313 
315 {
316  return mDriver;
317 }
318 
320 {
321  return mSSLmode;
322 }
323 
325 {
326  return mSchema;
327 }
328 
329 QString QgsDataSourceUri::table() const
330 {
331  return mTable;
332 }
333 
334 QString QgsDataSourceUri::sql() const
335 {
336  return mSql;
337 }
338 
340 {
341  return mGeometryColumn;
342 }
343 
345 {
346  return mKeyColumn;
347 }
348 
349 
350 void QgsDataSourceUri::setDriver( const QString &driver )
351 {
352  mDriver = driver;
353 }
354 
355 
356 void QgsDataSourceUri::setKeyColumn( const QString &column )
357 {
358  mKeyColumn = column;
359 }
360 
361 
363 {
364  mUseEstimatedMetadata = flag;
365 }
366 
368 {
369  return mUseEstimatedMetadata;
370 }
371 
373 {
374  mSelectAtIdDisabled = flag;
375 }
376 
378 {
379  return mSelectAtIdDisabled;
380 }
381 
382 void QgsDataSourceUri::setSql( const QString &sql )
383 {
384  mSql = sql;
385 }
386 
388 {
389  mSchema = QLatin1String( "" );
390 }
391 
392 void QgsDataSourceUri::setSchema( const QString &schema )
393 {
394  mSchema = schema;
395 }
396 
397 QString QgsDataSourceUri::escape( const QString &val, QChar delim = '\'' ) const
398 {
399  QString escaped = val;
400 
401  escaped.replace( '\\', QLatin1String( "\\\\" ) );
402  escaped.replace( delim, QStringLiteral( "\\%1" ).arg( delim ) );
403 
404  return escaped;
405 }
406 
407 void QgsDataSourceUri::skipBlanks( const QString &uri, int &i )
408 {
409  // skip space before value
410  while ( i < uri.length() && uri[i].isSpace() )
411  i++;
412 }
413 
414 QString QgsDataSourceUri::getValue( const QString &uri, int &i )
415 {
416  skipBlanks( uri, i );
417 
418  // Get the parameter value
419  QString pval;
420  if ( i < uri.length() && ( uri[i] == '\'' || uri[i] == '"' ) )
421  {
422  QChar delim = uri[i];
423 
424  i++;
425 
426  // value is quoted
427  for ( ;; )
428  {
429  if ( i == uri.length() )
430  {
431  QgsDebugMsg( "unterminated quoted string in connection info string" );
432  return pval;
433  }
434 
435  if ( uri[i] == '\\' )
436  {
437  i++;
438  if ( i == uri.length() )
439  continue;
440  if ( uri[i] != delim && uri[i] != '\\' )
441  i--;
442  }
443  else if ( uri[i] == delim )
444  {
445  i++;
446  break;
447  }
448 
449  pval += uri[i++];
450  }
451  }
452  else
453  {
454  // value is not quoted
455  while ( i < uri.length() )
456  {
457  if ( uri[i].isSpace() )
458  {
459  // end of value
460  break;
461  }
462 
463  if ( uri[i] == '\\' )
464  {
465  i++;
466  if ( i == uri.length() )
467  break;
468  if ( uri[i] != '\\' && uri[i] != '\'' )
469  i--;
470  }
471 
472  pval += uri[i++];
473  }
474  }
475 
476  skipBlanks( uri, i );
477 
478  return pval;
479 }
480 
481 QString QgsDataSourceUri::connectionInfo( bool expandAuthConfig ) const
482 {
483  QStringList connectionItems;
484 
485  if ( mDatabase != QLatin1String( "" ) )
486  {
487  connectionItems << "dbname='" + escape( mDatabase ) + '\'';
488  }
489 
490  if ( mService != QLatin1String( "" ) )
491  {
492  connectionItems << "service='" + escape( mService ) + '\'';
493  }
494  else if ( mHost != QLatin1String( "" ) )
495  {
496  connectionItems << "host=" + mHost;
497  }
498 
499  if ( mService.isEmpty() )
500  {
501  if ( mPort != QLatin1String( "" ) )
502  connectionItems << "port=" + mPort;
503  }
504 
505  if ( mDriver != QLatin1String( "" ) )
506  {
507  connectionItems << "driver='" + escape( mDriver ) + '\'';
508  }
509 
510  if ( mUsername != QLatin1String( "" ) )
511  {
512  connectionItems << "user='" + escape( mUsername ) + '\'';
513 
514  if ( mPassword != QLatin1String( "" ) )
515  {
516  connectionItems << "password='" + escape( mPassword ) + '\'';
517  }
518  }
519 
520  if ( mSSLmode == SslDisable )
521  connectionItems << QStringLiteral( "sslmode=disable" );
522  else if ( mSSLmode == SslAllow )
523  connectionItems << QStringLiteral( "sslmode=allow" );
524  else if ( mSSLmode == SslRequire )
525  connectionItems << QStringLiteral( "sslmode=require" );
526 #if 0
527  else if ( mSSLmode == SSLprefer ) // no need to output the default
528  connectionItems << "sslmode=prefer";
529 #endif
530  else if ( mSSLmode == SslVerifyCa )
531  connectionItems << QStringLiteral( "sslmode=verify-ca" );
532  else if ( mSSLmode == SslVerifyFull )
533  connectionItems << QStringLiteral( "sslmode=verify-full" );
534 
535  if ( !mAuthConfigId.isEmpty() )
536  {
537  if ( expandAuthConfig )
538  {
539  if ( !QgsAuthManager::instance()->updateDataSourceUriItems( connectionItems, mAuthConfigId ) )
540  {
541  QgsDebugMsg( QString( "Data source URI FAILED to update via loading configuration ID '%1'" ).arg( mAuthConfigId ) );
542  }
543  }
544  else
545  {
546  connectionItems << "authcfg=" + mAuthConfigId;
547  }
548  }
549 
550  return connectionItems.join( QStringLiteral( " " ) );
551 }
552 
553 QString QgsDataSourceUri::uri( bool expandAuthConfig ) const
554 {
555  QString uri = connectionInfo( expandAuthConfig );
556 
557  if ( !mKeyColumn.isEmpty() )
558  {
559  uri += QStringLiteral( " key='%1'" ).arg( escape( mKeyColumn ) );
560  }
561 
562  if ( mUseEstimatedMetadata )
563  {
564  uri += QStringLiteral( " estimatedmetadata=true" );
565  }
566 
567  if ( !mSrid.isEmpty() )
568  {
569  uri += QStringLiteral( " srid=%1" ).arg( mSrid );
570  }
571 
572  if ( mWkbType != QgsWkbTypes::Unknown && mWkbType != QgsWkbTypes::NoGeometry )
573  {
574  uri += QLatin1String( " type=" );
575  uri += QgsWkbTypes::displayString( mWkbType );
576  }
577 
578  if ( mSelectAtIdDisabled )
579  {
580  uri += QStringLiteral( " selectatid=false" );
581  }
582 
583  for ( QMap<QString, QString>::const_iterator it = mParams.begin(); it != mParams.end(); ++it )
584  {
585  if ( it.key().contains( '=' ) || it.key().contains( ' ' ) )
586  {
587  QgsDebugMsg( QString( "invalid uri parameter %1 skipped" ).arg( it.key() ) );
588  continue;
589  }
590 
591  uri += ' ' + it.key() + "='" + escape( it.value() ) + '\'';
592  }
593 
594  QString columnName( mGeometryColumn );
595  columnName.replace( '\\', QLatin1String( "\\\\" ) );
596  columnName.replace( ')', QLatin1String( "\\)" ) );
597 
598  uri += QStringLiteral( " table=%1%2 sql=%3" )
599  .arg( quotedTablename(),
600  mGeometryColumn.isNull() ? QString() : QStringLiteral( " (%1)" ).arg( columnName ),
601  mSql );
602 
603  return uri;
604 }
605 
607 {
608  QUrl url;
609  Q_FOREACH ( const QString &key, mParams.uniqueKeys() )
610  {
611  Q_FOREACH ( const QString &value, mParams.values( key ) )
612  {
613  url.addQueryItem( key, value );
614  }
615  }
616  return url.encodedQuery();
617 }
618 
619 void QgsDataSourceUri::setEncodedUri( const QByteArray &uri )
620 {
621  mParams.clear();
622  QUrl url;
623  url.setEncodedQuery( uri );
624  QPair<QString, QString> item;
625  Q_FOREACH ( item, url.queryItems() )
626  {
627  mParams.insertMulti( item.first, item.second );
628  }
629 }
630 
631 void QgsDataSourceUri::setEncodedUri( const QString &uri )
632 {
633  setEncodedUri( uri.toLatin1() );
634 }
635 
637 {
638  if ( !mSchema.isEmpty() )
639  return QStringLiteral( "\"%1\".\"%2\"" )
640  .arg( escape( mSchema, '"' ),
641  escape( mTable, '"' ) );
642  else
643  return QStringLiteral( "\"%1\"" )
644  .arg( escape( mTable, '"' ) );
645 }
646 
648  const QString &port,
649  const QString &database,
650  const QString &username,
651  const QString &password,
652  SslMode sslmode,
653  const QString &authConfigId )
654 {
655  mHost = host;
656  mDatabase = database;
657  mPort = port;
658  mUsername = username;
659  mPassword = password;
660  mSSLmode = sslmode;
661  mAuthConfigId = authConfigId;
662 }
663 
665  const QString &database,
666  const QString &username,
667  const QString &password,
668  SslMode sslmode,
669  const QString &authConfigId )
670 {
671  mService = service;
672  mDatabase = database;
673  mUsername = username;
674  mPassword = password;
675  mSSLmode = sslmode;
676  mAuthConfigId = authConfigId;
677 }
678 
680  const QString &table,
681  const QString &geometryColumn,
682  const QString &sql,
683  const QString &keyColumn )
684 {
685  mSchema = schema;
686  mTable = table;
687  mGeometryColumn = geometryColumn;
688  mSql = sql;
689  mKeyColumn = keyColumn;
690 }
691 
692 void QgsDataSourceUri::setAuthConfigId( const QString &authcfg )
693 {
694  mAuthConfigId = authcfg;
695 }
696 
698 {
699  mDatabase = database;
700 }
701 
703 {
704  return mWkbType;
705 }
706 
708 {
709  mWkbType = wkbType;
710 }
711 
712 QString QgsDataSourceUri::srid() const
713 {
714  return mSrid;
715 }
716 
717 void QgsDataSourceUri::setSrid( const QString &srid )
718 {
719  mSrid = srid;
720 }
721 
722 void QgsDataSourceUri::setParam( const QString &key, const QString &value )
723 {
724  // may be multiple
725  mParams.insertMulti( key, value );
726 }
727 
728 void QgsDataSourceUri::setParam( const QString &key, const QStringList &value )
729 {
730  Q_FOREACH ( const QString &val, value )
731  {
732  mParams.insertMulti( key, val );
733  }
734 }
735 
736 int QgsDataSourceUri::removeParam( const QString &key )
737 {
738  return mParams.remove( key );
739 }
740 
741 QString QgsDataSourceUri::param( const QString &key ) const
742 {
743  return mParams.value( key );
744 }
745 
746 QStringList QgsDataSourceUri::params( const QString &key ) const
747 {
748  return mParams.values( key );
749 }
750 
751 bool QgsDataSourceUri::hasParam( const QString &key ) const
752 {
753  return mParams.contains( key );
754 }
QString param(const QString &key) const
Get generic param (generic mode)
QgsWkbTypes::Type wkbType() const
The wkb type.
QString table() const
Returns the table.
static QgsAuthManager * instance()
Enforce singleton pattern.
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
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:39
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:66
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)
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
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.