summaryrefslogtreecommitdiffabout
path: root/microkde/kurl.cpp
Unidiff
Diffstat (limited to 'microkde/kurl.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--microkde/kurl.cpp30
1 files changed, 16 insertions, 14 deletions
diff --git a/microkde/kurl.cpp b/microkde/kurl.cpp
index 2574e25..122ad71 100644
--- a/microkde/kurl.cpp
+++ b/microkde/kurl.cpp
@@ -1,1043 +1,1045 @@
1/* 1/*
2 Copyright (C) 1999 Torben Weis <weis@kde.org> 2 Copyright (C) 1999 Torben Weis <weis@kde.org>
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public 5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either 6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version. 7 version 2 of the License, or (at your option) any later version.
8 8
9 This library is distributed in the hope that it will be useful, 9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details. 12 Library General Public License for more details.
13 13
14 You should have received a copy of the GNU Library General Public License 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 15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. 17 Boston, MA 02111-1307, USA.
18*/ 18*/
19 19
20#include "kurl.h" 20#include "kurl.h"
21 21
22#ifndef KDE_QT_ONLY 22#ifndef KDE_QT_ONLY
23#include <kdebug.h> 23#include <kdebug.h>
24#include <kglobal.h> 24#include <kglobal.h>
25//US#include <kidna.h> 25//US#include <kidna.h>
26#endif 26#endif
27 27
28#include <stdio.h> 28#include <stdio.h>
29#include <assert.h> 29#include <assert.h>
30#include <ctype.h> 30#include <ctype.h>
31#include <stdlib.h> 31#include <stdlib.h>
32#ifdef _WIN32_ 32#ifdef _WIN32_
33 33
34#else 34#else
35#include <unistd.h> 35#include <unistd.h>
36#endif 36#endif
37#include <qurl.h> 37#include <q3url.h>
38#include <qdir.h> 38#include <qdir.h>
39#include <qstringlist.h> 39#include <qstringlist.h>
40#include <qregexp.h> 40#include <qregexp.h>
41//US#include <qstylesheet.h> 41//US#include <qstylesheet.h>
42#include <qmap.h> 42#include <qmap.h>
43#include <qtextcodec.h> 43#include <qtextcodec.h>
44//Added by qt3to4:
45#include <Q3CString>
44 46
45static const QString fileProt = "file"; 47static const QString fileProt = "file";
46 48
47static QTextCodec * codecForHint( int encoding_hint /* not 0 ! */ ) 49static QTextCodec * codecForHint( int encoding_hint /* not 0 ! */ )
48{ 50{
49 return QTextCodec::codecForMib( encoding_hint ); 51 return QTextCodec::codecForMib( encoding_hint );
50} 52}
51 53
52static QString encode( const QString& segment, bool encode_slash, int encoding_hint ) 54static QString encode( const QString& segment, bool encode_slash, int encoding_hint )
53{ 55{
54 const char *encode_string; 56 const char *encode_string;
55 if (encode_slash) 57 if (encode_slash)
56 encode_string = "<>#@\"&%?={}|^~[]\'`\\:+/"; 58 encode_string = "<>#@\"&%?={}|^~[]\'`\\:+/";
57 else 59 else
58 encode_string = "<>#@\"&%?={}|^~[]\'`\\:+"; 60 encode_string = "<>#@\"&%?={}|^~[]\'`\\:+";
59 61
60 QCString local; 62 Q3CString local;
61 if (encoding_hint==0) 63 if (encoding_hint==0)
62 local = segment.local8Bit(); 64 local = segment.local8Bit();
63 else 65 else
64 { 66 {
65 QTextCodec * textCodec = codecForHint( encoding_hint ); 67 QTextCodec * textCodec = codecForHint( encoding_hint );
66 if (!textCodec) 68 if (!textCodec)
67 local = segment.local8Bit(); 69 local = segment.local8Bit();
68 else 70 else
69 local = textCodec->fromUnicode( segment ); 71 local = textCodec->fromUnicode( segment );
70 } 72 }
71 73
72 int old_length = local.length(); 74 int old_length = local.length();
73 75
74 if ( !old_length ) 76 if ( !old_length )
75 return segment.isNull() ? QString::null : QString(""); // differenciate null and empty 77 return segment.isNull() ? QString::null : QString(""); // differenciate null and empty
76 78
77 // a worst case approximation 79 // a worst case approximation
78 QChar *new_segment = new QChar[ old_length * 3 + 1 ]; 80 QChar *new_segment = new QChar[ old_length * 3 + 1 ];
79 int new_length = 0; 81 int new_length = 0;
80 82
81 for ( int i = 0; i < old_length; i++ ) 83 for ( int i = 0; i < old_length; i++ )
82 { 84 {
83 // 'unsave' and 'reserved' characters 85 // 'unsave' and 'reserved' characters
84 // according to RFC 1738, 86 // according to RFC 1738,
85 // 2.2. URL Character Encoding Issues (pp. 3-4) 87 // 2.2. URL Character Encoding Issues (pp. 3-4)
86 // WABA: Added non-ascii 88 // WABA: Added non-ascii
87 unsigned char character = local[i]; 89 unsigned char character = local[i];
88 if ( (character <= 32) || (character >= 127) || 90 if ( (character <= 32) || (character >= 127) ||
89 strchr(encode_string, character) ) 91 strchr(encode_string, character) )
90 { 92 {
91 new_segment[ new_length++ ] = '%'; 93 new_segment[ new_length++ ] = '%';
92 94
93 unsigned int c = character / 16; 95 unsigned int c = character / 16;
94 c += (c > 9) ? ('A' - 10) : '0'; 96 c += (c > 9) ? ('A' - 10) : '0';
95 new_segment[ new_length++ ] = c; 97 new_segment[ new_length++ ] = c;
96 98
97 c = character % 16; 99 c = character % 16;
98 c += (c > 9) ? ('A' - 10) : '0'; 100 c += (c > 9) ? ('A' - 10) : '0';
99 new_segment[ new_length++ ] = c; 101 new_segment[ new_length++ ] = c;
100 102
101 } 103 }
102 else 104 else
103 new_segment[ new_length++ ] = local[i]; 105 new_segment[ new_length++ ] = character;
104 } 106 }
105 107
106 QString result = QString(new_segment, new_length); 108 QString result = QString(new_segment, new_length);
107 delete [] new_segment; 109 delete [] new_segment;
108 return result; 110 return result;
109} 111}
110 112
111static QString encodeHost( const QString& segment, bool encode_slash, int encoding_hint ) 113static QString encodeHost( const QString& segment, bool encode_slash, int encoding_hint )
112{ 114{
113 // Hostnames are encoded differently 115 // Hostnames are encoded differently
114 // we use the IDNA transformation instead 116 // we use the IDNA transformation instead
115 117
116 // Note: when merging qt-addon, use QResolver::domainToAscii here 118 // Note: when merging qt-addon, use QResolver::domainToAscii here
117#ifndef KDE_QT_ONLY 119#ifndef KDE_QT_ONLY
118 Q_UNUSED( encode_slash ); 120 Q_UNUSED( encode_slash );
119 Q_UNUSED( encoding_hint ); 121 Q_UNUSED( encoding_hint );
120 return KIDNA::toAscii(segment); 122 return KIDNA::toAscii(segment);
121#else 123#else
122 return encode(segment, encode_slash, encoding_hint); 124 return encode(segment, encode_slash, encoding_hint);
123#endif 125#endif
124} 126}
125 127
126static int hex2int( unsigned int _char ) 128static int hex2int( unsigned int _char )
127{ 129{
128 if ( _char >= 'A' && _char <='F') 130 if ( _char >= 'A' && _char <='F')
129 return _char - 'A' + 10; 131 return _char - 'A' + 10;
130 if ( _char >= 'a' && _char <='f') 132 if ( _char >= 'a' && _char <='f')
131 return _char - 'a' + 10; 133 return _char - 'a' + 10;
132 if ( _char >= '0' && _char <='9') 134 if ( _char >= '0' && _char <='9')
133 return _char - '0'; 135 return _char - '0';
134 return -1; 136 return -1;
135} 137}
136 138
137// WABA: The result of lazy_encode isn't usable for a URL which 139// WABA: The result of lazy_encode isn't usable for a URL which
138// needs to satisfies RFC requirements. However, the following 140// needs to satisfies RFC requirements. However, the following
139// operation will make it usable again: 141// operation will make it usable again:
140// encode(decode(...)) 142// encode(decode(...))
141// 143//
142// As a result one can see that url.prettyURL() does not result in 144// As a result one can see that url.prettyURL() does not result in
143// a RFC compliant URL but that the following sequence does: 145// a RFC compliant URL but that the following sequence does:
144// KURL(url.prettyURL()).url() 146// KURL(url.prettyURL()).url()
145 147
146 148
147static QString lazy_encode( const QString& segment ) 149static QString lazy_encode( const QString& segment )
148{ 150{
149 int old_length = segment.length(); 151 int old_length = segment.length();
150 152
151 if ( !old_length ) 153 if ( !old_length )
152 return QString::null; 154 return QString::null;
153 155
154 // a worst case approximation 156 // a worst case approximation
155 QChar *new_segment = new QChar[ old_length * 3 + 1 ]; 157 QChar *new_segment = new QChar[ old_length * 3 + 1 ];
156 int new_length = 0; 158 int new_length = 0;
157 159
158 for ( int i = 0; i < old_length; i++ ) 160 for ( int i = 0; i < old_length; i++ )
159 { 161 {
160 unsigned int character = segment[i].unicode(); // Don't use latin1() 162 unsigned int character = segment[i].unicode(); // Don't use latin1()
161 // It returns 0 for non-latin1 values 163 // It returns 0 for non-latin1 values
162 // Small set of really ambiguous chars 164 // Small set of really ambiguous chars
163 if ((character < 32) || // Low ASCII 165 if ((character < 32) || // Low ASCII
164 ((character == '%') && // The escape character itself 166 ((character == '%') && // The escape character itself
165 (i+2 < old_length) && // But only if part of a valid escape sequence! 167 (i+2 < old_length) && // But only if part of a valid escape sequence!
166 (hex2int(segment[i+1].unicode())!= -1) && 168 (hex2int(segment[i+1].unicode())!= -1) &&
167 (hex2int(segment[i+2].unicode())!= -1)) || 169 (hex2int(segment[i+2].unicode())!= -1)) ||
168 (character == '?') || // Start of query delimiter 170 (character == '?') || // Start of query delimiter
169 (character == '@') || // Username delimiter 171 (character == '@') || // Username delimiter
170 (character == '#') || // Start of reference delimiter 172 (character == '#') || // Start of reference delimiter
171 ((character == 32) && (i+1 == old_length))) // A trailing space 173 ((character == 32) && (i+1 == old_length))) // A trailing space
172 { 174 {
173 new_segment[ new_length++ ] = '%'; 175 new_segment[ new_length++ ] = '%';
174 176
175 unsigned int c = character / 16; 177 unsigned int c = character / 16;
176 c += (c > 9) ? ('A' - 10) : '0'; 178 c += (c > 9) ? ('A' - 10) : '0';
177 new_segment[ new_length++ ] = c; 179 new_segment[ new_length++ ] = c;
178 180
179 c = character % 16; 181 c = character % 16;
180 c += (c > 9) ? ('A' - 10) : '0'; 182 c += (c > 9) ? ('A' - 10) : '0';
181 new_segment[ new_length++ ] = c; 183 new_segment[ new_length++ ] = c;
182 } 184 }
183 else 185 else
184 new_segment[ new_length++ ] = segment[i]; 186 new_segment[ new_length++ ] = segment[i];
185 } 187 }
186 188
187 QString result = QString(new_segment, new_length); 189 QString result = QString(new_segment, new_length);
188 delete [] new_segment; 190 delete [] new_segment;
189 return result; 191 return result;
190} 192}
191 193
192static void decode( const QString& segment, QString &decoded, QString &encoded, int encoding_hint=0, bool updateDecoded = true ) 194static void decode( const QString& segment, QString &decoded, QString &encoded, int encoding_hint=0, bool updateDecoded = true )
193{ 195{
194 decoded = QString::null; 196 decoded = QString::null;
195 encoded = segment; 197 encoded = segment;
196 198
197 int old_length = segment.length(); 199 int old_length = segment.length();
198 if ( !old_length ) 200 if ( !old_length )
199 return; 201 return;
200 202
201 QTextCodec *textCodec = 0; 203 QTextCodec *textCodec = 0;
202 if (encoding_hint) 204 if (encoding_hint)
203 textCodec = codecForHint( encoding_hint ); 205 textCodec = codecForHint( encoding_hint );
204 206
205 if (!textCodec) 207 if (!textCodec)
206 textCodec = QTextCodec::codecForLocale(); 208 textCodec = QTextCodec::codecForLocale();
207 209
208 QCString csegment = textCodec->fromUnicode(segment); 210 Q3CString csegment = textCodec->fromUnicode(segment);
209 // Check if everything went ok 211 // Check if everything went ok
210 if (textCodec->toUnicode(csegment) != segment) 212 if (textCodec->toUnicode(csegment) != segment)
211 { 213 {
212 // Uh oh 214 // Uh oh
213 textCodec = codecForHint( 106 ); // Fall back to utf-8 215 textCodec = codecForHint( 106 ); // Fall back to utf-8
214 csegment = textCodec->fromUnicode(segment); 216 csegment = textCodec->fromUnicode(segment);
215 } 217 }
216 old_length = csegment.length(); 218 old_length = csegment.length();
217 219
218 int new_length = 0; 220 int new_length = 0;
219 int new_length2 = 0; 221 int new_length2 = 0;
220 222
221 // make a copy of the old one 223 // make a copy of the old one
222 char *new_segment = new char[ old_length + 1 ]; 224 char *new_segment = new char[ old_length + 1 ];
223 QChar *new_usegment = new QChar[ old_length * 3 + 1 ]; 225 QChar *new_usegment = new QChar[ old_length * 3 + 1 ];
224 226
225 int i = 0; 227 int i = 0;
226 while( i < old_length ) 228 while( i < old_length )
227 { 229 {
228 bool bReencode = false; 230 bool bReencode = false;
229 unsigned char character = csegment[ i++ ]; 231 unsigned char character = csegment[ i++ ];
230 if ((character <= ' ') || (character > 127)) 232 if ((character <= ' ') || (character > 127))
231 bReencode = true; 233 bReencode = true;
232 234
233 new_usegment [ new_length2++ ] = character; 235 new_usegment [ new_length2++ ] = character;
234 if (character == '%' ) 236 if (character == '%' )
235 { 237 {
236 int a = i+1 < old_length ? hex2int( csegment[i] ) : -1; 238 int a = i+1 < old_length ? hex2int( csegment[i] ) : -1;
237 int b = i+1 < old_length ? hex2int( csegment[i+1] ) : -1; 239 int b = i+1 < old_length ? hex2int( csegment[i+1] ) : -1;
238 if ((a == -1) || (b == -1)) // Only replace if sequence is valid 240 if ((a == -1) || (b == -1)) // Only replace if sequence is valid
239 { 241 {
240 // Contains stray %, make sure to re-encode! 242 // Contains stray %, make sure to re-encode!
241 bReencode = true; 243 bReencode = true;
242 } 244 }
243 else 245 else
244 { 246 {
245 // Valid %xx sequence 247 // Valid %xx sequence
246 character = a * 16 + b; // Replace with value of %dd 248 character = a * 16 + b; // Replace with value of %dd
247 if (!character && updateDecoded) 249 if (!character && updateDecoded)
248 break; // Stop at %00 250 break; // Stop at %00
249 251
250 new_usegment [ new_length2++ ] = (unsigned char) csegment[i++]; 252 new_usegment [ new_length2++ ] = (unsigned char) csegment[i++];
251 new_usegment [ new_length2++ ] = (unsigned char) csegment[i++]; 253 new_usegment [ new_length2++ ] = (unsigned char) csegment[i++];
252 } 254 }
253 } 255 }
254 if (bReencode) 256 if (bReencode)
255 { 257 {
256 new_length2--; 258 new_length2--;
257 new_usegment [ new_length2++ ] = '%'; 259 new_usegment [ new_length2++ ] = '%';
258 260
259 unsigned int c = character / 16; 261 unsigned int c = character / 16;
260 c += (c > 9) ? ('A' - 10) : '0'; 262 c += (c > 9) ? ('A' - 10) : '0';
261 new_usegment[ new_length2++ ] = c; 263 new_usegment[ new_length2++ ] = c;
262 264
263 c = character % 16; 265 c = character % 16;
264 c += (c > 9) ? ('A' - 10) : '0'; 266 c += (c > 9) ? ('A' - 10) : '0';
265 new_usegment[ new_length2++ ] = c; 267 new_usegment[ new_length2++ ] = c;
266 } 268 }
267 269
268 new_segment [ new_length++ ] = character; 270 new_segment [ new_length++ ] = character;
269 } 271 }
270 new_segment [ new_length ] = 0; 272 new_segment [ new_length ] = 0;
271 273
272 encoded = QString( new_usegment, new_length2); 274 encoded = QString( new_usegment, new_length2);
273 275
274 // Encoding specified 276 // Encoding specified
275 if (updateDecoded) 277 if (updateDecoded)
276 { 278 {
277 QByteArray array; 279 QByteArray array;
278 array.setRawData(new_segment, new_length); 280 array.setRawData(new_segment, new_length);
279 decoded = textCodec->toUnicode( array, new_length ); 281 decoded = textCodec->toUnicode( array, new_length );
280 array.resetRawData(new_segment, new_length); 282 array.resetRawData(new_segment, new_length);
281 QCString validate = textCodec->fromUnicode(decoded); 283 Q3CString validate = textCodec->fromUnicode(decoded);
282 284
283 if (strcmp(validate.data(), new_segment) != 0) 285 if (strcmp(validate.data(), new_segment) != 0)
284 { 286 {
285 decoded = QString::fromLocal8Bit(new_segment, new_length); 287 decoded = QString::fromLocal8Bit(new_segment, new_length);
286 } 288 }
287 } 289 }
288 290
289 delete [] new_segment; 291 delete [] new_segment;
290 delete [] new_usegment; 292 delete [] new_usegment;
291} 293}
292 294
293static QString decode(const QString &segment, int encoding_hint = 0) 295static QString decode(const QString &segment, int encoding_hint = 0)
294{ 296{
295 QString result; 297 QString result;
296 QString tmp; 298 QString tmp;
297 decode(segment, result, tmp, encoding_hint); 299 decode(segment, result, tmp, encoding_hint);
298 return result; 300 return result;
299} 301}
300 302
301static QString cleanpath(const QString &path, bool cleanDirSeparator=true) 303static QString cleanpath(const QString &path, bool cleanDirSeparator=true)
302{ 304{
303 if (path.isEmpty()) return QString::null; 305 if (path.isEmpty()) return QString::null;
304 int len = path.length(); 306 int len = path.length();
305 bool slash = (len && path[len-1] == '/') || 307 bool slash = (len && path[len-1] == '/') ||
306 (len > 1 && path[len-2] == '/' && path[len-1] == '.'); 308 (len > 1 && path[len-2] == '/' && path[len-1] == '.');
307 309
308 // The following code cleans up directory path much like 310 // The following code cleans up directory path much like
309 // QDir::cleanDirPath() except it can be made to ignore multiple 311 // QDir::cleanDirPath() except it can be made to ignore multiple
310 // directory separators by setting the flag to false. That fixes 312 // directory separators by setting the flag to false. That fixes
311 // bug# 15044, mail.altavista.com and other similar brain-dead server 313 // bug# 15044, mail.altavista.com and other similar brain-dead server
312 // implementations that do not follow what has been specified in 314 // implementations that do not follow what has been specified in
313 // RFC 2396!! (dA) 315 // RFC 2396!! (dA)
314 QString result; 316 QString result;
315 int cdUp, orig_pos, pos; 317 int cdUp, orig_pos, pos;
316 318
317 cdUp = 0; 319 cdUp = 0;
318 pos = orig_pos = len; 320 pos = orig_pos = len;
319 while ( pos && (pos = path.findRev('/',--pos)) != -1 ) 321 while ( pos && (pos = path.findRev('/',--pos)) != -1 )
320 { 322 {
321 len = orig_pos - pos - 1; 323 len = orig_pos - pos - 1;
322 if ( len == 2 && path[pos+1] == '.' && path[pos+2] == '.' ) 324 if ( len == 2 && path[pos+1] == '.' && path[pos+2] == '.' )
323 cdUp++; 325 cdUp++;
324 else 326 else
325 { 327 {
326 // Ignore any occurances of '.' 328 // Ignore any occurances of '.'
327 // This includes entries that simply do not make sense like /..../ 329 // This includes entries that simply do not make sense like /..../
328 if ( (len || !cleanDirSeparator) && 330 if ( (len || !cleanDirSeparator) &&
329 (len != 1 || path[pos+1] != '.' ) ) 331 (len != 1 || path[pos+1] != '.' ) )
330 { 332 {
331 if ( !cdUp ) 333 if ( !cdUp )
332 result.prepend(path.mid(pos, len+1)); 334 result.prepend(path.mid(pos, len+1));
333 else 335 else
334 cdUp--; 336 cdUp--;
335 } 337 }
336 } 338 }
337 orig_pos = pos; 339 orig_pos = pos;
338 } 340 }
339 341
340 if ( result.isEmpty() ) 342 if ( result.isEmpty() )
341 result = "/"; 343 result = "/";
342 else if ( slash && result.at(result.length()-1) != '/' ) 344 else if ( slash && result.at(result.length()-1) != '/' )
343 result.append('/'); 345 result.append('/');
344 346
345 return result; 347 return result;
346} 348}
347 349
348bool KURL::isRelativeURL(const QString &_url) 350bool KURL::isRelativeURL(const QString &_url)
349{ 351{
350 int len = _url.length(); 352 int len = _url.length();
351 if (!len) return true; // Very short relative URL. 353 if (!len) return true; // Very short relative URL.
352 const QChar *str = _url.unicode(); 354 const QChar *str = _url.unicode();
353 355
354 // Absolute URL must start with alpha-character 356 // Absolute URL must start with alpha-character
355 if (!isalpha(str[0].latin1())) 357 if (!isalpha(str[0].latin1()))
356 return true; // Relative URL 358 return true; // Relative URL
357 359
358 for(int i = 1; i < len; i++) 360 for(int i = 1; i < len; i++)
359 { 361 {
360 char c = str[i].latin1(); // Note: non-latin1 chars return 0! 362 char c = str[i].latin1(); // Note: non-latin1 chars return 0!
361 if (c == ':') 363 if (c == ':')
362 return false; // Absolute URL 364 return false; // Absolute URL
363 365
364 // Protocol part may only contain alpha, digit, + or - 366 // Protocol part may only contain alpha, digit, + or -
365 if (!isalpha(c) && !isdigit(c) && (c != '+') && (c != '-')) 367 if (!isalpha(c) && !isdigit(c) && (c != '+') && (c != '-'))
366 return true; // Relative URL 368 return true; // Relative URL
367 } 369 }
368 // URL did not contain ':' 370 // URL did not contain ':'
369 return true; // Relative URL 371 return true; // Relative URL
370} 372}
371 373
372KURL::List::List(const KURL &url) 374KURL::List::List(const KURL &url)
373{ 375{
374 append( url ); 376 append( url );
375} 377}
376 378
377KURL::List::List(const QStringList &list) 379KURL::List::List(const QStringList &list)
378{ 380{
379 for (QStringList::ConstIterator it = list.begin(); 381 for (QStringList::ConstIterator it = list.begin();
380 it != list.end(); 382 it != list.end();
381 it++) 383 it++)
382 { 384 {
383 append( KURL(*it) ); 385 append( KURL(*it) );
384 } 386 }
385} 387}
386 388
387QStringList KURL::List::toStringList() const 389QStringList KURL::List::toStringList() const
388{ 390{
389 QStringList lst; 391 QStringList lst;
390 for( KURL::List::ConstIterator it = begin(); 392 for( KURL::List::ConstIterator it = begin();
391 it != end(); 393 it != end();
392 it++) 394 it++)
393 { 395 {
394 lst.append( (*it).url() ); 396 lst.append( (*it).url() );
395 } 397 }
396 return lst; 398 return lst;
397} 399}
398 400
399 401
400KURL::KURL() 402KURL::KURL()
401{ 403{
402 reset(); 404 reset();
403} 405}
404 406
405KURL::~KURL() 407KURL::~KURL()
406{ 408{
407} 409}
408 410
409 411
410KURL::KURL( const QString &url, int encoding_hint ) 412KURL::KURL( const QString &url, int encoding_hint )
411{ 413{
412 reset(); 414 reset();
413 parse( url, encoding_hint ); 415 parse( url, encoding_hint );
414} 416}
415 417
416KURL::KURL( const char * url, int encoding_hint ) 418KURL::KURL( const char * url, int encoding_hint )
417{ 419{
418 reset(); 420 reset();
419 parse( QString::fromLatin1(url), encoding_hint ); 421 parse( QString::fromLatin1(url), encoding_hint );
420} 422}
421 423
422KURL::KURL( const QCString& url, int encoding_hint ) 424KURL::KURL( const Q3CString& url, int encoding_hint )
423{ 425{
424 reset(); 426 reset();
425 parse( QString::fromLatin1(url), encoding_hint ); 427 parse( QString::fromLatin1(url), encoding_hint );
426} 428}
427 429
428KURL::KURL( const KURL& _u ) 430KURL::KURL( const KURL& _u )
429{ 431{
430 *this = _u; 432 *this = _u;
431} 433}
432 434
433QDataStream & operator<< (QDataStream & s, const KURL & a) 435QDataStream & operator<< (QDataStream & s, const KURL & a)
434{ 436{
435 QString QueryForWire=a.m_strQuery_encoded; 437 QString QueryForWire=a.m_strQuery_encoded;
436 if (!a.m_strQuery_encoded.isNull()) 438 if (!a.m_strQuery_encoded.isNull())
437 QueryForWire.prepend("?"); 439 QueryForWire.prepend("?");
438 440
439 s << a.m_strProtocol << a.m_strUser << a.m_strPass << a.m_strHost 441 s << a.m_strProtocol << a.m_strUser << a.m_strPass << a.m_strHost
440 << a.m_strPath << a.m_strPath_encoded << QueryForWire << a.m_strRef_encoded 442 << a.m_strPath << a.m_strPath_encoded << QueryForWire << a.m_strRef_encoded
441 << Q_INT8(a.m_bIsMalformed ? 1 : 0) << a.m_iPort; 443 << Q_INT8(a.m_bIsMalformed ? 1 : 0) << a.m_iPort;
442 return s; 444 return s;
443} 445}
444 446
445QDataStream & operator>> (QDataStream & s, KURL & a) 447QDataStream & operator>> (QDataStream & s, KURL & a)
446{ 448{
447 Q_INT8 malf; 449 Q_INT8 malf;
448 QString QueryFromWire; 450 QString QueryFromWire;
449 s >> a.m_strProtocol >> a.m_strUser >> a.m_strPass >> a.m_strHost 451 s >> a.m_strProtocol >> a.m_strUser >> a.m_strPass >> a.m_strHost
450 >> a.m_strPath >> a.m_strPath_encoded >> QueryFromWire >> a.m_strRef_encoded 452 >> a.m_strPath >> a.m_strPath_encoded >> QueryFromWire >> a.m_strRef_encoded
451 >> malf >> a.m_iPort; 453 >> malf >> a.m_iPort;
452 a.m_bIsMalformed = (malf != 0); 454 a.m_bIsMalformed = (malf != 0);
453 455
454 if ( QueryFromWire.isEmpty() ) 456 if ( QueryFromWire.isEmpty() )
455 a.m_strQuery_encoded = QString::null; 457 a.m_strQuery_encoded = QString::null;
456 else 458 else
457 a.m_strQuery_encoded = QueryFromWire.mid(1); 459 a.m_strQuery_encoded = QueryFromWire.mid(1);
458 460
459 return s; 461 return s;
460} 462}
461 463
462#ifndef QT_NO_NETWORKPROTOCOL 464#ifndef QT_NO_NETWORKPROTOCOL
463KURL::KURL( const QUrl &u ) 465KURL::KURL( const Q3Url &u )
464{ 466{
465 *this = u; 467 *this = u;
466} 468}
467#endif 469#endif
468 470
469KURL::KURL( const KURL& _u, const QString& _rel_url, int encoding_hint ) 471KURL::KURL( const KURL& _u, const QString& _rel_url, int encoding_hint )
470{ 472{
471 // WORKAROUND THE RFC 1606 LOOPHOLE THAT ALLOWS 473 // WORKAROUND THE RFC 1606 LOOPHOLE THAT ALLOWS
472 // http:/index.html AS A VALID SYNTAX FOR RELATIVE 474 // http:/index.html AS A VALID SYNTAX FOR RELATIVE
473 // URLS. ( RFC 2396 section 5.2 item # 3 ) 475 // URLS. ( RFC 2396 section 5.2 item # 3 )
474 QString rUrl = _rel_url; 476 QString rUrl = _rel_url;
475 int len = _u.m_strProtocol.length(); 477 int len = _u.m_strProtocol.length();
476 if ( !_u.m_strHost.isEmpty() && !rUrl.isEmpty() && 478 if ( !_u.m_strHost.isEmpty() && !rUrl.isEmpty() &&
477 rUrl.find( _u.m_strProtocol, 0, false ) == 0 && 479 rUrl.find( _u.m_strProtocol, 0, false ) == 0 &&
478 rUrl[len] == ':' && (rUrl[len+1] != '/' || 480 rUrl[len] == ':' && (rUrl[len+1] != '/' ||
479 (rUrl[len+1] == '/' && rUrl[len+2] != '/')) ) 481 (rUrl[len+1] == '/' && rUrl[len+2] != '/')) )
480 { 482 {
481 rUrl.remove( 0, rUrl.find( ':' ) + 1 ); 483 rUrl.remove( 0, rUrl.find( ':' ) + 1 );
482 } 484 }
483 485
484 if ( rUrl.isEmpty() ) 486 if ( rUrl.isEmpty() )
485 { 487 {
486 *this = _u; 488 *this = _u;
487 } 489 }
488 else if ( rUrl[0] == '#' ) 490 else if ( rUrl[0] == '#' )
489 { 491 {
490 *this = _u; 492 *this = _u;
491 QString ref = decode(rUrl.mid(1), encoding_hint); 493 QString ref = decode(rUrl.mid(1), encoding_hint);
492 if ( ref.isNull() ) 494 if ( ref.isNull() )
493 ref = ""; // we know there was an (empty) html ref, we saw the '#' 495 ref = ""; // we know there was an (empty) html ref, we saw the '#'
494 setHTMLRef( ref ); 496 setHTMLRef( ref );
495 } 497 }
496 else if ( isRelativeURL( rUrl) ) 498 else if ( isRelativeURL( rUrl) )
497 { 499 {
498 *this = _u; 500 *this = _u;
499 m_strQuery_encoded = QString::null; 501 m_strQuery_encoded = QString::null;
500 m_strRef_encoded = QString::null; 502 m_strRef_encoded = QString::null;
501 if ( rUrl[0] == '/') 503 if ( rUrl[0] == '/')
502 { 504 {
503 if ((rUrl.length() > 1) && (rUrl[1] == '/')) 505 if ((rUrl.length() > 1) && (rUrl[1] == '/'))
504 { 506 {
505 m_strHost = QString::null; 507 m_strHost = QString::null;
506 } 508 }
507 m_strPath = QString::null; 509 m_strPath = QString::null;
508 m_strPath_encoded = QString::null; 510 m_strPath_encoded = QString::null;
509 } 511 }
510 else if ( rUrl[0] != '?' ) 512 else if ( rUrl[0] != '?' )
511 { 513 {
512 int pos = m_strPath.findRev( '/' ); 514 int pos = m_strPath.findRev( '/' );
513 if (pos >= 0) 515 if (pos >= 0)
514 m_strPath.truncate(pos); 516 m_strPath.truncate(pos);
515 m_strPath += '/'; 517 m_strPath += '/';
516 if (!m_strPath_encoded.isEmpty()) 518 if (!m_strPath_encoded.isEmpty())
517 { 519 {
518 pos = m_strPath_encoded.findRev( '/' ); 520 pos = m_strPath_encoded.findRev( '/' );
519 if (pos >= 0) 521 if (pos >= 0)
520 m_strPath_encoded.truncate(pos); 522 m_strPath_encoded.truncate(pos);
521 m_strPath_encoded += '/'; 523 m_strPath_encoded += '/';
522 } 524 }
523 } 525 }
524 else 526 else
525 { 527 {
526 if ( m_strPath.isEmpty() ) 528 if ( m_strPath.isEmpty() )
527 m_strPath = '/'; 529 m_strPath = '/';
528 } 530 }
529 KURL tmp( url() + rUrl, encoding_hint); 531 KURL tmp( url() + rUrl, encoding_hint);
530 *this = tmp; 532 *this = tmp;
531 cleanPath(false); 533 cleanPath(false);
532 } 534 }
533 else 535 else
534 { 536 {
535 KURL tmp( rUrl, encoding_hint); 537 KURL tmp( rUrl, encoding_hint);
536 *this = tmp; 538 *this = tmp;
537 // Preserve userinfo if applicable. 539 // Preserve userinfo if applicable.
538 if (!_u.m_strUser.isEmpty() && m_strUser.isEmpty() && (_u.m_strHost == m_strHost) && (_u.m_strProtocol == m_strProtocol)) 540 if (!_u.m_strUser.isEmpty() && m_strUser.isEmpty() && (_u.m_strHost == m_strHost) && (_u.m_strProtocol == m_strProtocol))
539 { 541 {
540 m_strUser = _u.m_strUser; 542 m_strUser = _u.m_strUser;
541 m_strPass = _u.m_strPass; 543 m_strPass = _u.m_strPass;
542 } 544 }
543 } 545 }
544} 546}
545 547
546void KURL::reset() 548void KURL::reset()
547{ 549{
548 m_strProtocol = QString::null; 550 m_strProtocol = QString::null;
549 m_strUser = QString::null; 551 m_strUser = QString::null;
550 m_strPass = QString::null; 552 m_strPass = QString::null;
551 m_strHost = QString::null; 553 m_strHost = QString::null;
552 m_strPath = QString::null; 554 m_strPath = QString::null;
553 m_strPath_encoded = QString::null; 555 m_strPath_encoded = QString::null;
554 m_strQuery_encoded = QString::null; 556 m_strQuery_encoded = QString::null;
555 m_strRef_encoded = QString::null; 557 m_strRef_encoded = QString::null;
556 m_bIsMalformed = true; 558 m_bIsMalformed = true;
557 m_iPort = 0; 559 m_iPort = 0;
558} 560}
559 561
560bool KURL::isEmpty() const 562bool KURL::isEmpty() const
561{ 563{
562 return (m_strPath.isEmpty() && m_strProtocol.isEmpty()); 564 return (m_strPath.isEmpty() && m_strProtocol.isEmpty());
563} 565}
564 566
565void KURL::parse( const QString& _url, int encoding_hint ) 567void KURL::parse( const QString& _url, int encoding_hint )
566{ 568{
567 //kdDebug(126) << "parse " << _url << endl; 569 //kdDebug(126) << "parse " << _url << endl;
568 // Return immediately whenever the given url 570 // Return immediately whenever the given url
569 // is empty or null. 571 // is empty or null.
570 if ( _url.isEmpty() ) 572 if ( _url.isEmpty() )
571 { 573 {
572 m_strProtocol = _url; 574 m_strProtocol = _url;
573 return; 575 return;
574 } 576 }
575 577
576 QString port; 578 QString port;
577 bool badHostName = false; 579 bool badHostName = false;
578 int start = 0; 580 int start = 0;
579 uint len = _url.length(); 581 uint len = _url.length();
580 const QChar* buf = _url.unicode(); 582 const QChar* buf = _url.unicode();
581 const QChar* orig = buf; 583 const QChar* orig = buf;
582 584
583 QChar delim; 585 QChar delim;
584 QString tmp; 586 QString tmp;
585 587
586 uint pos = 0; 588 uint pos = 0;
587 589
588 // Node 1: Accept alpha or slash 590 // Node 1: Accept alpha or slash
589 QChar x = buf[pos++]; 591 QChar x = buf[pos++];
590 if ( x == '/' ) 592 if ( x == '/' )
591 goto Node9; 593 goto Node9;
592 if ( !isalpha( (int)x ) ) 594 if ( !x.isLetter() )
593 goto NodeErr; 595 goto NodeErr;
594 596
595 // Node 2: Accept any amount of (alpha|digit|'+'|'-') 597 // Node 2: Accept any amount of (alpha|digit|'+'|'-')
596 // '.' is not currently accepted, because current KURL may be confused. 598 // '.' is not currently accepted, because current KURL may be confused.
597 // Proceed with :// :/ or : 599 // Proceed with :// :/ or :
598 while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) || 600 while( pos < len && ( buf[pos].isLetter() || buf[pos].isDigit() ||
599 buf[pos] == '+' || buf[pos] == '-')) pos++; 601 buf[pos] == '+' || buf[pos] == '-')) pos++;
600 602
601 if ( pos+2 < len && buf[pos] == ':' && buf[pos+1] == '/' && buf[pos+2] == '/' ) 603 if ( pos+2 < len && buf[pos] == ':' && buf[pos+1] == '/' && buf[pos+2] == '/' )
602 { 604 {
603 m_strProtocol = QString( orig, pos ).lower(); 605 m_strProtocol = QString( orig, pos ).lower();
604 pos += 3; 606 pos += 3;
605 } 607 }
606 else if (pos+1 < len && buf[pos] == ':' ) // Need to always compare length()-1 otherwise KURL passes "http:" as legal!! 608 else if (pos+1 < len && buf[pos] == ':' ) // Need to always compare length()-1 otherwise KURL passes "http:" as legal!!
607 { 609 {
608 m_strProtocol = QString( orig, pos ).lower(); 610 m_strProtocol = QString( orig, pos ).lower();
609 //kdDebug(126)<<"setting protocol to "<<m_strProtocol<<endl; 611 //kdDebug(126)<<"setting protocol to "<<m_strProtocol<<endl;
610 pos++; 612 pos++;
611 start = pos; 613 start = pos;
612 goto Node9; 614 goto Node9;
613 } 615 }
614 else 616 else
615 goto NodeErr; 617 goto NodeErr;
616 618
617 //Node 3: We need at least one character here 619 //Node 3: We need at least one character here
618 if ( pos == len ) 620 if ( pos == len )
619 goto NodeErr; 621 goto NodeErr;
620 start = pos; 622 start = pos;
621 623
622 // Node 4: Accept any amount of characters. 624 // Node 4: Accept any amount of characters.
623 if (buf[pos] == '[') // An IPv6 host follows. 625 if (buf[pos] == '[') // An IPv6 host follows.
624 goto Node8; 626 goto Node8;
625 // Terminate on / or @ or ? or # or " or ; or < 627 // Terminate on / or @ or ? or # or " or ; or <
626 x = buf[pos]; 628 x = buf[pos];
627 while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') ) 629 while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') )
628 { 630 {
629 if ((x == '\"') || (x == ';') || (x == '<')) 631 if ((x == '\"') || (x == ';') || (x == '<'))
630 badHostName = true; 632 badHostName = true;
631 if (++pos == len) 633 if (++pos == len)
632 break; 634 break;
633 x = buf[pos]; 635 x = buf[pos];
634 } 636 }
635 if ( pos == len ) 637 if ( pos == len )
636 { 638 {
637 if (badHostName) 639 if (badHostName)
638 goto NodeErr; 640 goto NodeErr;
639 641
640 setHost(decode(QString( buf + start, pos - start ), encoding_hint)); 642 setHost(decode(QString( buf + start, pos - start ), encoding_hint));
641 goto NodeOk; 643 goto NodeOk;
642 } 644 }
643 if ( x == '@' ) 645 if ( x == '@' )
644 { 646 {
645 m_strUser = decode(QString( buf + start, pos - start ), encoding_hint); 647 m_strUser = decode(QString( buf + start, pos - start ), encoding_hint);
646 pos++; 648 pos++;
647 goto Node7; 649 goto Node7;
648 } 650 }
649 else if ( (x == '/') || (x == '?') || (x == '#')) 651 else if ( (x == '/') || (x == '?') || (x == '#'))
650 { 652 {
651 if (badHostName) 653 if (badHostName)
652 goto NodeErr; 654 goto NodeErr;
653 655
654 setHost(decode(QString( buf + start, pos - start ), encoding_hint)); 656 setHost(decode(QString( buf + start, pos - start ), encoding_hint));
655 start = pos; 657 start = pos;
656 goto Node9; 658 goto Node9;
657 } 659 }
658 else if ( x != ':' ) 660 else if ( x != ':' )
659 goto NodeErr; 661 goto NodeErr;
660 m_strUser = decode(QString( buf + start, pos - start ), encoding_hint); 662 m_strUser = decode(QString( buf + start, pos - start ), encoding_hint);
661 pos++; 663 pos++;
662 664
663 // Node 5: We need at least one character 665 // Node 5: We need at least one character
664 if ( pos == len ) 666 if ( pos == len )
665 goto NodeErr; 667 goto NodeErr;
666 start = pos++; 668 start = pos++;
667 669
668 // Node 6: Read everything until @, /, ? or # 670 // Node 6: Read everything until @, /, ? or #
669 while( (pos < len) && 671 while( (pos < len) &&
670 (buf[pos] != '@') && 672 (buf[pos] != '@') &&
671 (buf[pos] != '/') && 673 (buf[pos] != '/') &&
672 (buf[pos] != '?') && 674 (buf[pos] != '?') &&
673 (buf[pos] != '#')) pos++; 675 (buf[pos] != '#')) pos++;
674 // If we now have a '@' the ':' seperates user and password. 676 // If we now have a '@' the ':' seperates user and password.
675 // Otherwise it seperates host and port. 677 // Otherwise it seperates host and port.
676 if ( (pos == len) || (buf[pos] != '@') ) 678 if ( (pos == len) || (buf[pos] != '@') )
677 { 679 {
678 // Ok the : was used to separate host and port 680 // Ok the : was used to separate host and port
679 if (badHostName) 681 if (badHostName)
680 goto NodeErr; 682 goto NodeErr;
681 setHost(m_strUser); 683 setHost(m_strUser);
682 m_strUser = QString::null; 684 m_strUser = QString::null;
683 QString tmp( buf + start, pos - start ); 685 QString tmp( buf + start, pos - start );
684 char *endptr; 686 char *endptr;
685 m_iPort = (unsigned short int)strtol(tmp.ascii(), &endptr, 10); 687 m_iPort = (unsigned short int)strtol(tmp.ascii(), &endptr, 10);
686 if ((pos == len) && (strlen(endptr) == 0)) 688 if ((pos == len) && (strlen(endptr) == 0))
687 goto NodeOk; 689 goto NodeOk;
688 // there is more after the digits 690 // there is more after the digits
689 pos -= strlen(endptr); 691 pos -= strlen(endptr);
690 start = pos++; 692 start = pos++;
691 goto Node9; 693 goto Node9;
692 } 694 }
693 m_strPass = decode(QString( buf + start, pos - start), encoding_hint); 695 m_strPass = decode(QString( buf + start, pos - start), encoding_hint);
694 pos++; 696 pos++;
695 697
696 // Node 7: We need at least one character 698 // Node 7: We need at least one character
697 Node7: 699 Node7:
698 if ( pos == len ) 700 if ( pos == len )
699 goto NodeErr; 701 goto NodeErr;
700 702
701 Node8: 703 Node8:
702 if (buf[pos] == '[') 704 if (buf[pos] == '[')
703 { 705 {
704 // IPv6 address 706 // IPv6 address
705 start = ++pos; // Skip '[' 707 start = ++pos; // Skip '['
706 708
707 if (pos == len) 709 if (pos == len)
708 { 710 {
709 badHostName = true; 711 badHostName = true;
710 goto NodeErr; 712 goto NodeErr;
711 } 713 }
712 // Node 8b: Read everything until ] or terminate 714 // Node 8b: Read everything until ] or terminate
713 badHostName = false; 715 badHostName = false;
714 x = buf[pos]; 716 x = buf[pos];
715 while( (x != ']') ) 717 while( (x != ']') )
716 { 718 {
717 if ((x == '\"') || (x == ';') || (x == '<')) 719 if ((x == '\"') || (x == ';') || (x == '<'))
718 badHostName = true; 720 badHostName = true;
719 if (++pos == len) 721 if (++pos == len)
720 { 722 {
721 badHostName = true; 723 badHostName = true;
722 break; 724 break;
723 } 725 }
724 x = buf[pos]; 726 x = buf[pos];
725 } 727 }
726 if (badHostName) 728 if (badHostName)
727 goto NodeErr; 729 goto NodeErr;
728 setHost(decode(QString( buf + start, pos - start ), encoding_hint)); 730 setHost(decode(QString( buf + start, pos - start ), encoding_hint));
729 if (pos < len) pos++; // Skip ']' 731 if (pos < len) pos++; // Skip ']'
730 if (pos == len) 732 if (pos == len)
731 goto NodeOk; 733 goto NodeOk;
732 } 734 }
733 else 735 else
734 { 736 {
735 // Non IPv6 address 737 // Non IPv6 address
736 start = pos; 738 start = pos;
737 739
738 // Node 8b: Read everything until / : or terminate 740 // Node 8b: Read everything until / : or terminate
739 badHostName = false; 741 badHostName = false;
740 x = buf[pos]; 742 x = buf[pos];
741 while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') ) 743 while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') )
742 { 744 {
743 if ((x == '\"') || (x == ';') || (x == '<')) 745 if ((x == '\"') || (x == ';') || (x == '<'))
744 badHostName = true; 746 badHostName = true;
745 if (++pos == len) 747 if (++pos == len)
746 break; 748 break;
747 x = buf[pos]; 749 x = buf[pos];
748 } 750 }
749 if (badHostName) 751 if (badHostName)
750 goto NodeErr; 752 goto NodeErr;
751 if ( pos == len ) 753 if ( pos == len )
752 { 754 {
753 setHost(decode(QString( buf + start, pos - start ), encoding_hint)); 755 setHost(decode(QString( buf + start, pos - start ), encoding_hint));
754 goto NodeOk; 756 goto NodeOk;
755 } 757 }
756 setHost(decode(QString( buf + start, pos - start ), encoding_hint)); 758 setHost(decode(QString( buf + start, pos - start ), encoding_hint));
757 } 759 }
758 x = buf[pos]; 760 x = buf[pos];
759 if ( x == '/' ) 761 if ( x == '/' )
760 { 762 {
761 start = pos++; 763 start = pos++;
762 goto Node9; 764 goto Node9;
763 } 765 }
764 else if ( x != ':' ) 766 else if ( x != ':' )
765 goto NodeErr; 767 goto NodeErr;
766 pos++; 768 pos++;
767 769
768 // Node 8a: Accept at least one digit 770 // Node 8a: Accept at least one digit
769 if ( pos == len ) 771 if ( pos == len )
770 goto NodeErr; 772 goto NodeErr;
771 start = pos; 773 start = pos;
772 if ( !isdigit( buf[pos++] ) ) 774 if ( !buf[pos++].isDigit() )
773 goto NodeErr; 775 goto NodeErr;
774 776
775 // Node 8b: Accept any amount of digits 777 // Node 8b: Accept any amount of digits
776 while( pos < len && isdigit( buf[pos] ) ) pos++; 778 while( pos < len && buf[pos].isDigit() ) pos++;
777 port = QString( buf + start, pos - start ); 779 port = QString( buf + start, pos - start );
778 m_iPort = port.toUShort(); 780 m_iPort = port.toUShort();
779 if ( pos == len ) 781 if ( pos == len )
780 goto NodeOk; 782 goto NodeOk;
781 start = pos++; 783 start = pos++;
782 784
783 Node9: // parse path until query or reference reached 785 Node9: // parse path until query or reference reached
784 786
785 while( pos < len && buf[pos] != '#' && buf[pos]!='?' ) pos++; 787 while( pos < len && buf[pos] != '#' && buf[pos]!='?' ) pos++;
786 788
787 tmp = QString( buf + start, pos - start ); 789 tmp = QString( buf + start, pos - start );
788 //kdDebug(126)<<" setting encoded path&query to:"<<tmp<<endl; 790 //kdDebug(126)<<" setting encoded path&query to:"<<tmp<<endl;
789 setEncodedPath( tmp, encoding_hint ); 791 setEncodedPath( tmp, encoding_hint );
790 792
791 if ( pos == len ) 793 if ( pos == len )
792 goto NodeOk; 794 goto NodeOk;
793 795
794 //Node10: // parse query or reference depending on what comes first 796 //Node10: // parse query or reference depending on what comes first
795 delim = (buf[pos++]=='#'?'?':'#'); 797 delim = (buf[pos++]=='#'?'?':'#');
796 798
797 start = pos; 799 start = pos;
798 800
799 while(pos < len && buf[pos]!=delim ) pos++; 801 while(pos < len && buf[pos]!=delim ) pos++;
800 802
801 tmp = QString(buf + start, pos - start); 803 tmp = QString(buf + start, pos - start);
802 if (delim=='#') 804 if (delim=='#')
803 setQuery(tmp, encoding_hint); 805 setQuery(tmp, encoding_hint);
804 else 806 else
805 m_strRef_encoded = tmp; 807 m_strRef_encoded = tmp;
806 808
807 if (pos == len) 809 if (pos == len)
808 goto NodeOk; 810 goto NodeOk;
809 811
810 //Node11: // feed the rest into the remaining variable 812 //Node11: // feed the rest into the remaining variable
811 tmp = QString( buf + pos + 1, len - pos - 1); 813 tmp = QString( buf + pos + 1, len - pos - 1);
812 if (delim == '#') 814 if (delim == '#')
813 m_strRef_encoded = tmp; 815 m_strRef_encoded = tmp;
814 else 816 else
815 setQuery(tmp, encoding_hint); 817 setQuery(tmp, encoding_hint);
816 818
817 NodeOk: 819 NodeOk:
818 //kdDebug(126)<<"parsing finished. m_strProtocol="<<m_strProtocol<<" m_strHost="<<m_strHost<<" m_strPath="<<m_strPath<<endl; 820 //kdDebug(126)<<"parsing finished. m_strProtocol="<<m_strProtocol<<" m_strHost="<<m_strHost<<" m_strPath="<<m_strPath<<endl;
819 m_bIsMalformed = false; // Valid URL 821 m_bIsMalformed = false; // Valid URL
820 822
821 //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; 823 //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;
822 if (m_strProtocol.isEmpty()) 824 if (m_strProtocol.isEmpty())
823 { 825 {
824 m_strProtocol = fileProt; 826 m_strProtocol = fileProt;
825 } 827 }
826 return; 828 return;
827 829
828 NodeErr: 830 NodeErr:
829// kdDebug(126) << "KURL couldn't parse URL \"" << _url << "\"" << endl; 831// kdDebug(126) << "KURL couldn't parse URL \"" << _url << "\"" << endl;
830 reset(); 832 reset();
831 m_strProtocol = _url; 833 m_strProtocol = _url;
832} 834}
833 835
834KURL& KURL::operator=( const QString& _url ) 836KURL& KURL::operator=( const QString& _url )
835{ 837{
836 reset(); 838 reset();
837 parse( _url ); 839 parse( _url );
838 840
839 return *this; 841 return *this;
840} 842}
841 843
842KURL& KURL::operator=( const char * _url ) 844KURL& KURL::operator=( const char * _url )
843{ 845{
844 reset(); 846 reset();
845 parse( QString::fromLatin1(_url) ); 847 parse( QString::fromLatin1(_url) );
846 848
847 return *this; 849 return *this;
848} 850}
849 851
850#ifndef QT_NO_NETWORKPROTOCOL 852#ifndef QT_NO_NETWORKPROTOCOL
851KURL& KURL::operator=( const QUrl & u ) 853KURL& KURL::operator=( const Q3Url & u )
852{ 854{
853 m_strProtocol = u.protocol(); 855 m_strProtocol = u.protocol();
854 m_strUser = u.user(); 856 m_strUser = u.user();
855 m_strPass = u.password(); 857 m_strPass = u.password();
856 m_strHost = u.host(); 858 m_strHost = u.host();
857 m_strPath = u.path( FALSE ); 859 m_strPath = u.path( FALSE );
858 m_strPath_encoded = QString::null; 860 m_strPath_encoded = QString::null;
859 m_strQuery_encoded = u.query(); 861 m_strQuery_encoded = u.query();
860 m_strRef_encoded = u.ref(); 862 m_strRef_encoded = u.ref();
861 m_bIsMalformed = !u.isValid(); 863 m_bIsMalformed = !u.isValid();
862 m_iPort = u.port(); 864 m_iPort = u.port();
863 865
864 return *this; 866 return *this;
865} 867}
866#endif 868#endif
867 869
868KURL& KURL::operator=( const KURL& _u ) 870KURL& KURL::operator=( const KURL& _u )
869{ 871{
870 m_strProtocol = _u.m_strProtocol; 872 m_strProtocol = _u.m_strProtocol;
871 m_strUser = _u.m_strUser; 873 m_strUser = _u.m_strUser;
872 m_strPass = _u.m_strPass; 874 m_strPass = _u.m_strPass;
873 m_strHost = _u.m_strHost; 875 m_strHost = _u.m_strHost;
874 m_strPath = _u.m_strPath; 876 m_strPath = _u.m_strPath;
875 m_strPath_encoded = _u.m_strPath_encoded; 877 m_strPath_encoded = _u.m_strPath_encoded;
876 m_strQuery_encoded = _u.m_strQuery_encoded; 878 m_strQuery_encoded = _u.m_strQuery_encoded;
877 m_strRef_encoded = _u.m_strRef_encoded; 879 m_strRef_encoded = _u.m_strRef_encoded;
878 m_bIsMalformed = _u.m_bIsMalformed; 880 m_bIsMalformed = _u.m_bIsMalformed;
879 m_iPort = _u.m_iPort; 881 m_iPort = _u.m_iPort;
880 882
881 return *this; 883 return *this;
882} 884}
883 885
884bool KURL::operator==( const KURL& _u ) const 886bool KURL::operator==( const KURL& _u ) const
885{ 887{
886 if ( isMalformed() || _u.isMalformed() ) 888 if ( isMalformed() || _u.isMalformed() )
887 return false; 889 return false;
888 890
889 if ( m_strProtocol == _u.m_strProtocol && 891 if ( m_strProtocol == _u.m_strProtocol &&
890 m_strUser == _u.m_strUser && 892 m_strUser == _u.m_strUser &&
891 m_strPass == _u.m_strPass && 893 m_strPass == _u.m_strPass &&
892 m_strHost == _u.m_strHost && 894 m_strHost == _u.m_strHost &&
893 m_strPath == _u.m_strPath && 895 m_strPath == _u.m_strPath &&
894 // The encoded path may be null, but the URLs are still equal (David) 896 // The encoded path may be null, but the URLs are still equal (David)
895 ( m_strPath_encoded.isNull() || _u.m_strPath_encoded.isNull() || 897 ( m_strPath_encoded.isNull() || _u.m_strPath_encoded.isNull() ||
896 m_strPath_encoded == _u.m_strPath_encoded ) && 898 m_strPath_encoded == _u.m_strPath_encoded ) &&
897 m_strQuery_encoded == _u.m_strQuery_encoded && 899 m_strQuery_encoded == _u.m_strQuery_encoded &&
898 m_strRef_encoded == _u.m_strRef_encoded && 900 m_strRef_encoded == _u.m_strRef_encoded &&
899 m_iPort == _u.m_iPort ) 901 m_iPort == _u.m_iPort )
900 { 902 {
901 return true; 903 return true;
902 } 904 }
903 905
904 return false; 906 return false;
905} 907}
906 908
907bool KURL::operator==( const QString& _u ) const 909bool KURL::operator==( const QString& _u ) const
908{ 910{
909 KURL u( _u ); 911 KURL u( _u );
910 return ( *this == u ); 912 return ( *this == u );
911} 913}
912 914
913bool KURL::cmp( const KURL &u, bool ignore_trailing ) const 915bool KURL::cmp( const KURL &u, bool ignore_trailing ) const
914{ 916{
915 return equals( u, ignore_trailing ); 917 return equals( u, ignore_trailing );
916} 918}
917 919
918bool KURL::equals( const KURL &_u, bool ignore_trailing ) const 920bool KURL::equals( const KURL &_u, bool ignore_trailing ) const
919{ 921{
920 if ( isMalformed() || _u.isMalformed() ) 922 if ( isMalformed() || _u.isMalformed() )
921 return false; 923 return false;
922 924
923 if ( ignore_trailing ) 925 if ( ignore_trailing )
924 { 926 {
925 QString path1 = path(1); 927 QString path1 = path(1);
926 QString path2 = _u.path(1); 928 QString path2 = _u.path(1);
927 if ( path1 != path2 ) 929 if ( path1 != path2 )
928 return false; 930 return false;
929 931
930 if ( m_strProtocol == _u.m_strProtocol && 932 if ( m_strProtocol == _u.m_strProtocol &&
931 m_strUser == _u.m_strUser && 933 m_strUser == _u.m_strUser &&
932 m_strPass == _u.m_strPass && 934 m_strPass == _u.m_strPass &&
933 m_strHost == _u.m_strHost && 935 m_strHost == _u.m_strHost &&
934 m_strQuery_encoded == _u.m_strQuery_encoded && 936 m_strQuery_encoded == _u.m_strQuery_encoded &&
935 m_strRef_encoded == _u.m_strRef_encoded && 937 m_strRef_encoded == _u.m_strRef_encoded &&
936 m_iPort == _u.m_iPort ) 938 m_iPort == _u.m_iPort )
937 return true; 939 return true;
938 940
939 return false; 941 return false;
940 } 942 }
941 943
942 return ( *this == _u ); 944 return ( *this == _u );
943} 945}
944 946
945bool KURL::isParentOf( const KURL& _u ) const 947bool KURL::isParentOf( const KURL& _u ) const
946{ 948{
947 if ( isMalformed() || _u.isMalformed() ) 949 if ( isMalformed() || _u.isMalformed() )
948 return false; 950 return false;
949 951
950 if ( m_strProtocol == _u.m_strProtocol && 952 if ( m_strProtocol == _u.m_strProtocol &&
951 m_strUser == _u.m_strUser && 953 m_strUser == _u.m_strUser &&
952 m_strPass == _u.m_strPass && 954 m_strPass == _u.m_strPass &&
953 m_strHost == _u.m_strHost && 955 m_strHost == _u.m_strHost &&
954 m_strQuery_encoded == _u.m_strQuery_encoded && 956 m_strQuery_encoded == _u.m_strQuery_encoded &&
955 m_strRef_encoded == _u.m_strRef_encoded && 957 m_strRef_encoded == _u.m_strRef_encoded &&
956 m_iPort == _u.m_iPort ) 958 m_iPort == _u.m_iPort )
957 { 959 {
958 if ( path().isEmpty() || _u.path().isEmpty() ) 960 if ( path().isEmpty() || _u.path().isEmpty() )
959 return false; // can't work with implicit paths 961 return false; // can't work with implicit paths
960 962
961 QString p1( cleanpath( path() ) ); 963 QString p1( cleanpath( path() ) );
962 if ( p1.at(p1.length()-1) != '/' ) 964 if ( p1.at(p1.length()-1) != '/' )
963 p1 += '/'; 965 p1 += '/';
964 QString p2( cleanpath( _u.path() ) ); 966 QString p2( cleanpath( _u.path() ) );
965 if ( p2.at(p2.length()-1) != '/' ) 967 if ( p2.at(p2.length()-1) != '/' )
966 p2 += '/'; 968 p2 += '/';
967 969
968 //kdDebug(126) << "p1=" << p1 << endl; 970 //kdDebug(126) << "p1=" << p1 << endl;
969 //kdDebug(126) << "p2=" << p2 << endl; 971 //kdDebug(126) << "p2=" << p2 << endl;
970 //kdDebug(126) << "p1.length()=" << p1.length() << endl; 972 //kdDebug(126) << "p1.length()=" << p1.length() << endl;
971 //kdDebug(126) << "p2.left(!$)=" << p2.left( p1.length() ) << endl; 973 //kdDebug(126) << "p2.left(!$)=" << p2.left( p1.length() ) << endl;
972 return p2.startsWith( p1 ); 974 return p2.startsWith( p1 );
973 } 975 }
974 return false; 976 return false;
975} 977}
976 978
977void KURL::setFileName( const QString& _txt ) 979void KURL::setFileName( const QString& _txt )
978{ 980{
979 m_strRef_encoded = QString::null; 981 m_strRef_encoded = QString::null;
980 int i = 0; 982 int i = 0;
981 while( _txt[i] == '/' ) ++i; 983 while( _txt[i] == '/' ) ++i;
982 QString tmp; 984 QString tmp;
983 if ( i ) 985 if ( i )
984 tmp = _txt.mid( i ); 986 tmp = _txt.mid( i );
985 else 987 else
986 tmp = _txt; 988 tmp = _txt;
987 989
988 QString path = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded; 990 QString path = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
989 if ( path.isEmpty() ) 991 if ( path.isEmpty() )
990 path = "/"; 992 path = "/";
991 else 993 else
992 { 994 {
993 int lastSlash = path.findRev( '/' ); 995 int lastSlash = path.findRev( '/' );
994 if ( lastSlash == -1) 996 if ( lastSlash == -1)
995 { 997 {
996 // The first character is not a '/' ??? 998 // The first character is not a '/' ???
997 // This looks strange ... 999 // This looks strange ...
998 path = "/"; 1000 path = "/";
999 } 1001 }
1000 else if ( path.right(1) != "/" ) 1002 else if ( path.right(1) != "/" )
1001 path.truncate( lastSlash+1 ); // keep the "/" 1003 path.truncate( lastSlash+1 ); // keep the "/"
1002 } 1004 }
1003 if (m_strPath_encoded.isEmpty()) 1005 if (m_strPath_encoded.isEmpty())
1004 { 1006 {
1005 path += tmp; 1007 path += tmp;
1006 setPath( path ); 1008 setPath( path );
1007 } 1009 }
1008 else 1010 else
1009 { 1011 {
1010 path += encode_string(tmp); 1012 path += encode_string(tmp);
1011 setEncodedPath( path ); 1013 setEncodedPath( path );
1012 } 1014 }
1013 cleanPath(); 1015 cleanPath();
1014} 1016}
1015 1017
1016void KURL::cleanPath( bool cleanDirSeparator ) // taken from the old KURL 1018void KURL::cleanPath( bool cleanDirSeparator ) // taken from the old KURL
1017{ 1019{
1018 m_strPath = cleanpath(m_strPath, cleanDirSeparator); 1020 m_strPath = cleanpath(m_strPath, cleanDirSeparator);
1019 // WABA: Is this safe when "/../" is encoded with %? 1021 // WABA: Is this safe when "/../" is encoded with %?
1020 m_strPath_encoded = cleanpath(m_strPath_encoded, cleanDirSeparator); 1022 m_strPath_encoded = cleanpath(m_strPath_encoded, cleanDirSeparator);
1021} 1023}
1022 1024
1023static QString trailingSlash( int _trailing, const QString &path ) 1025static QString trailingSlash( int _trailing, const QString &path )
1024{ 1026{
1025 QString result = path; 1027 QString result = path;
1026 1028
1027 if ( _trailing == 0 ) 1029 if ( _trailing == 0 )
1028 return result; 1030 return result;
1029 else if ( _trailing == 1 ) 1031 else if ( _trailing == 1 )
1030 { 1032 {
1031 int len = result.length(); 1033 int len = result.length();
1032 if ( len == 0 ) 1034 if ( len == 0 )
1033 result = QString::null; 1035 result = QString::null;
1034 else if ( result[ len - 1 ] != '/' ) 1036 else if ( result[ len - 1 ] != '/' )
1035 result += "/"; 1037 result += "/";
1036 return result; 1038 return result;
1037 } 1039 }
1038 else if ( _trailing == -1 ) 1040 else if ( _trailing == -1 )
1039 { 1041 {
1040 if ( result == "/" ) 1042 if ( result == "/" )
1041 return result; 1043 return result;
1042 int len = result.length(); 1044 int len = result.length();
1043 if ( len != 0 && result[ len - 1 ] == '/' ) 1045 if ( len != 0 && result[ len - 1 ] == '/' )
@@ -1185,429 +1187,429 @@ QString KURL::fileEncoding() const
1185 { 1187 {
1186 QString s = decode_string(*it); 1188 QString s = decode_string(*it);
1187 if (s.startsWith("charset=")) 1189 if (s.startsWith("charset="))
1188 return s.mid(8); 1190 return s.mid(8);
1189 } 1191 }
1190 return QString::null; 1192 return QString::null;
1191} 1193}
1192 1194
1193bool KURL::hasSubURL() const 1195bool KURL::hasSubURL() const
1194{ 1196{
1195 if ( m_strProtocol.isEmpty() || m_bIsMalformed ) 1197 if ( m_strProtocol.isEmpty() || m_bIsMalformed )
1196 return false; 1198 return false;
1197 if (m_strRef_encoded.isEmpty()) 1199 if (m_strRef_encoded.isEmpty())
1198 return false; 1200 return false;
1199 if (m_strRef_encoded.startsWith("gzip:")) 1201 if (m_strRef_encoded.startsWith("gzip:"))
1200 return true; 1202 return true;
1201 if (m_strRef_encoded.startsWith("bzip:")) 1203 if (m_strRef_encoded.startsWith("bzip:"))
1202 return true; 1204 return true;
1203 if (m_strRef_encoded.startsWith("bzip2:")) 1205 if (m_strRef_encoded.startsWith("bzip2:"))
1204 return true; 1206 return true;
1205 if (m_strRef_encoded.startsWith("tar:")) 1207 if (m_strRef_encoded.startsWith("tar:"))
1206 return true; 1208 return true;
1207 if ( m_strProtocol == "error" ) // anything that starts with error: has suburls 1209 if ( m_strProtocol == "error" ) // anything that starts with error: has suburls
1208 return true; 1210 return true;
1209 return false; 1211 return false;
1210} 1212}
1211 1213
1212QString KURL::url( int _trailing, int encoding_hint ) const 1214QString KURL::url( int _trailing, int encoding_hint ) const
1213{ 1215{
1214 if( m_bIsMalformed ) 1216 if( m_bIsMalformed )
1215 { 1217 {
1216 // Return the whole url even when the url is 1218 // Return the whole url even when the url is
1217 // malformed. Under such conditions the url 1219 // malformed. Under such conditions the url
1218 // is stored in m_strProtocol. 1220 // is stored in m_strProtocol.
1219 return m_strProtocol; 1221 return m_strProtocol;
1220 } 1222 }
1221 1223
1222 QString u = m_strProtocol; 1224 QString u = m_strProtocol;
1223 if (!u.isEmpty()) 1225 if (!u.isEmpty())
1224 u += ":"; 1226 u += ":";
1225 1227
1226 if ( hasHost() ) 1228 if ( hasHost() )
1227 { 1229 {
1228 u += "//"; 1230 u += "//";
1229 if ( hasUser() ) 1231 if ( hasUser() )
1230 { 1232 {
1231 u += encode(m_strUser, true, encoding_hint); 1233 u += encode(m_strUser, true, encoding_hint);
1232 if ( hasPass() ) 1234 if ( hasPass() )
1233 { 1235 {
1234 u += ":"; 1236 u += ":";
1235 u += encode(m_strPass, true, encoding_hint); 1237 u += encode(m_strPass, true, encoding_hint);
1236 } 1238 }
1237 u += "@"; 1239 u += "@";
1238 } 1240 }
1239 bool IPv6 = (m_strHost.find(':') != -1); 1241 bool IPv6 = (m_strHost.find(':') != -1);
1240 if (IPv6) 1242 if (IPv6)
1241 u += '[' + m_strHost + ']'; 1243 u += '[' + m_strHost + ']';
1242 else 1244 else
1243 u += encodeHost(m_strHost, true, encoding_hint); 1245 u += encodeHost(m_strHost, true, encoding_hint);
1244 if ( m_iPort != 0 ) { 1246 if ( m_iPort != 0 ) {
1245 QString buffer; 1247 QString buffer;
1246 buffer.sprintf( ":%u", m_iPort ); 1248 buffer.sprintf( ":%u", m_iPort );
1247 u += buffer; 1249 u += buffer;
1248 } 1250 }
1249 } 1251 }
1250 1252
1251 u += encodedPathAndQuery( _trailing, false, encoding_hint ); 1253 u += encodedPathAndQuery( _trailing, false, encoding_hint );
1252 1254
1253 if ( hasRef() ) 1255 if ( hasRef() )
1254 { 1256 {
1255 u += "#"; 1257 u += "#";
1256 u += m_strRef_encoded; 1258 u += m_strRef_encoded;
1257 } 1259 }
1258 1260
1259 return u; 1261 return u;
1260} 1262}
1261 1263
1262QString KURL::prettyURL( int _trailing ) const 1264QString KURL::prettyURL( int _trailing ) const
1263{ 1265{
1264 if( m_bIsMalformed ) 1266 if( m_bIsMalformed )
1265 { 1267 {
1266 // Return the whole url even when the url is 1268 // Return the whole url even when the url is
1267 // malformed. Under such conditions the url 1269 // malformed. Under such conditions the url
1268 // is stored in m_strProtocol. 1270 // is stored in m_strProtocol.
1269 return m_strProtocol; 1271 return m_strProtocol;
1270 } 1272 }
1271 1273
1272 QString u = m_strProtocol; 1274 QString u = m_strProtocol;
1273 if (!u.isEmpty()) 1275 if (!u.isEmpty())
1274 u += ":"; 1276 u += ":";
1275 1277
1276 if ( hasHost() ) 1278 if ( hasHost() )
1277 { 1279 {
1278 u += "//"; 1280 u += "//";
1279 if ( hasUser() ) 1281 if ( hasUser() )
1280 { 1282 {
1281 u += lazy_encode(m_strUser); 1283 u += lazy_encode(m_strUser);
1282 // Don't show password! 1284 // Don't show password!
1283 u += "@"; 1285 u += "@";
1284 } 1286 }
1285 bool IPv6 = (m_strHost.find(':') != -1); 1287 bool IPv6 = (m_strHost.find(':') != -1);
1286 if (IPv6) 1288 if (IPv6)
1287 { 1289 {
1288 u += '[' + m_strHost + ']'; 1290 u += '[' + m_strHost + ']';
1289 } 1291 }
1290 else 1292 else
1291 { 1293 {
1292 u += lazy_encode(m_strHost); 1294 u += lazy_encode(m_strHost);
1293 } 1295 }
1294 if ( m_iPort != 0 ) { 1296 if ( m_iPort != 0 ) {
1295 QString buffer; 1297 QString buffer;
1296 buffer.sprintf( ":%u", m_iPort ); 1298 buffer.sprintf( ":%u", m_iPort );
1297 u += buffer; 1299 u += buffer;
1298 } 1300 }
1299 } 1301 }
1300 1302
1301 u += trailingSlash( _trailing, lazy_encode( m_strPath ) ); 1303 u += trailingSlash( _trailing, lazy_encode( m_strPath ) );
1302 if (!m_strQuery_encoded.isNull()) 1304 if (!m_strQuery_encoded.isNull())
1303 u += '?' + m_strQuery_encoded; 1305 u += '?' + m_strQuery_encoded;
1304 1306
1305 if ( hasRef() ) 1307 if ( hasRef() )
1306 { 1308 {
1307 u += "#"; 1309 u += "#";
1308 u += m_strRef_encoded; 1310 u += m_strRef_encoded;
1309 } 1311 }
1310 1312
1311 return u; 1313 return u;
1312} 1314}
1313 1315
1314QString KURL::prettyURL( int _trailing, AdjustementFlags _flags) const 1316QString KURL::prettyURL( int _trailing, AdjustementFlags _flags) const
1315{ 1317{
1316 QString u = prettyURL(_trailing); 1318 QString u = prettyURL(_trailing);
1317 if (_flags & StripFileProtocol && u.startsWith("file:")) 1319 if (_flags & StripFileProtocol && u.startsWith("file:"))
1318 u.remove(0, 5); 1320 u.remove(0, 5);
1319 return u; 1321 return u;
1320} 1322}
1321 1323
1322QString KURL::htmlURL() const 1324QString KURL::htmlURL() const
1323{ 1325{
1324//US QStyleSheet::escape was not in my Qt distribution. Why ??? 1326//US QStyleSheet::escape was not in my Qt distribution. Why ???
1325//US return QStyleSheet::escape(prettyURL()); 1327//US return QStyleSheet::escape(prettyURL());
1326 return prettyURL(); 1328 return prettyURL();
1327} 1329}
1328 1330
1329KURL::List KURL::split( const KURL& _url ) 1331KURL::List KURL::split( const KURL& _url )
1330{ 1332{
1331 QString ref; 1333 QString ref;
1332 KURL::List lst; 1334 KURL::List lst;
1333 KURL url = _url; 1335 KURL url = _url;
1334 1336
1335 while(true) 1337 while(true)
1336 { 1338 {
1337 KURL u = url; 1339 KURL u = url;
1338 u.m_strRef_encoded = QString::null; 1340 u.m_strRef_encoded = QString::null;
1339 lst.append(u); 1341 lst.append(u);
1340 if (url.hasSubURL()) 1342 if (url.hasSubURL())
1341 { 1343 {
1342 url = KURL(url.m_strRef_encoded); 1344 url = KURL(url.m_strRef_encoded);
1343 } 1345 }
1344 else 1346 else
1345 { 1347 {
1346 ref = url.m_strRef_encoded; 1348 ref = url.m_strRef_encoded;
1347 break; 1349 break;
1348 } 1350 }
1349 } 1351 }
1350 1352
1351 // Set HTML ref in all URLs. 1353 // Set HTML ref in all URLs.
1352 KURL::List::Iterator it; 1354 KURL::List::Iterator it;
1353 for( it = lst.begin() ; it != lst.end(); ++it ) 1355 for( it = lst.begin() ; it != lst.end(); ++it )
1354 { 1356 {
1355 (*it).m_strRef_encoded = ref; 1357 (*it).m_strRef_encoded = ref;
1356 } 1358 }
1357 1359
1358 return lst; 1360 return lst;
1359} 1361}
1360 1362
1361KURL::List KURL::split( const QString& _url ) 1363KURL::List KURL::split( const QString& _url )
1362{ 1364{
1363 return split(KURL(_url)); 1365 return split(KURL(_url));
1364} 1366}
1365 1367
1366KURL KURL::join( const KURL::List & lst ) 1368KURL KURL::join( const KURL::List & lst )
1367{ 1369{
1368 if (lst.isEmpty()) return KURL(); 1370 if (lst.isEmpty()) return KURL();
1369 KURL tmp; 1371 KURL tmp;
1370 1372
1371 KURL::List::ConstIterator first = lst.fromLast(); 1373 KURL::List::ConstIterator first = lst.fromLast();
1372 for( KURL::List::ConstIterator it = first; it != lst.end(); --it ) 1374 for( KURL::List::ConstIterator it = first; it != lst.end(); --it )
1373 { 1375 {
1374 KURL u(*it); 1376 KURL u(*it);
1375 if (it != first) 1377 if (it != first)
1376 { 1378 {
1377 if (!u.m_strRef_encoded) u.m_strRef_encoded = tmp.url(); 1379 if (u.m_strRef_encoded.isEmpty()) u.m_strRef_encoded = tmp.url();
1378 else u.m_strRef_encoded += "#" + tmp.url(); // Support more than one suburl thingy 1380 else u.m_strRef_encoded += "#" + tmp.url(); // Support more than one suburl thingy
1379 } 1381 }
1380 tmp = u; 1382 tmp = u;
1381 } 1383 }
1382 1384
1383 return tmp; 1385 return tmp;
1384} 1386}
1385 1387
1386QString KURL::fileName( bool _strip_trailing_slash ) const 1388QString KURL::fileName( bool _strip_trailing_slash ) const
1387{ 1389{
1388 QString fname; 1390 QString fname;
1389 if (hasSubURL()) { // If we have a suburl, then return the filename from there 1391 if (hasSubURL()) { // If we have a suburl, then return the filename from there
1390 KURL::List list = KURL::split(*this); 1392 KURL::List list = KURL::split(*this);
1391 KURL::List::Iterator it = list.fromLast(); 1393 KURL::List::Iterator it = list.fromLast();
1392 return (*it).fileName(_strip_trailing_slash); 1394 return (*it).fileName(_strip_trailing_slash);
1393 } 1395 }
1394 const QString &path = m_strPath; 1396 const QString &path = m_strPath;
1395 1397
1396 int len = path.length(); 1398 int len = path.length();
1397 if ( len == 0 ) 1399 if ( len == 0 )
1398 return fname; 1400 return fname;
1399 1401
1400 if ( _strip_trailing_slash ) 1402 if ( _strip_trailing_slash )
1401 { 1403 {
1402 while ( len >= 1 && path[ len - 1 ] == '/' ) 1404 while ( len >= 1 && path[ len - 1 ] == '/' )
1403 len--; 1405 len--;
1404 } 1406 }
1405 else if ( path[ len - 1 ] == '/' ) 1407 else if ( path[ len - 1 ] == '/' )
1406 return fname; 1408 return fname;
1407 1409
1408 // Does the path only consist of '/' characters ? 1410 // Does the path only consist of '/' characters ?
1409 if ( len == 1 && path[ 0 ] == '/' ) 1411 if ( len == 1 && path[ 0 ] == '/' )
1410 return fname; 1412 return fname;
1411 1413
1412 // Skip last n slashes 1414 // Skip last n slashes
1413 int n = 1; 1415 int n = 1;
1414 if (!m_strPath_encoded.isEmpty()) 1416 if (!m_strPath_encoded.isEmpty())
1415 { 1417 {
1416 // This is hairy, we need the last unencoded slash. 1418 // This is hairy, we need the last unencoded slash.
1417 // Count in the encoded string how many encoded slashes follow the last 1419 // Count in the encoded string how many encoded slashes follow the last
1418 // unencoded one. 1420 // unencoded one.
1419 int i = m_strPath_encoded.findRev( '/', len - 1 ); 1421 int i = m_strPath_encoded.findRev( '/', len - 1 );
1420 QString fileName_encoded = m_strPath_encoded.mid(i+1); 1422 QString fileName_encoded = m_strPath_encoded.mid(i+1);
1421 n += fileName_encoded.contains("%2f", false); 1423 n += fileName_encoded.count("%2f", Qt::CaseInsensitive);
1422 } 1424 }
1423 int i = len; 1425 int i = len;
1424 do { 1426 do {
1425 i = path.findRev( '/', i - 1 ); 1427 i = path.findRev( '/', i - 1 );
1426 } 1428 }
1427 while (--n && (i > 0)); 1429 while (--n && (i > 0));
1428 1430
1429 // If ( i == -1 ) => the first character is not a '/' 1431 // If ( i == -1 ) => the first character is not a '/'
1430 // So it's some URL like file:blah.tgz, return the whole path 1432 // So it's some URL like file:blah.tgz, return the whole path
1431 if ( i == -1 ) { 1433 if ( i == -1 ) {
1432 if ( len == (int)path.length() ) 1434 if ( len == (int)path.length() )
1433 fname = path; 1435 fname = path;
1434 else 1436 else
1435 // Might get here if _strip_trailing_slash is true 1437 // Might get here if _strip_trailing_slash is true
1436 fname = path.left( len ); 1438 fname = path.left( len );
1437 } 1439 }
1438 else 1440 else
1439 { 1441 {
1440 fname = path.mid( i + 1, len - i - 1 ); // TO CHECK 1442 fname = path.mid( i + 1, len - i - 1 ); // TO CHECK
1441 } 1443 }
1442 return fname; 1444 return fname;
1443} 1445}
1444 1446
1445void KURL::addPath( const QString& _txt ) 1447void KURL::addPath( const QString& _txt )
1446{ 1448{
1447 if (hasSubURL()) 1449 if (hasSubURL())
1448 { 1450 {
1449 KURL::List lst = split( *this ); 1451 KURL::List lst = split( *this );
1450 KURL &u = lst.last(); 1452 KURL &u = lst.last();
1451 u.addPath(_txt); 1453 u.addPath(_txt);
1452 *this = join( lst ); 1454 *this = join( lst );
1453 return; 1455 return;
1454 } 1456 }
1455 1457
1456 m_strPath_encoded = QString::null; 1458 m_strPath_encoded = QString::null;
1457 1459
1458 if ( _txt.isEmpty() ) 1460 if ( _txt.isEmpty() )
1459 return; 1461 return;
1460 1462
1461 int i = 0; 1463 int i = 0;
1462 int len = m_strPath.length(); 1464 int len = m_strPath.length();
1463 // NB: avoid three '/' when building a new path from nothing 1465 // NB: avoid three '/' when building a new path from nothing
1464 if ( len == 0 ) { 1466 if ( len == 0 ) {
1465 while( _txt[i] == '/' ) ++i; 1467 while( _txt[i] == '/' ) ++i;
1466 } 1468 }
1467 // Add the trailing '/' if it is missing 1469 // Add the trailing '/' if it is missing
1468 else if ( _txt[0] != '/' && ( len == 0 || m_strPath[ len - 1 ] != '/' ) ) 1470 else if ( _txt[0] != '/' && ( len == 0 || m_strPath[ len - 1 ] != '/' ) )
1469 m_strPath += "/"; 1471 m_strPath += "/";
1470 1472
1471 // No double '/' characters 1473 // No double '/' characters
1472 i = 0; 1474 i = 0;
1473 if ( len != 0 && m_strPath[ len - 1 ] == '/' ) 1475 if ( len != 0 && m_strPath[ len - 1 ] == '/' )
1474 { 1476 {
1475 while( _txt[i] == '/' ) 1477 while( _txt[i] == '/' )
1476 ++i; 1478 ++i;
1477 } 1479 }
1478 1480
1479 m_strPath += _txt.mid( i ); 1481 m_strPath += _txt.mid( i );
1480} 1482}
1481 1483
1482QString KURL::directory( bool _strip_trailing_slash_from_result, 1484QString KURL::directory( bool _strip_trailing_slash_from_result,
1483 bool _ignore_trailing_slash_in_path ) const 1485 bool _ignore_trailing_slash_in_path ) const
1484{ 1486{
1485 QString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded; 1487 QString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded;
1486 if ( _ignore_trailing_slash_in_path ) 1488 if ( _ignore_trailing_slash_in_path )
1487 result = trailingSlash( -1, result ); 1489 result = trailingSlash( -1, result );
1488 1490
1489 if ( result.isEmpty() || result == "/" ) 1491 if ( result.isEmpty() || result == "/" )
1490 return result; 1492 return result;
1491 1493
1492 int i = result.findRev( "/" ); 1494 int i = result.findRev( "/" );
1493 // If ( i == -1 ) => the first character is not a '/' 1495 // If ( i == -1 ) => the first character is not a '/'
1494 // So it's some URL like file:blah.tgz, with no path 1496 // So it's some URL like file:blah.tgz, with no path
1495 if ( i == -1 ) 1497 if ( i == -1 )
1496 return QString::null; 1498 return QString::null;
1497 1499
1498 if ( i == 0 ) 1500 if ( i == 0 )
1499 { 1501 {
1500 result = "/"; 1502 result = "/";
1501 return result; 1503 return result;
1502 } 1504 }
1503 1505
1504 if ( _strip_trailing_slash_from_result ) 1506 if ( _strip_trailing_slash_from_result )
1505 result = result.left( i ); 1507 result = result.left( i );
1506 else 1508 else
1507 result = result.left( i + 1 ); 1509 result = result.left( i + 1 );
1508 1510
1509 if (!m_strPath_encoded.isEmpty()) 1511 if (!m_strPath_encoded.isEmpty())
1510 result = decode(result); 1512 result = decode(result);
1511 1513
1512 return result; 1514 return result;
1513} 1515}
1514 1516
1515 1517
1516bool KURL::cd( const QString& _dir ) 1518bool KURL::cd( const QString& _dir )
1517{ 1519{
1518 if ( _dir.isEmpty() || m_bIsMalformed ) 1520 if ( _dir.isEmpty() || m_bIsMalformed )
1519 return false; 1521 return false;
1520 1522
1521 if (hasSubURL()) 1523 if (hasSubURL())
1522 { 1524 {
1523 KURL::List lst = split( *this ); 1525 KURL::List lst = split( *this );
1524 KURL &u = lst.last(); 1526 KURL &u = lst.last();
1525 u.cd(_dir); 1527 u.cd(_dir);
1526 *this = join( lst ); 1528 *this = join( lst );
1527 return true; 1529 return true;
1528 } 1530 }
1529 1531
1530 // absolute path ? 1532 // absolute path ?
1531 if ( _dir[0] == '/' ) 1533 if ( _dir[0] == '/' )
1532 { 1534 {
1533 m_strPath_encoded = QString::null; 1535 m_strPath_encoded = QString::null;
1534 m_strPath = _dir; 1536 m_strPath = _dir;
1535 setHTMLRef( QString::null ); 1537 setHTMLRef( QString::null );
1536 m_strQuery_encoded = QString::null; 1538 m_strQuery_encoded = QString::null;
1537 return true; 1539 return true;
1538 } 1540 }
1539 1541
1540 // Users home directory on the local disk ? 1542 // Users home directory on the local disk ?
1541 if ( ( _dir[0] == '~' ) && ( m_strProtocol == fileProt )) 1543 if ( ( _dir[0] == '~' ) && ( m_strProtocol == fileProt ))
1542 { 1544 {
1543 m_strPath_encoded = QString::null; 1545 m_strPath_encoded = QString::null;
1544 m_strPath = QDir::homeDirPath(); 1546 m_strPath = QDir::homeDirPath();
1545 m_strPath += "/"; 1547 m_strPath += "/";
1546 m_strPath += _dir.right(m_strPath.length() - 1); 1548 m_strPath += _dir.right(m_strPath.length() - 1);
1547 setHTMLRef( QString::null ); 1549 setHTMLRef( QString::null );
1548 m_strQuery_encoded = QString::null; 1550 m_strQuery_encoded = QString::null;
1549 return true; 1551 return true;
1550 } 1552 }
1551 1553
1552 // relative path 1554 // relative path
1553 // we always work on the past of the first url. 1555 // we always work on the past of the first url.
1554 // Sub URLs are not touched. 1556 // Sub URLs are not touched.
1555 1557
1556 // append '/' if necessary 1558 // append '/' if necessary
1557 QString p = path(1); 1559 QString p = path(1);
1558 p += _dir; 1560 p += _dir;
1559 p = cleanpath( p ); 1561 p = cleanpath( p );
1560 setPath( p ); 1562 setPath( p );
1561 1563
1562 setHTMLRef( QString::null ); 1564 setHTMLRef( QString::null );
1563 m_strQuery_encoded = QString::null; 1565 m_strQuery_encoded = QString::null;
1564 1566
1565 return true; 1567 return true;
1566} 1568}
1567 1569
1568KURL KURL::upURL( ) const 1570KURL KURL::upURL( ) const
1569{ 1571{
1570 if (!query().isEmpty()) 1572 if (!query().isEmpty())
1571 { 1573 {
1572 KURL u(*this); 1574 KURL u(*this);
1573 u.setQuery(QString::null); 1575 u.setQuery(QString::null);
1574 return u; 1576 return u;
1575 }; 1577 };
1576 1578
1577 if (!hasSubURL()) 1579 if (!hasSubURL())
1578 { 1580 {
1579 KURL u(*this); 1581 KURL u(*this);
1580 u.cd("../"); 1582 u.cd("../");
1581 return u; 1583 return u;
1582 } 1584 }
1583 1585
1584 // We have a subURL. 1586 // We have a subURL.
1585 KURL::List lst = split( *this ); 1587 KURL::List lst = split( *this );
1586 if (lst.isEmpty()) 1588 if (lst.isEmpty())
1587 return KURL(); // Huh? 1589 return KURL(); // Huh?
1588 while (true) 1590 while (true)
1589 { 1591 {
1590 KURL &u = lst.last(); 1592 KURL &u = lst.last();
1591 QString old = u.path(); 1593 QString old = u.path();
1592 u.cd("../"); 1594 u.cd("../");
1593 if (u.path() != old) 1595 if (u.path() != old)
1594 break; // Finshed. 1596 break; // Finshed.
1595 if (lst.count() == 1) 1597 if (lst.count() == 1)
1596 break; // Finished. 1598 break; // Finished.
1597 lst.remove(lst.fromLast()); 1599 lst.remove(lst.fromLast());
1598 } 1600 }
1599 return join( lst ); 1601 return join( lst );
1600} 1602}
1601 1603
1602QString KURL::htmlRef() const 1604QString KURL::htmlRef() const
1603{ 1605{
1604 if ( !hasSubURL() ) 1606 if ( !hasSubURL() )
1605 { 1607 {
1606 return decode( ref() ); 1608 return decode( ref() );
1607 } 1609 }
1608 1610
1609 List lst = split( *this ); 1611 List lst = split( *this );
1610 return decode( (*lst.begin()).ref() ); 1612 return decode( (*lst.begin()).ref() );
1611} 1613}
1612 1614
1613QString KURL::encodedHtmlRef() const 1615QString KURL::encodedHtmlRef() const