QGIS API Documentation  2.15.0-Master (94d88e6)
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 }
QString srid() const
Returns the srid.
QString database() const
Returns the database.
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
QString quotedTablename() const
quoted table name
QString geometryColumn() const
Return the name of the geometry column.
void setMinimal(bool minimal)
void setEncodedUri(const QByteArray &uri)
set complete encoded uri (generic mode)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static QString removePassword(const QString &aUri)
Removes password element from uris.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QString password() const
Returns the password.
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.
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.
bool useEstimatedMetadata() const
Returns true if estimated metadata are used.
bool isNull() const
QStringList params(const QString &key) const
Get multiple generic param (generic mode)
void setKeyColumn(const QString &column)
Sets the name of the (primary) key column.
QString keyColumn() const
Returns the name of the (primary) key column.
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
iterator insertMulti(const Key &key, const T &value)
void disableSelectAtId(bool theFlag)
Set to true to disable selection by id.
QString authConfigId() const
Any associated authentication configuration ID.
Q_DECL_DEPRECATED QGis::WkbType wkbType() const
The (old) wkb type.
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
void setUseEstimatedMetadata(bool theFlag)
set use Estimated Metadata
enum SSLmode sslMode() const
Returns the SSL mode.
void setSchema(const QString &schema)
set the table schema
bool hasParam(const QString &key) const
Test if param exists (generic mode)
QString connectionInfo(bool expandAuthConfig=true) const
return connection part of URI
bool isEmpty() const
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.
void setAuthConfigId(const QString &authcfg)
Set authentication configuration ID.
iterator end()
iterator begin()
QString host() const
Returns the host.
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QString schema() const
Returns the schema.
void clearSchema()
Clears the schema.
QString param(const QString &key) const
Get generic param (generic mode)
void setDriver(const QString &driver)
Sets the driver name.
void setUsername(const QString &username)
set username
QString service() const
Returns the service name.
QString & replace(int position, int n, QChar after)
void setEncodedQuery(const QByteArray &query)
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 table() const
Returns the table.
QByteArray encodedQuery() const
int length() const
bool selectAtIdDisabled() const
Returns whether the selection by id is disabled.
void addQueryItem(const QString &key, const QString &value)
QString sql() const
Returns the SQL query.
QByteArray encodedUri() const
return complete encoded uri (generic mode)
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 uri(bool expandAuthConfig=true) const
return complete uri
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QgsWKBTypes::Type newWkbType() const
The wkb type.
QString username() const
Returns the username.
QString port() const
Returns the port.
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.