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,1942 +1,1944 @@
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 ] == '/' )
1044 result.truncate( len - 1 ); 1046 result.truncate( len - 1 );
1045 return result; 1047 return result;
1046 } 1048 }
1047 else { 1049 else {
1048 assert( 0 ); 1050 assert( 0 );
1049 return QString::null; 1051 return QString::null;
1050 } 1052 }
1051} 1053}
1052 1054
1053void KURL::adjustPath( int _trailing ) 1055void KURL::adjustPath( int _trailing )
1054{ 1056{
1055 if (!m_strPath_encoded.isEmpty()) 1057 if (!m_strPath_encoded.isEmpty())
1056 { 1058 {
1057 m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded ); 1059 m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded );
1058 } 1060 }
1059 m_strPath = trailingSlash( _trailing, m_strPath ); 1061 m_strPath = trailingSlash( _trailing, m_strPath );
1060} 1062}
1061 1063
1062 1064
1063QString KURL::encodedPathAndQuery( int _trailing, bool _no_empty_path, int encoding_hint ) const 1065QString KURL::encodedPathAndQuery( int _trailing, bool _no_empty_path, int encoding_hint ) const
1064{ 1066{
1065 QString tmp; 1067 QString tmp;
1066 if (!m_strPath_encoded.isEmpty() && encoding_hint == 0) 1068 if (!m_strPath_encoded.isEmpty() && encoding_hint == 0)
1067 { 1069 {
1068 tmp = trailingSlash( _trailing, m_strPath_encoded ); 1070 tmp = trailingSlash( _trailing, m_strPath_encoded );
1069 } 1071 }
1070 else 1072 else
1071 { 1073 {
1072 tmp = path( _trailing ); 1074 tmp = path( _trailing );
1073 if ( _no_empty_path && tmp.isEmpty() ) 1075 if ( _no_empty_path && tmp.isEmpty() )
1074 tmp = "/"; 1076 tmp = "/";
1075 tmp = encode( tmp, false, encoding_hint ); 1077 tmp = encode( tmp, false, encoding_hint );
1076 } 1078 }
1077 1079
1078 // TODO apply encoding_hint to the query 1080 // TODO apply encoding_hint to the query
1079 if (!m_strQuery_encoded.isNull()) 1081 if (!m_strQuery_encoded.isNull())
1080 tmp += '?' + m_strQuery_encoded; 1082 tmp += '?' + m_strQuery_encoded;
1081 return tmp; 1083 return tmp;
1082} 1084}
1083 1085
1084void KURL::setEncodedPath( const QString& _txt, int encoding_hint ) 1086void KURL::setEncodedPath( const QString& _txt, int encoding_hint )
1085{ 1087{
1086 m_strPath_encoded = _txt; 1088 m_strPath_encoded = _txt;
1087 1089
1088 decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint ); 1090 decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint );
1089 // Throw away encoding for local files, makes file-operations faster. 1091 // Throw away encoding for local files, makes file-operations faster.
1090 if (m_strProtocol == fileProt) 1092 if (m_strProtocol == fileProt)
1091 m_strPath_encoded = QString::null; 1093 m_strPath_encoded = QString::null;
1092} 1094}
1093 1095
1094 1096
1095void KURL::setEncodedPathAndQuery( const QString& _txt, int encoding_hint ) 1097void KURL::setEncodedPathAndQuery( const QString& _txt, int encoding_hint )
1096{ 1098{
1097 int pos = _txt.find( '?' ); 1099 int pos = _txt.find( '?' );
1098 if ( pos == -1 ) 1100 if ( pos == -1 )
1099 { 1101 {
1100 setEncodedPath(_txt, encoding_hint); 1102 setEncodedPath(_txt, encoding_hint);
1101 m_strQuery_encoded = QString::null; 1103 m_strQuery_encoded = QString::null;
1102 } 1104 }
1103 else 1105 else
1104 { 1106 {
1105 setEncodedPath(_txt.left( pos ), encoding_hint); 1107 setEncodedPath(_txt.left( pos ), encoding_hint);
1106 setQuery(_txt.right(_txt.length() - pos - 1), encoding_hint); 1108 setQuery(_txt.right(_txt.length() - pos - 1), encoding_hint);
1107 } 1109 }
1108} 1110}
1109 1111
1110QString KURL::path( int _trailing ) const 1112QString KURL::path( int _trailing ) const
1111{ 1113{
1112 return trailingSlash( _trailing, path() ); 1114 return trailingSlash( _trailing, path() );
1113} 1115}
1114 1116
1115bool KURL::isLocalFile() const 1117bool KURL::isLocalFile() const
1116{ 1118{
1117 if ( (m_strProtocol != fileProt ) || hasSubURL() ) 1119 if ( (m_strProtocol != fileProt ) || hasSubURL() )
1118 return false; 1120 return false;
1119 1121
1120 if (m_strHost.isEmpty() || (m_strHost == "localhost")) 1122 if (m_strHost.isEmpty() || (m_strHost == "localhost"))
1121 return true; 1123 return true;
1122 1124
1123 char hostname[ 256 ]; 1125 char hostname[ 256 ];
1124 hostname[ 0 ] = '\0'; 1126 hostname[ 0 ] = '\0';
1125#ifdef _WIN32_ 1127#ifdef _WIN32_
1126 // pending LR fixme 1128 // pending LR fixme
1127 //hostname = "localhost"; 1129 //hostname = "localhost";
1128#else 1130#else
1129 if (!gethostname( hostname, 255 )) 1131 if (!gethostname( hostname, 255 ))
1130 hostname[sizeof(hostname)-1] = '\0'; 1132 hostname[sizeof(hostname)-1] = '\0';
1131#endif 1133#endif
1132 for(char *p = hostname; *p; p++) 1134 for(char *p = hostname; *p; p++)
1133 *p = tolower(*p); 1135 *p = tolower(*p);
1134 1136
1135 return (m_strHost == hostname); 1137 return (m_strHost == hostname);
1136} 1138}
1137 1139
1138void KURL::setFileEncoding(const QString &encoding) 1140void KURL::setFileEncoding(const QString &encoding)
1139{ 1141{
1140 if (!isLocalFile()) 1142 if (!isLocalFile())
1141 return; 1143 return;
1142 1144
1143 QString q = query(); 1145 QString q = query();
1144 1146
1145 if (!q.isEmpty() && (q[0] == '?')) 1147 if (!q.isEmpty() && (q[0] == '?'))
1146 q = q.mid(1); 1148 q = q.mid(1);
1147 1149
1148 QStringList args = QStringList::split('&', q); 1150 QStringList args = QStringList::split('&', q);
1149 for(QStringList::Iterator it = args.begin(); 1151 for(QStringList::Iterator it = args.begin();
1150 it != args.end();) 1152 it != args.end();)
1151 { 1153 {
1152 QString s = decode_string(*it); 1154 QString s = decode_string(*it);
1153 if (s.startsWith("charset=")) 1155 if (s.startsWith("charset="))
1154//US changed erase into remove ??? 1156//US changed erase into remove ???
1155 it = args.remove(it); 1157 it = args.remove(it);
1156 else 1158 else
1157 ++it; 1159 ++it;
1158 } 1160 }
1159 if (!encoding.isEmpty()) 1161 if (!encoding.isEmpty())
1160 args.append("charset="+encode_string(encoding)); 1162 args.append("charset="+encode_string(encoding));
1161 1163
1162 if (args.isEmpty()) 1164 if (args.isEmpty())
1163 setQuery(QString::null); 1165 setQuery(QString::null);
1164 else 1166 else
1165 setQuery(args.join("&")); 1167 setQuery(args.join("&"));
1166} 1168}
1167 1169
1168QString KURL::fileEncoding() const 1170QString KURL::fileEncoding() const
1169{ 1171{
1170 if (!isLocalFile()) 1172 if (!isLocalFile())
1171 return QString::null; 1173 return QString::null;
1172 1174
1173 QString q = query(); 1175 QString q = query();
1174 1176
1175 if (q.isEmpty()) 1177 if (q.isEmpty())
1176 return QString::null; 1178 return QString::null;
1177 1179
1178 if (q[0] == '?') 1180 if (q[0] == '?')
1179 q = q.mid(1); 1181 q = q.mid(1);
1180 1182
1181 QStringList args = QStringList::split('&', q); 1183 QStringList args = QStringList::split('&', q);
1182 for(QStringList::ConstIterator it = args.begin(); 1184 for(QStringList::ConstIterator it = args.begin();
1183 it != args.end(); 1185 it != args.end();
1184 ++it) 1186 ++it)
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
1614{ 1616{
1615 if ( !hasSubURL() ) 1617 if ( !hasSubURL() )
1616 { 1618 {
1617 return ref(); 1619 return ref();
1618 } 1620 }
1619 1621
1620 List lst = split( *this ); 1622 List lst = split( *this );
1621 return (*lst.begin()).ref(); 1623 return (*lst.begin()).ref();
1622} 1624}
1623 1625
1624void KURL::setHTMLRef( const QString& _ref ) 1626void KURL::setHTMLRef( const QString& _ref )
1625{ 1627{
1626 if ( !hasSubURL() ) 1628 if ( !hasSubURL() )
1627 { 1629 {
1628 m_strRef_encoded = encode( _ref, true, 0 /*?*/); 1630 m_strRef_encoded = encode( _ref, true, 0 /*?*/);
1629 return; 1631 return;
1630 } 1632 }
1631 1633
1632 List lst = split( *this ); 1634 List lst = split( *this );
1633 1635
1634 (*lst.begin()).setRef( encode( _ref, true, 0 /*?*/) ); 1636 (*lst.begin()).setRef( encode( _ref, true, 0 /*?*/) );
1635 1637
1636 *this = join( lst ); 1638 *this = join( lst );
1637} 1639}
1638 1640
1639bool KURL::hasHTMLRef() const 1641bool KURL::hasHTMLRef() const
1640{ 1642{
1641 if ( !hasSubURL() ) 1643 if ( !hasSubURL() )
1642 { 1644 {
1643 return hasRef(); 1645 return hasRef();
1644 } 1646 }
1645 1647
1646 List lst = split( *this ); 1648 List lst = split( *this );
1647 return (*lst.begin()).hasRef(); 1649 return (*lst.begin()).hasRef();
1648} 1650}
1649 1651
1650void 1652void
1651KURL::setProtocol( const QString& _txt ) 1653KURL::setProtocol( const QString& _txt )
1652{ 1654{
1653 m_strProtocol = _txt; 1655 m_strProtocol = _txt;
1654 m_bIsMalformed = false; 1656 m_bIsMalformed = false;
1655} 1657}
1656 1658
1657void 1659void
1658KURL::setUser( const QString& _txt ) 1660KURL::setUser( const QString& _txt )
1659{ 1661{
1660 m_strUser = _txt; 1662 m_strUser = _txt;
1661} 1663}
1662 1664
1663void 1665void
1664KURL::setPass( const QString& _txt ) 1666KURL::setPass( const QString& _txt )
1665{ 1667{
1666 m_strPass = _txt; 1668 m_strPass = _txt;
1667} 1669}
1668 1670
1669void 1671void
1670KURL::setHost( const QString& _txt ) 1672KURL::setHost( const QString& _txt )
1671{ 1673{
1672#ifndef KDE_QT_ONLY 1674#ifndef KDE_QT_ONLY
1673 m_strHost = KIDNA::toUnicode(_txt); 1675 m_strHost = KIDNA::toUnicode(_txt);
1674 if (m_strHost.isEmpty()) 1676 if (m_strHost.isEmpty())
1675 m_strHost = _txt.lower(); // Probably an invalid hostname, but... 1677 m_strHost = _txt.lower(); // Probably an invalid hostname, but...
1676#else 1678#else
1677 m_strHost = _txt.lower(); 1679 m_strHost = _txt.lower();
1678#endif 1680#endif
1679} 1681}
1680 1682
1681void 1683void
1682KURL::setPort( unsigned short int _p ) 1684KURL::setPort( unsigned short int _p )
1683{ 1685{
1684 m_iPort = _p; 1686 m_iPort = _p;
1685} 1687}
1686 1688
1687void KURL::setPath( const QString & path ) 1689void KURL::setPath( const QString & path )
1688{ 1690{
1689 if (isEmpty()) 1691 if (isEmpty())
1690 m_bIsMalformed = false; 1692 m_bIsMalformed = false;
1691 if (m_strProtocol.isEmpty()) 1693 if (m_strProtocol.isEmpty())
1692 { 1694 {
1693 m_strProtocol = fileProt; 1695 m_strProtocol = fileProt;
1694 } 1696 }
1695 m_strPath = path; 1697 m_strPath = path;
1696 m_strPath_encoded = QString::null; 1698 m_strPath_encoded = QString::null;
1697} 1699}
1698 1700
1699void KURL::setDirectory( const QString &dir) 1701void KURL::setDirectory( const QString &dir)
1700{ 1702{
1701//US this has to be fixed. endsWith is not available in my distribution 1703//US this has to be fixed. endsWith is not available in my distribution
1702//US if ( dir.endsWith("/")) 1704//US if ( dir.endsWith("/"))
1703//US setPath(dir); 1705//US setPath(dir);
1704//US else 1706//US else
1705 setPath(dir+"/"); 1707 setPath(dir+"/");
1706} 1708}
1707 1709
1708void KURL::setQuery( const QString &_txt, int encoding_hint) 1710void KURL::setQuery( const QString &_txt, int encoding_hint)
1709{ 1711{
1710 if (!_txt.length()) 1712 if (!_txt.length())
1711 { 1713 {
1712 m_strQuery_encoded = _txt; 1714 m_strQuery_encoded = _txt;
1713 return; 1715 return;
1714 } 1716 }
1715 if (_txt[0] =='?') 1717 if (_txt[0] =='?')
1716 m_strQuery_encoded = _txt.mid(1); 1718 m_strQuery_encoded = _txt.mid(1);
1717 else 1719 else
1718 m_strQuery_encoded = _txt; 1720 m_strQuery_encoded = _txt;
1719 1721
1720 int l = m_strQuery_encoded.length(); 1722 int l = m_strQuery_encoded.length();
1721 int i = 0; 1723 int i = 0;
1722 QString result; 1724 QString result;
1723 while (i < l) 1725 while (i < l)
1724 { 1726 {
1725 int s = i; 1727 int s = i;
1726 // Re-encode. Break encoded string up according to the reserved 1728 // Re-encode. Break encoded string up according to the reserved
1727 // characters '&:;=/?' and re-encode part by part. 1729 // characters '&:;=/?' and re-encode part by part.
1728 while(i < l) 1730 while(i < l)
1729 { 1731 {
1730 char c = m_strQuery_encoded[i].latin1(); 1732 char c = m_strQuery_encoded[i].latin1();
1731 if ((c == '&') || (c == ':') || (c == ';') || 1733 if ((c == '&') || (c == ':') || (c == ';') ||
1732 (c == '=') || (c == '/') || (c == '?')) 1734 (c == '=') || (c == '/') || (c == '?'))
1733 break; 1735 break;
1734 i++; 1736 i++;
1735 } 1737 }
1736 if (i > s) 1738 if (i > s)
1737 { 1739 {
1738 QString tmp = m_strQuery_encoded.mid(s, i-s); 1740 QString tmp = m_strQuery_encoded.mid(s, i-s);
1739 QString newTmp; 1741 QString newTmp;
1740 decode( tmp, newTmp, tmp, encoding_hint, false ); 1742 decode( tmp, newTmp, tmp, encoding_hint, false );
1741 result += tmp; 1743 result += tmp;
1742 } 1744 }
1743 if (i < l) 1745 if (i < l)
1744 { 1746 {
1745 result += m_strQuery_encoded[i]; 1747 result += m_strQuery_encoded[i];
1746 i++; 1748 i++;
1747 } 1749 }
1748 } 1750 }
1749 m_strQuery_encoded = result; 1751 m_strQuery_encoded = result;
1750} 1752}
1751 1753
1752QString KURL::query() const 1754QString KURL::query() const
1753{ 1755{
1754 if (m_strQuery_encoded.isNull()) 1756 if (m_strQuery_encoded.isNull())
1755 return QString::null; 1757 return QString::null;
1756 return '?'+m_strQuery_encoded; 1758 return '?'+m_strQuery_encoded;
1757} 1759}
1758 1760
1759QString KURL::decode_string(const QString &str, int encoding_hint) 1761QString KURL::decode_string(const QString &str, int encoding_hint)
1760{ 1762{
1761 return decode(str, encoding_hint); 1763 return decode(str, encoding_hint);
1762} 1764}
1763 1765
1764QString KURL::encode_string(const QString &str, int encoding_hint) 1766QString KURL::encode_string(const QString &str, int encoding_hint)
1765{ 1767{
1766 return encode(str, false, encoding_hint); 1768 return encode(str, false, encoding_hint);
1767} 1769}
1768 1770
1769QString KURL::encode_string_no_slash(const QString &str, int encoding_hint) 1771QString KURL::encode_string_no_slash(const QString &str, int encoding_hint)
1770{ 1772{
1771 return encode(str, true, encoding_hint); 1773 return encode(str, true, encoding_hint);
1772} 1774}
1773 1775
1774bool urlcmp( const QString& _url1, const QString& _url2 ) 1776bool urlcmp( const QString& _url1, const QString& _url2 )
1775{ 1777{
1776 // Both empty ? 1778 // Both empty ?
1777 if ( _url1.isEmpty() && _url2.isEmpty() ) 1779 if ( _url1.isEmpty() && _url2.isEmpty() )
1778 return true; 1780 return true;
1779 // Only one empty ? 1781 // Only one empty ?
1780 if ( _url1.isEmpty() || _url2.isEmpty() ) 1782 if ( _url1.isEmpty() || _url2.isEmpty() )
1781 return false; 1783 return false;
1782 1784
1783 KURL::List list1 = KURL::split( _url1 ); 1785 KURL::List list1 = KURL::split( _url1 );
1784 KURL::List list2 = KURL::split( _url2 ); 1786 KURL::List list2 = KURL::split( _url2 );
1785 1787
1786 // Malformed ? 1788 // Malformed ?
1787 if ( list1.isEmpty() || list2.isEmpty() ) 1789 if ( list1.isEmpty() || list2.isEmpty() )
1788 return false; 1790 return false;
1789 1791
1790 return ( list1 == list2 ); 1792 return ( list1 == list2 );
1791} 1793}
1792 1794
1793bool urlcmp( const QString& _url1, const QString& _url2, bool _ignore_trailing, bool _ignore_ref ) 1795bool urlcmp( const QString& _url1, const QString& _url2, bool _ignore_trailing, bool _ignore_ref )
1794{ 1796{
1795 // Both empty ? 1797 // Both empty ?
1796 if ( _url1.isEmpty() && _url2.isEmpty() ) 1798 if ( _url1.isEmpty() && _url2.isEmpty() )
1797 return true; 1799 return true;
1798 // Only one empty ? 1800 // Only one empty ?
1799 if ( _url1.isEmpty() || _url2.isEmpty() ) 1801 if ( _url1.isEmpty() || _url2.isEmpty() )
1800 return false; 1802 return false;
1801 1803
1802 KURL::List list1 = KURL::split( _url1 ); 1804 KURL::List list1 = KURL::split( _url1 );
1803 KURL::List list2 = KURL::split( _url2 ); 1805 KURL::List list2 = KURL::split( _url2 );
1804 1806
1805 // Malformed ? 1807 // Malformed ?
1806 if ( list1.isEmpty() || list2.isEmpty() ) 1808 if ( list1.isEmpty() || list2.isEmpty() )
1807 return false; 1809 return false;
1808 1810
1809 unsigned int size = list1.count(); 1811 unsigned int size = list1.count();
1810 if ( list2.count() != size ) 1812 if ( list2.count() != size )
1811 return false; 1813 return false;
1812 1814
1813 if ( _ignore_ref ) 1815 if ( _ignore_ref )
1814 { 1816 {
1815 (*list1.begin()).setRef(QString::null); 1817 (*list1.begin()).setRef(QString::null);
1816 (*list2.begin()).setRef(QString::null); 1818 (*list2.begin()).setRef(QString::null);
1817 } 1819 }
1818 1820
1819 KURL::List::Iterator it1 = list1.begin(); 1821 KURL::List::Iterator it1 = list1.begin();
1820 KURL::List::Iterator it2 = list2.begin(); 1822 KURL::List::Iterator it2 = list2.begin();
1821 for( ; it1 != list1.end() ; ++it1, ++it2 ) 1823 for( ; it1 != list1.end() ; ++it1, ++it2 )
1822 if ( !(*it1).equals( *it2, _ignore_trailing ) ) 1824 if ( !(*it1).equals( *it2, _ignore_trailing ) )
1823 return false; 1825 return false;
1824 1826
1825 return true; 1827 return true;
1826} 1828}
1827/*US we do not need this functions 1829/*US we do not need this functions
1828 1830
1829QMap< QString, QString > KURL::queryItems( int options ) const { 1831QMap< QString, QString > KURL::queryItems( int options ) const {
1830 return queryItems(options, 0); 1832 return queryItems(options, 0);
1831} 1833}
1832 1834
1833QMap< QString, QString > KURL::queryItems( int options, int encoding_hint ) const { 1835QMap< QString, QString > KURL::queryItems( int options, int encoding_hint ) const {
1834 if ( m_strQuery_encoded.isEmpty() ) 1836 if ( m_strQuery_encoded.isEmpty() )
1835 return QMap<QString,QString>(); 1837 return QMap<QString,QString>();
1836 1838
1837 QMap< QString, QString > result; 1839 QMap< QString, QString > result;
1838 QStringList items = QStringList::split( '&', m_strQuery_encoded ); 1840 QStringList items = QStringList::split( '&', m_strQuery_encoded );
1839 for ( QStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) { 1841 for ( QStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) {
1840 int equal_pos = (*it).find( '=' ); 1842 int equal_pos = (*it).find( '=' );
1841 if ( equal_pos > 0 ) { // = is not the first char... 1843 if ( equal_pos > 0 ) { // = is not the first char...
1842 QString name = (*it).left( equal_pos ); 1844 QString name = (*it).left( equal_pos );
1843 if ( options & CaseInsensitiveKeys ) 1845 if ( options & CaseInsensitiveKeys )
1844 name = name.lower(); 1846 name = name.lower();
1845 QString value = (*it).mid( equal_pos + 1 ); 1847 QString value = (*it).mid( equal_pos + 1 );
1846 if ( value.isEmpty() ) 1848 if ( value.isEmpty() )
1847 result.insert( name, QString::fromLatin1("") ); 1849 result.insert( name, QString::fromLatin1("") );
1848 else { 1850 else {
1849 // ### why is decoding name not neccessary? 1851 // ### why is decoding name not neccessary?
1850 value.replace( '+', ' ' ); // + in queries means space 1852 value.replace( '+', ' ' ); // + in queries means space
1851 result.insert( name, decode_string( value, encoding_hint ) ); 1853 result.insert( name, decode_string( value, encoding_hint ) );
1852 } 1854 }
1853 } else if ( equal_pos < 0 ) { // no = 1855 } else if ( equal_pos < 0 ) { // no =
1854 QString name = (*it); 1856 QString name = (*it);
1855 if ( options & CaseInsensitiveKeys ) 1857 if ( options & CaseInsensitiveKeys )
1856 name = name.lower(); 1858 name = name.lower();
1857 result.insert( name, QString::null ); 1859 result.insert( name, QString::null );
1858 } 1860 }
1859 } 1861 }
1860 1862
1861 return result; 1863 return result;
1862} 1864}
1863 1865
1864QString KURL::queryItem( const QString& _item ) const 1866QString KURL::queryItem( const QString& _item ) const
1865{ 1867{
1866 return queryItem( _item, 0 ); 1868 return queryItem( _item, 0 );
1867} 1869}
1868 1870
1869QString KURL::queryItem( const QString& _item, int encoding_hint ) const 1871QString KURL::queryItem( const QString& _item, int encoding_hint ) const
1870{ 1872{
1871 QString item = _item + '='; 1873 QString item = _item + '=';
1872 if ( m_strQuery_encoded.length() <= 1 ) 1874 if ( m_strQuery_encoded.length() <= 1 )
1873 return QString::null; 1875 return QString::null;
1874 1876
1875 QStringList items = QStringList::split( '&', m_strQuery_encoded ); 1877 QStringList items = QStringList::split( '&', m_strQuery_encoded );
1876 unsigned int _len = item.length(); 1878 unsigned int _len = item.length();
1877 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it ) 1879 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it )
1878 { 1880 {
1879 if ( (*it).startsWith( item ) ) 1881 if ( (*it).startsWith( item ) )
1880 { 1882 {
1881 if ( (*it).length() > _len ) 1883 if ( (*it).length() > _len )
1882 { 1884 {
1883 QString str = (*it).mid( _len ); 1885 QString str = (*it).mid( _len );
1884 str.replace( '+', ' ' ); // + in queries means space. 1886 str.replace( '+', ' ' ); // + in queries means space.
1885 return decode_string( str, encoding_hint ); 1887 return decode_string( str, encoding_hint );
1886 } 1888 }
1887 else // empty value 1889 else // empty value
1888 return QString::fromLatin1(""); 1890 return QString::fromLatin1("");
1889 } 1891 }
1890 } 1892 }
1891 1893
1892 return QString::null; 1894 return QString::null;
1893} 1895}
1894US we do not need this functions*/ 1896US we do not need this functions*/
1895 1897
1896void KURL::removeQueryItem( const QString& _item ) 1898void KURL::removeQueryItem( const QString& _item )
1897{ 1899{
1898 QString item = _item + '='; 1900 QString item = _item + '=';
1899 if ( m_strQuery_encoded.length() <= 1 ) 1901 if ( m_strQuery_encoded.length() <= 1 )
1900 return; 1902 return;
1901 1903
1902 QStringList items = QStringList::split( '&', m_strQuery_encoded ); 1904 QStringList items = QStringList::split( '&', m_strQuery_encoded );
1903 for ( QStringList::Iterator it = items.begin(); it != items.end(); ) 1905 for ( QStringList::Iterator it = items.begin(); it != items.end(); )
1904 { 1906 {
1905 if ( (*it).startsWith( item ) || (*it == _item) ) 1907 if ( (*it).startsWith( item ) || (*it == _item) )
1906 { 1908 {
1907 QStringList::Iterator deleteIt = it; 1909 QStringList::Iterator deleteIt = it;
1908 ++it; 1910 ++it;
1909 items.remove(deleteIt); 1911 items.remove(deleteIt);
1910 } 1912 }
1911 else 1913 else
1912 { 1914 {
1913 ++it; 1915 ++it;
1914 } 1916 }
1915 } 1917 }
1916 m_strQuery_encoded = items.join( "&" ); 1918 m_strQuery_encoded = items.join( "&" );
1917} 1919}
1918 1920
1919void KURL::addQueryItem( const QString& _item, const QString& _value, int encoding_hint ) 1921void KURL::addQueryItem( const QString& _item, const QString& _value, int encoding_hint )
1920{ 1922{
1921 QString item = _item + '='; 1923 QString item = _item + '=';
1922 QString value = encode( _value, true, encoding_hint ); 1924 QString value = encode( _value, true, encoding_hint );
1923 1925
1924 if (!m_strQuery_encoded.isEmpty()) 1926 if (!m_strQuery_encoded.isEmpty())
1925 m_strQuery_encoded += '&'; 1927 m_strQuery_encoded += '&';
1926 m_strQuery_encoded += item + value; 1928 m_strQuery_encoded += item + value;
1927} 1929}
1928 1930
1929// static 1931// static
1930KURL KURL::fromPathOrURL( const QString& text ) 1932KURL KURL::fromPathOrURL( const QString& text )
1931{ 1933{
1932 if ( text.isEmpty() ) 1934 if ( text.isEmpty() )
1933 return KURL(); 1935 return KURL();
1934 1936
1935 KURL url; 1937 KURL url;
1936 if ( text[0] == '/' ) 1938 if ( text[0] == '/' )
1937 url.setPath( text ); 1939 url.setPath( text );
1938 else 1940 else
1939 url = text; 1941 url = text;
1940 1942
1941 return url; 1943 return url;
1942} 1944}