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#ifdef WIN32 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <windows.h> 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <pthread.h> 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm> 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <iostream> 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "googleurl/src/gurl.h" 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "googleurl/src/url_canon_stdstring.h" 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "googleurl/src/url_util.h" 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// External template that can handle initialization of either character type. 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The input spec is given, and the canonical version will be placed in 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// |*canonical|, along with the parsing of the canonical spec in |*parsed|. 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<typename STR> 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool InitCanonical(const STR& input_spec, 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* canonical, 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_parse::Parsed* parsed) { 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reserve enough room in the output for the input, plus some extra so that 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we have room if we have to escape a few things without reallocating. 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott canonical->reserve(input_spec.size() + 32); 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::StdStringCanonOutput output(canonical); 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool success = url_util::Canonicalize( 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott input_spec.data(), static_cast<int>(input_spec.length()), 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, &output, parsed); 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output.Complete(); // Must be done before using string. 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return success; 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic std::string* empty_string = NULL; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic GURL* empty_gurl = NULL; 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef WIN32 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a static reference to an empty string for returning a reference 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// when there is no underlying string. 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string& EmptyStringForGURL() { 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Avoid static object construction/destruction on startup/shutdown. 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!empty_string) { 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Create the string. Be careful that we don't break in the case that this 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is being called from multiple threads. Statics are not threadsafe. 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* new_empty_string = new std::string; 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (InterlockedCompareExchangePointer( 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<PVOID*>(&empty_string), new_empty_string, NULL)) { 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The old value was non-NULL, so no replacement was done. Another 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // thread did the initialization out from under us. 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete new_empty_string; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return *empty_string; 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic pthread_once_t empty_string_once = PTHREAD_ONCE_INIT; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic pthread_once_t empty_gurl_once = PTHREAD_ONCE_INIT; 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EmptyStringForGURLOnce(void) { 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott empty_string = new std::string; 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string& EmptyStringForGURL() { 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Avoid static object construction/destruction on startup/shutdown. 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pthread_once(&empty_string_once, EmptyStringForGURLOnce); 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return *empty_string; 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // WIN32 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL::GURL() : is_valid_(false) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL::GURL(const GURL& other) 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : spec_(other.spec_), 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_valid_(other.is_valid_), 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_(other.parsed_) { 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL::GURL(const std::string& url_string) { 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_valid_ = InitCanonical(url_string, &spec_, &parsed_); 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL::GURL(const string16& url_string) { 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_valid_ = InitCanonical(url_string, &spec_, &parsed_); 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL::GURL(const char* canonical_spec, size_t canonical_spec_len, 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const url_parse::Parsed& parsed, bool is_valid) 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : spec_(canonical_spec, canonical_spec_len), 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_valid_(is_valid), 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_(parsed) { 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NDEBUG 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For testing purposes, check that the parsed canonical URL is identical to 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // what we would have produced. Skip checking for invalid URLs have no meaning 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // and we can't always canonicalize then reproducabely. 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (is_valid_) { 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL test_url(spec_); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.is_valid_ == is_valid_); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.spec_ == spec_); 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.scheme == parsed_.scheme); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.username == parsed_.username); 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.password == parsed_.password); 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.host == parsed_.host); 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.port == parsed_.port); 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.path == parsed_.path); 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.query == parsed_.query); 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(test_url.parsed_.ref == parsed_.ref); 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 152513209b27ff55e2841eac0e4120199c23acce758Ben MurdochGURL& GURL::operator=(const GURL& other) { 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch spec_ = other.spec_; 154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch is_valid_ = other.is_valid_; 155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch parsed_ = other.parsed_; 156513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return *this; 157513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string& GURL::spec() const { 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (is_valid_ || spec_.empty()) 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return spec_; 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(false) << "Trying to get the spec of an invalid URL!"; 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return EmptyStringForGURL(); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::Resolve(const std::string& relative) const { 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ResolveWithCharsetConverter(relative, NULL); 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::Resolve(const string16& relative) const { 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ResolveWithCharsetConverter(relative, NULL); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: code duplicated below (it's inconvenient to use a template here). 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::ResolveWithCharsetConverter( 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& relative, 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::CharsetConverter* charset_converter) const { 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not allowed for invalid URLs. 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_) 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL result; 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reserve enough room in the output for the input, plus some extra so that 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we have room if we have to escape a few things without reallocating. 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.spec_.reserve(spec_.size() + 32); 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::StdStringCanonOutput output(&result.spec_); 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!url_util::ResolveRelative( 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott spec_.data(), static_cast<int>(spec_.length()), parsed_, 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott relative.data(), static_cast<int>(relative.length()), 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott charset_converter, &output, &result.parsed_)) { 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Error resolving, return an empty URL. 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output.Complete(); 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.is_valid_ = true; 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: code duplicated above (it's inconvenient to use a template here). 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::ResolveWithCharsetConverter( 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16& relative, 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::CharsetConverter* charset_converter) const { 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not allowed for invalid URLs. 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_) 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL result; 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reserve enough room in the output for the input, plus some extra so that 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we have room if we have to escape a few things without reallocating. 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.spec_.reserve(spec_.size() + 32); 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::StdStringCanonOutput output(&result.spec_); 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!url_util::ResolveRelative( 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott spec_.data(), static_cast<int>(spec_.length()), parsed_, 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott relative.data(), static_cast<int>(relative.length()), 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott charset_converter, &output, &result.parsed_)) { 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Error resolving, return an empty URL. 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output.Complete(); 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.is_valid_ = true; 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: code duplicated below (it's inconvenient to use a template here). 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::ReplaceComponents( 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const url_canon::Replacements<char>& replacements) const { 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL result; 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not allowed for invalid URLs. 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_) 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reserve enough room in the output for the input, plus some extra so that 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we have room if we have to escape a few things without reallocating. 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.spec_.reserve(spec_.size() + 32); 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::StdStringCanonOutput output(&result.spec_); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.is_valid_ = url_util::ReplaceComponents( 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements, 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, &output, &result.parsed_); 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output.Complete(); 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: code duplicated above (it's inconvenient to use a template here). 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::ReplaceComponents( 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const url_canon::Replacements<char16>& replacements) const { 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL result; 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not allowed for invalid URLs. 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_) 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reserve enough room in the output for the input, plus some extra so that 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we have room if we have to escape a few things without reallocating. 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.spec_.reserve(spec_.size() + 32); 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::StdStringCanonOutput output(&result.spec_); 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.is_valid_ = url_util::ReplaceComponents( 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements, 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, &output, &result.parsed_); 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output.Complete(); 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::GetOrigin() const { 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This doesn't make sense for invalid or nonstandard URLs, so return 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the empty URL 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_ || !IsStandard()) 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::Replacements<char> replacements; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott replacements.ClearUsername(); 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott replacements.ClearPassword(); 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott replacements.ClearPath(); 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott replacements.ClearQuery(); 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott replacements.ClearRef(); 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ReplaceComponents(replacements); 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL GURL::GetWithEmptyPath() const { 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This doesn't make sense for invalid or nonstandard URLs, so return 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the empty URL. 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_ || !IsStandard()) 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GURL(); 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We could optimize this since we know that the URL is canonical, and we are 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // appending a canonical path, so avoiding re-parsing. 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL other(*this); 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_.path.len == 0) 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return other; 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Clear everything after the path. 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other.parsed_.query.reset(); 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other.parsed_.ref.reset(); 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set the path, since the path is longer than one, we can just set the 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // first character and resize. 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other.spec_[other.parsed_.path.begin] = '/'; 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other.parsed_.path.len = 1; 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other.spec_.resize(other.parsed_.path.begin + 1); 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return other; 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GURL::IsStandard() const { 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return url_util::IsStandard(spec_.data(), parsed_.scheme); 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GURL::SchemeIs(const char* lower_ascii_scheme) const { 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_.scheme.len <= 0) 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return lower_ascii_scheme == NULL; 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return url_util::LowerCaseEqualsASCII(spec_.data() + parsed_.scheme.begin, 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott spec_.data() + parsed_.scheme.end(), 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lower_ascii_scheme); 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint GURL::IntPort() const { 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_.port.is_nonempty()) 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return url_parse::ParsePort(spec_.data(), parsed_.port); 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return url_parse::PORT_UNSPECIFIED; 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint GURL::EffectiveIntPort() const { 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int int_port = IntPort(); 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (int_port == url_parse::PORT_UNSPECIFIED && IsStandard()) 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return url_canon::DefaultPortForScheme(spec_.data() + parsed_.scheme.begin, 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_.scheme.len); 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return int_port; 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string GURL::ExtractFileName() const { 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_parse::Component file_component; 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_parse::ExtractFileName(spec_.data(), parsed_.path, &file_component); 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ComponentString(file_component); 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string GURL::PathForRequest() const { 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(parsed_.path.len > 0) << "Canonical path for requests should be non-empty"; 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_.ref.len >= 0) { 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Clip off the reference when it exists. The reference starts after the # 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // sign, so we have to subtract one to also remove it. 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string(spec_, parsed_.path.begin, 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_.ref.begin - parsed_.path.begin - 1); 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Use everything form the path to the end. 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string(spec_, parsed_.path.begin); 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string GURL::HostNoBrackets() const { 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If host looks like an IPv6 literal, strip the square brackets. 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_parse::Component h(parsed_.host); 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (h.len >= 2 && spec_[h.begin] == '[' && spec_[h.end() - 1] == ']') { 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott h.begin++; 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott h.len -= 2; 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ComponentString(h); 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GURL::HostIsIPAddress() const { 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_ || spec_.empty()) 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::RawCanonOutputT<char, 128> ignored_output; 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::CanonHostInfo host_info; 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_canon::CanonicalizeIPAddress(spec_.c_str(), parsed_.host, 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &ignored_output, &host_info); 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return host_info.IsIPAddress(); 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef WIN32 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst GURL& GURL::EmptyGURL() { 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Avoid static object construction/destruction on startup/shutdown. 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!empty_gurl) { 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Create the string. Be careful that we don't break in the case that this 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is being called from multiple threads. 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL* new_empty_gurl = new GURL; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (InterlockedCompareExchangePointer( 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<PVOID*>(&empty_gurl), new_empty_gurl, NULL)) { 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The old value was non-NULL, so no replacement was done. Another 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // thread did the initialization out from under us. 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete new_empty_gurl; 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return *empty_gurl; 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EmptyGURLOnce(void) { 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott empty_gurl = new GURL; 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst GURL& GURL::EmptyGURL() { 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Avoid static object construction/destruction on startup/shutdown. 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pthread_once(&empty_gurl_once, EmptyGURLOnce); 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return *empty_gurl; 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // WIN32 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GURL::DomainIs(const char* lower_ascii_domain, 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int domain_len) const { 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Return false if this URL is not valid or domain is empty. 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!is_valid_ || !parsed_.host.is_nonempty() || !domain_len) 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check whether the host name is end with a dot. If yes, treat it 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the same as no-dot unless the input comparison domain is end 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // with dot. 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* last_pos = spec_.data() + parsed_.host.end() - 1; 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int host_len = parsed_.host.len; 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ('.' == *last_pos && '.' != lower_ascii_domain[domain_len - 1]) { 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott last_pos--; 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_len--; 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Return false if host's length is less than domain's length. 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (host_len < domain_len) 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Compare this url whether belong specific domain. 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* start_pos = spec_.data() + parsed_.host.begin + 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_len - domain_len; 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!url_util::LowerCaseEqualsASCII(start_pos, 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott last_pos + 1, 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lower_ascii_domain, 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lower_ascii_domain + domain_len)) 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check whether host has right domain start with dot, make sure we got 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // right domain range. For example www.google.com has domain 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // "google.com" but www.iamnotgoogle.com does not. 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ('.' != lower_ascii_domain[0] && host_len > domain_len && 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott '.' != *(start_pos - 1)) 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid GURL::Swap(GURL* other) { 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott spec_.swap(other->spec_); 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::swap(is_valid_, other->is_valid_); 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::swap(parsed_, other->parsed_); 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstd::ostream& operator<<(std::ostream& out, const GURL& url) { 45921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return out << url.possibly_invalid_spec(); 46021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 461