00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00023
00024
00025
00026
00027
00028
00029 #include "kurl.h"
00030
00031 #include <kdebug.h>
00032 #include <kglobal.h>
00033 #include <kshell.h>
00034 #include <kstringhandler.h>
00035
00036 #include <stdio.h>
00037 #include <assert.h>
00038 #include <ctype.h>
00039 #include <stdlib.h>
00040 #include <unistd.h>
00041
00042 #include <QtCore/QDir>
00043 #include <QtCore/QMutableStringListIterator>
00044 #include <QtCore/QRegExp>
00045 #include <QtCore/QMimeData>
00046 #include <QtCore/QTextCodec>
00047
00048 static QString cleanpath( const QString &_path, bool cleanDirSeparator, bool decodeDots )
00049 {
00050 if (_path.isEmpty())
00051 return QString();
00052
00053 if (QFileInfo(_path).isRelative())
00054 return _path;
00055
00056 QString path = _path;
00057
00058 int len = path.length();
00059
00060 if (decodeDots)
00061 {
00062 static const QString &encodedDot = KGlobal::staticQString("%2e");
00063 if (path.indexOf(encodedDot, 0, Qt::CaseInsensitive) != -1)
00064 {
00065 static const QString &encodedDOT = KGlobal::staticQString("%2E");
00066 path.replace(encodedDot, ".");
00067 path.replace(encodedDOT, ".");
00068 len = path.length();
00069 }
00070 }
00071
00072 bool slash = (len && path[len-1] == QLatin1Char('/')) ||
00073 (len > 1 && path[len-2] == QLatin1Char('/') && path[len-1] == QLatin1Char('.'));
00074
00075
00076
00077
00078
00079
00080
00081 QString result;
00082 int cdUp, orig_pos, pos;
00083
00084 cdUp = 0;
00085 pos = orig_pos = len;
00086 while ( pos && (pos = path.lastIndexOf(QLatin1Char('/'),--pos)) != -1 )
00087 {
00088 len = orig_pos - pos - 1;
00089 if ( len == 2 && path[pos+1] == '.' && path[pos+2] == '.' )
00090 cdUp++;
00091 else
00092 {
00093
00094
00095 if ( (len || !cleanDirSeparator) &&
00096 (len != 1 || path[pos+1] != '.' ) )
00097 {
00098 if ( !cdUp )
00099 result.prepend(path.mid(pos, len+1));
00100 else
00101 cdUp--;
00102 }
00103 }
00104 orig_pos = pos;
00105 }
00106
00107 #ifdef Q_WS_WIN // prepend drive letter if exists (js)
00108 if (orig_pos >= 2 && path[0].isLetter() && path[1] == QLatin1Char(':') ) {
00109 result.prepend(QString(path[0]) + QLatin1Char(':') );
00110 }
00111 #endif
00112
00113 if ( result.isEmpty() )
00114 result = '/';
00115 else if ( slash && result[result.length()-1] != QLatin1Char('/') )
00116 result.append(QChar('/'));
00117
00118 return result;
00119 }
00120
00121 #ifdef Q_WS_WIN
00122
00123
00124 #define IS_DRIVE_OR_DOUBLESLASH(isletter, char1, char2, colon, slash) \
00125 ((isletter && char2 == colon) || (char1 == slash && char2 == slash))
00126
00127
00128
00129
00130 static QString removeSlashOrFilePrefix(const QString& str)
00131 {
00132
00133 const int len = str.length();
00134 if (str[0]=='f') {
00135 if ( len > 10 && str.startsWith( QLatin1String( "file:///" ) )
00136 && IS_DRIVE_OR_DOUBLESLASH(str[8].isLetter(), str[8], str[9], QLatin1Char(':'), QLatin1Char('/')) )
00137 return QUrl::fromPercentEncoding( str.toLatin1() ).mid(8);
00138 else if ( len > 9 && str.startsWith( QLatin1String( "file://" ) )
00139 && IS_DRIVE_OR_DOUBLESLASH(str[7].isLetter(), str[7], str[8], QLatin1Char(':'), QLatin1Char('/')) )
00140 return QUrl::fromPercentEncoding( str.toLatin1() ).mid(7);
00141 else if ( len > 8 && str.startsWith( QLatin1String( "file:/" ) )
00142 && IS_DRIVE_OR_DOUBLESLASH(str[6].isLetter(), str[6], str[7], QLatin1Char(':'), QLatin1Char('/')) )
00143 return QUrl::fromPercentEncoding( str.toLatin1() ).mid(6);
00144 }
00145
00146
00147
00148 if ( len > 2 && str[0] == QLatin1Char('/')
00149 && IS_DRIVE_OR_DOUBLESLASH(str[1].isLetter(), str[1], str[2], QLatin1Char(':'), QLatin1Char('/')) )
00150 return str.mid(1);
00151
00152 else if ( len >= 2 && IS_DRIVE_OR_DOUBLESLASH(str[0].isLetter(), str[0], str[1], QLatin1Char(':'), QLatin1Char('/')) )
00153 return str;
00154 return QString();
00155 }
00156 #endif
00157
00158 bool KUrl::isRelativeUrl(const QString &_url)
00159 {
00160 #if 0
00161
00162 return QUrl( _url ).isRelative();
00163 #endif
00164 int len = _url.length();
00165 if (!len) return true;
00166 const QChar *str = _url.unicode();
00167
00168
00169 if (!isalpha(str[0].toLatin1()))
00170 return true;
00171
00172 for(int i = 1; i < len; i++)
00173 {
00174 char c = str[i].toLatin1();
00175 if (c == ':')
00176 return false;
00177
00178
00179 if (!isalpha(c) && !isdigit(c) && (c != '+') && (c != '-'))
00180 return true;
00181 }
00182
00183 return true;
00184 }
00185
00186 KUrl::List::List(const KUrl &url)
00187 {
00188 append( url );
00189 }
00190
00191 KUrl::List::List(const QList<KUrl> &list)
00192 : QList<KUrl>(list)
00193 {
00194 }
00195
00196 KUrl::List::List(const QStringList &list)
00197 {
00198 for (QStringList::ConstIterator it = list.begin();
00199 it != list.end();
00200 ++it)
00201 {
00202 append( KUrl(*it) );
00203 }
00204 }
00205
00206 QStringList KUrl::List::toStringList() const
00207 {
00208 QStringList lst;
00209 for( KUrl::List::ConstIterator it = begin();
00210 it != end();
00211 ++it)
00212 {
00213 lst.append( (*it).url() );
00214 }
00215 return lst;
00216 }
00217
00218
00219 void KUrl::List::populateMimeData( QMimeData* mimeData,
00220 const KUrl::MetaDataMap& metaData,
00221 MimeDataFlags flags ) const
00222 {
00223 QList<QByteArray> urlStringList;
00224 KUrl::List::ConstIterator uit = begin();
00225 const KUrl::List::ConstIterator uEnd = end();
00226 for ( ; uit != uEnd ; ++uit )
00227 {
00228
00229
00230 urlStringList.append( (*uit).toMimeDataString().toLatin1() );
00231 }
00232
00233 QByteArray uriListData;
00234 for (int i = 0, n = urlStringList.count(); i < n; ++i) {
00235 uriListData += urlStringList.at(i);
00236 if (i < n-1)
00237 uriListData += "\r\n";
00238 }
00239 mimeData->setData( "text/uri-list", uriListData );
00240
00241 if ( ( flags & KUrl::NoTextExport ) == 0 )
00242 {
00243 QStringList prettyURLsList;
00244 for ( uit = begin(); uit != uEnd ; ++uit ) {
00245 QString prettyURL = (*uit).prettyUrl();
00246 if ( (*uit).protocol() == "mailto" ) {
00247 prettyURL = (*uit).path();
00248 }
00249 prettyURLsList.append( prettyURL );
00250 }
00251
00252 QByteArray plainTextData = prettyURLsList.join( "\n" ).toLocal8Bit();
00253 if( count() > 1 )
00254 plainTextData.append( "\n" );
00255 mimeData->setData( "text/plain", plainTextData );
00256 }
00257
00258 if ( !metaData.isEmpty() )
00259 {
00260 QByteArray metaDataData;
00261 for( KUrl::MetaDataMap::const_iterator it = metaData.begin(); it != metaData.end(); ++it )
00262 {
00263 metaDataData += it.key().toUtf8();
00264 metaDataData += "$@@$";
00265 metaDataData += it.value().toUtf8();
00266 metaDataData += "$@@$";
00267 }
00268 mimeData->setData( "application/x-kio-metadata", metaDataData );
00269 }
00270 }
00271
00272 bool KUrl::List::canDecode( const QMimeData *mimeData )
00273 {
00274 return mimeData->hasFormat( "text/uri-list" ) || mimeData->hasFormat( "application/x-kde-urilist" );
00275 }
00276
00277 QStringList KUrl::List::mimeDataTypes()
00278 {
00279 return QStringList()<<( "application/x-kde-urilist" )<<( "text/uri-list" );
00280 }
00281
00282 KUrl::List KUrl::List::fromMimeData( const QMimeData *mimeData, KUrl::MetaDataMap* metaData )
00283 {
00284 KUrl::List uris;
00285
00286
00287
00288 QByteArray payload = mimeData->data( "application/x-kde-urilist" );
00289 if ( payload.isEmpty() )
00290 payload = mimeData->data( "text/uri-list" );
00291 if ( !payload.isEmpty() ) {
00292 int c = 0;
00293 const char* d = payload.data();
00294 while ( c < payload.size() && d[c] ) {
00295 int f = c;
00296
00297 while (c < payload.size() && d[c] && d[c]!='\r'
00298 && d[c] != '\n')
00299 c++;
00300 QByteArray s( d+f, c-f );
00301 if ( s[0] != '#' )
00302 uris.append( KUrl::fromMimeDataByteArray( s ) );
00303
00304 while ( c < payload.size() && d[c] &&
00305 ( d[c] == '\n' || d[c] == '\r' ) )
00306 ++c;
00307 }
00308 }
00309 if ( metaData )
00310 {
00311 const QByteArray metaDataPayload = mimeData->data( "application/x-kio-metadata" );
00312 if ( !metaDataPayload.isEmpty() )
00313 {
00314 QString str = QString::fromUtf8( metaDataPayload );
00315 Q_ASSERT( str.endsWith( "$@@$" ) );
00316 str.truncate( str.length() - 4 );
00317 const QStringList lst = str.split( "$@@$" );
00318 QStringList::ConstIterator it = lst.begin();
00319 bool readingKey = true;
00320 QString key;
00321 for ( ; it != lst.end(); ++it ) {
00322 if ( readingKey )
00323 key = *it;
00324 else
00325 metaData->insert( key, *it );
00326 readingKey = !readingKey;
00327 }
00328 Q_ASSERT( readingKey );
00329 }
00330 }
00331
00332 return uris;
00333 }
00334
00335 KUrl::List::operator QVariant() const
00336 {
00337 return qVariantFromValue(*this);
00338 }
00339
00341
00342 KUrl::KUrl()
00343 : QUrl(), d(0)
00344 {
00345 }
00346
00347 KUrl::~KUrl()
00348 {
00349 }
00350
00351
00352 KUrl::KUrl( const QString &str )
00353 : QUrl(), d(0)
00354 {
00355 if ( !str.isEmpty() ) {
00356 #ifdef Q_WS_WIN
00357 kDebug(126) << "KUrl::KUrl ( const QString &str = " << str.toAscii().data() << " )";
00358 QString pathToSet( removeSlashOrFilePrefix( QDir::fromNativeSeparators(str) ) );
00359 if ( !pathToSet.isEmpty() ) {
00360
00361
00362 int index = pathToSet.lastIndexOf('?');
00363 if (index == -1)
00364 setPath( QDir::fromNativeSeparators( pathToSet ) );
00365 else {
00366 setPath( QDir::fromNativeSeparators( pathToSet.left( index ) ) );
00367 _setQuery( pathToSet.mid( index + 1 ) );
00368 }
00369 }
00370 #else
00371 if ( str[0] == QLatin1Char('/') || str[0] == QLatin1Char('~') )
00372 setPath( str );
00373 #endif
00374 else {
00375 _setEncodedUrl( str.toUtf8() );
00376 }
00377 }
00378 }
00379
00380 KUrl::KUrl( const char * str )
00381 : QUrl(), d(0)
00382 {
00383 #ifdef Q_WS_WIN
00384
00385 #define IS_LETTER(c) \
00386 ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
00387
00388
00389 #define IS_SLASH_AND_DRIVE_OR_DOUBLESLASH_0 \
00390 ( str[0] == '/' && IS_DRIVE_OR_DOUBLESLASH(IS_LETTER(str[1]), str[1], str[2], ':', '/') )
00391
00392
00393 #define IS_DRIVE_OR_DOUBLESLASH_0 \
00394 ( IS_DRIVE_OR_DOUBLESLASH(IS_LETTER(str[0]), str[0], str[1], ':', '/') )
00395
00396 #if defined(DEBUG_KURL)
00397 kDebug(126) << "KUrl::KUrl " << " " << str;
00398 #endif
00399 if ( str && str[0] && str[1] && str[2] ) {
00400 if ( IS_SLASH_AND_DRIVE_OR_DOUBLESLASH_0 )
00401 setPath( QString::fromUtf8( str+1 ) );
00402 else if ( IS_DRIVE_OR_DOUBLESLASH_0 )
00403 setPath( QString::fromUtf8( str ) );
00404 #else
00405 if ( str && str[0] ) {
00406 if ( str[0] == '/' || str[0] == '~' )
00407 setPath( QString::fromUtf8( str ) );
00408 #endif
00409 else
00410 _setEncodedUrl( str );
00411 }
00412 }
00413
00414 KUrl::KUrl( const QByteArray& str )
00415 : QUrl(), d(0)
00416 {
00417 if ( !str.isEmpty() ) {
00418 #ifdef Q_WS_WIN
00419 #ifdef DEBUG_KURL
00420 kDebug(126) << "KUrl::KUrl " << " " << str.data();
00421 #endif
00422 if ( IS_SLASH_AND_DRIVE_OR_DOUBLESLASH_0 )
00423 setPath( QString::fromUtf8( str.mid( 1 ) ) );
00424 else if ( IS_DRIVE_OR_DOUBLESLASH_0 )
00425 setPath( QString::fromUtf8( str ) );
00426 #else
00427 if ( str[0] == '/' || str[0] == '~' )
00428 setPath( QString::fromUtf8( str ) );
00429 #endif
00430 else
00431 _setEncodedUrl( str );
00432 }
00433 }
00434
00435 KUrl::KUrl( const KUrl& _u )
00436 : QUrl( _u ), d(0)
00437 {
00438 #if defined(Q_WS_WIN) && defined(DEBUG_KURL)
00439 kDebug(126) << "KUrl::KUrl(KUrl) " << " path " << _u.path() << " toLocalFile " << _u.toLocalFile();
00440 #endif
00441 }
00442
00443 KUrl::KUrl( const QUrl &u )
00444 : QUrl( u ), d(0)
00445 {
00446 #if defined(Q_WS_WIN) && defined(DEBUG_KURL)
00447 kDebug(126) << "KUrl::KUrl(Qurl) " << " path " << u.path() << " toLocalFile " << u.toLocalFile();
00448 #endif
00449 }
00450
00451 KUrl::KUrl( const KUrl& _u, const QString& _rel_url )
00452 : QUrl(), d(0)
00453 {
00454 #if defined(Q_WS_WIN) && defined(DEBUG_KURL)
00455 kDebug(126) << "KUrl::KUrl(KUrl,QString rel_url) " << " path " << _u.path() << " toLocalFile " << _u.toLocalFile();
00456 #endif
00457 #if 0
00458 if (_u.hasSubUrl())
00459 {
00460 KUrl::List lst = split( _u );
00461 KUrl u(lst.last(), _rel_url);
00462 lst.erase( --lst.end() );
00463 lst.append( u );
00464 *this = join( lst );
00465 return;
00466 }
00467 #endif
00468 QString rUrl = _rel_url;
00469
00470
00471
00472
00473 int len = _u.scheme().length();
00474 if ( !_u.host().isEmpty() && !rUrl.isEmpty() &&
00475 rUrl.indexOf( _u.scheme(), 0, Qt::CaseInsensitive ) == 0 &&
00476 rUrl[len] == ':' && (rUrl[len+1] != QLatin1Char('/') ||
00477 (rUrl[len+1] == '/' && rUrl[len+2] != QLatin1Char('/'))) )
00478 {
00479 rUrl.remove( 0, rUrl.indexOf( ':' ) + 1 );
00480 }
00481
00482
00483 if ( rUrl.isEmpty() )
00484 {
00485 *this = _u;
00486 }
00487 else if ( rUrl[0] == '#' )
00488 {
00489 *this = _u;
00490 QString strRef_encoded = rUrl.mid(1);
00491 if ( strRef_encoded.isNull() )
00492 strRef_encoded = "";
00493 setFragment( strRef_encoded );
00494 }
00495 else if ( isRelativeUrl( rUrl ) )
00496 {
00497 *this = _u;
00498 setFragment( QString() );
00499 setEncodedQuery( QByteArray() );
00500 QString strPath = path();
00501 if ( rUrl[0] == QLatin1Char('/') )
00502 {
00503 if ((rUrl.length() > 1) && (rUrl[1] == QLatin1Char('/')))
00504 {
00505 setHost( QString() );
00506 setPort( -1 );
00507
00508 if ( _u.isLocalFile() )
00509 rUrl.remove(0, 2);
00510 }
00511 strPath.clear();
00512 }
00513 else if ( rUrl[0] != '?' )
00514 {
00515 int pos = strPath.lastIndexOf( QLatin1Char('/') );
00516 if (pos >= 0)
00517 strPath.truncate(pos);
00518 strPath += QLatin1Char('/');
00519 }
00520 else
00521 {
00522 if ( strPath.isEmpty() )
00523 strPath = QLatin1Char('/');
00524 }
00525 setPath( strPath );
00526
00527 KUrl tmp( url() + rUrl);
00528
00529 *this = tmp;
00530 cleanPath(KeepDirSeparators);
00531 }
00532 else
00533 {
00534 KUrl tmp( rUrl );
00535
00536 *this = tmp;
00537
00538 if (!_u.userInfo().isEmpty() && userInfo().isEmpty()
00539 && (_u.host() == host()) && (_u.scheme() == scheme()))
00540 {
00541 setUserInfo( _u.userInfo() );
00542 }
00543 cleanPath(KeepDirSeparators);
00544 }
00545 }
00546
00547 KUrl& KUrl::operator=( const KUrl& _u )
00548 {
00549 QUrl::operator=( _u );
00550 return *this;
00551 }
00552
00553 bool KUrl::operator==( const KUrl& _u ) const
00554 {
00555 return QUrl::operator==( _u );;
00556 }
00557
00558 bool KUrl::operator==( const QString& _u ) const
00559 {
00560 KUrl u( _u );
00561 return ( *this == u );
00562 }
00563
00564 KUrl::operator QVariant() const
00565 {
00566 return qVariantFromValue(*this);
00567 }
00568
00569 bool KUrl::cmp( const KUrl &u, bool ignore_trailing ) const
00570 {
00571 return equals( u, ignore_trailing ? CompareWithoutTrailingSlash : EqualsOptions(0) );
00572 }
00573
00574 bool KUrl::equals( const KUrl &_u, const EqualsOptions& options ) const
00575 {
00576 if ( !isValid() || !_u.isValid() )
00577 return false;
00578
00579 if ( options & CompareWithoutTrailingSlash || options & CompareWithoutFragment )
00580 {
00581 QString path1 = path((options & CompareWithoutTrailingSlash) ? RemoveTrailingSlash : LeaveTrailingSlash);
00582 QString path2 = _u.path((options & CompareWithoutTrailingSlash) ? RemoveTrailingSlash : LeaveTrailingSlash);
00583 #ifdef Q_WS_WIN
00584 const bool bLocal1 = isLocalFile();
00585 const bool bLocal2 = _u.isLocalFile();
00586 if ( !bLocal1 && bLocal2 || bLocal1 && !bLocal2 )
00587 return false;
00588
00589 if ( bLocal1 && bLocal2 && 0 != QString::compare( path1, path2, Qt::CaseInsensitive ) )
00590 return false;
00591 #endif
00592 if ( path1 != path2 )
00593 return false;
00594
00595 if ( scheme() == _u.scheme() &&
00596 authority() == _u.authority() &&
00597 encodedQuery() == _u.encodedQuery() &&
00598 (fragment() == _u.fragment() || options & CompareWithoutFragment ) )
00599 return true;
00600
00601 return false;
00602 }
00603
00604 return ( *this == _u );
00605 }
00606
00607 QString KUrl::protocol() const
00608 {
00609 return scheme().toLower();
00610 }
00611
00612 void KUrl::setProtocol( const QString& proto )
00613 {
00614 setScheme( proto );
00615 }
00616
00617 QString KUrl::user() const
00618 {
00619 return userName();
00620 }
00621
00622 void KUrl::setUser( const QString& user )
00623 {
00624 setUserName( user );
00625 }
00626
00627 bool KUrl::hasUser() const
00628 {
00629 return !userName().isEmpty();
00630 }
00631
00632 QString KUrl::pass() const
00633 {
00634 return password();
00635 }
00636
00637 void KUrl::setPass( const QString& pass )
00638 {
00639 setPassword( pass );
00640 }
00641
00642 bool KUrl::hasPass() const
00643 {
00644 return !password().isEmpty();
00645 }
00646
00647 bool KUrl::hasHost() const
00648 {
00649 return !host().isEmpty();
00650 }
00651
00652 bool KUrl::hasPath() const
00653 {
00654 return !path().isEmpty();
00655 }
00656
00657 KUrl KUrl::fromPath( const QString& text )
00658 {
00659 KUrl u;
00660 u.setPath( text );
00661 return u;
00662 }
00663
00664 void KUrl::setFileName( const QString& _txt )
00665 {
00666 setFragment( QString() );
00667 int i = 0;
00668 while( i < _txt.length() && _txt[i] == QLatin1Char('/') )
00669 ++i;
00670 QString tmp = i ? _txt.mid( i ) : _txt;
00671
00672
00673 QString path = this->path();
00674 if ( path.isEmpty() )
00675 #ifdef Q_OS_WIN
00676 path = isLocalFile() ? QDir::rootPath() : QLatin1String("/");
00677 #else
00678 path = QDir::rootPath();
00679 #endif
00680 else
00681 {
00682 int lastSlash = path.lastIndexOf( QLatin1Char('/') );
00683 if ( lastSlash == -1)
00684 {
00685
00686
00687 path = QLatin1Char('/');
00688 }
00689 else if ( !path.endsWith( QLatin1Char('/') ) )
00690 path.truncate( lastSlash+1 );
00691 }
00692 #if 0
00693 if (m_strPath_encoded.isEmpty())
00694 #endif
00695 {
00696 path += tmp;
00697 setPath( path );
00698 }
00699 #if 0
00700 else
00701 {
00702 path += encode_string(tmp);
00703 setEncodedPath( path );
00704 }
00705 #endif
00706 cleanPath();
00707 }
00708
00709 void KUrl::cleanPath( const CleanPathOption& options )
00710 {
00711
00712 const QString newPath = cleanpath(path(), !(options & KeepDirSeparators), false);
00713 if ( path() != newPath )
00714 setPath( newPath );
00715
00716
00717 }
00718
00719 static QString trailingSlash( KUrl::AdjustPathOption trailing, const QString &path )
00720 {
00721 if ( trailing == KUrl::LeaveTrailingSlash ) {
00722 return path;
00723 }
00724
00725 QString result = path;
00726
00727 if ( trailing == KUrl::AddTrailingSlash )
00728 {
00729 int len = result.length();
00730 if ( (len == 0) || (result[ len - 1 ] != QLatin1Char('/')) )
00731 result += QLatin1Char('/');
00732 return result;
00733 }
00734 else if ( trailing == KUrl::RemoveTrailingSlash )
00735 {
00736 if ( result == QLatin1String("/") )
00737 return result;
00738 int len = result.length();
00739 while (len > 1 && result[ len - 1 ] == QLatin1Char('/'))
00740 {
00741 len--;
00742 }
00743 result.truncate( len );
00744 return result;
00745 }
00746 else {
00747 assert( 0 );
00748 return result;
00749 }
00750 }
00751
00752 void KUrl::adjustPath( AdjustPathOption trailing )
00753 {
00754 #if 0
00755 if (!m_strPath_encoded.isEmpty())
00756 {
00757 m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded );
00758 }
00759 #endif
00760 const QString newPath = trailingSlash( trailing, path() );
00761 if ( path() != newPath )
00762 setPath( newPath );
00763 }
00764
00765
00766 QString KUrl::encodedPathAndQuery( AdjustPathOption trailing , const EncodedPathAndQueryOptions &options) const
00767 {
00768 QString tmp;
00769 #if 0
00770 if (!m_strPath_encoded.isEmpty())
00771 {
00772 tmp = trailingSlash( _trailing, m_strPath_encoded );
00773 }
00774 else
00775 #endif
00776 {
00777 tmp = path( trailing );
00778 if ( (options & AvoidEmptyPath) && tmp.isEmpty() )
00779 tmp = "/";
00780 #if 0
00781 if (m_iUriMode == Mailto)
00782 {
00783 tmp = encode( tmp, 2 );
00784 }
00785 else
00786 {
00787 tmp = encode( tmp, 1 );
00788 }
00789 #endif
00790
00791 tmp = QString::fromLatin1( QUrl::toPercentEncoding( tmp, "!$&'()*+,;=:@/" ) );
00792 }
00793
00794 if (hasQuery())
00795 {
00796 tmp += query();
00797 }
00798 return tmp;
00799 }
00800
00801 #if 0
00802 void KUrl::setEncodedPath( const QString& _txt, int encoding_hint )
00803 {
00804 m_strPath_encoded = _txt;
00805
00806 decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint );
00807
00808 if (m_strProtocol == "file")
00809 m_strPath_encoded.clear();
00810
00811 if ( m_iUriMode == Auto )
00812 m_iUriMode = URL;
00813 }
00814 #endif
00815
00816 void KUrl::setEncodedPathAndQuery( const QString& _txt )
00817 {
00818 int pos = _txt.indexOf( '?' );
00819 if ( pos == -1 )
00820 {
00821 setPath( QUrl::fromPercentEncoding( _txt.toLatin1() ) );
00822 setEncodedQuery( QByteArray() );
00823 }
00824 else
00825 {
00826 setPath( QUrl::fromPercentEncoding( _txt.toLatin1() ).left( pos ) );
00827 _setQuery( _txt.right( _txt.length() - pos - 1 ) );
00828 }
00829 }
00830
00831 QString KUrl::path( AdjustPathOption trailing ) const
00832 {
00833 #ifdef Q_OS_WIN
00834
00835 return trailingSlash( trailing, isLocalFile() ? QUrl::toLocalFile() : QUrl::path() );
00836 #else
00837 return trailingSlash( trailing, QUrl::path() );
00838 #endif
00839 }
00840
00841 QString KUrl::toLocalFile( AdjustPathOption trailing ) const
00842 {
00843 return trailingSlash( trailing, QUrl::toLocalFile() );
00844 }
00845
00846 inline static bool hasSubUrl( const QUrl& url );
00847
00848 static inline bool isLocalFile( const QUrl& url )
00849 {
00850 if ( ( url.scheme() != QLatin1String("file") ) || hasSubUrl( url ) )
00851 return false;
00852
00853 if (url.host().isEmpty() || (url.host() == QLatin1String("localhost")))
00854 return true;
00855
00856 char hostname[ 256 ];
00857 hostname[ 0 ] = '\0';
00858 if (!gethostname( hostname, 255 ))
00859 hostname[sizeof(hostname)-1] = '\0';
00860
00861 for(char *p = hostname; *p; p++)
00862 *p = tolower(*p);
00863
00864 return (url.host() == QString::fromLatin1( hostname ));
00865 }
00866
00867 bool KUrl::isLocalFile() const
00868 {
00869 return ::isLocalFile( *this );
00870 }
00871
00872 void KUrl::setFileEncoding(const QString &encoding)
00873 {
00874 if (!isLocalFile())
00875 return;
00876
00877 QString q = query();
00878
00879 if (!q.isEmpty() && (q[0] == '?'))
00880 q = q.mid(1);
00881
00882 QStringList args = q.split('&', QString::SkipEmptyParts);
00883 for(QStringList::Iterator it = args.begin();
00884 it != args.end();)
00885 {
00886 QString s = QUrl::fromPercentEncoding( (*it).toLatin1() );
00887 if (s.startsWith("charset="))
00888 it = args.erase(it);
00889 else
00890 ++it;
00891 }
00892 if (!encoding.isEmpty())
00893 args.append("charset=" + QUrl::toPercentEncoding(encoding));
00894
00895 if (args.isEmpty())
00896 _setQuery(QString());
00897 else
00898 _setQuery(args.join("&"));
00899 }
00900
00901 QString KUrl::fileEncoding() const
00902 {
00903 if (!isLocalFile())
00904 return QString();
00905
00906 QString q = query();
00907
00908 if (q.isEmpty())
00909 return QString();
00910
00911 if (q[0] == '?')
00912 q = q.mid(1);
00913
00914 const QStringList args = q.split('&', QString::SkipEmptyParts);
00915 for(QStringList::ConstIterator it = args.begin();
00916 it != args.end();
00917 ++it)
00918 {
00919 QString s = QUrl::fromPercentEncoding((*it).toLatin1());
00920 if (s.startsWith("charset="))
00921 return s.mid(8);
00922 }
00923 return QString();
00924 }
00925
00926 inline static bool hasSubUrl( const QUrl& url )
00927 {
00928
00929
00930 if ( url.scheme().isEmpty() )
00931 return false;
00932 const QByteArray ref( url.fragment().toLatin1() );
00933 if (ref.isEmpty())
00934 return false;
00935 switch ( ref.data()[0] ) {
00936 case 'g':
00937 if ( ref.startsWith("gzip:") )
00938 return true;
00939 break;
00940 case 'b':
00941 if ( ref.startsWith("bzip:") || ref.startsWith("bzip2:") )
00942 return true;
00943 break;
00944 case 't':
00945 if ( ref.startsWith("tar:") )
00946 return true;
00947 break;
00948 case 'a':
00949 if ( ref.startsWith("ar:") )
00950 return true;
00951 break;
00952 case 'z':
00953 if ( ref.startsWith("zip:") )
00954 return true;
00955 break;
00956 default:
00957 break;
00958 }
00959 if ( url.scheme() == "error" )
00960 return true;
00961 return false;
00962 }
00963
00964 bool KUrl::hasSubUrl() const
00965 {
00966 return ::hasSubUrl( *this );
00967 }
00968
00969 QString KUrl::url( AdjustPathOption trailing ) const
00970 {
00971 if ( trailing == AddTrailingSlash && !path().endsWith( QLatin1Char('/') ) ) {
00972
00973
00974
00975 QUrl newUrl( *this );
00976 newUrl.setPath( path() + QLatin1Char('/') );
00977 return QString::fromLatin1( newUrl.toEncoded() );
00978 }
00979 else if ( trailing == RemoveTrailingSlash && path() == "/" ) {
00980 return QLatin1String( toEncoded( None ) );
00981 }
00982 return QString::fromLatin1( toEncoded( trailing == RemoveTrailingSlash ? StripTrailingSlash : None ) );
00983 }
00984
00985 static QString toPrettyPercentEncoding(const QString &input)
00986 {
00987 QString result;
00988 for (int i = 0; i < input.length(); ++i) {
00989 QChar c = input.at(i);
00990 register short u = c.unicode();
00991 if (u < 0x20 || u == '?' || u == '#' || u == '%'
00992 || (u == ' ' && (i+1 == input.length() || input.at(i+1) == ' '))) {
00993 static const char hexdigits[] = "0123456789ABCDEF";
00994 result += QLatin1Char('%');
00995 result += QLatin1Char(hexdigits[(u & 0xf0) >> 4]);
00996 result += QLatin1Char(hexdigits[u & 0xf]);
00997 } else {
00998 result += c;
00999 }
01000 }
01001
01002 return result;
01003 }
01004
01005 QString KUrl::prettyUrl( AdjustPathOption trailing ) const
01006 {
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 QString result = scheme();
01017 if (!result.isEmpty())
01018 {
01019 if(!authority().isEmpty() || result == QLatin1String("file"))
01020 result += QLatin1String("://");
01021 else
01022 result += QLatin1String(":");
01023 }
01024
01025 QString tmp = userName();
01026 if (!tmp.isEmpty()) {
01027 result += QUrl::toPercentEncoding(tmp);
01028 result += QLatin1Char('@');
01029 }
01030
01031 result += host();
01032
01033 if (port() != -1) {
01034 result += QLatin1Char(':');
01035 result += QString::number(port());
01036 }
01037
01038 tmp = path();
01039 result += toPrettyPercentEncoding(tmp);
01040
01041
01042 if (trailing == AddTrailingSlash && !tmp.endsWith(QLatin1Char('/')))
01043 result += QLatin1Char('/');
01044 else if (trailing == RemoveTrailingSlash && tmp.length() > 1 && tmp.endsWith(QLatin1Char('/')))
01045 result.chop(1);
01046
01047 if (hasQuery()) {
01048 result += QLatin1Char('?');
01049 result += QLatin1String(encodedQuery());
01050 }
01051
01052 if (hasFragment()) {
01053 result += QLatin1Char('#');
01054 result += toPrettyPercentEncoding(fragment());
01055 }
01056
01057 return result;
01058 }
01059
01060 #if 0
01061 QString KUrl::prettyUrl( int _trailing, AdjustementFlags _flags) const
01062 {
01063 QString u = prettyUrl(_trailing);
01064 if (_flags & StripFileProtocol && u.startsWith("file://")) {
01065 u.remove(0, 7);
01066 #ifdef Q_WS_WIN
01067 return QDir::convertSeparators(u);
01068 #endif
01069 }
01070 return u;
01071 }
01072 #endif
01073
01074 QString KUrl::pathOrUrl() const
01075 {
01076 if ( isLocalFile() && fragment().isNull() && encodedQuery().isNull() ) {
01077 return toLocalFile();
01078 } else {
01079 return prettyUrl();
01080 }
01081 }
01082
01083
01084 QString KUrl::toMimeDataString() const
01085 {
01086 if ( isLocalFile() )
01087 {
01088 #if 1
01089
01090
01091
01092 return url();
01093 #else
01094
01095
01096
01097 const QString s = url( 0, KGlobal::locale()->fileEncodingMib() );
01098 if( !s.startsWith( "file://" ))
01099 {
01100 char hostname[257];
01101 if ( gethostname( hostname, 255 ) == 0 )
01102 {
01103 hostname[256] = '\0';
01104 return QString( "file://" ) + hostname + s.mid( 5 );
01105 }
01106 }
01107 #endif
01108 }
01109
01110 return url();
01111 }
01112
01113 KUrl KUrl::fromMimeDataByteArray( const QByteArray& str )
01114 {
01115 if ( str.startsWith( "file:" ) )
01116 return KUrl( str );
01117
01118 return KUrl( str );
01119 }
01120
01121 KUrl::List KUrl::split( const KUrl& _url )
01122 {
01123 QString ref;
01124 bool hasRef;
01125 KUrl::List lst;
01126 KUrl url = _url;
01127
01128 while(true)
01129 {
01130 KUrl u = url;
01131 u.setFragment( QString() );
01132 lst.append(u);
01133 if (url.hasSubUrl())
01134 {
01135 url = KUrl(url.fragment());
01136 }
01137 else
01138 {
01139 ref = url.fragment();
01140 hasRef = url.hasFragment();
01141 break;
01142 }
01143 }
01144
01145 if ( hasRef )
01146 {
01147
01148 KUrl::List::Iterator it;
01149 for( it = lst.begin() ; it != lst.end(); ++it )
01150 {
01151 (*it).setFragment( ref );
01152 }
01153 }
01154
01155 return lst;
01156 }
01157
01158 KUrl::List KUrl::split( const QString& _url )
01159 {
01160 return split(KUrl(_url));
01161 }
01162
01163 KUrl KUrl::join( const KUrl::List & lst )
01164 {
01165 if (lst.isEmpty()) return KUrl();
01166 KUrl tmp;
01167
01168
01169 bool first = true;
01170 QListIterator<KUrl> it(lst);
01171 it.toBack();
01172 while (it.hasPrevious())
01173 {
01174 KUrl u(it.previous());
01175 if (!first)
01176 {
01177
01178
01179 u.setFragment( tmp.url() );
01180 }
01181 tmp = u;
01182
01183 first = false;
01184 }
01185
01186 return tmp;
01187 }
01188
01189 QString KUrl::fileName( const DirectoryOptions& options ) const
01190 {
01191 Q_ASSERT( options != 0 );
01192 QString fname;
01193 if (hasSubUrl()) {
01194 KUrl::List list = KUrl::split(*this);
01195 return list.last().fileName(options);
01196 }
01197 const QString path = this->path();
01198
01199 int len = path.length();
01200 if ( len == 0 )
01201 return fname;
01202
01203 if (!(options & ObeyTrailingSlash) )
01204 {
01205 while ( len >= 1 && path[ len - 1 ] == QLatin1Char('/') )
01206 len--;
01207 }
01208 else if ( path[ len - 1 ] == QLatin1Char('/') )
01209 return fname;
01210
01211
01212 if ( len == 1 && path[ 0 ] == QLatin1Char('/') )
01213 return fname;
01214
01215
01216 int n = 1;
01217 #if 0
01218 if (!m_strPath_encoded.isEmpty())
01219 {
01220
01221
01222
01223 int i = m_strPath_encoded.lastIndexOf( QLatin1Char('/'), len - 1 );
01224 QString fileName_encoded = m_strPath_encoded.mid(i+1);
01225 n += fileName_encoded.count("%2f", Qt::CaseInsensitive);
01226 }
01227 #endif
01228 int i = len;
01229 do {
01230 i = path.lastIndexOf( QLatin1Char('/'), i - 1 );
01231 }
01232 while (--n && (i > 0));
01233
01234
01235
01236 if ( i == -1 ) {
01237 if ( len == (int)path.length() )
01238 fname = path;
01239 else
01240
01241 fname = path.left( len );
01242 }
01243 else
01244 {
01245 fname = path.mid( i + 1, len - i - 1 );
01246 }
01247 return fname;
01248 }
01249
01250 void KUrl::addPath( const QString& _txt )
01251 {
01252 if (hasSubUrl())
01253 {
01254 KUrl::List lst = split( *this );
01255 KUrl &u = lst.last();
01256 u.addPath(_txt);
01257 *this = join( lst );
01258 return;
01259 }
01260
01261
01262
01263 if ( _txt.isEmpty() )
01264 return;
01265
01266 QString strPath = path();
01267 int i = 0;
01268 int len = strPath.length();
01269
01270 if ( _txt[0] != QLatin1Char('/') && ( len == 0 || strPath[ len - 1 ] != QLatin1Char('/') ) )
01271 strPath += QLatin1Char('/');
01272
01273
01274 i = 0;
01275 const int _txtlen = _txt.length();
01276 if ( strPath.endsWith( QLatin1Char('/') ) )
01277 {
01278 while ( ( i < _txtlen ) && ( _txt[i] == QLatin1Char('/') ) )
01279 ++i;
01280 }
01281
01282 setPath( strPath + _txt.mid( i ) );
01283
01284 }
01285
01286 QString KUrl::directory( const DirectoryOptions& options ) const
01287 {
01288 Q_ASSERT( options != 0 );
01289 QString result = path();
01290 if ( !(options & ObeyTrailingSlash) )
01291 result = trailingSlash( RemoveTrailingSlash, result );
01292
01293 if ( result.isEmpty() || result == "/" )
01294 return result;
01295
01296 int i = result.lastIndexOf( "/" );
01297
01298
01299 if ( i == -1 )
01300 return QString();
01301
01302 if ( i == 0 )
01303 {
01304 result = "/";
01305 return result;
01306 }
01307
01308 if ( options & AppendTrailingSlash )
01309 result = result.left( i + 1 );
01310 else
01311 result = result.left( i );
01312
01313
01314
01315
01316 return result;
01317 }
01318
01319
01320 bool KUrl::cd( const QString& _dir )
01321 {
01322 if ( _dir.isEmpty() || !isValid() )
01323 return false;
01324
01325 if (hasSubUrl())
01326 {
01327 KUrl::List lst = split( *this );
01328 KUrl &u = lst.last();
01329 u.cd(_dir);
01330 *this = join( lst );
01331 return true;
01332 }
01333
01334
01335 #ifdef Q_OS_WIN
01336 if ( !QFileInfo(_dir).isRelative() )
01337 #else
01338 if ( _dir[0] == QLatin1Char('/') )
01339 #endif
01340 {
01341
01342 setPath( _dir );
01343 setHTMLRef( QString() );
01344 setEncodedQuery( QByteArray() );
01345 return true;
01346 }
01347
01348
01349 if ( ( _dir[0] == '~' ) && ( scheme() == "file" ))
01350 {
01351
01352 QString strPath = QDir::homePath();
01353 strPath += QLatin1Char('/');
01354 strPath += _dir.right( strPath.length() - 1 );
01355 setPath( strPath );
01356 setHTMLRef( QString() );
01357 setEncodedQuery( QByteArray() );
01358 return true;
01359 }
01360
01361
01362
01363
01364
01365
01366 QString p = path(AddTrailingSlash);
01367 p += _dir;
01368 p = cleanpath( p, true, false );
01369 setPath( p );
01370
01371 setHTMLRef( QString() );
01372 setEncodedQuery( QByteArray() );
01373
01374 return true;
01375 }
01376
01377 KUrl KUrl::upUrl( ) const
01378 {
01379 if (!encodedQuery().isEmpty())
01380 {
01381 KUrl u(*this);
01382 u.setEncodedQuery(QByteArray());
01383 return u;
01384 };
01385
01386 if (!hasSubUrl())
01387 {
01388 KUrl u(*this);
01389
01390 u.cd("../");
01391
01392 return u;
01393 }
01394
01395
01396 KUrl::List lst = split( *this );
01397 if (lst.isEmpty())
01398 return KUrl();
01399 while (true)
01400 {
01401 KUrl &u = lst.last();
01402 const QString old = u.path();
01403 u.cd("../");
01404 if (u.path() != old)
01405 break;
01406 if (lst.count() == 1)
01407 break;
01408 lst.removeLast();
01409 }
01410 return join( lst );
01411 }
01412
01413 QString KUrl::htmlRef() const
01414 {
01415 if ( !hasSubUrl() )
01416 {
01417 return QUrl::fromPercentEncoding( ref().toLatin1() );
01418 }
01419
01420 List lst = split( *this );
01421 return QUrl::fromPercentEncoding( (*lst.begin()).ref().toLatin1() );
01422 }
01423
01424 QString KUrl::encodedHtmlRef() const
01425 {
01426 if ( !hasSubUrl() )
01427 {
01428 return ref();
01429 }
01430
01431 List lst = split( *this );
01432 return (*lst.begin()).ref();
01433 }
01434
01435 void KUrl::setHTMLRef( const QString& _ref )
01436 {
01437 if ( !hasSubUrl() )
01438 {
01439 setFragment( _ref );
01440 return;
01441 }
01442
01443 List lst = split( *this );
01444
01445 (*lst.begin()).setFragment( _ref );
01446
01447 *this = join( lst );
01448 }
01449
01450 bool KUrl::hasHTMLRef() const
01451 {
01452 if ( !hasSubUrl() )
01453 {
01454 return hasRef();
01455 }
01456
01457 List lst = split( *this );
01458 return (*lst.begin()).hasRef();
01459 }
01460
01461 void KUrl::setDirectory( const QString &dir)
01462 {
01463 if ( dir.endsWith(QLatin1Char('/')))
01464 setPath(dir);
01465 else
01466 setPath(dir + QLatin1Char('/'));
01467 }
01468
01469 void KUrl::setQuery( const QString &_txt )
01470 {
01471 if (!_txt.isEmpty() && _txt[0] == '?')
01472 _setQuery( _txt.length() > 1 ? _txt.mid(1) : "" );
01473 else
01474 _setQuery( _txt );
01475 }
01476
01477 void KUrl::_setQuery( const QString& query )
01478 {
01479 if ( query.isNull() ) {
01480 setEncodedQuery( QByteArray() );
01481 } else if ( query.isEmpty() ) {
01482 setEncodedQuery( "" );
01483 } else {
01484 setEncodedQuery( query.toLatin1() );
01485 }
01486 }
01487
01488 QString KUrl::query() const
01489 {
01490 if (!hasQuery()) {
01491 return QString();
01492 }
01493 return QString( QChar( '?' ) ) + QString::fromAscii( encodedQuery() );
01494 }
01495
01496 void KUrl::_setEncodedUrl(const QByteArray& url)
01497 {
01498 setEncodedUrl(url, QUrl::TolerantMode);
01499 if (!isValid())
01500 setUrl(url, QUrl::TolerantMode);
01501 }
01502
01503 bool urlcmp( const QString& _url1, const QString& _url2 )
01504 {
01505 return QUrl( _url1, QUrl::TolerantMode ) == QUrl( _url2, QUrl::TolerantMode );
01506 #if 0
01507
01508 if ( _url1.isEmpty() && _url2.isEmpty() )
01509 return true;
01510
01511 if ( _url1.isEmpty() || _url2.isEmpty() )
01512 return false;
01513
01514 KUrl::List list1 = KUrl::split( _url1 );
01515 KUrl::List list2 = KUrl::split( _url2 );
01516
01517
01518 if ( list1.isEmpty() || list2.isEmpty() )
01519 return false;
01520
01521 return ( list1 == list2 );
01522 #endif
01523 }
01524
01525 bool urlcmp( const QString& _url1, const QString& _url2, const KUrl::EqualsOptions& _options )
01526 {
01527 QUrl u1( _url1 );
01528 QUrl u2( _url2 );
01529 QUrl::FormattingOptions options = QUrl::None;
01530 if ( _options & KUrl::CompareWithoutTrailingSlash )
01531 options |= QUrl::StripTrailingSlash;
01532 if ( _options & KUrl::CompareWithoutFragment )
01533 options |= QUrl::RemoveFragment;
01534 #ifdef Q_WS_WIN
01535 if ( ::isLocalFile( u1 ) && ::isLocalFile( u2 ) )
01536 return 0 == QString::compare( u1.toString( options ), u2.toString( options ), Qt::CaseInsensitive );
01537 #endif
01538 return u1.toString( options ) == u2.toString( options );
01539
01540 #if 0
01541
01542 if ( _url1.isEmpty() && _url2.isEmpty() )
01543 return true;
01544
01545 if ( _url1.isEmpty() || _url2.isEmpty() )
01546 return false;
01547
01548 KUrl::List list1 = KUrl::split( _url1 );
01549 KUrl::List list2 = KUrl::split( _url2 );
01550
01551
01552 if ( list1.isEmpty() || list2.isEmpty() )
01553 return false;
01554
01555 int size = list1.count();
01556 if ( list2.count() != size )
01557 return false;
01558
01559 if ( _ignore_ref )
01560 {
01561 (*list1.begin()).setRef(QString());
01562 (*list2.begin()).setRef(QString());
01563 }
01564
01565 KUrl::List::Iterator it1 = list1.begin();
01566 KUrl::List::Iterator it2 = list2.begin();
01567 for( ; it1 != list1.end() ; ++it1, ++it2 )
01568 if ( !(*it1).equals( *it2, _ignore_trailing ) )
01569 return false;
01570 return true;
01571 #endif
01572 }
01573
01574
01575 KUrl KUrl::fromPathOrUrl( const QString& text )
01576 {
01577 KUrl url;
01578 if ( !text.isEmpty() )
01579 {
01580 if (!QDir::isRelativePath(text) || text[0] == '~')
01581 url.setPath( text );
01582 else
01583 url = KUrl( text );
01584 }
01585
01586 return url;
01587 }
01588
01589 static QString _relativePath(const QString &base_dir, const QString &path, bool &isParent)
01590 {
01591 QString _base_dir(QDir::cleanPath(base_dir));
01592 QString _path(QDir::cleanPath(path.isEmpty() || (path[0] != QLatin1Char('/')) ? _base_dir+'/'+path : path));
01593
01594 if (_base_dir.isEmpty())
01595 return _path;
01596
01597 if (_base_dir[_base_dir.length()-1] != QLatin1Char('/'))
01598 _base_dir.append(QLatin1Char('/') );
01599
01600 const QStringList list1 = _base_dir.split(QLatin1Char('/'), QString::SkipEmptyParts);
01601 const QStringList list2 = _path.split(QLatin1Char('/'), QString::SkipEmptyParts);
01602
01603
01604 int level = 0;
01605 int maxLevel = qMin(list1.count(), list2.count());
01606 while((level < maxLevel) && (list1[level] == list2[level])) level++;
01607
01608 QString result;
01609
01610 for(int i = level; i < list1.count(); i++)
01611 result.append("../");
01612
01613
01614 for(int i = level; i < list2.count(); i++)
01615 result.append(list2[i]).append("/");
01616
01617 if ((level < list2.count()) && (path[path.length()-1] != QLatin1Char('/')))
01618 result.truncate(result.length()-1);
01619
01620 isParent = (level == list1.count());
01621
01622 return result;
01623 }
01624
01625 QString KUrl::relativePath(const QString &base_dir, const QString &path, bool *isParent)
01626 {
01627 bool parent = false;
01628 QString result = _relativePath(base_dir, path, parent);
01629 if (parent)
01630 result.prepend("./");
01631
01632 if (isParent)
01633 *isParent = parent;
01634
01635 return result;
01636 }
01637
01638
01639 QString KUrl::relativeUrl(const KUrl &base_url, const KUrl &url)
01640 {
01641 if ((url.protocol() != base_url.protocol()) ||
01642 (url.host() != base_url.host()) ||
01643 (url.port() && url.port() != base_url.port()) ||
01644 (url.hasUser() && url.user() != base_url.user()) ||
01645 (url.hasPass() && url.pass() != base_url.pass()))
01646 {
01647 return url.url();
01648 }
01649
01650 QString relURL;
01651
01652 if ((base_url.path() != url.path()) || (base_url.query() != url.query()))
01653 {
01654 bool dummy;
01655 QString basePath = base_url.directory(KUrl::ObeyTrailingSlash);
01656 relURL = _relativePath(basePath, url.path(), dummy);
01657 relURL += url.query();
01658 }
01659
01660 if ( url.hasRef() )
01661 {
01662 relURL += '#';
01663 relURL += url.ref();
01664 }
01665
01666 if ( relURL.isEmpty() )
01667 return "./";
01668
01669 return relURL;
01670 }
01671
01672 void KUrl::setPath( const QString& _path )
01673 {
01674 #ifdef Q_WS_WIN
01675 kDebug(126) << "KUrl::setPath " << " " << _path.toAscii().data();
01676 #endif
01677 if ( scheme().isEmpty() )
01678 setScheme( QLatin1String( "file" ) );
01679 QString path = KShell::tildeExpand( _path );
01680 #ifdef Q_WS_WIN
01681
01682
01683
01684 if( !path.isEmpty() && path[0] != QLatin1Char('/') && scheme() == QLatin1String( "file" ) )
01685 path = QLatin1Char('/') + path;
01686 #endif
01687 QUrl::setPath( path );
01688 }
01689
01690 #if 0 // this would be if we didn't decode '+' into ' '
01691 QMap< QString, QString > KUrl::queryItems( int options ) const {
01692 QMap< QString, QString > result;
01693 const QList<QPair<QString, QString> > items = QUrl::queryItems();
01694 QPair<QString, QString> item;
01695 Q_FOREACH( item, items ) {
01696 result.insert( options & CaseInsensitiveKeys ? item.first.toLower() : item.first, item.second );
01697 }
01698 return result;
01699 }
01700 #endif
01701
01702 QMap< QString, QString > KUrl::queryItems( const QueryItemsOptions &options ) const {
01703 const QString strQueryEncoded = encodedQuery();
01704 if ( strQueryEncoded.isEmpty() )
01705 return QMap<QString,QString>();
01706
01707 QMap< QString, QString > result;
01708 const QStringList items = strQueryEncoded.split( '&', QString::SkipEmptyParts );
01709 for ( QStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
01710 const int equal_pos = (*it).indexOf( '=' );
01711 if ( equal_pos > 0 ) {
01712 QString name = (*it).left( equal_pos );
01713 if ( options & CaseInsensitiveKeys )
01714 name = name.toLower();
01715 QString value = (*it).mid( equal_pos + 1 );
01716 if ( value.isEmpty() )
01717 result.insert( name, QString::fromLatin1("") );
01718 else {
01719
01720 value.replace( '+', ' ' );
01721 result.insert( name, QUrl::fromPercentEncoding( value.toLatin1() ) );
01722 }
01723 } else if ( equal_pos < 0 ) {
01724 QString name = (*it);
01725 if ( options & CaseInsensitiveKeys )
01726 name = name.toLower();
01727 result.insert( name, QString() );
01728 }
01729 }
01730
01731 return result;
01732 }
01733
01734 QString KUrl::queryItem( const QString& _item ) const
01735 {
01736 const QString strQueryEncoded = encodedQuery();
01737 const QString item = _item + '=';
01738 if ( strQueryEncoded.length() <= 1 )
01739 return QString();
01740
01741 const QStringList items = strQueryEncoded.split( '&', QString::SkipEmptyParts );
01742 const int _len = item.length();
01743 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it )
01744 {
01745 if ( (*it).startsWith( item ) )
01746 {
01747 if ( (*it).length() > _len )
01748 {
01749 QString str = (*it).mid( _len );
01750 str.replace( '+', ' ' );
01751 return QUrl::fromPercentEncoding( str.toLatin1() );
01752 }
01753 else
01754 return QString::fromLatin1("");
01755 }
01756 }
01757
01758 return QString();
01759 }
01760
01761 void KUrl::addQueryItem( const QString& _item, const QString& _value )
01762 {
01763 QString item = _item + '=';
01764 QString value = QUrl::toPercentEncoding( _value );
01765
01766 QString strQueryEncoded = encodedQuery();
01767 if (!strQueryEncoded.isEmpty())
01768 strQueryEncoded += '&';
01769 strQueryEncoded += item + value;
01770 setEncodedQuery( strQueryEncoded.toLatin1() );
01771 }
01772
01773 void KUrl::populateMimeData( QMimeData* mimeData,
01774 const MetaDataMap& metaData,
01775 MimeDataFlags flags ) const
01776 {
01777 KUrl::List lst( *this );
01778 lst.populateMimeData( mimeData, metaData, flags );
01779 }
01780
01781 bool KUrl::hasRef() const
01782 {
01783 return hasFragment();
01784 }
01785
01786 void KUrl::setRef( const QString& fragment )
01787 {
01788 if ( fragment.isNull() )
01789 setFragment( fragment );
01790 else
01791 setFragment( QUrl::fromPercentEncoding( fragment.toLatin1() ) );
01792 }
01793
01794 QString KUrl::ref() const
01795 {
01796 if ( fragment().isNull() )
01797 return QString();
01798 else
01799 return QString::fromLatin1( QUrl::toPercentEncoding( fragment() ) );
01800 }
01801
01802 bool KUrl::isParentOf( const KUrl& u ) const
01803 {
01804 return QUrl::isParentOf( u ) || equals( u, CompareWithoutTrailingSlash );
01805 }