• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
kurl.cpp
1/*
2 Copyright (C) 1999 Torben Weis <weis@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20/*
21 * The currently active RFC for URL/URIs is RFC3986
22 * Previous (and now deprecated) RFCs are RFC1738 and RFC2396
23 */
24
25#include "kurl.h"
26
27// KDE_QT_ONLY is first used for dcop/client (e.g. marshalling)
28#ifndef KDE_QT_ONLY
29#include <kdebug.h>
30#include <tdeglobal.h>
31#include <kidna.h>
32#include <kprotocolinfo.h>
33#endif
34
35#include <stdio.h>
36#include <assert.h>
37#include <ctype.h>
38#include <stdlib.h>
39#include <unistd.h>
40
41#include <tqurl.h>
42#include <tqdir.h>
43#include <tqstringlist.h>
44#include <tqregexp.h>
45#include <tqstylesheet.h>
46#include <tqmap.h>
47#include <tqtextcodec.h>
48#include <tqmutex.h>
49
50#ifdef TQ_WS_WIN
51# define KURL_ROOTDIR_PATH "C:/"
52#else
53# define KURL_ROOTDIR_PATH "/"
54#endif
55
56static const TQString fileProt = "file";
57
58static TQTextCodec * codecForHint( int encoding_hint /* not 0 ! */ )
59{
60 return TQTextCodec::codecForMib( encoding_hint );
61}
62
63// encoding_offset:
64// 0 encode both @ and /
65// 1 encode @ but not /
66// 2 encode neither @ or /
67static TQString encode( const TQString& segment, int encoding_offset, int encoding_hint, bool isRawURI = false )
68{
69 const char *encode_string = "/@<>#\"&?={}|^~[]\'`\\:+%";
70 encode_string += encoding_offset;
71
72 TQCString local;
73 if (encoding_hint==0)
74 local = segment.local8Bit();
75 else
76 {
77 TQTextCodec * textCodec = codecForHint( encoding_hint );
78 if (!textCodec)
79 local = segment.local8Bit();
80 else
81 local = textCodec->fromUnicode( segment );
82 }
83
84 int old_length = isRawURI ? local.size() - 1 : local.length();
85
86 if ( old_length < 1 )
87 return segment.isNull() ? TQString::null : TQString(""); // differentiate null and empty
88
89 // a worst case approximation
90 TQChar *new_segment = new TQChar[ old_length * 3 + 1 ];
91 int new_length = 0;
92
93 for ( int i = 0; i < old_length; i++ )
94 {
95 // 'unsave' and 'reserved' characters
96 // according to RFC 1738,
97 // 2.2. URL Character Encoding Issues (pp. 3-4)
98 // WABA: Added non-ascii
99 unsigned char character = local[i];
100 if ( (character <= 32) || (character >= 127) ||
101 strchr(encode_string, character) )
102 {
103 new_segment[ new_length++ ] = '%';
104
105 unsigned int c = character / 16;
106 c += (c > 9) ? ('A' - 10) : '0';
107 new_segment[ new_length++ ] = c;
108
109 c = character % 16;
110 c += (c > 9) ? ('A' - 10) : '0';
111 new_segment[ new_length++ ] = c;
112
113 }
114 else
115 new_segment[ new_length++ ] = (TQChar)local[i];
116 }
117
118 TQString result = TQString(new_segment, new_length);
119 delete [] new_segment;
120 return result;
121}
122
123static TQString encodeHost( const TQString& segment, bool encode_slash, int encoding_hint )
124{
125 // Hostnames are encoded differently
126 // we use the IDNA transformation instead
127
128 // Note: when merging qt-addon, use QResolver::domainToAscii here
129#ifndef KDE_QT_ONLY
130 Q_UNUSED( encode_slash );
131 Q_UNUSED( encoding_hint );
132 TQString host = KIDNA::toAscii(segment);
133 if (host.isEmpty())
134 return segment;
135 return host;
136#else
137 return encode(segment, encode_slash ? 0 : 1, encoding_hint);
138#endif
139}
140
141static int hex2int( unsigned int _char )
142{
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')
148 return _char - '0';
149 return -1;
150}
151
152// WABA: The result of lazy_encode isn't usable for a URL which
153// needs to satisfies RFC requirements. However, the following
154// operation will make it usable again:
155// encode(decode(...))
156//
157// As a result one can see that url.prettyURL() does not result in
158// a RFC compliant URL but that the following sequence does:
159// KURL(url.prettyURL()).url()
160
161
162static TQString lazy_encode( const TQString& segment, bool encodeAt=true )
163{
164 int old_length = segment.length();
165
166 if ( !old_length )
167 return TQString::null;
168
169 // a worst case approximation
170 TQChar *new_segment = new TQChar[ old_length * 3 + 1 ];
171 int new_length = 0;
172
173 for ( int i = 0; i < old_length; i++ )
174 {
175 unsigned int character = segment[i].unicode(); // Don't use latin1()
176 // It returns 0 for non-latin1 values
177 // Small set of really ambiguous chars
178 if ((character < 32) || // Low ASCII
179 ((character == '%') && // The escape character itself
180 (i+2 < old_length) && // But only if part of a valid escape sequence!
181 (hex2int(segment[i+1].unicode())!= -1) &&
182 (hex2int(segment[i+2].unicode())!= -1)) ||
183 (character == '?') || // Start of query delimiter
184 ((character == '@') && encodeAt) || // Username delimiter
185 (character == '#') || // Start of reference delimiter
186 ((character == 32) && (i+1 == old_length || segment[i+1] == (TQChar)' '))) // A trailing space
187 {
188 new_segment[ new_length++ ] = '%';
189
190 unsigned int c = character / 16;
191 c += (c > 9) ? ('A' - 10) : '0';
192 new_segment[ new_length++ ] = c;
193
194 c = character % 16;
195 c += (c > 9) ? ('A' - 10) : '0';
196 new_segment[ new_length++ ] = c;
197 }
198 else
199 new_segment[ new_length++ ] = segment[i];
200 }
201
202 TQString result = TQString(new_segment, new_length);
203 delete [] new_segment;
204 return result;
205}
206
207static void decode( const TQString& segment, TQString &decoded, TQString &encoded, int encoding_hint=0, bool updateDecoded = true, bool isRawURI = false )
208{
209 decoded = TQString::null;
210 encoded = segment;
211
212 int old_length = segment.length();
213 if ( !old_length )
214 return;
215
216 TQTextCodec *textCodec = 0;
217 if (encoding_hint)
218 textCodec = codecForHint( encoding_hint );
219
220 if (!textCodec)
221 textCodec = TQTextCodec::codecForLocale();
222
223 TQCString csegment = textCodec->fromUnicode(segment);
224 // Check if everything went ok
225 if (textCodec->toUnicode(csegment) != segment)
226 {
227 // Uh oh
228 textCodec = codecForHint( 106 ); // Fall back to utf-8
229 csegment = textCodec->fromUnicode(segment);
230 }
231 old_length = csegment.length();
232
233 int new_length = 0;
234 int new_length2 = 0;
235
236 // make a copy of the old one
237 char *new_segment = new char[ old_length + 1 ];
238 TQChar *new_usegment = new TQChar[ old_length * 3 + 1 ];
239
240 int i = 0;
241 while( i < old_length )
242 {
243 bool bReencode = false;
244 unsigned char character = csegment[ i++ ];
245 if ((character <= ' ') || (character > 127))
246 bReencode = true;
247
248 new_usegment [ new_length2++ ] = character;
249 if (character == '%' )
250 {
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)) // Only replace if sequence is valid
254 {
255 // Contains stray %, make sure to re-encode!
256 bReencode = true;
257 }
258 else
259 {
260 // Valid %xx sequence
261 character = a * 16 + b; // Replace with value of %dd
262 if (!isRawURI && !character && updateDecoded)
263 break; // Stop at %00
264
265 new_usegment [ new_length2++ ] = (unsigned char) csegment[i++];
266 new_usegment [ new_length2++ ] = (unsigned char) csegment[i++];
267 }
268 }
269 if (bReencode)
270 {
271 new_length2--;
272 new_usegment [ new_length2++ ] = '%';
273
274 unsigned int c = character / 16;
275 c += (c > 9) ? ('A' - 10) : '0';
276 new_usegment[ new_length2++ ] = c;
277
278 c = character % 16;
279 c += (c > 9) ? ('A' - 10) : '0';
280 new_usegment[ new_length2++ ] = c;
281 }
282
283 new_segment [ new_length++ ] = character;
284 }
285 new_segment [ new_length ] = 0;
286
287 encoded = TQString( new_usegment, new_length2);
288
289 // Encoding specified
290 if (updateDecoded)
291 {
292 decoded = textCodec->toUnicode( new_segment );
293 if ( isRawURI ) {
294 int length = tqstrlen( new_segment );
295 while ( length < new_length ) {
296 decoded += TQChar::null;
297 length += 1;
298 decoded += textCodec->toUnicode( new_segment + length );
299 length += tqstrlen( new_segment + length );
300 }
301 }
302
303 TQCString validate = textCodec->fromUnicode(decoded);
304
305 if (strcmp(validate.data(), new_segment) != 0)
306 {
307 decoded = TQString::fromLocal8Bit(new_segment, new_length);
308 }
309 }
310
311 delete [] new_segment;
312 delete [] new_usegment;
313}
314
315static TQString decode(const TQString &segment, int encoding_hint = 0, bool isRawURI = false)
316{
317 TQString result;
318 TQString tmp;
319 decode(segment, result, tmp, encoding_hint, true, isRawURI);
320 return result;
321}
322
323static TQString cleanpath(const TQString &_path, bool cleanDirSeparator, bool decodeDots)
324{
325 if (_path.isEmpty()) return TQString::null;
326
327 if (TQDir::isRelativePath(_path))
328 return _path; // Don't mangle mailto-style URLs
329
330 TQString path = _path;
331
332 int len = path.length();
333
334 if (decodeDots)
335 {
336#ifndef KDE_QT_ONLY
337 static const TQString &encodedDot = TDEGlobal::staticQString("%2e");
338#else
339 TQString encodedDot("%2e");
340#endif
341 if (path.find(encodedDot, 0, false) != -1)
342 {
343#ifndef KDE_QT_ONLY
344 static const TQString &encodedDOT = TDEGlobal::staticQString("%2E"); // Uppercase!
345#else
346 TQString encodedDOT("%2E");
347#endif
348 path.replace(encodedDot, ".");
349 path.replace(encodedDOT, ".");
350 len = path.length();
351 }
352 }
353
354 bool slash = (len && path[len-1] == '/') ||
355 (len > 1 && path[len-2] == '/' && path[len-1] == '.');
356
357 // The following code cleans up directory path much like
358 // TQDir::cleanDirPath() except it can be made to ignore multiple
359 // directory separators by setting the flag to false. That fixes
360 // bug# 15044, mail.altavista.com and other similar brain-dead server
361 // implementations that do not follow what has been specified in
362 // RFC 2396!! (dA)
363 TQString result;
364 int cdUp, orig_pos, pos;
365
366 cdUp = 0;
367 pos = orig_pos = len;
368 while ( pos && (pos = path.findRev('/',--pos)) != -1 )
369 {
370 len = orig_pos - pos - 1;
371 if ( len == 2 && path[pos+1] == '.' && path[pos+2] == '.' )
372 cdUp++;
373 else
374 {
375 // Ignore any occurrences of '.'
376 // This includes entries that simply do not make sense like /..../
377 if ( (len || !cleanDirSeparator) &&
378 (len != 1 || path[pos+1] != '.' ) )
379 {
380 if ( !cdUp )
381 result.prepend(path.mid(pos, len+1));
382 else
383 cdUp--;
384 }
385 }
386 orig_pos = pos;
387 }
388
389#ifdef TQ_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])+":");
392 }
393#endif
394
395 if ( result.isEmpty() )
396 result = KURL_ROOTDIR_PATH;
397 else if ( slash && result[result.length()-1] != '/' )
398 result.append('/');
399
400 return result;
401}
402
403class KURLPrivate
404{
405public:
406 TQString m_strInternalReferenceURL;
407};
408
409bool KURL::isRelativeURL(const TQString &_url)
410{
411 int len = _url.length();
412 if (!len) return true; // Very short relative URL.
413 const TQChar *str = _url.unicode();
414
415 // Absolute URL must start with alpha-character
416 if (!isalpha(str[0].latin1()))
417 return true; // Relative URL
418
419 for(int i = 1; i < len; i++)
420 {
421 char c = str[i].latin1(); // Note: non-latin1 chars return 0!
422 if (c == ':')
423 return false; // Absolute URL
424
425 // Protocol part may only contain alpha, digit, + or -
426 if (!isalpha(c) && !isdigit(c) && (c != '+') && (c != '-'))
427 return true; // Relative URL
428 }
429 // URL did not contain ':'
430 return true; // Relative URL
431}
432
433KURL::List::List(const KURL &url)
434{
435 append( url );
436}
437
438KURL::List::List(const TQStringList &list)
439{
440 for (TQStringList::ConstIterator it = list.begin();
441 it != list.end();
442 it++)
443 {
444 append( KURL(*it) );
445 }
446}
447
448TQStringList KURL::List::toStringList() const
449{
450 TQStringList lst;
451 for( KURL::List::ConstIterator it = begin();
452 it != end();
453 it++)
454 {
455 lst.append( (*it).url() );
456 }
457 return lst;
458}
459
460
461KURL::KURL()
462{
463 d = new KURLPrivate();
464 reset();
465}
466
467KURL::~KURL()
468{
469 if (d) {
470 delete d;
471 }
472}
473
474
475KURL::KURL( const TQString &url, int encoding_hint )
476{
477 d = new KURLPrivate();
478 reset();
479 parse( url, encoding_hint );
480}
481
482KURL::KURL( const char * url, int encoding_hint )
483{
484 d = new KURLPrivate();
485 reset();
486 parse( TQString::fromLatin1(url), encoding_hint );
487}
488
489KURL::KURL( const TQCString& url, int encoding_hint )
490{
491 d = new KURLPrivate();
492 reset();
493 parse( TQString::fromLatin1(url), encoding_hint );
494}
495
496KURL::KURL( const KURL& _u )
497{
498 d = new KURLPrivate();
499 *this = _u;
500 d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
501}
502
503TQDataStream & operator<< (TQDataStream & s, const KURL & a)
504{
505 TQString QueryForWire=a.m_strQuery_encoded;
506 if (!a.m_strQuery_encoded.isNull())
507 QueryForWire.prepend("?");
508
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;
512 return s;
513}
514
515TQDataStream & operator>> (TQDataStream & s, KURL & a)
516{
517 TQ_INT8 malf;
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);
523
524 if ( QueryFromWire.isNull() )
525 a.m_strQuery_encoded = TQString::null;
526 else if ( QueryFromWire.length() == 1 ) // empty query
527 a.m_strQuery_encoded = "";
528 else
529 a.m_strQuery_encoded = QueryFromWire.mid(1);
530
531 a.m_iUriMode = KURL::uriModeForProtocol( a.m_strProtocol );
532
533 return s;
534}
535
536#ifndef TQT_NO_NETWORKPROTOCOL
537KURL::KURL( const TQUrl &u )
538{
539 d = new KURLPrivate();
540 *this = u;
541}
542#endif
543
544KURL::KURL( const KURL& _u, const TQString& _rel_url, int encoding_hint )
545{
546 d = new KURLPrivate();
547 d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
548
549 if (_u.hasSubURL()) // Operate on the last suburl, not the first
550 {
551 KURL::List lst = split( _u );
552 KURL u(lst.last(), _rel_url, encoding_hint);
553 lst.remove( lst.last() );
554 lst.append( u );
555 *this = join( lst );
556 d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
557 return;
558 }
559 // WORKAROUND THE RFC 1606 LOOPHOLE THAT ALLOWS
560 // http:/index.html AS A VALID SYNTAX FOR RELATIVE
561 // URLS. ( RFC 2396 section 5.2 item # 3 )
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] != '/')) )
568 {
569 rUrl.remove( 0, rUrl.find( ':' ) + 1 );
570 }
571
572 if ( rUrl.isEmpty() )
573 {
574 *this = _u;
575 }
576 else if ( rUrl[0] == '#' )
577 {
578 *this = _u;
579 m_strRef_encoded = rUrl.mid(1);
580 if ( m_strRef_encoded.isNull() )
581 m_strRef_encoded = ""; // we know there was an (empty) html ref, we saw the '#'
582 }
583 else if ( isRelativeURL( rUrl) )
584 {
585 *this = _u;
586 m_strQuery_encoded = TQString::null;
587 m_strRef_encoded = TQString::null;
588 if ( rUrl[0] == '/')
589 {
590 if ((rUrl.length() > 1) && (rUrl[1] == '/'))
591 {
592 m_strHost = TQString::null;
593 // File protocol returns file:/// without host, strip // from rUrl
594 if (_u.m_strProtocol == fileProt)
595 rUrl.remove(0, 2);
596 }
597 m_strPath = TQString::null;
598 m_strPath_encoded = TQString::null;
599 }
600 else if ( rUrl[0] != '?' )
601 {
602 int pos = m_strPath.findRev( '/' );
603 if (pos >= 0)
604 m_strPath.truncate(pos);
605 m_strPath += '/';
606 if (!m_strPath_encoded.isEmpty())
607 {
608 pos = m_strPath_encoded.findRev( '/' );
609 if (pos >= 0)
610 m_strPath_encoded.truncate(pos);
611 m_strPath_encoded += '/';
612 }
613 }
614 else
615 {
616 if ( m_strPath.isEmpty() )
617 m_strPath = '/';
618 }
619 KURL tmp( url() + rUrl, encoding_hint);
620 *this = tmp;
621 cleanPath(false);
622 }
623 else
624 {
625 KURL tmp( rUrl, encoding_hint);
626 *this = tmp;
627 // Preserve userinfo if applicable.
628 if (!_u.m_strUser.isEmpty() && m_strUser.isEmpty() && (_u.m_strHost == m_strHost) && (_u.m_strProtocol == m_strProtocol))
629 {
630 m_strUser = _u.m_strUser;
631 m_strPass = _u.m_strPass;
632 }
633 cleanPath(false);
634 }
635}
636
637void KURL::reset()
638{
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;
648 m_iPort = 0;
649 m_iUriMode = Auto;
650}
651
652bool KURL::isEmpty() const
653{
654 return (m_strPath.isEmpty() && m_strProtocol.isEmpty());
655}
656
657void KURL::parse( const TQString& _url, int encoding_hint )
658{
659 if ( _url.isEmpty() || m_iUriMode == Invalid )
660 {
661 m_strProtocol = _url;
662 m_iUriMode = Invalid;
663 return;
664 }
665
666 const TQChar* buf = _url.unicode();
667 const TQChar* orig = buf;
668 uint len = _url.length();
669 uint pos = 0;
670
671 // Node 1: Accept alpha or slash
672 TQChar x = buf[pos++];
673#ifdef TQ_WS_WIN
674 /* win32: accept <letter>: or <letter>:/ or <letter>:\ */
675 const bool alpha = isalpha((int)x);
676 if (alpha && len<2)
677 goto NodeErr;
678 if (alpha && buf[pos]==':' && (len==2 || (len>2 && (buf[pos+1]=='/' || buf[pos+1]=='\\'))))
679#else
680 if ( x == (TQChar)'/' )
681#endif
682 {
683 // A slash means we immediately proceed to parse it as a file URL.
684 m_iUriMode = URL;
685 m_strProtocol = fileProt;
686 parseURL( _url, encoding_hint );
687 return;
688 }
689 if ( !isalpha( (int)x ) )
690 goto NodeErr;
691
692 // Node 2: Accept any amount of (alpha|digit|'+'|'-')
693 // '.' is not currently accepted, because current KURL may be confused.
694 // Proceed with :// :/ or :
695 while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) ||
696 buf[pos] == (TQChar)'+' || buf[pos] == (TQChar)'-')) pos++;
697
698 if (pos < len && buf[pos] == (TQChar)':' )
699 {
700 m_strProtocol = TQString( orig, pos ).lower();
701 if ( m_iUriMode == Auto )
702 m_iUriMode = uriModeForProtocol( m_strProtocol );
703 // Proceed to correct parse function.
704 switch ( m_iUriMode )
705 {
706 case RawURI:
707 parseRawURI( _url );
708 return;
709 case Mailto:
710 parseMailto( _url );
711 return;
712 case URL:
713 parseURL( _url, encoding_hint );
714 return;
715 default:
716 // Unknown URI mode results in an invalid URI.
717 break;
718 }
719 }
720
721NodeErr:
722 reset();
723 m_strProtocol = _url;
724 m_iUriMode = Invalid;
725}
726
727void KURL::parseRawURI( const TQString& _url, int encoding_hint )
728{
729 uint len = _url.length();
730 const TQChar* buf = _url.unicode();
731
732 uint pos = 0;
733
734 // Accept any amount of (alpha|digit|'+'|'-')
735 // '.' is not currently accepted, because current KURL may be confused.
736 // Proceed with :
737 while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) ||
738 buf[pos] == (TQChar)'+' || buf[pos] == (TQChar)'-')) pos++;
739
740 // Note that m_strProtocol is already set here, so we just skip over the protocol.
741 if (pos < len && buf[pos] == (TQChar)':' )
742 pos++;
743 else { // can't happen, the caller checked all this already
744 reset();
745 m_strProtocol = _url;
746 m_iUriMode = Invalid;
747 return;
748 }
749
750 if ( pos == len ) // can't happen, the caller checked this already
751 m_strPath = TQString::null;
752 else
753 m_strPath = decode( TQString( buf + pos, len - pos ), encoding_hint, true );
754
755 m_bIsMalformed = false;
756
757 return;
758}
759
760void KURL::parseMailto( const TQString& _url, int encoding_hint )
761{
762 parseURL( _url, encoding_hint);
763 if ( m_bIsMalformed )
764 return;
765 TQRegExp mailre("(.+@)(.+)");
766 if ( mailre.exactMatch( m_strPath ) )
767 {
768#ifndef KDE_QT_ONLY
769 TQString host = KIDNA::toUnicode( mailre.cap( 2 ) );
770 if (host.isEmpty())
771 host = TQString(mailre.cap( 2 )).lower();
772#else
773 TQString host = TQString(mailre.cap( 2 )).lower();
774#endif
775 m_strPath = mailre.cap( 1 ) + host;
776 }
777}
778
779void KURL::parseURL( const TQString& _url, int encoding_hint )
780{
781 TQString port;
782 bool badHostName = false;
783 int start = 0;
784 uint len = _url.length();
785 const TQChar* buf = _url.unicode();
786
787 TQChar delim;
788 TQString tmp;
789
790 uint pos = 0;
791
792 // Node 1: Accept alpha or slash
793 TQChar x = buf[pos++];
794#ifdef TQ_WS_WIN
795 /* win32: accept <letter>: or <letter>:/ or <letter>:\ */
796 const bool alpha = isalpha((int)x);
797 if (alpha && len<2)
798 goto NodeErr;
799 if (alpha && buf[pos]==(TQChar)':' && (len==2 || (len>2 && (buf[pos+1]==(TQChar)'/' || buf[pos+1]==(TQChar)'\\'))))
800#else
801 if ( x == (TQChar)'/' )
802#endif
803 goto Node9;
804 if ( !isalpha( (int)x ) )
805 goto NodeErr;
806
807 // Node 2: Accept any amount of (alpha|digit|'+'|'-')
808 // '.' is not currently accepted, because current KURL may be confused.
809 // Proceed with :// :/ or :
810 while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) ||
811 buf[pos] == (TQChar)'+' || buf[pos] == (TQChar)'-')) pos++;
812
813 // Note that m_strProtocol is already set here, so we just skip over the protocol.
814 if ( pos+2 < len && buf[pos] == (TQChar)':' && buf[pos+1] == (TQChar)'/' && buf[pos+2] == (TQChar)'/' )
815 {
816 pos += 3;
817 }
818 else if (pos+1 < len && buf[pos] == (TQChar)':' ) // Need to always compare length()-1 otherwise KURL passes "http:" as legal!!
819 {
820 pos++;
821 start = pos;
822 goto Node9;
823 }
824 else
825 goto NodeErr;
826
827 //Node 3: We need at least one character here
828 if ( pos == len )
829 goto NodeErr;
830 start = pos;
831
832 // Node 4: Accept any amount of characters.
833 if (buf[pos] == (TQChar)'[') // An IPv6 host follows.
834 goto Node8;
835 // Terminate on / or @ or ? or # or " or ; or <
836 x = buf[pos];
837 while( (x != (TQChar)':') && (x != (TQChar)'@') && (x != (TQChar)'/') && (x != (TQChar)'?') && (x != (TQChar)'#') )
838 {
839 if ((x == (TQChar)'\"') || (x == (TQChar)';') || (x == (TQChar)'<'))
840 badHostName = true;
841 if (++pos == len)
842 break;
843 x = buf[pos];
844 }
845 if ( pos == len )
846 {
847 if (badHostName)
848 goto NodeErr;
849
850 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
851 goto NodeOk;
852 }
853 if ( x == (TQChar)'@' )
854 {
855 m_strUser = decode(TQString( buf + start, pos - start ), encoding_hint);
856 pos++;
857 goto Node7;
858 }
859 else if ( (x == (TQChar)'/') || (x == (TQChar)'?') || (x == (TQChar)'#'))
860 {
861 if (badHostName)
862 goto NodeErr;
863
864 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
865 start = pos;
866 goto Node9;
867 }
868 else if ( x != (TQChar)':' )
869 goto NodeErr;
870 m_strUser = decode(TQString( buf + start, pos - start ), encoding_hint);
871 pos++;
872
873 // Node 5: We need at least one character
874 if ( pos == len )
875 goto NodeErr;
876 start = pos++;
877
878 // Node 6: Read everything until @, /, ? or #
879 while( (pos < len) &&
880 (buf[pos] != (TQChar)'@') &&
881 (buf[pos] != (TQChar)'/') &&
882 (buf[pos] != (TQChar)'?') &&
883 (buf[pos] != (TQChar)'#')) pos++;
884 // If we now have a '@' the ':' seperates user and password.
885 // Otherwise it seperates host and port.
886 if ( (pos == len) || (buf[pos] != (TQChar)'@') )
887 {
888 // Ok the : was used to separate host and port
889 if (badHostName)
890 goto NodeErr;
891 setHost(m_strUser);
892 m_strUser = TQString::null;
893 TQString tmp( buf + start, pos - start );
894 char *endptr;
895 m_iPort = (unsigned short int)strtol(tmp.ascii(), &endptr, 10);
896 if ((pos == len) && (strlen(endptr) == 0))
897 goto NodeOk;
898 // there is more after the digits
899 pos -= strlen(endptr);
900 if ((buf[pos] != (TQChar)'@') &&
901 (buf[pos] != (TQChar)'/') &&
902 (buf[pos] != (TQChar)'?') &&
903 (buf[pos] != (TQChar)'#'))
904 goto NodeErr;
905
906 start = pos;
907 goto Node9;
908 }
909 m_strPass = decode(TQString( buf + start, pos - start), encoding_hint);
910 pos++;
911
912 // Node 7: We need at least one character
913 Node7:
914 if ( pos == len )
915 goto NodeErr;
916
917 Node8:
918 if (buf[pos] == (TQChar)'[')
919 {
920 // IPv6 address
921 start = ++pos; // Skip '['
922
923 if (pos == len)
924 {
925 badHostName = true;
926 goto NodeErr;
927 }
928 // Node 8a: Read everything until ] or terminate
929 badHostName = false;
930 x = buf[pos];
931 while( (x != (TQChar)']') )
932 {
933 if ((x == (TQChar)'\"') || (x == (TQChar)';') || (x == (TQChar)'<'))
934 badHostName = true;
935 if (++pos == len)
936 {
937 badHostName = true;
938 break;
939 }
940 x = buf[pos];
941 }
942 if (badHostName)
943 goto NodeErr;
944 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
945 if (pos < len) pos++; // Skip ']'
946 if (pos == len)
947 goto NodeOk;
948 }
949 else
950 {
951 // Non IPv6 address, with a user
952 start = pos;
953
954 // Node 8b: Read everything until / : or terminate
955 badHostName = false;
956 x = buf[pos];
957 while( (x != (TQChar)':') && (x != (TQChar)'@') && (x != (TQChar)'/') && (x != (TQChar)'?') && (x != (TQChar)'#') )
958 {
959 if ((x == (TQChar)'\"') || (x == (TQChar)';') || (x == (TQChar)'<'))
960 badHostName = true;
961 if (++pos == len)
962 break;
963 x = buf[pos];
964 }
965 if (badHostName)
966 goto NodeErr;
967 if ( pos == len )
968 {
969 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
970 goto NodeOk;
971 }
972 setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
973 }
974 x = buf[pos];
975 if ( x == (TQChar)'/' || x == (TQChar)'#' || x == (TQChar)'?' )
976 {
977 start = pos;
978 goto Node9;
979 }
980 else if ( x != (TQChar)':' )
981 goto NodeErr;
982 pos++;
983
984 // Node 8c: Accept at least one digit
985 if ( pos == len )
986 goto NodeErr;
987 start = pos;
988 if ( !isdigit( buf[pos++] ) )
989 goto NodeErr;
990
991 // Node 8d: Accept any amount of digits
992 while( pos < len && isdigit( buf[pos] ) ) pos++;
993 port = TQString( buf + start, pos - start );
994 m_iPort = port.toUShort();
995 if ( pos == len )
996 goto NodeOk;
997 start = pos;
998
999 Node9: // parse path until query or reference reached
1000
1001 while( pos < len && buf[pos] != (TQChar)'#' && buf[pos]!=(TQChar)'?' ) pos++;
1002
1003 tmp = TQString( buf + start, pos - start );
1004 //kdDebug(126)<<" setting encoded path to:"<<tmp<<endl;
1005 setEncodedPath( tmp, encoding_hint );
1006
1007 if ( pos == len )
1008 goto NodeOk;
1009
1010 //Node10: // parse query or reference depending on what comes first
1011 delim = (buf[pos++]==(TQChar)'#'?(TQChar)'?':(TQChar)'#');
1012
1013 start = pos;
1014
1015 while(pos < len && buf[pos]!=delim ) pos++;
1016
1017 tmp = TQString(buf + start, pos - start);
1018 if (delim==(TQChar)'#')
1019 _setQuery(tmp, encoding_hint);
1020 else
1021 m_strRef_encoded = tmp;
1022
1023 if (pos == len)
1024 goto NodeOk;
1025
1026 //Node11: // feed the rest into the remaining variable
1027 tmp = TQString( buf + pos + 1, len - pos - 1);
1028 if (delim == (TQChar)'#')
1029 m_strRef_encoded = tmp;
1030 else
1031 _setQuery(tmp, encoding_hint);
1032
1033 NodeOk:
1034 //kdDebug(126)<<"parsing finished. m_strProtocol="<<m_strProtocol<<" m_strHost="<<m_strHost<<" m_strPath="<<m_strPath<<endl;
1035 m_bIsMalformed = false; // Valid URL
1036
1037 //kdDebug()<<"Prot="<<m_strProtocol<<"\nUser="<<m_strUser<<"\nPass="<<m_strPass<<"\nHost="<<m_strHost<<"\nPath="<<m_strPath<<"\nQuery="<<m_strQuery_encoded<<"\nRef="<<m_strRef_encoded<<"\nPort="<<m_iPort<<endl;
1038 if (m_strProtocol.isEmpty())
1039 {
1040 m_iUriMode = URL;
1041 m_strProtocol = fileProt;
1042 }
1043 return;
1044
1045 NodeErr:
1046// kdDebug(126) << "KURL couldn't parse URL \"" << _url << "\"" << endl;
1047 reset();
1048 m_strProtocol = _url;
1049 m_iUriMode = Invalid;
1050}
1051
1052KURL& KURL::operator=( const TQString& _url )
1053{
1054 reset();
1055 parse( _url );
1056
1057 return *this;
1058}
1059
1060KURL& KURL::operator=( const char * _url )
1061{
1062 reset();
1063 parse( TQString::fromLatin1(_url) );
1064
1065 return *this;
1066}
1067
1068#ifndef TQT_NO_NETWORKPROTOCOL
1069KURL& KURL::operator=( const TQUrl & u )
1070{
1071 m_strProtocol = u.protocol();
1072 m_iUriMode = Auto;
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();
1081 m_iPort = u.port();
1082
1083 return *this;
1084}
1085#endif
1086
1087KURL& KURL::operator=( const KURL& _u )
1088{
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;
1101
1102 return *this;
1103}
1104
1105bool KURL::operator<( const KURL& _u) const
1106{
1107 int i;
1108 if (!_u.isValid())
1109 {
1110 if (!isValid())
1111 {
1112 i = m_strProtocol.compare(_u.m_strProtocol);
1113 return (i < 0);
1114 }
1115 return false;
1116 }
1117 if (!isValid())
1118 return true;
1119
1120 i = m_strProtocol.compare(_u.m_strProtocol);
1121 if (i) return (i < 0);
1122
1123 i = m_strHost.compare(_u.m_strHost);
1124 if (i) return (i < 0);
1125
1126 if (m_iPort != _u.m_iPort) return (m_iPort < _u.m_iPort);
1127
1128 i = m_strPath.compare(_u.m_strPath);
1129 if (i) return (i < 0);
1130
1131 i = m_strQuery_encoded.compare(_u.m_strQuery_encoded);
1132 if (i) return (i < 0);
1133
1134 i = m_strRef_encoded.compare(_u.m_strRef_encoded);
1135 if (i) return (i < 0);
1136
1137 i = m_strUser.compare(_u.m_strUser);
1138 if (i) return (i < 0);
1139
1140 i = m_strPass.compare(_u.m_strPass);
1141 if (i) return (i < 0);
1142
1143 i = d->m_strInternalReferenceURL.compare(_u.d->m_strInternalReferenceURL);
1144 if (i) return (i < 0);
1145
1146 return false;
1147}
1148
1149bool KURL::operator==( const KURL& _u ) const
1150{
1151 if ( !isValid() || !_u.isValid() )
1152 return false;
1153
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 &&
1159 // The encoded path may be null, but the URLs are still equal (David)
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 )
1166 {
1167 return true;
1168 }
1169
1170 return false;
1171}
1172
1173bool KURL::operator==( const TQString& _u ) const
1174{
1175 KURL u( _u );
1176 return ( *this == u );
1177}
1178
1179bool KURL::cmp( const KURL &u, bool ignore_trailing ) const
1180{
1181 return equals( u, ignore_trailing );
1182}
1183
1184bool KURL::equals( const KURL &_u, bool ignore_trailing ) const
1185{
1186 return equals(_u, ignore_trailing, false);
1187}
1188
1189bool KURL::equals( const KURL &_u, bool ignore_trailing, bool ignore_internalReferenceURLS ) const
1190{
1191 if ( !isValid() || !_u.isValid() )
1192 return false;
1193
1194 if ( ignore_trailing )
1195 {
1196 TQString path1 = path(1);
1197 TQString path2 = _u.path(1);
1198 if ( path1 != path2 )
1199 return false;
1200
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)) )
1209 return true;
1210
1211 return false;
1212 }
1213
1214 return ( *this == _u );
1215}
1216
1217bool KURL::isParentOf( const KURL& _u ) const
1218{
1219 if ( !isValid() || !_u.isValid() )
1220 return false;
1221
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 )
1229 {
1230 if ( path().isEmpty() || _u.path().isEmpty() )
1231 return false; // can't work with implicit paths
1232
1233 TQString p1( cleanpath( path(), true, false ) );
1234 if ( p1[p1.length()-1] != '/' )
1235 p1 += '/';
1236 TQString p2( cleanpath( _u.path(), true, false ) );
1237 if ( p2[p2.length()-1] != '/' )
1238 p2 += '/';
1239
1240 //kdDebug(126) << "p1=" << p1 << endl;
1241 //kdDebug(126) << "p2=" << p2 << endl;
1242 //kdDebug(126) << "p1.length()=" << p1.length() << endl;
1243 //kdDebug(126) << "p2.left(!$)=" << p2.left( p1.length() ) << endl;
1244 return p2.startsWith( p1 );
1245 }
1246 return false;
1247}
1248
1249void KURL::setFileName( const TQString& _txt )
1250{
1251 m_strRef_encoded = TQString::null;
1252 int i = 0;
1253 while( _txt[i] == (TQChar)'/' ) ++i;
1254 TQString tmp;
1255 if ( i )
1256 tmp = _txt.mid( i );
1257 else
1258 tmp = _txt;
1259
1260 TQString path = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
1261 if ( path.isEmpty() )
1262 path = "/";
1263 else
1264 {
1265 int lastSlash = path.findRev( '/' );
1266 if ( lastSlash == -1)
1267 {
1268 // The first character is not a '/' ???
1269 // This looks strange ...
1270 path = "/";
1271 }
1272 else if ( path.right(1) != "/" )
1273 path.truncate( lastSlash+1 ); // keep the "/"
1274 }
1275 if (m_strPath_encoded.isEmpty())
1276 {
1277 path += tmp;
1278 setPath( path );
1279 }
1280 else
1281 {
1282 path += encode_string(tmp);
1283 setEncodedPath( path );
1284 }
1285 cleanPath();
1286}
1287
1288void KURL::cleanPath( bool cleanDirSeparator ) // taken from the old KURL
1289{
1290 if (m_iUriMode != URL) return;
1291 m_strPath = cleanpath(m_strPath, cleanDirSeparator, false);
1292 // WABA: Is this safe when "/../" is encoded with %?
1293 m_strPath_encoded = cleanpath(m_strPath_encoded, cleanDirSeparator, true);
1294}
1295
1296static TQString trailingSlash( int _trailing, const TQString &path )
1297{
1298 TQString result = path;
1299
1300 if ( _trailing == 0 )
1301 return result;
1302 else if ( _trailing == 1 )
1303 {
1304 int len = result.length();
1305 if ( (len == 0) || (result[ len - 1 ] != (TQChar)'/') )
1306 result += "/";
1307 return result;
1308 }
1309 else if ( _trailing == -1 )
1310 {
1311 if ( result == "/" )
1312 return result;
1313 int len = result.length();
1314 while (len > 1 && result[ len - 1 ] == (TQChar)'/')
1315 {
1316 len--;
1317 }
1318 result.truncate( len );
1319 return result;
1320 }
1321 else {
1322 assert( 0 );
1323 return TQString::null;
1324 }
1325}
1326
1327void KURL::adjustPath( int _trailing )
1328{
1329 if (!m_strPath_encoded.isEmpty())
1330 {
1331 m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded );
1332 }
1333 m_strPath = trailingSlash( _trailing, m_strPath );
1334}
1335
1336
1337TQString KURL::encodedPathAndQuery( int _trailing, bool _no_empty_path, int encoding_hint ) const
1338{
1339 TQString tmp;
1340 if (!m_strPath_encoded.isEmpty() && encoding_hint == 0)
1341 {
1342 tmp = trailingSlash( _trailing, m_strPath_encoded );
1343 }
1344 else
1345 {
1346 tmp = path( _trailing );
1347 if ( _no_empty_path && tmp.isEmpty() )
1348 tmp = "/";
1349 if (m_iUriMode == Mailto)
1350 {
1351 tmp = encode( tmp, 2, encoding_hint );
1352 }
1353 else
1354 {
1355 tmp = encode( tmp, 1, encoding_hint );
1356 }
1357 }
1358
1359 // TODO apply encoding_hint to the query
1360 if (!m_strQuery_encoded.isNull())
1361 tmp += '?' + m_strQuery_encoded;
1362 return tmp;
1363}
1364
1365void KURL::setEncodedPath( const TQString& _txt, int encoding_hint )
1366{
1367 m_strPath_encoded = _txt;
1368
1369 decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint );
1370 // Throw away encoding for local files, makes file-operations faster.
1371 if (m_strProtocol == fileProt)
1372 m_strPath_encoded = TQString::null;
1373
1374 if ( m_iUriMode == Auto )
1375 m_iUriMode = URL;
1376}
1377
1378
1379void KURL::setEncodedPathAndQuery( const TQString& _txt, int encoding_hint )
1380{
1381 int pos = _txt.find( '?' );
1382 if ( pos == -1 )
1383 {
1384 setEncodedPath(_txt, encoding_hint);
1385 m_strQuery_encoded = TQString::null;
1386 }
1387 else
1388 {
1389 setEncodedPath(_txt.left( pos ), encoding_hint);
1390 _setQuery(_txt.right(_txt.length() - pos - 1), encoding_hint);
1391 }
1392}
1393
1394TQString KURL::path( int _trailing ) const
1395{
1396 return trailingSlash( _trailing, path() );
1397}
1398
1399bool KURL::isLocalFile() const
1400{
1401 if ( (m_strProtocol != fileProt ) || hasSubURL() )
1402 return false;
1403
1404 if (m_strHost.isEmpty() || (m_strHost == "localhost"))
1405 return true;
1406
1407 char hostname[ 256 ];
1408 hostname[ 0 ] = '\0';
1409 if (!gethostname( hostname, 255 ))
1410 hostname[sizeof(hostname)-1] = '\0';
1411
1412 for(char *p = hostname; *p; p++)
1413 *p = tolower(*p);
1414
1415 return (m_strHost == hostname);
1416}
1417
1418void KURL::setFileEncoding(const TQString &encoding)
1419{
1420 if (!isLocalFile())
1421 return;
1422
1423 TQString q = query();
1424
1425 if (!q.isEmpty() && (q[0] == '?'))
1426 q = q.mid(1);
1427
1428 TQStringList args = TQStringList::split('&', q);
1429 for(TQStringList::Iterator it = args.begin();
1430 it != args.end();)
1431 {
1432 TQString s = decode_string(*it);
1433 if (s.startsWith("charset="))
1434 it = args.erase(it);
1435 else
1436 ++it;
1437 }
1438 if (!encoding.isEmpty())
1439 args.append("charset="+encode_string(encoding));
1440
1441 if (args.isEmpty())
1442 _setQuery(TQString::null);
1443 else
1444 _setQuery(args.join("&"));
1445}
1446
1447TQString KURL::fileEncoding() const
1448{
1449 if (!isLocalFile())
1450 return TQString::null;
1451
1452 TQString q = query();
1453
1454 if (q.isEmpty())
1455 return TQString::null;
1456
1457 if (q[0] == '?')
1458 q = q.mid(1);
1459
1460 TQStringList args = TQStringList::split('&', q);
1461 for(TQStringList::ConstIterator it = args.begin();
1462 it != args.end();
1463 ++it)
1464 {
1465 TQString s = decode_string(*it);
1466 if (s.startsWith("charset="))
1467 return s.mid(8);
1468 }
1469 return TQString::null;
1470}
1471
1472bool KURL::hasSubURL() const
1473{
1474 if ( m_strProtocol.isEmpty() || m_bIsMalformed )
1475 return false;
1476 if (m_strRef_encoded.isEmpty())
1477 return false;
1478 if (m_strRef_encoded.startsWith("gzip:"))
1479 return true;
1480 if (m_strRef_encoded.startsWith("bzip:"))
1481 return true;
1482 if (m_strRef_encoded.startsWith("bzip2:"))
1483 return true;
1484 if (m_strRef_encoded.startsWith("tar:"))
1485 return true;
1486 if (m_strRef_encoded.startsWith("ar:"))
1487 return true;
1488 if (m_strRef_encoded.startsWith("zip:"))
1489 return true;
1490 if (m_strRef_encoded.startsWith("lzma:"))
1491 return true;
1492 if (m_strRef_encoded.startsWith("xz:"))
1493 return true;
1494 if ( m_strProtocol == "error" ) // anything that starts with error: has suburls
1495 return true;
1496 return false;
1497}
1498
1499TQString KURL::url( int _trailing, int encoding_hint ) const
1500{
1501 if( m_bIsMalformed )
1502 {
1503 // Return the whole url even when the url is
1504 // malformed. Under such conditions the url
1505 // is stored in m_strProtocol.
1506 return m_strProtocol;
1507 }
1508
1509 TQString u = m_strProtocol;
1510 if (!u.isEmpty())
1511 u += ":";
1512
1513 if ( hasHost() || (m_strProtocol == fileProt) )
1514 {
1515 u += "//";
1516 if ( hasUser() )
1517 {
1518 u += encode(m_strUser, 0, encoding_hint);
1519 if ( hasPass() )
1520 {
1521 u += ":";
1522 u += encode(m_strPass, 0, encoding_hint);
1523 }
1524 u += "@";
1525 }
1526 if ( m_iUriMode == URL )
1527 {
1528 bool IPv6 = (m_strHost.find(':') != -1);
1529 if (IPv6)
1530 u += '[' + m_strHost + ']';
1531 else
1532 u += encodeHost(m_strHost, true, encoding_hint);
1533 if ( m_iPort != 0 ) {
1534 TQString buffer;
1535 buffer.sprintf( ":%u", m_iPort );
1536 u += buffer;
1537 }
1538 }
1539 else
1540 {
1541 u += m_strHost;
1542 }
1543 }
1544
1545 if ( m_iUriMode == URL || m_iUriMode == Mailto )
1546 u += encodedPathAndQuery( _trailing, false, encoding_hint );
1547 else
1548 u += encode( m_strPath, 21, encoding_hint, true );
1549
1550 if ( hasRef() )
1551 {
1552 u += "#";
1553 u += m_strRef_encoded;
1554 }
1555
1556 return u;
1557}
1558
1559TQString KURL::prettyURL( int _trailing ) const
1560{
1561 if( m_bIsMalformed )
1562 {
1563 // Return the whole url even when the url is
1564 // malformed. Under such conditions the url
1565 // is stored in m_strProtocol.
1566 return m_strProtocol;
1567 }
1568
1569 TQString u = m_strProtocol;
1570 if (!u.isEmpty())
1571 u += ":";
1572
1573 if ( hasHost() || (m_strProtocol == fileProt) )
1574 {
1575 u += "//";
1576 if ( hasUser() )
1577 {
1578 u += encode(m_strUser, 0, 0);
1579 // Don't show password!
1580 u += "@";
1581 }
1582 if ( m_iUriMode == URL )
1583 {
1584 bool IPv6 = (m_strHost.find(':') != -1);
1585 if (IPv6)
1586 {
1587 u += '[' + m_strHost + ']';
1588 }
1589 else
1590 {
1591 u += lazy_encode(m_strHost);
1592 }
1593 }
1594 else
1595 {
1596 u += lazy_encode(m_strHost);
1597 }
1598 if ( m_iPort != 0 ) {
1599 TQString buffer;
1600 buffer.sprintf( ":%u", m_iPort );
1601 u += buffer;
1602 }
1603 }
1604
1605 if (m_iUriMode == Mailto)
1606 {
1607 u += lazy_encode( m_strPath, false );
1608 }
1609 else
1610 {
1611 u += trailingSlash( _trailing, lazy_encode( m_strPath, false ) );
1612 }
1613
1614 if (!m_strQuery_encoded.isNull())
1615 u += '?' + m_strQuery_encoded;
1616
1617 if ( hasRef() )
1618 {
1619 u += "#";
1620 u += m_strRef_encoded;
1621 }
1622
1623 return u;
1624}
1625
1626TQString KURL::prettyURL( int _trailing, AdjustementFlags _flags) const
1627{
1628 TQString u = prettyURL(_trailing);
1629 if (_flags & StripFileProtocol && u.startsWith("file://")) {
1630 u.remove(0, 7);
1631#ifdef TQ_WS_WIN
1632 return TQDir::convertSeparators(u);
1633#endif
1634 }
1635 return u;
1636}
1637
1638TQString KURL::pathOrURL() const
1639{
1640 if ( isLocalFile() && m_strRef_encoded.isNull() && m_strQuery_encoded.isNull() ) {
1641 return path();
1642 } else {
1643 return prettyURL();
1644 }
1645}
1646
1647TQString KURL::htmlURL() const
1648{
1649 return TQStyleSheet::escape(prettyURL());
1650}
1651
1652KURL::List KURL::split( const KURL& _url )
1653{
1654 TQString ref;
1655 KURL::List lst;
1656 KURL url = _url;
1657
1658 while(true)
1659 {
1660 KURL u = url;
1661 u.m_strRef_encoded = TQString::null;
1662 lst.append(u);
1663 if (url.hasSubURL())
1664 {
1665 url = KURL(url.m_strRef_encoded);
1666 }
1667 else
1668 {
1669 ref = url.m_strRef_encoded;
1670 break;
1671 }
1672 }
1673
1674 // Set HTML ref in all URLs.
1675 KURL::List::Iterator it;
1676 for( it = lst.begin() ; it != lst.end(); ++it )
1677 {
1678 (*it).m_strRef_encoded = ref;
1679 }
1680
1681 return lst;
1682}
1683
1684KURL::List KURL::split( const TQString& _url )
1685{
1686 return split(KURL(_url));
1687}
1688
1689KURL KURL::join( const KURL::List & lst )
1690{
1691 if (lst.isEmpty()) return KURL();
1692 KURL tmp;
1693
1694 KURL::List::ConstIterator first = lst.fromLast();
1695 for( KURL::List::ConstIterator it = first; it != lst.end(); --it )
1696 {
1697 KURL u(*it);
1698 if (it != first)
1699 {
1700 if (!u.m_strRef_encoded) u.m_strRef_encoded = tmp.url();
1701 else u.m_strRef_encoded += "#" + tmp.url(); // Support more than one suburl thingy
1702 }
1703 tmp = u;
1704 }
1705
1706 return tmp;
1707}
1708
1709TQString KURL::fileName( bool _strip_trailing_slash ) const
1710{
1711 TQString fname;
1712 if (hasSubURL()) { // If we have a suburl, then return the filename from there
1713 KURL::List list = KURL::split(*this);
1714 KURL::List::Iterator it = list.fromLast();
1715 return (*it).fileName(_strip_trailing_slash);
1716 }
1717 const TQString &path = m_strPath;
1718
1719 int len = path.length();
1720 if ( len == 0 )
1721 return fname;
1722
1723 if ( _strip_trailing_slash )
1724 {
1725 while ( len >= 1 && path[ len - 1 ] == TQChar('/') )
1726 len--;
1727 }
1728 else if ( path[ len - 1 ] == TQChar('/') )
1729 return fname;
1730
1731 // Does the path only consist of '/' characters ?
1732 if ( len == 1 && path[ 0 ] == TQChar('/') )
1733 return fname;
1734
1735 // Skip last n slashes
1736 int n = 1;
1737 if (!m_strPath_encoded.isEmpty())
1738 {
1739 // This is hairy, we need the last unencoded slash.
1740 // Count in the encoded string how many encoded slashes follow the last
1741 // unencoded one.
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);
1745 }
1746 int i = len;
1747 do {
1748 i = path.findRev( TQChar('/'), i - 1 );
1749 }
1750 while (--n && (i > 0));
1751
1752 // If ( i == -1 ) => the first character is not a '/'
1753 // So it's some URL like file:blah.tgz, return the whole path
1754 if ( i == -1 ) {
1755 if ( len == (int)path.length() )
1756 fname = path;
1757 else
1758 // Might get here if _strip_trailing_slash is true
1759 fname = path.left( len );
1760 }
1761 else
1762 {
1763 fname = path.mid( i + 1, len - i - 1 ); // TO CHECK
1764 }
1765 return fname;
1766}
1767
1768void KURL::addPath( const TQString& _txt )
1769{
1770 if (hasSubURL())
1771 {
1772 KURL::List lst = split( *this );
1773 KURL &u = lst.last();
1774 u.addPath(_txt);
1775 *this = join( lst );
1776 return;
1777 }
1778
1779 m_strPath_encoded = TQString::null;
1780
1781 if ( _txt.isEmpty() )
1782 return;
1783
1784 int i = 0;
1785 int len = m_strPath.length();
1786 // Add the trailing '/' if it is missing
1787 if ( _txt[0] != (TQChar)'/' && ( len == 0 || m_strPath[ len - 1 ] != (TQChar)'/' ) )
1788 m_strPath += "/";
1789
1790 // No double '/' characters
1791 i = 0;
1792 if ( len != 0 && m_strPath[ len - 1 ] == (TQChar)'/' )
1793 {
1794 while( _txt[i] == (TQChar)'/' )
1795 ++i;
1796 }
1797
1798 m_strPath += _txt.mid( i );
1799}
1800
1801TQString KURL::directory( bool _strip_trailing_slash_from_result,
1802 bool _ignore_trailing_slash_in_path ) const
1803{
1804 TQString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
1805 if ( _ignore_trailing_slash_in_path )
1806 result = trailingSlash( -1, result );
1807
1808 if ( result.isEmpty() || result == "/" )
1809 return result;
1810
1811 int i = result.findRev( "/" );
1812 // If ( i == -1 ) => the first character is not a '/'
1813 // So it's some URL like file:blah.tgz, with no path
1814 if ( i == -1 )
1815 return TQString::null;
1816
1817 if ( i == 0 )
1818 {
1819 result = "/";
1820 return result;
1821 }
1822
1823 if ( _strip_trailing_slash_from_result )
1824 result = result.left( i );
1825 else
1826 result = result.left( i + 1 );
1827
1828 if (!m_strPath_encoded.isEmpty())
1829 result = decode(result);
1830
1831 return result;
1832}
1833
1834
1835bool KURL::cd( const TQString& _dir )
1836{
1837 if ( _dir.isEmpty() || m_bIsMalformed )
1838 return false;
1839
1840 if (hasSubURL())
1841 {
1842 KURL::List lst = split( *this );
1843 KURL &u = lst.last();
1844 u.cd(_dir);
1845 *this = join( lst );
1846 return true;
1847 }
1848
1849 // absolute path ?
1850 if ( _dir[0] == (TQChar)'/' )
1851 {
1852 m_strPath_encoded = TQString::null;
1853 m_strPath = _dir;
1854 setHTMLRef( TQString::null );
1855 m_strQuery_encoded = TQString::null;
1856 return true;
1857 }
1858
1859 // Users home directory on the local disk ?
1860 if ( ( _dir[0] == (TQChar)'~' ) && ( m_strProtocol == fileProt ))
1861 {
1862 m_strPath_encoded = TQString::null;
1863 m_strPath = TQDir::homeDirPath();
1864 m_strPath += "/";
1865 m_strPath += _dir.right(m_strPath.length() - 1);
1866 setHTMLRef( TQString::null );
1867 m_strQuery_encoded = TQString::null;
1868 return true;
1869 }
1870
1871 // relative path
1872 // we always work on the past of the first url.
1873 // Sub URLs are not touched.
1874
1875 // append '/' if necessary
1876 TQString p = path(1);
1877 p += _dir;
1878 p = cleanpath( p, true, false );
1879 setPath( p );
1880
1881 setHTMLRef( TQString::null );
1882 m_strQuery_encoded = TQString::null;
1883
1884 return true;
1885}
1886
1887KURL KURL::upURL( ) const
1888{
1889 if (!query().isEmpty())
1890 {
1891 KURL u(*this);
1892 u._setQuery(TQString::null);
1893 return u;
1894 };
1895
1896 if (!hasSubURL())
1897 {
1898 KURL u(*this);
1899
1900 u.cd("../");
1901
1902 return u;
1903 }
1904
1905 // We have a subURL.
1906 KURL::List lst = split( *this );
1907 if (lst.isEmpty())
1908 return KURL(); // Huh?
1909 while (true)
1910 {
1911 KURL &u = lst.last();
1912 TQString old = u.path();
1913 u.cd("../");
1914 if (u.path() != old)
1915 break; // Finshed.
1916 if (lst.count() == 1)
1917 break; // Finished.
1918 lst.remove(lst.fromLast());
1919 }
1920 return join( lst );
1921}
1922
1923TQString KURL::htmlRef() const
1924{
1925 if ( !hasSubURL() )
1926 {
1927 return decode( ref() );
1928 }
1929
1930 List lst = split( *this );
1931 return decode( (*lst.begin()).ref() );
1932}
1933
1934TQString KURL::encodedHtmlRef() const
1935{
1936 if ( !hasSubURL() )
1937 {
1938 return ref();
1939 }
1940
1941 List lst = split( *this );
1942 return (*lst.begin()).ref();
1943}
1944
1945void KURL::setHTMLRef( const TQString& _ref )
1946{
1947 if ( !hasSubURL() )
1948 {
1949 m_strRef_encoded = encode( _ref, 0, 0 /*?*/);
1950 return;
1951 }
1952
1953 List lst = split( *this );
1954
1955 (*lst.begin()).setRef( encode( _ref, 0, 0 /*?*/) );
1956
1957 *this = join( lst );
1958}
1959
1960bool KURL::hasHTMLRef() const
1961{
1962 if ( !hasSubURL() )
1963 {
1964 return hasRef();
1965 }
1966
1967 List lst = split( *this );
1968 return (*lst.begin()).hasRef();
1969}
1970
1971void
1972KURL::setProtocol( const TQString& _txt )
1973{
1974 m_strProtocol = _txt;
1975 if ( m_iUriMode == Auto ) m_iUriMode = uriModeForProtocol( m_strProtocol );
1976 m_bIsMalformed = false;
1977}
1978
1979void
1980KURL::setUser( const TQString& _txt )
1981{
1982 if ( _txt.isEmpty() )
1983 m_strUser = TQString::null;
1984 else
1985 m_strUser = _txt;
1986}
1987
1988void
1989KURL::setPass( const TQString& _txt )
1990{
1991 if ( _txt.isEmpty() )
1992 m_strPass = TQString::null;
1993 else
1994 m_strPass = _txt;
1995}
1996
1997void
1998KURL::setHost( const TQString& _txt )
1999{
2000 if ( m_iUriMode == Auto )
2001 m_iUriMode = URL;
2002 switch ( m_iUriMode )
2003 {
2004 case URL:
2005#ifndef KDE_QT_ONLY
2006 m_strHost = KIDNA::toUnicode(_txt);
2007 if (m_strHost.isEmpty())
2008 m_strHost = _txt.lower(); // Probably an invalid hostname, but...
2009#else
2010 m_strHost = _txt.lower();
2011#endif
2012 break;
2013 default:
2014 m_strHost = _txt;
2015 break;
2016 }
2017}
2018
2019void
2020KURL::setPort( unsigned short int _p )
2021{
2022 m_iPort = _p;
2023}
2024
2025void KURL::setPath( const TQString & path )
2026{
2027 if (isEmpty())
2028 m_bIsMalformed = false;
2029 if (m_strProtocol.isEmpty())
2030 {
2031 m_strProtocol = fileProt;
2032 }
2033 m_strPath = path;
2034 m_strPath_encoded = TQString::null;
2035 if ( m_iUriMode == Auto )
2036 m_iUriMode = URL;
2037}
2038
2039void KURL::setDirectory( const TQString &dir)
2040{
2041 if ( dir.endsWith("/"))
2042 setPath(dir);
2043 else
2044 setPath(dir+"/");
2045}
2046
2047void KURL::setQuery( const TQString &_txt, int encoding_hint)
2048{
2049 if (_txt[0] == (TQChar)'?')
2050 _setQuery( _txt.length() > 1 ? _txt.mid(1) : "" /*empty, not null*/, encoding_hint );
2051 else
2052 _setQuery( _txt, encoding_hint );
2053}
2054
2055// This is a private function that expects a query without '?'
2056void KURL::_setQuery( const TQString &_txt, int encoding_hint)
2057{
2058 m_strQuery_encoded = _txt;
2059 if (!_txt.length())
2060 return;
2061
2062 int l = m_strQuery_encoded.length();
2063 int i = 0;
2064 TQString result;
2065 while (i < l)
2066 {
2067 int s = i;
2068 // Re-encode. Break encoded string up according to the reserved
2069 // characters '&:;=/?' and re-encode part by part.
2070 while(i < l)
2071 {
2072 char c = m_strQuery_encoded[i].latin1();
2073 if ((c == '&') || (c == ':') || (c == ';') ||
2074 (c == '=') || (c == '/') || (c == '?'))
2075 break;
2076 i++;
2077 }
2078 if (i > s)
2079 {
2080 TQString tmp = m_strQuery_encoded.mid(s, i-s);
2081 TQString newTmp;
2082 decode( tmp, newTmp, tmp, encoding_hint, false );
2083 result += tmp;
2084 }
2085 if (i < l)
2086 {
2087 result += m_strQuery_encoded[i];
2088 i++;
2089 }
2090 }
2091 m_strQuery_encoded = result;
2092}
2093
2094TQString KURL::query() const
2095{
2096 if (m_strQuery_encoded.isNull())
2097 return TQString::null;
2098 return '?'+m_strQuery_encoded;
2099}
2100
2101TQString KURL::decode_string(const TQString &str, int encoding_hint)
2102{
2103 return decode(str, encoding_hint);
2104}
2105
2106TQString KURL::encode_string(const TQString &str, int encoding_hint)
2107{
2108 return encode(str, 1, encoding_hint);
2109}
2110
2111TQString KURL::encode_string_no_slash(const TQString &str, int encoding_hint)
2112{
2113 return encode(str, 0, encoding_hint);
2114}
2115
2116bool urlcmp( const TQString& _url1, const TQString& _url2 )
2117{
2118 // Both empty ?
2119 if ( _url1.isEmpty() && _url2.isEmpty() )
2120 return true;
2121 // Only one empty ?
2122 if ( _url1.isEmpty() || _url2.isEmpty() )
2123 return false;
2124
2125 KURL::List list1 = KURL::split( _url1 );
2126 KURL::List list2 = KURL::split( _url2 );
2127
2128 // Malformed ?
2129 if ( list1.isEmpty() || list2.isEmpty() )
2130 return false;
2131
2132 return ( list1 == list2 );
2133}
2134
2135bool urlcmp( const TQString& _url1, const TQString& _url2, bool _ignore_trailing, bool _ignore_ref )
2136{
2137 // Both empty ?
2138 if ( _url1.isEmpty() && _url2.isEmpty() )
2139 return true;
2140 // Only one empty ?
2141 if ( _url1.isEmpty() || _url2.isEmpty() )
2142 return false;
2143
2144 KURL::List list1 = KURL::split( _url1 );
2145 KURL::List list2 = KURL::split( _url2 );
2146
2147 // Malformed ?
2148 if ( list1.isEmpty() || list2.isEmpty() )
2149 return false;
2150
2151 unsigned int size = list1.count();
2152 if ( list2.count() != size )
2153 return false;
2154
2155 if ( _ignore_ref )
2156 {
2157 (*list1.begin()).setRef(TQString::null);
2158 (*list2.begin()).setRef(TQString::null);
2159 }
2160
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 ) )
2165 return false;
2166
2167 return true;
2168}
2169
2170TQMap< TQString, TQString > KURL::queryItems( int options ) const {
2171 return queryItems(options, 0);
2172}
2173
2174TQMap< TQString, TQString > KURL::queryItems( int options, int encoding_hint ) const {
2175 if ( m_strQuery_encoded.isEmpty() )
2176 return TQMap<TQString,TQString>();
2177
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 ) { // = is not the first char...
2183 TQString name = (*it).left( equal_pos );
2184 if ( options & CaseInsensitiveKeys )
2185 name = name.lower();
2186 TQString value = (*it).mid( equal_pos + 1 );
2187 if ( value.isEmpty() )
2188 result.insert( name, TQString::fromLatin1("") );
2189 else {
2190 // ### why is decoding name not necessary?
2191 value.replace( '+', ' ' ); // + in queries means space
2192 result.insert( name, decode_string( value, encoding_hint ) );
2193 }
2194 } else if ( equal_pos < 0 ) { // no =
2195 TQString name = (*it);
2196 if ( options & CaseInsensitiveKeys )
2197 name = name.lower();
2198 result.insert( name, TQString::null );
2199 }
2200 }
2201
2202 return result;
2203}
2204
2205TQString KURL::queryItem( const TQString& _item ) const
2206{
2207 return queryItem( _item, 0 );
2208}
2209
2210TQString KURL::queryItem( const TQString& _item, int encoding_hint ) const
2211{
2212 TQString item = _item + '=';
2213 if ( m_strQuery_encoded.length() <= 1 )
2214 return TQString::null;
2215
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 )
2219 {
2220 if ( (*it).startsWith( item ) )
2221 {
2222 if ( (*it).length() > _len )
2223 {
2224 TQString str = (*it).mid( _len );
2225 str.replace( '+', ' ' ); // + in queries means space.
2226 return decode_string( str, encoding_hint );
2227 }
2228 else // empty value
2229 return TQString::fromLatin1("");
2230 }
2231 }
2232
2233 return TQString::null;
2234}
2235
2236void KURL::removeQueryItem( const TQString& _item )
2237{
2238 TQString item = _item + '=';
2239 if ( m_strQuery_encoded.length() <= 1 )
2240 return;
2241
2242 TQStringList items = TQStringList::split( '&', m_strQuery_encoded );
2243 for ( TQStringList::Iterator it = items.begin(); it != items.end(); )
2244 {
2245 if ( (*it).startsWith( item ) || (*it == _item) )
2246 {
2247 TQStringList::Iterator deleteIt = it;
2248 ++it;
2249 items.remove(deleteIt);
2250 }
2251 else
2252 {
2253 ++it;
2254 }
2255 }
2256 m_strQuery_encoded = items.join( "&" );
2257}
2258
2259void KURL::addQueryItem( const TQString& _item, const TQString& _value, int encoding_hint )
2260{
2261 TQString item = _item + '=';
2262 TQString value = encode( _value, 0, encoding_hint );
2263
2264 if (!m_strQuery_encoded.isEmpty())
2265 m_strQuery_encoded += '&';
2266 m_strQuery_encoded += item + value;
2267}
2268
2269// static
2270KURL KURL::fromPathOrURL( const TQString& text )
2271{
2272 if ( text.isEmpty() )
2273 return KURL();
2274
2275 KURL url;
2276 if (!TQDir::isRelativePath(text))
2277 url.setPath( text );
2278 else
2279 url = text;
2280
2281 return url;
2282}
2283
2284static TQString _relativePath(const TQString &base_dir, const TQString &path, bool &isParent)
2285{
2286 TQString _base_dir(TQDir::cleanDirPath(base_dir));
2287 TQString _path(TQDir::cleanDirPath(path.isEmpty() || (path[0] != (TQChar)'/') ? _base_dir+"/"+path : path));
2288
2289 if (_base_dir.isEmpty())
2290 return _path;
2291
2292 if (_base_dir[_base_dir.length()-1] != '/')
2293 _base_dir.append('/');
2294
2295 TQStringList list1 = TQStringList::split('/', _base_dir);
2296 TQStringList list2 = TQStringList::split('/', _path);
2297
2298 // Find where they meet
2299 uint level = 0;
2300 uint maxLevel = TQMIN(list1.count(), list2.count());
2301 while((level < maxLevel) && (list1[level] == list2[level])) level++;
2302
2303 TQString result;
2304 // Need to go down out of the first path to the common branch.
2305 for(uint i = level; i < list1.count(); i++)
2306 result.append("../");
2307
2308 // Now up up from the common branch to the second path.
2309 for(uint i = level; i < list2.count(); i++)
2310 result.append(list2[i]).append("/");
2311
2312 if ((level < list2.count()) && (path[path.length()-1] != (TQChar)'/'))
2313 result.truncate(result.length()-1);
2314
2315 isParent = (level == list1.count());
2316
2317 return result;
2318}
2319
2320TQString KURL::relativePath(const TQString &base_dir, const TQString &path, bool *isParent)
2321{
2322 bool parent = false;
2323 TQString result = _relativePath(base_dir, path, parent);
2324 if (parent)
2325 result.prepend("./");
2326
2327 if (isParent)
2328 *isParent = parent;
2329
2330 return result;
2331}
2332
2333void KURL::setInternalReferenceURL( const TQString& url ) {
2334 d->m_strInternalReferenceURL = url;
2335}
2336
2337TQString KURL::internalReferenceURL( void ) const {
2338 return d->m_strInternalReferenceURL;
2339}
2340
2341TQString KURL::relativeURL(const KURL &base_url, const KURL &url, int encoding_hint)
2342{
2343 if ((url.protocol() != base_url.protocol()) ||
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()))
2348 {
2349 return url.url(0, encoding_hint);
2350 }
2351
2352 TQString relURL;
2353
2354 if ((base_url.path() != url.path()) || (base_url.query() != url.query()))
2355 {
2356 bool dummy;
2357 TQString basePath = base_url.directory(false, false);
2358 relURL = encode( _relativePath(basePath, url.path(), dummy), 1, encoding_hint);
2359 relURL += url.query();
2360 }
2361
2362 if ( url.hasRef() )
2363 {
2364 relURL += "#";
2365 relURL += url.ref();
2366 }
2367
2368 if ( relURL.isEmpty() )
2369 return "./";
2370
2371 return relURL;
2372}
2373
2374int KURL::uriMode() const
2375{
2376 return m_iUriMode;
2377}
2378
2379KURL::URIMode KURL::uriModeForProtocol(const TQString& protocol)
2380{
2381 KURL::URIMode mode = Auto;
2382#ifndef KDE_QT_ONLY
2383 if (protocol == fileProt)
2384 return URL;
2385 if (TDEGlobal::_instance)
2386 mode = KProtocolInfo::uriParseMode(protocol);
2387#endif
2388 if (mode == Auto ) {
2389 if ( protocol == "ed2k" || protocol == "sig2dat" || protocol == "slsk" || protocol == "data" ) mode = RawURI;
2390 else if ( protocol == "mailto" ) mode = Mailto;
2391 else mode = URL;
2392 }
2393 return mode;
2394}
KURL::List
KURL::List is a TQValueList that contains KURLs with a few convenience methods.
Definition: kurl.h:188
KURL::List::toStringList
TQStringList toStringList() const
Converts the URLs of this list to a list of strings.
Definition: kurl.cpp:448
KURL::List::List
List()
Creates an empty List.
Definition: kurl.h:193
KURL
Represents and parses a URL.
Definition: kurl.h:128
KURL::operator==
bool operator==(const KURL &_u) const
Tests if this URL is equal to the given one.
Definition: kurl.cpp:1149
KURL::relativePath
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.
Definition: kurl.cpp:2320
KURL::path
TQString path() const
Returns the current decoded path.
Definition: kurl.h:532
KURL::isRelativeURL
static bool isRelativeURL(const TQString &_url)
Tests if a given URL is a relative as opposed to an absolute URL.
Definition: kurl.cpp:409
KURL::adjustPath
void adjustPath(int _trailing)
Adds or removes a trailing slash to/from the path.
Definition: kurl.cpp:1327
KURL::relativeURL
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.
Definition: kurl.cpp:2341
KURL::parseMailto
void parseMailto(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
Definition: kurl.cpp:760
KURL::urlcmp
bool urlcmp(const TQString &_url1, const TQString &_url2)
Compares URLs.
Definition: kurl.cpp:2116
KURL::user
TQString user() const
Returns the decoded user name (login, user id, etc) included in the URL.
Definition: kurl.h:401
KURL::directory
TQString directory(bool _strip_trailing_slash_from_result=true, bool _ignore_trailing_slash_in_path=true) const
Returns the directory of the path.
Definition: kurl.cpp:1801
KURL::port
unsigned short int port() const
Returns the port number included in the URL.
Definition: kurl.h:509
KURL::setUser
void setUser(const TQString &_txt)
Sets the user name (login, user id, etc) to include in the URL.
Definition: kurl.cpp:1980
KURL::removeQueryItem
void removeQueryItem(const TQString &_item)
Removea an item from the query.
Definition: kurl.cpp:2236
KURL::AdjustementFlags
AdjustementFlags
Flags to choose how file: URLs are treated when creating their TQString representation with prettyURL...
Definition: kurl.h:137
KURL::StripFileProtocol
@ StripFileProtocol
Strip the file: protocol from the string, i.e.
Definition: kurl.h:146
KURL::query
TQString query() const
Returns the encoded query of the URL.
Definition: kurl.cpp:2094
KURL::encodedHtmlRef
TQString encodedHtmlRef() const
Returns the encoded HTML-style reference (the part of the URL after '#')
Definition: kurl.cpp:1934
KURL::setFileEncoding
void setFileEncoding(const TQString &encoding)
Adds file encoding information.
Definition: kurl.cpp:1418
KURL::setRef
void setRef(const TQString &_txt)
Sets the encoded reference part (everything after '#')
Definition: kurl.h:756
KURL::isParentOf
bool isParentOf(const KURL &u) const
Tests if the given URL is parent of this URL.
Definition: kurl.cpp:1217
KURL::encode_string
static TQString encode_string(const TQString &str, int encoding_hint=0)
Encodes a string for use in URLs.
Definition: kurl.cpp:2106
KURL::setPath
void setPath(const TQString &path)
Sets the decoded path of the URL.
Definition: kurl.cpp:2025
KURL::encode_string_no_slash
static TQString encode_string_no_slash(const TQString &str, int encoding_hint=0)
Encodes a string for use in URLs.
Definition: kurl.cpp:2111
KURL::hasSubURL
bool hasSubURL() const
Tests if the URL has any sub URLs.
Definition: kurl.cpp:1472
KURL::setHost
void setHost(const TQString &_txt)
Sets the hostname to include in the URL.
Definition: kurl.cpp:1998
KURL::reset
void reset()
Resets the members to their "null" state.
Definition: kurl.cpp:637
KURL::setEncodedPathAndQuery
void setEncodedPathAndQuery(const TQString &_txt, int encoding_hint=0)
Sets both path and query of the URL in their encoded form.
Definition: kurl.cpp:1379
KURL::setPass
void setPass(const TQString &_txt)
Sets the password (corresponding to user()) to include in the URL.
Definition: kurl.cpp:1989
KURL::split
static List split(const TQString &_url)
Splits nested URLs into a list of URLs.
Definition: kurl.cpp:1684
KURL::fileEncoding
TQString fileEncoding() const
Returns encoding information of the URL.
Definition: kurl.cpp:1447
KURL::setHTMLRef
void setHTMLRef(const TQString &_ref)
Sets the decoded HTML-style reference.
Definition: kurl.cpp:1945
KURL::~KURL
~KURL()
Destructs the KURL object.
Definition: kurl.cpp:467
KURL::setDirectory
void setDirectory(const TQString &dir)
Sets the directory of the path, leaving the filename empty.
Definition: kurl.cpp:2039
KURL::operator<
bool operator<(const KURL &_u) const
Tests if this URL is less than the given URL.
Definition: kurl.cpp:1105
KURL::KURL
KURL()
Constructs an empty URL.
Definition: kurl.cpp:461
KURL::protocol
TQString protocol() const
Returns the protocol for the URL.
Definition: kurl.h:367
KURL::isEmpty
bool isEmpty() const
Tests if the KURL is empty.
Definition: kurl.cpp:652
KURL::hasHost
bool hasHost() const
Tests if this URL has a hostname included in it.
Definition: kurl.h:498
KURL::parseURL
void parseURL(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
Definition: kurl.cpp:779
KURL::hasPass
bool hasPass() const
Tests if this URL has a password included in it.
Definition: kurl.h:467
KURL::operator=
KURL & operator=(const KURL &_u)
Copies the values of the given URL into this one.
Definition: kurl.cpp:1087
KURL::setPort
void setPort(unsigned short int _p)
Sets the port number to include in the URL.
Definition: kurl.cpp:2020
KURL::cd
bool cd(const TQString &_dir)
Changes the directory by descending into the given directory.
Definition: kurl.cpp:1835
KURL::parseRawURI
void parseRawURI(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
Definition: kurl.cpp:727
KURL::queryItem
TQString queryItem(const TQString &item) const
Returns the value of a certain query item.
Definition: kurl.cpp:2205
KURL::hasUser
bool hasUser() const
Tests if this URL has a user name included in it.
Definition: kurl.h:425
KURL::join
static KURL join(const List &_list)
Joins a list of URLs into a single URL with sub URLs.
Definition: kurl.cpp:1689
KURL::addPath
void addPath(const TQString &txt)
Adds to the current path.
Definition: kurl.cpp:1768
KURL::setQuery
void setQuery(const TQString &_txt, int encoding_hint=0)
Sets the encoded query of the URL.
Definition: kurl.cpp:2047
KURL::fileName
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
Returns the filename of the path.
Definition: kurl.cpp:1709
KURL::hasHTMLRef
bool hasHTMLRef() const
Tests if there is an HTML-style reference.
Definition: kurl.cpp:1960
KURL::addQueryItem
void addQueryItem(const TQString &_item, const TQString &_value, int encoding_hint=0)
Adds an additional query item.
Definition: kurl.cpp:2259
KURL::cleanPath
void cleanPath(bool cleanDirSeparator=true)
Resolves "." and ".." components in path.
Definition: kurl.cpp:1288
KURL::parse
void parse(const TQString &_url, int encoding_hint=0)
Parses the given string and fills the URL's values on success.
Definition: kurl.cpp:657
KURL::CaseInsensitiveKeys
@ CaseInsensitiveKeys
Normalize query keys to lowercase.
Definition: kurl.h:940
KURL::url
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.
Definition: kurl.cpp:1499
KURL::host
TQString host() const
Returns the decoded hostname included in the URL.
Definition: kurl.h:477
KURL::decode_string
static TQString decode_string(const TQString &str, int encoding_hint=0)
Decodes a string as used in URLs.
Definition: kurl.cpp:2101
KURL::uriModeForProtocol
static URIMode uriModeForProtocol(const TQString &protocol)
Determines which URI mode is suitable for processing URIs of a given protocol.
Definition: kurl.cpp:2379
KURL::cmp
bool cmp(const KURL &u, bool ignore_trailing=false) const TDE_DEPRECATED
Compares this URL with another one.
Definition: kurl.cpp:1179
KURL::pass
TQString pass() const
Returns the decoded password (corresponding to user()) included in the URL.
Definition: kurl.h:440
KURL::equals
bool equals(const KURL &u, bool ignore_trailing=false) const
Compares this URL with another one.
Definition: kurl.cpp:1184
KURL::setFileName
void setFileName(const TQString &_txt)
Sets the filename of the path.
Definition: kurl.cpp:1249
KURL::uriMode
int uriMode() const
Returns the URI processing mode for the URL.
Definition: kurl.cpp:2374
KURL::encodedPathAndQuery
TQString encodedPathAndQuery(int _trailing=0, bool _no_empty_path=false, int encoding_hint=0) const
Returns the encoded path and the query.
Definition: kurl.cpp:1337
KURL::isLocalFile
bool isLocalFile() const
Tests if the file is local.
Definition: kurl.cpp:1399
KURL::ref
TQString ref() const
Returns the encoded reference of the URL.
Definition: kurl.h:743
KURL::URIMode
URIMode
Defines the type of URI we are processing.
Definition: kurl.h:153
KURL::Invalid
@ Invalid
Invalid URI.
Definition: kurl.h:163
KURL::URL
@ URL
Standards compliant URL.
Definition: kurl.h:172
KURL::Auto
@ Auto
Automatically detected.
Definition: kurl.h:158
KURL::Mailto
@ Mailto
Mailto URI.
Definition: kurl.h:178
KURL::RawURI
@ RawURI
Raw URI.
Definition: kurl.h:168
KURL::prettyURL
TQString prettyURL(int _trailing=0) const
Returns the URL as string in human-friendly format.
Definition: kurl.cpp:1559
KURL::setProtocol
void setProtocol(const TQString &_txt)
Sets the protocol for the URL.
Definition: kurl.cpp:1972
KURL::upURL
KURL upURL() const
Returns the URL that is the best possible candidate for on level higher in the path hierachy.
Definition: kurl.cpp:1887
KURL::pathOrURL
TQString pathOrURL() const
Returns the URL as a string depending if it is a local file.
Definition: kurl.cpp:1638
KURL::setEncodedPath
void setEncodedPath(const TQString &_txt, int encoding_hint=0)
Sets the (already encoded) path of the URL.
Definition: kurl.cpp:1365
KURL::isValid
bool isValid() const
Tests if the URL is well formed.
Definition: kurl.h:826
KURL::htmlRef
TQString htmlRef() const
Returns decoded the HTML-style reference (the part of the URL after '#')
Definition: kurl.cpp:1923
KURL::htmlURL
TQString htmlURL() const
Returns the URL as string, escaped for HTML.
Definition: kurl.cpp:1647
KURL::fromPathOrURL
static KURL fromPathOrURL(const TQString &text)
Creates a KURL object from a TQString representing either an absolute path or a real URL.
Definition: kurl.cpp:2270
KURL::hasRef
bool hasRef() const
Tests if the URL has a reference part.
Definition: kurl.h:768
TDEGlobal::staticQString
static const TQString & staticQString(const char *str)
Creates a static TQString.
Definition: tdeglobal.cpp:148

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.