~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WTF/wtf/url/src/URLCanonRelative.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2007 Google Inc. All rights reserved.
 
3
 * Copyright 2012 Apple Inc. All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are
 
7
 * met:
 
8
 *
 
9
 *     * Redistributions of source code must retain the above copyright
 
10
 * notice, this list of conditions and the following disclaimer.
 
11
 *     * Redistributions in binary form must reproduce the above
 
12
 * copyright notice, this list of conditions and the following disclaimer
 
13
 * in the documentation and/or other materials provided with the
 
14
 * distribution.
 
15
 *     * Neither the name of Google Inc. nor the names of its
 
16
 * contributors may be used to endorse or promote products derived from
 
17
 * this software without specific prior written permission.
 
18
 *
 
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
20
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
21
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
22
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
23
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
24
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
25
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
26
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
27
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
28
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
29
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
30
 */
 
31
 
 
32
// Canonicalizer functions for working with and resolving relative URLs.
 
33
 
 
34
#include "config.h"
 
35
#include "URLCanon.h"
 
36
 
 
37
#include "URLCanonInternal.h"
 
38
#include "URLFile.h"
 
39
#include "URLParseInternal.h"
 
40
#include "URLUtilInternal.h"
 
41
 
 
42
#if USE(WTFURL)
 
43
 
 
44
namespace WTF {
 
45
 
 
46
namespace URLCanonicalizer {
 
47
 
 
48
namespace {
 
49
 
 
50
// Firefox does a case-sensitive compare (which is probably wrong--Mozilla bug
 
51
// 379034), whereas IE is case-insensetive.
 
52
//
 
53
// We choose to be more permissive like IE. We don't need to worry about
 
54
// unescaping or anything here: neither IE or Firefox allow this. We also
 
55
// don't have to worry about invalid scheme characters since we are comparing
 
56
// against the canonical scheme of the base.
 
57
//
 
58
// The base URL should always be canonical, therefore is ASCII.
 
59
template<typename CHAR>
 
60
bool AreSchemesEqual(const char* base,
 
61
                     const URLComponent& baseScheme,
 
62
                     const CHAR* cmp,
 
63
                     const URLComponent& cmpScheme)
 
64
{
 
65
    if (baseScheme.length() != cmpScheme.length())
 
66
        return false;
 
67
    for (int i = 0; i < baseScheme.length(); i++) {
 
68
        // We assume the base is already canonical, so we don't have to
 
69
        // canonicalize it.
 
70
        if (canonicalSchemeChar(cmp[cmpScheme.begin() + i]) !=
 
71
            base[baseScheme.begin() + i])
 
72
            return false;
 
73
    }
 
74
    return true;
 
75
}
 
76
 
 
77
#if OS(WINDOWS)
 
78
// Here, we also allow Windows paths to be represented as "/C:/" so we can be
 
79
// consistent about URL paths beginning with slashes. This function is like
 
80
// DoesBeginWindowsDrivePath except that it also requires a slash at the
 
81
// beginning.
 
82
template<typename CHAR>
 
83
bool doesBeginSlashWindowsDriveSpec(const CHAR* spec, int startOffset, int specLength)
 
84
{
 
85
    if (startOffset >= specLength)
 
86
        return false;
 
87
    return URLParser::isURLSlash(spec[startOffset]) && URLParser::doesBeginWindowsDriveSpec(spec, startOffset + 1, specLength);
 
88
}
 
89
 
 
90
#endif // OS(WINDOWS)
 
91
 
 
92
// See isRelativeURL in the header file for usage.
 
93
template<typename CharacterType>
 
94
bool doIsRelativeURL(const char* base, const URLSegments& baseParsed,
 
95
                     const CharacterType* url, int urlLength,
 
96
                     bool isBaseHierarchical,
 
97
                     bool& isRelative, URLComponent& relativeComponent)
 
98
{
 
99
    isRelative = false; // So we can default later to not relative.
 
100
 
 
101
    // Trim whitespace and construct a new range for the substring.
 
102
    int begin = 0;
 
103
    URLParser::trimURL(url, begin, urlLength);
 
104
    if (begin >= urlLength) {
 
105
        // Empty URLs are relative, but do nothing.
 
106
        relativeComponent = URLComponent(begin, 0);
 
107
        isRelative = true;
 
108
        return true;
 
109
    }
 
110
 
 
111
#if OS(WINDOWS)
 
112
    // We special case paths like "C:\foo" so they can link directly to the
 
113
    // file on Windows (IE compatability). The security domain stuff should
 
114
    // prevent a link like this from actually being followed if its on a
 
115
    // web page.
 
116
    //
 
117
    // We treat "C:/foo" as an absolute URL. We can go ahead and treat "/c:/"
 
118
    // as relative, as this will just replace the path when the base scheme
 
119
    // is a file and the answer will still be correct.
 
120
    //
 
121
    // We require strict backslashes when detecting UNC since two forward
 
122
    // shashes should be treated a a relative URL with a hostname.
 
123
    if (URLParser::doesBeginWindowsDriveSpec(url, begin, urlLength) || URLParser::doesBeginUNCPath(url, begin, urlLength, true))
 
124
        return true;
 
125
#endif // OS(WINDOWS)
 
126
 
 
127
    // See if we've got a scheme, if not, we know this is a relative URL.
 
128
    // BUT: Just because we have a scheme, doesn't make it absolute.
 
129
    // "http:foo.html" is a relative URL with path "foo.html". If the scheme is
 
130
    // empty, we treat it as relative (":foo") like IE does.
 
131
    URLComponent scheme;
 
132
    if (!URLParser::ExtractScheme(url, urlLength, &scheme) || !scheme.length()) {
 
133
        // Don't allow relative URLs if the base scheme doesn't support it.
 
134
        if (!isBaseHierarchical)
 
135
            return false;
 
136
 
 
137
        relativeComponent = URLComponent::fromRange(begin, urlLength);
 
138
        isRelative = true;
 
139
        return true;
 
140
    }
 
141
 
 
142
    // If the scheme isn't valid, then it's relative.
 
143
    int schemeEnd = scheme.end();
 
144
    for (int i = scheme.begin(); i < schemeEnd; i++) {
 
145
        if (!canonicalSchemeChar(url[i])) {
 
146
            relativeComponent = URLComponent::fromRange(begin, urlLength);
 
147
            isRelative = true;
 
148
            return true;
 
149
        }
 
150
    }
 
151
 
 
152
    // If the scheme is not the same, then we can't count it as relative.
 
153
    if (!AreSchemesEqual(base, baseParsed.scheme, url, scheme))
 
154
        return true;
 
155
 
 
156
    // When the scheme that they both share is not hierarchical, treat the
 
157
    // incoming scheme as absolute (this way with the base of "data:foo",
 
158
    // "data:bar" will be reported as absolute.
 
159
    if (!isBaseHierarchical)
 
160
        return true;
 
161
 
 
162
    int colonOffset = scheme.end();
 
163
 
 
164
    // If it's a filesystem URL, the only valid way to make it relative is not to
 
165
    // supply a scheme. There's no equivalent to e.g. http:index.html.
 
166
    if (URLUtilities::CompareSchemeComponent(url, scheme, "filesystem"))
 
167
        return true;
 
168
 
 
169
    // ExtractScheme guarantees that the colon immediately follows what it
 
170
    // considers to be the scheme. countConsecutiveSlashes will handle the
 
171
    // case where the begin offset is the end of the input.
 
172
    int numSlashes = URLParser::countConsecutiveSlashes(url, colonOffset + 1, urlLength);
 
173
 
 
174
    if (!numSlashes || numSlashes == 1) {
 
175
        // No slashes means it's a relative path like "http:foo.html". One slash
 
176
        // is an absolute path. "http:/home/foo.html"
 
177
        isRelative = true;
 
178
        relativeComponent = URLComponent::fromRange(colonOffset + 1, urlLength);
 
179
        return true;
 
180
    }
 
181
 
 
182
    // Two or more slashes after the scheme we treat as absolute.
 
183
    return true;
 
184
}
 
185
 
 
186
// Copies all characters in the range [begin, end) of |spec| to the output,
 
187
// up until and including the last slash. There should be a slash in the
 
188
// range, if not, nothing will be copied.
 
189
//
 
190
// The input is assumed to be canonical, so we search only for exact slashes
 
191
// and not backslashes as well. We also know that it's ASCII.
 
192
void CopyToLastSlash(const char* spec, int begin, int end, URLBuffer<char>& output)
 
193
{
 
194
    // Find the last slash.
 
195
    int lastSlash = -1;
 
196
    for (int i = end - 1; i >= begin; --i) {
 
197
        if (spec[i] == '/') {
 
198
            lastSlash = i;
 
199
            break;
 
200
        }
 
201
    }
 
202
    if (lastSlash < 0)
 
203
        return; // No slash.
 
204
 
 
205
    // Copy.
 
206
    for (int i = begin; i <= lastSlash; ++i)
 
207
        output.append(spec[i]);
 
208
}
 
209
 
 
210
// Copies a single component from the source to the output. This is used
 
211
// when resolving relative URLs and a given component is unchanged. Since the
 
212
// source should already be canonical, we don't have to do anything special,
 
213
// and the input is ASCII.
 
214
void CopyOneComponent(const char* source,
 
215
                      const URLComponent& sourceComponent,
 
216
                      URLBuffer<char>& output,
 
217
                      URLComponent* outputComponent)
 
218
{
 
219
    if (sourceComponent.length() < 0) {
 
220
        // This component is not present.
 
221
        *outputComponent = URLComponent();
 
222
        return;
 
223
    }
 
224
 
 
225
    outputComponent->setBegin(output.length());
 
226
    int sourceEnd = sourceComponent.end();
 
227
    for (int i = sourceComponent.begin(); i < sourceEnd; i++)
 
228
        output.append(source[i]);
 
229
    outputComponent->setLength(output.length() - outputComponent->begin());
 
230
}
 
231
 
 
232
#if OS(WINDOWS)
 
233
 
 
234
// Called on Windows when the base URL is a file URL, this will copy the "C:"
 
235
// to the output, if there is a drive letter and if that drive letter is not
 
236
// being overridden by the relative URL. Otherwise, do nothing.
 
237
//
 
238
// It will return the index of the beginning of the next character in the
 
239
// base to be processed: if there is a "C:", the slash after it, or if
 
240
// there is no drive letter, the slash at the beginning of the path, or
 
241
// the end of the base. This can be used as the starting offset for further
 
242
// path processing.
 
243
template<typename CHAR>
 
244
int CopyBaseDriveSpecIfNecessary(const char* baseURL,
 
245
                                 int basePathBegin,
 
246
                                 int basePathEnd,
 
247
                                 const CHAR* relativeURL,
 
248
                                 int pathStart,
 
249
                                 int relativeUrlLength,
 
250
                                 URLBuffer<char>& output)
 
251
{
 
252
    if (basePathBegin >= basePathEnd)
 
253
        return basePathBegin; // No path.
 
254
 
 
255
    // If the relative begins with a drive spec, don't do anything. The existing
 
256
    // drive spec in the base will be replaced.
 
257
    if (URLParser::doesBeginWindowsDriveSpec(relativeURL,
 
258
                                             pathStart, relativeUrlLength)) {
 
259
        return basePathBegin; // Relative URL path is "C:/foo"
 
260
    }
 
261
 
 
262
    // The path should begin with a slash (as all canonical paths do). We check
 
263
    // if it is followed by a drive letter and copy it.
 
264
    if (doesBeginSlashWindowsDriveSpec(baseURL, basePathBegin, basePathEnd)) {
 
265
        // Copy the two-character drive spec to the output. It will now look like
 
266
        // "file:///C:" so the rest of it can be treated like a standard path.
 
267
        output.append('/');
 
268
        output.append(baseURL[basePathBegin + 1]);
 
269
        output.append(baseURL[basePathBegin + 2]);
 
270
        return basePathBegin + 3;
 
271
    }
 
272
 
 
273
    return basePathBegin;
 
274
}
 
275
 
 
276
#endif // OS(WINDOWS)
 
277
 
 
278
// A subroutine of doResolveRelativeURL, this resolves the URL knowning that
 
279
// the input is a relative path or less (qyuery or ref).
 
280
template<typename CHAR>
 
281
bool doResolveRelativePath(const char* baseURL,
 
282
                           const URLSegments& baseParsed,
 
283
                           bool /* baseIsFile */,
 
284
                           const CHAR* relativeURL,
 
285
                           const URLComponent& relativeComponent,
 
286
                           URLQueryCharsetConverter* queryConverter,
 
287
                           URLBuffer<char>& output,
 
288
                           URLSegments* outputParsed)
 
289
{
 
290
    bool success = true;
 
291
 
 
292
    // We know the authority section didn't change, copy it to the output. We
 
293
    // also know we have a path so can copy up to there.
 
294
    URLComponent path, query, ref;
 
295
    URLParser::parsePathInternal(relativeURL,
 
296
                                 relativeComponent,
 
297
                                 &path,
 
298
                                 &query,
 
299
                                 &ref);
 
300
    // Canonical URLs always have a path, so we can use that offset.
 
301
    output.append(baseURL, baseParsed.path.begin());
 
302
 
 
303
    if (path.length() > 0) {
 
304
        // The path is replaced or modified.
 
305
        int truePathBegin = output.length();
 
306
 
 
307
        // For file: URLs on Windows, we don't want to treat the drive letter and
 
308
        // colon as part of the path for relative file resolution when the
 
309
        // incoming URL does not provide a drive spec. We save the true path
 
310
        // beginning so we can fix it up after we are done.
 
311
        int basePathBegin = baseParsed.path.begin();
 
312
#if OS(WINDOWS)
 
313
        if (baseIsFile) {
 
314
            basePathBegin = CopyBaseDriveSpecIfNecessary(baseURL, baseParsed.path.begin(), baseParsed.path.end(),
 
315
                                                         relativeURL, relativeComponent.begin(), relativeComponent.end(),
 
316
                                                         output);
 
317
            // Now the output looks like either "file://" or "file:///C:"
 
318
            // and we can start appending the rest of the path. |basePathBegin|
 
319
            // points to the character in the base that comes next.
 
320
        }
 
321
#endif // OS(WINDOWS)
 
322
 
 
323
        if (URLParser::isURLSlash(relativeURL[path.begin()])) {
 
324
            // Easy case: the path is an absolute path on the server, so we can
 
325
            // just replace everything from the path on with the new versions.
 
326
            // Since the input should be canonical hierarchical URL, we should
 
327
            // always have a path.
 
328
            success &= CanonicalizePath(relativeURL, path,
 
329
                                        output, &outputParsed->path);
 
330
        } else {
 
331
            // Relative path, replace the query, and reference. We take the
 
332
            // original path with the file part stripped, and append the new path.
 
333
            // The canonicalizer will take care of resolving ".." and "."
 
334
            int pathBegin = output.length();
 
335
            CopyToLastSlash(baseURL, basePathBegin, baseParsed.path.end(),
 
336
                            output);
 
337
            success &= CanonicalizePartialPath(relativeURL, path, pathBegin,
 
338
                                               output);
 
339
            outputParsed->path = URLComponent::fromRange(pathBegin, output.length());
 
340
 
 
341
            // Copy the rest of the stuff after the path from the relative path.
 
342
        }
 
343
 
 
344
        // Finish with the query and reference part (these can't fail).
 
345
        CanonicalizeQuery(relativeURL, query, queryConverter, output, &outputParsed->query);
 
346
        canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment);
 
347
 
 
348
        // Fix the path beginning to add back the "C:" we may have written above.
 
349
        outputParsed->path = URLComponent::fromRange(truePathBegin,
 
350
                                                     outputParsed->path.end());
 
351
        return success;
 
352
    }
 
353
 
 
354
    // If we get here, the path is unchanged: copy to output.
 
355
    CopyOneComponent(baseURL, baseParsed.path, output, &outputParsed->path);
 
356
 
 
357
    if (query.isValid()) {
 
358
        // Just the query specified, replace the query and reference (ignore
 
359
        // failures for refs)
 
360
        CanonicalizeQuery(relativeURL, query, queryConverter,
 
361
                          output, &outputParsed->query);
 
362
        canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment);
 
363
        return success;
 
364
    }
 
365
 
 
366
    // If we get here, the query is unchanged: copy to output. Note that the
 
367
    // range of the query parameter doesn't include the question mark, so we
 
368
    // have to add it manually if there is a component.
 
369
    if (baseParsed.query.isValid())
 
370
        output.append('?');
 
371
    CopyOneComponent(baseURL, baseParsed.query, output, &outputParsed->query);
 
372
 
 
373
    if (ref.isValid()) {
 
374
        // Just the reference specified: replace it (ignoring failures).
 
375
        canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment);
 
376
        return success;
 
377
    }
 
378
 
 
379
    // We should always have something to do in this function, the caller checks
 
380
    // that some component is being replaced.
 
381
    ASSERT_NOT_REACHED();
 
382
    return success;
 
383
}
 
