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