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