384
 
 
385
// Resolves a relative URL that contains a host. Typically, these will
 
386
// be of the form "//www.apple.com/foo/bar?baz#fragment" and the only thing which
 
387
// should be kept from the original URL is the scheme.
 
388
template<typename CHAR>
 
389
bool doResolveRelativeHost(const char* baseURL,
 
390
                           const URLSegments& baseParsed,
 
391
                           const CHAR* relativeURL,
 
392
                           const URLComponent& relativeComponent,
 
393
                           URLQueryCharsetConverter* queryConverter,
 
394
                           URLBuffer<char>& output,
 
395
                           URLSegments* outputParsed)
 
396
{
 
397
    // Parse the relative URL, just like we would for anything following a
 
398
    // scheme.
 
399
    URLSegments relativeParsed; // Everything but the scheme is valid.
 
400
    URLParser::parseAfterScheme(&relativeURL[relativeComponent.begin()],
 
401
                                relativeComponent.length(), relativeComponent.begin(),
 
402
                                relativeParsed);
 
403
 
 
404
    // Now we can just use the replacement function to replace all the necessary
 
405
    // parts of the old URL with the new one.
 
406
    Replacements<CHAR> replacements;
 
407
    replacements.SetUsername(relativeURL, relativeParsed.username);
 
408
    replacements.SetPassword(relativeURL, relativeParsed.password);
 
409
    replacements.SetHost(relativeURL, relativeParsed.host);
 
410
    replacements.SetPort(relativeURL, relativeParsed.port);
 
411
    replacements.SetPath(relativeURL, relativeParsed.path);
 
412
    replacements.SetQuery(relativeURL, relativeParsed.query);
 
413
    replacements.SetRef(relativeURL, relativeParsed.fragment);
 
414
 
 
415
    return ReplaceStandardURL(baseURL, baseParsed, replacements,
 
416
                              queryConverter, output, outputParsed);
 
417
}
 
