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