30 #include <tdeglobal.h>
32 #include <kprotocolinfo.h>
43 #include <tqstringlist.h>
45 #include <tqstylesheet.h>
47 #include <tqtextcodec.h>
51 # define KURL_ROOTDIR_PATH "C:/"
53 # define KURL_ROOTDIR_PATH "/"
56 static const TQString fileProt =
"file";
58 static TQTextCodec * codecForHint(
int encoding_hint )
60 return TQTextCodec::codecForMib( encoding_hint );
67 static TQString encode(
const TQString& segment,
int encoding_offset,
int encoding_hint,
bool isRawURI =
false )
69 const char *encode_string =
"/@<>#\"&?={}|^~[]\'`\\:+%";
70 encode_string += encoding_offset;
74 local = segment.local8Bit();
77 TQTextCodec * textCodec = codecForHint( encoding_hint );
79 local = segment.local8Bit();
81 local = textCodec->fromUnicode( segment );
84 int old_length = isRawURI ? local.size() - 1 : local.length();
87 return segment.isNull() ? TQString::null : TQString(
"");
90 TQChar *new_segment =
new TQChar[ old_length * 3 + 1 ];
93 for (
int i = 0; i < old_length; i++ )
99 unsigned char character = local[i];
100 if ( (character <= 32) || (character >= 127) ||
101 strchr(encode_string, character) )
103 new_segment[ new_length++ ] =
'%';
105 unsigned int c = character / 16;
106 c += (c > 9) ? (
'A' - 10) :
'0';
107 new_segment[ new_length++ ] = c;
110 c += (c > 9) ? (
'A' - 10) :
'0';
111 new_segment[ new_length++ ] = c;
115 new_segment[ new_length++ ] = (TQChar)local[i];
118 TQString result = TQString(new_segment, new_length);
119 delete [] new_segment;
123 static TQString encodeHost(
const TQString& segment,
bool encode_slash,
int encoding_hint )
130 Q_UNUSED( encode_slash );
131 Q_UNUSED( encoding_hint );
132 TQString host = KIDNA::toAscii(segment);
137 return encode(segment, encode_slash ? 0 : 1, encoding_hint);
141 static int hex2int(
unsigned int _char )
143 if ( _char >=
'A' && _char <=
'F')
144 return _char -
'A' + 10;
145 if ( _char >=
'a' && _char <=
'f')
146 return _char -
'a' + 10;
147 if ( _char >=
'0' && _char <=
'9')
162 static TQString lazy_encode(
const TQString& segment,
bool encodeAt=
true )
164 int old_length = segment.length();
167 return TQString::null;
170 TQChar *new_segment =
new TQChar[ old_length * 3 + 1 ];
173 for (
int i = 0; i < old_length; i++ )
175 unsigned int character = segment[i].unicode();
178 if ((character < 32) ||
179 ((character ==
'%') &&
180 (i+2 < old_length) &&
181 (hex2int(segment[i+1].unicode())!= -1) &&
182 (hex2int(segment[i+2].unicode())!= -1)) ||
183 (character ==
'?') ||
184 ((character ==
'@') && encodeAt) ||
185 (character ==
'#') ||
186 ((character == 32) && (i+1 == old_length || segment[i+1] == (TQChar)
' ')))
188 new_segment[ new_length++ ] =
'%';
190 unsigned int c = character / 16;
191 c += (c > 9) ? (
'A' - 10) :
'0';
192 new_segment[ new_length++ ] = c;
195 c += (c > 9) ? (
'A' - 10) :
'0';
196 new_segment[ new_length++ ] = c;
199 new_segment[ new_length++ ] = segment[i];
202 TQString result = TQString(new_segment, new_length);
203 delete [] new_segment;
207 static void decode(
const TQString& segment, TQString &decoded, TQString &encoded,
int encoding_hint=0,
bool updateDecoded =
true,
bool isRawURI =
false )
209 decoded = TQString::null;
212 int old_length = segment.length();
216 TQTextCodec *textCodec = 0;
218 textCodec = codecForHint( encoding_hint );
221 textCodec = TQTextCodec::codecForLocale();
223 TQCString csegment = textCodec->fromUnicode(segment);
225 if (textCodec->toUnicode(csegment) != segment)
228 textCodec = codecForHint( 106 );
229 csegment = textCodec->fromUnicode(segment);
231 old_length = csegment.length();
237 char *new_segment =
new char[ old_length + 1 ];
238 TQChar *new_usegment =
new TQChar[ old_length * 3 + 1 ];
241 while( i < old_length )
243 bool bReencode =
false;
244 unsigned char character = csegment[ i++ ];
245 if ((character <=
' ') || (character > 127))
248 new_usegment [ new_length2++ ] = character;
249 if (character ==
'%' )
251 int a = i+1 < old_length ? hex2int( csegment[i] ) : -1;
252 int b = i+1 < old_length ? hex2int( csegment[i+1] ) : -1;
253 if ((a == -1) || (b == -1))
261 character = a * 16 + b;
262 if (!isRawURI && !character && updateDecoded)
265 new_usegment [ new_length2++ ] = (
unsigned char) csegment[i++];
266 new_usegment [ new_length2++ ] = (
unsigned char) csegment[i++];
272 new_usegment [ new_length2++ ] =
'%';
274 unsigned int c = character / 16;
275 c += (c > 9) ? (
'A' - 10) :
'0';
276 new_usegment[ new_length2++ ] = c;
279 c += (c > 9) ? (
'A' - 10) :
'0';
280 new_usegment[ new_length2++ ] = c;
283 new_segment [ new_length++ ] = character;
285 new_segment [ new_length ] = 0;
287 encoded = TQString( new_usegment, new_length2);
292 decoded = textCodec->toUnicode( new_segment );
294 int length = tqstrlen( new_segment );
295 while ( length < new_length ) {
296 decoded += TQChar::null;
298 decoded += textCodec->toUnicode( new_segment + length );
299 length += tqstrlen( new_segment + length );
303 TQCString validate = textCodec->fromUnicode(decoded);
305 if (strcmp(validate.data(), new_segment) != 0)
307 decoded = TQString::fromLocal8Bit(new_segment, new_length);
311 delete [] new_segment;
312 delete [] new_usegment;
315 static TQString decode(
const TQString &segment,
int encoding_hint = 0,
bool isRawURI =
false)
319 decode(segment, result, tmp, encoding_hint,
true, isRawURI);
323 static TQString cleanpath(
const TQString &_path,
bool cleanDirSeparator,
bool decodeDots)
325 if (_path.isEmpty())
return TQString::null;
327 if (TQDir::isRelativePath(_path))
330 TQString path = _path;
332 int len = path.length();
339 TQString encodedDot(
"%2e");
341 if (path.find(encodedDot, 0,
false) != -1)
346 TQString encodedDOT(
"%2E");
348 path.replace(encodedDot,
".");
349 path.replace(encodedDOT,
".");
354 bool slash = (len && path[len-1] ==
'/') ||
355 (len > 1 && path[len-2] ==
'/' && path[len-1] ==
'.');
364 int cdUp, orig_pos, pos;
367 pos = orig_pos = len;
368 while ( pos && (pos = path.findRev(
'/',--pos)) != -1 )
370 len = orig_pos - pos - 1;
371 if ( len == 2 && path[pos+1] ==
'.' && path[pos+2] ==
'.' )
377 if ( (len || !cleanDirSeparator) &&
378 (len != 1 || path[pos+1] !=
'.' ) )
381 result.prepend(path.mid(pos, len+1));
389 #ifdef Q_WS_WIN // prepend drive letter if exists (js)
390 if (orig_pos >= 2 && isalpha(path[0].latin1()) && path[1]==
':') {
391 result.prepend(TQString(path[0])+
":");
395 if ( result.isEmpty() )
396 result = KURL_ROOTDIR_PATH;
397 else if ( slash && result[result.length()-1] !=
'/' )
406 TQString m_strInternalReferenceURL;
411 int len = _url.length();
412 if (!len)
return true;
413 const TQChar *str = _url.unicode();
416 if (!isalpha(str[0].latin1()))
419 for(
int i = 1; i < len; i++)
421 char c = str[i].latin1();
426 if (!isalpha(c) && !isdigit(c) && (c !=
'+') && (c !=
'-'))
440 for (TQStringList::ConstIterator it = list.begin();
451 for( KURL::List::ConstIterator it = begin();
455 lst.append( (*it).url() );
463 d =
new KURLPrivate();
477 d =
new KURLPrivate();
479 parse( url, encoding_hint );
484 d =
new KURLPrivate();
486 parse( TQString::fromLatin1(url), encoding_hint );
491 d =
new KURLPrivate();
493 parse( TQString::fromLatin1(url), encoding_hint );
498 d =
new KURLPrivate();
500 d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
503 TQDataStream & operator<< (TQDataStream & s,
const KURL & a)
505 TQString QueryForWire=a.m_strQuery_encoded;
506 if (!a.m_strQuery_encoded.isNull())
507 QueryForWire.prepend(
"?");
509 s << a.m_strProtocol << a.m_strUser << a.m_strPass << a.m_strHost
510 << a.m_strPath << a.m_strPath_encoded << QueryForWire << a.m_strRef_encoded
511 << TQ_INT8(a.m_bIsMalformed ? 1 : 0) << a.m_iPort;
515 TQDataStream & operator>> (TQDataStream & s,
KURL & a)
518 TQString QueryFromWire;
519 s >> a.m_strProtocol >> a.m_strUser >> a.m_strPass >> a.m_strHost
520 >> a.m_strPath >> a.m_strPath_encoded >> QueryFromWire >> a.m_strRef_encoded
521 >> malf >> a.m_iPort;
522 a.m_bIsMalformed = (malf != 0);
524 if ( QueryFromWire.isNull() )
525 a.m_strQuery_encoded = TQString::null;
526 else if ( QueryFromWire.length() == 1 )
527 a.m_strQuery_encoded =
"";
529 a.m_strQuery_encoded = QueryFromWire.mid(1);
536 #ifndef QT_NO_NETWORKPROTOCOL
539 d =
new KURLPrivate();
546 d =
new KURLPrivate();
547 d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
552 KURL u(lst.last(), _rel_url, encoding_hint);
553 lst.remove( lst.last() );
556 d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
562 TQString rUrl = _rel_url;
563 int len = _u.m_strProtocol.length();
564 if ( !_u.m_strHost.isEmpty() && !rUrl.isEmpty() &&
565 rUrl.find( _u.m_strProtocol, 0,
false ) == 0 &&
566 rUrl[len] ==
':' && (rUrl[len+1] !=
'/' ||
567 (rUrl[len+1] ==
'/' && rUrl[len+2] !=
'/')) )
569 rUrl.remove( 0, rUrl.find(
':' ) + 1 );
572 if ( rUrl.isEmpty() )
576 else if ( rUrl[0] ==
'#' )
579 m_strRef_encoded = rUrl.mid(1);
580 if ( m_strRef_encoded.isNull() )
581 m_strRef_encoded =
"";
586 m_strQuery_encoded = TQString::null;
587 m_strRef_encoded = TQString::null;
590 if ((rUrl.length() > 1) && (rUrl[1] ==
'/'))
592 m_strHost = TQString::null;
594 if (_u.m_strProtocol == fileProt)
597 m_strPath = TQString::null;
598 m_strPath_encoded = TQString::null;
600 else if ( rUrl[0] !=
'?' )
602 int pos = m_strPath.findRev(
'/' );
604 m_strPath.truncate(pos);
606 if (!m_strPath_encoded.isEmpty())
608 pos = m_strPath_encoded.findRev(
'/' );
610 m_strPath_encoded.truncate(pos);
611 m_strPath_encoded +=
'/';
616 if ( m_strPath.isEmpty() )
619 KURL tmp(
url() + rUrl, encoding_hint);
625 KURL tmp( rUrl, encoding_hint);
628 if (!_u.m_strUser.isEmpty() && m_strUser.isEmpty() && (_u.m_strHost == m_strHost) && (_u.m_strProtocol == m_strProtocol))
630 m_strUser = _u.m_strUser;
631 m_strPass = _u.m_strPass;
639 m_strProtocol = TQString::null;
640 m_strUser = TQString::null;
641 m_strPass = TQString::null;
642 m_strHost = TQString::null;
643 m_strPath = TQString::null;
644 m_strPath_encoded = TQString::null;
645 m_strQuery_encoded = TQString::null;
646 m_strRef_encoded = TQString::null;
647 m_bIsMalformed =
true;
654 return (m_strPath.isEmpty() && m_strProtocol.isEmpty());
659 if ( _url.isEmpty() || m_iUriMode ==
Invalid )
661 m_strProtocol = _url;
666 const TQChar* buf = _url.unicode();
667 const TQChar* orig = buf;
668 uint len = _url.length();
672 TQChar x = buf[pos++];
675 const bool alpha = isalpha((
int)x);
678 if (alpha && buf[pos]==
':' && (len==2 || (len>2 && (buf[pos+1]==
'/' || buf[pos+1]==
'\\'))))
680 if ( x == (TQChar)
'/' )
685 m_strProtocol = fileProt;
689 if ( !isalpha( (
int)x ) )
695 while( pos < len && (isalpha((
int)buf[pos]) || isdigit((
int)buf[pos]) ||
696 buf[pos] == (TQChar)
'+' || buf[pos] == (TQChar)
'-')) pos++;
698 if (pos < len && buf[pos] == (TQChar)
':' )
700 m_strProtocol = TQString( orig, pos ).lower();
701 if ( m_iUriMode ==
Auto )
704 switch ( m_iUriMode )
723 m_strProtocol = _url;
729 uint len = _url.length();
730 const TQChar* buf = _url.unicode();
737 while( pos < len && (isalpha((
int)buf[pos]) || isdigit((
int)buf[pos]) ||
738 buf[pos] == (TQChar)
'+' || buf[pos] == (TQChar)
'-')) pos++;
741 if (pos < len && buf[pos] == (TQChar)
':' )
745 m_strProtocol = _url;
751 m_strPath = TQString::null;
753 m_strPath = decode( TQString( buf + pos, len - pos ), encoding_hint,
true );
755 m_bIsMalformed =
false;
763 if ( m_bIsMalformed )
765 TQRegExp mailre(
"(.+@)(.+)");
766 if ( mailre.exactMatch( m_strPath ) )
769 TQString host = KIDNA::toUnicode( mailre.cap( 2 ) );
771 host = TQString(mailre.cap( 2 )).lower();
773 TQString host = TQString(mailre.cap( 2 )).lower();
775 m_strPath = mailre.cap( 1 ) +
host;
782 bool badHostName =
false;
784 uint len = _url.length();
785 const TQChar* buf = _url.unicode();
793 TQChar x = buf[pos++];
796 const bool alpha = isalpha((
int)x);
799 if (alpha && buf[pos]==(TQChar)
':' && (len==2 || (len>2 && (buf[pos+1]==(TQChar)
'/' || buf[pos+1]==(TQChar)
'\\'))))
801 if ( x == (TQChar)
'/' )
804 if ( !isalpha( (
int)x ) )
810 while( pos < len && (isalpha((
int)buf[pos]) || isdigit((
int)buf[pos]) ||
811 buf[pos] == (TQChar)
'+' || buf[pos] == (TQChar)
'-')) pos++;
814 if ( pos+2 < len && buf[pos] == (TQChar)
':' && buf[pos+1] == (TQChar)
'/' && buf[pos+2] == (TQChar)
'/' )
818 else if (pos+1 < len && buf[pos] == (TQChar)
':' )
833 if (buf[pos] == (TQChar)
'[')
837 while( (x != (TQChar)
':') && (x != (TQChar)
'@') && (x != (TQChar)
'/') && (x != (TQChar)
'?') && (x != (TQChar)
'#') )
839 if ((x == (TQChar)
'\"') || (x == (TQChar)
';') || (x == (TQChar)
'<'))
850 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
853 if ( x == (TQChar)
'@' )
855 m_strUser = decode(TQString( buf + start, pos - start ), encoding_hint);
859 else if ( (x == (TQChar)
'/') || (x == (TQChar)
'?') || (x == (TQChar)
'#'))
864 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
868 else if ( x != (TQChar)
':' )
870 m_strUser = decode(TQString( buf + start, pos - start ), encoding_hint);
879 while( (pos < len) &&
880 (buf[pos] != (TQChar)
'@') &&
881 (buf[pos] != (TQChar)
'/') &&
882 (buf[pos] != (TQChar)
'?') &&
883 (buf[pos] != (TQChar)
'#')) pos++;
886 if ( (pos == len) || (buf[pos] != (TQChar)
'@') )
892 m_strUser = TQString::null;
893 TQString tmp( buf + start, pos - start );
895 m_iPort = (
unsigned short int)strtol(tmp.ascii(), &endptr, 10);
896 if ((pos == len) && (strlen(endptr) == 0))
899 pos -= strlen(endptr);
900 if ((buf[pos] != (TQChar)
'@') &&
901 (buf[pos] != (TQChar)
'/') &&
902 (buf[pos] != (TQChar)
'?') &&
903 (buf[pos] != (TQChar)
'#'))
909 m_strPass = decode(TQString( buf + start, pos - start), encoding_hint);
918 if (buf[pos] == (TQChar)
'[')
931 while( (x != (TQChar)
']') )
933 if ((x == (TQChar)
'\"') || (x == (TQChar)
';') || (x == (TQChar)
'<'))
944 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
945 if (pos < len) pos++;
957 while( (x != (TQChar)
':') && (x != (TQChar)
'@') && (x != (TQChar)
'/') && (x != (TQChar)
'?') && (x != (TQChar)
'#') )
959 if ((x == (TQChar)
'\"') || (x == (TQChar)
';') || (x == (TQChar)
'<'))
969 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
972 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
975 if ( x == (TQChar)
'/' || x == (TQChar)
'#' || x == (TQChar)
'?' )
980 else if ( x != (TQChar)
':' )
988 if ( !isdigit( buf[pos++] ) )
992 while( pos < len && isdigit( buf[pos] ) ) pos++;
993 port = TQString( buf + start, pos - start );
994 m_iPort = port.toUShort();
1001 while( pos < len && buf[pos] != (TQChar)
'#' && buf[pos]!=(TQChar)
'?' ) pos++;
1003 tmp = TQString( buf + start, pos - start );
1011 delim = (buf[pos++]==(TQChar)
'#'?(TQChar)
'?':(TQChar)
'#');
1015 while(pos < len && buf[pos]!=delim ) pos++;
1017 tmp = TQString(buf + start, pos - start);
1018 if (delim==(TQChar)
'#')
1019 _setQuery(tmp, encoding_hint);
1021 m_strRef_encoded = tmp;
1027 tmp = TQString( buf + pos + 1, len - pos - 1);
1028 if (delim == (TQChar)
'#')
1029 m_strRef_encoded = tmp;
1031 _setQuery(tmp, encoding_hint);
1035 m_bIsMalformed =
false;
1038 if (m_strProtocol.isEmpty())
1041 m_strProtocol = fileProt;
1048 m_strProtocol = _url;
1063 parse( TQString::fromLatin1(_url) );
1068 #ifndef QT_NO_NETWORKPROTOCOL
1071 m_strProtocol = u.protocol();
1073 m_strUser = u.user();
1074 m_strPass = u.password();
1075 m_strHost = u.host();
1076 m_strPath = u.path(
false );
1077 m_strPath_encoded = TQString::null;
1078 m_strQuery_encoded = u.query();
1079 m_strRef_encoded = u.ref();
1080 m_bIsMalformed = !u.isValid();
1089 m_strProtocol = _u.m_strProtocol;
1090 m_strUser = _u.m_strUser;
1091 m_strPass = _u.m_strPass;
1092 m_strHost = _u.m_strHost;
1093 m_strPath = _u.m_strPath;
1094 m_strPath_encoded = _u.m_strPath_encoded;
1095 m_strQuery_encoded = _u.m_strQuery_encoded;
1096 m_strRef_encoded = _u.m_strRef_encoded;
1097 m_bIsMalformed = _u.m_bIsMalformed;
1098 m_iPort = _u.m_iPort;
1099 m_iUriMode = _u.m_iUriMode;
1100 d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
1112 i = m_strProtocol.compare(_u.m_strProtocol);
1120 i = m_strProtocol.compare(_u.m_strProtocol);
1121 if (i)
return (i < 0);
1123 i = m_strHost.compare(_u.m_strHost);
1124 if (i)
return (i < 0);
1126 if (m_iPort != _u.m_iPort)
return (m_iPort < _u.m_iPort);
1128 i = m_strPath.compare(_u.m_strPath);
1129 if (i)
return (i < 0);
1131 i = m_strQuery_encoded.compare(_u.m_strQuery_encoded);
1132 if (i)
return (i < 0);
1134 i = m_strRef_encoded.compare(_u.m_strRef_encoded);
1135 if (i)
return (i < 0);
1137 i = m_strUser.compare(_u.m_strUser);
1138 if (i)
return (i < 0);
1140 i = m_strPass.compare(_u.m_strPass);
1141 if (i)
return (i < 0);
1143 i = d->m_strInternalReferenceURL.compare(_u.d->m_strInternalReferenceURL);
1144 if (i)
return (i < 0);
1154 if ( m_strProtocol == _u.m_strProtocol &&
1155 m_strUser == _u.m_strUser &&
1156 m_strPass == _u.m_strPass &&
1157 m_strHost == _u.m_strHost &&
1158 m_strPath == _u.m_strPath &&
1160 ( m_strPath_encoded.isNull() || _u.m_strPath_encoded.isNull() ||
1161 m_strPath_encoded == _u.m_strPath_encoded ) &&
1162 m_strQuery_encoded == _u.m_strQuery_encoded &&
1163 m_strRef_encoded == _u.m_strRef_encoded &&
1164 m_iPort == _u.m_iPort &&
1165 d->m_strInternalReferenceURL == _u.d->m_strInternalReferenceURL )
1176 return ( *
this == u );
1181 return equals( u, ignore_trailing );
1186 return equals(_u, ignore_trailing,
false);
1189 bool KURL::equals(
const KURL &_u,
bool ignore_trailing,
bool ignore_internalReferenceURLS )
const
1194 if ( ignore_trailing )
1196 TQString path1 =
path(1);
1197 TQString path2 = _u.
path(1);
1198 if ( path1 != path2 )
1201 if ( m_strProtocol == _u.m_strProtocol &&
1202 m_strUser == _u.m_strUser &&
1203 m_strPass == _u.m_strPass &&
1204 m_strHost == _u.m_strHost &&
1205 m_strQuery_encoded == _u.m_strQuery_encoded &&
1206 m_strRef_encoded == _u.m_strRef_encoded &&
1207 m_iPort == _u.m_iPort &&
1208 ((ignore_internalReferenceURLS) || (d->m_strInternalReferenceURL == _u.d->m_strInternalReferenceURL)) )
1214 return ( *
this == _u );
1222 if ( m_strProtocol == _u.m_strProtocol &&
1223 m_strUser == _u.m_strUser &&
1224 m_strPass == _u.m_strPass &&
1225 m_strHost == _u.m_strHost &&
1226 m_strQuery_encoded == _u.m_strQuery_encoded &&
1227 m_strRef_encoded == _u.m_strRef_encoded &&
1228 m_iPort == _u.m_iPort )
1230 if (
path().isEmpty() || _u.
path().isEmpty() )
1233 TQString p1( cleanpath(
path(),
true,
false ) );
1234 if ( p1[p1.length()-1] !=
'/' )
1236 TQString p2( cleanpath( _u.
path(),
true, false ) );
1237 if ( p2[p2.length()-1] !=
'/' )
1244 return p2.startsWith( p1 );
1251 m_strRef_encoded = TQString::null;
1253 while( _txt[i] == (TQChar)
'/' ) ++i;
1256 tmp = _txt.mid( i );
1260 TQString path = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
1261 if ( path.isEmpty() )
1265 int lastSlash = path.findRev(
'/' );
1266 if ( lastSlash == -1)
1272 else if ( path.right(1) !=
"/" )
1273 path.truncate( lastSlash+1 );
1275 if (m_strPath_encoded.isEmpty())
1290 if (m_iUriMode !=
URL)
return;
1291 m_strPath = cleanpath(m_strPath, cleanDirSeparator,
false);
1293 m_strPath_encoded = cleanpath(m_strPath_encoded, cleanDirSeparator,
true);
1296 static TQString trailingSlash(
int _trailing,
const TQString &path )
1298 TQString result =
path;
1300 if ( _trailing == 0 )
1302 else if ( _trailing == 1 )
1304 int len = result.length();
1305 if ( (len == 0) || (result[ len - 1 ] != (TQChar)
'/') )
1309 else if ( _trailing == -1 )
1311 if ( result ==
"/" )
1313 int len = result.length();
1314 while (len > 1 && result[ len - 1 ] == (TQChar)
'/')
1318 result.truncate( len );
1323 return TQString::null;
1329 if (!m_strPath_encoded.isEmpty())
1331 m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded );
1333 m_strPath = trailingSlash( _trailing, m_strPath );
1340 if (!m_strPath_encoded.isEmpty() && encoding_hint == 0)
1342 tmp = trailingSlash( _trailing, m_strPath_encoded );
1346 tmp =
path( _trailing );
1347 if ( _no_empty_path && tmp.isEmpty() )
1349 if (m_iUriMode ==
Mailto)
1351 tmp = encode( tmp, 2, encoding_hint );
1355 tmp = encode( tmp, 1, encoding_hint );
1360 if (!m_strQuery_encoded.isNull())
1361 tmp +=
'?' + m_strQuery_encoded;
1367 m_strPath_encoded = _txt;
1369 decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint );
1371 if (m_strProtocol == fileProt)
1372 m_strPath_encoded = TQString::null;
1374 if ( m_iUriMode ==
Auto )
1381 int pos = _txt.find(
'?' );
1385 m_strQuery_encoded = TQString::null;
1390 _setQuery(_txt.right(_txt.length() - pos - 1), encoding_hint);
1396 return trailingSlash( _trailing,
path() );
1401 if ( (m_strProtocol != fileProt ) ||
hasSubURL() )
1404 if (m_strHost.isEmpty() || (m_strHost ==
"localhost"))
1407 char hostname[ 256 ];
1408 hostname[ 0 ] =
'\0';
1409 if (!gethostname( hostname, 255 ))
1410 hostname[
sizeof(hostname)-1] =
'\0';
1412 for(
char *p = hostname; *p; p++)
1415 return (m_strHost == hostname);
1423 TQString q =
query();
1425 if (!q.isEmpty() && (q[0] ==
'?'))
1429 for(TQStringList::Iterator it = args.begin();
1433 if (s.startsWith(
"charset="))
1434 it = args.erase(it);
1438 if (!encoding.isEmpty())
1439 args.append(
"charset="+encode_string(encoding));
1442 _setQuery(TQString::null);
1444 _setQuery(args.join(
"&"));
1450 return TQString::null;
1452 TQString q =
query();
1455 return TQString::null;
1461 for(TQStringList::ConstIterator it = args.begin();
1466 if (s.startsWith(
"charset="))
1469 return TQString::null;
1474 if ( m_strProtocol.isEmpty() || m_bIsMalformed )
1476 if (m_strRef_encoded.isEmpty())
1478 if (m_strRef_encoded.startsWith(
"gzip:"))
1480 if (m_strRef_encoded.startsWith(
"bzip:"))
1482 if (m_strRef_encoded.startsWith(
"bzip2:"))
1484 if (m_strRef_encoded.startsWith(
"tar:"))
1486 if (m_strRef_encoded.startsWith(
"ar:"))
1488 if (m_strRef_encoded.startsWith(
"zip:"))
1490 if (m_strRef_encoded.startsWith(
"lzma:"))
1492 if (m_strRef_encoded.startsWith(
"xz:"))
1494 if ( m_strProtocol ==
"error" )
1499 TQString
KURL::url(
int _trailing,
int encoding_hint )
const
1501 if( m_bIsMalformed )
1506 return m_strProtocol;
1509 TQString u = m_strProtocol;
1513 if (
hasHost() || (m_strProtocol == fileProt) )
1518 u += encode(m_strUser, 0, encoding_hint);
1522 u += encode(m_strPass, 0, encoding_hint);
1526 if ( m_iUriMode ==
URL )
1528 bool IPv6 = (m_strHost.find(
':') != -1);
1530 u +=
'[' + m_strHost +
']';
1532 u += encodeHost(m_strHost,
true, encoding_hint);
1533 if ( m_iPort != 0 ) {
1535 buffer.sprintf(
":%u", m_iPort );
1545 if ( m_iUriMode ==
URL || m_iUriMode ==
Mailto )
1548 u += encode( m_strPath, 21, encoding_hint,
true );
1553 u += m_strRef_encoded;
1561 if( m_bIsMalformed )
1566 return m_strProtocol;
1569 TQString u = m_strProtocol;
1573 if (
hasHost() || (m_strProtocol == fileProt) )
1578 u += encode(m_strUser, 0, 0);
1582 if ( m_iUriMode ==
URL )
1584 bool IPv6 = (m_strHost.find(
':') != -1);
1587 u +=
'[' + m_strHost +
']';
1591 u += lazy_encode(m_strHost);
1596 u += lazy_encode(m_strHost);
1598 if ( m_iPort != 0 ) {
1600 buffer.sprintf(
":%u", m_iPort );
1605 if (m_iUriMode ==
Mailto)
1607 u += lazy_encode( m_strPath,
false );
1611 u += trailingSlash( _trailing, lazy_encode( m_strPath ) );
1614 if (!m_strQuery_encoded.isNull())
1615 u +=
'?' + m_strQuery_encoded;
1620 u += m_strRef_encoded;
1632 return TQDir::convertSeparators(u);
1640 if (
isLocalFile() && m_strRef_encoded.isNull() && m_strQuery_encoded.isNull() ) {
1649 return TQStyleSheet::escape(
prettyURL());
1661 u.m_strRef_encoded = TQString::null;
1665 url =
KURL(url.m_strRef_encoded);
1669 ref = url.m_strRef_encoded;
1675 KURL::List::Iterator it;
1676 for( it = lst.begin() ; it != lst.end(); ++it )
1678 (*it).m_strRef_encoded =
ref;
1691 if (lst.isEmpty())
return KURL();
1694 KURL::List::ConstIterator first = lst.fromLast();
1695 for( KURL::List::ConstIterator it = first; it != lst.end(); --it )
1700 if (!u.m_strRef_encoded) u.m_strRef_encoded = tmp.
url();
1701 else u.m_strRef_encoded +=
"#" + tmp.
url();
1714 KURL::List::Iterator it = list.fromLast();
1715 return (*it).fileName(_strip_trailing_slash);
1717 const TQString &path = m_strPath;
1719 int len = path.length();
1723 if ( _strip_trailing_slash )
1725 while ( len >= 1 && path[ len - 1 ] == TQChar(
'/') )
1728 else if ( path[ len - 1 ] == TQChar(
'/') )
1732 if ( len == 1 && path[ 0 ] == TQChar(
'/') )
1737 if (!m_strPath_encoded.isEmpty())
1742 int i = m_strPath_encoded.findRev( TQChar(
'/'), len - 1 );
1743 TQString fileName_encoded = m_strPath_encoded.mid(i+1);
1744 n += fileName_encoded.contains(
"%2f",
false);
1748 i = path.findRev( TQChar(
'/'), i - 1 );
1750 while (--n && (i > 0));
1755 if ( len == (
int)path.length() )
1759 fname = path.left( len );
1763 fname = path.mid( i + 1, len - i - 1 );
1773 KURL &u = lst.last();
1775 *
this =
join( lst );
1779 m_strPath_encoded = TQString::null;
1781 if ( _txt.isEmpty() )
1785 int len = m_strPath.length();
1787 if ( _txt[0] != (TQChar)
'/' && ( len == 0 || m_strPath[ len - 1 ] != (TQChar)
'/' ) )
1792 if ( len != 0 && m_strPath[ len - 1 ] == (TQChar)
'/' )
1794 while( _txt[i] == (TQChar)
'/' )
1798 m_strPath += _txt.mid( i );
1802 bool _ignore_trailing_slash_in_path )
const
1804 TQString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
1805 if ( _ignore_trailing_slash_in_path )
1806 result = trailingSlash( -1, result );
1808 if ( result.isEmpty() || result ==
"/" )
1811 int i = result.findRev(
"/" );
1815 return TQString::null;
1823 if ( _strip_trailing_slash_from_result )
1824 result = result.left( i );
1826 result = result.left( i + 1 );
1828 if (!m_strPath_encoded.isEmpty())
1829 result = decode(result);
1837 if ( _dir.isEmpty() || m_bIsMalformed )
1843 KURL &u = lst.last();
1845 *
this =
join( lst );
1850 if ( _dir[0] == (TQChar)
'/' )
1852 m_strPath_encoded = TQString::null;
1855 m_strQuery_encoded = TQString::null;
1860 if ( ( _dir[0] == (TQChar)
'~' ) && ( m_strProtocol == fileProt ))
1862 m_strPath_encoded = TQString::null;
1863 m_strPath = TQDir::homeDirPath();
1865 m_strPath += _dir.right(m_strPath.length() - 1);
1867 m_strQuery_encoded = TQString::null;
1876 TQString p =
path(1);
1878 p = cleanpath( p,
true,
false );
1882 m_strQuery_encoded = TQString::null;
1892 u._setQuery(TQString::null);
1911 KURL &u = lst.last();
1912 TQString old = u.
path();
1914 if (u.
path() != old)
1916 if (lst.count() == 1)
1918 lst.remove(lst.fromLast());
1927 return decode(
ref() );
1931 return decode( (*lst.begin()).
ref() );
1942 return (*lst.begin()).
ref();
1949 m_strRef_encoded = encode( _ref, 0, 0 );
1955 (*lst.begin()).
setRef( encode( _ref, 0, 0 ) );
1957 *
this =
join( lst );
1968 return (*lst.begin()).
hasRef();
1974 m_strProtocol = _txt;
1976 m_bIsMalformed =
false;
1982 if ( _txt.isEmpty() )
1983 m_strUser = TQString::null;
1991 if ( _txt.isEmpty() )
1992 m_strPass = TQString::null;
2000 if ( m_iUriMode ==
Auto )
2002 switch ( m_iUriMode )
2006 m_strHost = KIDNA::toUnicode(_txt);
2007 if (m_strHost.isEmpty())
2008 m_strHost = _txt.lower();
2010 m_strHost = _txt.lower();
2028 m_bIsMalformed =
false;
2029 if (m_strProtocol.isEmpty())
2031 m_strProtocol = fileProt;
2034 m_strPath_encoded = TQString::null;
2035 if ( m_iUriMode ==
Auto )
2041 if ( dir.endsWith(
"/"))
2049 if (_txt[0] == (TQChar)
'?')
2050 _setQuery( _txt.length() > 1 ? _txt.mid(1) :
"" , encoding_hint );
2052 _setQuery( _txt, encoding_hint );
2056 void KURL::_setQuery(
const TQString &_txt,
int encoding_hint)
2058 m_strQuery_encoded = _txt;
2062 int l = m_strQuery_encoded.length();
2072 char c = m_strQuery_encoded[i].latin1();
2073 if ((c ==
'&') || (c ==
':') || (c ==
';') ||
2074 (c ==
'=') || (c ==
'/') || (c ==
'?'))
2080 TQString tmp = m_strQuery_encoded.mid(s, i-s);
2082 decode( tmp, newTmp, tmp, encoding_hint,
false );
2087 result += m_strQuery_encoded[i];
2091 m_strQuery_encoded = result;
2096 if (m_strQuery_encoded.isNull())
2097 return TQString::null;
2098 return '?'+m_strQuery_encoded;
2103 return decode(str, encoding_hint);
2108 return encode(str, 1, encoding_hint);
2113 return encode(str, 0, encoding_hint);
2116 bool urlcmp(
const TQString& _url1,
const TQString& _url2 )
2119 if ( _url1.isEmpty() && _url2.isEmpty() )
2122 if ( _url1.isEmpty() || _url2.isEmpty() )
2129 if ( list1.isEmpty() || list2.isEmpty() )
2132 return ( list1 == list2 );
2135 bool urlcmp(
const TQString& _url1,
const TQString& _url2,
bool _ignore_trailing,
bool _ignore_ref )
2138 if ( _url1.isEmpty() && _url2.isEmpty() )
2141 if ( _url1.isEmpty() || _url2.isEmpty() )
2148 if ( list1.isEmpty() || list2.isEmpty() )
2151 unsigned int size = list1.count();
2152 if ( list2.count() != size )
2157 (*list1.begin()).
setRef(TQString::null);
2158 (*list2.begin()).
setRef(TQString::null);
2161 KURL::List::Iterator it1 = list1.begin();
2162 KURL::List::Iterator it2 = list2.begin();
2163 for( ; it1 != list1.end() ; ++it1, ++it2 )
2164 if ( !(*it1).equals( *it2, _ignore_trailing ) )
2170 TQMap< TQString, TQString > KURL::queryItems(
int options )
const {
2171 return queryItems(options, 0);
2174 TQMap< TQString, TQString > KURL::queryItems(
int options,
int encoding_hint )
const {
2175 if ( m_strQuery_encoded.isEmpty() )
2176 return TQMap<TQString,TQString>();
2178 TQMap< TQString, TQString > result;
2180 for ( TQStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
2181 int equal_pos = (*it).find(
'=' );
2182 if ( equal_pos > 0 ) {
2183 TQString name = (*it).left( equal_pos );
2185 name = name.lower();
2186 TQString value = (*it).mid( equal_pos + 1 );
2187 if ( value.isEmpty() )
2188 result.insert( name, TQString::fromLatin1(
"") );
2191 value.replace(
'+',
' ' );
2192 result.insert( name,
decode_string( value, encoding_hint ) );
2194 }
else if ( equal_pos < 0 ) {
2195 TQString name = (*it);
2197 name = name.lower();
2198 result.insert( name, TQString::null );
2212 TQString item = _item +
'=';
2213 if ( m_strQuery_encoded.length() <= 1 )
2214 return TQString::null;
2217 unsigned int _len = item.length();
2218 for ( TQStringList::ConstIterator it = items.begin(); it != items.end(); ++it )
2220 if ( (*it).startsWith( item ) )
2222 if ( (*it).length() > _len )
2224 TQString str = (*it).mid( _len );
2225 str.replace(
'+',
' ' );
2229 return TQString::fromLatin1(
"");
2233 return TQString::null;
2238 TQString item = _item +
'=';
2239 if ( m_strQuery_encoded.length() <= 1 )
2243 for ( TQStringList::Iterator it = items.begin(); it != items.end(); )
2245 if ( (*it).startsWith( item ) || (*it == _item) )
2247 TQStringList::Iterator deleteIt = it;
2249 items.remove(deleteIt);
2256 m_strQuery_encoded = items.join(
"&" );
2261 TQString item = _item +
'=';
2262 TQString value = encode( _value, 0, encoding_hint );
2264 if (!m_strQuery_encoded.isEmpty())
2265 m_strQuery_encoded +=
'&';
2266 m_strQuery_encoded += item + value;
2272 if ( text.isEmpty() )
2276 if (!TQDir::isRelativePath(text))
2284 static TQString _relativePath(
const TQString &base_dir,
const TQString &path,
bool &isParent)
2286 TQString _base_dir(TQDir::cleanDirPath(base_dir));
2287 TQString _path(TQDir::cleanDirPath(path.isEmpty() || (path[0] != (TQChar)
'/') ? _base_dir+
"/"+path :
path));
2289 if (_base_dir.isEmpty())
2292 if (_base_dir[_base_dir.length()-1] !=
'/')
2293 _base_dir.append(
'/');
2300 uint maxLevel = TQMIN(list1.count(), list2.count());
2301 while((level < maxLevel) && (list1[level] == list2[level])) level++;
2305 for(uint i = level; i < list1.count(); i++)
2306 result.append(
"../");
2309 for(uint i = level; i < list2.count(); i++)
2310 result.append(list2[i]).append(
"/");
2312 if ((level < list2.count()) && (path[path.length()-1] != (TQChar)
'/'))
2313 result.truncate(result.length()-1);
2315 isParent = (level == list1.count());
2322 bool parent =
false;
2323 TQString result = _relativePath(base_dir, path, parent);
2325 result.prepend(
"./");
2333 void KURL::setInternalReferenceURL(
const TQString&
url ) {
2334 d->m_strInternalReferenceURL =
url;
2337 TQString KURL::internalReferenceURL(
void )
const {
2338 return d->m_strInternalReferenceURL;
2349 return url.
url(0, encoding_hint);
2357 TQString basePath = base_url.
directory(
false,
false);
2358 relURL = encode( _relativePath(basePath, url.
path(), dummy), 1, encoding_hint);
2359 relURL += url.
query();
2365 relURL += url.
ref();
2368 if ( relURL.isEmpty() )
2383 if (protocol == fileProt)
2385 if (TDEGlobal::_instance)
2386 mode = KProtocolInfo::uriParseMode(protocol);
2388 if (mode ==
Auto ) {
2389 if ( protocol ==
"ed2k" || protocol ==
"sig2dat" || protocol ==
"slsk" || protocol ==
"data" ) mode =
RawURI;
2390 else if ( protocol ==
"mailto" ) mode =
Mailto;