18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "KURL.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextEncoding.h" 31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h> 32d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <wtf/HashMap.h> 332bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/HexNumber.h> 34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h> 35f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include <wtf/text/StringHash.h> 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if USE(ICU_UNICODE) 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <unicode/uidna.h> 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#elif USE(QT4_UNICODE) 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <QUrl> 41d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(GLIB_UNICODE) 42d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <glib.h> 43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GOwnPtr.h" 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdio.h> 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std; 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF; 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef Vector<char, 512> CharBuffer; 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef Vector<UChar, 512> UCharBuffer; 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic const unsigned maximumValidPortNumber = 0xFFFE; 5781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic const unsigned invalidPortNumber = 0xFFFF; 5881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 5981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#if !USE(GOOGLEURL) 6081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: This file makes too much use of the + operator on String. 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// We either have to optimize that operator so it doesn't involve 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// so many allocations, or change this to use Vector<UChar> instead. 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectenum URLCharacterClasses { 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // alpha 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SchemeFirstChar = 1 << 0, 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ( alpha | digit | "+" | "-" | "." ) 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SchemeChar = 1 << 1, 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // unreserved = alphanum | mark 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ( unreserved | escaped | ";" | ":" | "&" | "=" | "+" | "$" | "," ) 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UserInfoChar = 1 << 2, 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // alnum | "." | "-" | "%" 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The above is what the specification says, but we are lenient to 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // match existing practice and also allow: 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // "_" 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HostnameChar = 1 << 3, 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // hexdigit | ":" | "%" 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project IPv6Char = 1 << 4, 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // "#" | "?" | "/" | nul 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project PathSegmentEndChar = 1 << 5, 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // not allowed in path 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BadChar = 1 << 6 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const unsigned char characterClassTable[256] = { 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 0 nul */ PathSegmentEndChar, /* 1 soh */ BadChar, 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 2 stx */ BadChar, /* 3 etx */ BadChar, 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 4 eot */ BadChar, /* 5 enq */ BadChar, /* 6 ack */ BadChar, /* 7 bel */ BadChar, 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 8 bs */ BadChar, /* 9 ht */ BadChar, /* 10 nl */ BadChar, /* 11 vt */ BadChar, 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 12 np */ BadChar, /* 13 cr */ BadChar, /* 14 so */ BadChar, /* 15 si */ BadChar, 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 16 dle */ BadChar, /* 17 dc1 */ BadChar, /* 18 dc2 */ BadChar, /* 19 dc3 */ BadChar, 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 20 dc4 */ BadChar, /* 21 nak */ BadChar, /* 22 syn */ BadChar, /* 23 etb */ BadChar, 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 24 can */ BadChar, /* 25 em */ BadChar, /* 26 sub */ BadChar, /* 27 esc */ BadChar, 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 28 fs */ BadChar, /* 29 gs */ BadChar, /* 30 rs */ BadChar, /* 31 us */ BadChar, 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 32 sp */ BadChar, /* 33 ! */ UserInfoChar, 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 34 " */ BadChar, /* 35 # */ PathSegmentEndChar | BadChar, 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 36 $ */ UserInfoChar, /* 37 % */ UserInfoChar | HostnameChar | IPv6Char | BadChar, 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 38 & */ UserInfoChar, /* 39 ' */ UserInfoChar, 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 40 ( */ UserInfoChar, /* 41 ) */ UserInfoChar, 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 42 * */ UserInfoChar, /* 43 + */ SchemeChar | UserInfoChar, 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 44 , */ UserInfoChar, 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 45 - */ SchemeChar | UserInfoChar | HostnameChar, 111643ca7872b450ea4efacab6188849e5aac2ba161Steve Block /* 46 . */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 47 / */ PathSegmentEndChar, 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 48 0 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 49 1 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 50 2 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 51 3 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 52 4 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 53 5 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 54 6 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 55 7 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 56 8 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 57 9 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 58 : */ UserInfoChar | IPv6Char, /* 59 ; */ UserInfoChar, 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 60 < */ BadChar, /* 61 = */ UserInfoChar, 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 62 > */ BadChar, /* 63 ? */ PathSegmentEndChar | BadChar, 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 64 @ */ 0, 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 65 A */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 66 B */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 67 C */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 68 D */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 69 E */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 70 F */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 71 G */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 72 H */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 73 I */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 74 J */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 75 K */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 76 L */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 77 M */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 78 N */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 79 O */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 80 P */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 81 Q */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 82 R */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 83 S */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 84 T */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 85 U */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 86 V */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 87 W */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 88 X */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 89 Y */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 90 Z */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 91 [ */ 0, 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 92 \ */ 0, /* 93 ] */ 0, 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 94 ^ */ 0, 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 95 _ */ UserInfoChar | HostnameChar, 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 96 ` */ 0, 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 97 a */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 98 b */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 99 c */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 100 d */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 101 e */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 102 f */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 103 g */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 104 h */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 105 i */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 106 j */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 107 k */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 108 l */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 109 m */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 110 n */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 111 o */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 112 p */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 113 q */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 114 r */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 115 s */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 116 t */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 117 u */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 118 v */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 119 w */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 120 x */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 121 y */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 122 z */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 123 { */ 0, 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 124 | */ 0, /* 125 } */ 0, /* 126 ~ */ UserInfoChar, /* 127 del */ BadChar, 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 128 */ BadChar, /* 129 */ BadChar, /* 130 */ BadChar, /* 131 */ BadChar, 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 132 */ BadChar, /* 133 */ BadChar, /* 134 */ BadChar, /* 135 */ BadChar, 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 136 */ BadChar, /* 137 */ BadChar, /* 138 */ BadChar, /* 139 */ BadChar, 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 140 */ BadChar, /* 141 */ BadChar, /* 142 */ BadChar, /* 143 */ BadChar, 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 144 */ BadChar, /* 145 */ BadChar, /* 146 */ BadChar, /* 147 */ BadChar, 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 148 */ BadChar, /* 149 */ BadChar, /* 150 */ BadChar, /* 151 */ BadChar, 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 152 */ BadChar, /* 153 */ BadChar, /* 154 */ BadChar, /* 155 */ BadChar, 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 156 */ BadChar, /* 157 */ BadChar, /* 158 */ BadChar, /* 159 */ BadChar, 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 160 */ BadChar, /* 161 */ BadChar, /* 162 */ BadChar, /* 163 */ BadChar, 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 164 */ BadChar, /* 165 */ BadChar, /* 166 */ BadChar, /* 167 */ BadChar, 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 168 */ BadChar, /* 169 */ BadChar, /* 170 */ BadChar, /* 171 */ BadChar, 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 172 */ BadChar, /* 173 */ BadChar, /* 174 */ BadChar, /* 175 */ BadChar, 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 176 */ BadChar, /* 177 */ BadChar, /* 178 */ BadChar, /* 179 */ BadChar, 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 180 */ BadChar, /* 181 */ BadChar, /* 182 */ BadChar, /* 183 */ BadChar, 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 184 */ BadChar, /* 185 */ BadChar, /* 186 */ BadChar, /* 187 */ BadChar, 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 188 */ BadChar, /* 189 */ BadChar, /* 190 */ BadChar, /* 191 */ BadChar, 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 192 */ BadChar, /* 193 */ BadChar, /* 194 */ BadChar, /* 195 */ BadChar, 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 196 */ BadChar, /* 197 */ BadChar, /* 198 */ BadChar, /* 199 */ BadChar, 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 200 */ BadChar, /* 201 */ BadChar, /* 202 */ BadChar, /* 203 */ BadChar, 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 204 */ BadChar, /* 205 */ BadChar, /* 206 */ BadChar, /* 207 */ BadChar, 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 208 */ BadChar, /* 209 */ BadChar, /* 210 */ BadChar, /* 211 */ BadChar, 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 212 */ BadChar, /* 213 */ BadChar, /* 214 */ BadChar, /* 215 */ BadChar, 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 216 */ BadChar, /* 217 */ BadChar, /* 218 */ BadChar, /* 219 */ BadChar, 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 220 */ BadChar, /* 221 */ BadChar, /* 222 */ BadChar, /* 223 */ BadChar, 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 224 */ BadChar, /* 225 */ BadChar, /* 226 */ BadChar, /* 227 */ BadChar, 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 228 */ BadChar, /* 229 */ BadChar, /* 230 */ BadChar, /* 231 */ BadChar, 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 232 */ BadChar, /* 233 */ BadChar, /* 234 */ BadChar, /* 235 */ BadChar, 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 236 */ BadChar, /* 237 */ BadChar, /* 238 */ BadChar, /* 239 */ BadChar, 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 240 */ BadChar, /* 241 */ BadChar, /* 242 */ BadChar, /* 243 */ BadChar, 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 244 */ BadChar, /* 245 */ BadChar, /* 246 */ BadChar, /* 247 */ BadChar, 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 248 */ BadChar, /* 249 */ BadChar, /* 250 */ BadChar, /* 251 */ BadChar, 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 252 */ BadChar, /* 253 */ BadChar, /* 254 */ BadChar, /* 255 */ BadChar 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd); 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void encodeRelativeString(const String& rel, const TextEncoding&, CharBuffer& ouput); 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic String substituteBackslashes(const String&); 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeFirstChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & SchemeFirstChar; } 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeFirstChar(UChar c) { return c <= 0xff && (characterClassTable[c] & SchemeFirstChar); } 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & SchemeChar; } 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeChar(UChar c) { return c <= 0xff && (characterClassTable[c] & SchemeChar); } 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isUserInfoChar(unsigned char c) { return characterClassTable[c] & UserInfoChar; } 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isHostnameChar(unsigned char c) { return characterClassTable[c] & HostnameChar; } 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isIPv6Char(unsigned char c) { return characterClassTable[c] & IPv6Char; } 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isPathSegmentEndChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & PathSegmentEndChar; } 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isPathSegmentEndChar(UChar c) { return c <= 0xff && (characterClassTable[c] & PathSegmentEndChar); } 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isBadChar(unsigned char c) { return characterClassTable[c] & BadChar; } 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline int hexDigitValue(UChar c) 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(isASCIIHexDigit(c)); 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c < 'A') 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c - '0'; 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return (c - 'A' + 10) & 0xF; // handle both upper and lower case without a branch 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Copies the source to the destination, assuming all the source characters are 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ASCII. The destination buffer must be large enough. Null characters are allowed 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in the source string, and no attempt is made to null-terminate the result. 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void copyASCII(const UChar* src, int length, char* dest) 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < length; i++) 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dest[i] = static_cast<char>(src[i]); 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void appendASCII(const String& base, const char* rel, size_t len, CharBuffer& buffer) 253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer.resize(base.length() + len + 1); 255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project copyASCII(base.characters(), base.length(), buffer.data()); 256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project memcpy(buffer.data() + base.length(), rel, len); 257635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer[buffer.size() - 1] = '\0'; 258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 259635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Move to PlatformString.h eventually. 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns the index of the first index in string |s| of any of the characters 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in |toFind|. |toFind| should be a null-terminated string, all characters up 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// to the null will be searched. Returns int if not found. 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic int findFirstOf(const UChar* s, int sLen, int startPos, const char* toFind) 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = startPos; i < sLen; i++) { 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* cur = toFind; 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (*cur) { 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (s[i] == *(cur++)) 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return i; 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return -1; 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 276635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 277635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void checkEncodedString(const String& url) 278635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 279635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (unsigned i = 0; i < url.length(); ++i) 280635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!(url[i] & ~0x7F)); 281635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 282635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!url.length() || isSchemeFirstChar(url[0])); 283635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 284635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else 285635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void checkEncodedString(const String&) 286635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 287635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline bool KURL::protocolIs(const String& string, const char* protocol) 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return WebCore::protocolIs(string, protocol); 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::invalidate() 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isValid = false; 2988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_protocolInHTTPFamily = false; 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_schemeEnd = 0; 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userStart = 0; 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userEnd = 0; 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_passwordEnd = 0; 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_hostEnd = 0; 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_portEnd = 0; 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathEnd = 0; 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathAfterLastSlash = 0; 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_queryEnd = 0; 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_fragmentEnd = 0; 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 311231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockKURL::KURL(ParsedURLStringTag, const char* url) 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(url, 0); 314635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(url == m_string); 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 317231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockKURL::KURL(ParsedURLStringTag, const String& url) 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 319635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(url); 320635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(url == m_string); 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3232fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockKURL::KURL(ParsedURLStringTag, const URLString& url) 3242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 3252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block parse(url.string()); 3262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(url.string() == m_string); 3272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 3282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectKURL::KURL(const KURL& base, const String& relative) 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project init(base, relative, UTF8Encoding()); 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectKURL::KURL(const KURL& base, const String& relative, const TextEncoding& encoding) 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 336635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // For UTF-{7,16,32}, we want to use UTF-8 for the query part as 337635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // we do when submitting a form. A form with GET method 338635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // has its contents added to a URL as query params and it makes sense 339635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to be consistent. 340635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project init(base, relative, encoding.encodingForFormSubmission()); 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 34381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic bool shouldTrimFromURL(unsigned char c) 34481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 34581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Browsers ignore leading/trailing whitespace and control 34681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // characters from URLs. Note that c is an *unsigned* char here 34781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // so this comparison should only catch control characters. 34881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return c <= ' '; 34981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 35081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::init(const KURL& base, const String& relative, const TextEncoding& encoding) 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Allow resolutions with a null or empty base URL, but not with any other invalid one. 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Is this a good rule? 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!base.m_isValid && !base.isEmpty()) { 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = relative; 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For compatibility with Win IE, treat backslashes as if they were slashes, 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // as long as we're not dealing with javascript: or data: URLs. 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String rel = relative; 3645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (rel.contains('\\') && !(protocolIsJavaScript(rel) || protocolIs(rel, "data"))) 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project rel = substituteBackslashes(rel); 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String* originalString = &rel; 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool allASCII = charactersAreAllASCII(rel.characters(), rel.length()); 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer strBuffer; 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* str; 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t len; 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (allASCII) { 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project len = rel.length(); 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strBuffer.resize(len + 1); 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project copyASCII(rel.characters(), len, strBuffer.data()); 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strBuffer[len] = 0; 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str = strBuffer.data(); 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project encodeRelativeString(rel, encoding, strBuffer); 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str = strBuffer.data(); 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project len = strlen(str); 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 38681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Get rid of leading whitespace and control characters. 38781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch while (len && shouldTrimFromURL(*str)) { 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str++; 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project --len; 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 39381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Get rid of trailing whitespace and control characters. 39481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch while (len && shouldTrimFromURL(str[len - 1])) { 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str[--len] = '\0'; 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // According to the RFC, the reference should be interpreted as an 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // absolute URI if possible, using the "leftmost, longest" 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // algorithm. If the URI reference is absolute it will have a 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // scheme, meaning that it will have a colon before the first 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // non-scheme element. 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool absolute = false; 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = str; 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isSchemeFirstChar(*p)) { 4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isSchemeChar(*p)) { 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (*p == ':') { 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p[1] != '/' && equalIgnoringCase(base.protocol(), String(str, p - str)) && base.isHierarchical()) { 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str = p + 1; 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project absolute = true; 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 420635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CharBuffer parseBuffer; 421635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (absolute) { 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(str, originalString); 4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If the base is empty or opaque (e.g. data: or javascript:), then the URL is invalid 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // unless the relative URL is a single fragment. 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!base.isHierarchical()) { 428635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (str[0] == '#') { 429635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer); 430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 431635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = relative; 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (str[0]) { 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project case '\0': 4405e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block // The reference is empty, so this is a reference to the same document with any fragment identifier removed. 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *this = base; 4425e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block removeFragmentIdentifier(); 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 444635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project case '#': { 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // must be fragment-only reference 446635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer); 447635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 449635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 450635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project case '?': { 4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // query-only reference, special case needed for non-URL results 452635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_pathEnd), str, len, parseBuffer); 453635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 455635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project case '/': 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // must be net-path or absolute-path reference 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (str[1] == '/') { 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // net-path 460635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_schemeEnd + 1), str, len, parseBuffer); 461635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // abs-path 464635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_portEnd), str, len, parseBuffer); 465635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project default: 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // must be relative-path reference 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Base part plus relative part plus one possible slash added in between plus terminating \0 byte. 473635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parseBuffer.resize(base.m_pathEnd + 1 + len + 1); 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 475635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project char* bufferPos = parseBuffer.data(); 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // first copy everything before the path from the base 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned baseLength = base.m_string.length(); 4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* baseCharacters = base.m_string.characters(); 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer baseStringBuffer(baseLength); 481635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project copyASCII(baseCharacters, baseLength, baseStringBuffer.data()); 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseString = baseStringBuffer.data(); 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringStart = baseString; 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* pathStart = baseStringStart + base.m_portEnd; 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (baseStringStart < pathStart) 4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *bufferPos++ = *baseStringStart++; 4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* bufferPathStart = bufferPos; 4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // now copy the base path 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringEnd = baseString + base.m_pathEnd; 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // go back to the last slash 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (baseStringEnd > baseStringStart && baseStringEnd[-1] != '/') 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringEnd--; 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (baseStringEnd == baseStringStart) { 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // no path in base, add a path separator if necessary 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (base.m_schemeEnd + 1 != base.m_pathEnd && *str && *str != '?' && *str != '#') 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *bufferPos++ = '/'; 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos += copyPathRemovingDots(bufferPos, baseStringStart, 0, baseStringEnd - baseStringStart); 5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* relStringStart = str; 5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* relStringPos = relStringStart; 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (*relStringPos && *relStringPos != '?' && *relStringPos != '#') { 5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (relStringPos[0] == '.' && bufferPos[-1] == '/') { 5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isPathSegmentEndChar(relStringPos[1])) { 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over "." segment 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos += 1; 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (relStringPos[0] == '/') 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos++; 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (relStringPos[1] == '.' && isPathSegmentEndChar(relStringPos[2])) { 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over ".." segment and rewind the last segment 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the RFC leaves it up to the app to decide what to do with excess 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ".." segments - we choose to drop them since some web content 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // relies on this. 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos += 2; 5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (relStringPos[0] == '/') 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos++; 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (bufferPos > bufferPathStart + 1) 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos--; 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (bufferPos > bufferPathStart + 1 && bufferPos[-1] != '/') 5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos--; 5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *bufferPos = *relStringPos; 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos++; 5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos++; 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // all done with the path work, now copy any remainder 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // of the relative reference; this will also add a null terminator 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strcpy(bufferPos, relStringPos); 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 540635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 542635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(strlen(parseBuffer.data()) + 1 <= parseBuffer.size()); 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 549635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectKURL KURL::copy() const 550635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 551635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project KURL result = *this; 552231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block result.m_string = result.m_string.crossThreadString(); 553635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return result; 554635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 555635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool KURL::hasPath() const 5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_pathEnd != m_portEnd; 5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::lastPathComponent() const 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!hasPath()) 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 566f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned end = m_pathEnd - 1; 5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_string[end] == '/') 5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project --end; 5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 570f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t start = m_string.reverseFind('/', end); 571f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (start < static_cast<unsigned>(m_portEnd)) 5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++start; 5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string.substring(start, end - start + 1); 5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::protocol() const 5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string.left(m_schemeEnd); 5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::host() const 5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int start = hostStart(); 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(m_string.substring(start, m_hostEnd - start)); 5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectunsigned short KURL::port() const 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 591dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We return a port of 0 if there is no port specified. This can happen in two situations: 592dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 1) The URL contains no colon after the host name and before the path component of the URL. 593dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 2) The URL contains a colon but there's no port number before the path component of the URL begins. 594dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_hostEnd == m_portEnd || m_hostEnd == m_portEnd - 1) 5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 597dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block const UChar* stringData = m_string.characters(); 598dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block bool ok = false; 599dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block unsigned number = charactersToUIntStrict(stringData + m_hostEnd + 1, m_portEnd - m_hostEnd - 1, &ok); 600dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!ok || number > maximumValidPortNumber) 601dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return invalidPortNumber; 6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return number; 6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::pass() const 6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_passwordEnd == m_userEnd) 6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(m_string.substring(m_userEnd + 1, m_passwordEnd - m_userEnd - 1)); 6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::user() const 6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(m_string.substring(m_userStart, m_userEnd - m_userStart)); 6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochString KURL::fragmentIdentifier() const 6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_fragmentEnd == m_queryEnd) 6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string.substring(m_queryEnd + 1, m_fragmentEnd - (m_queryEnd + 1)); 6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool KURL::hasFragmentIdentifier() const 6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_fragmentEnd != m_queryEnd; 6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 631a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid KURL::copyParsedQueryTo(ParsedURLParameters& parameters) const 632a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 633a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* pos = m_string.characters() + m_pathEnd + 1; 634a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* end = m_string.characters() + m_queryEnd; 635a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch while (pos < end) { 636a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* parameterStart = pos; 637a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch while (pos < end && *pos != '&') 638a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++pos; 639a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* parameterEnd = pos; 640a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (pos < end) { 641a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(*pos == '&'); 642a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++pos; 643a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 644a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (parameterStart == parameterEnd) 645a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch continue; 646a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* nameStart = parameterStart; 647a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* equalSign = parameterStart; 648a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch while (equalSign < parameterEnd && *equalSign != '=') 649a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++equalSign; 650a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (equalSign == nameStart) 651a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch continue; 652a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch String name(nameStart, equalSign - nameStart); 653a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch String value = equalSign == parameterEnd ? String() : String(equalSign + 1, parameterEnd - equalSign - 1); 654a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch parameters.set(name, value); 655a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 656a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 657a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 6588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianString KURL::baseAsString() const 6598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 6608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return m_string.left(m_pathAfterLastSlash); 6618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 6628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 663635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifdef NDEBUG 664635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 665635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void assertProtocolIsGood(const char*) 666635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 667635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 668635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 669635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else 670635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 671635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void assertProtocolIsGood(const char* protocol) 6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* p = protocol; 6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (*p) { 6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(*p > ' ' && *p < 0x7F && !(*p >= 'A' && *p <= 'Z')); 6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 680635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 681635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool KURL::protocolIs(const char* protocol) const 6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project assertProtocolIsGood(protocol); 6855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // JavaScript URLs are "valid" and should be executed even if KURL decides they are invalid. 6875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The free function protocolIsJavaScript() should be used instead. 688643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(!equalIgnoringCase(protocol, String("javascript"))); 6895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Do the comparison without making a new string object. 6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < m_schemeEnd; ++i) { 6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!protocol[i] || toASCIILower(m_string[i]) != protocol[i]) 6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return !protocol[m_schemeEnd]; // We should have consumed all characters in the argument. 6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::query() const 7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_queryEnd == m_pathEnd) 7048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return String(); 7058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return m_string.substring(m_pathEnd + 1, m_queryEnd - (m_pathEnd + 1)); 7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::path() const 7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 711e48d279609693b4d164199748c93ad791547c649Steve Block return m_string.substring(m_portEnd, m_pathEnd - m_portEnd); 7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 714d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool KURL::setProtocol(const String& s) 7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 716d0825bca7fe65beaee391d30da42e937db621564Steve Block // Firefox and IE remove everything after the first ':'. 717f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t separatorPosition = s.find(':'); 718d0825bca7fe65beaee391d30da42e937db621564Steve Block String newProtocol = s.substring(0, separatorPosition); 719d0825bca7fe65beaee391d30da42e937db621564Steve Block 720d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!isValidProtocol(newProtocol)) 721d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 722635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) { 724d0825bca7fe65beaee391d30da42e937db621564Steve Block parse(newProtocol + ":" + m_string); 725d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 728d0825bca7fe65beaee391d30da42e937db621564Steve Block parse(newProtocol + m_string.substring(m_schemeEnd)); 729d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setHost(const String& s) 7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 737635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 738635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just the host. 739635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool slashSlashNeeded = m_userStart == m_schemeEnd + 1; 7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(hostStart()) + (slashSlashNeeded ? "//" : "") + s + m_string.substring(m_hostEnd)); 7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 745643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid KURL::removePort() 746643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 747643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (m_hostEnd == m_portEnd) 748643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 749643ca7872b450ea4efacab6188849e5aac2ba161Steve Block parse(m_string.left(m_hostEnd) + m_string.substring(m_portEnd)); 750643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 751643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setPort(unsigned short i) 7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 757643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool colonNeeded = m_portEnd == m_hostEnd; 758643ca7872b450ea4efacab6188849e5aac2ba161Steve Block int portStart = (colonNeeded ? m_hostEnd : m_hostEnd + 1); 7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 760643ca7872b450ea4efacab6188849e5aac2ba161Steve Block parse(m_string.left(portStart) + (colonNeeded ? ":" : "") + String::number(i) + m_string.substring(m_portEnd)); 7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setHostAndPort(const String& hostAndPort) 7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 768635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 769635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just host and port. 770635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool slashSlashNeeded = m_userStart == m_schemeEnd + 1; 7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(hostStart()) + (slashSlashNeeded ? "//" : "") + hostAndPort + m_string.substring(m_portEnd)); 7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setUser(const String& user) 7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 781635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 782635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just the user login. 7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String u; 7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int end = m_userEnd; 7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!user.isEmpty()) { 7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project u = user; 7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userStart == m_schemeEnd + 1) 7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project u = "//" + u; 7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Add '@' if we didn't have one before. 7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (end == m_hostEnd || (end == m_passwordEnd && m_string[end] != '@')) 7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project u.append('@'); 7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove '@' if we now have neither user nor password. 7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userEnd == m_passwordEnd && end != m_hostEnd && m_string[end] == '@') 7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project end += 1; 7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_userStart) + u + m_string.substring(end)); 7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setPass(const String& password) 8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 805635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 806635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just the user password. 8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String p; 8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int end = m_passwordEnd; 8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!password.isEmpty()) { 8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = ":" + password + "@"; 8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userEnd == m_schemeEnd + 1) 8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = "//" + p; 8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Eat the existing '@' since we are going to add our own. 8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (end != m_hostEnd && m_string[end] == '@') 8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project end += 1; 8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove '@' if we now have neither user nor password. 8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userStart == m_userEnd && end != m_hostEnd && m_string[end] == '@') 8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project end += 1; 8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_userEnd) + p + m_string.substring(end)); 8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid KURL::setFragmentIdentifier(const String& s) 8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 828635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 829635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations. 8300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch parse(m_string.left(m_queryEnd) + "#" + s); 8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid KURL::removeFragmentIdentifier() 8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_queryEnd)); 8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setQuery(const String& query) 8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 845635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: '#' and non-ASCII characters must be encoded and escaped. 846635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Usually, the query is encoded using document encoding, not UTF-8, but we don't have 847635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // access to the document in this function. 8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((query.isEmpty() || query[0] != '?') && !query.isNull()) 8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_pathEnd) + "?" + query + m_string.substring(m_queryEnd)); 8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_pathEnd) + query + m_string.substring(m_queryEnd)); 8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setPath(const String& s) 8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 860635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: encodeWithURLEscapeSequences does not correctly escape '#' and '?', so fragment and query parts 861635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // may be inadvertently affected. 8622bde8e466a4451c7319e3a072d118917957d6554Steve Block String path = s; 8632bde8e466a4451c7319e3a072d118917957d6554Steve Block if (path.isEmpty() || path[0] != '/') 8642bde8e466a4451c7319e3a072d118917957d6554Steve Block path = "/" + path; 8652bde8e466a4451c7319e3a072d118917957d6554Steve Block 8662bde8e466a4451c7319e3a072d118917957d6554Steve Block parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(path) + m_string.substring(m_pathEnd)); 8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8696ed1fdfa7999878a811b09cdd647fbeace4353b8Steve BlockString KURL::deprecatedString() const 8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string; 8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> result; 8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(result, protocol()); 8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(':'); 8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> authority; 8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_hostEnd != m_passwordEnd) { 8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userEnd != m_userStart) { 8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(authority, user()); 8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project authority.append('@'); 8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(authority, host()); 887643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (hasPort()) { 8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project authority.append(':'); 8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(authority, String::number(port())); 8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!authority.isEmpty()) { 8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(authority); 8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (protocolIs("file")) { 8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(result, path()); 9038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_pathEnd != m_queryEnd) { 9058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.append('?'); 9068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian append(result, query()); 9078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_fragmentEnd != m_queryEnd) { 9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('#'); 9110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch append(result, fragmentIdentifier()); 9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String::adopt(result); 9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString decodeURLEscapeSequences(const String& str) 9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(str, UTF8Encoding()); 9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString decodeURLEscapeSequences(const String& str, const TextEncoding& encoding) 9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> result; 9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer buffer; 9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 928f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned length = str.length(); 929f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned decodedPosition = 0; 930f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned searchPosition = 0; 931f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t encodedRunPosition; 932f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick while ((encodedRunPosition = str.find('%', searchPosition)) != notFound) { 9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the sequence of %-escape codes. 934f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned encodedRunEnd = encodedRunPosition; 9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (length - encodedRunEnd >= 3 9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && str[encodedRunEnd] == '%' 9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && isASCIIHexDigit(str[encodedRunEnd + 1]) 9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && isASCIIHexDigit(str[encodedRunEnd + 2])) 9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project encodedRunEnd += 3; 9402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block searchPosition = encodedRunEnd; 9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (encodedRunEnd == encodedRunPosition) { 9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++searchPosition; 9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Decode the %-escapes into bytes. 9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned runLength = (encodedRunEnd - encodedRunPosition) / 3; 9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.resize(runLength); 9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = buffer.data(); 9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* q = str.characters() + encodedRunPosition; 9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < runLength; ++i) { 9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = (hexDigitValue(q[1]) << 4) | hexDigitValue(q[2]); 9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project q += 3; 9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Decode the bytes into Unicode characters. 9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String decoded = (encoding.isValid() ? encoding : UTF8Encoding()).decode(buffer.data(), p - buffer.data()); 9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (decoded.isEmpty()) 9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Build up the string with what we just skipped and what we just decoded. 9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(str.characters() + decodedPosition, encodedRunPosition - decodedPosition); 9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(decoded.characters(), decoded.length()); 9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decodedPosition = encodedRunEnd; 9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(str.characters() + decodedPosition, length - decodedPosition); 9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String::adopt(result); 9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// Caution: This function does not bounds check. 9732fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic void appendEscapedChar(char*& buffer, unsigned char c) 9742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 9752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *buffer++ = '%'; 9762bde8e466a4451c7319e3a072d118917957d6554Steve Block placeByteAsHex(c, buffer); 9772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 9782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void appendEscapingBadChars(char*& buffer, const char* strStart, size_t length) 9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = buffer; 9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* str = strStart; 9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* strEnd = strStart + length; 9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (str < strEnd) { 9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned char c = *str++; 9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isBadChar(c)) { 9882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (c == '%' || c == '?') 9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = c; 9902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else if (c != 0x09 && c != 0x0a && c != 0x0d) 9912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block appendEscapedChar(p, c); 9922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } else 9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = c; 9942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 9952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block buffer = p; 9972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 9982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 999e48d279609693b4d164199748c93ad791547c649Steve Blockstatic void escapeAndAppendNonHierarchicalPart(char*& buffer, const char* strStart, size_t length) 10002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 10012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block char* p = buffer; 10022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* str = strStart; 10042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* strEnd = strStart + length; 10052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block while (str < strEnd) { 10062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block unsigned char c = *str++; 10072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Strip CR, LF and Tab from fragments, per: 10082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // https://bugs.webkit.org/show_bug.cgi?id=8770 10092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (c == 0x09 || c == 0x0a || c == 0x0d) 10102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block continue; 10112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Chrome and IE allow non-ascii characters in fragments, however doing 10132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // so would hit an ASSERT in checkEncodedString, so for now we don't. 10142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (c < 0x20 || c >= 127) { 10152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block appendEscapedChar(p, c); 10162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block continue; 10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = c; 10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer = p; 10228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// copy a path, accounting for "." and ".." segments 10258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd) 10268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* bufferPathStart = dst; 10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // empty path is a special case, and need not have a leading slash 10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (srcStart != srcEnd) { 10318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringStart = src + srcStart; 10328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringEnd = src + srcEnd; 10338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringPos = baseStringStart; 10348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // this code is unprepared for paths that do not begin with a 10368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // slash and we should always have one in the source string 10378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(baseStringPos[0] == '/'); 10388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy the leading slash into the destination 10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *dst = *baseStringPos; 10418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos++; 10428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst++; 10438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (baseStringPos < baseStringEnd) { 10458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (baseStringPos[0] == '.' && dst[-1] == '/') { 10468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (baseStringPos[1] == '/' || baseStringPos + 1 == baseStringEnd) { 10478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over "." segment 10488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos += 2; 10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (baseStringPos[1] == '.' && (baseStringPos[2] == '/' || 10518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos + 2 == baseStringEnd)) { 10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over ".." segment and rewind the last segment 10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the RFC leaves it up to the app to decide what to do with excess 10548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ".." segments - we choose to drop them since some web content 10558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // relies on this. 10568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos += 3; 10578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (dst > bufferPathStart + 1) 10588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst--; 10598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (dst > bufferPathStart && dst[-1] != '/') 10608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst--; 10618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 10628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *dst = *baseStringPos; 10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos++; 10678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst++; 10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *dst = '\0'; 10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return dst - bufferPathStart; 10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool hasSlashDotOrDotDot(const char* str) 10758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const unsigned char* p = reinterpret_cast<const unsigned char*>(str); 10778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!*p) 10788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 10798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned char pc = *p; 10808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (unsigned char c = *++p) { 10818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '.' && (pc == '/' || pc == '.')) 10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 10838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pc = c; 10848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 10868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool matchLetter(char c, char lowercaseLetter) 10898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return (c | 0x20) == lowercaseLetter; 10918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::parse(const String& string) 10948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1095635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project checkEncodedString(string); 1096635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1097635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CharBuffer buffer(string.length() + 1); 1098635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project copyASCII(string.characters(), string.length(), buffer.data()); 1099635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer[string.length()] = '\0'; 11008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(buffer.data(), &string); 11018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11032fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic inline bool equal(const char* a, size_t lenA, const char* b, size_t lenB) 11042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 11052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (lenA != lenB) 11062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 11072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return !strncmp(a, b, lenA); 11082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 11092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 11102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// List of default schemes is taken from google-url: 11112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// http://code.google.com/p/google-url/source/browse/trunk/src/url_canon_stdurl.cc#120 11122fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic inline bool isDefaultPortForScheme(const char* port, size_t portLength, const char* scheme, size_t schemeLength) 11132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 11142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // This switch is theoretically a performance optimization. It came over when 11152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // the code was moved from google-url, but may be removed later. 11162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block switch (schemeLength) { 11172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 2: 11182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("ws", 2, scheme, schemeLength) && equal("80", 2, port, portLength); 11192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 3: 11202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (equal("ftp", 3, scheme, schemeLength)) 11212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("21", 2, port, portLength); 11222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (equal("wss", 3, scheme, schemeLength)) 11232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("443", 3, port, portLength); 11242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block break; 11252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 4: 11262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("http", 4, scheme, schemeLength) && equal("80", 2, port, portLength); 11272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 5: 11282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("https", 5, scheme, schemeLength) && equal("443", 3, port, portLength); 11292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 6: 11302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("gopher", 6, scheme, schemeLength) && equal("70", 2, port, portLength); 11312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 11322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 11332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 11342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 11352bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic inline bool hostPortIsEmptyButCredentialsArePresent(int hostStart, int portEnd, char userEndChar) 11362bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 11372bde8e466a4451c7319e3a072d118917957d6554Steve Block return userEndChar == '@' && hostStart == portEnd; 11382bde8e466a4451c7319e3a072d118917957d6554Steve Block} 11392bde8e466a4451c7319e3a072d118917957d6554Steve Block 1140db951b2c4c8fce1304a13d97dec4ae14be629380Steve Blockstatic bool isNonFileHierarchicalScheme(const char* scheme, size_t schemeLength) 1141db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block{ 1142db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block switch (schemeLength) { 1143db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block case 2: 1144db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block return equal("ws", 2, scheme, schemeLength); 1145db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block case 3: 1146db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block return equal("ftp", 3, scheme, schemeLength) || equal("wss", 3, scheme, schemeLength); 1147db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block case 4: 1148db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block return equal("http", 4, scheme, schemeLength); 1149db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block case 5: 1150db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block return equal("https", 5, scheme, schemeLength); 1151db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block case 6: 1152db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block return equal("gopher", 6, scheme, schemeLength); 1153db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block } 1154db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block return false; 1155db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block} 1156db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block 11578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::parse(const char* url, const String* originalString) 11588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!url || url[0] == '\0') { 11608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // valid URL must be non-empty 11618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 11628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 11638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isSchemeFirstChar(url[0])) { 11678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // scheme must start with an alphabetic character 11688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 11708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int schemeEnd = 0; 11748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isSchemeChar(url[schemeEnd])) 11758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project schemeEnd++; 11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[schemeEnd] != ':') { 11788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 11798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 11808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int userStart = schemeEnd + 1; 11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int userEnd; 11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int passwordStart; 11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int passwordEnd; 11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStart; 11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostEnd; 11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int portStart; 11908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int portEnd; 11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool hierarchical = url[schemeEnd + 1] == '/'; 1193db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block bool hasSecondSlash = hierarchical && url[schemeEnd + 2] == '/'; 11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool isFile = schemeEnd == 4 11968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[0], 'f') 11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[1], 'i') 11988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[2], 'l') 11998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[3], 'e'); 12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_protocolInHTTPFamily = matchLetter(url[0], 'h') 12028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[1], 't') 12038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[2], 't') 12048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[3], 'p') 12058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && (url[4] == ':' || (matchLetter(url[4], 's') && url[5] == ':')); 12068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1207db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block if ((hierarchical && hasSecondSlash) || isNonFileHierarchicalScheme(url, schemeEnd)) { 12088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The part after the scheme is either a net_path or an abs_path whose first path segment is empty. 12098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Attempt to find an authority. 12108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Authority characters may be scanned twice, and it would be nice to be faster. 1211db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block 1212db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block if (hierarchical) 1213db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block userStart++; 1214db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block if (hasSecondSlash) 1215db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block userStart++; 12168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 12178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int colonPos = 0; 12198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isUserInfoChar(url[userEnd])) { 12208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[userEnd] == ':' && colonPos == 0) 12218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project colonPos = userEnd; 12228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd++; 12238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[userEnd] == '@') { 12268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // actual end of the userinfo, start on the host 12278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (colonPos != 0) { 12288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordEnd = userEnd; 12298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = colonPos; 12308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = colonPos + 1; 12318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 12328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = passwordEnd = userEnd; 12338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = passwordEnd + 1; 12358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (url[userEnd] == '[' || isPathSegmentEndChar(url[userEnd])) { 12368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // hit the end of the authority, must have been no user 12378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // or looks like an IPv6 hostname 12388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // either way, try to parse it as a hostname 12398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 12408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = passwordEnd = userEnd; 12418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = userStart; 12428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 12438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // invalid character 12448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 12458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 12468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd = hostStart; 12508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // IPV6 IP address 12528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[hostEnd] == '[') { 12538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isIPv6Char(url[hostEnd])) 12558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[hostEnd] == ']') 12578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 12598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // invalid character 12608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 12618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 12628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 12658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isHostnameChar(url[hostEnd])) 12668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[hostEnd] == ':') { 12708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = portEnd = hostEnd + 1; 12718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // possible start of port 12738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portEnd = portStart; 12748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isASCIIDigit(url[portEnd])) 12758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portEnd++; 12768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 12778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = portEnd = hostEnd; 12788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isPathSegmentEndChar(url[portEnd])) { 12808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // invalid character 12818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 12828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 12838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12862bde8e466a4451c7319e3a072d118917957d6554Steve Block if (hostPortIsEmptyButCredentialsArePresent(hostStart, portEnd, url[userEnd])) { 12872bde8e466a4451c7319e3a072d118917957d6554Steve Block // in this circumstance, act as if there is an erroneous hostname containing an '@' 12882bde8e466a4451c7319e3a072d118917957d6554Steve Block userEnd = userStart; 12892bde8e466a4451c7319e3a072d118917957d6554Steve Block hostStart = userEnd; 12902bde8e466a4451c7319e3a072d118917957d6554Steve Block } 12912bde8e466a4451c7319e3a072d118917957d6554Steve Block 12928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (userStart == portEnd && !m_protocolInHTTPFamily && !isFile) { 12938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // No authority found, which means that this is not a net_path, but rather an abs_path whose first two 12948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // path segments are empty. For file, http and https only, an empty authority is allowed. 12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userStart -= 2; 12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 12978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = userEnd; 12988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordEnd = passwordStart; 12998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = passwordEnd; 13008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd = hostStart; 13018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = hostEnd; 13028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portEnd = hostEnd; 13038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 13058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the part after the scheme must be an opaque_part or an abs_path 13068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 13078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = passwordEnd = userEnd; 13088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = hostEnd = passwordEnd; 13098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = portEnd = hostEnd; 13108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int pathStart = portEnd; 13138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int pathEnd = pathStart; 13148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (url[pathEnd] && url[pathEnd] != '?' && url[pathEnd] != '#') 13158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd++; 13168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int queryStart = pathEnd; 13188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int queryEnd = queryStart; 13198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[queryStart] == '?') { 13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (url[queryEnd] && url[queryEnd] != '#') 13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project queryEnd++; 13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int fragmentStart = queryEnd; 13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int fragmentEnd = fragmentStart; 13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[fragmentStart] == '#') { 13278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fragmentStart++; 13288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fragmentEnd = fragmentStart; 13298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (url[fragmentEnd]) 13308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fragmentEnd++; 13318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // assemble it all, remembering the real ranges 13348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<char, 4096> buffer(fragmentEnd * 3 + 1); 13368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char *p = buffer.data(); 13388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char *strPtr = url; 13398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the scheme 13418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char *schemeEndPtr = url + schemeEnd; 13428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < schemeEndPtr) 13432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = toASCIILower(*strPtr++); 13448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_schemeEnd = p - buffer.data(); 13458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool hostIsLocalHost = portEnd - userStart == 9 13478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart], 'l') 13488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+1], 'o') 13498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+2], 'c') 13508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+3], 'a') 13518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+4], 'l') 13528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+5], 'h') 13538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+6], 'o') 13548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+7], 's') 13558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+8], 't'); 13568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // File URLs need a host part unless it is just file:// or file://localhost 13588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool degenFilePath = pathStart == pathEnd && (hostStart == hostEnd || hostIsLocalHost); 13598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool haveNonHostAuthorityPart = userStart != userEnd || passwordStart != passwordEnd || portStart != portEnd; 13618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add ":" after scheme 13638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = ':'; 13648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // if we have at least one authority part or a file URL - add "//" and authority 13668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isFile ? !degenFilePath : (haveNonHostAuthorityPart || hostStart != hostEnd)) { 13678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '/'; 13688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '/'; 13698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userStart = p - buffer.data(); 13718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the user 13738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strPtr = url + userStart; 13748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* userEndPtr = url + userEnd; 13758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < userEndPtr) 13768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = *strPtr++; 13778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userEnd = p - buffer.data(); 13788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the password 13808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (passwordEnd != passwordStart) { 13818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = ':'; 13828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strPtr = url + passwordStart; 13838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* passwordEndPtr = url + passwordEnd; 13848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < passwordEndPtr) 13858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = *strPtr++; 13868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_passwordEnd = p - buffer.data(); 13888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we had any user info, add "@" 13908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p - buffer.data() != m_userStart) 13918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '@'; 13928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the host, except in the case of a file URL with authority="localhost" 13948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!(isFile && hostIsLocalHost && !haveNonHostAuthorityPart)) { 13958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strPtr = url + hostStart; 13968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* hostEndPtr = url + hostEnd; 13978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < hostEndPtr) 13988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = *strPtr++; 13998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_hostEnd = p - buffer.data(); 14018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Copy in the port if the URL has one (and it's not default). 14038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hostEnd != portStart) { 14042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* portStr = url + portStart; 14052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block size_t portLength = portEnd - portStart; 14062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (portLength && !isDefaultPortForScheme(portStr, portLength, buffer.data(), m_schemeEnd)) { 14072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = ':'; 14082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* portEndPtr = url + portEnd; 14092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block while (portStr < portEndPtr) 14102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = *portStr++; 14112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 14128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_portEnd = p - buffer.data(); 14148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 14158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userStart = m_userEnd = m_passwordEnd = m_hostEnd = m_portEnd = p - buffer.data(); 14168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For canonicalization, ensure we have a '/' for no path. 1418db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block // Do this only for URL with protocol http or https. 1419db951b2c4c8fce1304a13d97dec4ae14be629380Steve Block if (m_protocolInHTTPFamily && pathEnd == pathStart) 14208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '/'; 14218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add path, escaping bad characters 1423e48d279609693b4d164199748c93ad791547c649Steve Block if (!hierarchical) 1424e48d279609693b4d164199748c93ad791547c649Steve Block escapeAndAppendNonHierarchicalPart(p, url + pathStart, pathEnd - pathStart); 1425e48d279609693b4d164199748c93ad791547c649Steve Block else if (!hasSlashDotOrDotDot(url)) 14268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEscapingBadChars(p, url + pathStart, pathEnd - pathStart); 14278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 14288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer pathBuffer(pathEnd - pathStart + 1); 14298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t length = copyPathRemovingDots(pathBuffer.data(), url, pathStart, pathEnd); 14308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEscapingBadChars(p, pathBuffer.data(), length); 14318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathEnd = p - buffer.data(); 14348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the position after the last slash in the path, or 14368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the position before the path if there are no slashes in it. 14378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int i; 14388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (i = m_pathEnd; i > m_portEnd; --i) { 14398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (buffer[i - 1] == '/') 14408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 14418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathAfterLastSlash = i; 14438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add query, escaping bad characters 14458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEscapingBadChars(p, url + queryStart, queryEnd - queryStart); 14468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_queryEnd = p - buffer.data(); 14478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add fragment, escaping bad characters 14498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (fragmentEnd != queryEnd) { 14508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '#'; 1451e48d279609693b4d164199748c93ad791547c649Steve Block escapeAndAppendNonHierarchicalPart(p, url + fragmentStart, fragmentEnd - fragmentStart); 14528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_fragmentEnd = p - buffer.data(); 14548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(p - buffer.data() <= static_cast<int>(buffer.size())); 14568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we didn't end up actually changing the original string and 14588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // it was already in a String, reuse it to avoid extra allocation. 14598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (originalString && originalString->length() == static_cast<unsigned>(m_fragmentEnd) && strncmp(buffer.data(), url, m_fragmentEnd) == 0) 14608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = *originalString; 14618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 14628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = String(buffer.data(), m_fragmentEnd); 14638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isValid = true; 14658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool equalIgnoringFragmentIdentifier(const KURL& a, const KURL& b) 14688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.m_queryEnd != b.m_queryEnd) 14708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 14718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned queryLength = a.m_queryEnd; 14728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < queryLength; ++i) 14738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.string()[i] != b.string()[i]) 14748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 14758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 14768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) 14798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.m_schemeEnd != b.m_schemeEnd) 14818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 148221939df44de1705786c545cd1bf519d47250322dBen Murdoch 14838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStartA = a.hostStart(); 148421939df44de1705786c545cd1bf519d47250322dBen Murdoch int hostLengthA = a.hostEnd() - hostStartA; 14858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStartB = b.hostStart(); 148621939df44de1705786c545cd1bf519d47250322dBen Murdoch int hostLengthB = b.hostEnd() - b.hostStart(); 148721939df44de1705786c545cd1bf519d47250322dBen Murdoch if (hostLengthA != hostLengthB) 14888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 14898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check the scheme 14918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < a.m_schemeEnd; ++i) 14928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.string()[i] != b.string()[i]) 14938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 149421939df44de1705786c545cd1bf519d47250322dBen Murdoch 14958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // And the host 149621939df44de1705786c545cd1bf519d47250322dBen Murdoch for (int i = 0; i < hostLengthA; ++i) 149721939df44de1705786c545cd1bf519d47250322dBen Murdoch if (a.string()[hostStartA + i] != b.string()[hostStartB + i]) 14988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 149921939df44de1705786c545cd1bf519d47250322dBen Murdoch 15008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.port() != b.port()) 15018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 15028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 15048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString encodeWithURLEscapeSequences(const String& notEncodedString) 15078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString asUTF8 = notEncodedString.utf8(); 15098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer buffer(asUTF8.length() * 3 + 1); 15118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = buffer.data(); 15128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* str = asUTF8.data(); 15148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* strEnd = str + asUTF8.length(); 15158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (str < strEnd) { 15168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned char c = *str++; 15172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (isBadChar(c)) 15182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block appendEscapedChar(p, c); 15192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else 15208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = c; 15218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(p - buffer.data() <= static_cast<int>(buffer.size())); 15248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(buffer.data(), p - buffer.data()); 15268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Appends the punycoded hostname identified by the given string and length to 15298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// the output buffer. The result will not be null terminated. 15308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void appendEncodedHostname(UCharBuffer& buffer, const UChar* str, unsigned strLen) 15318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Needs to be big enough to hold an IDN-encoded name. 15338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For host names bigger than this, we won't do IDN encoding, which is almost certainly OK. 15348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const unsigned hostnameBufferLength = 2048; 15358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (strLen > hostnameBufferLength || charactersAreAllASCII(str, strLen)) { 15378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.append(str, strLen); 15388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if USE(ICU_UNICODE) 15428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar hostnameBuffer[hostnameBufferLength]; 15438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UErrorCode error = U_ZERO_ERROR; 15448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int32_t numCharactersConverted = uidna_IDNToASCII(str, strLen, hostnameBuffer, 15458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameBufferLength, UIDNA_ALLOW_UNASSIGNED, 0, &error); 15468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (error == U_ZERO_ERROR) 15478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.append(hostnameBuffer, numCharactersConverted); 15488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#elif USE(QT4_UNICODE) 15498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project QByteArray result = QUrl::toAce(String(str, strLen)); 15508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.append(result.constData(), result.length()); 1551d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(GLIB_UNICODE) 1552d0825bca7fe65beaee391d30da42e937db621564Steve Block GOwnPtr<gchar> utf8Hostname; 1553d0825bca7fe65beaee391d30da42e937db621564Steve Block GOwnPtr<GError> utf8Err; 1554d0825bca7fe65beaee391d30da42e937db621564Steve Block utf8Hostname.set(g_utf16_to_utf8(str, strLen, 0, 0, &utf8Err.outPtr())); 1555d0825bca7fe65beaee391d30da42e937db621564Steve Block if (utf8Err) 1556d0825bca7fe65beaee391d30da42e937db621564Steve Block return; 1557d0825bca7fe65beaee391d30da42e937db621564Steve Block 1558d0825bca7fe65beaee391d30da42e937db621564Steve Block GOwnPtr<gchar> encodedHostname; 1559d0825bca7fe65beaee391d30da42e937db621564Steve Block encodedHostname.set(g_hostname_to_ascii(utf8Hostname.get())); 1560d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!encodedHostname) 1561d0825bca7fe65beaee391d30da42e937db621564Steve Block return; 1562d0825bca7fe65beaee391d30da42e937db621564Steve Block 1563d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.append(encodedHostname.get(), strlen(encodedHostname.get())); 15648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 15658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void findHostnamesInMailToURL(const UChar* str, int strLen, Vector<pair<int, int> >& nameRanges) 15688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // In a mailto: URL, host names come after a '@' character and end with a '>' or ',' or '?' or end of string character. 15708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Skip quoted strings so that characters in them don't confuse us. 15718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // When we find a '?' character, we are past the part of the URL that contains host names. 15728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nameRanges.clear(); 15748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int p = 0; 15768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 15778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find start of host name or of quoted string. 15788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameOrStringStart = findFirstOf(str, strLen, p, "\"@?"); 15798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hostnameOrStringStart == -1) 15808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar c = str[hostnameOrStringStart]; 15828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = hostnameOrStringStart + 1; 15838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '?') 15858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '@') { 15888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find end of host name. 15898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameStart = p; 15908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameEnd = findFirstOf(str, strLen, p, ">,?"); 15918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool done; 15928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hostnameEnd == -1) { 15938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameEnd = strLen; 15948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project done = true; 15958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 15968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = hostnameEnd; 15978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project done = false; 15988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nameRanges.append(make_pair(hostnameStart, hostnameEnd)); 16018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (done) 16038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 16048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 16058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Skip quoted string. 16068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(c == '"'); 16078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 16088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int escapedCharacterOrStringEnd = findFirstOf(str, strLen, p, "\"\\"); 16098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (escapedCharacterOrStringEnd == -1) 16108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 16118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project c = str[escapedCharacterOrStringEnd]; 16138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = escapedCharacterOrStringEnd + 1; 16148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we are the end of the string, then break from the string loop back to the host name loop. 16168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '"') 16178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 16188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Skip escaped character. 16208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(c == '\\'); 16218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p == strLen) 16228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 16238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 16258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 16298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool findHostnameInHierarchicalURL(const UChar* str, int strLen, int& startOffset, int& endOffset) 16318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 16328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the host name in a hierarchical URL. 16338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It comes after a "://" sequence, with scheme characters preceding, and 16348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // this should be the first colon in the string. 16358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It ends with the end of the string or a ":" or a path segment ending character. 16368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If there is a "@" character, the host part is just the part after the "@". 16378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int separator = findFirstOf(str, strLen, 0, ":"); 16388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (separator == -1 || separator + 2 >= strLen || 16398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str[separator + 1] != '/' || str[separator + 2] != '/') 16408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 16418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check that all characters before the :// are valid scheme characters. 16438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isSchemeFirstChar(str[0])) 16448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 16458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 1; i < separator; ++i) { 16468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isSchemeChar(str[i])) 16478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 16488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Start after the separator. 16518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int authorityStart = separator + 3; 16528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find terminating character. 16548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameEnd = strLen; 16558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = authorityStart; i < strLen; ++i) { 16568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar c = str[i]; 16578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == ':' || (isPathSegmentEndChar(c) && c != 0)) { 16588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameEnd = i; 16598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 16608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find "@" for the start of the host name. 16648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int userInfoTerminator = findFirstOf(str, strLen, authorityStart, "@"); 16658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameStart; 16668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (userInfoTerminator == -1 || userInfoTerminator > hostnameEnd) 16678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameStart = authorityStart; 16688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 16698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameStart = userInfoTerminator + 1; 16708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startOffset = hostnameStart; 16728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endOffset = hostnameEnd; 16738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 16748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 16758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Converts all hostnames found in the given input to punycode, preserving the 16778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// rest of the URL unchanged. The output will NOT be null-terminated. 16788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void encodeHostnames(const String& str, UCharBuffer& output) 16798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 16808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.clear(); 16818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (protocolIs(str, "mailto")) { 16838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<pair<int, int> > hostnameRanges; 16848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project findHostnamesInMailToURL(str.characters(), str.length(), hostnameRanges); 16858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int n = hostnameRanges.size(); 16868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int p = 0; 16878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < n; ++i) { 16888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const pair<int, int>& r = hostnameRanges[i]; 16898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(&str.characters()[p], r.first - p); 16908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEncodedHostname(output, &str.characters()[r.first], r.second - r.first); 16918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = r.second; 16928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This will copy either everything after the last hostname, or the 16948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // whole thing if there is no hostname. 16958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(&str.characters()[p], str.length() - p); 16968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 16978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStart, hostEnd; 16988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (findHostnameInHierarchicalURL(str.characters(), str.length(), hostStart, hostEnd)) { 16998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(str.characters(), hostStart); // Before hostname. 17008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEncodedHostname(output, &str.characters()[hostStart], hostEnd - hostStart); 17018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(&str.characters()[hostEnd], str.length() - hostEnd); // After hostname. 17028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 17038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // No hostname to encode, return the input. 17048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(str.characters(), str.length()); 17058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 17068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 17078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void encodeRelativeString(const String& rel, const TextEncoding& encoding, CharBuffer& output) 17108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UCharBuffer s; 17128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project encodeHostnames(rel, s); 17138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project TextEncoding pathEncoding(UTF8Encoding()); // Path is always encoded as UTF-8; other parts may depend on the scheme. 17158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int pathEnd = -1; 17175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (encoding != pathEncoding && encoding.isValid() && !protocolIs(rel, "mailto") && !protocolIs(rel, "data") && !protocolIsJavaScript(rel)) { 17188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the first instance of either # or ?, keep pathEnd at -1 otherwise. 17198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = findFirstOf(s.data(), s.size(), 0, "#?"); 17208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 17218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pathEnd == -1) { 17238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString decoded = pathEncoding.encode(s.data(), s.size(), URLEncodedEntitiesForUnencodables); 17248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.resize(decoded.length()); 17258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(output.data(), decoded.data(), decoded.length()); 17268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 17278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString pathDecoded = pathEncoding.encode(s.data(), pathEnd, URLEncodedEntitiesForUnencodables); 17288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Unencodable characters in URLs are represented by converting 17298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // them to XML entities and escaping non-alphanumeric characters. 17308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString otherDecoded = encoding.encode(s.data() + pathEnd, s.size() - pathEnd, URLEncodedEntitiesForUnencodables); 17318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.resize(pathDecoded.length() + otherDecoded.length()); 17338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(output.data(), pathDecoded.data(), pathDecoded.length()); 17348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(output.data() + pathDecoded.length(), otherDecoded.data(), otherDecoded.length()); 17358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 17368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append('\0'); // null-terminate the output. 17378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic String substituteBackslashes(const String& string) 17408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1741f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t questionPos = string.find('?'); 1742f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t hashPos = string.find('#'); 1743f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned pathEnd; 17448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1745f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (hashPos != notFound && (questionPos == notFound || questionPos > hashPos)) 17468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = hashPos; 1747f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick else if (questionPos != notFound) 17488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = questionPos; 17498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 17508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = string.length(); 17518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return string.left(pathEnd).replace('\\','/') + string.substring(pathEnd); 17538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool KURL::isHierarchical() const 17568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 17588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 17598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_string[m_schemeEnd] == ':'); 17608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string[m_schemeEnd + 1] == '/'; 17618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::copyToBuffer(CharBuffer& buffer) const 17648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This throws away the high bytes of all the characters in the string! 17668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // That's fine for a valid URL, which is all ASCII, but not for invalid URLs. 17678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.resize(m_string.length()); 17688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project copyASCII(m_string.characters(), m_string.length(), buffer.data()); 17698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool protocolIs(const String& url, const char* protocol) 17728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Do the comparison without making a new string object. 17748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project assertProtocolIsGood(protocol); 17758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; ; ++i) { 17768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!protocol[i]) 17778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return url[i] == ':'; 17788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (toASCIILower(url[i]) != protocol[i]) 17798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 17808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 17818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1783643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool isValidProtocol(const String& protocol) 1784643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 1785d0825bca7fe65beaee391d30da42e937db621564Steve Block // RFC3986: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) 1786d0825bca7fe65beaee391d30da42e937db621564Steve Block if (protocol.isEmpty()) 1787d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1788643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!isSchemeFirstChar(protocol[0])) 1789643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1790643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned protocolLength = protocol.length(); 1791643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (unsigned i = 1; i < protocolLength; i++) { 1792643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!isSchemeChar(protocol[i])) 1793643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1794643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 1795643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1796643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 1797643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 179881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#ifndef NDEBUG 179981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid KURL::print() const 180081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 180181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch printf("%s\n", m_string.utf8().data()); 180281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 180381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif 180481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 180581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif // !USE(GOOGLEURL) 180681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 180781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochString KURL::strippedForUseAsReferrer() const 180881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 180981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch KURL referrer(*this); 181081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch referrer.setUser(String()); 181181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch referrer.setPass(String()); 181281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch referrer.removeFragmentIdentifier(); 181381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return referrer.string(); 181481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 181581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 181681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool KURL::isLocalFile() const 181781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 181881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Including feed here might be a bad idea since drag and drop uses this check 181981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // and including feed would allow feeds to potentially let someone's blog 182081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // read the contents of the clipboard on a drag, even without a drop. 182181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Likewise with using the FrameLoader::shouldTreatURLAsLocal() function. 182281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return protocolIs("file"); 182381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 182481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 182581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool protocolIsJavaScript(const String& url) 182681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 182781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return protocolIs(url, "javascript"); 182881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 182981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 183081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochconst KURL& blankURL() 183181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 183281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch DEFINE_STATIC_LOCAL(KURL, staticBlankURL, (ParsedURLString, "about:blank")); 183381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return staticBlankURL; 183481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 183581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 1836643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool isDefaultPortForProtocol(unsigned short port, const String& protocol) 1837643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 1838643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (protocol.isEmpty()) 1839643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1840643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1841643ca7872b450ea4efacab6188849e5aac2ba161Steve Block typedef HashMap<String, unsigned, CaseFoldingHash> DefaultPortsMap; 1842643ca7872b450ea4efacab6188849e5aac2ba161Steve Block DEFINE_STATIC_LOCAL(DefaultPortsMap, defaultPorts, ()); 1843643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (defaultPorts.isEmpty()) { 1844643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("http", 80); 1845643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("https", 443); 1846643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("ftp", 21); 1847643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("ftps", 990); 1848643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 1849643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return defaultPorts.get(protocol) == port; 1850643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 1851643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1852643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool portAllowed(const KURL& url) 1853643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 1854643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned short port = url.port(); 1855643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1856643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Since most URLs don't have a port, return early for the "no port" case. 1857643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!port) 1858643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1859643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1860643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This blocked port list matches the port blocking that Mozilla implements. 1861643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // See http://www.mozilla.org/projects/netlib/PortBanning.html for more information. 1862643ca7872b450ea4efacab6188849e5aac2ba161Steve Block static const unsigned short blockedPortList[] = { 1863643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1, // tcpmux 1864643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 7, // echo 1865643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 9, // discard 1866643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 11, // systat 1867643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 13, // daytime 1868643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 15, // netstat 1869643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 17, // qotd 1870643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 19, // chargen 1871643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 20, // FTP-data 1872643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 21, // FTP-control 1873643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 22, // SSH 1874643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 23, // telnet 1875643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 25, // SMTP 1876643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 37, // time 1877643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 42, // name 1878643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 43, // nicname 1879643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 53, // domain 1880643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 77, // priv-rjs 1881643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 79, // finger 1882643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 87, // ttylink 1883643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 95, // supdup 1884643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 101, // hostriame 1885643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 102, // iso-tsap 1886643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 103, // gppitnp 1887643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 104, // acr-nema 1888643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 109, // POP2 1889643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 110, // POP3 1890643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 111, // sunrpc 1891643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 113, // auth 1892643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 115, // SFTP 1893643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 117, // uucp-path 1894643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 119, // nntp 1895643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 123, // NTP 1896643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 135, // loc-srv / epmap 1897643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 139, // netbios 1898643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 143, // IMAP2 1899643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 179, // BGP 1900643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 389, // LDAP 1901643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 465, // SMTP+SSL 1902643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 512, // print / exec 1903643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 513, // login 1904643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 514, // shell 1905643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 515, // printer 1906643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 526, // tempo 1907643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 530, // courier 1908643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 531, // Chat 1909643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 532, // netnews 1910643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 540, // UUCP 1911643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 556, // remotefs 1912643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 563, // NNTP+SSL 1913643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 587, // ESMTP 1914643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 601, // syslog-conn 1915643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 636, // LDAP+SSL 1916643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 993, // IMAP+SSL 1917643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 995, // POP3+SSL 1918643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2049, // NFS 1919643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3659, // apple-sasl / PasswordServer [Apple addition] 1920643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 4045, // lockd 1921643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 6000, // X11 19225e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6665, // Alternate IRC [Apple addition] 19235e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6666, // Alternate IRC [Apple addition] 19245e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6667, // Standard IRC [Apple addition] 19255e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6668, // Alternate IRC [Apple addition] 19265e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6669, // Alternate IRC [Apple addition] 1927dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block invalidPortNumber, // Used to block all invalid port numbers 1928643ca7872b450ea4efacab6188849e5aac2ba161Steve Block }; 19294576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang const unsigned short* const blockedPortListEnd = blockedPortList + WTF_ARRAY_LENGTH(blockedPortList); 1930643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1931643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#ifndef NDEBUG 1932643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // The port list must be sorted for binary_search to work. 1933643ca7872b450ea4efacab6188849e5aac2ba161Steve Block static bool checkedPortList = false; 1934643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!checkedPortList) { 1935643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (const unsigned short* p = blockedPortList; p != blockedPortListEnd - 1; ++p) 1936643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(*p < *(p + 1)); 1937643ca7872b450ea4efacab6188849e5aac2ba161Steve Block checkedPortList = true; 1938643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 1939643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 1940643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1941643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // If the port is not in the blocked port list, allow it. 1942643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!binary_search(blockedPortList, blockedPortListEnd, port)) 1943643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1944643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1945643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Allow ports 21 and 22 for FTP URLs, as Mozilla does. 1946643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ((port == 21 || port == 22) && url.protocolIs("ftp")) 1947643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1948643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1949643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Allow any port number in a file URL, since the port number is ignored. 1950643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (url.protocolIs("file")) 1951643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1952643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1953643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1954643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 1955643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 19568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString mimeTypeFromDataURL(const String& url) 19578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 19588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(protocolIs(url, "data")); 1959f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t index = url.find(';'); 1960f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (index == notFound) 19618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project index = url.find(','); 1962f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (index != notFound) { 1963f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (index > 5) 1964f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return url.substring(5, index - 5); 19658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return "text/plain"; // Data URLs with no MIME type are considered text/plain. 19668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 19678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ""; 19688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 19698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 19708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1971