1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright 2007, Google Inc. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// All rights reserved. 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Redistribution and use in source and binary forms, with or without 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// modification, are permitted provided that the following conditions are 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// met: 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * Redistributions of source code must retain the above copyright 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// notice, this list of conditions and the following disclaimer. 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * Redistributions in binary form must reproduce the above 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// copyright notice, this list of conditions and the following disclaimer 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// in the documentation and/or other materials provided with the 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// distribution. 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * Neither the name of Google Inc. nor the names of its 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// contributors may be used to endorse or promote products derived from 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// this software without specific prior written permission. 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ICU integration functions. 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h> 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string.h> 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <unicode/ucnv.h> 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <unicode/ucnv_cb.h> 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <unicode/uidna.h> 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "googleurl/src/url_canon_icu.h" 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "googleurl/src/url_canon_internal.h" // for _itoa_s 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace url_canon { 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called when converting a character that can not be represented, this will 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// append an escaped version of the numerical character reference for that code 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// point. It is of the form "Ӓ" and we will escape the non-digits to 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// "%26%231234%3B". Why? This is what Netscape did back in the olden days. 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid appendURLEscapedChar(const void* context, 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UConverterFromUnicodeArgs* from_args, 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const UChar* code_units, 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int32_t length, 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UChar32 code_point, 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UConverterCallbackReason reason, 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UErrorCode* err) { 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (reason == UCNV_UNASSIGNED) { 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *err = U_ZERO_ERROR; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const static int prefix_len = 6; 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const static char prefix[prefix_len + 1] = "%26%23"; // "&#" percent-escaped 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ucnv_cbFromUWriteBytes(from_args, prefix, prefix_len, 0, err); 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(code_point < 0x110000); 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char number[8]; // Max Unicode code point is 7 digits. 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott _itoa_s(code_point, number, 10); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int number_len = static_cast<int>(strlen(number)); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ucnv_cbFromUWriteBytes(from_args, number, number_len, 0, err); 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const static int postfix_len = 3; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const static char postfix[postfix_len + 1] = "%3B"; // ";" percent-escaped 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ucnv_cbFromUWriteBytes(from_args, postfix, postfix_len, 0, err); 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A class for scoping the installation of the invalid character callback. 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass AppendHandlerInstaller { 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The owner of this object must ensure that the converter is alive for the 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // duration of this object's lifetime. 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendHandlerInstaller(UConverter* converter) : converter_(converter) { 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UErrorCode err = U_ZERO_ERROR; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ucnv_setFromUCallBack(converter_, appendURLEscapedChar, 0, 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &old_callback_, &old_context_, &err); 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~AppendHandlerInstaller() { 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UErrorCode err = U_ZERO_ERROR; 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ucnv_setFromUCallBack(converter_, old_callback_, old_context_, 0, 0, &err); 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UConverter* converter_; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UConverterFromUCallback old_callback_; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const void* old_context_; 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottICUCharsetConverter::ICUCharsetConverter(UConverter* converter) 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : converter_(converter) { 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ICUCharsetConverter::ConvertFromUTF16(const char16* input, 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int input_len, 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CanonOutput* output) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Install our error handler. It will be called for character that can not 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // be represented in the destination character set. 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendHandlerInstaller handler(converter_); 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int begin_offset = output->length(); 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int dest_capacity = output->capacity() - begin_offset; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->set_length(output->length()); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UErrorCode err = U_ZERO_ERROR; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* dest = &output->data()[begin_offset]; 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int required_capacity = ucnv_fromUChars(converter_, dest, dest_capacity, 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott input, input_len, &err); 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (err != U_BUFFER_OVERFLOW_ERROR) { 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->set_length(begin_offset + required_capacity); 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Output didn't fit, expand 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dest_capacity = required_capacity; 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->Resize(begin_offset + dest_capacity); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (true); 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Converts the Unicode input representing a hostname to ASCII using IDN rules. 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The output must be ASCII, but is represented as wide characters. 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On success, the output will be filled with the ASCII host name and it will 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// return true. Unlike most other canonicalization functions, this assumes that 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the output is empty. The beginning of the host will be at offset 0, and 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the length of the output will be set to the length of the new host name. 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On error, this will return false. The output in this case is undefined. 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool IDNToASCII(const char16* src, int src_len, CanonOutputW* output) { 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(output->length() == 0); // Output buffer is assumed empty. 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (true) { 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Use ALLOW_UNASSIGNED to be more tolerant of hostnames that violate 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the spec (which do exist). This does not present any risk and is a 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // little more future proof. 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UErrorCode err = U_ZERO_ERROR; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int num_converted = uidna_IDNToASCII(src, src_len, output->data(), 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->capacity(), 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UIDNA_ALLOW_UNASSIGNED, NULL, &err); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (err == U_ZERO_ERROR) { 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->set_length(num_converted); 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (err != U_BUFFER_OVERFLOW_ERROR) 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; // Unknown error, give up. 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not enough room in our buffer, expand. 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->Resize(output->capacity() * 2); 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ReadUTFChar(const char* str, int* begin, int length, 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unsigned* code_point_out) { 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int code_point; // Avoids warning when U8_NEXT writes -1 to it. 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott U8_NEXT(str, *begin, length, code_point); 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *code_point_out = static_cast<unsigned>(code_point); 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The ICU macro above moves to the next char, we want to point to the last 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // char consumed. 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*begin)--; 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Validate the decoded value. 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (U_IS_UNICODE_CHAR(code_point)) 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *code_point_out = kUnicodeReplacementCharacter; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ReadUTFChar(const char16* str, int* begin, int length, 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unsigned* code_point) { 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (U16_IS_SURROGATE(str[*begin])) { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!U16_IS_SURROGATE_LEAD(str[*begin]) || *begin + 1 >= length || 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott !U16_IS_TRAIL(str[*begin + 1])) { 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Invalid surrogate pair. 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *code_point = kUnicodeReplacementCharacter; 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Valid surrogate pair. 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *code_point = U16_GET_SUPPLEMENTARY(str[*begin], str[*begin + 1]); 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*begin)++; 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not a surrogate, just one 16-bit word. 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *code_point = str[*begin]; 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (U_IS_UNICODE_CHAR(*code_point)) 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Invalid code point. 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *code_point = kUnicodeReplacementCharacter; 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace url_canon 208