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

kdecore

  • kdecore
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 <kglobal.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 Q_WS_WIN
51 # define KURL_ROOTDIR_PATH "C:/"
52 #else
53 # define KURL_ROOTDIR_PATH "/"
54 #endif
55 
56 static const TQString fileProt = "file";
57 
58 static 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 /
67 static 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++ ] = (QChar)local[i];
116  }
117 
118  TQString result = TQString(new_segment, new_length);
119  delete [] new_segment;
120  return result;
121 }
122 
123 static 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 
141 static 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 
162 static 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] == (QChar)' '))) // 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 
207 static 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 
315 static 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 
323 static 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 = KGlobal::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 = KGlobal::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 Q_WS_WIN // prepend drive letter if exists (js)
390  if (orig_pos >= 2 && isalpha(path[0].latin1()) && path[1]==':') {
391  result.prepend(TQString(path[0])+":");
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 
403 bool KURL::isRelativeURL(const TQString &_url)
404 {
405  int len = _url.length();
406  if (!len) return true; // Very short relative URL.
407  const TQChar *str = _url.unicode();
408 
409  // Absolute URL must start with alpha-character
410  if (!isalpha(str[0].latin1()))
411  return true; // Relative URL
412 
413  for(int i = 1; i < len; i++)
414  {
415  char c = str[i].latin1(); // Note: non-latin1 chars return 0!
416  if (c == ':')
417  return false; // Absolute URL
418 
419  // Protocol part may only contain alpha, digit, + or -
420  if (!isalpha(c) && !isdigit(c) && (c != '+') && (c != '-'))
421  return true; // Relative URL
422  }
423  // URL did not contain ':'
424  return true; // Relative URL
425 }
426 
427 KURL::List::List(const KURL &url)
428 {
429  append( url );
430 }
431 
432 KURL::List::List(const TQStringList &list)
433 {
434  for (TQStringList::ConstIterator it = list.begin();
435  it != list.end();
436  it++)
437  {
438  append( KURL(*it) );
439  }
440 }
441 
442 TQStringList KURL::List::toStringList() const
443 {
444  TQStringList lst;
445  for( KURL::List::ConstIterator it = begin();
446  it != end();
447  it++)
448  {
449  lst.append( (*it).url() );
450  }
451  return lst;
452 }
453 
454 
455 KURL::KURL()
456 {
457  reset();
458 }
459 
460 KURL::~KURL()
461 {
462 }
463 
464 
465 KURL::KURL( const TQString &url, int encoding_hint )
466 {
467  reset();
468  parse( url, encoding_hint );
469 }
470 
471 KURL::KURL( const char * url, int encoding_hint )
472 {
473  reset();
474  parse( TQString::fromLatin1(url), encoding_hint );
475 }
476 
477 KURL::KURL( const TQCString& url, int encoding_hint )
478 {
479  reset();
480  parse( TQString::fromLatin1(url), encoding_hint );
481 }
482 
483 KURL::KURL( const KURL& _u )
484 {
485  *this = _u;
486 }
487 
488 TQDataStream & operator<< (TQDataStream & s, const KURL & a)
489 {
490  TQString QueryForWire=a.m_strQuery_encoded;
491  if (!a.m_strQuery_encoded.isNull())
492  QueryForWire.prepend("?");
493 
494  s << a.m_strProtocol << a.m_strUser << a.m_strPass << a.m_strHost
495  << a.m_strPath << a.m_strPath_encoded << QueryForWire << a.m_strRef_encoded
496  << TQ_INT8(a.m_bIsMalformed ? 1 : 0) << a.m_iPort;
497  return s;
498 }
499 
500 TQDataStream & operator>> (TQDataStream & s, KURL & a)
501 {
502  TQ_INT8 malf;
503  TQString QueryFromWire;
504  s >> a.m_strProtocol >> a.m_strUser >> a.m_strPass >> a.m_strHost
505  >> a.m_strPath >> a.m_strPath_encoded >> QueryFromWire >> a.m_strRef_encoded
506  >> malf >> a.m_iPort;
507  a.m_bIsMalformed = (malf != 0);
508 
509  if ( QueryFromWire.isNull() )
510  a.m_strQuery_encoded = TQString::null;
511  else if ( QueryFromWire.length() == 1 ) // empty query
512  a.m_strQuery_encoded = "";
513  else
514  a.m_strQuery_encoded = QueryFromWire.mid(1);
515 
516  a.m_iUriMode = KURL::uriModeForProtocol( a.m_strProtocol );
517 
518  return s;
519 }
520 
521 #ifndef QT_NO_NETWORKPROTOCOL
522 KURL::KURL( const TQUrl &u )
523 {
524  *this = u;
525 }
526 #endif
527 
528 KURL::KURL( const KURL& _u, const TQString& _rel_url, int encoding_hint )
529 {
530  if (_u.hasSubURL()) // Operate on the last suburl, not the first
531  {
532  KURL::List lst = split( _u );
533  KURL u(lst.last(), _rel_url, encoding_hint);
534  lst.remove( lst.last() );
535  lst.append( u );
536  *this = join( lst );
537  return;
538  }
539  // WORKAROUND THE RFC 1606 LOOPHOLE THAT ALLOWS
540  // http:/index.html AS A VALID SYNTAX FOR RELATIVE
541  // URLS. ( RFC 2396 section 5.2 item # 3 )
542  TQString rUrl = _rel_url;
543  int len = _u.m_strProtocol.length();
544  if ( !_u.m_strHost.isEmpty() && !rUrl.isEmpty() &&
545  rUrl.find( _u.m_strProtocol, 0, false ) == 0 &&
546  rUrl[len] == ':' && (rUrl[len+1] != '/' ||
547  (rUrl[len+1] == '/' && rUrl[len+2] != '/')) )
548  {
549  rUrl.remove( 0, rUrl.find( ':' ) + 1 );
550  }
551 
552  if ( rUrl.isEmpty() )
553  {
554  *this = _u;
555  }
556  else if ( rUrl[0] == '#' )
557  {
558  *this = _u;
559  m_strRef_encoded = rUrl.mid(1);
560  if ( m_strRef_encoded.isNull() )
561  m_strRef_encoded = ""; // we know there was an (empty) html ref, we saw the '#'
562  }
563  else if ( isRelativeURL( rUrl) )
564  {
565  *this = _u;
566  m_strQuery_encoded = TQString::null;
567  m_strRef_encoded = TQString::null;
568  if ( rUrl[0] == '/')
569  {
570  if ((rUrl.length() > 1) && (rUrl[1] == '/'))
571  {
572  m_strHost = TQString::null;
573  // File protocol returns file:/// without host, strip // from rUrl
574  if (_u.m_strProtocol == fileProt)
575  rUrl.remove(0, 2);
576  }
577  m_strPath = TQString::null;
578  m_strPath_encoded = TQString::null;
579  }
580  else if ( rUrl[0] != '?' )
581  {
582  int pos = m_strPath.findRev( '/' );
583  if (pos >= 0)
584  m_strPath.truncate(pos);
585  m_strPath += '/';
586  if (!m_strPath_encoded.isEmpty())
587  {
588  pos = m_strPath_encoded.findRev( '/' );
589  if (pos >= 0)
590  m_strPath_encoded.truncate(pos);
591  m_strPath_encoded += '/';
592  }
593  }
594  else
595  {
596  if ( m_strPath.isEmpty() )
597  m_strPath = '/';
598  }
599  KURL tmp( url() + rUrl, encoding_hint);
600  *this = tmp;
601  cleanPath(false);
602  }
603  else
604  {
605  KURL tmp( rUrl, encoding_hint);
606  *this = tmp;
607  // Preserve userinfo if applicable.
608  if (!_u.m_strUser.isEmpty() && m_strUser.isEmpty() && (_u.m_strHost == m_strHost) && (_u.m_strProtocol == m_strProtocol))
609  {
610  m_strUser = _u.m_strUser;
611  m_strPass = _u.m_strPass;
612  }
613  cleanPath(false);
614  }
615 }
616 
617 void KURL::reset()
618 {
619  m_strProtocol = TQString::null;
620  m_strUser = TQString::null;
621  m_strPass = TQString::null;
622  m_strHost = TQString::null;
623  m_strPath = TQString::null;
624  m_strPath_encoded = TQString::null;
625  m_strQuery_encoded = TQString::null;
626  m_strRef_encoded = TQString::null;
627  m_bIsMalformed = true;
628  m_iPort = 0;
629  m_iUriMode = Auto;
630 }
631 
632 bool KURL::isEmpty() const
633 {
634  return (m_strPath.isEmpty() && m_strProtocol.isEmpty());
635 }
636 
637 void KURL::parse( const TQString& _url, int encoding_hint )
638 {
639  if ( _url.isEmpty() || m_iUriMode == Invalid )
640  {
641  m_strProtocol = _url;
642  m_iUriMode = Invalid;
643  return;
644  }
645 
646  const TQChar* buf = _url.unicode();
647  const TQChar* orig = buf;
648  uint len = _url.length();
649  uint pos = 0;
650 
651  // Node 1: Accept alpha or slash
652  TQChar x = buf[pos++];
653 #ifdef Q_WS_WIN
654  /* win32: accept <letter>: or <letter>:/ or <letter>:\ */
655  const bool alpha = isalpha((int)x);
656  if (alpha && len<2)
657  goto NodeErr;
658  if (alpha && buf[pos]==':' && (len==2 || (len>2 && (buf[pos+1]=='/' || buf[pos+1]=='\\'))))
659 #else
660  if ( x == (QChar)'/' )
661 #endif
662  {
663  // A slash means we immediately proceed to parse it as a file URL.
664  m_iUriMode = URL;
665  m_strProtocol = fileProt;
666  parseURL( _url, encoding_hint );
667  return;
668  }
669  if ( !isalpha( (int)x ) )
670  goto NodeErr;
671 
672  // Node 2: Accept any amount of (alpha|digit|'+'|'-')
673  // '.' is not currently accepted, because current KURL may be confused.
674  // Proceed with :// :/ or :
675  while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) ||
676  buf[pos] == (QChar)'+' || buf[pos] == (QChar)'-')) pos++;
677 
678  if (pos < len && buf[pos] == (QChar)':' )
679  {
680  m_strProtocol = TQString( orig, pos ).lower();
681  if ( m_iUriMode == Auto )
682  m_iUriMode = uriModeForProtocol( m_strProtocol );
683  // Proceed to correct parse function.
684  switch ( m_iUriMode )
685  {
686  case RawURI:
687  parseRawURI( _url );
688  return;
689  case Mailto:
690  parseMailto( _url );
691  return;
692  case URL:
693  parseURL( _url, encoding_hint );
694  return;
695  default:
696  // Unknown URI mode results in an invalid URI.
697  break;
698  }
699  }
700 
701 NodeErr:
702  reset();
703  m_strProtocol = _url;
704  m_iUriMode = Invalid;
705 }
706 
707 void KURL::parseRawURI( const TQString& _url, int encoding_hint )
708 {
709  uint len = _url.length();
710  const TQChar* buf = _url.unicode();
711 
712  uint pos = 0;
713 
714  // Accept any amount of (alpha|digit|'+'|'-')
715  // '.' is not currently accepted, because current KURL may be confused.
716  // Proceed with :
717  while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) ||
718  buf[pos] == (QChar)'+' || buf[pos] == (QChar)'-')) pos++;
719 
720  // Note that m_strProtocol is already set here, so we just skip over the protocol.
721  if (pos < len && buf[pos] == (QChar)':' )
722  pos++;
723  else { // can't happen, the caller checked all this already
724  reset();
725  m_strProtocol = _url;
726  m_iUriMode = Invalid;
727  return;
728  }
729 
730  if ( pos == len ) // can't happen, the caller checked this already
731  m_strPath = TQString::null;
732  else
733  m_strPath = decode( TQString( buf + pos, len - pos ), encoding_hint, true );
734 
735  m_bIsMalformed = false;
736 
737  return;
738 }
739 
740 void KURL::parseMailto( const TQString& _url, int encoding_hint )
741 {
742  parseURL( _url, encoding_hint);
743  if ( m_bIsMalformed )
744  return;
745  TQRegExp mailre("(.+@)(.+)");
746  if ( mailre.exactMatch( m_strPath ) )
747  {
748 #ifndef KDE_QT_ONLY
749  TQString host = KIDNA::toUnicode( mailre.cap( 2 ) );
750  if (host.isEmpty())
751  host = TQString(mailre.cap( 2 )).lower();
752 #else
753  TQString host = TQString(mailre.cap( 2 )).lower();
754 #endif
755  m_strPath = mailre.cap( 1 ) + host;
756  }
757 }
758 
759 void KURL::parseURL( const TQString& _url, int encoding_hint )
760 {
761  TQString port;
762  bool badHostName = false;
763  int start = 0;
764  uint len = _url.length();
765  const TQChar* buf = _url.unicode();
766 
767  TQChar delim;
768  TQString tmp;
769 
770  uint pos = 0;
771 
772  // Node 1: Accept alpha or slash
773  TQChar x = buf[pos++];
774 #ifdef Q_WS_WIN
775  /* win32: accept <letter>: or <letter>:/ or <letter>:\ */
776  const bool alpha = isalpha((int)x);
777  if (alpha && len<2)
778  goto NodeErr;
779  if (alpha && buf[pos]==(QChar)':' && (len==2 || (len>2 && (buf[pos+1]==(QChar)'/' || buf[pos+1]==(QChar)'\\'))))
780 #else
781  if ( x == (QChar)'/' )
782 #endif
783  goto Node9;
784  if ( !isalpha( (int)x ) )
785  goto NodeErr;
786 
787  // Node 2: Accept any amount of (alpha|digit|'+'|'-')
788  // '.' is not currently accepted, because current KURL may be confused.
789  // Proceed with :// :/ or :
790  while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) ||
791  buf[pos] == (QChar)'+' || buf[pos] == (QChar)'-')) pos++;
792 
793  // Note that m_strProtocol is already set here, so we just skip over the protocol.
794  if ( pos+2 < len && buf[pos] == (QChar)':' && buf[pos+1] == (QChar)'/' && buf[pos+2] == (QChar)'/' )
795  {
796  pos += 3;
797  }
798  else if (pos+1 < len && buf[pos] == (QChar)':' ) // Need to always compare length()-1 otherwise KURL passes "http:" as legal!!
799  {
800  pos++;
801  start = pos;
802  goto Node9;
803  }
804  else
805  goto NodeErr;
806 
807  //Node 3: We need at least one character here
808  if ( pos == len )
809  goto NodeErr;
810  start = pos;
811 
812  // Node 4: Accept any amount of characters.
813  if (buf[pos] == (QChar)'[') // An IPv6 host follows.
814  goto Node8;
815  // Terminate on / or @ or ? or # or " or ; or <
816  x = buf[pos];
817  while( (x != (QChar)':') && (x != (QChar)'@') && (x != (QChar)'/') && (x != (QChar)'?') && (x != (QChar)'#') )
818  {
819  if ((x == (QChar)'\"') || (x == (QChar)';') || (x == (QChar)'<'))
820  badHostName = true;
821  if (++pos == len)
822  break;
823  x = buf[pos];
824  }
825  if ( pos == len )
826  {
827  if (badHostName)
828  goto NodeErr;
829 
830  setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
831  goto NodeOk;
832  }
833  if ( x == (QChar)'@' )
834  {
835  m_strUser = decode(TQString( buf + start, pos - start ), encoding_hint);
836  pos++;
837  goto Node7;
838  }
839  else if ( (x == (QChar)'/') || (x == (QChar)'?') || (x == (QChar)'#'))
840  {
841  if (badHostName)
842  goto NodeErr;
843 
844  setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
845  start = pos;
846  goto Node9;
847  }
848  else if ( x != (QChar)':' )
849  goto NodeErr;
850  m_strUser = decode(TQString( buf + start, pos - start ), encoding_hint);
851  pos++;
852 
853  // Node 5: We need at least one character
854  if ( pos == len )
855  goto NodeErr;
856  start = pos++;
857 
858  // Node 6: Read everything until @, /, ? or #
859  while( (pos < len) &&
860  (buf[pos] != (QChar)'@') &&
861  (buf[pos] != (QChar)'/') &&
862  (buf[pos] != (QChar)'?') &&
863  (buf[pos] != (QChar)'#')) pos++;
864  // If we now have a '@' the ':' seperates user and password.
865  // Otherwise it seperates host and port.
866  if ( (pos == len) || (buf[pos] != (QChar)'@') )
867  {
868  // Ok the : was used to separate host and port
869  if (badHostName)
870  goto NodeErr;
871  setHost(m_strUser);
872  m_strUser = TQString::null;
873  TQString tmp( buf + start, pos - start );
874  char *endptr;
875  m_iPort = (unsigned short int)strtol(tmp.ascii(), &endptr, 10);
876  if ((pos == len) && (strlen(endptr) == 0))
877  goto NodeOk;
878  // there is more after the digits
879  pos -= strlen(endptr);
880  if ((buf[pos] != (QChar)'@') &&
881  (buf[pos] != (QChar)'/') &&
882  (buf[pos] != (QChar)'?') &&
883  (buf[pos] != (QChar)'#'))
884  goto NodeErr;
885 
886  start = pos;
887  goto Node9;
888  }
889  m_strPass = decode(TQString( buf + start, pos - start), encoding_hint);
890  pos++;
891 
892  // Node 7: We need at least one character
893  Node7:
894  if ( pos == len )
895  goto NodeErr;
896 
897  Node8:
898  if (buf[pos] == (QChar)'[')
899  {
900  // IPv6 address
901  start = ++pos; // Skip '['
902 
903  if (pos == len)
904  {
905  badHostName = true;
906  goto NodeErr;
907  }
908  // Node 8a: Read everything until ] or terminate
909  badHostName = false;
910  x = buf[pos];
911  while( (x != (QChar)']') )
912  {
913  if ((x == (QChar)'\"') || (x == (QChar)';') || (x == (QChar)'<'))
914  badHostName = true;
915  if (++pos == len)
916  {
917  badHostName = true;
918  break;
919  }
920  x = buf[pos];
921  }
922  if (badHostName)
923  goto NodeErr;
924  setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
925  if (pos < len) pos++; // Skip ']'
926  if (pos == len)
927  goto NodeOk;
928  }
929  else
930  {
931  // Non IPv6 address, with a user
932  start = pos;
933 
934  // Node 8b: Read everything until / : or terminate
935  badHostName = false;
936  x = buf[pos];
937  while( (x != (QChar)':') && (x != (QChar)'@') && (x != (QChar)'/') && (x != (QChar)'?') && (x != (QChar)'#') )
938  {
939  if ((x == (QChar)'\"') || (x == (QChar)';') || (x == (QChar)'<'))
940  badHostName = true;
941  if (++pos == len)
942  break;
943  x = buf[pos];
944  }
945  if (badHostName)
946  goto NodeErr;
947  if ( pos == len )
948  {
949  setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
950  goto NodeOk;
951  }
952  setHost(decode(TQString( buf + start, pos - start ), encoding_hint));
953  }
954  x = buf[pos];
955  if ( x == (QChar)'/' || x == (QChar)'#' || x == (QChar)'?' )
956  {
957  start = pos;
958  goto Node9;
959  }
960  else if ( x != (QChar)':' )
961  goto NodeErr;
962  pos++;
963 
964  // Node 8c: Accept at least one digit
965  if ( pos == len )
966  goto NodeErr;
967  start = pos;
968  if ( !isdigit( buf[pos++] ) )
969  goto NodeErr;
970 
971  // Node 8d: Accept any amount of digits
972  while( pos < len && isdigit( buf[pos] ) ) pos++;
973  port = TQString( buf + start, pos - start );
974  m_iPort = port.toUShort();
975  if ( pos == len )
976  goto NodeOk;
977  start = pos;
978 
979  Node9: // parse path until query or reference reached
980 
981  while( pos < len && buf[pos] != (QChar)'#' && buf[pos]!=(QChar)'?' ) pos++;
982 
983  tmp = TQString( buf + start, pos - start );
984  //kdDebug(126)<<" setting encoded path to:"<<tmp<<endl;
985  setEncodedPath( tmp, encoding_hint );
986 
987  if ( pos == len )
988  goto NodeOk;
989 
990  //Node10: // parse query or reference depending on what comes first
991  delim = (buf[pos++]==(QChar)'#'?(QChar)'?':(QChar)'#');
992 
993  start = pos;
994 
995  while(pos < len && buf[pos]!=delim ) pos++;
996 
997  tmp = TQString(buf + start, pos - start);
998  if (delim==(QChar)'#')
999  _setQuery(tmp, encoding_hint);
1000  else
1001  m_strRef_encoded = tmp;
1002 
1003  if (pos == len)
1004  goto NodeOk;
1005 
1006  //Node11: // feed the rest into the remaining variable
1007  tmp = TQString( buf + pos + 1, len - pos - 1);
1008  if (delim == (QChar)'#')
1009  m_strRef_encoded = tmp;
1010  else
1011  _setQuery(tmp, encoding_hint);
1012 
1013  NodeOk:
1014  //kdDebug(126)<<"parsing finished. m_strProtocol="<<m_strProtocol<<" m_strHost="<<m_strHost<<" m_strPath="<<m_strPath<<endl;
1015  m_bIsMalformed = false; // Valid URL
1016 
1017  //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;
1018  if (m_strProtocol.isEmpty())
1019  {
1020  m_iUriMode = URL;
1021  m_strProtocol = fileProt;
1022  }
1023  return;
1024 
1025  NodeErr:
1026 // kdDebug(126) << "KURL couldn't parse URL \"" << _url << "\"" << endl;
1027  reset();
1028  m_strProtocol = _url;
1029  m_iUriMode = Invalid;
1030 }
1031 
1032 KURL& KURL::operator=( const TQString& _url )
1033 {
1034  reset();
1035  parse( _url );
1036 
1037  return *this;
1038 }
1039 
1040 KURL& KURL::operator=( const char * _url )
1041 {
1042  reset();
1043  parse( TQString::fromLatin1(_url) );
1044 
1045  return *this;
1046 }
1047 
1048 #ifndef QT_NO_NETWORKPROTOCOL
1049 KURL& KURL::operator=( const TQUrl & u )
1050 {
1051  m_strProtocol = u.protocol();
1052  m_iUriMode = Auto;
1053  m_strUser = u.user();
1054  m_strPass = u.password();
1055  m_strHost = u.host();
1056  m_strPath = u.path( false );
1057  m_strPath_encoded = TQString::null;
1058  m_strQuery_encoded = u.query();
1059  m_strRef_encoded = u.ref();
1060  m_bIsMalformed = !u.isValid();
1061  m_iPort = u.port();
1062 
1063  return *this;
1064 }
1065 #endif
1066 
1067 KURL& KURL::operator=( const KURL& _u )
1068 {
1069  m_strProtocol = _u.m_strProtocol;
1070  m_strUser = _u.m_strUser;
1071  m_strPass = _u.m_strPass;
1072  m_strHost = _u.m_strHost;
1073  m_strPath = _u.m_strPath;
1074  m_strPath_encoded = _u.m_strPath_encoded;
1075  m_strQuery_encoded = _u.m_strQuery_encoded;
1076  m_strRef_encoded = _u.m_strRef_encoded;
1077  m_bIsMalformed = _u.m_bIsMalformed;
1078  m_iPort = _u.m_iPort;
1079  m_iUriMode = _u.m_iUriMode;
1080 
1081  return *this;
1082 }
1083 
1084 bool KURL::operator<( const KURL& _u) const
1085 {
1086  int i;
1087  if (!_u.isValid())
1088  {
1089  if (!isValid())
1090  {
1091  i = m_strProtocol.compare(_u.m_strProtocol);
1092  return (i < 0);
1093  }
1094  return false;
1095  }
1096  if (!isValid())
1097  return true;
1098 
1099  i = m_strProtocol.compare(_u.m_strProtocol);
1100  if (i) return (i < 0);
1101 
1102  i = m_strHost.compare(_u.m_strHost);
1103  if (i) return (i < 0);
1104 
1105  if (m_iPort != _u.m_iPort) return (m_iPort < _u.m_iPort);
1106 
1107  i = m_strPath.compare(_u.m_strPath);
1108  if (i) return (i < 0);
1109 
1110  i = m_strQuery_encoded.compare(_u.m_strQuery_encoded);
1111  if (i) return (i < 0);
1112 
1113  i = m_strRef_encoded.compare(_u.m_strRef_encoded);
1114  if (i) return (i < 0);
1115 
1116  i = m_strUser.compare(_u.m_strUser);
1117  if (i) return (i < 0);
1118 
1119  i = m_strPass.compare(_u.m_strPass);
1120  if (i) return (i < 0);
1121 
1122  return false;
1123 }
1124 
1125 bool KURL::operator==( const KURL& _u ) const
1126 {
1127  if ( !isValid() || !_u.isValid() )
1128  return false;
1129 
1130  if ( m_strProtocol == _u.m_strProtocol &&
1131  m_strUser == _u.m_strUser &&
1132  m_strPass == _u.m_strPass &&
1133  m_strHost == _u.m_strHost &&
1134  m_strPath == _u.m_strPath &&
1135  // The encoded path may be null, but the URLs are still equal (David)
1136  ( m_strPath_encoded.isNull() || _u.m_strPath_encoded.isNull() ||
1137  m_strPath_encoded == _u.m_strPath_encoded ) &&
1138  m_strQuery_encoded == _u.m_strQuery_encoded &&
1139  m_strRef_encoded == _u.m_strRef_encoded &&
1140  m_iPort == _u.m_iPort )
1141  {
1142  return true;
1143  }
1144 
1145  return false;
1146 }
1147 
1148 bool KURL::operator==( const TQString& _u ) const
1149 {
1150  KURL u( _u );
1151  return ( *this == u );
1152 }
1153 
1154 bool KURL::cmp( const KURL &u, bool ignore_trailing ) const
1155 {
1156  return equals( u, ignore_trailing );
1157 }
1158 
1159 bool KURL::equals( const KURL &_u, bool ignore_trailing ) const
1160 {
1161  if ( !isValid() || !_u.isValid() )
1162  return false;
1163 
1164  if ( ignore_trailing )
1165  {
1166  TQString path1 = path(1);
1167  TQString path2 = _u.path(1);
1168  if ( path1 != path2 )
1169  return false;
1170 
1171  if ( m_strProtocol == _u.m_strProtocol &&
1172  m_strUser == _u.m_strUser &&
1173  m_strPass == _u.m_strPass &&
1174  m_strHost == _u.m_strHost &&
1175  m_strQuery_encoded == _u.m_strQuery_encoded &&
1176  m_strRef_encoded == _u.m_strRef_encoded &&
1177  m_iPort == _u.m_iPort )
1178  return true;
1179 
1180  return false;
1181  }
1182 
1183  return ( *this == _u );
1184 }
1185 
1186 bool KURL::isParentOf( const KURL& _u ) const
1187 {
1188  if ( !isValid() || !_u.isValid() )
1189  return false;
1190 
1191  if ( m_strProtocol == _u.m_strProtocol &&
1192  m_strUser == _u.m_strUser &&
1193  m_strPass == _u.m_strPass &&
1194  m_strHost == _u.m_strHost &&
1195  m_strQuery_encoded == _u.m_strQuery_encoded &&
1196  m_strRef_encoded == _u.m_strRef_encoded &&
1197  m_iPort == _u.m_iPort )
1198  {
1199  if ( path().isEmpty() || _u.path().isEmpty() )
1200  return false; // can't work with implicit paths
1201 
1202  TQString p1( cleanpath( path(), true, false ) );
1203  if ( p1[p1.length()-1] != '/' )
1204  p1 += '/';
1205  TQString p2( cleanpath( _u.path(), true, false ) );
1206  if ( p2[p2.length()-1] != '/' )
1207  p2 += '/';
1208 
1209  //kdDebug(126) << "p1=" << p1 << endl;
1210  //kdDebug(126) << "p2=" << p2 << endl;
1211  //kdDebug(126) << "p1.length()=" << p1.length() << endl;
1212  //kdDebug(126) << "p2.left(!$)=" << p2.left( p1.length() ) << endl;
1213  return p2.startsWith( p1 );
1214  }
1215  return false;
1216 }
1217 
1218 void KURL::setFileName( const TQString& _txt )
1219 {
1220  m_strRef_encoded = TQString::null;
1221  int i = 0;
1222  while( _txt[i] == (QChar)'/' ) ++i;
1223  TQString tmp;
1224  if ( i )
1225  tmp = _txt.mid( i );
1226  else
1227  tmp = _txt;
1228 
1229  TQString path = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
1230  if ( path.isEmpty() )
1231  path = "/";
1232  else
1233  {
1234  int lastSlash = path.findRev( '/' );
1235  if ( lastSlash == -1)
1236  {
1237  // The first character is not a '/' ???
1238  // This looks strange ...
1239  path = "/";
1240  }
1241  else if ( path.right(1) != "/" )
1242  path.truncate( lastSlash+1 ); // keep the "/"
1243  }
1244  if (m_strPath_encoded.isEmpty())
1245  {
1246  path += tmp;
1247  setPath( path );
1248  }
1249  else
1250  {
1251  path += encode_string(tmp);
1252  setEncodedPath( path );
1253  }
1254  cleanPath();
1255 }
1256 
1257 void KURL::cleanPath( bool cleanDirSeparator ) // taken from the old KURL
1258 {
1259  if (m_iUriMode != URL) return;
1260  m_strPath = cleanpath(m_strPath, cleanDirSeparator, false);
1261  // WABA: Is this safe when "/../" is encoded with %?
1262  m_strPath_encoded = cleanpath(m_strPath_encoded, cleanDirSeparator, true);
1263 }
1264 
1265 static TQString trailingSlash( int _trailing, const TQString &path )
1266 {
1267  TQString result = path;
1268 
1269  if ( _trailing == 0 )
1270  return result;
1271  else if ( _trailing == 1 )
1272  {
1273  int len = result.length();
1274  if ( (len == 0) || (result[ len - 1 ] != (QChar)'/') )
1275  result += "/";
1276  return result;
1277  }
1278  else if ( _trailing == -1 )
1279  {
1280  if ( result == "/" )
1281  return result;
1282  int len = result.length();
1283  while (len > 1 && result[ len - 1 ] == (QChar)'/')
1284  {
1285  len--;
1286  }
1287  result.truncate( len );
1288  return result;
1289  }
1290  else {
1291  assert( 0 );
1292  return TQString::null;
1293  }
1294 }
1295 
1296 void KURL::adjustPath( int _trailing )
1297 {
1298  if (!m_strPath_encoded.isEmpty())
1299  {
1300  m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded );
1301  }
1302  m_strPath = trailingSlash( _trailing, m_strPath );
1303 }
1304 
1305 
1306 TQString KURL::encodedPathAndQuery( int _trailing, bool _no_empty_path, int encoding_hint ) const
1307 {
1308  TQString tmp;
1309  if (!m_strPath_encoded.isEmpty() && encoding_hint == 0)
1310  {
1311  tmp = trailingSlash( _trailing, m_strPath_encoded );
1312  }
1313  else
1314  {
1315  tmp = path( _trailing );
1316  if ( _no_empty_path && tmp.isEmpty() )
1317  tmp = "/";
1318  if (m_iUriMode == Mailto)
1319  {
1320  tmp = encode( tmp, 2, encoding_hint );
1321  }
1322  else
1323  {
1324  tmp = encode( tmp, 1, encoding_hint );
1325  }
1326  }
1327 
1328  // TODO apply encoding_hint to the query
1329  if (!m_strQuery_encoded.isNull())
1330  tmp += '?' + m_strQuery_encoded;
1331  return tmp;
1332 }
1333 
1334 void KURL::setEncodedPath( const TQString& _txt, int encoding_hint )
1335 {
1336  m_strPath_encoded = _txt;
1337 
1338  decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint );
1339  // Throw away encoding for local files, makes file-operations faster.
1340  if (m_strProtocol == fileProt)
1341  m_strPath_encoded = TQString::null;
1342 
1343  if ( m_iUriMode == Auto )
1344  m_iUriMode = URL;
1345 }
1346 
1347 
1348 void KURL::setEncodedPathAndQuery( const TQString& _txt, int encoding_hint )
1349 {
1350  int pos = _txt.find( '?' );
1351  if ( pos == -1 )
1352  {
1353  setEncodedPath(_txt, encoding_hint);
1354  m_strQuery_encoded = TQString::null;
1355  }
1356  else
1357  {
1358  setEncodedPath(_txt.left( pos ), encoding_hint);
1359  _setQuery(_txt.right(_txt.length() - pos - 1), encoding_hint);
1360  }
1361 }
1362 
1363 TQString KURL::path( int _trailing ) const
1364 {
1365  return trailingSlash( _trailing, path() );
1366 }
1367 
1368 bool KURL::isLocalFile() const
1369 {
1370  if ( (m_strProtocol != fileProt ) || hasSubURL() )
1371  return false;
1372 
1373  if (m_strHost.isEmpty() || (m_strHost == "localhost"))
1374  return true;
1375 
1376  char hostname[ 256 ];
1377  hostname[ 0 ] = '\0';
1378  if (!gethostname( hostname, 255 ))
1379  hostname[sizeof(hostname)-1] = '\0';
1380 
1381  for(char *p = hostname; *p; p++)
1382  *p = tolower(*p);
1383 
1384  return (m_strHost == hostname);
1385 }
1386 
1387 void KURL::setFileEncoding(const TQString &encoding)
1388 {
1389  if (!isLocalFile())
1390  return;
1391 
1392  TQString q = query();
1393 
1394  if (!q.isEmpty() && (q[0] == '?'))
1395  q = q.mid(1);
1396 
1397  TQStringList args = TQStringList::split('&', q);
1398  for(TQStringList::Iterator it = args.begin();
1399  it != args.end();)
1400  {
1401  TQString s = decode_string(*it);
1402  if (s.startsWith("charset="))
1403  it = args.erase(it);
1404  else
1405  ++it;
1406  }
1407  if (!encoding.isEmpty())
1408  args.append("charset="+encode_string(encoding));
1409 
1410  if (args.isEmpty())
1411  _setQuery(TQString::null);
1412  else
1413  _setQuery(args.join("&"));
1414 }
1415 
1416 TQString KURL::fileEncoding() const
1417 {
1418  if (!isLocalFile())
1419  return TQString::null;
1420 
1421  TQString q = query();
1422 
1423  if (q.isEmpty())
1424  return TQString::null;
1425 
1426  if (q[0] == '?')
1427  q = q.mid(1);
1428 
1429  TQStringList args = TQStringList::split('&', q);
1430  for(TQStringList::ConstIterator it = args.begin();
1431  it != args.end();
1432  ++it)
1433  {
1434  TQString s = decode_string(*it);
1435  if (s.startsWith("charset="))
1436  return s.mid(8);
1437  }
1438  return TQString::null;
1439 }
1440 
1441 bool KURL::hasSubURL() const
1442 {
1443  if ( m_strProtocol.isEmpty() || m_bIsMalformed )
1444  return false;
1445  if (m_strRef_encoded.isEmpty())
1446  return false;
1447  if (m_strRef_encoded.startsWith("gzip:"))
1448  return true;
1449  if (m_strRef_encoded.startsWith("bzip:"))
1450  return true;
1451  if (m_strRef_encoded.startsWith("bzip2:"))
1452  return true;
1453  if (m_strRef_encoded.startsWith("tar:"))
1454  return true;
1455  if (m_strRef_encoded.startsWith("ar:"))
1456  return true;
1457  if (m_strRef_encoded.startsWith("zip:"))
1458  return true;
1459  if (m_strRef_encoded.startsWith("lzma:"))
1460  return true;
1461  if (m_strRef_encoded.startsWith("xz:"))
1462  return true;
1463  if ( m_strProtocol == "error" ) // anything that starts with error: has suburls
1464  return true;
1465  return false;
1466 }
1467 
1468 TQString KURL::url( int _trailing, int encoding_hint ) const
1469 {
1470  if( m_bIsMalformed )
1471  {
1472  // Return the whole url even when the url is
1473  // malformed. Under such conditions the url
1474  // is stored in m_strProtocol.
1475  return m_strProtocol;
1476  }
1477 
1478  TQString u = m_strProtocol;
1479  if (!u.isEmpty())
1480  u += ":";
1481 
1482  if ( hasHost() || (m_strProtocol == fileProt) )
1483  {
1484  u += "//";
1485  if ( hasUser() )
1486  {
1487  u += encode(m_strUser, 0, encoding_hint);
1488  if ( hasPass() )
1489  {
1490  u += ":";
1491  u += encode(m_strPass, 0, encoding_hint);
1492  }
1493  u += "@";
1494  }
1495  if ( m_iUriMode == URL )
1496  {
1497  bool IPv6 = (m_strHost.find(':') != -1);
1498  if (IPv6)
1499  u += '[' + m_strHost + ']';
1500  else
1501  u += encodeHost(m_strHost, true, encoding_hint);
1502  if ( m_iPort != 0 ) {
1503  TQString buffer;
1504  buffer.sprintf( ":%u", m_iPort );
1505  u += buffer;
1506  }
1507  }
1508  else
1509  {
1510  u += m_strHost;
1511  }
1512  }
1513 
1514  if ( m_iUriMode == URL || m_iUriMode == Mailto )
1515  u += encodedPathAndQuery( _trailing, false, encoding_hint );
1516  else
1517  u += encode( m_strPath, 21, encoding_hint, true );
1518 
1519  if ( hasRef() )
1520  {
1521  u += "#";
1522  u += m_strRef_encoded;
1523  }
1524 
1525  return u;
1526 }
1527 
1528 TQString KURL::prettyURL( int _trailing ) const
1529 {
1530  if( m_bIsMalformed )
1531  {
1532  // Return the whole url even when the url is
1533  // malformed. Under such conditions the url
1534  // is stored in m_strProtocol.
1535  return m_strProtocol;
1536  }
1537 
1538  TQString u = m_strProtocol;
1539  if (!u.isEmpty())
1540  u += ":";
1541 
1542  if ( hasHost() || (m_strProtocol == fileProt) )
1543  {
1544  u += "//";
1545  if ( hasUser() )
1546  {
1547  u += encode(m_strUser, 0, 0);
1548  // Don't show password!
1549  u += "@";
1550  }
1551  if ( m_iUriMode == URL )
1552  {
1553  bool IPv6 = (m_strHost.find(':') != -1);
1554  if (IPv6)
1555  {
1556  u += '[' + m_strHost + ']';
1557  }
1558  else
1559  {
1560  u += lazy_encode(m_strHost);
1561  }
1562  }
1563  else
1564  {
1565  u += lazy_encode(m_strHost);
1566  }
1567  if ( m_iPort != 0 ) {
1568  TQString buffer;
1569  buffer.sprintf( ":%u", m_iPort );
1570  u += buffer;
1571  }
1572  }
1573 
1574  if (m_iUriMode == Mailto)
1575  {
1576  u += lazy_encode( m_strPath, false );
1577  }
1578  else
1579  {
1580  u += trailingSlash( _trailing, lazy_encode( m_strPath ) );
1581  }
1582 
1583  if (!m_strQuery_encoded.isNull())
1584  u += '?' + m_strQuery_encoded;
1585 
1586  if ( hasRef() )
1587  {
1588  u += "#";
1589  u += m_strRef_encoded;
1590  }
1591 
1592  return u;
1593 }
1594 
1595 TQString KURL::prettyURL( int _trailing, AdjustementFlags _flags) const
1596 {
1597  TQString u = prettyURL(_trailing);
1598  if (_flags & StripFileProtocol && u.startsWith("file://")) {
1599  u.remove(0, 7);
1600 #ifdef Q_WS_WIN
1601  return TQDir::convertSeparators(u);
1602 #endif
1603  }
1604  return u;
1605 }
1606 
1607 TQString KURL::pathOrURL() const
1608 {
1609  if ( isLocalFile() && m_strRef_encoded.isNull() && m_strQuery_encoded.isNull() ) {
1610  return path();
1611  } else {
1612  return prettyURL();
1613  }
1614 }
1615 
1616 TQString KURL::htmlURL() const
1617 {
1618  return TQStyleSheet::escape(prettyURL());
1619 }
1620 
1621 KURL::List KURL::split( const KURL& _url )
1622 {
1623  TQString ref;
1624  KURL::List lst;
1625  KURL url = _url;
1626 
1627  while(true)
1628  {
1629  KURL u = url;
1630  u.m_strRef_encoded = TQString::null;
1631  lst.append(u);
1632  if (url.hasSubURL())
1633  {
1634  url = KURL(url.m_strRef_encoded);
1635  }
1636  else
1637  {
1638  ref = url.m_strRef_encoded;
1639  break;
1640  }
1641  }
1642 
1643  // Set HTML ref in all URLs.
1644  KURL::List::Iterator it;
1645  for( it = lst.begin() ; it != lst.end(); ++it )
1646  {
1647  (*it).m_strRef_encoded = ref;
1648  }
1649 
1650  return lst;
1651 }
1652 
1653 KURL::List KURL::split( const TQString& _url )
1654 {
1655  return split(KURL(_url));
1656 }
1657 
1658 KURL KURL::join( const KURL::List & lst )
1659 {
1660  if (lst.isEmpty()) return KURL();
1661  KURL tmp;
1662 
1663  KURL::List::ConstIterator first = lst.fromLast();
1664  for( KURL::List::ConstIterator it = first; it != lst.end(); --it )
1665  {
1666  KURL u(*it);
1667  if (it != first)
1668  {
1669  if (!u.m_strRef_encoded) u.m_strRef_encoded = tmp.url();
1670  else u.m_strRef_encoded += "#" + tmp.url(); // Support more than one suburl thingy
1671  }
1672  tmp = u;
1673  }
1674 
1675  return tmp;
1676 }
1677 
1678 TQString KURL::fileName( bool _strip_trailing_slash ) const
1679 {
1680  TQString fname;
1681  if (hasSubURL()) { // If we have a suburl, then return the filename from there
1682  KURL::List list = KURL::split(*this);
1683  KURL::List::Iterator it = list.fromLast();
1684  return (*it).fileName(_strip_trailing_slash);
1685  }
1686  const TQString &path = m_strPath;
1687 
1688  int len = path.length();
1689  if ( len == 0 )
1690  return fname;
1691 
1692  if ( _strip_trailing_slash )
1693  {
1694  while ( len >= 1 && path[ len - 1 ] == TQChar('/') )
1695  len--;
1696  }
1697  else if ( path[ len - 1 ] == TQChar('/') )
1698  return fname;
1699 
1700  // Does the path only consist of '/' characters ?
1701  if ( len == 1 && path[ 0 ] == TQChar('/') )
1702  return fname;
1703 
1704  // Skip last n slashes
1705  int n = 1;
1706  if (!m_strPath_encoded.isEmpty())
1707  {
1708  // This is hairy, we need the last unencoded slash.
1709  // Count in the encoded string how many encoded slashes follow the last
1710  // unencoded one.
1711  int i = m_strPath_encoded.findRev( TQChar('/'), len - 1 );
1712  TQString fileName_encoded = m_strPath_encoded.mid(i+1);
1713  n += fileName_encoded.contains("%2f", false);
1714  }
1715  int i = len;
1716  do {
1717  i = path.findRev( TQChar('/'), i - 1 );
1718  }
1719  while (--n && (i > 0));
1720 
1721  // If ( i == -1 ) => the first character is not a '/'
1722  // So it's some URL like file:blah.tgz, return the whole path
1723  if ( i == -1 ) {
1724  if ( len == (int)path.length() )
1725  fname = path;
1726  else
1727  // Might get here if _strip_trailing_slash is true
1728  fname = path.left( len );
1729  }
1730  else
1731  {
1732  fname = path.mid( i + 1, len - i - 1 ); // TO CHECK
1733  }
1734  return fname;
1735 }
1736 
1737 void KURL::addPath( const TQString& _txt )
1738 {
1739  if (hasSubURL())
1740  {
1741  KURL::List lst = split( *this );
1742  KURL &u = lst.last();
1743  u.addPath(_txt);
1744  *this = join( lst );
1745  return;
1746  }
1747 
1748  m_strPath_encoded = TQString::null;
1749 
1750  if ( _txt.isEmpty() )
1751  return;
1752 
1753  int i = 0;
1754  int len = m_strPath.length();
1755  // Add the trailing '/' if it is missing
1756  if ( _txt[0] != (QChar)'/' && ( len == 0 || m_strPath[ len - 1 ] != (QChar)'/' ) )
1757  m_strPath += "/";
1758 
1759  // No double '/' characters
1760  i = 0;
1761  if ( len != 0 && m_strPath[ len - 1 ] == (QChar)'/' )
1762  {
1763  while( _txt[i] == (QChar)'/' )
1764  ++i;
1765  }
1766 
1767  m_strPath += _txt.mid( i );
1768 }
1769 
1770 TQString KURL::directory( bool _strip_trailing_slash_from_result,
1771  bool _ignore_trailing_slash_in_path ) const
1772 {
1773  TQString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
1774  if ( _ignore_trailing_slash_in_path )
1775  result = trailingSlash( -1, result );
1776 
1777  if ( result.isEmpty() || result == "/" )
1778  return result;
1779 
1780  int i = result.findRev( "/" );
1781  // If ( i == -1 ) => the first character is not a '/'
1782  // So it's some URL like file:blah.tgz, with no path
1783  if ( i == -1 )
1784  return TQString::null;
1785 
1786  if ( i == 0 )
1787  {
1788  result = "/";
1789  return result;
1790  }
1791 
1792  if ( _strip_trailing_slash_from_result )
1793  result = result.left( i );
1794  else
1795  result = result.left( i + 1 );
1796 
1797  if (!m_strPath_encoded.isEmpty())
1798  result = decode(result);
1799 
1800  return result;
1801 }
1802 
1803 
1804 bool KURL::cd( const TQString& _dir )
1805 {
1806  if ( _dir.isEmpty() || m_bIsMalformed )
1807  return false;
1808 
1809  if (hasSubURL())
1810  {
1811  KURL::List lst = split( *this );
1812  KURL &u = lst.last();
1813  u.cd(_dir);
1814  *this = join( lst );
1815  return true;
1816  }
1817 
1818  // absolute path ?
1819  if ( _dir[0] == (QChar)'/' )
1820  {
1821  m_strPath_encoded = TQString::null;
1822  m_strPath = _dir;
1823  setHTMLRef( TQString::null );
1824  m_strQuery_encoded = TQString::null;
1825  return true;
1826  }
1827 
1828  // Users home directory on the local disk ?
1829  if ( ( _dir[0] == (QChar)'~' ) && ( m_strProtocol == fileProt ))
1830  {
1831  m_strPath_encoded = TQString::null;
1832  m_strPath = TQDir::homeDirPath();
1833  m_strPath += "/";
1834  m_strPath += _dir.right(m_strPath.length() - 1);
1835  setHTMLRef( TQString::null );
1836  m_strQuery_encoded = TQString::null;
1837  return true;
1838  }
1839 
1840  // relative path
1841  // we always work on the past of the first url.
1842  // Sub URLs are not touched.
1843 
1844  // append '/' if necessary
1845  TQString p = path(1);
1846  p += _dir;
1847  p = cleanpath( p, true, false );
1848  setPath( p );
1849 
1850  setHTMLRef( TQString::null );
1851  m_strQuery_encoded = TQString::null;
1852 
1853  return true;
1854 }
1855 
1856 KURL KURL::upURL( ) const
1857 {
1858  if (!query().isEmpty())
1859  {
1860  KURL u(*this);
1861  u._setQuery(TQString::null);
1862  return u;
1863  };
1864 
1865  if (!hasSubURL())
1866  {
1867  KURL u(*this);
1868 
1869  u.cd("../");
1870 
1871  return u;
1872  }
1873 
1874  // We have a subURL.
1875  KURL::List lst = split( *this );
1876  if (lst.isEmpty())
1877  return KURL(); // Huh?
1878  while (true)
1879  {
1880  KURL &u = lst.last();
1881  TQString old = u.path();
1882  u.cd("../");
1883  if (u.path() != old)
1884  break; // Finshed.
1885  if (lst.count() == 1)
1886  break; // Finished.
1887  lst.remove(lst.fromLast());
1888  }
1889  return join( lst );
1890 }
1891 
1892 TQString KURL::htmlRef() const
1893 {
1894  if ( !hasSubURL() )
1895  {
1896  return decode( ref() );
1897  }
1898 
1899  List lst = split( *this );
1900  return decode( (*lst.begin()).ref() );
1901 }
1902 
1903 TQString KURL::encodedHtmlRef() const
1904 {
1905  if ( !hasSubURL() )
1906  {
1907  return ref();
1908  }
1909 
1910  List lst = split( *this );
1911  return (*lst.begin()).ref();
1912 }
1913 
1914 void KURL::setHTMLRef( const TQString& _ref )
1915 {
1916  if ( !hasSubURL() )
1917  {
1918  m_strRef_encoded = encode( _ref, 0, 0 /*?*/);
1919  return;
1920  }
1921 
1922  List lst = split( *this );
1923 
1924  (*lst.begin()).setRef( encode( _ref, 0, 0 /*?*/) );
1925 
1926  *this = join( lst );
1927 }
1928 
1929 bool KURL::hasHTMLRef() const
1930 {
1931  if ( !hasSubURL() )
1932  {
1933  return hasRef();
1934  }
1935 
1936  List lst = split( *this );
1937  return (*lst.begin()).hasRef();
1938 }
1939 
1940 void
1941 KURL::setProtocol( const TQString& _txt )
1942 {
1943  m_strProtocol = _txt;
1944  if ( m_iUriMode == Auto ) m_iUriMode = uriModeForProtocol( m_strProtocol );
1945  m_bIsMalformed = false;
1946 }
1947 
1948 void
1949 KURL::setUser( const TQString& _txt )
1950 {
1951  if ( _txt.isEmpty() )
1952  m_strUser = TQString::null;
1953  else
1954  m_strUser = _txt;
1955 }
1956 
1957 void
1958 KURL::setPass( const TQString& _txt )
1959 {
1960  if ( _txt.isEmpty() )
1961  m_strPass = TQString::null;
1962  else
1963  m_strPass = _txt;
1964 }
1965 
1966 void
1967 KURL::setHost( const TQString& _txt )
1968 {
1969  if ( m_iUriMode == Auto )
1970  m_iUriMode = URL;
1971  switch ( m_iUriMode )
1972  {
1973  case URL:
1974 #ifndef KDE_QT_ONLY
1975  m_strHost = KIDNA::toUnicode(_txt);
1976  if (m_strHost.isEmpty())
1977  m_strHost = _txt.lower(); // Probably an invalid hostname, but...
1978 #else
1979  m_strHost = _txt.lower();
1980 #endif
1981  break;
1982  default:
1983  m_strHost = _txt;
1984  break;
1985  }
1986 }
1987 
1988 void
1989 KURL::setPort( unsigned short int _p )
1990 {
1991  m_iPort = _p;
1992 }
1993 
1994 void KURL::setPath( const TQString & path )
1995 {
1996  if (isEmpty())
1997  m_bIsMalformed = false;
1998  if (m_strProtocol.isEmpty())
1999  {
2000  m_strProtocol = fileProt;
2001  }
2002  m_strPath = path;
2003  m_strPath_encoded = TQString::null;
2004  if ( m_iUriMode == Auto )
2005  m_iUriMode = URL;
2006 }
2007 
2008 void KURL::setDirectory( const TQString &dir)
2009 {
2010  if ( dir.endsWith("/"))
2011  setPath(dir);
2012  else
2013  setPath(dir+"/");
2014 }
2015 
2016 void KURL::setQuery( const TQString &_txt, int encoding_hint)
2017 {
2018  if (_txt[0] == (QChar)'?')
2019  _setQuery( _txt.length() > 1 ? _txt.mid(1) : "" /*empty, not null*/, encoding_hint );
2020  else
2021  _setQuery( _txt, encoding_hint );
2022 }
2023 
2024 // This is a private function that expects a query without '?'
2025 void KURL::_setQuery( const TQString &_txt, int encoding_hint)
2026 {
2027  m_strQuery_encoded = _txt;
2028  if (!_txt.length())
2029  return;
2030 
2031  int l = m_strQuery_encoded.length();
2032  int i = 0;
2033  TQString result;
2034  while (i < l)
2035  {
2036  int s = i;
2037  // Re-encode. Break encoded string up according to the reserved
2038  // characters '&:;=/?' and re-encode part by part.
2039  while(i < l)
2040  {
2041  char c = m_strQuery_encoded[i].latin1();
2042  if ((c == '&') || (c == ':') || (c == ';') ||
2043  (c == '=') || (c == '/') || (c == '?'))
2044  break;
2045  i++;
2046  }
2047  if (i > s)
2048  {
2049  TQString tmp = m_strQuery_encoded.mid(s, i-s);
2050  TQString newTmp;
2051  decode( tmp, newTmp, tmp, encoding_hint, false );
2052  result += tmp;
2053  }
2054  if (i < l)
2055  {
2056  result += m_strQuery_encoded[i];
2057  i++;
2058  }
2059  }
2060  m_strQuery_encoded = result;
2061 }
2062 
2063 TQString KURL::query() const
2064 {
2065  if (m_strQuery_encoded.isNull())
2066  return TQString::null;
2067  return '?'+m_strQuery_encoded;
2068 }
2069 
2070 TQString KURL::decode_string(const TQString &str, int encoding_hint)
2071 {
2072  return decode(str, encoding_hint);
2073 }
2074 
2075 TQString KURL::encode_string(const TQString &str, int encoding_hint)
2076 {
2077  return encode(str, 1, encoding_hint);
2078 }
2079 
2080 TQString KURL::encode_string_no_slash(const TQString &str, int encoding_hint)
2081 {
2082  return encode(str, 0, encoding_hint);
2083 }
2084 
2085 bool urlcmp( const TQString& _url1, const TQString& _url2 )
2086 {
2087  // Both empty ?
2088  if ( _url1.isEmpty() && _url2.isEmpty() )
2089  return true;
2090  // Only one empty ?
2091  if ( _url1.isEmpty() || _url2.isEmpty() )
2092  return false;
2093 
2094  KURL::List list1 = KURL::split( _url1 );
2095  KURL::List list2 = KURL::split( _url2 );
2096 
2097  // Malformed ?
2098  if ( list1.isEmpty() || list2.isEmpty() )
2099  return false;
2100 
2101  return ( list1 == list2 );
2102 }
2103 
2104 bool urlcmp( const TQString& _url1, const TQString& _url2, bool _ignore_trailing, bool _ignore_ref )
2105 {
2106  // Both empty ?
2107  if ( _url1.isEmpty() && _url2.isEmpty() )
2108  return true;
2109  // Only one empty ?
2110  if ( _url1.isEmpty() || _url2.isEmpty() )
2111  return false;
2112 
2113  KURL::List list1 = KURL::split( _url1 );
2114  KURL::List list2 = KURL::split( _url2 );
2115 
2116  // Malformed ?
2117  if ( list1.isEmpty() || list2.isEmpty() )
2118  return false;
2119 
2120  unsigned int size = list1.count();
2121  if ( list2.count() != size )
2122  return false;
2123 
2124  if ( _ignore_ref )
2125  {
2126  (*list1.begin()).setRef(TQString::null);
2127  (*list2.begin()).setRef(TQString::null);
2128  }
2129 
2130  KURL::List::Iterator it1 = list1.begin();
2131  KURL::List::Iterator it2 = list2.begin();
2132  for( ; it1 != list1.end() ; ++it1, ++it2 )
2133  if ( !(*it1).equals( *it2, _ignore_trailing ) )
2134  return false;
2135 
2136  return true;
2137 }
2138 
2139 TQMap< TQString, TQString > KURL::queryItems( int options ) const {
2140  return queryItems(options, 0);
2141 }
2142 
2143 TQMap< TQString, TQString > KURL::queryItems( int options, int encoding_hint ) const {
2144  if ( m_strQuery_encoded.isEmpty() )
2145  return TQMap<TQString,TQString>();
2146 
2147  TQMap< TQString, TQString > result;
2148  TQStringList items = TQStringList::split( '&', m_strQuery_encoded );
2149  for ( TQStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
2150  int equal_pos = (*it).find( '=' );
2151  if ( equal_pos > 0 ) { // = is not the first char...
2152  TQString name = (*it).left( equal_pos );
2153  if ( options & CaseInsensitiveKeys )
2154  name = name.lower();
2155  TQString value = (*it).mid( equal_pos + 1 );
2156  if ( value.isEmpty() )
2157  result.insert( name, TQString::fromLatin1("") );
2158  else {
2159  // ### why is decoding name not necessary?
2160  value.replace( '+', ' ' ); // + in queries means space
2161  result.insert( name, decode_string( value, encoding_hint ) );
2162  }
2163  } else if ( equal_pos < 0 ) { // no =
2164  TQString name = (*it);
2165  if ( options & CaseInsensitiveKeys )
2166  name = name.lower();
2167  result.insert( name, TQString::null );
2168  }
2169  }
2170 
2171  return result;
2172 }
2173 
2174 TQString KURL::queryItem( const TQString& _item ) const
2175 {
2176  return queryItem( _item, 0 );
2177 }
2178 
2179 TQString KURL::queryItem( const TQString& _item, int encoding_hint ) const
2180 {
2181  TQString item = _item + '=';
2182  if ( m_strQuery_encoded.length() <= 1 )
2183  return TQString::null;
2184 
2185  TQStringList items = TQStringList::split( '&', m_strQuery_encoded );
2186  unsigned int _len = item.length();
2187  for ( TQStringList::ConstIterator it = items.begin(); it != items.end(); ++it )
2188  {
2189  if ( (*it).startsWith( item ) )
2190  {
2191  if ( (*it).length() > _len )
2192  {
2193  TQString str = (*it).mid( _len );
2194  str.replace( '+', ' ' ); // + in queries means space.
2195  return decode_string( str, encoding_hint );
2196  }
2197  else // empty value
2198  return TQString::fromLatin1("");
2199  }
2200  }
2201 
2202  return TQString::null;
2203 }
2204 
2205 void KURL::removeQueryItem( const TQString& _item )
2206 {
2207  TQString item = _item + '=';
2208  if ( m_strQuery_encoded.length() <= 1 )
2209  return;
2210 
2211  TQStringList items = TQStringList::split( '&', m_strQuery_encoded );
2212  for ( TQStringList::Iterator it = items.begin(); it != items.end(); )
2213  {
2214  if ( (*it).startsWith( item ) || (*it == _item) )
2215  {
2216  TQStringList::Iterator deleteIt = it;
2217  ++it;
2218  items.remove(deleteIt);
2219  }
2220  else
2221  {
2222  ++it;
2223  }
2224  }
2225  m_strQuery_encoded = items.join( "&" );
2226 }
2227 
2228 void KURL::addQueryItem( const TQString& _item, const TQString& _value, int encoding_hint )
2229 {
2230  TQString item = _item + '=';
2231  TQString value = encode( _value, 0, encoding_hint );
2232 
2233  if (!m_strQuery_encoded.isEmpty())
2234  m_strQuery_encoded += '&';
2235  m_strQuery_encoded += item + value;
2236 }
2237 
2238 // static
2239 KURL KURL::fromPathOrURL( const TQString& text )
2240 {
2241  if ( text.isEmpty() )
2242  return KURL();
2243 
2244  KURL url;
2245  if (!TQDir::isRelativePath(text))
2246  url.setPath( text );
2247  else
2248  url = text;
2249 
2250  return url;
2251 }
2252 
2253 static TQString _relativePath(const TQString &base_dir, const TQString &path, bool &isParent)
2254 {
2255  TQString _base_dir(TQDir::cleanDirPath(base_dir));
2256  TQString _path(TQDir::cleanDirPath(path.isEmpty() || (path[0] != (QChar)'/') ? _base_dir+"/"+path : path));
2257 
2258  if (_base_dir.isEmpty())
2259  return _path;
2260 
2261  if (_base_dir[_base_dir.length()-1] != '/')
2262  _base_dir.append('/');
2263 
2264  TQStringList list1 = TQStringList::split('/', _base_dir);
2265  TQStringList list2 = TQStringList::split('/', _path);
2266 
2267  // Find where they meet
2268  uint level = 0;
2269  uint maxLevel = QMIN(list1.count(), list2.count());
2270  while((level < maxLevel) && (list1[level] == list2[level])) level++;
2271 
2272  TQString result;
2273  // Need to go down out of the first path to the common branch.
2274  for(uint i = level; i < list1.count(); i++)
2275  result.append("../");
2276 
2277  // Now up up from the common branch to the second path.
2278  for(uint i = level; i < list2.count(); i++)
2279  result.append(list2[i]).append("/");
2280 
2281  if ((level < list2.count()) && (path[path.length()-1] != (QChar)'/'))
2282  result.truncate(result.length()-1);
2283 
2284  isParent = (level == list1.count());
2285 
2286  return result;
2287 }
2288 
2289 TQString KURL::relativePath(const TQString &base_dir, const TQString &path, bool *isParent)
2290 {
2291  bool parent = false;
2292  TQString result = _relativePath(base_dir, path, parent);
2293  if (parent)
2294  result.prepend("./");
2295 
2296  if (isParent)
2297  *isParent = parent;
2298 
2299  return result;
2300 }
2301 
2302 
2303 TQString KURL::relativeURL(const KURL &base_url, const KURL &url, int encoding_hint)
2304 {
2305  if ((url.protocol() != base_url.protocol()) ||
2306  (url.host() != base_url.host()) ||
2307  (url.port() && url.port() != base_url.port()) ||
2308  (url.hasUser() && url.user() != base_url.user()) ||
2309  (url.hasPass() && url.pass() != base_url.pass()))
2310  {
2311  return url.url(0, encoding_hint);
2312  }
2313 
2314  TQString relURL;
2315 
2316  if ((base_url.path() != url.path()) || (base_url.query() != url.query()))
2317  {
2318  bool dummy;
2319  TQString basePath = base_url.directory(false, false);
2320  relURL = encode( _relativePath(basePath, url.path(), dummy), 1, encoding_hint);
2321  relURL += url.query();
2322  }
2323 
2324  if ( url.hasRef() )
2325  {
2326  relURL += "#";
2327  relURL += url.ref();
2328  }
2329 
2330  if ( relURL.isEmpty() )
2331  return "./";
2332 
2333  return relURL;
2334 }
2335 
2336 int KURL::uriMode() const
2337 {
2338  return m_iUriMode;
2339 }
2340 
2341 KURL::URIMode KURL::uriModeForProtocol(const TQString& protocol)
2342 {
2343 #ifndef KDE_QT_ONLY
2344  KURL::URIMode mode = Auto;
2345  if (protocol == fileProt)
2346  return URL;
2347  if (KGlobal::_instance)
2348  mode = KProtocolInfo::uriParseMode(protocol);
2349  if (mode == Auto ) {
2350 #else
2351  KURL::URIMode mode = Auto;
2352 #endif
2353  if ( protocol == "ed2k" || protocol == "sig2dat" || protocol == "slsk" || protocol == "data" ) mode = RawURI;
2354  else if ( protocol == "mailto" ) mode = Mailto;
2355  else mode = URL;
2356 #ifndef KDE_QT_ONLY
2357  }
2358 #endif
2359  return mode;
2360 }
KGlobal::staticQString
static const TQString & staticQString(const char *str)
Creates a static TQString.
Definition: kglobal.cpp:128
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:442
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:1125
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:2289
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:403
KURL::adjustPath
void adjustPath(int _trailing)
Adds or removes a trailing slash to/from the path.
Definition: kurl.cpp:1296
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:2303
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:740
KURL::urlcmp
bool urlcmp(const TQString &_url1, const TQString &_url2)
Compares URLs.
Definition: kurl.cpp:2085
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:1770
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:1949
KURL::removeQueryItem
void removeQueryItem(const TQString &_item)
Removea an item from the query.
Definition: kurl.cpp:2205
KURL::AdjustementFlags
AdjustementFlags
Flags to choose how file: URLs are treated when creating their QString 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:2063
KURL::encodedHtmlRef
TQString encodedHtmlRef() const
Returns the encoded HTML-style reference (the part of the URL after '#')
Definition: kurl.cpp:1903
KURL::setFileEncoding
void setFileEncoding(const TQString &encoding)
Adds file encoding information.
Definition: kurl.cpp:1387
KURL::setRef
void setRef(const TQString &_txt)
Sets the encoded reference part (everything after '#')
Definition: kurl.h:746
KURL::isParentOf
bool isParentOf(const KURL &u) const
Tests if the given URL is parent of this URL.
Definition: kurl.cpp:1186
KURL::encode_string
static TQString encode_string(const TQString &str, int encoding_hint=0)
Encodes a string for use in URLs.
Definition: kurl.cpp:2075
KURL::setPath
void setPath(const TQString &path)
Sets the decoded path of the URL.
Definition: kurl.cpp:1994
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:2080
KURL::hasSubURL
bool hasSubURL() const
Tests if the URL has any sub URLs.
Definition: kurl.cpp:1441
KURL::setHost
void setHost(const TQString &_txt)
Sets the hostname to include in the URL.
Definition: kurl.cpp:1967
KURL::reset
void reset()
Resets the members to their "null" state.
Definition: kurl.cpp:617
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:1348
KURL::setPass
void setPass(const TQString &_txt)
Sets the password (corresponding to user()) to include in the URL.
Definition: kurl.cpp:1958
KURL::split
static List split(const TQString &_url)
Splits nested URLs into a list of URLs.
Definition: kurl.cpp:1653
KURL::fileEncoding
TQString fileEncoding() const
Returns encoding information of the URL.
Definition: kurl.cpp:1416
KURL::setHTMLRef
void setHTMLRef(const TQString &_ref)
Sets the decoded HTML-style reference.
Definition: kurl.cpp:1914
KURL::~KURL
~KURL()
Destructs the KURL object.
Definition: kurl.cpp:460
KURL::setDirectory
void setDirectory(const TQString &dir)
Sets the directory of the path, leaving the filename empty.
Definition: kurl.cpp:2008
KURL::operator<
bool operator<(const KURL &_u) const
Tests if this URL is less than the given URL.
Definition: kurl.cpp:1084
KURL::KURL
KURL()
Constructs an empty URL.
Definition: kurl.cpp:455
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:632
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:759
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:1067
KURL::setPort
void setPort(unsigned short int _p)
Sets the port number to include in the URL.
Definition: kurl.cpp:1989
KURL::cd
bool cd(const TQString &_dir)
Changes the directory by descending into the given directory.
Definition: kurl.cpp:1804
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:707
KURL::queryItem
TQString queryItem(const TQString &item) const
Returns the value of a certain query item.
Definition: kurl.cpp:2174
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:1658
KURL::addPath
void addPath(const TQString &txt)
Adds to the current path.
Definition: kurl.cpp:1737
KURL::setQuery
void setQuery(const TQString &_txt, int encoding_hint=0)
Sets the encoded query of the URL.
Definition: kurl.cpp:2016
KURL::fileName
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
Returns the filename of the path.
Definition: kurl.cpp:1678
KURL::hasHTMLRef
bool hasHTMLRef() const
Tests if there is an HTML-style reference.
Definition: kurl.cpp:1929
KURL::addQueryItem
void addQueryItem(const TQString &_item, const TQString &_value, int encoding_hint=0)
Adds an additional query item.
Definition: kurl.cpp:2228
KURL::cleanPath
void cleanPath(bool cleanDirSeparator=true)
Resolves "." and ".." components in path.
Definition: kurl.cpp:1257
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:637
KURL::CaseInsensitiveKeys
@ CaseInsensitiveKeys
Normalize query keys to lowercase.
Definition: kurl.h:930
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:1468
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:2070
KURL::uriModeForProtocol
static URIMode uriModeForProtocol(const TQString &protocol)
Determines which URI mode is suitable for processing URIs of a given protocol.
Definition: kurl.cpp:2341
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:1159
KURL::setFileName
void setFileName(const TQString &_txt)
Sets the filename of the path.
Definition: kurl.cpp:1218
KURL::uriMode
int uriMode() const
Returns the URI processing mode for the URL.
Definition: kurl.cpp:2336
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:1306
KURL::isLocalFile
bool isLocalFile() const
Tests if the file is local.
Definition: kurl.cpp:1368
KURL::ref
TQString ref() const
Returns the encoded reference of the URL.
Definition: kurl.h:733
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::cmp
bool cmp(const KURL &u, bool ignore_trailing=false) const KDE_DEPRECATED
Compares this URL with another one.
Definition: kurl.cpp:1154
KURL::prettyURL
TQString prettyURL(int _trailing=0) const
Returns the URL as string in human-friendly format.
Definition: kurl.cpp:1528
KURL::setProtocol
void setProtocol(const TQString &_txt)
Sets the protocol for the URL.
Definition: kurl.cpp:1941
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:1856
KURL::pathOrURL
TQString pathOrURL() const
Returns the URL as a string depending if it is a local file.
Definition: kurl.cpp:1607
KURL::setEncodedPath
void setEncodedPath(const TQString &_txt, int encoding_hint=0)
Sets the (already encoded) path of the URL.
Definition: kurl.cpp:1334
KURL::isValid
bool isValid() const
Tests if the URL is well formed.
Definition: kurl.h:816
KURL::htmlRef
TQString htmlRef() const
Returns decoded the HTML-style reference (the part of the URL after '#')
Definition: kurl.cpp:1892
KURL::htmlURL
TQString htmlURL() const
Returns the URL as string, escaped for HTML.
Definition: kurl.cpp:1616
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:2239
KURL::hasRef
bool hasRef() const
Tests if the URL has a reference part.
Definition: kurl.h:758

kdecore

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

kdecore

Skip menu "kdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdecore by doxygen 1.9.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |