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