QGIS API Documentation  2.13.0-Master
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( QGis::WKBUnknown )
34 {
35  // do nothing
36 }
37 
39  : mSSLmode( SSLprefer )
40  , mKeyColumn( "" )
41  , mUseEstimatedMetadata( false )
42  , mSelectAtIdDisabled( false )
43  , mWkbType( QGis::WKBUnknown )
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 = QGis::fromNewWkbType( 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 == "tty" )
185  {
186  QgsDebugMsg( "backend debug tty ignored" );
187  }
188  else if ( pname == "options" )
189  {
190  QgsDebugMsg( "backend debug options ignored" );
191  }
192  else if ( pname == "sslmode" )
193  {
194  if ( pval == "disable" )
195  mSSLmode = SSLdisable;
196  else if ( pval == "allow" )
197  mSSLmode = SSLallow;
198  else if ( pval == "prefer" )
199  mSSLmode = SSLprefer;
200  else if ( pval == "require" )
201  mSSLmode = SSLrequire;
202  }
203  else if ( pname == "requiressl" )
204  {
205  if ( pval == "0" )
206  mSSLmode = SSLdisable;
207  else
208  mSSLmode = SSLprefer;
209  }
210  else if ( pname == "krbsrvname" )
211  {
212  QgsDebugMsg( "kerberos server name ignored" );
213  }
214  else if ( pname == "gsslib" )
215  {
216  QgsDebugMsg( "gsslib ignored" );
217  }
218  else
219  {
220  QgsDebugMsg( "parameter \"" + pname + "\":\"" + pval + "\" added" );
221  setParam( pname, pval );
222  }
223  }
224  }
225 }
226 
228 {
229  QRegExp regexp;
230  regexp.setMinimal( true );
231  QString safeName( aUri );
232  if ( aUri.contains( " password=" ) )
233  {
234  regexp.setPattern( " password=.* " );
235  safeName.replace( regexp, " " );
236  }
237  else if ( aUri.contains( ",password=" ) )
238  {
239  regexp.setPattern( ",password=.*," );
240  safeName.replace( regexp, "," );
241  }
242  else if ( aUri.contains( "IDB:" ) )
243  {
244  regexp.setPattern( " pass=.* " );
245  safeName.replace( regexp, " " );
246  }
247  else if (( aUri.contains( "OCI:" ) )
248  || ( aUri.contains( "ODBC:" ) ) )
249  {
250  regexp.setPattern( "/.*@" );
251  safeName.replace( regexp, "/@" );
252  }
253  else if ( aUri.contains( "SDE:" ) )
254  {
255  QStringList strlist = aUri.split( ',' );
256  safeName = strlist[0] + ',' + strlist[1] + ',' + strlist[2] + ',' + strlist[3];
257  }
258  return safeName;
259 }
260 
262 {
263  return mAuthConfigId;
264 }
265 
267 {
268  return mUsername;
269 }
270 
272 {
273  mUsername = username;
274 }
275 
277 {
278  return mService;
279 }
280 
282 {
283  return mHost;
284 }
285 
287 {
288  return mDatabase;
289 }
290 
292 {
293  return mPassword;
294 }
295 
297 {
298  mPassword = password;
299 }
300 
302 {
303  return mPort;
304 }
305 
307 {
308  return mSSLmode;
309 }
310 
312 {
313  return mSchema;
314 }
315 
317 {
318  return mTable;
319 }
320 
322 {
323  return mSql;
324 }
325 
327 {
328  return mGeometryColumn;
329 }
330 
332 {
333  return mKeyColumn;
334 }
335 
337 {
338  mKeyColumn = column;
339 }
340 
341 
343 {
344  mUseEstimatedMetadata = theFlag;
345 }
346 
348 {
349  return mUseEstimatedMetadata;
350 }
351 
353 {
354  mSelectAtIdDisabled = theFlag;
355 }
356 
358 {
359  return mSelectAtIdDisabled;
360 }
361 
363 {
364  mSql = sql;
365 }
366 
368 {
369  mSchema = "";
370 }
371 
373 {
374  mSchema = schema;
375 }
376 
377 QString QgsDataSourceURI::escape( const QString &theVal, QChar delim = '\'' ) const
378 {
379  QString val = theVal;
380 
381  val.replace( '\\', "\\\\" );
382  val.replace( delim, QString( "\\%1" ).arg( delim ) );
383 
384  return val;
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( "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 != "" )
466  {
467  connectionItems << "dbname='" + escape( mDatabase ) + '\'';
468  }
469 
470  if ( mService != "" )
471  {
472  connectionItems << "service='" + escape( mService ) + '\'';
473  }
474  else if ( mHost != "" )
475  {
476  connectionItems << "host=" + mHost;
477  }
478 
479  if ( mService.isEmpty() )
480  {
481  if ( mPort != "" )
482  connectionItems << "port=" + mPort;
483  }
484 
485  if ( mUsername != "" )
486  {
487  connectionItems << "user='" + escape( mUsername ) + '\'';
488 
489  if ( mPassword != "" )
490  {
491  connectionItems << "password='" + escape( mPassword ) + '\'';
492  }
493  }
494 
495  if ( mSSLmode == SSLdisable )
496  connectionItems << "sslmode=disable";
497  else if ( mSSLmode == SSLallow )
498  connectionItems << "sslmode=allow";
499  else if ( mSSLmode == SSLrequire )
500  connectionItems << "sslmode=require";
501 #if 0
502  else if ( mSSLmode == SSLprefer )
503  connectionItems << "sslmode=prefer";
504 #endif
505 
506  if ( !mAuthConfigId.isEmpty() )
507  {
508  if ( expandAuthConfig )
509  {
510  if ( !QgsAuthManager::instance()->updateDataSourceUriItems( connectionItems, mAuthConfigId ) )
511  {
512  QgsDebugMsg( QString( "Data source URI FAILED to update via loading configuration ID '%1'" ).arg( mAuthConfigId ) );
513  }
514  }
515  else
516  {
517  connectionItems << "authcfg=" + mAuthConfigId;
518  }
519  }
520 
521  return connectionItems.join( " " );
522 }
523 
524 QString QgsDataSourceURI::uri( bool expandAuthConfig ) const
525 {
526  QString theUri = connectionInfo( expandAuthConfig );
527 
528  if ( !mKeyColumn.isEmpty() )
529  {
530  theUri += QString( " key='%1'" ).arg( escape( mKeyColumn ) );
531  }
532 
533  if ( mUseEstimatedMetadata )
534  {
535  theUri += QString( " estimatedmetadata=true" );
536  }
537 
538  if ( !mSrid.isEmpty() )
539  {
540  theUri += QString( " srid=%1" ).arg( mSrid );
541  }
542 
543  if ( mWkbType != QGis::WKBUnknown && mWkbType != QGis::WKBNoGeometry )
544  {
545  theUri += " type=";
547  }
548 
549  if ( mSelectAtIdDisabled )
550  {
551  theUri += QString( " selectatid=false" );
552  }
553 
554  for ( QMap<QString, QString>::const_iterator it = mParams.begin(); it != mParams.end(); ++it )
555  {
556  if ( it.key().contains( '=' ) || it.key().contains( ' ' ) )
557  {
558  QgsDebugMsg( QString( "invalid uri parameter %1 skipped" ).arg( it.key() ) );
559  continue;
560  }
561 
562  theUri += ' ' + it.key() + "='" + escape( it.value() ) + '\'';
563  }
564 
565  QString columnName( mGeometryColumn );
566  columnName.replace( '\\', "\\\\" );
567  columnName.replace( ')', "\\)" );
568 
569  theUri += QString( " table=%1%2 sql=%3" )
570  .arg( quotedTablename(),
571  mGeometryColumn.isNull() ? QString() : QString( " (%1)" ).arg( columnName ),
572  mSql );
573 
574  return theUri;
575 }
576 
578 {
579  QUrl url;
580  Q_FOREACH ( const QString& key, mParams.uniqueKeys() )
581  {
582  Q_FOREACH ( const QString& value, mParams.values( key ) )
583  {
584  url.addQueryItem( key, value );
585  }
586  }
587  return url.encodedQuery();
588 }
589 
591 {
592  mParams.clear();
593  QUrl url;
594  url.setEncodedQuery( uri );
596  Q_FOREACH ( item, url.queryItems() )
597  {
598  mParams.insertMulti( item.first, item.second );
599  }
600 }
601 
603 {
604  setEncodedUri( uri.toAscii() );
605 }
606 
608 {
609  if ( !mSchema.isEmpty() )
610  return QString( "\"%1\".\"%2\"" )
611  .arg( escape( mSchema, '"' ),
612  escape( mTable, '"' ) );
613  else
614  return QString( "\"%1\"" )
615  .arg( escape( mTable, '"' ) );
616 }
617 
619  const QString &port,
620  const QString &database,
621  const QString &username,
622  const QString &password,
623  SSLmode sslmode,
624  const QString &authConfigId )
625 {
626  mHost = host;
627  mDatabase = database;
628  mPort = port;
629  mUsername = username;
630  mPassword = password;
631  mSSLmode = sslmode;
632  mAuthConfigId = authConfigId;
633 }
634 
636  const QString &database,
637  const QString &username,
638  const QString &password,
639  SSLmode sslmode,
640  const QString &authConfigId )
641 {
642  mService = service;
643  mDatabase = database;
644  mUsername = username;
645  mPassword = password;
646  mSSLmode = sslmode;
647  mAuthConfigId = authConfigId;
648 }
649 
651  const QString &table,
652  const QString &geometryColumn,
653  const QString &sql,
654  const QString &keyColumn )
655 {
656  mSchema = schema;
657  mTable = table;
658  mGeometryColumn = geometryColumn;
659  mSql = sql;
660  mKeyColumn = keyColumn;
661 }
662 
664 {
665  mAuthConfigId = authcfg;
666 }
667 
669 {
670  mDatabase = database;
671 }
672 
674 {
675  return mWkbType;
676 }
677 
679 {
680  mWkbType = wkbType;
681 }
682 
684 {
685  return mSrid;
686 }
687 
689 {
690  mSrid = srid;
691 }
692 
693 void QgsDataSourceURI::setParam( const QString &key, const QString &value )
694 {
695  // may be multiple
696  mParams.insertMulti( key, value );
697 }
698 
699 void QgsDataSourceURI::setParam( const QString &key, const QStringList &value )
700 {
701  Q_FOREACH ( const QString& val, value )
702  {
703  mParams.insertMulti( key, val );
704  }
705 }
706 
708 {
709  return mParams.remove( key );
710 }
711 
713 {
714  return mParams.value( key );
715 }
716 
718 {
719  return mParams.values( key );
720 }
721 
722 bool QgsDataSourceURI::hasParam( const QString &key ) const
723 {
724  return mParams.contains( key );
725 }
QString srid() const
QString database() const
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
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
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 to old WKB type.
Definition: qgis.cpp:144
void setSrid(const QString &srid)
WkbType
Used for symbology operations.
Definition: qgis.h:57
The QGis class provides global constants for use throughout the application.
Definition: qgis.h:36
QString join(const QString &separator) const
void clear()
void setSql(const QString &sql)
bool useEstimatedMetadata() const
bool isNull() const
QStringList params(const QString &key) const
Get multiple generic param (generic mode)
void setKeyColumn(const QString &column)
QString keyColumn() const
void setPattern(const QString &pattern)
iterator insertMulti(const Key &key, const T &value)
void disableSelectAtId(bool theFlag)
QString authConfigId() const
Any associated authentication configuration ID.
QGis::WkbType wkbType() const
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
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
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QString schema() const
QString param(const QString &key) const
Get generic param (generic mode)
void setUsername(const QString &username)
set username
QString service() const
QString & replace(int position, int n, QChar after)
void setEncodedQuery(const QByteArray &query)
QString mid(int position, int n) const
void setWkbType(QGis::WkbType type)
QString table() const
QByteArray encodedQuery() const
int length() const
bool selectAtIdDisabled() const
void addQueryItem(const QString &key, const QString &value)
QString sql() const
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
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:46
QString uri(bool expandAuthConfig=true) const
return complete uri
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString username() const
QString port() const
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