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));
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();
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 TQT_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 TQT_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 )
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] ==
'?'))
1428 TQStringList args = TQStringList::split(
'&', q);
1429 for(TQStringList::Iterator it = args.begin();
1433 if (s.startsWith(
"charset="))
1434 it = args.erase(it);
1438 if (!encoding.isEmpty())
1442 _setQuery(TQString::null);
1444 _setQuery(args.join(
"&"));
1450 return TQString::null;
1452 TQString q =
query();
1455 return TQString::null;
1460 TQStringList args = TQStringList::split(
'&', q);
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,
false ) );
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;
1663 if (
url.hasSubURL())
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;
2179 TQStringList items = TQStringList::split(
'&', m_strQuery_encoded );
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;
2216 TQStringList items = TQStringList::split(
'&', m_strQuery_encoded );
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 )
2242 TQStringList items = TQStringList::split(
'&', m_strQuery_encoded );
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))
2277 url.setPath( 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(
'/');
2295 TQStringList list1 = TQStringList::split(
'/', _base_dir);
2296 TQStringList list2 = TQStringList::split(
'/', _path);
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;
2344 (
url.host() != base_url.
host()) ||
2345 (
url.port() &&
url.port() != base_url.
port()) ||
2346 (
url.hasUser() &&
url.user() != base_url.
user()) ||
2347 (
url.hasPass() &&
url.pass() != base_url.
pass()))
2349 return url.url(0, encoding_hint);
2354 if ((base_url.
path() !=
url.path()) || (base_url.
query() !=
url.query()))
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() )
2385 if (TDEGlobal::_instance)
2386 mode = KProtocolInfo::uriParseMode(
protocol);
2388 if (mode ==
Auto ) {
KURL::List is a TQValueList that contains KURLs with a few convenience methods.
TQStringList toStringList() const
Converts the URLs of this list to a list of strings.
List()
Creates an empty List.
Represents and parses a URL.
bool operator==(const KURL &_u) const
Tests if this URL is equal to the given one.
static TQString relativePath(const TQString &base_dir, const TQString &path, bool *isParent=0)
Creates a path relative to a base path for a given input path.
TQString path() const
Returns the current decoded path.
static bool isRelativeURL(const TQString &_url)
Tests if a given URL is a relative as opposed to an absolute URL.
void adjustPath(int _trailing)
Adds or removes a trailing slash to/from the path.
static TQString relativeURL(const KURL &base_url, const KURL &url, int encoding_hint=0)
Creates an URL relative to a base URL for a given input URL.
void parseMailto(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
bool urlcmp(const TQString &_url1, const TQString &_url2)
Compares URLs.
TQString user() const
Returns the decoded user name (login, user id, etc) included in the URL.
TQString directory(bool _strip_trailing_slash_from_result=true, bool _ignore_trailing_slash_in_path=true) const
Returns the directory of the path.
unsigned short int port() const
Returns the port number included in the URL.
void setUser(const TQString &_txt)
Sets the user name (login, user id, etc) to include in the URL.
void removeQueryItem(const TQString &_item)
Removea an item from the query.
AdjustementFlags
Flags to choose how file: URLs are treated when creating their TQString representation with prettyURL...
@ StripFileProtocol
Strip the file: protocol from the string, i.e.
TQString query() const
Returns the encoded query of the URL.
TQString encodedHtmlRef() const
Returns the encoded HTML-style reference (the part of the URL after '#')
void setFileEncoding(const TQString &encoding)
Adds file encoding information.
void setRef(const TQString &_txt)
Sets the encoded reference part (everything after '#')
bool isParentOf(const KURL &u) const
Tests if the given URL is parent of this URL.
static TQString encode_string(const TQString &str, int encoding_hint=0)
Encodes a string for use in URLs.
void setPath(const TQString &path)
Sets the decoded path of the URL.
static TQString encode_string_no_slash(const TQString &str, int encoding_hint=0)
Encodes a string for use in URLs.
bool hasSubURL() const
Tests if the URL has any sub URLs.
void setHost(const TQString &_txt)
Sets the hostname to include in the URL.
void reset()
Resets the members to their "null" state.
void setEncodedPathAndQuery(const TQString &_txt, int encoding_hint=0)
Sets both path and query of the URL in their encoded form.
void setPass(const TQString &_txt)
Sets the password (corresponding to user()) to include in the URL.
static List split(const TQString &_url)
Splits nested URLs into a list of URLs.
TQString fileEncoding() const
Returns encoding information of the URL.
void setHTMLRef(const TQString &_ref)
Sets the decoded HTML-style reference.
~KURL()
Destructs the KURL object.
void setDirectory(const TQString &dir)
Sets the directory of the path, leaving the filename empty.
bool operator<(const KURL &_u) const
Tests if this URL is less than the given URL.
KURL()
Constructs an empty URL.
TQString protocol() const
Returns the protocol for the URL.
bool isEmpty() const
Tests if the KURL is empty.
bool hasHost() const
Tests if this URL has a hostname included in it.
void parseURL(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
bool hasPass() const
Tests if this URL has a password included in it.
KURL & operator=(const KURL &_u)
Copies the values of the given URL into this one.
void setPort(unsigned short int _p)
Sets the port number to include in the URL.
bool cd(const TQString &_dir)
Changes the directory by descending into the given directory.
void parseRawURI(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
TQString queryItem(const TQString &item) const
Returns the value of a certain query item.
bool hasUser() const
Tests if this URL has a user name included in it.
static KURL join(const List &_list)
Joins a list of URLs into a single URL with sub URLs.
void addPath(const TQString &txt)
Adds to the current path.
void setQuery(const TQString &_txt, int encoding_hint=0)
Sets the encoded query of the URL.
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
Returns the filename of the path.
bool hasHTMLRef() const
Tests if there is an HTML-style reference.
void addQueryItem(const TQString &_item, const TQString &_value, int encoding_hint=0)
Adds an additional query item.
void cleanPath(bool cleanDirSeparator=true)
Resolves "." and ".." components in path.
void parse(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
@ CaseInsensitiveKeys
Normalize query keys to lowercase.
TQString url(int _trailing=0, int encoding_hint=0) const
Returns the URL as string, with all escape sequences intact, encoded in a given charset.
TQString host() const
Returns the decoded hostname included in the URL.
static TQString decode_string(const TQString &str, int encoding_hint=0)
Decodes a string as used in URLs.
static URIMode uriModeForProtocol(const TQString &protocol)
Determines which URI mode is suitable for processing URIs of a given protocol.
bool cmp(const KURL &u, bool ignore_trailing=false) const TDE_DEPRECATED
Compares this URL with another one.
TQString pass() const
Returns the decoded password (corresponding to user()) included in the URL.
bool equals(const KURL &u, bool ignore_trailing=false) const
Compares this URL with another one.
void setFileName(const TQString &_txt)
Sets the filename of the path.
int uriMode() const
Returns the URI processing mode for the URL.
TQString encodedPathAndQuery(int _trailing=0, bool _no_empty_path=false, int encoding_hint=0) const
Returns the encoded path and the query.
bool isLocalFile() const
Tests if the file is local.
TQString ref() const
Returns the encoded reference of the URL.
URIMode
Defines the type of URI we are processing.
@ URL
Standards compliant URL.
@ Auto
Automatically detected.
TQString prettyURL(int _trailing=0) const
Returns the URL as string in human-friendly format.
void setProtocol(const TQString &_txt)
Sets the protocol for the URL.
KURL upURL() const
Returns the URL that is the best possible candidate for on level higher in the path hierachy.
TQString pathOrURL() const
Returns the URL as a string depending if it is a local file.
void setEncodedPath(const TQString &_txt, int encoding_hint=0)
Sets the (already encoded) path of the URL.
bool isValid() const
Tests if the URL is well formed.
TQString htmlRef() const
Returns decoded the HTML-style reference (the part of the URL after '#')
TQString htmlURL() const
Returns the URL as string, escaped for HTML.
static KURL fromPathOrURL(const TQString &text)
Creates a KURL object from a TQString representing either an absolute path or a real URL.
bool hasRef() const
Tests if the URL has a reference part.
static const TQString & staticQString(const char *str)
Creates a static TQString.