QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 "qgslogger.h"
21 #include "qgswkbtypes.h"
22 
23 #include <QStringList>
24 #include <QRegExp>
25 #include <QUrl>
26 
28  : mSSLmode( SSLprefer )
29  , mKeyColumn( "" )
30  , mUseEstimatedMetadata( false )
31  , mSelectAtIdDisabled( false )
32  , mWkbType( QGis::WKBUnknown )
33 {
34  // do nothing
35 }
36 
38  : mSSLmode( SSLprefer )
39  , mKeyColumn( "" )
40  , mUseEstimatedMetadata( false )
41  , mSelectAtIdDisabled( false )
42  , mWkbType( QGis::WKBUnknown )
43 {
44  int i = 0;
45  while ( i < uri.length() )
46  {
47  skipBlanks( uri, i );
48 
49  if ( uri[i] == '=' )
50  {
51  QgsDebugMsg( "parameter name expected before =" );
52  i++;
53  continue;
54  }
55 
56  int start = i;
57 
58  while ( i < uri.length() && uri[i] != '=' && !uri[i].isSpace() )
59  i++;
60 
61  QString pname = uri.mid( start, i - start );
62 
63  skipBlanks( uri, i );
64 
65  if ( i == uri.length() || uri[i] != '=' )
66  {
67  QgsDebugMsg( "= expected after parameter name" );
68  return;
69  }
70 
71  i++;
72 
73  if ( pname == "sql" )
74  {
75  // rest of line is a sql where clause
76  skipBlanks( uri, i );
77  mSql = uri.mid( i );
78  break;
79  }
80  else
81  {
82  QString pval = getValue( uri, i );
83 
84  if ( pname == "table" )
85  {
86  if ( uri[i] == '.' )
87  {
88  i++;
89 
90  mSchema = pval;
91  mTable = getValue( uri, i );
92  }
93  else
94  {
95  mSchema = "";
96  mTable = pval;
97  }
98 
99  if ( uri[i] == '(' )
100  {
101  i++;
102 
103  int start = i;
104  QString col;
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::WkbType )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 == "user" )
153  {
154  mUsername = pval;
155  }
156  else if ( pname == "password" )
157  {
158  mPassword = pval;
159  }
160  else if ( pname == "connect_timeout" )
161  {
162  QgsDebugMsg( "connection timeout ignored" );
163  }
164  else if ( pname == "dbname" )
165  {
166  mDatabase = pval;
167  }
168  else if ( pname == "host" )
169  {
170  mHost = pval;
171  }
172  else if ( pname == "hostaddr" )
173  {
174  QgsDebugMsg( "database host ip address ignored" );
175  }
176  else if ( pname == "port" )
177  {
178  mPort = pval;
179  }
180  else if ( pname == "tty" )
181  {
182  QgsDebugMsg( "backend debug tty ignored" );
183  }
184  else if ( pname == "options" )
185  {
186  QgsDebugMsg( "backend debug options ignored" );
187  }
188  else if ( pname == "sslmode" )
189  {
190  if ( pval == "disable" )
191  mSSLmode = SSLdisable;
192  else if ( pval == "allow" )
193  mSSLmode = SSLallow;
194  else if ( pval == "prefer" )
195  mSSLmode = SSLprefer;
196  else if ( pval == "require" )
197  mSSLmode = SSLrequire;
198  }
199  else if ( pname == "requiressl" )
200  {
201  if ( pval == "0" )
202  mSSLmode = SSLdisable;
203  else
204  mSSLmode = SSLprefer;
205  }
206  else if ( pname == "krbsrvname" )
207  {
208  QgsDebugMsg( "kerberos server name ignored" );
209  }
210  else if ( pname == "gsslib" )
211  {
212  QgsDebugMsg( "gsslib ignored" );
213  }
214  else
215  {
216  QgsDebugMsg( "parameter \"" + pname + "\":\"" + pval + "\" added" );
217  setParam( pname, pval );
218  }
219  }
220  }
221 }
222 
224 {
225  QRegExp regexp;
226  regexp.setMinimal( true );
227  QString safeName( aUri );
228  if ( aUri.contains( " password=" ) )
229  {
230  regexp.setPattern( " password=.* " );
231  safeName.replace( regexp, " " );
232  }
233  else if ( aUri.contains( ",password=" ) )
234  {
235  regexp.setPattern( ",password=.*," );
236  safeName.replace( regexp, "," );
237  }
238  else if ( aUri.contains( "IDB:" ) )
239  {
240  regexp.setPattern( " pass=.* " );
241  safeName.replace( regexp, " " );
242  }
243  else if (( aUri.contains( "OCI:" ) )
244  || ( aUri.contains( "ODBC:" ) ) )
245  {
246  regexp.setPattern( "/.*@" );
247  safeName.replace( regexp, "/@" );
248  }
249  else if ( aUri.contains( "SDE:" ) )
250  {
251  QStringList strlist = aUri.split( "," );
252  safeName = strlist[0] + "," + strlist[1] + "," + strlist[2] + "," + strlist[3];
253  }
254  return safeName;
255 }
256 
258 {
259  return mUsername;
260 }
261 
263 {
264  mUsername = username;
265 }
266 
268 {
269  return mService;
270 }
271 
273 {
274  return mHost;
275 }
276 
278 {
279  return mDatabase;
280 }
281 
283 {
284  return mPassword;
285 }
286 
288 {
289  mPassword = password;
290 }
291 
293 {
294  return mPort;
295 }
296 
298 {
299  return mSSLmode;
300 }
301 
303 {
304  return mSchema;
305 }
306 
308 {
309  return mTable;
310 }
311 
313 {
314  return mSql;
315 }
316 
318 {
319  return mGeometryColumn;
320 }
321 
323 {
324  return mKeyColumn;
325 }
326 
328 {
329  mKeyColumn = column;
330 }
331 
332 
334 {
335  mUseEstimatedMetadata = theFlag;
336 }
337 
339 {
340  return mUseEstimatedMetadata;
341 }
342 
344 {
345  mSelectAtIdDisabled = theFlag;
346 }
347 
349 {
350  return mSelectAtIdDisabled;
351 }
352 
354 {
355  mSql = sql;
356 }
357 
359 {
360  mSchema = "";
361 }
362 
363 QString QgsDataSourceURI::escape( const QString &theVal, QChar delim = '\'' ) const
364 {
365  QString val = theVal;
366 
367  val.replace( "\\", "\\\\" );
368  val.replace( delim, QString( "\\%1" ).arg( delim ) );
369 
370  return val;
371 }
372 
373 void QgsDataSourceURI::skipBlanks( const QString &uri, int &i )
374 {
375  // skip space before value
376  while ( i < uri.length() && uri[i].isSpace() )
377  i++;
378 }
379 
380 QString QgsDataSourceURI::getValue( const QString &uri, int &i )
381 {
382  skipBlanks( uri, i );
383 
384  // Get the parameter value
385  QString pval;
386  if ( i < uri.length() && ( uri[i] == '\'' || uri[i] == '"' ) )
387  {
388  QChar delim = uri[i];
389 
390  i++;
391 
392  // value is quoted
393  for ( ;; )
394  {
395  if ( i == uri.length() )
396  {
397  QgsDebugMsg( "unterminated quoted string in connection info string" );
398  return pval;
399  }
400 
401  if ( uri[i] == '\\' )
402  {
403  i++;
404  if ( i == uri.length() )
405  continue;
406  if ( uri[i] != delim && uri[i] != '\\' )
407  i--;
408  }
409  else if ( uri[i] == delim )
410  {
411  i++;
412  break;
413  }
414 
415  pval += uri[i++];
416  }
417  }
418  else
419  {
420  // value is not quoted
421  while ( i < uri.length() )
422  {
423  if ( uri[i].isSpace() )
424  {
425  // end of value
426  break;
427  }
428 
429  if ( uri[i] == '\\' )
430  {
431  i++;
432  if ( i == uri.length() )
433  break;
434  if ( uri[i] != '\\' && uri[i] != '\'' )
435  i--;
436  }
437 
438  pval += uri[i++];
439  }
440  }
441 
442  skipBlanks( uri, i );
443 
444  return pval;
445 }
446 
448 {
449  QStringList connectionItems;
450 
451  if ( mDatabase != "" )
452  {
453  connectionItems << "dbname='" + escape( mDatabase ) + "'";
454  }
455 
456  if ( mService != "" )
457  {
458  connectionItems << "service='" + escape( mService ) + "'";
459  }
460  else if ( mHost != "" )
461  {
462  connectionItems << "host=" + mHost;
463  }
464 
465  if ( mService.isEmpty() )
466  {
467  if ( mPort != "" )
468  connectionItems << "port=" + mPort;
469  }
470 
471  if ( mUsername != "" )
472  {
473  connectionItems << "user='" + escape( mUsername ) + "'";
474 
475  if ( mPassword != "" )
476  {
477  connectionItems << "password='" + escape( mPassword ) + "'";
478  }
479  }
480 
481  if ( mSSLmode == SSLdisable )
482  connectionItems << "sslmode=disable";
483  else if ( mSSLmode == SSLallow )
484  connectionItems << "sslmode=allow";
485  else if ( mSSLmode == SSLrequire )
486  connectionItems << "sslmode=require";
487 #if 0
488  else if ( mSSLmode == SSLprefer )
489  connectionItems << "sslmode=prefer";
490 #endif
491 
492  return connectionItems.join( " " );
493 }
494 
496 {
497  QString theUri = connectionInfo();
498 
499  if ( !mKeyColumn.isEmpty() )
500  {
501  theUri += QString( " key='%1'" ).arg( escape( mKeyColumn ) );
502  }
503 
504  if ( mUseEstimatedMetadata )
505  {
506  theUri += QString( " estimatedmetadata=true" );
507  }
508 
509  if ( !mSrid.isEmpty() )
510  {
511  theUri += QString( " srid=%1" ).arg( mSrid );
512  }
513 
514  if ( mWkbType != QGis::WKBUnknown && mWkbType != QGis::WKBNoGeometry )
515  {
516  theUri += " type=";
518  }
519 
520  if ( mSelectAtIdDisabled )
521  {
522  theUri += QString( " selectatid=false" );
523  }
524 
525  for ( QMap<QString, QString>::const_iterator it = mParams.begin(); it != mParams.end(); ++it )
526  {
527  if ( it.key().contains( "=" ) || it.key().contains( " " ) )
528  {
529  QgsDebugMsg( QString( "invalid uri parameter %1 skipped" ).arg( it.key() ) );
530  continue;
531  }
532 
533  theUri += " " + it.key() + "='" + escape( it.value() ) + "'";
534  }
535 
536  QString columnName( mGeometryColumn );
537  columnName.replace( "\\", "\\\\" );
538  columnName.replace( ")", "\\)" );
539 
540  theUri += QString( " table=%1%2 sql=%3" )
541  .arg( quotedTablename() )
542  .arg( mGeometryColumn.isNull() ? QString() : QString( " (%1)" ).arg( columnName ) )
543  .arg( mSql );
544 
545  return theUri;
546 }
547 
549 {
550  QUrl url;
551  foreach ( QString key, mParams.uniqueKeys() )
552  {
553  foreach ( QString value, mParams.values( key ) )
554  {
555  url.addQueryItem( key, value );
556  }
557  }
558  return url.encodedQuery();
559 }
560 
562 {
563  mParams.clear();
564  QUrl url;
565  url.setEncodedQuery( uri );
567  foreach ( item, url.queryItems() )
568  {
569  mParams.insertMulti( item.first, item.second );
570  }
571 }
572 
574 {
575  setEncodedUri( uri.toAscii() );
576 }
577 
579 {
580  if ( !mSchema.isEmpty() )
581  return QString( "\"%1\".\"%2\"" )
582  .arg( escape( mSchema, '"' ) )
583  .arg( escape( mTable, '"' ) );
584  else
585  return QString( "\"%1\"" )
586  .arg( escape( mTable, '"' ) );
587 }
588 
590  const QString &port,
591  const QString &database,
592  const QString &username,
593  const QString &password,
594  SSLmode sslmode )
595 {
596  mHost = host;
597  mDatabase = database;
598  mPort = port;
599  mUsername = username;
600  mPassword = password;
601  mSSLmode = sslmode;
602 }
603 
605  const QString &database,
606  const QString &username,
607  const QString &password,
608  SSLmode sslmode )
609 {
610  mService = service;
611  mDatabase = database;
612  mUsername = username;
613  mPassword = password;
614  mSSLmode = sslmode;
615 }
616 
618  const QString &table,
619  const QString &geometryColumn,
620  const QString &sql,
621  const QString &keyColumn )
622 {
623  mSchema = schema;
624  mTable = table;
625  mGeometryColumn = geometryColumn;
626  mSql = sql;
627  mKeyColumn = keyColumn;
628 }
629 
630 void QgsDataSourceURI::setDatabase( const QString &database )
631 {
632  mDatabase = database;
633 }
634 
636 {
637  return mWkbType;
638 }
639 
641 {
642  mWkbType = wkbType;
643 }
644 
646 {
647  return mSrid;
648 }
649 
651 {
652  mSrid = srid;
653 }
654 
655 void QgsDataSourceURI::setParam( const QString &key, const QString &value )
656 {
657  // may be multiple
658  mParams.insertMulti( key, value );
659 }
660 
661 void QgsDataSourceURI::setParam( const QString &key, const QStringList &value )
662 {
663  foreach ( QString val, value )
664  {
665  mParams.insertMulti( key, val );
666  }
667 }
668 
670 {
671  return mParams.remove( key );
672 }
673 
675 {
676  return mParams.value( key );
677 }
678 
680 {
681  return mParams.values( key );
682 }
683 
684 bool QgsDataSourceURI::hasParam( const QString &key ) const
685 {
686  return mParams.contains( key );
687 }
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)
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.
QString connectionInfo() const
return connection part of URI
The QGis class provides global constants for use throughout the application.
Definition: qgis.h:34
QString join(const QString &separator) const
WkbType
Used for symbology operations.
Definition: qgis.h:53
void clear()
bool useEstimatedMetadata() const
bool isNull() const
QStringList params(const QString &key) const
Get multiple generic param (generic mode)
QString keyColumn() const
void setPattern(const QString &pattern)
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SSLmode sslmode=SSLprefer)
Set all connection related members at once.
void setPassword(QString password)
set password
static Type flatType(Type type)
Definition: qgswkbtypes.cpp:46
iterator insertMulti(const Key &key, const T &value)
void disableSelectAtId(bool theFlag)
QGis::WkbType wkbType() const
QString uri() const
return complete uri
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
bool hasParam(const QString &key) const
Test if param exists (generic mode)
bool isEmpty() const
void setSrid(QString srid)
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)
QString service() const
QString & replace(int position, int n, QChar after)
void setKeyColumn(QString column)
void setEncodedQuery(const QByteArray &query)
void setUsername(QString username)
set username
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
QByteArray encodedUri() const
return complete encoded uri (generic mode)
static Type parseType(const QString &wktStr)
Definition: qgswkbtypes.cpp:56
static QString displayString(Type type)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void setSql(QString sql)
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