• 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 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++ ] = (TQChar)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] == (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 
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 = 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 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 class KURLPrivate
404 {
405 public:
406  TQString m_strInternalReferenceURL;
407 };
408 
409 bool 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 
433 KURL::List::List(const KURL &url)
434 {
435  append( url );
436 }
437 
438 KURL::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 
448 TQStringList 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 
461 KURL::KURL()
462 {
463  d = new KURLPrivate();
464  reset();
465 }
466 
467 KURL::~KURL()
468 {
469  if (d) {
470  delete d;
471  }
472 }
473 
474 
475 KURL::KURL( const TQString &url, int encoding_hint )
476 {
477  d = new KURLPrivate();
478  reset();
479  parse( url, encoding_hint );
480 }
481 
482 KURL::KURL( const char * url, int encoding_hint )
483 {
484  d = new KURLPrivate();
485  reset();
486  parse( TQString::fromLatin1(url), encoding_hint );
487 }
488 
489 KURL::KURL( const TQCString& url, int encoding_hint )
490 {
491  d = new KURLPrivate();
492  reset();
493  parse( TQString::fromLatin1(url), encoding_hint );
494 }
495 
496 KURL::KURL( const KURL& _u )
497 {
498  d = new KURLPrivate();
499  *this = _u;
500  d->m_strInternalReferenceURL = _u.d->m_strInternalReferenceURL;
501 }
502 
503 TQDataStream & 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 
515 TQDataStream & 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 QT_NO_NETWORKPROTOCOL
537 KURL::KURL( const TQUrl &u )
538 {
539  d = new KURLPrivate();
540  *this = u;
541 }
542 #endif
543 
544 KURL::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 
637 void 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 
652 bool KURL::isEmpty() const
653 {
654  return (m_strPath.isEmpty() && m_strProtocol.isEmpty());
655 }
656 
657 void 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 Q_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 
721 NodeErr:
722  reset();
723  m_strProtocol = _url;
724  m_iUriMode = Invalid;
725 }
726 
727 void 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 
760 void 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 
779 void 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 Q_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 
1052 KURL& KURL::operator=( const TQString& _url )
1053 {
1054  reset();
1055  parse( _url );
1056 
1057  return *this;
1058 }
1059 
1060 KURL& KURL::operator=( const char * _url )
1061 {
1062  reset();
1063  parse( TQString::fromLatin1(_url) );
1064 
1065  return *this;
1066 }
1067 
1068 #ifndef QT_NO_NETWORKPROTOCOL
1069 KURL& 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 
1087 KURL& 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 
1105 bool 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 
1149 bool 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 
1173 bool KURL::operator==( const TQString& _u ) const
1174 {
1175  KURL u( _u );
1176  return ( *this == u );
1177 }
1178 
1179 bool KURL::cmp( const KURL &u, bool ignore_trailing ) const
1180 {
1181  return equals( u, ignore_trailing );
1182 }
1183 
1184 bool KURL::equals( const KURL &_u, bool ignore_trailing ) const
1185 {
1186  return equals(_u, ignore_trailing, false);
1187 }
1188 
1189 bool 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 
1217 bool 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 
1249 void 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 
1288 void 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 
1296 static 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 
1327 void 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 
1337 TQString 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 
1365 void 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 
1379 void 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 
1394 TQString KURL::path( int _trailing ) const
1395 {
1396  return trailingSlash( _trailing, path() );
1397 }
1398 
1399 bool 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 
1418 void 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 
1447 TQString 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 
1472 bool 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 
1499 TQString 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 
1559 TQString 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 ) );
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 
1626 TQString 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 Q_WS_WIN
1632  return TQDir::convertSeparators(u);
1633 #endif
1634  }
1635  return u;
1636 }
1637 
1638 TQString 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 
1647 TQString KURL::htmlURL() const
1648 {
1649  return TQStyleSheet::escape(prettyURL());
1650 }
1651 
1652 KURL::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 
1684 KURL::List KURL::split( const TQString& _url )
1685 {
1686  return split(KURL(_url));
1687 }
1688 
1689 KURL 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 
1709 TQString 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 
1768 void 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 
1801 TQString 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 
1835 bool 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 
1887 KURL 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 
1923 TQString 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 
1934 TQString 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 
1945 void 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 
1960 bool 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 
1971 void
1972 KURL::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 
1979 void
1980 KURL::setUser( const TQString& _txt )
1981 {
1982  if ( _txt.isEmpty() )
1983  m_strUser = TQString::null;
1984  else
1985  m_strUser = _txt;
1986 }
1987 
1988 void
1989 KURL::setPass( const TQString& _txt )
1990 {
1991  if ( _txt.isEmpty() )
1992  m_strPass = TQString::null;
1993  else
1994  m_strPass = _txt;
1995 }
1996 
1997 void
1998 KURL::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 
2019 void
2020 KURL::setPort( unsigned short int _p )
2021 {
2022  m_iPort = _p;
2023 }
2024 
2025 void 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 
2039 void KURL::setDirectory( const TQString &dir)
2040 {
2041  if ( dir.endsWith("/"))
2042  setPath(dir);
2043  else
2044  setPath(dir+"/");
2045 }
2046 
2047 void 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 '?'
2056 void 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 
2094 TQString KURL::query() const
2095 {
2096  if (m_strQuery_encoded.isNull())
2097  return TQString::null;
2098  return '?'+m_strQuery_encoded;
2099 }
2100 
2101 TQString KURL::decode_string(const TQString &str, int encoding_hint)
2102 {
2103  return decode(str, encoding_hint);
2104 }
2105 
2106 TQString KURL::encode_string(const TQString &str, int encoding_hint)
2107 {
2108  return encode(str, 1, encoding_hint);
2109 }
2110 
2111 TQString KURL::encode_string_no_slash(const TQString &str, int encoding_hint)
2112 {
2113  return encode(str, 0, encoding_hint);
2114 }
2115 
2116 bool 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 
2135 bool 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 
2170 TQMap< TQString, TQString > KURL::queryItems( int options ) const {
2171  return queryItems(options, 0);
2172 }
2173 
2174 TQMap< 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 
2205 TQString KURL::queryItem( const TQString& _item ) const
2206 {
2207  return queryItem( _item, 0 );
2208 }
2209 
2210 TQString 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 
2236 void 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 
2259 void 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
2270 KURL 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 
2284 static 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 
2320 TQString 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 
2333 void KURL::setInternalReferenceURL( const TQString& url ) {
2334  d->m_strInternalReferenceURL = url;
2335 }
2336 
2337 TQString KURL::internalReferenceURL( void ) const {
2338  return d->m_strInternalReferenceURL;
2339 }
2340 
2341 TQString 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 
2374 int KURL::uriMode() const
2375 {
2376  return m_iUriMode;
2377 }
2378 
2379 KURL::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::setQuery
void setQuery(const TQString &_txt, int encoding_hint=0)
Sets the encoded query of the URL.
Definition: kurl.cpp:2047
KURL
Represents and parses a URL.
Definition: kurl.h:127
KURL::setRef
void setRef(const TQString &_txt)
Sets the encoded reference part (everything after '#')
Definition: kurl.h:756
KURL::equals
bool equals(const KURL &u, bool ignore_trailing=false) const
Compares this URL with another one.
Definition: kurl.cpp:1184
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::hasRef
bool hasRef() const
Tests if the URL has a reference part.
Definition: kurl.h:768
KURL::hasSubURL
bool hasSubURL() const
Tests if the URL has any sub URLs.
Definition: kurl.cpp:1472
KURL::operator=
KURL & operator=(const KURL &_u)
Copies the values of the given URL into this one.
Definition: kurl.cpp:1087
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::adjustPath
void adjustPath(int _trailing)
Adds or removes a trailing slash to/from the path.
Definition: kurl.cpp:1327
KURL::ref
TQString ref() const
Returns the encoded reference of the URL.
Definition: kurl.h:743
KURL::addQueryItem
void addQueryItem(const TQString &_item, const TQString &_value, int encoding_hint=0)
Adds an additional query item.
Definition: kurl.cpp:2259
KURL::URIMode
URIMode
Defines the type of URI we are processing.
Definition: kurl.h:152
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::query
TQString query() const
Returns the encoded query of the URL.
Definition: kurl.cpp:2094
KURL::RawURI
Raw URI.
Definition: kurl.h:168
KURL::protocol
TQString protocol() const
Returns the protocol for the URL.
Definition: kurl.h:367
KURL::fileName
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
Returns the filename of the path.
Definition: kurl.cpp:1709
KURL::hasPass
bool hasPass() const
Tests if this URL has a password included in it.
Definition: kurl.h:467
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::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::port
unsigned short int port() const
Returns the port number included in the URL.
Definition: kurl.h:509
KURL::pathOrURL
TQString pathOrURL() const
Returns the URL as a string depending if it is a local file.
Definition: kurl.cpp:1638
KURL::queryItem
TQString queryItem(const TQString &item) const
Returns the value of a certain query item.
Definition: kurl.cpp:2205
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::isEmpty
bool isEmpty() const
Tests if the KURL is empty.
Definition: kurl.cpp:652
KURL::split
static List split(const TQString &_url)
Splits nested URLs into a list of URLs.
Definition: kurl.cpp:1684
KURL::hasHost
bool hasHost() const
Tests if this URL has a hostname included in it.
Definition: kurl.h:498
KURL::AdjustementFlags
AdjustementFlags
Flags to choose how file: URLs are treated when creating their QString representation with prettyURL(...
Definition: kurl.h:136
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::host
TQString host() const
Returns the decoded hostname included in the URL.
Definition: kurl.h:477
KURL::user
TQString user() const
Returns the decoded user name (login, user id, etc) included in the URL.
Definition: kurl.h:401
KURL::setFileName
void setFileName(const TQString &_txt)
Sets the filename of the path.
Definition: kurl.cpp:1249
KURL::setPass
void setPass(const TQString &_txt)
Sets the password (corresponding to user()) to include in the URL.
Definition: kurl.cpp:1989
KURL::Auto
Automatically detected.
Definition: kurl.h:158
KURL::isParentOf
bool isParentOf(const KURL &u) const
Tests if the given URL is parent of this URL.
Definition: kurl.cpp:1217
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::isLocalFile
bool isLocalFile() const
Tests if the file is local.
Definition: kurl.cpp:1399
KURL::removeQueryItem
void removeQueryItem(const TQString &_item)
Removea an item from the query.
Definition: kurl.cpp:2236
KURL::setPath
void setPath(const TQString &path)
Sets the decoded path of the URL.
Definition: kurl.cpp:2025
KURL::cleanPath
void cleanPath(bool cleanDirSeparator=true)
Resolves "." and ".." components in path.
Definition: kurl.cpp:1288
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::uriMode
int uriMode() const
Returns the URI processing mode for the URL.
Definition: kurl.cpp:2374
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::operator<
bool operator<(const KURL &_u) const
Tests if this URL is less than the given URL.
Definition: kurl.cpp:1105
KURL::List::toStringList
TQStringList toStringList() const
Converts the URLs of this list to a list of strings.
Definition: kurl.cpp:448
KURL::setHost
void setHost(const TQString &_txt)
Sets the hostname to include in the URL.
Definition: kurl.cpp:1998
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::hasUser
bool hasUser() const
Tests if this URL has a user name included in it.
Definition: kurl.h:425
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::StripFileProtocol
Strip the file: protocol from the string, i.e.
Definition: kurl.h:146
TDEGlobal::staticQString
static const TQString & staticQString(const char *str)
Creates a static TQString.
Definition: tdeglobal.cpp:148
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::Mailto
Mailto URI.
Definition: kurl.h:178
KURL::KURL
KURL()
Constructs an empty URL.
Definition: kurl.cpp:461
KURL::urlcmp
bool urlcmp(const TQString &_url1, const TQString &_url2)
Definition: kurl.cpp:2116
KURL::hasHTMLRef
bool hasHTMLRef() const
Tests if there is an HTML-style reference.
Definition: kurl.cpp:1960
KURL::cd
bool cd(const TQString &_dir)
Changes the directory by descending into the given directory.
Definition: kurl.cpp:1835
KURL::cmp
bool cmp(const KURL &u, bool ignore_trailing=false) const KDE_DEPRECATED
Compares this URL with another one.
Definition: kurl.cpp:1179
KURL::~KURL
~KURL()
Destructs the KURL object.
Definition: kurl.cpp:467
KURL::htmlURL
TQString htmlURL() const
Returns the URL as string, escaped for HTML.
Definition: kurl.cpp:1647
KURL::setDirectory
void setDirectory(const TQString &dir)
Sets the directory of the path, leaving the filename empty.
Definition: kurl.cpp:2039
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::Invalid
Invalid URI.
Definition: kurl.h:163
KURL::addPath
void addPath(const TQString &txt)
Adds to the current path.
Definition: kurl.cpp:1768
KURL::URL
Standards compliant URL.
Definition: kurl.h:172
KURL::setHTMLRef
void setHTMLRef(const TQString &_ref)
Sets the decoded HTML-style reference.
Definition: kurl.cpp:1945
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::path
TQString path() const
Returns the current decoded path.
Definition: kurl.h:532
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::encodedHtmlRef
TQString encodedHtmlRef() const
Returns the encoded HTML-style reference (the part of the URL after '#')
Definition: kurl.cpp:1934
KURL::setEncodedPath
void setEncodedPath(const TQString &_txt, int encoding_hint=0)
Sets the (already encoded) path of the URL.
Definition: kurl.cpp:1365
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::setPort
void setPort(unsigned short int _p)
Sets the port number to include in the URL.
Definition: kurl.cpp:2020
KURL::CaseInsensitiveKeys
Normalize query keys to lowercase.
Definition: kurl.h:940
KURL::operator==
bool operator==(const KURL &_u) const
Tests if this URL is equal to the given one.
Definition: kurl.cpp:1149
KURL::setFileEncoding
void setFileEncoding(const TQString &encoding)
Adds file encoding information.
Definition: kurl.cpp:1418
KURL::reset
void reset()
Resets the members to their "null" state.
Definition: kurl.cpp:637
KURL::List
KURL::List is a TQValueList that contains KURLs with a few convenience methods.
Definition: kurl.h:187
KURL::fileEncoding
TQString fileEncoding() const
Returns encoding information of the URL.
Definition: kurl.cpp:1447
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::List::List
List()
Creates an empty List.
Definition: kurl.h:193
KURL::pass
TQString pass() const
Returns the decoded password (corresponding to user()) included in the URL.
Definition: kurl.h:440
KURL::isValid
bool isValid() const
Tests if the URL is well formed.
Definition: kurl.h:826
KURL::prettyURL
TQString prettyURL(int _trailing=0) const
Returns the URL as string in human-friendly format.
Definition: kurl.cpp:1559
KURL::htmlRef
TQString htmlRef() const
Returns decoded the HTML-style reference (the part of the URL after '#')
Definition: kurl.cpp:1923
KURL::setProtocol
void setProtocol(const TQString &_txt)
Sets the protocol for the URL.
Definition: kurl.cpp:1972
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

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.8.8
This website is maintained by Timothy Pearson.