QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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  {
145  }
146  else if ( geomTypeUpper == "LINESTRING" || geomTypeUpper == "LINE" )
147  {
149  }
150  else if ( geomTypeUpper == "POLYGON" )
151  {
153  }
154  else if ( geomTypeUpper == "MULTIPOINT" )
155  {
157  }
158  else if ( geomTypeUpper == "MULTILINESTRING" )
159  {
161  }
162  else if ( geomTypeUpper == "MULTIPOLYGON" )
163  {
165  }
166  else
167  {
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" )
219  else if ( pval == "allow" )
220  mSSLmode = SSLallow;
221  else if ( pval == "prefer" )
223  else if ( pval == "require" )
225  }
226  else if ( pname == "requiressl" )
227  {
228  if ( pval == "0" )
230  else
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( "invalid connection option \"" + pname + "\" ignored" );
244  }
245  }
246  }
247 }
248 
249 QString QgsDataSourceURI::removePassword( const QString& aUri )
250 {
251  QRegExp regexp;
252  regexp.setMinimal( true );
253  QString safeName( aUri );
254  if ( aUri.contains( " password=" ) )
255  {
256  regexp.setPattern( " password=.* " );
257  safeName.replace( regexp, " " );
258  }
259  else if ( aUri.contains( ",password=" ) )
260  {
261  regexp.setPattern( ",password=.*," );
262  safeName.replace( regexp, "," );
263  }
264  else if ( aUri.contains( "IDB:" ) )
265  {
266  regexp.setPattern( " pass=.* " );
267  safeName.replace( regexp, " " );
268  }
269  else if (( aUri.contains( "OCI:" ) )
270  || ( aUri.contains( "ODBC:" ) ) )
271  {
272  regexp.setPattern( "/.*@" );
273  safeName.replace( regexp, "/@" );
274  }
275  else if ( aUri.contains( "SDE:" ) )
276  {
277  QStringList strlist = aUri.split( "," );
278  safeName = strlist[0] + "," + strlist[1] + "," + strlist[2] + "," + strlist[3];
279  }
280  return safeName;
281 }
282 
284 {
285  return mUsername;
286 }
287 
288 void QgsDataSourceURI::setUsername( QString username )
289 {
291 }
292 
294 {
295  return mService;
296 }
297 
298 QString QgsDataSourceURI::host() const
299 {
300  return mHost;
301 }
302 
304 {
305  return mDatabase;
306 }
307 
309 {
310  return mPassword;
311 }
312 
313 void QgsDataSourceURI::setPassword( QString password )
314 {
316 }
317 
318 QString QgsDataSourceURI::port() const
319 {
320  return mPort;
321 }
322 
324 {
325  return mSSLmode;
326 }
327 
329 {
330  return mSchema;
331 }
332 
333 QString QgsDataSourceURI::table() const
334 {
335  return mTable;
336 }
337 
338 QString QgsDataSourceURI::sql() const
339 {
340  return mSql;
341 }
342 
344 {
345  return mGeometryColumn;
346 }
347 
349 {
350  return mKeyColumn;
351 }
352 
353 void QgsDataSourceURI::setKeyColumn( QString column )
354 {
355  mKeyColumn = column;
356 }
357 
358 
360 {
361  mUseEstimatedMetadata = theFlag;
362 }
363 
365 {
366  return mUseEstimatedMetadata;
367 }
368 
370 {
371  mSelectAtIdDisabled = theFlag;
372 }
373 
375 {
376  return mSelectAtIdDisabled;
377 }
378 
379 void QgsDataSourceURI::setSql( QString sql )
380 {
381  mSql = sql;
382 }
383 
385 {
386  mSchema = "";
387 }
388 
389 QString QgsDataSourceURI::escape( const QString &theVal, QChar delim = '\'' ) const
390 {
391  QString val = theVal;
392 
393  val.replace( "\\", "\\\\" );
394  val.replace( delim, QString( "\\%1" ).arg( delim ) );
395 
396  return val;
397 }
398 
399 void QgsDataSourceURI::skipBlanks( const QString &uri, int &i )
400 {
401  // skip space before value
402  while ( i < uri.length() && uri[i].isSpace() )
403  i++;
404 }
405 
406 QString QgsDataSourceURI::getValue( const QString &uri, int &i )
407 {
408  skipBlanks( uri, i );
409 
410  // Get the parameter value
411  QString pval;
412  if ( uri[i] == '\'' || uri[i] == '"' )
413  {
414  QChar delim = uri[i];
415 
416  i++;
417 
418  // value is quoted
419  for ( ;; )
420  {
421  if ( i == uri.length() )
422  {
423  QgsDebugMsg( "unterminated quoted string in connection info string" );
424  return pval;
425  }
426 
427  if ( uri[i] == '\\' )
428  {
429  i++;
430  if ( i == uri.length() )
431  continue;
432  if ( uri[i] != delim && uri[i] != '\\' )
433  i--;
434  }
435  else if ( uri[i] == delim )
436  {
437  i++;
438  break;
439  }
440 
441  pval += uri[i++];
442  }
443  }
444  else
445  {
446  // value is not quoted
447  while ( i < uri.length() )
448  {
449  if ( uri[i].isSpace() )
450  {
451  // end of value
452  break;
453  }
454 
455  if ( uri[i] == '\\' )
456  {
457  i++;
458  if ( i == uri.length() )
459  break;
460  if ( uri[i] != '\\' && uri[i] != '\'' )
461  i--;
462  }
463 
464  pval += uri[i++];
465  }
466  }
467 
468  skipBlanks( uri, i );
469 
470  return pval;
471 }
472 
474 {
475  QStringList connectionItems;
476 
477  if ( mDatabase != "" )
478  {
479  connectionItems << "dbname='" + escape( mDatabase ) + "'";
480  }
481 
482  if ( mService != "" )
483  {
484  connectionItems << "service='" + escape( mService ) + "'";
485  }
486  else if ( mHost != "" )
487  {
488  connectionItems << "host=" + mHost;
489  }
490 
491  if ( mService.isEmpty() )
492  {
493  if ( mPort != "" )
494  connectionItems << "port=" + mPort;
495  }
496 
497  if ( mUsername != "" )
498  {
499  connectionItems << "user='" + escape( mUsername ) + "'";
500 
501  if ( mPassword != "" )
502  {
503  connectionItems << "password='" + escape( mPassword ) + "'";
504  }
505  }
506 
507  if ( mSSLmode == SSLdisable )
508  connectionItems << "sslmode=disable";
509  else if ( mSSLmode == SSLallow )
510  connectionItems << "sslmode=allow";
511  else if ( mSSLmode == SSLrequire )
512  connectionItems << "sslmode=require";
513 #if 0
514  else if ( mSSLmode == SSLprefer )
515  connectionItems << "sslmode=prefer";
516 #endif
517 
518  return connectionItems.join( " " );
519 }
520 
521 QString QgsDataSourceURI::uri() const
522 {
523  QString theUri = connectionInfo();
524 
525  if ( !mKeyColumn.isEmpty() )
526  {
527  theUri += QString( " key='%1'" ).arg( escape( mKeyColumn ) );
528  }
529 
530  if ( mUseEstimatedMetadata )
531  {
532  theUri += QString( " estimatedmetadata=true" );
533  }
534 
535  if ( !mSrid.isEmpty() )
536  {
537  theUri += QString( " srid=%1" ).arg( mSrid );
538  }
539 
541  {
542  theUri += " type=";
543 
544  switch ( mWkbType )
545  {
546  case QGis::WKBPoint:
547  theUri += "POINT";
548  break;
549  case QGis::WKBLineString:
550  theUri += "LINESTRING";
551  break;
552  case QGis::WKBPolygon:
553  theUri += "POLYGON";
554  break;
555  case QGis::WKBMultiPoint:
556  theUri += "MULTIPOINT";
557  break;
559  theUri += "MULTILINESTRING";
560  break;
562  theUri += "MULTIPOLYGON";
563  break;
564  case QGis::WKBPoint25D:
565  theUri += "POINTM";
566  break;
568  theUri += "LINESTRINGM";
569  break;
570  case QGis::WKBPolygon25D:
571  theUri += "POLYGONM";
572  break;
574  theUri += "MULTIPOINTM";
575  break;
577  theUri += "MULTILINESTRINGM";
578  break;
580  theUri += "MULTIPOLYGONM";
581  break;
582  case QGis::WKBUnknown:
583  case QGis::WKBNoGeometry:
584  break;
585  }
586  }
587 
588  if ( mSelectAtIdDisabled )
589  {
590  theUri += QString( " selectatid=false" );
591  }
592 
593  QString columnName( mGeometryColumn );
594  columnName.replace( "\\", "\\\\" );
595  columnName.replace( ")", "\\)" );
596 
597  theUri += QString( " table=%1%2 sql=%3" )
598  .arg( quotedTablename() )
599  .arg( mGeometryColumn.isNull() ? QString() : QString( " (%1)" ).arg( columnName ) )
600  .arg( mSql );
601 
602  return theUri;
603 }
604 
606 {
607  QUrl url;
608  foreach ( QString key, mParams.uniqueKeys() )
609  {
610  foreach ( QString value, mParams.values( key ) )
611  {
612  url.addQueryItem( key, value );
613  }
614  }
615  return url.encodedQuery();
616 }
617 
618 void QgsDataSourceURI::setEncodedUri( const QByteArray & uri )
619 {
620  mParams.clear();
621  QUrl url;
622  url.setEncodedQuery( uri );
623  QPair<QString, QString> item;
624  foreach ( item, url.queryItems() )
625  {
626  mParams.insertMulti( item.first, item.second );
627  }
628 }
629 
630 void QgsDataSourceURI::setEncodedUri( const QString & uri )
631 {
632  setEncodedUri( uri.toAscii() );
633 }
634 
636 {
637  if ( !mSchema.isEmpty() )
638  return QString( "\"%1\".\"%2\"" )
639  .arg( escape( mSchema, '"' ) )
640  .arg( escape( mTable, '"' ) );
641  else
642  return QString( "\"%1\"" )
643  .arg( escape( mTable, '"' ) );
644 }
645 
646 void QgsDataSourceURI::setConnection( const QString &host,
647  const QString &port,
648  const QString &database,
649  const QString &username,
650  const QString &password,
651  SSLmode sslmode )
652 {
653  mHost = host;
655  mPort = port;
658  mSSLmode = sslmode;
659 }
660 
661 void QgsDataSourceURI::setConnection( const QString &service,
662  const QString &database,
663  const QString &username,
664  const QString &password,
665  SSLmode sslmode )
666 {
667  mService = service;
671  mSSLmode = sslmode;
672 }
673 
674 void QgsDataSourceURI::setDataSource( const QString &schema,
675  const QString &table,
676  const QString &geometryColumn,
677  const QString &sql,
678  const QString &keyColumn )
679 {
680  mSchema = schema;
681  mTable = table;
683  mSql = sql;
685 }
686 
687 void QgsDataSourceURI::setDatabase( const QString &database )
688 {
690 }
691 
693 {
694  return mWkbType;
695 }
696 
698 {
699  mWkbType = wkbType;
700 }
701 
702 QString QgsDataSourceURI::srid() const
703 {
704  return mSrid;
705 }
706 
707 void QgsDataSourceURI::setSrid( QString srid )
708 {
709  mSrid = srid;
710 }
711 
712 void QgsDataSourceURI::setParam( const QString &key, const QString &value )
713 {
714  // may be multiple
715  mParams.insertMulti( key, value );
716 }
717 
718 void QgsDataSourceURI::setParam( const QString &key, const QStringList &value )
719 {
720  foreach ( QString val, value )
721  {
722  mParams.insertMulti( key, val );
723  }
724 }
725 
726 int QgsDataSourceURI::removeParam( const QString &key )
727 {
728  return mParams.remove( key );
729 }
730 
731 QString QgsDataSourceURI::param( const QString &key ) const
732 {
733  return mParams.value( key );
734 }
735 
736 QStringList QgsDataSourceURI::params( const QString &key ) const
737 {
738  return mParams.values( key );
739 }
740 
741 bool QgsDataSourceURI::hasParam( const QString &key ) const
742 {
743  return mParams.contains( key );
744 }