QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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( QStringLiteral( "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( QStringLiteral( "= 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( QStringLiteral( "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( QStringLiteral( "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( QStringLiteral( "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( QStringLiteral( "backend debug tty ignored" ) );
182  }
183  else if ( pname == QLatin1String( "options" ) )
184  {
185  QgsDebugMsg( QStringLiteral( "backend debug options ignored" ) );
186  }
187  else if ( pname == QLatin1String( "sslmode" ) )
188  {
189  mSSLmode = decodeSslMode( pval );
190  }
191  else if ( pname == QLatin1String( "requiressl" ) )
192  {
193  if ( pval == QLatin1String( "0" ) )
194  mSSLmode = SslDisable;
195  else
196  mSSLmode = SslPrefer;
197  }
198  else if ( pname == QLatin1String( "krbsrvname" ) )
199  {
200  QgsDebugMsg( QStringLiteral( "kerberos server name ignored" ) );
201  }
202  else if ( pname == QLatin1String( "gsslib" ) )
203  {
204  QgsDebugMsg( QStringLiteral( "gsslib ignored" ) );
205  }
206  else
207  {
208  QgsDebugMsgLevel( "parameter \"" + pname + "\":\"" + pval + "\" added", 4 );
209  setParam( pname, pval );
210  }
211  }
212  }
213 }
214 
215 QString QgsDataSourceUri::removePassword( const QString &aUri )
216 {
217  QRegExp regexp;
218  regexp.setMinimal( true );
219  QString safeName( aUri );
220  if ( aUri.contains( QLatin1String( " password=" ) ) )
221  {
222  regexp.setPattern( QStringLiteral( " password=.* " ) );
223  safeName.replace( regexp, QStringLiteral( " " ) );
224  }
225  else if ( aUri.contains( QLatin1String( ",password=" ) ) )
226  {
227  regexp.setPattern( QStringLiteral( ",password=.*," ) );
228  safeName.replace( regexp, QStringLiteral( "," ) );
229  }
230  else if ( aUri.contains( QLatin1String( "IDB:" ) ) )
231  {
232  regexp.setPattern( QStringLiteral( " pass=.* " ) );
233  safeName.replace( regexp, QStringLiteral( " " ) );
234  }
235  else if ( ( aUri.contains( QLatin1String( "OCI:" ) ) )
236  || ( aUri.contains( QLatin1String( "ODBC:" ) ) ) )
237  {
238  regexp.setPattern( QStringLiteral( "/.*@" ) );
239  safeName.replace( regexp, QStringLiteral( "/@" ) );
240  }
241  else if ( aUri.contains( QLatin1String( "SDE:" ) ) )
242  {
243  QStringList strlist = aUri.split( ',' );
244  safeName = strlist[0] + ',' + strlist[1] + ',' + strlist[2] + ',' + strlist[3];
245  }
246  return safeName;
247 }
248 
250 {
251  return mAuthConfigId;
252 }
253 
255 {
256  return mUsername;
257 }
258 
260 {
261  mUsername = username;
262 }
263 
265 {
266  return mService;
267 }
268 
269 QString QgsDataSourceUri::host() const
270 {
271  return mHost;
272 }
273 
275 {
276  return mDatabase;
277 }
278 
280 {
281  return mPassword;
282 }
283 
285 {
286  mPassword = password;
287 }
288 
289 QString QgsDataSourceUri::port() const
290 {
291  return mPort;
292 }
293 
295 {
296  return mDriver;
297 }
298 
300 {
301  return mSSLmode;
302 }
303 
305 {
306  return mSchema;
307 }
308 
309 QString QgsDataSourceUri::table() const
310 {
311  return mTable;
312 }
313 
314 QString QgsDataSourceUri::sql() const
315 {
316  return mSql;
317 }
318 
320 {
321  return mGeometryColumn;
322 }
323 
325 {
326  return mKeyColumn;
327 }
328 
329 
330 void QgsDataSourceUri::setDriver( const QString &driver )
331 {
332  mDriver = driver;
333 }
334 
335 
336 void QgsDataSourceUri::setKeyColumn( const QString &column )
337 {
338  mKeyColumn = column;
339 }
340 
341 
343 {
344  mUseEstimatedMetadata = flag;
345 }
346 
348 {
349  return mUseEstimatedMetadata;
350 }
351 
353 {
354  mSelectAtIdDisabled = flag;
355 }
356 
358 {
359  return mSelectAtIdDisabled;
360 }
361 
362 void QgsDataSourceUri::setSql( const QString &sql )
363 {
364  mSql = sql;
365 }
366 
368 {
369  mSchema.clear();
370 }
371 
372 void QgsDataSourceUri::setSchema( const QString &schema )
373 {
374  mSchema = schema;
375 }
376 
377 QString QgsDataSourceUri::escape( const QString &val, QChar delim = '\'' ) const
378 {
379  QString escaped = val;
380 
381  escaped.replace( '\\', QLatin1String( "\\\\" ) );
382  escaped.replace( delim, QStringLiteral( "\\%1" ).arg( delim ) );
383 
384  return escaped;
385 }
386 
387 void QgsDataSourceUri::skipBlanks( const QString &uri, int &i )
388 {
389  // skip space before value
390  while ( i < uri.length() && uri[i].isSpace() )
391  i++;
392 }
393 
394 QString QgsDataSourceUri::getValue( const QString &uri, int &i )
395 {
396  skipBlanks( uri, i );
397 
398  // Get the parameter value
399  QString pval;
400  if ( i < uri.length() && ( uri[i] == '\'' || uri[i] == '"' ) )
401  {
402  QChar delim = uri[i];
403 
404  i++;
405 
406  // value is quoted
407  for ( ;; )
408  {
409  if ( i == uri.length() )
410  {
411  QgsDebugMsg( QStringLiteral( "unterminated quoted string in connection info string" ) );
412  return pval;
413  }
414 
415  if ( uri[i] == '\\' )
416  {
417  i++;
418  if ( i == uri.length() )
419  continue;
420  if ( uri[i] != delim && uri[i] != '\\' )
421  i--;
422  }
423  else if ( uri[i] == delim )
424  {
425  i++;
426  break;
427  }
428 
429  pval += uri[i++];
430  }
431  }
432  else
433  {
434  // value is not quoted
435  while ( i < uri.length() )
436  {
437  if ( uri[i].isSpace() )
438  {
439  // end of value
440  break;
441  }
442 
443  if ( uri[i] == '\\' )
444  {
445  i++;
446  if ( i == uri.length() )
447  break;
448  if ( uri[i] != '\\' && uri[i] != '\'' )
449  i--;
450  }
451 
452  pval += uri[i++];
453  }
454  }
455 
456  skipBlanks( uri, i );
457 
458  return pval;
459 }
460 
461 QString QgsDataSourceUri::connectionInfo( bool expandAuthConfig ) const
462 {
463  QStringList connectionItems;
464 
465  if ( !mDatabase.isEmpty() )
466  {
467  connectionItems << "dbname='" + escape( mDatabase ) + '\'';
468  }
469 
470  if ( !mService.isEmpty() )
471  {
472  connectionItems << "service='" + escape( mService ) + '\'';
473  }
474  else if ( !mHost.isEmpty() )
475  {
476  connectionItems << "host=" + mHost;
477  }
478 
479  if ( mService.isEmpty() )
480  {
481  if ( !mPort.isEmpty() )
482  connectionItems << "port=" + mPort;
483  }
484 
485  if ( !mDriver.isEmpty() )
486  {
487  connectionItems << "driver='" + escape( mDriver ) + '\'';
488  }
489 
490  if ( !mUsername.isEmpty() )
491  {
492  connectionItems << "user='" + escape( mUsername ) + '\'';
493 
494  if ( !mPassword.isEmpty() )
495  {
496  connectionItems << "password='" + escape( mPassword ) + '\'';
497  }
498  }
499 
500  if ( mSSLmode != SslPrefer ) // no need to output the default
501  {
502  connectionItems << QStringLiteral( "sslmode=" ) + encodeSslMode( mSSLmode );
503  }
504 
505  if ( !mAuthConfigId.isEmpty() )
506  {
507  if ( expandAuthConfig )
508  {
509  if ( !QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, mAuthConfigId ) )
510  {
511  QgsDebugMsg( QStringLiteral( "Data source URI FAILED to update via loading configuration ID '%1'" ).arg( mAuthConfigId ) );
512  }
513  }
514  else
515  {
516  connectionItems << "authcfg=" + mAuthConfigId;
517  }
518  }
519 
520  return connectionItems.join( QStringLiteral( " " ) );
521 }
522 
523 QString QgsDataSourceUri::uri( bool expandAuthConfig ) const
524 {
525  QString uri = connectionInfo( expandAuthConfig );
526 
527  if ( !mKeyColumn.isEmpty() )
528  {
529  uri += QStringLiteral( " key='%1'" ).arg( escape( mKeyColumn ) );
530  }
531 
532  if ( mUseEstimatedMetadata )
533  {
534  uri += QStringLiteral( " estimatedmetadata=true" );
535  }
536 
537  if ( !mSrid.isEmpty() )
538  {
539  uri += QStringLiteral( " srid=%1" ).arg( mSrid );
540  }
541 
542  if ( mWkbType != QgsWkbTypes::Unknown && mWkbType != QgsWkbTypes::NoGeometry )
543  {
544  uri += QLatin1String( " type=" );
545  uri += QgsWkbTypes::displayString( mWkbType );
546  }
547 
548  if ( mSelectAtIdDisabled )
549  {
550  uri += QStringLiteral( " selectatid=false" );
551  }
552 
553  for ( QMap<QString, QString>::const_iterator it = mParams.begin(); it != mParams.end(); ++it )
554  {
555  if ( it.key().contains( '=' ) || it.key().contains( ' ' ) )
556  {
557  QgsDebugMsg( QStringLiteral( "invalid uri parameter %1 skipped" ).arg( it.key() ) );
558  continue;
559  }
560 
561  uri += ' ' + it.key() + "='" + escape( it.value() ) + '\'';
562  }
563 
564  QString columnName( mGeometryColumn );
565  columnName.replace( '\\', QLatin1String( "\\\\" ) );
566  columnName.replace( ')', QLatin1String( "\\)" ) );
567 
568  uri += QStringLiteral( " table=%1%2 sql=%3" )
569  .arg( quotedTablename(),
570  mGeometryColumn.isNull() ? QString() : QStringLiteral( " (%1)" ).arg( columnName ),
571  mSql );
572 
573  return uri;
574 }
575 
577 {
578  QUrl url;
579  for ( auto it = mParams.constBegin(); it != mParams.constEnd(); ++it )
580  {
581  url.addQueryItem( it.key(), it.value() );
582  }
583  return url.encodedQuery();
584 }
585 
586 void QgsDataSourceUri::setEncodedUri( const QByteArray &uri )
587 {
588  mParams.clear();
589  QUrl url;
590  url.setEncodedQuery( uri );
591  QPair<QString, QString> item;
592  Q_FOREACH ( item, url.queryItems() )
593  {
594  mParams.insertMulti( item.first, item.second );
595  }
596 }
597 
598 void QgsDataSourceUri::setEncodedUri( const QString &uri )
599 {
600  setEncodedUri( uri.toLatin1() );
601 }
602 
604 {
605  if ( !mSchema.isEmpty() )
606  return QStringLiteral( "\"%1\".\"%2\"" )
607  .arg( escape( mSchema, '"' ),
608  escape( mTable, '"' ) );
609  else
610  return QStringLiteral( "\"%1\"" )
611  .arg( escape( mTable, '"' ) );
612 }
613 
615  const QString &port,
616  const QString &database,
617  const QString &username,
618  const QString &password,
619  SslMode sslmode,
620  const QString &authConfigId )
621 {
622  mHost = host;
623  mDatabase = database;
624  mPort = port;
625  mUsername = username;
626  mPassword = password;
627  mSSLmode = sslmode;
628  mAuthConfigId = authConfigId;
629 }
630 
632  const QString &database,
633  const QString &username,
634  const QString &password,
635  SslMode sslmode,
636  const QString &authConfigId )
637 {
638  mService = service;
639  mDatabase = database;
640  mUsername = username;
641  mPassword = password;
642  mSSLmode = sslmode;
643  mAuthConfigId = authConfigId;
644 }
645 
647  const QString &table,
648  const QString &geometryColumn,
649  const QString &sql,
650  const QString &keyColumn )
651 {
652  mSchema = schema;
653  mTable = table;
654  mGeometryColumn = geometryColumn;
655  mSql = sql;
656  mKeyColumn = keyColumn;
657 }
658 
659 void QgsDataSourceUri::setAuthConfigId( const QString &authcfg )
660 {
661  mAuthConfigId = authcfg;
662 }
663 
665 {
666  mDatabase = database;
667 }
668 
670 {
671  return mWkbType;
672 }
673 
675 {
676  mWkbType = wkbType;
677 }
678 
679 QString QgsDataSourceUri::srid() const
680 {
681  return mSrid;
682 }
683 
684 void QgsDataSourceUri::setSrid( const QString &srid )
685 {
686  mSrid = srid;
687 }
688 
690 {
691  if ( sslMode == QLatin1String( "prefer" ) )
692  return SslPrefer;
693  else if ( sslMode == QLatin1String( "disable" ) )
694  return SslDisable;
695  else if ( sslMode == QLatin1String( "allow" ) )
696  return SslAllow;
697  else if ( sslMode == QLatin1String( "require" ) )
698  return SslRequire;
699  else if ( sslMode == QLatin1String( "verify-ca" ) )
700  return SslVerifyCa;
701  else if ( sslMode == QLatin1String( "verify-full" ) )
702  return SslVerifyFull;
703  else
704  return SslPrefer; // default
705 }
706 
708 {
709  switch ( sslMode )
710  {
711  case SslPrefer: return QStringLiteral( "prefer" );
712  case SslDisable: return QStringLiteral( "disable" );
713  case SslAllow: return QStringLiteral( "allow" );
714  case SslRequire: return QStringLiteral( "require" );
715  case SslVerifyCa: return QStringLiteral( "verify-ca" );
716  case SslVerifyFull: return QStringLiteral( "verify-full" );
717  }
718  return QString();
719 }
720 
721 void QgsDataSourceUri::setParam( const QString &key, const QString &value )
722 {
723  // may be multiple
724  mParams.insertMulti( key, value );
725 }
726 
727 void QgsDataSourceUri::setParam( const QString &key, const QStringList &value )
728 {
729  Q_FOREACH ( const QString &val, value )
730  {
731  mParams.insertMulti( key, val );
732  }
733 }
734 
735 int QgsDataSourceUri::removeParam( const QString &key )
736 {
737  return mParams.remove( key );
738 }
739 
740 QString QgsDataSourceUri::param( const QString &key ) const
741 {
742  return mParams.value( key );
743 }
744 
745 QStringList QgsDataSourceUri::params( const QString &key ) const
746 {
747  return mParams.values( key );
748 }
749 
750 bool QgsDataSourceUri::hasParam( const QString &key ) const
751 {
752  return mParams.contains( key );
753 }
QString schema() const
Returns the schema.
void setUsername(const QString &username)
Sets username.
SslMode sslMode() const
Returns the SSL mode.
QString keyColumn() const
Returns the name of the (primary) key column.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QStringList params(const QString &key) const
Gets multiple generic param (generic mode)
void clearSchema()
Clears the schema.
QString driver() const
Returns the driver.
static SslMode decodeSslMode(const QString &sslMode)
Decodes SSL mode string into enum value.
QgsWkbTypes::Type wkbType() const
The wkb type.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
QString host() const
Returns the host.
QString port() const
Returns the port.
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 param(const QString &key) const
Gets generic param (generic mode)
QString database() const
Returns the database.
QString connectionInfo(bool expandAuthConfig=true) const
Returns connection part of URI.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
bool selectAtIdDisabled() const
Returns whether the selection by id is disabled.
QString uri(bool expandAuthConfig=true) const
Returns complete uri.
QgsDataSourceUri()
default constructor
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:39
QString authConfigId() const
Any associated authentication configuration ID.
QString srid() const
Returns the srid.
void setKeyColumn(const QString &column)
Sets the name of the (primary) key column.
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)
static QString encodeSslMode(SslMode sslMode)
Encodes SSL mode enum value into a string.
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
void setAuthConfigId(const QString &authcfg)
Sets authentication configuration ID.
QByteArray encodedUri() const
Returns complete encoded uri (generic mode)
QString quotedTablename() const
quoted table name
void setSrid(const QString &srid)
Sets the srid.
void setWkbType(QgsWkbTypes::Type type)
Sets the wkb type.
bool useEstimatedMetadata() const
Returns true if estimated metadata are used.
static QgsAuthManager * authManager()
Returns the application&#39;s authentication manager instance.
void disableSelectAtId(bool flag)
Sets to true to disable selection by id.
QString geometryColumn() const
Returns the name of the geometry column.
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.
void setPassword(const QString &password)
Sets password.
QString sql() const
Returns the SQL query.
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
bool hasParam(const QString &key) const
Test if param exists (generic mode)
void setSchema(const QString &schema)
Sets the table schema.
QString service() const
Returns the service name.
QString table() const
Returns the table.
void setUseEstimatedMetadata(bool flag)
Sets use Estimated Metadata.
void setDatabase(const QString &database)
Sets database.
QString username() const
Returns the username.
static QString removePassword(const QString &aUri)
Removes password element from uris.
QString password() const
Returns the password.