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