|
QGIS API Documentation
master-3f58142
|
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 }