418
 
 
419
// Resolves a relative URL that happens to be an absolute file path. Examples
 
420
// include: "//hostname/path", "/c:/foo", and "//hostname/c:/foo".
 
421
template<typename CharacterType>
 
422
bool doResolveAbsoluteFile(const CharacterType* relativeURL,
 
423
                           const URLComponent& relativeComponent,
 
424
                           URLQueryCharsetConverter* queryConverter,
 
425
                           URLBuffer<char>& output,
 
426
                           URLSegments& outputParsed)
 
427
{
 
428
    // Parse the file URL. The file URl parsing function uses the same logic
 
429
    // as we do for determining if the file is absolute, in which case it will
 
430
    // not bother to look for a scheme.
 
431
    URLSegments relativeParsed;
 
432
    URLParser::ParseFileURL(&relativeURL[relativeComponent.begin()],
 
433
                            relativeComponent.length(), &relativeParsed);
 
434
 
 
435
    return CanonicalizeFileURL(&relativeURL[relativeComponent.begin()],
 
436
                               relativeComponent.length(), relativeParsed,
 
437
                               queryConverter, output, &outputParsed);
 
438
}
 
439
 
 
440
// TODO(brettw) treat two slashes as root like Mozilla for FTP?
 
441
template<typename CHAR>
 
