1bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Copyright 2016 the V8 project authors. All rights reserved. 2bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// found in the LICENSE file. 4bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/uri.h" 6bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 7bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/char-predicates-inl.h" 8bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/handles.h" 9bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/isolate-inl.h" 10bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/list.h" 1113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/string-search.h" 12bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 13bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace v8 { 14bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace internal { 15bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace { // anonymous namespace for DecodeURI helper functions 1713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool IsReservedPredicate(uc16 c) { 1813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch switch (c) { 1913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '#': 2013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '$': 2113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '&': 2213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '+': 2313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case ',': 2413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '/': 2513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case ':': 2613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case ';': 2713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '=': 2813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '?': 2913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '@': 3013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return true; 3113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch default: 3213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 3313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 3413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 3513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 3613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool IsReplacementCharacter(const uint8_t* octets, int length) { 3713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The replacement character is at codepoint U+FFFD in the Unicode Specials 3813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // table. Its UTF-8 encoding is 0xEF 0xBF 0xBD. 3913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (length != 3 || octets[0] != 0xef || octets[1] != 0xbf || 4013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch octets[2] != 0xbd) { 4113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 4213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 4313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return true; 4413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 4513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 4613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool DecodeOctets(const uint8_t* octets, int length, List<uc16>* buffer) { 4713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch size_t cursor = 0; 4813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uc32 value = unibrow::Utf8::ValueOf(octets, length, &cursor); 4913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (value == unibrow::Utf8::kBadChar && 5013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch !IsReplacementCharacter(octets, length)) { 5113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 5313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 54c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (value <= static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) { 5513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add(value); 5613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 5713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add(unibrow::Utf16::LeadSurrogate(value)); 5813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add(unibrow::Utf16::TrailSurrogate(value)); 5913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 6013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return true; 6113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 6213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 6313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochint TwoDigitHex(uc16 character1, uc16 character2) { 6413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (character1 > 'f') return -1; 6513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int high = HexValue(character1); 6613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (high == -1) return -1; 6713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (character2 > 'f') return -1; 6813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int low = HexValue(character2); 6913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (low == -1) return -1; 7013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return (high << 4) + low; 7113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 7213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 7313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename T> 7413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid AddToBuffer(uc16 decoded, String::FlatContent* uri_content, int index, 7513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch bool is_uri, List<T>* buffer) { 7613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (is_uri && IsReservedPredicate(decoded)) { 7713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add('%'); 7813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uc16 first = uri_content->Get(index + 1); 7913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uc16 second = uri_content->Get(index + 2); 8013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_GT(std::numeric_limits<T>::max(), first); 8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_GT(std::numeric_limits<T>::max(), second); 8213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 8313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add(first); 8413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add(second); 8513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 8613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add(decoded); 8713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 8813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 8913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 9013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool IntoTwoByte(int index, bool is_uri, int uri_length, 9113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch String::FlatContent* uri_content, List<uc16>* buffer) { 9213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int k = index; k < uri_length; k++) { 9313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uc16 code = uri_content->Get(k); 9413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (code == '%') { 95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int two_digits; 9613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (k + 2 >= uri_length || 97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch (two_digits = TwoDigitHex(uri_content->Get(k + 1), 98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uri_content->Get(k + 2))) < 0) { 9913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 10013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 10113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch k += 2; 102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uc16 decoded = static_cast<uc16>(two_digits); 10313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (decoded > unibrow::Utf8::kMaxOneByteChar) { 10413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint8_t octets[unibrow::Utf8::kMaxEncodedSize]; 10513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch octets[0] = decoded; 10613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 10713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int number_of_continuation_bytes = 0; 10813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch while ((decoded << ++number_of_continuation_bytes) & 0x80) { 10913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (number_of_continuation_bytes > 3 || k + 3 >= uri_length) { 11013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 11113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 11213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (uri_content->Get(++k) != '%' || 113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch (two_digits = TwoDigitHex(uri_content->Get(k + 1), 114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uri_content->Get(k + 2))) < 0) { 11513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 11613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 11713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch k += 2; 118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uc16 continuation_byte = static_cast<uc16>(two_digits); 11913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch octets[number_of_continuation_bytes] = continuation_byte; 12013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 12113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 12213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!DecodeOctets(octets, number_of_continuation_bytes, buffer)) { 12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 12413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 12613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AddToBuffer(decoded, uri_content, k - 2, is_uri, buffer); 12713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 12813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch buffer->Add(code); 13013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 13113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 13213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return true; 13313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 13413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 13513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool IntoOneAndTwoByte(Handle<String> uri, bool is_uri, 13613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch List<uint8_t>* one_byte_buffer, 13713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch List<uc16>* two_byte_buffer) { 13813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DisallowHeapAllocation no_gc; 13913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch String::FlatContent uri_content = uri->GetFlatContent(); 14013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 14113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int uri_length = uri->length(); 14213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int k = 0; k < uri_length; k++) { 14313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uc16 code = uri_content.Get(k); 14413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (code == '%') { 145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int two_digits; 14613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (k + 2 >= uri_length || 147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch (two_digits = TwoDigitHex(uri_content.Get(k + 1), 148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uri_content.Get(k + 2))) < 0) { 14913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 15013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 15113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uc16 decoded = static_cast<uc16>(two_digits); 15313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (decoded > unibrow::Utf8::kMaxOneByteChar) { 15413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return IntoTwoByte(k, is_uri, uri_length, &uri_content, 15513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch two_byte_buffer); 15613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 15713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 15813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AddToBuffer(decoded, &uri_content, k, is_uri, one_byte_buffer); 15913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch k += 2; 16013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 16113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (code > unibrow::Utf8::kMaxOneByteChar) { 16213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return IntoTwoByte(k, is_uri, uri_length, &uri_content, 16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch two_byte_buffer); 16413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 16513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch one_byte_buffer->Add(code); 16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 16713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 16813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return true; 16913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 17013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 17113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} // anonymous namespace 17213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 17313e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochMaybeHandle<String> Uri::Decode(Isolate* isolate, Handle<String> uri, 17413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch bool is_uri) { 17513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uri = String::Flatten(uri); 17613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch List<uint8_t> one_byte_buffer; 17713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch List<uc16> two_byte_buffer; 17813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 17913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!IntoOneAndTwoByte(uri, is_uri, &one_byte_buffer, &two_byte_buffer)) { 18013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch THROW_NEW_ERROR(isolate, NewURIError(), String); 18113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 18213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 18313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (two_byte_buffer.is_empty()) { 18413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return isolate->factory()->NewStringFromOneByte( 18513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch one_byte_buffer.ToConstVector()); 18613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 18713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 18813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<SeqTwoByteString> result; 18913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ASSIGN_RETURN_ON_EXCEPTION( 19013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch isolate, result, isolate->factory()->NewRawTwoByteString( 19113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch one_byte_buffer.length() + two_byte_buffer.length()), 19213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch String); 19313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 19413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(), 19513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch one_byte_buffer.length()); 19613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CopyChars(result->GetChars() + one_byte_buffer.length(), 19713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch two_byte_buffer.ToConstVector().start(), two_byte_buffer.length()); 19813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return result; 20013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 20113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace { // anonymous namespace for EncodeURI helper functions 203bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochbool IsUnescapePredicateInUriComponent(uc16 c) { 204bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IsAlphaNumeric(c)) { 205bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return true; 206bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch switch (c) { 209bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '!': 210bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '\'': 211bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '(': 212bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case ')': 213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '*': 214bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '-': 215bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '.': 216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '_': 217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '~': 218bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return true; 219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch default: 220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return false; 221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 223bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochbool IsUriSeparator(uc16 c) { 225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch switch (c) { 226bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '#': 227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case ':': 228bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case ';': 229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '/': 230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '?': 231bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '$': 232bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '&': 233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '+': 234bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case ',': 235bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '@': 236bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case '=': 237bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return true; 238bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch default: 239bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return false; 240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 241bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 242bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 24313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid AddEncodedOctetToBuffer(uint8_t octet, List<uint8_t>* buffer) { 244bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch buffer->Add('%'); 245bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch buffer->Add(HexCharOfValue(octet >> 4)); 246bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch buffer->Add(HexCharOfValue(octet & 0x0F)); 247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 248bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 249bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid EncodeSingle(uc16 c, List<uint8_t>* buffer) { 25013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch char s[4] = {}; 25113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int number_of_bytes; 25213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch number_of_bytes = 25313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch unibrow::Utf8::Encode(s, c, unibrow::Utf16::kNoPreviousCharacter, false); 25413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int k = 0; k < number_of_bytes; k++) { 25513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AddEncodedOctetToBuffer(s[k], buffer); 256bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 257bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid EncodePair(uc16 cc1, uc16 cc2, List<uint8_t>* buffer) { 26013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch char s[4] = {}; 26113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int number_of_bytes = 26213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch unibrow::Utf8::Encode(s, unibrow::Utf16::CombineSurrogatePair(cc1, cc2), 26313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch unibrow::Utf16::kNoPreviousCharacter, false); 26413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int k = 0; k < number_of_bytes; k++) { 26513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AddEncodedOctetToBuffer(s[k], buffer); 26613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 267bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 268bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 269bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // anonymous namespace 270bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 27113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochMaybeHandle<String> Uri::Encode(Isolate* isolate, Handle<String> uri, 27213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch bool is_uri) { 273bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch uri = String::Flatten(uri); 274bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch int uri_length = uri->length(); 275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch List<uint8_t> buffer(uri_length); 276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DisallowHeapAllocation no_gc; 279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch String::FlatContent uri_content = uri->GetFlatContent(); 280bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 281bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (int k = 0; k < uri_length; k++) { 282bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch uc16 cc1 = uri_content.Get(k); 283bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (unibrow::Utf16::IsLeadSurrogate(cc1)) { 284bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch k++; 285bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (k < uri_length) { 286bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch uc16 cc2 = uri->Get(k); 287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (unibrow::Utf16::IsTrailSurrogate(cc2)) { 288bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch EncodePair(cc1, cc2, &buffer); 289bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch continue; 290bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 291bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 292bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else if (!unibrow::Utf16::IsTrailSurrogate(cc1)) { 293bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IsUnescapePredicateInUriComponent(cc1) || 294bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch (is_uri && IsUriSeparator(cc1))) { 295bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch buffer.Add(cc1); 296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch EncodeSingle(cc1, &buffer); 298bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 299bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch continue; 300bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 301bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch AllowHeapAllocation allocate_error_and_return; 30313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch THROW_NEW_ERROR(isolate, NewURIError(), String); 30413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 30513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 30613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 30713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return isolate->factory()->NewStringFromOneByte(buffer.ToConstVector()); 30813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 30913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace { // Anonymous namespace for Escape and Unescape 31113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 31213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename Char> 31313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochint UnescapeChar(Vector<const Char> vector, int i, int length, int* step) { 31413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint16_t character = vector[i]; 31513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int32_t hi = 0; 31613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int32_t lo = 0; 31713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (character == '%' && i <= length - 6 && vector[i + 1] == 'u' && 31813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch (hi = TwoDigitHex(vector[i + 2], vector[i + 3])) > -1 && 31913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch (lo = TwoDigitHex(vector[i + 4], vector[i + 5])) > -1) { 32013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *step = 6; 32113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return (hi << 8) + lo; 32213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (character == '%' && i <= length - 3 && 32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch (lo = TwoDigitHex(vector[i + 1], vector[i + 2])) > -1) { 32413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *step = 3; 32513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return lo; 32613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 32713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *step = 1; 32813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return character; 32913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 33013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 33113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 33213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename Char> 33313e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochMaybeHandle<String> UnescapeSlow(Isolate* isolate, Handle<String> string, 33413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int start_index) { 33513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch bool one_byte = true; 33613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int length = string->length(); 33713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 33813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int unescaped_length = 0; 33913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 34013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DisallowHeapAllocation no_allocation; 34113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Vector<const Char> vector = string->GetCharVector<Char>(); 34213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int i = start_index; i < length; unescaped_length++) { 34313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int step; 34413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (UnescapeChar(vector, i, length, &step) > 34513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch String::kMaxOneByteCharCode) { 34613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch one_byte = false; 34713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 34813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch i += step; 349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 350bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 351bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 35213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(start_index < length); 35313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<String> first_part = 35413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch isolate->factory()->NewProperSubString(string, 0, start_index); 35513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 35613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int dest_position = 0; 35713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<String> second_part; 35813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(unescaped_length <= String::kMaxLength); 35913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (one_byte) { 36013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<SeqOneByteString> dest = isolate->factory() 36113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ->NewRawOneByteString(unescaped_length) 36213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch .ToHandleChecked(); 36313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DisallowHeapAllocation no_allocation; 36413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Vector<const Char> vector = string->GetCharVector<Char>(); 36513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int i = start_index; i < length; dest_position++) { 36613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int step; 36713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position, 36813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch UnescapeChar(vector, i, length, &step)); 36913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch i += step; 37013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 37113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch second_part = dest; 37213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 37313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<SeqTwoByteString> dest = isolate->factory() 37413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ->NewRawTwoByteString(unescaped_length) 37513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch .ToHandleChecked(); 37613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DisallowHeapAllocation no_allocation; 37713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Vector<const Char> vector = string->GetCharVector<Char>(); 37813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int i = start_index; i < length; dest_position++) { 37913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int step; 38013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqTwoByteStringSet(dest_position, 38113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch UnescapeChar(vector, i, length, &step)); 38213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch i += step; 38313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 38413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch second_part = dest; 38513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 38613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return isolate->factory()->NewConsString(first_part, second_part); 38713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 38813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 38913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool IsNotEscaped(uint16_t c) { 39013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (IsAlphaNumeric(c)) { 39113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return true; 39213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 39313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // @*_+-./ 39413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch switch (c) { 39513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '@': 39613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '*': 39713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '_': 39813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '+': 39913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '-': 40013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '.': 40113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case '/': 40213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return true; 40313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch default: 40413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return false; 40513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 40613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 40713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 40813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename Char> 40913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic MaybeHandle<String> UnescapePrivate(Isolate* isolate, 41013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<String> source) { 41113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int index; 41213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 41313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DisallowHeapAllocation no_allocation; 41413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch StringSearch<uint8_t, Char> search(isolate, STATIC_CHAR_VECTOR("%")); 41513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch index = search.Search(source->GetCharVector<Char>(), 0); 41613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (index < 0) return source; 41713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 41813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return UnescapeSlow<Char>(isolate, source, index); 41913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 42013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 42113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename Char> 42213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic MaybeHandle<String> EscapePrivate(Isolate* isolate, 42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<String> string) { 42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(string->IsFlat()); 42513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int escaped_length = 0; 42613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int length = string->length(); 42713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 42813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 42913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DisallowHeapAllocation no_allocation; 43013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Vector<const Char> vector = string->GetCharVector<Char>(); 43113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int i = 0; i < length; i++) { 43213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint16_t c = vector[i]; 43313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (c >= 256) { 43413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch escaped_length += 6; 43513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (IsNotEscaped(c)) { 43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch escaped_length++; 43713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 43813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch escaped_length += 3; 43913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 44113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // We don't allow strings that are longer than a maximal length. 44213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow. 44313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (escaped_length > String::kMaxLength) break; // Provoke exception. 44413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 44513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 44613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 44713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // No length change implies no change. Return original string if no change. 44813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (escaped_length == length) return string; 44913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 45013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<SeqOneByteString> dest; 45113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ASSIGN_RETURN_ON_EXCEPTION( 45213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch isolate, dest, isolate->factory()->NewRawOneByteString(escaped_length), 45313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch String); 45413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int dest_position = 0; 45513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 45613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 45713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DisallowHeapAllocation no_allocation; 45813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Vector<const Char> vector = string->GetCharVector<Char>(); 45913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int i = 0; i < length; i++) { 46013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint16_t c = vector[i]; 46113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (c >= 256) { 46213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position, '%'); 46313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position + 1, 'u'); 46413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position + 2, HexCharOfValue(c >> 12)); 46513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position + 3, 46613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HexCharOfValue((c >> 8) & 0xf)); 46713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position + 4, 46813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HexCharOfValue((c >> 4) & 0xf)); 46913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position + 5, HexCharOfValue(c & 0xf)); 47013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest_position += 6; 47113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (IsNotEscaped(c)) { 47213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position, c); 47313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest_position++; 47413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 47513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position, '%'); 47613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position + 1, HexCharOfValue(c >> 4)); 47713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest->SeqOneByteStringSet(dest_position + 2, HexCharOfValue(c & 0xf)); 47813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dest_position += 3; 47913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 48013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 48113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 48213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 48313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return dest; 48413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 48513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 48613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} // Anonymous namespace 48713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 48813e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochMaybeHandle<String> Uri::Escape(Isolate* isolate, Handle<String> string) { 48913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<String> result; 49013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch string = String::Flatten(string); 49113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return string->IsOneByteRepresentationUnderneath() 49213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ? EscapePrivate<uint8_t>(isolate, string) 49313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch : EscapePrivate<uc16>(isolate, string); 49413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 49513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 49613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochMaybeHandle<String> Uri::Unescape(Isolate* isolate, Handle<String> string) { 497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Handle<String> result; 49813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch string = String::Flatten(string); 49913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return string->IsOneByteRepresentationUnderneath() 50013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ? UnescapePrivate<uint8_t>(isolate, string) 50113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch : UnescapePrivate<uc16>(isolate, string); 502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace internal 505bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace v8 506