QGIS API Documentation  2.99.0-Master (8ec3eaf)
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::null;
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" ) )
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 = theFlag;
365 }
366 
368 {
369  return mUseEstimatedMetadata;
370 }
371 
373 {
374  mSelectAtIdDisabled = theFlag;
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 &theVal, QChar delim = '\'' ) const
398 {
399  QString val = theVal;
400 
401  val.replace( '\\', QLatin1String( "\\\\" ) );
402  val.replace( delim, QStringLiteral( "\\%1" ).arg( delim ) );
403 
404  return val;
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 theUri = connectionInfo( expandAuthConfig );
556 
557  if ( !mKeyColumn.isEmpty() )
558  {
559  theUri += QStringLiteral( " key='%1'" ).arg( escape( mKeyColumn ) );
560  }
561 
562  if ( mUseEstimatedMetadata )
563  {
564  theUri += QStringLiteral( " estimatedmetadata=true" );
565  }
566 
567  if ( !mSrid.isEmpty() )
568  {
569  theUri += QStringLiteral( " srid=%1" ).arg( mSrid );
570  }
571 
572  if ( mWkbType != QgsWkbTypes::Unknown && mWkbType != QgsWkbTypes::NoGeometry )
573  {
574  theUri += QLatin1String( " type=" );
575  theUri += QgsWkbTypes::displayString( mWkbType );
576  }
577 
578  if ( mSelectAtIdDisabled )
579  {
580  theUri += 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  theUri += ' ' + it.key() + "='" + escape( it.value() ) + '\'';
592  }
593 
594  QString columnName( mGeometryColumn );
595  columnName.replace( '\\', QLatin1String( "\\\\" ) );
596  columnName.replace( ')', QLatin1String( "\\)" ) );
597 
598  theUri += QStringLiteral( " table=%1%2 sql=%3" )
599  .arg( quotedTablename(),
600  mGeometryColumn.isNull() ? QString() : QStringLiteral( " (%1)" ).arg( columnName ),
601  mSql );
602 
603  return theUri;
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:33
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:36
void clearSchema()
Clears the schema.
QString authConfigId() const
Any associated authentication configuration ID.
void disableSelectAtId(bool theFlag)
Set to true to disable selection by id.
enum SslMode sslMode() const
Returns the SSL mode.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
Definition: qgswkbtypes.cpp:32
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.
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
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)
void setUseEstimatedMetadata(bool theFlag)
set use Estimated Metadata
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, eg the geometry name used in WKT geometry representatio...
Definition: qgswkbtypes.cpp:48
QString password() const
Returns the password.
void setSchema(const QString &schema)
set the table schema
QString schema() const
Returns the schema.
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.