442
bool doResolveRelativeURL(const char* baseURL,
 
443
                          const URLSegments& baseParsed,
 
444
                          bool baseIsFile,
 
445
                          const CHAR* relativeURL,
 
446
                          const URLComponent& relativeComponent,
 
447
                          URLQueryCharsetConverter* queryConverter,
 
448
                          URLBuffer<char>& output,
 
449
                          URLSegments* outputParsed)
 
450
{
 
451
    // Starting point for our output parsed. We'll fix what we change.
 
452
    *outputParsed = baseParsed;
 
453
 
 
454
    // Sanity check: the input should have a host or we'll break badly below.
 
455
    // We can only resolve relative URLs with base URLs that have hosts and
 
456
    // paths (even the default path of "/" is OK).
 
457
    //
 
458
    // We allow hosts with no length so we can handle file URLs, for example.
 
459
    if (baseParsed.path.length() <= 0) {
 
460
        // On error, return the input (resolving a relative URL on a non-relative
 
461
        // base = the base).
 
462
        int baseLength = baseParsed.length();
 
463
        for (int i = 0; i < baseLength; i++)
 
464
            output.append(baseURL[i]);
 
465
        return false;
 
466
    }
 
467
 
 
468
    if (relativeComponent.length() <= 0) {
 
469
        // Empty relative URL, leave unchanged, only removing the ref component.
 
470
        int baseLength = baseParsed.length();
 
471
        baseLength -= baseParsed.fragment.length() + 1;
 
472
        outputParsed->fragment.reset();
 
473
        output.append(baseURL, baseLength);
 
474
        return true;
 
475
    }
 
476
 
 
477
    int numSlashes = URLParser::countConsecutiveSlashes(relativeURL, relativeComponent.begin(), relativeComponent.end());
 
478
 
 
479
#if OS(WINDOWS)
 
480
    // On Windows, two slashes for a file path (regardless of which direction
 
481
    // they are) means that it's UNC. Two backslashes on any base scheme mean
 
482
    // that it's an absolute UNC path (we use the baseIsFile flag to control
 
483
    // how strict the UNC finder is).
 
484
    //
 
485
    // We also allow Windows absolute drive specs on any scheme (for example
 
486
    // "c:\foo") like IE does. There must be no preceeding slashes in this
 
487
    // case (we reject anything like "/c:/foo") because that should be treated
 
488
    // as a path. For file URLs, we allow any number of slashes since that would
 
489
    // be setting the path.
 
490
    //
 
491
    // This assumes the absolute path resolver handles absolute URLs like this
 
492
    // properly. URLUtilities::DoCanonicalize does this.
 
493
    int afterSlashes = relativeComponent.begin + numSlashes;
 
494
    if (URLParser::doesBeginUNCPath(relativeURL, relativeComponent.begin(), relativeComponent.end(), !baseIsFile)
 
495
        || ((!numSlashes || baseIsFile) && URLParser::doesBeginWindowsDriveSpec(relativeURL, afterSlashes, relativeComponent.end()))) {
 
496
             return doResolveAbsoluteFile(relativeURL, relativeComponent,
 
497
                                          queryConverter, output, *outputParsed);
 
498
         }
 
499
#else
 
500
    // Other platforms need explicit handling for file: URLs with multiple
 
501
    // slashes because the generic scheme parsing always extracts a host, but a
 
502
    // file: URL only has a host if it has exactly 2 slashes. This also
 
503
    // handles the special case where the URL is only slashes, since that
 
504
    // doesn't have a host part either.
 
505
    if (baseIsFile && (numSlashes > 2 || numSlashes == relativeComponent.length())) {
 
506
        return doResolveAbsoluteFile(relativeURL, relativeComponent,
 
507
                                     queryConverter, output, *outputParsed);
 
508
    }
 
509
#endif
 
510
 
 
511
    // Any other double-slashes mean that this is relative to the scheme.
 
512
    if (numSlashes >= 2) {
 
513
        return doResolveRelativeHost(baseURL, baseParsed,
 
514
                                     relativeURL, relativeComponent,
 
515
                                     queryConverter, output, outputParsed);
 
516
    }
 
517
 
 
518
    // When we get here, we know that the relative URL is on the same host.
 
519
    return doResolveRelativePath(baseURL, baseParsed, baseIsFile,
 
520
                                 relativeURL, relativeComponent,
 
521
                                 queryConverter, output, outputParsed);
 
522
}
 
