QGIS API Documentation  master-3f58142
src/core/qgsdatasourceuri.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002       qgsdatasourceuri.h  -  Structure to contain the component parts
00003                              of a data source URI
00004                              -------------------
00005     begin                : Dec 5, 2004
00006     copyright            : (C) 2004 by Gary E.Sherman
00007     email                : sherman at mrcc.com
00008  ***************************************************************************/
00009 
00010 /***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #include "qgsdatasourceuri.h"
00020 #include "qgslogger.h"
00021 
00022 #include <QStringList>
00023 #include <QRegExp>
00024 #include <QUrl>
00025 
00026 QgsDataSourceURI::QgsDataSourceURI()
00027     : mSSLmode( SSLprefer )
00028     , mKeyColumn( "" )
00029     , mUseEstimatedMetadata( false )
00030     , mSelectAtIdDisabled( false )
00031     , mWkbType( QGis::WKBUnknown )
00032 {
00033   // do nothing
00034 }
00035 
00036 QgsDataSourceURI::QgsDataSourceURI( QString uri )
00037     : mSSLmode( SSLprefer )
00038     , mKeyColumn( "" )
00039     , mUseEstimatedMetadata( false )
00040     , mSelectAtIdDisabled( false )
00041     , mWkbType( QGis::WKBUnknown )
00042 {
00043   int i = 0;
00044   while ( i < uri.length() )
00045   {
00046     skipBlanks( uri, i );
00047 
00048     if ( uri[i] == '=' )
00049     {
00050       QgsDebugMsg( "parameter name expected before =" );
00051       i++;
00052       continue;
00053     }
00054 
00055     int start = i;
00056 
00057     while ( i < uri.length() && uri[i] != '=' && !uri[i].isSpace() )
00058       i++;
00059 
00060     QString pname = uri.mid( start, i - start );
00061 
00062     skipBlanks( uri, i );
00063 
00064     if ( uri[i] != '=' )
00065     {
00066       QgsDebugMsg( "= expected after parameter name" );
00067       return;
00068     }
00069 
00070     i++;
00071 
00072     if ( pname == "sql" )
00073     {
00074       // rest of line is a sql where clause
00075       skipBlanks( uri, i );
00076       mSql = uri.mid( i );
00077       break;
00078     }
00079     else
00080     {
00081       QString pval = getValue( uri, i );
00082 
00083       if ( pname == "table" )
00084       {
00085         if ( uri[i] == '.' )
00086         {
00087           i++;
00088 
00089           mSchema = pval;
00090           mTable = getValue( uri, i );
00091         }
00092         else
00093         {
00094           mSchema = "";
00095           mTable = pval;
00096         }
00097 
00098         if ( uri[i] == '(' )
00099         {
00100           i++;
00101 
00102           int start = i;
00103           QString col;
00104           while ( i < uri.length() && uri[i] != ')' )
00105           {
00106             if ( uri[i] == '\\' )
00107               i++;
00108             i++;
00109           }
00110 
00111           if ( i == uri.length() )
00112           {
00113             QgsDebugMsg( "closing parenthesis missing" );
00114           }
00115 
00116           mGeometryColumn = uri.mid( start, i - start );
00117           mGeometryColumn.replace( "\\)", ")" );
00118           mGeometryColumn.replace( "\\\\", "\\" );
00119 
00120           i++;
00121         }
00122         else
00123         {
00124           mGeometryColumn = QString::null;
00125         }
00126       }
00127       else if ( pname == "key" )
00128       {
00129         mKeyColumn = pval;
00130       }
00131       else if ( pname == "estimatedmetadata" )
00132       {
00133         mUseEstimatedMetadata = pval == "true";
00134       }
00135       else if ( pname == "srid" )
00136       {
00137         mSrid = pval;
00138       }
00139       else if ( pname == "type" )
00140       {
00141         QString geomTypeUpper = pval.toUpper();
00142         if ( geomTypeUpper == "POINT" )
00143         {
00144           mWkbType = QGis::WKBPoint;
00145         }
00146         else if ( geomTypeUpper == "LINESTRING" || geomTypeUpper == "LINE" )
00147         {
00148           mWkbType = QGis::WKBLineString;
00149         }
00150         else if ( geomTypeUpper == "POLYGON" )
00151         {
00152           mWkbType = QGis::WKBPolygon;
00153         }
00154         else if ( geomTypeUpper == "MULTIPOINT" )
00155         {
00156           mWkbType = QGis::WKBMultiPoint;
00157         }
00158         else if ( geomTypeUpper == "MULTILINESTRING" )
00159         {
00160           mWkbType = QGis::WKBMultiLineString;
00161         }
00162         else if ( geomTypeUpper == "MULTIPOLYGON" )
00163         {
00164           mWkbType = QGis::WKBMultiPolygon;
00165         }
00166         else
00167         {
00168           mWkbType = QGis::WKBUnknown;
00169         }
00170       }
00171       else if ( pname == "selectatid" )
00172       {
00173         mSelectAtIdDisabled = pval == "false";
00174       }
00175       else if ( pname == "service" )
00176       {
00177         mService = pval;
00178       }
00179       else if ( pname == "user" )
00180       {
00181         mUsername = pval;
00182       }
00183       else if ( pname == "password" )
00184       {
00185         mPassword = pval;
00186       }
00187       else if ( pname == "connect_timeout" )
00188       {
00189         QgsDebugMsg( "connection timeout ignored" );
00190       }
00191       else if ( pname == "dbname" )
00192       {
00193         mDatabase = pval;
00194       }
00195       else if ( pname == "host" )
00196       {
00197         mHost = pval;
00198       }
00199       else if ( pname == "hostaddr" )
00200       {
00201         QgsDebugMsg( "database host ip address ignored" );
00202       }
00203       else if ( pname == "port" )
00204       {
00205         mPort = pval;
00206       }
00207       else if ( pname == "tty" )
00208       {
00209         QgsDebugMsg( "backend debug tty ignored" );
00210       }
00211       else if ( pname == "options" )
00212       {
00213         QgsDebugMsg( "backend debug options ignored" );
00214       }
00215       else if ( pname == "sslmode" )
00216       {
00217         if ( pval == "disable" )
00218           mSSLmode = SSLdisable;
00219         else if ( pval == "allow" )
00220           mSSLmode = SSLallow;
00221         else if ( pval == "prefer" )
00222           mSSLmode = SSLprefer;
00223         else if ( pval == "require" )
00224           mSSLmode = SSLrequire;
00225       }
00226       else if ( pname == "requiressl" )
00227       {
00228         if ( pval == "0" )
00229           mSSLmode = SSLdisable;
00230         else
00231           mSSLmode = SSLprefer;
00232       }
00233       else if ( pname == "krbsrvname" )
00234       {
00235         QgsDebugMsg( "kerberos server name ignored" );
00236       }
00237       else if ( pname == "gsslib" )
00238       {
00239         QgsDebugMsg( "gsslib ignored" );
00240       }
00241       else
00242       {
00243         QgsDebugMsg( "invalid connection option \"" + pname + "\" ignored" );
00244       }
00245     }
00246   }
00247 }
00248 
00249 QString QgsDataSourceURI::removePassword( const QString& aUri )
00250 {
00251   QRegExp regexp;
00252   regexp.setMinimal( true );
00253   QString safeName( aUri );
00254   if ( aUri.contains( " password=" ) )
00255   {
00256     regexp.setPattern( " password=.* " );
00257     safeName.replace( regexp, " " );
00258   }
00259   else if ( aUri.contains( ",password=" ) )
00260   {
00261     regexp.setPattern( ",password=.*," );
00262     safeName.replace( regexp, "," );
00263   }
00264   else if ( aUri.contains( "IDB:" ) )
00265   {
00266     regexp.setPattern( " pass=.* " );
00267     safeName.replace( regexp, " " );
00268   }
00269   else if (( aUri.contains( "OCI:" ) )
00270            || ( aUri.contains( "ODBC:" ) ) )
00271   {
00272     regexp.setPattern( "/.*@" );
00273     safeName.replace( regexp, "/@" );
00274   }
00275   else if ( aUri.contains( "SDE:" ) )
00276   {
00277     QStringList strlist = aUri.split( "," );
00278     safeName = strlist[0] + "," + strlist[1] + "," + strlist[2] + "," + strlist[3];
00279   }
00280   return safeName;
00281 }
00282 
00283 QString QgsDataSourceURI::username() const
00284 {
00285   return mUsername;
00286 }
00287 
00288 void QgsDataSourceURI::setUsername( QString username )
00289 {
00290   mUsername = username;
00291 }
00292 
00293 QString QgsDataSourceURI::service() const
00294 {
00295   return mService;
00296 }
00297 
00298 QString QgsDataSourceURI::host() const
00299 {
00300   return mHost;
00301 }
00302 
00303 QString QgsDataSourceURI::database() const
00304 {
00305   return mDatabase;
00306 }
00307 
00308 QString QgsDataSourceURI::password() const
00309 {
00310   return mPassword;
00311 }
00312 
00313 void QgsDataSourceURI::setPassword( QString password )
00314 {
00315   mPassword = password;
00316 }
00317 
00318 QString QgsDataSourceURI::port() const
00319 {
00320   return mPort;
00321 }
00322 
00323 QgsDataSourceURI::SSLmode QgsDataSourceURI::sslMode() const
00324 {
00325   return mSSLmode;
00326 }
00327 
00328 QString QgsDataSourceURI::schema() const
00329 {
00330   return mSchema;
00331 }
00332 
00333 QString QgsDataSourceURI::table() const
00334 {
00335   return mTable;
00336 }
00337 
00338 QString QgsDataSourceURI::sql() const
00339 {
00340   return mSql;
00341 }
00342 
00343 QString QgsDataSourceURI::geometryColumn() const
00344 {
00345   return mGeometryColumn;
00346 }
00347 
00348 QString QgsDataSourceURI::keyColumn() const
00349 {
00350   return mKeyColumn;
00351 }
00352 
00353 void QgsDataSourceURI::setKeyColumn( QString column )
00354 {
00355   mKeyColumn = column;
00356 }
00357 
00358 
00359 void QgsDataSourceURI::setUseEstimatedMetadata( bool theFlag )
00360 {
00361   mUseEstimatedMetadata = theFlag;
00362 }
00363 
00364 bool QgsDataSourceURI::useEstimatedMetadata() const
00365 {
00366   return mUseEstimatedMetadata;
00367 }
00368 
00369 void QgsDataSourceURI::disableSelectAtId( bool theFlag )
00370 {
00371   mSelectAtIdDisabled = theFlag;
00372 }
00373 
00374 bool QgsDataSourceURI::selectAtIdDisabled() const
00375 {
00376   return mSelectAtIdDisabled;
00377 }
00378 
00379 void QgsDataSourceURI::setSql( QString sql )
00380 {
00381   mSql = sql;
00382 }
00383 
00384 void QgsDataSourceURI::clearSchema()
00385 {
00386   mSchema = "";
00387 }
00388 
00389 QString QgsDataSourceURI::escape( const QString &theVal, QChar delim = '\'' ) const
00390 {
00391   QString val = theVal;
00392 
00393   val.replace( "\\", "\\\\" );
00394   val.replace( delim, QString( "\\%1" ).arg( delim ) );
00395 
00396   return val;
00397 }
00398 
00399 void QgsDataSourceURI::skipBlanks( const QString &uri, int &i )
00400 {
00401   // skip space before value
00402   while ( i < uri.length() && uri[i].isSpace() )
00403     i++;
00404 }
00405 
00406 QString QgsDataSourceURI::getValue( const QString &uri, int &i )
00407 {
00408   skipBlanks( uri, i );
00409 
00410   // Get the parameter value
00411   QString pval;
00412   if ( uri[i] == '\'' || uri[i] == '"' )
00413   {
00414     QChar delim = uri[i];
00415 
00416     i++;
00417 
00418     // value is quoted
00419     for ( ;; )
00420     {
00421       if ( i == uri.length() )
00422       {
00423         QgsDebugMsg( "unterminated quoted string in connection info string" );
00424         return pval;
00425       }
00426 
00427       if ( uri[i] == '\\' )
00428       {
00429         i++;
00430         if ( i == uri.length() )
00431           continue;
00432         if ( uri[i] != delim && uri[i] != '\\' )
00433           i--;
00434       }
00435       else if ( uri[i] == delim )
00436       {
00437         i++;
00438         break;
00439       }
00440 
00441       pval += uri[i++];
00442     }
00443   }
00444   else
00445   {
00446     // value is not quoted
00447     while ( i < uri.length() )
00448     {
00449       if ( uri[i].isSpace() )
00450       {
00451         // end of value
00452         break;
00453       }
00454 
00455       if ( uri[i] == '\\' )
00456       {
00457         i++;
00458         if ( i == uri.length() )
00459           break;
00460         if ( uri[i] != '\\' && uri[i] != '\'' )
00461           i--;
00462       }
00463 
00464       pval += uri[i++];
00465     }
00466   }
00467 
00468   skipBlanks( uri, i );
00469 
00470   return pval;
00471 }
00472 
00473 QString QgsDataSourceURI::connectionInfo() const
00474 {
00475   QStringList connectionItems;
00476 
00477   if ( mDatabase != "" )
00478   {
00479     connectionItems << "dbname='" + escape( mDatabase ) + "'";
00480   }
00481 
00482   if ( mService != "" )
00483   {
00484     connectionItems << "service='" + escape( mService ) + "'";
00485   }
00486   else if ( mHost != "" )
00487   {
00488     connectionItems << "host=" + mHost;
00489   }
00490 
00491   if ( mService.isEmpty() )
00492   {
00493     if ( mPort != "" )
00494       connectionItems << "port=" + mPort;
00495   }
00496 
00497   if ( mUsername != "" )
00498   {
00499     connectionItems << "user='" + escape( mUsername ) + "'";
00500 
00501     if ( mPassword != "" )
00502     {
00503       connectionItems << "password='" + escape( mPassword ) + "'";
00504     }
00505   }
00506 
00507   if ( mSSLmode == SSLdisable )
00508     connectionItems << "sslmode=disable";
00509   else if ( mSSLmode == SSLallow )
00510     connectionItems << "sslmode=allow";
00511   else if ( mSSLmode == SSLrequire )
00512     connectionItems << "sslmode=require";
00513 #if 0
00514   else if ( mSSLmode == SSLprefer )
00515     connectionItems << "sslmode=prefer";
00516 #endif
00517 
00518   return connectionItems.join( " " );
00519 }
00520 
00521 QString QgsDataSourceURI::uri() const
00522 {
00523   QString theUri = connectionInfo();
00524 
00525   if ( !mKeyColumn.isEmpty() )
00526   {
00527     theUri += QString( " key='%1'" ).arg( escape( mKeyColumn ) );
00528   }
00529 
00530   if ( mUseEstimatedMetadata )
00531   {
00532     theUri += QString( " estimatedmetadata=true" );
00533   }
00534 
00535   if ( !mSrid.isEmpty() )
00536   {
00537     theUri += QString( " srid=%1" ).arg( mSrid );
00538   }
00539 
00540   if ( mWkbType != QGis::WKBUnknown && mWkbType != QGis::WKBNoGeometry )
00541   {
00542     theUri += " type=";
00543 
00544     switch ( mWkbType )
00545     {
00546       case QGis::WKBPoint:
00547         theUri += "POINT";
00548         break;
00549       case QGis::WKBLineString:
00550         theUri += "LINESTRING";
00551         break;
00552       case QGis::WKBPolygon:
00553         theUri += "POLYGON";
00554         break;
00555       case QGis::WKBMultiPoint:
00556         theUri += "MULTIPOINT";
00557         break;
00558       case QGis::WKBMultiLineString:
00559         theUri += "MULTILINESTRING";
00560         break;
00561       case QGis::WKBMultiPolygon:
00562         theUri += "MULTIPOLYGON";
00563         break;
00564       case QGis::WKBPoint25D:
00565         theUri += "POINTM";
00566         break;
00567       case QGis::WKBLineString25D:
00568         theUri += "LINESTRINGM";
00569         break;
00570       case QGis::WKBPolygon25D:
00571         theUri += "POLYGONM";
00572         break;
00573       case QGis::WKBMultiPoint25D:
00574         theUri += "MULTIPOINTM";
00575         break;
00576       case QGis::WKBMultiLineString25D:
00577         theUri += "MULTILINESTRINGM";
00578         break;
00579       case QGis::WKBMultiPolygon25D:
00580         theUri += "MULTIPOLYGONM";
00581         break;
00582       case QGis::WKBUnknown:
00583       case QGis::WKBNoGeometry:
00584         break;
00585     }
00586   }
00587 
00588   if ( mSelectAtIdDisabled )
00589   {
00590     theUri += QString( " selectatid=false" );
00591   }
00592 
00593   QString columnName( mGeometryColumn );
00594   columnName.replace( "\\", "\\\\" );
00595   columnName.replace( ")", "\\)" );
00596 
00597   theUri += QString( " table=%1%2 sql=%3" )
00598             .arg( quotedTablename() )
00599             .arg( mGeometryColumn.isNull() ? QString() : QString( " (%1)" ).arg( columnName ) )
00600             .arg( mSql );
00601 
00602   return theUri;
00603 }
00604 
00605 QByteArray QgsDataSourceURI::encodedUri() const
00606 {
00607   QUrl url;
00608   foreach ( QString key, mParams.uniqueKeys() )
00609   {
00610     foreach ( QString value, mParams.values( key ) )
00611     {
00612       url.addQueryItem( key, value );
00613     }
00614   }
00615   return url.encodedQuery();
00616 }
00617 
00618 void QgsDataSourceURI::setEncodedUri( const QByteArray & uri )
00619 {
00620   mParams.clear();
00621   QUrl url;
00622   url.setEncodedQuery( uri );
00623   QPair<QString, QString> item;
00624   foreach ( item, url.queryItems() )
00625   {
00626     mParams.insertMulti( item.first, item.second );
00627   }
00628 }
00629 
00630 void QgsDataSourceURI::setEncodedUri( const QString & uri )
00631 {
00632   setEncodedUri( uri.toAscii() );
00633 }
00634 
00635 QString QgsDataSourceURI::quotedTablename() const
00636 {
00637   if ( !mSchema.isEmpty() )
00638     return QString( "\"%1\".\"%2\"" )
00639            .arg( escape( mSchema, '"' ) )
00640            .arg( escape( mTable, '"' ) );
00641   else
00642     return QString( "\"%1\"" )
00643            .arg( escape( mTable, '"' ) );
00644 }
00645 
00646 void QgsDataSourceURI::setConnection( const QString &host,
00647                                       const QString &port,
00648                                       const QString &database,
00649                                       const QString &username,
00650                                       const QString &password,
00651                                       SSLmode sslmode )
00652 {
00653   mHost = host;
00654   mDatabase = database;
00655   mPort = port;
00656   mUsername = username;
00657   mPassword = password;
00658   mSSLmode = sslmode;
00659 }
00660 
00661 void QgsDataSourceURI::setConnection( const QString &service,
00662                                       const QString &database,
00663                                       const QString &username,
00664                                       const QString &password,
00665                                       SSLmode sslmode )
00666 {
00667   mService = service;
00668   mDatabase = database;
00669   mUsername = username;
00670   mPassword = password;
00671   mSSLmode = sslmode;
00672 }
00673 
00674 void QgsDataSourceURI::setDataSource( const QString &schema,
00675                                       const QString &table,
00676                                       const QString &geometryColumn,
00677                                       const QString &sql,
00678                                       const QString &keyColumn )
00679 {
00680   mSchema = schema;
00681   mTable = table;
00682   mGeometryColumn = geometryColumn;
00683   mSql = sql;
00684   mKeyColumn = keyColumn;
00685 }
00686 
00687 void QgsDataSourceURI::setDatabase( const QString &database )
00688 {
00689   mDatabase = database;
00690 }
00691 
00692 QGis::WkbType QgsDataSourceURI::wkbType() const
00693 {
00694   return mWkbType;
00695 }
00696 
00697 void QgsDataSourceURI::setWkbType( QGis::WkbType wkbType )
00698 {
00699   mWkbType = wkbType;
00700 }
00701 
00702 QString QgsDataSourceURI::srid() const
00703 {
00704   return mSrid;
00705 }
00706 
00707 void QgsDataSourceURI::setSrid( QString srid )
00708 {
00709   mSrid = srid;
00710 }
00711 
00712 void QgsDataSourceURI::setParam( const QString &key, const QString &value )
00713 {
00714   // may be multiple
00715   mParams.insertMulti( key, value );
00716 }
00717 
00718 void QgsDataSourceURI::setParam( const QString &key, const QStringList &value )
00719 {
00720   foreach ( QString val, value )
00721   {
00722     mParams.insertMulti( key, val );
00723   }
00724 }
00725 
00726 int QgsDataSourceURI::removeParam( const QString &key )
00727 {
00728   return mParams.remove( key );
00729 }
00730 
00731 QString QgsDataSourceURI::param( const QString &key ) const
00732 {
00733   return mParams.value( key );
00734 }
00735 
00736 QStringList QgsDataSourceURI::params( const QString &key ) const
00737 {
00738   return mParams.values( key );
00739 }
00740 
00741 bool QgsDataSourceURI::hasParam( const QString &key ) const
00742 {
00743   return mParams.contains( key );
00744 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines