QGIS API Documentation  2.17.0-Master (0497e4a)
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( "" )
31  , mUseEstimatedMetadata( false )
32  , mSelectAtIdDisabled( false )
33  , mWkbType( QgsWKBTypes::Unknown )
34 {
35  // do nothing
36 }
37 
39  : mSSLmode( SSLprefer )
40  , mKeyColumn( "" )
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 == "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 == "table" )
86  {
87  if ( uri[i] == '.' )
88  {
89  i++;
90 
91  mSchema = pval;
92  mTable = getValue( uri, i );
93  }
94  else
95  {
96  mSchema = "";
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( "\\)", ")" );
119  mGeometryColumn.replace( "\\\\", "\\" );
120 
121  i++;
122  }
123  else
124  {
125  mGeometryColumn = QString::null;
126  }
127  }
128  else if ( pname == "key" )
129  {
130  mKeyColumn = pval;
131  }
132  else if ( pname == "estimatedmetadata" )
133  {
134  mUseEstimatedMetadata = pval == "true";
135  }
136  else if ( pname == "srid" )
137  {
138  mSrid = pval;
139  }
140  else if ( pname == "type" )
141  {
142  mWkbType = QgsWKBTypes::parseType( pval );
143  }
144  else if ( pname == "selectatid" )
145  {
146  mSelectAtIdDisabled = pval == "false";
147  }
148  else if ( pname == "service" )
149  {
150  mService = pval;
151  }
152  else if ( pname == "authcfg" )
153  {
154  mAuthConfigId = pval;
155  }
156  else if ( pname == "user" )
157  {
158  mUsername = pval;
159  }
160  else if ( pname == "password" )
161  {
162  mPassword = pval;
163  }
164  else if ( pname == "connect_timeout" )
165  {
166  QgsDebugMsg( "connection timeout ignored" );
167  }
168  else if ( pname == "dbname" )
169  {
170  mDatabase = pval;
171  }
172  else if ( pname == "host" )
173  {
174  mHost = pval;
175  }
176  else if ( pname == "hostaddr" )
177  {
178  QgsDebugMsg( "database host ip address ignored" );
179  }
180  else if ( pname == "port" )
181  {
182  mPort = pval;
183  }
184  else if ( pname == "driver" )
185  {
186  mDriver = pval;
187  }
188  else if ( pname == "tty" )
189  {
190  QgsDebugMsg( "backend debug tty ignored" );
191  }
192  else if ( pname == "options" )
193  {
194  QgsDebugMsg( "backend debug options ignored" );
195  }
196  else if ( pname == "sslmode" )
197  {
198  if ( pval == "disable" )
199  mSSLmode = SSLdisable;
200  else if ( pval == "allow" )
201  mSSLmode = SSLallow;
202  else if ( pval == "prefer" )
203  mSSLmode = SSLprefer;
204  else if ( pval == "require" )
205  mSSLmode = SSLrequire;
206  else if ( pval == "verify-ca" )
207  mSSLmode = SSLverifyCA;
208  else if ( pval == "verify-full" )
209  mSSLmode = SSLverifyFull;
210  }
211  else if ( pname == "requiressl" )
212  {
213  if ( pval == "0" )
214  mSSLmode = SSLdisable;
215  else
216  mSSLmode = SSLprefer;
217  }
218  else if ( pname == "krbsrvname" )
219  {
220  QgsDebugMsg( "kerberos server name ignored" );
221  }
222  else if ( pname == "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 
236 {
237  QRegExp regexp;
238  regexp.setMinimal( true );
239  QString safeName( aUri );
240  if ( aUri.contains( " password=" ) )
241  {
242  regexp.setPattern( " password=.* " );
243  safeName.replace( regexp, " " );
244  }
245  else if ( aUri.contains( ",password=" ) )
246  {
247  regexp.setPattern( ",password=.*," );
248  safeName.replace( regexp, "," );
249  }
250  else if ( aUri.contains( "IDB:" ) )
251  {
252  regexp.setPattern( " pass=.* " );
253  safeName.replace( regexp, " " );
254  }
255  else if (( aUri.contains( "OCI:" ) )
256  || ( aUri.contains( "ODBC:" ) ) )
257  {
258  regexp.setPattern( "/.*@" );
259  safeName.replace( regexp, "/@" );
260  }
261  else if ( aUri.contains( "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 
290 {
291  return mHost;
292 }
293 
295 {
296  return mDatabase;
297 }
298 
300 {
301  return mPassword;
302 }
303 
305 {
306  mPassword = password;
307 }
308 
310 {
311  return mPort;
312 }
313 
315 {
316  return mDriver;
317 }
318 
320 {
321  return mSSLmode;
322 }
323 
325 {
326  return mSchema;
327 }
328 
330 {
331  return mTable;
332 }
333 
335 {
336  return mSql;
337 }
338 
340 {
341  return mGeometryColumn;
342 }
343 
345 {
346  return mKeyColumn;
347 }
348 
349 
351 {
352  mDriver = driver;
353 }
354 
355 
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 
383 {
384  mSql = sql;
385 }
386 
388 {
389  mSchema = "";
390 }
391 
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( '\\', "\\\\" );
402  val.replace( delim, QString( "\\%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 != "" )
486  {
487  connectionItems << "dbname='" + escape( mDatabase ) + '\'';
488  }
489 
490  if ( mService != "" )
491  {
492  connectionItems << "service='" + escape( mService ) + '\'';
493  }
494  else if ( mHost != "" )
495  {
496  connectionItems << "host=" + mHost;
497  }
498 
499  if ( mService.isEmpty() )
500  {
501  if ( mPort != "" )
502  connectionItems << "port=" + mPort;
503  }
504 
505  if ( mDriver != "" )
506  {
507  connectionItems << "driver='" + escape( mDriver ) + '\'';
508  }
509 
510  if ( mUsername != "" )
511  {
512  connectionItems << "user='" + escape( mUsername ) + '\'';
513 
514  if ( mPassword != "" )
515  {
516  connectionItems << "password='" + escape( mPassword ) + '\'';
517  }
518  }
519 
520  if ( mSSLmode == SSLdisable )
521  connectionItems << "sslmode=disable";
522  else if ( mSSLmode == SSLallow )
523  connectionItems << "sslmode=allow";
524  else if ( mSSLmode == SSLrequire )
525  connectionItems << "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 << "sslmode=verify-ca";
532  else if ( mSSLmode == SSLverifyFull )
533  connectionItems << "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( " " );
551 }
552 
553 QString QgsDataSourceURI::uri( bool expandAuthConfig ) const
554 {
555  QString theUri = connectionInfo( expandAuthConfig );
556 
557  if ( !mKeyColumn.isEmpty() )
558  {
559  theUri += QString( " key='%1'" ).arg( escape( mKeyColumn ) );
560  }
561 
562  if ( mUseEstimatedMetadata )
563  {
564  theUri += QString( " estimatedmetadata=true" );
565  }
566 
567  if ( !mSrid.isEmpty() )
568  {
569  theUri += QString( " srid=%1" ).arg( mSrid );
570  }
571 
572  if ( mWkbType != QgsWKBTypes::Unknown && mWkbType != QgsWKBTypes::NoGeometry )
573  {
574  theUri += " type=";
575  theUri += QgsWKBTypes::displayString( mWkbType );
576  }
577 
578  if ( mSelectAtIdDisabled )
579  {
580  theUri += QString( " 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( '\\', "\\\\" );
596  columnName.replace( ')', "\\)" );
597 
598  theUri += QString( " table=%1%2 sql=%3" )
599  .arg( quotedTablename(),
600  mGeometryColumn.isNull() ? QString() : QString( " (%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 
620 {
621  mParams.clear();
622  QUrl url;
623  url.setEncodedQuery( uri );
625  Q_FOREACH ( item, url.queryItems() )
626  {
627  mParams.insertMulti( item.first, item.second );
628  }
629 }
630 
632 {
633  setEncodedUri( uri.toAscii() );
634 }
635 
637 {
638  if ( !mSchema.isEmpty() )
639  return QString( "\"%1\".\"%2\"" )
640  .arg( escape( mSchema, '"' ),
641  escape( mTable, '"' ) );
642  else
643  return QString( "\"%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 
693 {
694  mAuthConfigId = authcfg;
695 }
696 
698 {
699  mDatabase = database;
700 }
701 
703 {
704  return QGis::fromNewWkbType( mWkbType );
705 }
706 
708 {
709  return mWkbType;
710 }
711 
713 {
714  mWkbType = QGis::fromOldWkbType( wkbType );
715 }
716 
718 {
719  mWkbType = wkbType;
720 }
721 
723 {
724  return mSrid;
725 }
726 
728 {
729  mSrid = srid;
730 }
731 
732 void QgsDataSourceURI::setParam( const QString &key, const QString &value )
733 {
734  // may be multiple
735  mParams.insertMulti( key, value );
736 }
737 
738 void QgsDataSourceURI::setParam( const QString &key, const QStringList &value )
739 {
740  Q_FOREACH ( const QString& val, value )
741  {
742  mParams.insertMulti( key, val );
743  }
744 }
745 
747 {
748  return mParams.remove( key );
749 }
750 
752 {
753  return mParams.value( key );
754 }
755 
757 {
758  return mParams.values( key );
759 }
760 
761 bool QgsDataSourceURI::hasParam( const QString &key ) const
762 {
763  return mParams.contains( key );
764 }
bool selectAtIdDisabled() const
Returns whether the selection by id is disabled.
QgsDataSourceURI()
default constructor
bool contains(const Key &key) const
int removeParam(const QString &key)
Remove generic param (generic mode)
static QgsAuthManager * instance()
Enforce singleton pattern.
QList< T > values() const
void setMinimal(bool minimal)
void setEncodedUri(const QByteArray &uri)
set complete encoded uri (generic mode)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QString param(const QString &key) const
Get generic param (generic mode)
static QString removePassword(const QString &aUri)
Removes password element from uris.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QList< QPair< QString, QString > > queryItems() const
void setDatabase(const QString &database)
Set database.
static QGis::WkbType fromNewWkbType(QgsWKBTypes::Type type)
Converts from new (post 2.10) WKB type (OGC) to old WKB type.
Definition: qgis.cpp:146
void setSrid(const QString &srid)
Sets the srid.
enum SSLmode sslMode() const
Returns the SSL mode.
WkbType
Used for symbology operations.
Definition: qgis.h:61
QString join(const QString &separator) const
void clear()
void setSql(const QString &sql)
Sets the SQL query.
QString keyColumn() const
Returns the name of the (primary) key column.
bool isNull() const
void setKeyColumn(const QString &column)
Sets the name of the (primary) key column.
QString port() const
Returns the port.
void setPattern(const QString &pattern)
static QgsWKBTypes::Type fromOldWkbType(QGis::WkbType type)
Converts from old (pre 2.10) WKB type (OGR) to new WKB type.
Definition: qgis.cpp:106
QString password() const
Returns the password.
Q_DECL_DEPRECATED QGis::WkbType wkbType() const
The (old) wkb type.
iterator insertMulti(const Key &key, const T &value)
void disableSelectAtId(bool theFlag)
Set to true to disable selection by id.
QString geometryColumn() const
Return the name of the geometry column.
QString schema() const
Returns the schema.
bool hasParam(const QString &key) const
Test if param exists (generic mode)
QString database() const
Returns the database.
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
void setUseEstimatedMetadata(bool theFlag)
set use Estimated Metadata
QString srid() const
Returns the srid.
void setSchema(const QString &schema)
set the table schema
bool isEmpty() const
QString service() const
Returns the service name.
bool updateDataSourceUriItems(QStringList &connectionItems, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QgsDataSourceURI with an authentication config.
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 uri(bool expandAuthConfig=true) const
return complete uri
QString sql() const
Returns the SQL query.
void setAuthConfigId(const QString &authcfg)
Set authentication configuration ID.
iterator end()
QString quotedTablename() const
quoted table name
iterator begin()
bool contains(QChar ch, Qt::CaseSensitivity cs) const
void clearSchema()
Clears the schema.
QString username() const
Returns the username.
QByteArray encodedUri() const
return complete encoded uri (generic mode)
void setDriver(const QString &driver)
Sets the driver name.
void setUsername(const QString &username)
set username
QString & replace(int position, int n, QChar after)
void setEncodedQuery(const QByteArray &query)
QgsWKBTypes::Type newWkbType() const
The wkb type.
QString mid(int position, int n) const
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:36
Q_DECL_DEPRECATED void setWkbType(QGis::WkbType type)
QString host() const
Returns the host.
QByteArray encodedQuery() const
QString table() const
Returns the table.
int length() const
QString authConfigId() const
Any associated authentication configuration ID.
void addQueryItem(const QString &key, const QString &value)
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
Definition: qgswkbtypes.cpp:32
void setPassword(const QString &password)
set password
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 connectionInfo(bool expandAuthConfig=true) const
return connection part of URI
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
bool useEstimatedMetadata() const
Returns true if estimated metadata are used.
QStringList params(const QString &key) const
Get multiple generic param (generic mode)
QByteArray toAscii() const
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.
const T value(const Key &key) const
int remove(const Key &key)
QList< Key > uniqueKeys() const
QString driver() const
Returns the driver.