523
 
 
524
} // namespace
 
525
 
 
526
bool isRelativeURL(const char* base, const URLSegments& baseParsed,
 
527
                   const char* fragment, int fragmentLength,
 
528
                   bool isBaseHierarchical,
 
529
                   bool& isRelative, URLComponent& relativeComponent)
 
530
{
 
531
    return doIsRelativeURL<char>(base, baseParsed, fragment, fragmentLength, isBaseHierarchical, isRelative, relativeComponent);
 
532
}
 
533
 
 
534
bool isRelativeURL(const char* base, const URLSegments& baseParsed,
 
535
                   const UChar* fragment, int fragmentLength,
 
536
                   bool isBaseHierarchical,
 
537
                   bool& isRelative, URLComponent& relativeComponent)
 
538
{
 
539
    return doIsRelativeURL<UChar>(base, baseParsed, fragment, fragmentLength, isBaseHierarchical, isRelative, relativeComponent);
 
540
}
 
541
 
 
542
bool resolveRelativeURL(const char* baseURL,
 
543
                        const URLSegments& baseParsed,
 
544
                        bool baseIsFile,
 
545
                        const char* relativeURL,
 
546
                        const URLComponent& relativeComponent,
 
547
                        URLQueryCharsetConverter* queryConverter,
 
548
                        URLBuffer<char>& output,
 
549
                        URLSegments* outputParsed)
 
550
{
 
551
    return doResolveRelativeURL<char>(baseURL, baseParsed, baseIsFile, relativeURL,
 
552
                                      relativeComponent, queryConverter, output, outputParsed);
 
553
}
 
554
 
 
555
bool resolveRelativeURL(const char* baseURL,
 
556
                        const URLSegments& baseParsed,
 
557
                        bool baseIsFile,
 
558
                        const UChar* relativeURL,
 
559
                        const URLComponent& relativeComponent,
 
560
                        URLQueryCharsetConverter* queryConverter,
 
561
                        URLBuffer<char>& output,
 
562
                        URLSegments* outputParsed)
 
563
{
 
564
    return doResolveRelativeURL<UChar>(baseURL, baseParsed, baseIsFile, relativeURL,
 
565
                                       relativeComponent, queryConverter, output, outputParsed);
 
566
}
 
567
 
 
568
} // namespace URLCanonicalizer
 
569
 
 
570
} // namespace WTF
 
571
 
 
572
#endif // USE(WTFURL)