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 += "@";
01217 }
01218 bool IPv6 = (m_strHost.find(':') != -1);
01219 if (IPv6)
01220 u += '[' + m_strHost + ']';
01221 else
01222 u += encode(m_strHost, true, encoding_hint);
01223 if ( m_iPort != 0 ) {
01224 QString buffer;
01225 buffer.sprintf( ":%u", m_iPort );
01226 u += buffer;
01227 }
01228 }
01229
01230 u += encodedPathAndQuery( _trailing, false, encoding_hint );
01231
01232 if ( hasRef() )
01233 {
01234 u += "#";
01235 u += m_strRef_encoded;
01236 }
01237
01238 return u;
01239 }
01240
01241 QString KURL::prettyURL( int _trailing ) const
01242 {
01243 if( m_bIsMalformed )
01244 {
01245
01246
01247
01248 return m_strProtocol;
01249 }
01250
01251 QString u = m_strProtocol;
01252 if (!u.isEmpty())
01253 u += ":";
01254
01255 if ( hasHost() )
01256 {
01257 u += "//";
01258 if ( hasUser() )
01259 {
01260 u += lazy_encode(m_strUser);
01261
01262 u += "@";
01263 }
01264 bool IPv6 = (m_strHost.find(':') != -1);
01265 if (IPv6)
01266 u += '[' + m_strHost + ']';
01267 else
01268 u += lazy_encode(m_strHost);
01269 if ( m_iPort != 0 ) {
01270 QString buffer;
01271 buffer.sprintf( ":%u", m_iPort );
01272 u += buffer;
01273 }
01274 }
01275
01276 u += trailingSlash( _trailing, lazy_encode( m_strPath ) );
01277 if (!m_strQuery_encoded.isNull())
01278 u += '?' + m_strQuery_encoded;
01279
01280 if ( hasRef() )
01281 {
01282 u += "#";
01283 u += m_strRef_encoded;
01284 }
01285
01286 return u;
01287 }
01288
01289 QString KURL::prettyURL( int _trailing, AdjustementFlags _flags) const
01290 {
01291 QString u = prettyURL(_trailing);
01292 if (_flags & StripFileProtocol && u.startsWith("file:"))
01293 u.remove(0, 5);
01294 return u;
01295 }
01296
01297 QString KURL::htmlURL() const
01298 {
01299 return QStyleSheet::escape(prettyURL());
01300 }
01301
01302 KURL::List KURL::split( const KURL& _url )
01303 {
01304 QString ref;
01305 KURL::List lst;
01306 KURL url = _url;
01307
01308 while(true)
01309 {
01310 KURL u = url;
01311 u.m_strRef_encoded = QString::null;
01312 lst.append(u);
01313 if (url.hasSubURL())
01314 {
01315 url = KURL(url.m_strRef_encoded);
01316 }
01317 else
01318 {
01319 ref = url.m_strRef_encoded;
01320 break;
01321 }
01322 }
01323
01324
01325 KURL::List::Iterator it;
01326 for( it = lst.begin() ; it != lst.end(); ++it )
01327 {
01328 (*it).m_strRef_encoded = ref;
01329 }
01330
01331 return lst;
01332 }
01333
01334 KURL::List KURL::split( const QString& _url )
01335 {
01336 return split(KURL(_url));
01337 }
01338
01339 KURL KURL::join( const KURL::List & lst )
01340 {
01341 if (lst.isEmpty()) return KURL();
01342 KURL tmp;
01343
01344 KURL::List::ConstIterator first = lst.fromLast();
01345 for( KURL::List::ConstIterator it = first; it != lst.end(); --it )
01346 {
01347 KURL u(*it);
01348 if (it != first)
01349 {
01350 u.m_strRef_encoded = tmp.url();
01351 }
01352 tmp = u;
01353 }
01354
01355 return tmp;
01356 }
01357
01358 QString KURL::fileName( bool _strip_trailing_slash ) const
01359 {
01360 QString fname;
01361 const QString &path = m_strPath;
01362
01363 int len = path.length();
01364 if ( len == 0 )
01365 return fname;
01366
01367 if ( _strip_trailing_slash )
01368 {
01369 while ( len >= 1 && path[ len - 1 ] == '/' )
01370 len--;
01371 }
01372 else if ( path[ len - 1 ] == '/' )
01373 return fname;
01374
01375
01376 if ( len == 1 && path[ 0 ] == '/' )
01377 return fname;
01378
01379
01380 int n = 1;
01381 if (!m_strPath_encoded.isEmpty())
01382 {
01383
01384
01385
01386 int i = m_strPath_encoded.findRev( '/', len - 1 );
01387 QString fileName_encoded = m_strPath_encoded.mid(i+1);
01388 n += fileName_encoded.contains("%2f", false);
01389 }
01390 int i = len;
01391 do {
01392 i = path.findRev( '/', i - 1 );
01393 }
01394 while (--n && (i > 0));
01395
01396
01397
01398 if ( i == -1 ) {
01399 if ( len == (int)path.length() )
01400 fname = path;
01401 else
01402
01403 fname = path.left( len );
01404 }
01405 else
01406 {
01407 fname = path.mid( i + 1, len - i - 1 );
01408 }
01409 return fname;
01410 }
01411
01412 void KURL::addPath( const QString& _txt )
01413 {
01414 m_strPath_encoded = QString::null;
01415
01416 if ( _txt.isEmpty() )
01417 return;
01418
01419 int i = 0;
01420 int len = m_strPath.length();
01421
01422 if ( len == 0 ) {
01423 while( _txt[i] == '/' ) ++i;
01424 }
01425
01426 else if ( _txt[0] != '/' && ( len == 0 || m_strPath[ len - 1 ] != '/' ) )
01427 m_strPath += "/";
01428
01429
01430 i = 0;
01431 if ( len != 0 && m_strPath[ len - 1 ] == '/' )
01432 {
01433 while( _txt[i] == '/' )
01434 ++i;
01435 }
01436
01437 m_strPath += _txt.mid( i );
01438 }
01439
01440 QString KURL::directory( bool _strip_trailing_slash_from_result,
01441 bool _ignore_trailing_slash_in_path ) const
01442 {
01443 QString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
01444 if ( _ignore_trailing_slash_in_path )
01445 result = trailingSlash( -1, result );
01446
01447 if ( result.isEmpty() || result == "/" )
01448 return result;
01449
01450 int i = result.findRev( "/" );
01451
01452
01453 if ( i == -1 )
01454 return QString::null;
01455
01456 if ( i == 0 )
01457 {
01458 result = "/";
01459 return result;
01460 }
01461
01462 if ( _strip_trailing_slash_from_result )
01463 result = result.left( i );
01464 else
01465 result = result.left( i + 1 );
01466
01467 if (!m_strPath_encoded.isEmpty())
01468 result = decode(result);
01469
01470 return result;
01471 }
01472
01473
01474 bool KURL::cd( const QString& _dir )
01475 {
01476 if ( _dir.isEmpty() || m_bIsMalformed )
01477 return false;
01478
01479 if (hasSubURL())
01480 {
01481 KURL::List lst = split( *this );
01482 KURL &u = lst.last();
01483 u.cd(_dir);
01484 *this = join( lst );
01485 return true;
01486 }
01487
01488
01489 if ( _dir[0] == '/' )
01490 {
01491 m_strPath_encoded = QString::null;
01492 m_strPath = _dir;
01493 setHTMLRef( QString::null );
01494 m_strQuery_encoded = QString::null;
01495 return true;
01496 }
01497
01498
01499 if ( ( _dir[0] == '~' ) && ( m_strProtocol == "file" ))
01500 {
01501 m_strPath_encoded = QString::null;
01502 m_strPath = QDir::homeDirPath();
01503 m_strPath += "/";
01504 m_strPath += _dir.right(m_strPath.length() - 1);
01505 setHTMLRef( QString::null );
01506 m_strQuery_encoded = QString::null;
01507 return true;
01508 }
01509
01510
01511
01512
01513
01514
01515 QString p = path(1);
01516 p += _dir;
01517 p = cleanpath( p );
01518 setPath( p );
01519
01520 setHTMLRef( QString::null );
01521 m_strQuery_encoded = QString::null;
01522
01523 return true;
01524 }
01525
01526 KURL KURL::upURL( ) const
01527 {
01528 if (!query().isEmpty())
01529 {
01530 KURL u(*this);
01531 u.setQuery(QString::null);
01532 return u;
01533 };
01534
01535 if (!hasSubURL())
01536 {
01537 KURL u(*this);
01538 u.cd("../");
01539 return u;
01540 }
01541
01542
01543 KURL::List lst = split( *this );
01544 if (lst.isEmpty())
01545 return KURL();
01546 while (true)
01547 {
01548 KURL &u = lst.last();
01549 QString old = u.path();
01550 u.cd("../");
01551 if (u.path() != old)
01552 break;
01553 if (lst.count() == 1)
01554 break;
01555 lst.remove(lst.fromLast());
01556 }
01557 return join( lst );
01558 }
01559
01560 QString KURL::htmlRef() const
01561 {
01562 if ( !hasSubURL() )
01563 {
01564 return decode( ref() );
01565 }
01566
01567 List lst = split( *this );
01568 return decode( (*lst.begin()).ref() );
01569 }
01570
01571 QString KURL::encodedHtmlRef() const
01572 {
01573 if ( !hasSubURL() )
01574 {
01575 return ref();
01576 }
01577
01578 List lst = split( *this );
01579 return (*lst.begin()).ref();
01580 }
01581
01582 void KURL::setHTMLRef( const QString& _ref )
01583 {
01584 if ( !hasSubURL() )
01585 {
01586 m_strRef_encoded = encode( _ref, true, 0 );
01587 return;
01588 }
01589
01590 List lst = split( *this );
01591
01592 (*lst.begin()).setRef( encode( _ref, true, 0 ) );
01593
01594 *this = join( lst );
01595 }
01596
01597 bool KURL::hasHTMLRef() const
01598 {
01599 if ( !hasSubURL() )
01600 {
01601 return hasRef();
01602 }
01603
01604 List lst = split( *this );
01605 return (*lst.begin()).hasRef();
01606 }
01607
01608 void
01609 KURL::setProtocol( const QString& _txt )
01610 {
01611 m_strProtocol = _txt;
01612 m_bIsMalformed = false;
01613 }
01614
01615 void
01616 KURL::setUser( const QString& _txt )
01617 {
01618 m_strUser = _txt;
01619 }
01620
01621 void
01622 KURL::setPass( const QString& _txt )
01623 {
01624 m_strPass = _txt;
01625 }
01626
01627 void
01628 KURL::setHost( const QString& _txt )
01629 {
01630 m_strHost = _txt;
01631 }
01632
01633 void
01634 KURL::setPort( unsigned short int _p )
01635 {
01636 m_iPort = _p;
01637 }
01638
01639 void KURL::setPath( const QString & path )
01640 {
01641 if (isEmpty())
01642 m_bIsMalformed = false;
01643 if (m_strProtocol.isEmpty())
01644 m_strProtocol = "file";
01645 m_strPath = path;
01646 m_strPath_encoded = QString::null;
01647 }
01648
01649 void KURL::setQuery( const QString &_txt, int encoding_hint)
01650 {
01651 if (!_txt.length())
01652 {
01653 m_strQuery_encoded = _txt;
01654 return;
01655 }
01656 if (_txt[0] =='?')
01657 m_strQuery_encoded = _txt.mid(1);
01658 else
01659 m_strQuery_encoded = _txt;
01660
01661 int l = m_strQuery_encoded.length();
01662 int i = 0;
01663 QString result;
01664 while (i < l)
01665 {
01666 int s = i;
01667
01668
01669 while(i < l)
01670 {
01671 char c = m_strQuery_encoded[i].latin1();
01672 if ((c == '&') || (c == ':') || (c == ';') ||
01673 (c == '=') || (c == '/') || (c == '?'))
01674 break;
01675 i++;
01676 }
01677 if (i > s)
01678 {
01679 QString tmp = m_strQuery_encoded.mid(s, i-s);
01680 QString newTmp;
01681 decode( tmp, newTmp, tmp, encoding_hint, false );
01682 result += tmp;
01683 }
01684 if (i < l)
01685 {
01686 result += m_strQuery_encoded[i];
01687 i++;
01688 }
01689 }
01690 m_strQuery_encoded = result;
01691 }
01692
01693 QString KURL::query() const
01694 {
01695 if (m_strQuery_encoded.isNull())
01696 return QString::null;
01697 return '?'+m_strQuery_encoded;
01698 }
01699
01700 QString KURL::decode_string(const QString &str, int encoding_hint)
01701 {
01702 return decode(str, encoding_hint);
01703 }
01704
01705 QString KURL::encode_string(const QString &str, int encoding_hint)
01706 {
01707 return encode(str, false, encoding_hint);
01708 }
01709
01710 QString KURL::encode_string_no_slash(const QString &str, int encoding_hint)
01711 {
01712 return encode(str, true, encoding_hint);
01713 }
01714
01715 bool urlcmp( const QString& _url1, const QString& _url2 )
01716 {
01717
01718 if ( _url1.isEmpty() && _url2.isEmpty() )
01719 return true;
01720
01721 if ( _url1.isEmpty() || _url2.isEmpty() )
01722 return false;
01723
01724 KURL::List list1 = KURL::split( _url1 );
01725 KURL::List list2 = KURL::split( _url2 );
01726
01727
01728 if ( list1.isEmpty() || list2.isEmpty() )
01729 return false;
01730
01731 return ( list1 == list2 );
01732 }
01733
01734 bool urlcmp( const QString& _url1, const QString& _url2, bool _ignore_trailing, bool _ignore_ref )
01735 {
01736
01737 if ( _url1.isEmpty() && _url2.isEmpty() )
01738 return true;
01739
01740 if ( _url1.isEmpty() || _url2.isEmpty() )
01741 return false;
01742
01743 KURL::List list1 = KURL::split( _url1 );
01744 KURL::List list2 = KURL::split( _url2 );
01745
01746
01747 if ( list1.isEmpty() || list2.isEmpty() )
01748 return false;
01749
01750 unsigned int size = list1.count();
01751 if ( list2.count() != size )
01752 return false;
01753
01754 if ( _ignore_ref )
01755 {
01756 (*list1.begin()).setRef(QString::null);
01757 (*list2.begin()).setRef(QString::null);
01758 }
01759
01760 KURL::List::Iterator it1 = list1.begin();
01761 KURL::List::Iterator it2 = list2.begin();
01762 for( ; it1 != list1.end() ; ++it1, ++it2 )
01763 if ( !(*it1).equals( *it2, _ignore_trailing ) )
01764 return false;
01765
01766 return true;
01767 }
01768
01769 QMap< QString, QString > KURL::queryItems( int options ) const {
01770 if ( m_strQuery_encoded.isEmpty() )
01771 return QMap<QString,QString>();
01772
01773 QMap< QString, QString > result;
01774 QStringList items = QStringList::split( '&', m_strQuery_encoded );
01775 for ( QStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
01776 int equal_pos = (*it).find( '=' );
01777 if ( equal_pos > 0 ) {
01778 QString name = (*it).left( equal_pos );
01779 if ( options & CaseInsensitiveKeys )
01780 name = name.lower();
01781 QString value = (*it).mid( equal_pos + 1 );
01782 if ( value.isEmpty() )
01783 result.insert( name, QString::fromLatin1("") );
01784 else {
01785
01786 value.replace( '+', ' ' );
01787 result.insert( name, decode_string( value ) );
01788 }
01789 } else if ( equal_pos < 0 ) {
01790 QString name = (*it);
01791 if ( options & CaseInsensitiveKeys )
01792 name = name.lower();
01793 result.insert( name, QString::null );
01794 }
01795 }
01796
01797 return result;
01798 }
01799
01800 QString KURL::queryItem( const QString& _item ) const
01801 {
01802 QString item = _item + '=';
01803 if ( m_strQuery_encoded.length() <= 1 )
01804 return QString::null;
01805
01806 QStringList items = QStringList::split( '&', m_strQuery_encoded );
01807 unsigned int _len = item.length();
01808 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it )
01809 {
01810 if ( (*it).startsWith( item ) )
01811 {
01812 if ( (*it).length() > _len )
01813 {
01814 QString str = (*it).mid( _len );
01815 str.replace( '+', ' ' );
01816 return decode_string( str );
01817 }
01818 else
01819 return QString::fromLatin1("");
01820 }
01821 }
01822
01823 return QString::null;
01824 }
01825
01826 void KURL::removeQueryItem( const QString& _item )
01827 {
01828 QString item = _item + '=';
01829 if ( m_strQuery_encoded.length() <= 1 )
01830 return;
01831
01832 QStringList items = QStringList::split( '&', m_strQuery_encoded );
01833 for ( QStringList::Iterator it = items.begin(); it != items.end(); )
01834 {
01835 if ( (*it).startsWith( item ) || (*it == _item) )
01836 {
01837 QStringList::Iterator deleteIt = it;
01838 ++it;
01839 items.remove(deleteIt);
01840 }
01841 else
01842 {
01843 ++it;
01844 }
01845 }
01846 m_strQuery_encoded = items.join( "&" );
01847 }
01848
01849 void KURL::addQueryItem( const QString& _item, const QString& _value, int encoding_hint )
01850 {
01851 QString item = _item + '=';
01852 QString value = encode( _value, true, encoding_hint );
01853
01854 if (!m_strQuery_encoded.isEmpty())
01855 m_strQuery_encoded += '&';
01856 m_strQuery_encoded += item + value;
01857 }
01858
01859
01860 KURL KURL::fromPathOrURL( const QString& text )
01861 {
01862 if ( text.isEmpty() )
01863 return KURL();
01864
01865 KURL url;
01866 if ( text[0] == '/' )
01867 url.setPath( text );
01868 else
01869 url = text;
01870
01871 return url;
01872 }