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