KURL.cpp revision 81bc750723a18f21cd17d1b173cd2a4dda9cea6e
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> 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h> 34f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include <wtf/text/StringHash.h> 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if USE(ICU_UNICODE) 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <unicode/uidna.h> 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#elif USE(QT4_UNICODE) 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <QUrl> 40d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(GLIB_UNICODE) 41d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <glib.h> 42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GOwnPtr.h" 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdio.h> 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std; 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF; 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef Vector<char, 512> CharBuffer; 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef Vector<UChar, 512> UCharBuffer; 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic const unsigned maximumValidPortNumber = 0xFFFE; 5681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic const unsigned invalidPortNumber = 0xFFFF; 5781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 5881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#if !USE(GOOGLEURL) 5981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: This file makes too much use of the + operator on String. 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// We either have to optimize that operator so it doesn't involve 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// so many allocations, or change this to use Vector<UChar> instead. 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectenum URLCharacterClasses { 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // alpha 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SchemeFirstChar = 1 << 0, 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ( alpha | digit | "+" | "-" | "." ) 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SchemeChar = 1 << 1, 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // unreserved = alphanum | mark 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ( unreserved | escaped | ";" | ":" | "&" | "=" | "+" | "$" | "," ) 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UserInfoChar = 1 << 2, 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // alnum | "." | "-" | "%" 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The above is what the specification says, but we are lenient to 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // match existing practice and also allow: 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // "_" 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HostnameChar = 1 << 3, 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // hexdigit | ":" | "%" 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project IPv6Char = 1 << 4, 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // "#" | "?" | "/" | nul 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project PathSegmentEndChar = 1 << 5, 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // not allowed in path 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BadChar = 1 << 6 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const char hexDigits[17] = "0123456789ABCDEF"; 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const unsigned char characterClassTable[256] = { 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 0 nul */ PathSegmentEndChar, /* 1 soh */ BadChar, 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 2 stx */ BadChar, /* 3 etx */ BadChar, 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 4 eot */ BadChar, /* 5 enq */ BadChar, /* 6 ack */ BadChar, /* 7 bel */ BadChar, 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 8 bs */ BadChar, /* 9 ht */ BadChar, /* 10 nl */ BadChar, /* 11 vt */ BadChar, 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 12 np */ BadChar, /* 13 cr */ BadChar, /* 14 so */ BadChar, /* 15 si */ BadChar, 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 16 dle */ BadChar, /* 17 dc1 */ BadChar, /* 18 dc2 */ BadChar, /* 19 dc3 */ BadChar, 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 20 dc4 */ BadChar, /* 21 nak */ BadChar, /* 22 syn */ BadChar, /* 23 etb */ BadChar, 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 24 can */ BadChar, /* 25 em */ BadChar, /* 26 sub */ BadChar, /* 27 esc */ BadChar, 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 28 fs */ BadChar, /* 29 gs */ BadChar, /* 30 rs */ BadChar, /* 31 us */ BadChar, 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 32 sp */ BadChar, /* 33 ! */ UserInfoChar, 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 34 " */ BadChar, /* 35 # */ PathSegmentEndChar | BadChar, 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 36 $ */ UserInfoChar, /* 37 % */ UserInfoChar | HostnameChar | IPv6Char | BadChar, 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 38 & */ UserInfoChar, /* 39 ' */ UserInfoChar, 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 40 ( */ UserInfoChar, /* 41 ) */ UserInfoChar, 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 42 * */ UserInfoChar, /* 43 + */ SchemeChar | UserInfoChar, 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 44 , */ UserInfoChar, 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 45 - */ SchemeChar | UserInfoChar | HostnameChar, 112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block /* 46 . */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 47 / */ PathSegmentEndChar, 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 48 0 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 49 1 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 50 2 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 51 3 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 52 4 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 53 5 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 54 6 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 55 7 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 56 8 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 57 9 */ SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 58 : */ UserInfoChar | IPv6Char, /* 59 ; */ UserInfoChar, 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 60 < */ BadChar, /* 61 = */ UserInfoChar, 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 62 > */ BadChar, /* 63 ? */ PathSegmentEndChar | BadChar, 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 64 @ */ 0, 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 65 A */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 66 B */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 67 C */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 68 D */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 69 E */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 70 F */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 71 G */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 72 H */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 73 I */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 74 J */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 75 K */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 76 L */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 77 M */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 78 N */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 79 O */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 80 P */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 81 Q */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 82 R */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 83 S */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 84 T */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 85 U */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 86 V */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 87 W */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 88 X */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 89 Y */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 90 Z */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 91 [ */ 0, 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 92 \ */ 0, /* 93 ] */ 0, 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 94 ^ */ 0, 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 95 _ */ UserInfoChar | HostnameChar, 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 96 ` */ 0, 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 97 a */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 98 b */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 99 c */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 100 d */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 101 e */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 102 f */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | IPv6Char, 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 103 g */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 104 h */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 105 i */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 106 j */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 107 k */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 108 l */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 109 m */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 110 n */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 111 o */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 112 p */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 113 q */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 114 r */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 115 s */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 116 t */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 117 u */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 118 v */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 119 w */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 120 x */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 121 y */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 122 z */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar, 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 123 { */ 0, 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 124 | */ 0, /* 125 } */ 0, /* 126 ~ */ UserInfoChar, /* 127 del */ BadChar, 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 128 */ BadChar, /* 129 */ BadChar, /* 130 */ BadChar, /* 131 */ BadChar, 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 132 */ BadChar, /* 133 */ BadChar, /* 134 */ BadChar, /* 135 */ BadChar, 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 136 */ BadChar, /* 137 */ BadChar, /* 138 */ BadChar, /* 139 */ BadChar, 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 140 */ BadChar, /* 141 */ BadChar, /* 142 */ BadChar, /* 143 */ BadChar, 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 144 */ BadChar, /* 145 */ BadChar, /* 146 */ BadChar, /* 147 */ BadChar, 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 148 */ BadChar, /* 149 */ BadChar, /* 150 */ BadChar, /* 151 */ BadChar, 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 152 */ BadChar, /* 153 */ BadChar, /* 154 */ BadChar, /* 155 */ BadChar, 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 156 */ BadChar, /* 157 */ BadChar, /* 158 */ BadChar, /* 159 */ BadChar, 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 160 */ BadChar, /* 161 */ BadChar, /* 162 */ BadChar, /* 163 */ BadChar, 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 164 */ BadChar, /* 165 */ BadChar, /* 166 */ BadChar, /* 167 */ BadChar, 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 168 */ BadChar, /* 169 */ BadChar, /* 170 */ BadChar, /* 171 */ BadChar, 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 172 */ BadChar, /* 173 */ BadChar, /* 174 */ BadChar, /* 175 */ BadChar, 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 176 */ BadChar, /* 177 */ BadChar, /* 178 */ BadChar, /* 179 */ BadChar, 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 180 */ BadChar, /* 181 */ BadChar, /* 182 */ BadChar, /* 183 */ BadChar, 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 184 */ BadChar, /* 185 */ BadChar, /* 186 */ BadChar, /* 187 */ BadChar, 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 188 */ BadChar, /* 189 */ BadChar, /* 190 */ BadChar, /* 191 */ BadChar, 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 192 */ BadChar, /* 193 */ BadChar, /* 194 */ BadChar, /* 195 */ BadChar, 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 196 */ BadChar, /* 197 */ BadChar, /* 198 */ BadChar, /* 199 */ BadChar, 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 200 */ BadChar, /* 201 */ BadChar, /* 202 */ BadChar, /* 203 */ BadChar, 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 204 */ BadChar, /* 205 */ BadChar, /* 206 */ BadChar, /* 207 */ BadChar, 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 208 */ BadChar, /* 209 */ BadChar, /* 210 */ BadChar, /* 211 */ BadChar, 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 212 */ BadChar, /* 213 */ BadChar, /* 214 */ BadChar, /* 215 */ BadChar, 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 216 */ BadChar, /* 217 */ BadChar, /* 218 */ BadChar, /* 219 */ BadChar, 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 220 */ BadChar, /* 221 */ BadChar, /* 222 */ BadChar, /* 223 */ BadChar, 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 224 */ BadChar, /* 225 */ BadChar, /* 226 */ BadChar, /* 227 */ BadChar, 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 228 */ BadChar, /* 229 */ BadChar, /* 230 */ BadChar, /* 231 */ BadChar, 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 232 */ BadChar, /* 233 */ BadChar, /* 234 */ BadChar, /* 235 */ BadChar, 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 236 */ BadChar, /* 237 */ BadChar, /* 238 */ BadChar, /* 239 */ BadChar, 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 240 */ BadChar, /* 241 */ BadChar, /* 242 */ BadChar, /* 243 */ BadChar, 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 244 */ BadChar, /* 245 */ BadChar, /* 246 */ BadChar, /* 247 */ BadChar, 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 248 */ BadChar, /* 249 */ BadChar, /* 250 */ BadChar, /* 251 */ BadChar, 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* 252 */ BadChar, /* 253 */ BadChar, /* 254 */ BadChar, /* 255 */ BadChar 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd); 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void encodeRelativeString(const String& rel, const TextEncoding&, CharBuffer& ouput); 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic String substituteBackslashes(const String&); 224d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic bool isValidProtocol(const String&); 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeFirstChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & SchemeFirstChar; } 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeFirstChar(UChar c) { return c <= 0xff && (characterClassTable[c] & SchemeFirstChar); } 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & SchemeChar; } 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isSchemeChar(UChar c) { return c <= 0xff && (characterClassTable[c] & SchemeChar); } 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isUserInfoChar(unsigned char c) { return characterClassTable[c] & UserInfoChar; } 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isHostnameChar(unsigned char c) { return characterClassTable[c] & HostnameChar; } 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isIPv6Char(unsigned char c) { return characterClassTable[c] & IPv6Char; } 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isPathSegmentEndChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & PathSegmentEndChar; } 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isPathSegmentEndChar(UChar c) { return c <= 0xff && (characterClassTable[c] & PathSegmentEndChar); } 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isBadChar(unsigned char c) { return characterClassTable[c] & BadChar; } 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline int hexDigitValue(UChar c) 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(isASCIIHexDigit(c)); 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c < 'A') 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c - '0'; 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return (c - 'A' + 10) & 0xF; // handle both upper and lower case without a branch 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Copies the source to the destination, assuming all the source characters are 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ASCII. The destination buffer must be large enough. Null characters are allowed 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in the source string, and no attempt is made to null-terminate the result. 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void copyASCII(const UChar* src, int length, char* dest) 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < length; i++) 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dest[i] = static_cast<char>(src[i]); 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void appendASCII(const String& base, const char* rel, size_t len, CharBuffer& buffer) 255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer.resize(base.length() + len + 1); 257635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project copyASCII(base.characters(), base.length(), buffer.data()); 258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project memcpy(buffer.data() + base.length(), rel, len); 259635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer[buffer.size() - 1] = '\0'; 260635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 261635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Move to PlatformString.h eventually. 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns the index of the first index in string |s| of any of the characters 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in |toFind|. |toFind| should be a null-terminated string, all characters up 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// to the null will be searched. Returns int if not found. 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic int findFirstOf(const UChar* s, int sLen, int startPos, const char* toFind) 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = startPos; i < sLen; i++) { 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* cur = toFind; 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (*cur) { 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (s[i] == *(cur++)) 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return i; 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return -1; 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 279635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void checkEncodedString(const String& url) 280635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 281635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (unsigned i = 0; i < url.length(); ++i) 282635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!(url[i] & ~0x7F)); 283635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 284635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!url.length() || isSchemeFirstChar(url[0])); 285635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 286635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else 287635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void checkEncodedString(const String&) 288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline bool KURL::protocolIs(const String& string, const char* protocol) 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return WebCore::protocolIs(string, protocol); 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::invalidate() 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isValid = false; 3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_protocolInHTTPFamily = false; 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_schemeEnd = 0; 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userStart = 0; 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userEnd = 0; 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_passwordEnd = 0; 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_hostEnd = 0; 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_portEnd = 0; 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathEnd = 0; 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathAfterLastSlash = 0; 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_queryEnd = 0; 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_fragmentEnd = 0; 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 313231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockKURL::KURL(ParsedURLStringTag, const char* url) 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(url, 0); 316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(url == m_string); 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 319231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockKURL::KURL(ParsedURLStringTag, const String& url) 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 321635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(url); 322635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(url == m_string); 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3252fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockKURL::KURL(ParsedURLStringTag, const URLString& url) 3262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 3272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block parse(url.string()); 3282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(url.string() == m_string); 3292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 3302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectKURL::KURL(const KURL& base, const String& relative) 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project init(base, relative, UTF8Encoding()); 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectKURL::KURL(const KURL& base, const String& relative, const TextEncoding& encoding) 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 338635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // For UTF-{7,16,32}, we want to use UTF-8 for the query part as 339635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // we do when submitting a form. A form with GET method 340635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // has its contents added to a URL as query params and it makes sense 341635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to be consistent. 342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project init(base, relative, encoding.encodingForFormSubmission()); 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 34581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic bool shouldTrimFromURL(unsigned char c) 34681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 34781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Browsers ignore leading/trailing whitespace and control 34881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // characters from URLs. Note that c is an *unsigned* char here 34981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // so this comparison should only catch control characters. 35081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return c <= ' '; 35181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 35281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::init(const KURL& base, const String& relative, const TextEncoding& encoding) 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Allow resolutions with a null or empty base URL, but not with any other invalid one. 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Is this a good rule? 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!base.m_isValid && !base.isEmpty()) { 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = relative; 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For compatibility with Win IE, treat backslashes as if they were slashes, 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // as long as we're not dealing with javascript: or data: URLs. 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String rel = relative; 3665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (rel.contains('\\') && !(protocolIsJavaScript(rel) || protocolIs(rel, "data"))) 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project rel = substituteBackslashes(rel); 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String* originalString = &rel; 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool allASCII = charactersAreAllASCII(rel.characters(), rel.length()); 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer strBuffer; 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* str; 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t len; 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (allASCII) { 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project len = rel.length(); 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strBuffer.resize(len + 1); 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project copyASCII(rel.characters(), len, strBuffer.data()); 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strBuffer[len] = 0; 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str = strBuffer.data(); 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project encodeRelativeString(rel, encoding, strBuffer); 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str = strBuffer.data(); 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project len = strlen(str); 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 38881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Get rid of leading whitespace and control characters. 38981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch while (len && shouldTrimFromURL(*str)) { 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str++; 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project --len; 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 39581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Get rid of trailing whitespace and control characters. 39681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch while (len && shouldTrimFromURL(str[len - 1])) { 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str[--len] = '\0'; 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // According to the RFC, the reference should be interpreted as an 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // absolute URI if possible, using the "leftmost, longest" 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // algorithm. If the URI reference is absolute it will have a 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // scheme, meaning that it will have a colon before the first 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // non-scheme element. 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool absolute = false; 4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = str; 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isSchemeFirstChar(*p)) { 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isSchemeChar(*p)) { 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (*p == ':') { 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p[1] != '/' && equalIgnoringCase(base.protocol(), String(str, p - str)) && base.isHierarchical()) { 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str = p + 1; 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalString = 0; 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project absolute = true; 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 422635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CharBuffer parseBuffer; 423635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (absolute) { 4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(str, originalString); 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If the base is empty or opaque (e.g. data: or javascript:), then the URL is invalid 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // unless the relative URL is a single fragment. 4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!base.isHierarchical()) { 430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (str[0] == '#') { 431635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer); 432635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 433635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = relative; 4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (str[0]) { 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project case '\0': 4425e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block // The reference is empty, so this is a reference to the same document with any fragment identifier removed. 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *this = base; 4445e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block removeFragmentIdentifier(); 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 446635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project case '#': { 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // must be fragment-only reference 448635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer); 449635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 451635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 452635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project case '?': { 4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // query-only reference, special case needed for non-URL results 454635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_pathEnd), str, len, parseBuffer); 455635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 457635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project case '/': 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // must be net-path or absolute-path reference 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (str[1] == '/') { 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // net-path 462635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_schemeEnd + 1), str, len, parseBuffer); 463635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // abs-path 466635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendASCII(base.m_string.left(base.m_portEnd), str, len, parseBuffer); 467635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project default: 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // must be relative-path reference 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Base part plus relative part plus one possible slash added in between plus terminating \0 byte. 475635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parseBuffer.resize(base.m_pathEnd + 1 + len + 1); 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 477635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project char* bufferPos = parseBuffer.data(); 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // first copy everything before the path from the base 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned baseLength = base.m_string.length(); 4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* baseCharacters = base.m_string.characters(); 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer baseStringBuffer(baseLength); 483635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project copyASCII(baseCharacters, baseLength, baseStringBuffer.data()); 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseString = baseStringBuffer.data(); 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringStart = baseString; 4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* pathStart = baseStringStart + base.m_portEnd; 4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (baseStringStart < pathStart) 4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *bufferPos++ = *baseStringStart++; 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* bufferPathStart = bufferPos; 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // now copy the base path 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringEnd = baseString + base.m_pathEnd; 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // go back to the last slash 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (baseStringEnd > baseStringStart && baseStringEnd[-1] != '/') 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringEnd--; 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (baseStringEnd == baseStringStart) { 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // no path in base, add a path separator if necessary 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (base.m_schemeEnd + 1 != base.m_pathEnd && *str && *str != '?' && *str != '#') 5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *bufferPos++ = '/'; 5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos += copyPathRemovingDots(bufferPos, baseStringStart, 0, baseStringEnd - baseStringStart); 5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* relStringStart = str; 5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* relStringPos = relStringStart; 5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (*relStringPos && *relStringPos != '?' && *relStringPos != '#') { 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (relStringPos[0] == '.' && bufferPos[-1] == '/') { 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isPathSegmentEndChar(relStringPos[1])) { 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over "." segment 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos += 1; 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (relStringPos[0] == '/') 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos++; 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (relStringPos[1] == '.' && isPathSegmentEndChar(relStringPos[2])) { 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over ".." segment and rewind the last segment 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the RFC leaves it up to the app to decide what to do with excess 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ".." segments - we choose to drop them since some web content 5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // relies on this. 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos += 2; 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (relStringPos[0] == '/') 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos++; 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (bufferPos > bufferPathStart + 1) 5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos--; 5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (bufferPos > bufferPathStart + 1 && bufferPos[-1] != '/') 5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos--; 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *bufferPos = *relStringPos; 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project relStringPos++; 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferPos++; 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // all done with the path work, now copy any remainder 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // of the relative reference; this will also add a null terminator 5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strcpy(bufferPos, relStringPos); 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 542635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project parse(parseBuffer.data(), 0); 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 544635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(strlen(parseBuffer.data()) + 1 <= parseBuffer.size()); 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 551635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectKURL KURL::copy() const 552635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 553635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project KURL result = *this; 554231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block result.m_string = result.m_string.crossThreadString(); 555635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return result; 556635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 557635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool KURL::hasPath() const 5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_pathEnd != m_portEnd; 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::lastPathComponent() const 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!hasPath()) 5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 568f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned end = m_pathEnd - 1; 5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_string[end] == '/') 5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project --end; 5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 572f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t start = m_string.reverseFind('/', end); 573f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (start < static_cast<unsigned>(m_portEnd)) 5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++start; 5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string.substring(start, end - start + 1); 5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::protocol() const 5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string.left(m_schemeEnd); 5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::host() const 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int start = hostStart(); 5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(m_string.substring(start, m_hostEnd - start)); 5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectunsigned short KURL::port() const 5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 593dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We return a port of 0 if there is no port specified. This can happen in two situations: 594dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 1) The URL contains no colon after the host name and before the path component of the URL. 595dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 2) The URL contains a colon but there's no port number before the path component of the URL begins. 596dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_hostEnd == m_portEnd || m_hostEnd == m_portEnd - 1) 5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 599dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block const UChar* stringData = m_string.characters(); 600dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block bool ok = false; 601dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block unsigned number = charactersToUIntStrict(stringData + m_hostEnd + 1, m_portEnd - m_hostEnd - 1, &ok); 602dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!ok || number > maximumValidPortNumber) 603dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return invalidPortNumber; 6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return number; 6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::pass() const 6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_passwordEnd == m_userEnd) 6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(m_string.substring(m_userEnd + 1, m_passwordEnd - m_userEnd - 1)); 6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::user() const 6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(m_string.substring(m_userStart, m_userEnd - m_userStart)); 6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochString KURL::fragmentIdentifier() const 6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_fragmentEnd == m_queryEnd) 6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string.substring(m_queryEnd + 1, m_fragmentEnd - (m_queryEnd + 1)); 6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool KURL::hasFragmentIdentifier() const 6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_fragmentEnd != m_queryEnd; 6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 633a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid KURL::copyParsedQueryTo(ParsedURLParameters& parameters) const 634a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 635a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* pos = m_string.characters() + m_pathEnd + 1; 636a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* end = m_string.characters() + m_queryEnd; 637a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch while (pos < end) { 638a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* parameterStart = pos; 639a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch while (pos < end && *pos != '&') 640a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++pos; 641a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* parameterEnd = pos; 642a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (pos < end) { 643a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(*pos == '&'); 644a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++pos; 645a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 646a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (parameterStart == parameterEnd) 647a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch continue; 648a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* nameStart = parameterStart; 649a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* equalSign = parameterStart; 650a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch while (equalSign < parameterEnd && *equalSign != '=') 651a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++equalSign; 652a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (equalSign == nameStart) 653a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch continue; 654a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch String name(nameStart, equalSign - nameStart); 655a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch String value = equalSign == parameterEnd ? String() : String(equalSign + 1, parameterEnd - equalSign - 1); 656a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch parameters.set(name, value); 657a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 658a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 659a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 6608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianString KURL::baseAsString() const 6618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 6628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return m_string.left(m_pathAfterLastSlash); 6638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 6648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 665635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifdef NDEBUG 666635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 667635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void assertProtocolIsGood(const char*) 668635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 669635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 670635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 671635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else 672635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 673635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void assertProtocolIsGood(const char* protocol) 6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* p = protocol; 6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (*p) { 6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(*p > ' ' && *p < 0x7F && !(*p >= 'A' && *p <= 'Z')); 6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 682635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 683635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool KURL::protocolIs(const char* protocol) const 6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project assertProtocolIsGood(protocol); 6875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // JavaScript URLs are "valid" and should be executed even if KURL decides they are invalid. 6895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The free function protocolIsJavaScript() should be used instead. 690643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(!equalIgnoringCase(protocol, String("javascript"))); 6915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 6955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Do the comparison without making a new string object. 6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < m_schemeEnd; ++i) { 6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!protocol[i] || toASCIILower(m_string[i]) != protocol[i]) 6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return !protocol[m_schemeEnd]; // We should have consumed all characters in the argument. 7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::query() const 7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_queryEnd == m_pathEnd) 7068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return String(); 7078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 7088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return m_string.substring(m_pathEnd + 1, m_queryEnd - (m_pathEnd + 1)); 7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::path() const 7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(m_string.substring(m_portEnd, m_pathEnd - m_portEnd)); 7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 716d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool KURL::setProtocol(const String& s) 7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 718d0825bca7fe65beaee391d30da42e937db621564Steve Block // Firefox and IE remove everything after the first ':'. 719f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t separatorPosition = s.find(':'); 720d0825bca7fe65beaee391d30da42e937db621564Steve Block String newProtocol = s.substring(0, separatorPosition); 721d0825bca7fe65beaee391d30da42e937db621564Steve Block 722d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!isValidProtocol(newProtocol)) 723d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 724635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) { 726d0825bca7fe65beaee391d30da42e937db621564Steve Block parse(newProtocol + ":" + m_string); 727d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 730d0825bca7fe65beaee391d30da42e937db621564Steve Block parse(newProtocol + m_string.substring(m_schemeEnd)); 731d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setHost(const String& s) 7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 739635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 740635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just the host. 741635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool slashSlashNeeded = m_userStart == m_schemeEnd + 1; 7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(hostStart()) + (slashSlashNeeded ? "//" : "") + s + m_string.substring(m_hostEnd)); 7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 747643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid KURL::removePort() 748643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 749643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (m_hostEnd == m_portEnd) 750643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 751643ca7872b450ea4efacab6188849e5aac2ba161Steve Block parse(m_string.left(m_hostEnd) + m_string.substring(m_portEnd)); 752643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 753643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setPort(unsigned short i) 7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 759643ca7872b450ea4efacab6188849e5aac2ba161Steve Block bool colonNeeded = m_portEnd == m_hostEnd; 760643ca7872b450ea4efacab6188849e5aac2ba161Steve Block int portStart = (colonNeeded ? m_hostEnd : m_hostEnd + 1); 7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 762643ca7872b450ea4efacab6188849e5aac2ba161Steve Block parse(m_string.left(portStart) + (colonNeeded ? ":" : "") + String::number(i) + m_string.substring(m_portEnd)); 7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setHostAndPort(const String& hostAndPort) 7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 770635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 771635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just host and port. 772635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool slashSlashNeeded = m_userStart == m_schemeEnd + 1; 7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(hostStart()) + (slashSlashNeeded ? "//" : "") + hostAndPort + m_string.substring(m_portEnd)); 7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setUser(const String& user) 7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 783635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 784635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just the user login. 7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String u; 7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int end = m_userEnd; 7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!user.isEmpty()) { 7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project u = user; 7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userStart == m_schemeEnd + 1) 7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project u = "//" + u; 7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Add '@' if we didn't have one before. 7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (end == m_hostEnd || (end == m_passwordEnd && m_string[end] != '@')) 7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project u.append('@'); 7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove '@' if we now have neither user nor password. 7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userEnd == m_passwordEnd && end != m_hostEnd && m_string[end] == '@') 7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project end += 1; 7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_userStart) + u + m_string.substring(end)); 8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setPass(const String& password) 8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 807635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, 808635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and to avoid changing more than just the user password. 8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String p; 8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int end = m_passwordEnd; 8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!password.isEmpty()) { 8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = ":" + password + "@"; 8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userEnd == m_schemeEnd + 1) 8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = "//" + p; 8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Eat the existing '@' since we are going to add our own. 8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (end != m_hostEnd && m_string[end] == '@') 8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project end += 1; 8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove '@' if we now have neither user nor password. 8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userStart == m_userEnd && end != m_hostEnd && m_string[end] == '@') 8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project end += 1; 8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_userEnd) + p + m_string.substring(end)); 8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid KURL::setFragmentIdentifier(const String& s) 8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 830635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 831635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations. 8320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch parse(m_string.left(m_queryEnd) + "#" + s); 8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid KURL::removeFragmentIdentifier() 8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_queryEnd)); 8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setQuery(const String& query) 8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 847635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: '#' and non-ASCII characters must be encoded and escaped. 848635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Usually, the query is encoded using document encoding, not UTF-8, but we don't have 849635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // access to the document in this function. 8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((query.isEmpty() || query[0] != '?') && !query.isNull()) 8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_pathEnd) + "?" + query + m_string.substring(m_queryEnd)); 8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_pathEnd) + query + m_string.substring(m_queryEnd)); 8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::setPath(const String& s) 8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 862635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: encodeWithURLEscapeSequences does not correctly escape '#' and '?', so fragment and query parts 863635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // may be inadvertently affected. 8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(s) + m_string.substring(m_pathEnd)); 8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString KURL::prettyURL() const 8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string; 8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> result; 8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(result, protocol()); 8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(':'); 8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> authority; 8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_hostEnd != m_passwordEnd) { 8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_userEnd != m_userStart) { 8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(authority, user()); 8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project authority.append('@'); 8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(authority, host()); 885643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (hasPort()) { 8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project authority.append(':'); 8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(authority, String::number(port())); 8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!authority.isEmpty()) { 8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(authority); 8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (protocolIs("file")) { 8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('/'); 8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(result, path()); 9018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 9028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_pathEnd != m_queryEnd) { 9038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.append('?'); 9048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian append(result, query()); 9058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_fragmentEnd != m_queryEnd) { 9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append('#'); 9090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch append(result, fragmentIdentifier()); 9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String::adopt(result); 9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString decodeURLEscapeSequences(const String& str) 9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return decodeURLEscapeSequences(str, UTF8Encoding()); 9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString decodeURLEscapeSequences(const String& str, const TextEncoding& encoding) 9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> result; 9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer buffer; 9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 926f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned length = str.length(); 927f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned decodedPosition = 0; 928f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned searchPosition = 0; 929f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t encodedRunPosition; 930f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick while ((encodedRunPosition = str.find('%', searchPosition)) != notFound) { 9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the sequence of %-escape codes. 932f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned encodedRunEnd = encodedRunPosition; 9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (length - encodedRunEnd >= 3 9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && str[encodedRunEnd] == '%' 9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && isASCIIHexDigit(str[encodedRunEnd + 1]) 9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && isASCIIHexDigit(str[encodedRunEnd + 2])) 9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project encodedRunEnd += 3; 9382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block searchPosition = encodedRunEnd; 9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (encodedRunEnd == encodedRunPosition) { 9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++searchPosition; 9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Decode the %-escapes into bytes. 9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned runLength = (encodedRunEnd - encodedRunPosition) / 3; 9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.resize(runLength); 9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = buffer.data(); 9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* q = str.characters() + encodedRunPosition; 9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < runLength; ++i) { 9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = (hexDigitValue(q[1]) << 4) | hexDigitValue(q[2]); 9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project q += 3; 9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Decode the bytes into Unicode characters. 9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String decoded = (encoding.isValid() ? encoding : UTF8Encoding()).decode(buffer.data(), p - buffer.data()); 9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (decoded.isEmpty()) 9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Build up the string with what we just skipped and what we just decoded. 9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(str.characters() + decodedPosition, encodedRunPosition - decodedPosition); 9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(decoded.characters(), decoded.length()); 9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decodedPosition = encodedRunEnd; 9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(str.characters() + decodedPosition, length - decodedPosition); 9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String::adopt(result); 9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// Caution: This function does not bounds check. 9712fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic void appendEscapedChar(char*& buffer, unsigned char c) 9722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 9732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *buffer++ = '%'; 9742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *buffer++ = hexDigits[c >> 4]; 9752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *buffer++ = hexDigits[c & 0xF]; 9762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 9772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void appendEscapingBadChars(char*& buffer, const char* strStart, size_t length) 9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = buffer; 9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* str = strStart; 9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* strEnd = strStart + length; 9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (str < strEnd) { 9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned char c = *str++; 9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isBadChar(c)) { 9872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (c == '%' || c == '?') 9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = c; 9892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else if (c != 0x09 && c != 0x0a && c != 0x0d) 9902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block appendEscapedChar(p, c); 9912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } else 9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = c; 9932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 9942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block buffer = p; 9962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 9972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9982fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic void escapeAndAppendFragment(char*& buffer, const char* strStart, size_t length) 9992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 10002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block char* p = buffer; 10012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* str = strStart; 10032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* strEnd = strStart + length; 10042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block while (str < strEnd) { 10052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block unsigned char c = *str++; 10062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Strip CR, LF and Tab from fragments, per: 10072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // https://bugs.webkit.org/show_bug.cgi?id=8770 10082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (c == 0x09 || c == 0x0a || c == 0x0d) 10092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block continue; 10102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Chrome and IE allow non-ascii characters in fragments, however doing 10122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // so would hit an ASSERT in checkEncodedString, so for now we don't. 10132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (c < 0x20 || c >= 127) { 10142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block appendEscapedChar(p, c); 10152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block continue; 10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = c; 10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer = p; 10218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// copy a path, accounting for "." and ".." segments 10248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd) 10258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* bufferPathStart = dst; 10278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // empty path is a special case, and need not have a leading slash 10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (srcStart != srcEnd) { 10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringStart = src + srcStart; 10318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringEnd = src + srcEnd; 10328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* baseStringPos = baseStringStart; 10338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // this code is unprepared for paths that do not begin with a 10358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // slash and we should always have one in the source string 10368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(baseStringPos[0] == '/'); 10378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy the leading slash into the destination 10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *dst = *baseStringPos; 10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos++; 10418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst++; 10428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (baseStringPos < baseStringEnd) { 10448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (baseStringPos[0] == '.' && dst[-1] == '/') { 10458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (baseStringPos[1] == '/' || baseStringPos + 1 == baseStringEnd) { 10468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over "." segment 10478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos += 2; 10488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (baseStringPos[1] == '.' && (baseStringPos[2] == '/' || 10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos + 2 == baseStringEnd)) { 10518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip over ".." segment and rewind the last segment 10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the RFC leaves it up to the app to decide what to do with excess 10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ".." segments - we choose to drop them since some web content 10548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // relies on this. 10558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos += 3; 10568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (dst > bufferPathStart + 1) 10578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst--; 10588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (dst > bufferPathStart && dst[-1] != '/') 10598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst--; 10608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 10618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *dst = *baseStringPos; 10658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project baseStringPos++; 10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dst++; 10678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *dst = '\0'; 10708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return dst - bufferPathStart; 10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool hasSlashDotOrDotDot(const char* str) 10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const unsigned char* p = reinterpret_cast<const unsigned char*>(str); 10768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!*p) 10778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 10788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned char pc = *p; 10798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (unsigned char c = *++p) { 10808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '.' && (pc == '/' || pc == '.')) 10818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pc = c; 10838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 10858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool matchLetter(char c, char lowercaseLetter) 10888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return (c | 0x20) == lowercaseLetter; 10908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::parse(const String& string) 10938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1094635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project checkEncodedString(string); 1095635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1096635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CharBuffer buffer(string.length() + 1); 1097635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project copyASCII(string.characters(), string.length(), buffer.data()); 1098635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer[string.length()] = '\0'; 10998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse(buffer.data(), &string); 11008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11022fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic inline bool equal(const char* a, size_t lenA, const char* b, size_t lenB) 11032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 11042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (lenA != lenB) 11052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 11062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return !strncmp(a, b, lenA); 11072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 11082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 11092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// List of default schemes is taken from google-url: 11102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// http://code.google.com/p/google-url/source/browse/trunk/src/url_canon_stdurl.cc#120 11112fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic inline bool isDefaultPortForScheme(const char* port, size_t portLength, const char* scheme, size_t schemeLength) 11122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 11132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // This switch is theoretically a performance optimization. It came over when 11142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // the code was moved from google-url, but may be removed later. 11152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block switch (schemeLength) { 11162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 2: 11172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("ws", 2, scheme, schemeLength) && equal("80", 2, port, portLength); 11182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 3: 11192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (equal("ftp", 3, scheme, schemeLength)) 11202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("21", 2, port, portLength); 11212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (equal("wss", 3, scheme, schemeLength)) 11222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("443", 3, port, portLength); 11232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block break; 11242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 4: 11252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("http", 4, scheme, schemeLength) && equal("80", 2, port, portLength); 11262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 5: 11272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("https", 5, scheme, schemeLength) && equal("443", 3, port, portLength); 11282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 6: 11292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return equal("gopher", 6, scheme, schemeLength) && equal("70", 2, port, portLength); 11302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 11312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 11322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 11332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::parse(const char* url, const String* originalString) 11358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!url || url[0] == '\0') { 11378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // valid URL must be non-empty 11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 11398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 11408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isSchemeFirstChar(url[0])) { 11448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // scheme must start with an alphabetic character 11458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 11468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 11478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int schemeEnd = 0; 11518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isSchemeChar(url[schemeEnd])) 11528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project schemeEnd++; 11538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[schemeEnd] != ':') { 11558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 11568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 11578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int userStart = schemeEnd + 1; 11618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int userEnd; 11628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int passwordStart; 11638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int passwordEnd; 11648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStart; 11658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostEnd; 11668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int portStart; 11678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int portEnd; 11688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool hierarchical = url[schemeEnd + 1] == '/'; 11708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool isFile = schemeEnd == 4 11728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[0], 'f') 11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[1], 'i') 11748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[2], 'l') 11758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[3], 'e'); 11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_protocolInHTTPFamily = matchLetter(url[0], 'h') 11788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[1], 't') 11798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[2], 't') 11808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[3], 'p') 11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && (url[4] == ':' || (matchLetter(url[4], 's') && url[5] == ':')); 11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hierarchical && url[schemeEnd + 2] == '/') { 11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The part after the scheme is either a net_path or an abs_path whose first path segment is empty. 11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Attempt to find an authority. 11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Authority characters may be scanned twice, and it would be nice to be faster. 11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userStart += 2; 11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 11908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int colonPos = 0; 11928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isUserInfoChar(url[userEnd])) { 11938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[userEnd] == ':' && colonPos == 0) 11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project colonPos = userEnd; 11958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd++; 11968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[userEnd] == '@') { 11998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // actual end of the userinfo, start on the host 12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (colonPos != 0) { 12018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordEnd = userEnd; 12028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = colonPos; 12038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = colonPos + 1; 12048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 12058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = passwordEnd = userEnd; 12068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = passwordEnd + 1; 12088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (url[userEnd] == '[' || isPathSegmentEndChar(url[userEnd])) { 12098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // hit the end of the authority, must have been no user 12108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // or looks like an IPv6 hostname 12118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // either way, try to parse it as a hostname 12128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 12138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = passwordEnd = userEnd; 12148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = userStart; 12158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 12168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // invalid character 12178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 12188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 12198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd = hostStart; 12238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // IPV6 IP address 12258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[hostEnd] == '[') { 12268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isIPv6Char(url[hostEnd])) 12288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[hostEnd] == ']') 12308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 12328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // invalid character 12338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 12348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 12358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 12388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isHostnameChar(url[hostEnd])) 12398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd++; 12408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[hostEnd] == ':') { 12438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = portEnd = hostEnd + 1; 12448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // possible start of port 12468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portEnd = portStart; 12478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (isASCIIDigit(url[portEnd])) 12488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portEnd++; 12498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 12508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = portEnd = hostEnd; 12518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isPathSegmentEndChar(url[portEnd])) { 12538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // invalid character 12548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = originalString ? *originalString : url; 12558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project invalidate(); 12568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (userStart == portEnd && !m_protocolInHTTPFamily && !isFile) { 12608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // No authority found, which means that this is not a net_path, but rather an abs_path whose first two 12618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // path segments are empty. For file, http and https only, an empty authority is allowed. 12628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userStart -= 2; 12638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 12648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = userEnd; 12658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordEnd = passwordStart; 12668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = passwordEnd; 12678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostEnd = hostStart; 12688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = hostEnd; 12698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portEnd = hostEnd; 12708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 12728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the part after the scheme must be an opaque_part or an abs_path 12738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project userEnd = userStart; 12748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project passwordStart = passwordEnd = userEnd; 12758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostStart = hostEnd = passwordEnd; 12768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project portStart = portEnd = hostEnd; 12778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int pathStart = portEnd; 12808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int pathEnd = pathStart; 12818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (url[pathEnd] && url[pathEnd] != '?' && url[pathEnd] != '#') 12828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd++; 12838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int queryStart = pathEnd; 12858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int queryEnd = queryStart; 12868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[queryStart] == '?') { 12878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (url[queryEnd] && url[queryEnd] != '#') 12888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project queryEnd++; 12898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int fragmentStart = queryEnd; 12928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int fragmentEnd = fragmentStart; 12938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (url[fragmentStart] == '#') { 12948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fragmentStart++; 12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fragmentEnd = fragmentStart; 12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (url[fragmentEnd]) 12978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fragmentEnd++; 12988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // assemble it all, remembering the real ranges 13018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<char, 4096> buffer(fragmentEnd * 3 + 1); 13038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char *p = buffer.data(); 13058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char *strPtr = url; 13068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the scheme 13088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char *schemeEndPtr = url + schemeEnd; 13098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < schemeEndPtr) 13102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = toASCIILower(*strPtr++); 13118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_schemeEnd = p - buffer.data(); 13128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool hostIsLocalHost = portEnd - userStart == 9 13148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart], 'l') 13158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+1], 'o') 13168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+2], 'c') 13178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+3], 'a') 13188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+4], 'l') 13198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+5], 'h') 13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+6], 'o') 13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+7], 's') 13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && matchLetter(url[userStart+8], 't'); 13238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // File URLs need a host part unless it is just file:// or file://localhost 13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool degenFilePath = pathStart == pathEnd && (hostStart == hostEnd || hostIsLocalHost); 13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool haveNonHostAuthorityPart = userStart != userEnd || passwordStart != passwordEnd || portStart != portEnd; 13288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add ":" after scheme 13308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = ':'; 13318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // if we have at least one authority part or a file URL - add "//" and authority 13338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isFile ? !degenFilePath : (haveNonHostAuthorityPart || hostStart != hostEnd)) { 13348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '/'; 13358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '/'; 13368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userStart = p - buffer.data(); 13388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the user 13408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strPtr = url + userStart; 13418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* userEndPtr = url + userEnd; 13428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < userEndPtr) 13438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = *strPtr++; 13448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userEnd = p - buffer.data(); 13458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the password 13478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (passwordEnd != passwordStart) { 13488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = ':'; 13498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strPtr = url + passwordStart; 13508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* passwordEndPtr = url + passwordEnd; 13518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < passwordEndPtr) 13528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = *strPtr++; 13538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_passwordEnd = p - buffer.data(); 13558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we had any user info, add "@" 13578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p - buffer.data() != m_userStart) 13588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '@'; 13598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // copy in the host, except in the case of a file URL with authority="localhost" 13618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!(isFile && hostIsLocalHost && !haveNonHostAuthorityPart)) { 13628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project strPtr = url + hostStart; 13638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* hostEndPtr = url + hostEnd; 13648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (strPtr < hostEndPtr) 13658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = *strPtr++; 13668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_hostEnd = p - buffer.data(); 13688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Copy in the port if the URL has one (and it's not default). 13708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hostEnd != portStart) { 13712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* portStr = url + portStart; 13722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block size_t portLength = portEnd - portStart; 13732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (portLength && !isDefaultPortForScheme(portStr, portLength, buffer.data(), m_schemeEnd)) { 13742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = ':'; 13752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const char* portEndPtr = url + portEnd; 13762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block while (portStr < portEndPtr) 13772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *p++ = *portStr++; 13782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 13798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_portEnd = p - buffer.data(); 13818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 13828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_userStart = m_userEnd = m_passwordEnd = m_hostEnd = m_portEnd = p - buffer.data(); 13838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For canonicalization, ensure we have a '/' for no path. 1385643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Do this only for hierarchical URL with protocol http or https. 1386643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (m_protocolInHTTPFamily && hierarchical && pathEnd == pathStart) 13878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '/'; 13888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add path, escaping bad characters 13908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!hierarchical || !hasSlashDotOrDotDot(url)) 13918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEscapingBadChars(p, url + pathStart, pathEnd - pathStart); 13928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 13938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer pathBuffer(pathEnd - pathStart + 1); 13948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t length = copyPathRemovingDots(pathBuffer.data(), url, pathStart, pathEnd); 13958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEscapingBadChars(p, pathBuffer.data(), length); 13968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathEnd = p - buffer.data(); 13998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the position after the last slash in the path, or 14018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the position before the path if there are no slashes in it. 14028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int i; 14038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (i = m_pathEnd; i > m_portEnd; --i) { 14048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (buffer[i - 1] == '/') 14058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 14068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pathAfterLastSlash = i; 14088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add query, escaping bad characters 14108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEscapingBadChars(p, url + queryStart, queryEnd - queryStart); 14118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_queryEnd = p - buffer.data(); 14128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // add fragment, escaping bad characters 14148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (fragmentEnd != queryEnd) { 14158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = '#'; 14162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block escapeAndAppendFragment(p, url + fragmentStart, fragmentEnd - fragmentStart); 14178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_fragmentEnd = p - buffer.data(); 14198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(p - buffer.data() <= static_cast<int>(buffer.size())); 14218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we didn't end up actually changing the original string and 14238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // it was already in a String, reuse it to avoid extra allocation. 14248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (originalString && originalString->length() == static_cast<unsigned>(m_fragmentEnd) && strncmp(buffer.data(), url, m_fragmentEnd) == 0) 14258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = *originalString; 14268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 14278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_string = String(buffer.data(), m_fragmentEnd); 14288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isValid = true; 14308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool equalIgnoringFragmentIdentifier(const KURL& a, const KURL& b) 14338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.m_queryEnd != b.m_queryEnd) 14358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 14368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned queryLength = a.m_queryEnd; 14378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < queryLength; ++i) 14388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.string()[i] != b.string()[i]) 14398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 14408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 14418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) 14448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.m_schemeEnd != b.m_schemeEnd) 14468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 144721939df44de1705786c545cd1bf519d47250322dBen Murdoch 14488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStartA = a.hostStart(); 144921939df44de1705786c545cd1bf519d47250322dBen Murdoch int hostLengthA = a.hostEnd() - hostStartA; 14508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStartB = b.hostStart(); 145121939df44de1705786c545cd1bf519d47250322dBen Murdoch int hostLengthB = b.hostEnd() - b.hostStart(); 145221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (hostLengthA != hostLengthB) 14538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 14548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check the scheme 14568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < a.m_schemeEnd; ++i) 14578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.string()[i] != b.string()[i]) 14588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 145921939df44de1705786c545cd1bf519d47250322dBen Murdoch 14608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // And the host 146121939df44de1705786c545cd1bf519d47250322dBen Murdoch for (int i = 0; i < hostLengthA; ++i) 146221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (a.string()[hostStartA + i] != b.string()[hostStartB + i]) 14638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 146421939df44de1705786c545cd1bf519d47250322dBen Murdoch 14658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (a.port() != b.port()) 14668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 14678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 14698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString encodeWithURLEscapeSequences(const String& notEncodedString) 14728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString asUTF8 = notEncodedString.utf8(); 14748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CharBuffer buffer(asUTF8.length() * 3 + 1); 14768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char* p = buffer.data(); 14778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* str = asUTF8.data(); 14798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const char* strEnd = str + asUTF8.length(); 14808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (str < strEnd) { 14818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned char c = *str++; 14822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (isBadChar(c)) 14832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block appendEscapedChar(p, c); 14842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else 14858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *p++ = c; 14868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(p - buffer.data() <= static_cast<int>(buffer.size())); 14898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(buffer.data(), p - buffer.data()); 14918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Appends the punycoded hostname identified by the given string and length to 14948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// the output buffer. The result will not be null terminated. 14958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void appendEncodedHostname(UCharBuffer& buffer, const UChar* str, unsigned strLen) 14968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Needs to be big enough to hold an IDN-encoded name. 14988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For host names bigger than this, we won't do IDN encoding, which is almost certainly OK. 14998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const unsigned hostnameBufferLength = 2048; 15008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (strLen > hostnameBufferLength || charactersAreAllASCII(str, strLen)) { 15028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.append(str, strLen); 15038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if USE(ICU_UNICODE) 15078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar hostnameBuffer[hostnameBufferLength]; 15088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UErrorCode error = U_ZERO_ERROR; 15098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int32_t numCharactersConverted = uidna_IDNToASCII(str, strLen, hostnameBuffer, 15108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameBufferLength, UIDNA_ALLOW_UNASSIGNED, 0, &error); 15118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (error == U_ZERO_ERROR) 15128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.append(hostnameBuffer, numCharactersConverted); 15138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#elif USE(QT4_UNICODE) 15148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project QByteArray result = QUrl::toAce(String(str, strLen)); 15158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.append(result.constData(), result.length()); 1516d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(GLIB_UNICODE) 1517d0825bca7fe65beaee391d30da42e937db621564Steve Block GOwnPtr<gchar> utf8Hostname; 1518d0825bca7fe65beaee391d30da42e937db621564Steve Block GOwnPtr<GError> utf8Err; 1519d0825bca7fe65beaee391d30da42e937db621564Steve Block utf8Hostname.set(g_utf16_to_utf8(str, strLen, 0, 0, &utf8Err.outPtr())); 1520d0825bca7fe65beaee391d30da42e937db621564Steve Block if (utf8Err) 1521d0825bca7fe65beaee391d30da42e937db621564Steve Block return; 1522d0825bca7fe65beaee391d30da42e937db621564Steve Block 1523d0825bca7fe65beaee391d30da42e937db621564Steve Block GOwnPtr<gchar> encodedHostname; 1524d0825bca7fe65beaee391d30da42e937db621564Steve Block encodedHostname.set(g_hostname_to_ascii(utf8Hostname.get())); 1525d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!encodedHostname) 1526d0825bca7fe65beaee391d30da42e937db621564Steve Block return; 1527d0825bca7fe65beaee391d30da42e937db621564Steve Block 1528d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.append(encodedHostname.get(), strlen(encodedHostname.get())); 15298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 15308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void findHostnamesInMailToURL(const UChar* str, int strLen, Vector<pair<int, int> >& nameRanges) 15338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The 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. 15358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Skip quoted strings so that characters in them don't confuse us. 15368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // When we find a '?' character, we are past the part of the URL that contains host names. 15378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nameRanges.clear(); 15398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int p = 0; 15418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 15428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find start of host name or of quoted string. 15438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameOrStringStart = findFirstOf(str, strLen, p, "\"@?"); 15448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hostnameOrStringStart == -1) 15458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar c = str[hostnameOrStringStart]; 15478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = hostnameOrStringStart + 1; 15488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '?') 15508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '@') { 15538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find end of host name. 15548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameStart = p; 15558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameEnd = findFirstOf(str, strLen, p, ">,?"); 15568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool done; 15578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hostnameEnd == -1) { 15588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameEnd = strLen; 15598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project done = true; 15608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 15618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = hostnameEnd; 15628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project done = false; 15638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nameRanges.append(make_pair(hostnameStart, hostnameEnd)); 15668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (done) 15688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 15708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Skip quoted string. 15718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(c == '"'); 15728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 15738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int escapedCharacterOrStringEnd = findFirstOf(str, strLen, p, "\"\\"); 15748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (escapedCharacterOrStringEnd == -1) 15758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project c = str[escapedCharacterOrStringEnd]; 15788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = escapedCharacterOrStringEnd + 1; 15798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we are the end of the string, then break from the string loop back to the host name loop. 15818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == '"') 15828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 15838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Skip escaped character. 15858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(c == '\\'); 15868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p == strLen) 15878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++p; 15908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool findHostnameInHierarchicalURL(const UChar* str, int strLen, int& startOffset, int& endOffset) 15968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the host name in a hierarchical URL. 15988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It comes after a "://" sequence, with scheme characters preceding, and 15998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // this should be the first colon in the string. 16008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It ends with the end of the string or a ":" or a path segment ending character. 16018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If there is a "@" character, the host part is just the part after the "@". 16028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int separator = findFirstOf(str, strLen, 0, ":"); 16038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (separator == -1 || separator + 2 >= strLen || 16048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project str[separator + 1] != '/' || str[separator + 2] != '/') 16058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 16068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check that all characters before the :// are valid scheme characters. 16088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isSchemeFirstChar(str[0])) 16098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 16108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 1; i < separator; ++i) { 16118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isSchemeChar(str[i])) 16128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 16138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Start after the separator. 16168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int authorityStart = separator + 3; 16178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find terminating character. 16198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameEnd = strLen; 16208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = authorityStart; i < strLen; ++i) { 16218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar c = str[i]; 16228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c == ':' || (isPathSegmentEndChar(c) && c != 0)) { 16238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameEnd = i; 16248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 16258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find "@" for the start of the host name. 16298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int userInfoTerminator = findFirstOf(str, strLen, authorityStart, "@"); 16308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostnameStart; 16318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (userInfoTerminator == -1 || userInfoTerminator > hostnameEnd) 16328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameStart = authorityStart; 16338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 16348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hostnameStart = userInfoTerminator + 1; 16358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startOffset = hostnameStart; 16378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endOffset = hostnameEnd; 16388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 16398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 16408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Converts all hostnames found in the given input to punycode, preserving the 16428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// rest of the URL unchanged. The output will NOT be null-terminated. 16438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void encodeHostnames(const String& str, UCharBuffer& output) 16448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 16458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.clear(); 16468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (protocolIs(str, "mailto")) { 16488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<pair<int, int> > hostnameRanges; 16498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project findHostnamesInMailToURL(str.characters(), str.length(), hostnameRanges); 16508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int n = hostnameRanges.size(); 16518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int p = 0; 16528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < n; ++i) { 16538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const pair<int, int>& r = hostnameRanges[i]; 16548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(&str.characters()[p], r.first - p); 16558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEncodedHostname(output, &str.characters()[r.first], r.second - r.first); 16568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = r.second; 16578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This will copy either everything after the last hostname, or the 16598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // whole thing if there is no hostname. 16608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(&str.characters()[p], str.length() - p); 16618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 16628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int hostStart, hostEnd; 16638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (findHostnameInHierarchicalURL(str.characters(), str.length(), hostStart, hostEnd)) { 16648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(str.characters(), hostStart); // Before hostname. 16658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendEncodedHostname(output, &str.characters()[hostStart], hostEnd - hostStart); 16668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(&str.characters()[hostEnd], str.length() - hostEnd); // After hostname. 16678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 16688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // No hostname to encode, return the input. 16698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append(str.characters(), str.length()); 16708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 16738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void encodeRelativeString(const String& rel, const TextEncoding& encoding, CharBuffer& output) 16758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 16768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UCharBuffer s; 16778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project encodeHostnames(rel, s); 16788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project TextEncoding pathEncoding(UTF8Encoding()); // Path is always encoded as UTF-8; other parts may depend on the scheme. 16808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int pathEnd = -1; 16825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (encoding != pathEncoding && encoding.isValid() && !protocolIs(rel, "mailto") && !protocolIs(rel, "data") && !protocolIsJavaScript(rel)) { 16838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Find the first instance of either # or ?, keep pathEnd at -1 otherwise. 16848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = findFirstOf(s.data(), s.size(), 0, "#?"); 16858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 16868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pathEnd == -1) { 16888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString decoded = pathEncoding.encode(s.data(), s.size(), URLEncodedEntitiesForUnencodables); 16898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.resize(decoded.length()); 16908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(output.data(), decoded.data(), decoded.length()); 16918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 16928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString pathDecoded = pathEncoding.encode(s.data(), pathEnd, URLEncodedEntitiesForUnencodables); 16938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Unencodable characters in URLs are represented by converting 16948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // them to XML entities and escaping non-alphanumeric characters. 16958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CString otherDecoded = encoding.encode(s.data() + pathEnd, s.size() - pathEnd, URLEncodedEntitiesForUnencodables); 16968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.resize(pathDecoded.length() + otherDecoded.length()); 16988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(output.data(), pathDecoded.data(), pathDecoded.length()); 16998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(output.data() + pathDecoded.length(), otherDecoded.data(), otherDecoded.length()); 17008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 17018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project output.append('\0'); // null-terminate the output. 17028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic String substituteBackslashes(const String& string) 17058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1706f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t questionPos = string.find('?'); 1707f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t hashPos = string.find('#'); 1708f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned pathEnd; 17098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1710f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (hashPos != notFound && (questionPos == notFound || questionPos > hashPos)) 17118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = hashPos; 1712f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick else if (questionPos != notFound) 17138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = questionPos; 17148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 17158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pathEnd = string.length(); 17168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return string.left(pathEnd).replace('\\','/') + string.substring(pathEnd); 17188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool KURL::isHierarchical() const 17218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isValid) 17238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 17248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_string[m_schemeEnd] == ':'); 17258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_string[m_schemeEnd + 1] == '/'; 17268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid KURL::copyToBuffer(CharBuffer& buffer) const 17298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This throws away the high bytes of all the characters in the string! 17318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // That's fine for a valid URL, which is all ASCII, but not for invalid URLs. 17328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.resize(m_string.length()); 17338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project copyASCII(m_string.characters(), m_string.length(), buffer.data()); 17348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 17368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool protocolIs(const String& url, const char* protocol) 17378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Do the comparison without making a new string object. 17398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project assertProtocolIsGood(protocol); 17408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; ; ++i) { 17418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!protocol[i]) 17428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return url[i] == ':'; 17438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (toASCIILower(url[i]) != protocol[i]) 17448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 17458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 17468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 17478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1748643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool isValidProtocol(const String& protocol) 1749643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 1750d0825bca7fe65beaee391d30da42e937db621564Steve Block // RFC3986: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) 1751d0825bca7fe65beaee391d30da42e937db621564Steve Block if (protocol.isEmpty()) 1752d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1753643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!isSchemeFirstChar(protocol[0])) 1754643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1755643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned protocolLength = protocol.length(); 1756643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (unsigned i = 1; i < protocolLength; i++) { 1757643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!isSchemeChar(protocol[i])) 1758643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1759643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 1760643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1761643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 1762643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 176381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#ifndef NDEBUG 176481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid KURL::print() const 176581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 176681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch printf("%s\n", m_string.utf8().data()); 176781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 176881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif 176981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 177081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif // !USE(GOOGLEURL) 177181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 177281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochString KURL::strippedForUseAsReferrer() const 177381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 177481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch KURL referrer(*this); 177581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch referrer.setUser(String()); 177681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch referrer.setPass(String()); 177781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch referrer.removeFragmentIdentifier(); 177881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return referrer.string(); 177981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 178081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 178181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool KURL::isLocalFile() const 178281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 178381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Including feed here might be a bad idea since drag and drop uses this check 178481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // and including feed would allow feeds to potentially let someone's blog 178581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // read the contents of the clipboard on a drag, even without a drop. 178681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Likewise with using the FrameLoader::shouldTreatURLAsLocal() function. 178781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return protocolIs("file"); 178881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 178981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 179081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool protocolIsJavaScript(const String& url) 179181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 179281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return protocolIs(url, "javascript"); 179381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 179481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 179581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochconst KURL& blankURL() 179681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 179781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch DEFINE_STATIC_LOCAL(KURL, staticBlankURL, (ParsedURLString, "about:blank")); 179881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return staticBlankURL; 179981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 180081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 1801643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool isDefaultPortForProtocol(unsigned short port, const String& protocol) 1802643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 1803643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (protocol.isEmpty()) 1804643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1805643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1806643ca7872b450ea4efacab6188849e5aac2ba161Steve Block typedef HashMap<String, unsigned, CaseFoldingHash> DefaultPortsMap; 1807643ca7872b450ea4efacab6188849e5aac2ba161Steve Block DEFINE_STATIC_LOCAL(DefaultPortsMap, defaultPorts, ()); 1808643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (defaultPorts.isEmpty()) { 1809643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("http", 80); 1810643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("https", 443); 1811643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("ftp", 21); 1812643ca7872b450ea4efacab6188849e5aac2ba161Steve Block defaultPorts.set("ftps", 990); 1813643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 1814643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return defaultPorts.get(protocol) == port; 1815643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 1816643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1817643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool portAllowed(const KURL& url) 1818643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 1819643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned short port = url.port(); 1820643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1821643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Since most URLs don't have a port, return early for the "no port" case. 1822643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!port) 1823643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1824643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1825643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This blocked port list matches the port blocking that Mozilla implements. 1826643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // See http://www.mozilla.org/projects/netlib/PortBanning.html for more information. 1827643ca7872b450ea4efacab6188849e5aac2ba161Steve Block static const unsigned short blockedPortList[] = { 1828643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1, // tcpmux 1829643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 7, // echo 1830643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 9, // discard 1831643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 11, // systat 1832643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 13, // daytime 1833643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 15, // netstat 1834643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 17, // qotd 1835643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 19, // chargen 1836643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 20, // FTP-data 1837643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 21, // FTP-control 1838643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 22, // SSH 1839643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 23, // telnet 1840643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 25, // SMTP 1841643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 37, // time 1842643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 42, // name 1843643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 43, // nicname 1844643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 53, // domain 1845643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 77, // priv-rjs 1846643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 79, // finger 1847643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 87, // ttylink 1848643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 95, // supdup 1849643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 101, // hostriame 1850643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 102, // iso-tsap 1851643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 103, // gppitnp 1852643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 104, // acr-nema 1853643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 109, // POP2 1854643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 110, // POP3 1855643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 111, // sunrpc 1856643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 113, // auth 1857643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 115, // SFTP 1858643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 117, // uucp-path 1859643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 119, // nntp 1860643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 123, // NTP 1861643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 135, // loc-srv / epmap 1862643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 139, // netbios 1863643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 143, // IMAP2 1864643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 179, // BGP 1865643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 389, // LDAP 1866643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 465, // SMTP+SSL 1867643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 512, // print / exec 1868643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 513, // login 1869643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 514, // shell 1870643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 515, // printer 1871643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 526, // tempo 1872643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 530, // courier 1873643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 531, // Chat 1874643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 532, // netnews 1875643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 540, // UUCP 1876643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 556, // remotefs 1877643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 563, // NNTP+SSL 1878643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 587, // ESMTP 1879643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 601, // syslog-conn 1880643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 636, // LDAP+SSL 1881643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 993, // IMAP+SSL 1882643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 995, // POP3+SSL 1883643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2049, // NFS 1884643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3659, // apple-sasl / PasswordServer [Apple addition] 1885643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 4045, // lockd 1886643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 6000, // X11 18875e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6665, // Alternate IRC [Apple addition] 18885e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6666, // Alternate IRC [Apple addition] 18895e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6667, // Standard IRC [Apple addition] 18905e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6668, // Alternate IRC [Apple addition] 18915e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 6669, // Alternate IRC [Apple addition] 1892dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block invalidPortNumber, // Used to block all invalid port numbers 1893643ca7872b450ea4efacab6188849e5aac2ba161Steve Block }; 18944576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang const unsigned short* const blockedPortListEnd = blockedPortList + WTF_ARRAY_LENGTH(blockedPortList); 1895643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1896643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#ifndef NDEBUG 1897643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // The port list must be sorted for binary_search to work. 1898643ca7872b450ea4efacab6188849e5aac2ba161Steve Block static bool checkedPortList = false; 1899643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!checkedPortList) { 1900643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (const unsigned short* p = blockedPortList; p != blockedPortListEnd - 1; ++p) 1901643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(*p < *(p + 1)); 1902643ca7872b450ea4efacab6188849e5aac2ba161Steve Block checkedPortList = true; 1903643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 1904643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 1905643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1906643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // If the port is not in the blocked port list, allow it. 1907643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!binary_search(blockedPortList, blockedPortListEnd, port)) 1908643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1909643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1910643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Allow ports 21 and 22 for FTP URLs, as Mozilla does. 1911643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ((port == 21 || port == 22) && url.protocolIs("ftp")) 1912643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1913643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1914643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Allow any port number in a file URL, since the port number is ignored. 1915643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (url.protocolIs("file")) 1916643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1917643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1918643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 1919643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 1920643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 19218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString mimeTypeFromDataURL(const String& url) 19228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 19238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(protocolIs(url, "data")); 1924f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t index = url.find(';'); 1925f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (index == notFound) 19268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project index = url.find(','); 1927f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (index != notFound) { 1928f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (index > 5) 1929f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return url.substring(5, index - 5); 19308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return "text/plain"; // Data URLs with no MIME type are considered text/plain. 19318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 19328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ""; 19338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 19348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 19358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1936