gurl.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef WIN32 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <windows.h> 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <pthread.h> 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm> 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <ostream> 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/gurl.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_canon_stdstring.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_util.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// External template that can handle initialization of either character type. 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The input spec is given, and the canonical version will be placed in 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// |*canonical|, along with the parsing of the canonical spec in |*parsed|. 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template<typename STR> 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool InitCanonical(const STR& input_spec, 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string* canonical, 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_parse::Parsed* parsed) { 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) canonical->reserve(input_spec.size() + 32); 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::StdStringCanonOutput output(canonical); 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success = url_util::Canonicalize( 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) input_spec.data(), static_cast<int>(input_spec.length()), 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NULL, &output, parsed); 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); // Must be done before using string. 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return success; 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static std::string* empty_string = NULL; 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static GURL* empty_gurl = NULL; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef WIN32 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns a static reference to an empty string for returning a reference 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// when there is no underlying string. 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& EmptyStringForGURL() { 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!empty_string) { 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create the string. Be careful that we don't break in the case that this 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is being called from multiple threads. Statics are not threadsafe. 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string* new_empty_string = new std::string; 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (InterlockedCompareExchangePointer( 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<PVOID*>(&empty_string), new_empty_string, NULL)) { 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The old value was non-NULL, so no replacement was done. Another 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // thread did the initialization out from under us. 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete new_empty_string; 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_string; 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static pthread_once_t empty_string_once = PTHREAD_ONCE_INIT; 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static pthread_once_t empty_gurl_once = PTHREAD_ONCE_INIT; 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EmptyStringForGURLOnce(void) { 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) empty_string = new std::string; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& EmptyStringForGURL() { 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pthread_once(&empty_string_once, EmptyStringForGURLOnce); 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_string; 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // WIN32 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL::GURL() : is_valid_(false), inner_url_(NULL) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL::GURL(const GURL& other) 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : spec_(other.spec_), 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_valid_(other.is_valid_), 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parsed_(other.parsed_), 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_(NULL) { 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (other.inner_url_) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_ = new GURL(*other.inner_url_); 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Valid filesystem urls should always have an inner_url_. 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!is_valid_ || !SchemeIsFileSystem() || inner_url_); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL::GURL(const std::string& url_string) : inner_url_(NULL) { 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_valid_ = InitCanonical(url_string, &spec_, &parsed_); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_ && SchemeIsFileSystem()) { 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_ = 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new GURL(spec_.data(), parsed_.Length(), *parsed_.inner_parsed(), true); 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GURL::GURL(const base::string16& url_string) : inner_url_(NULL) { 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_valid_ = InitCanonical(url_string, &spec_, &parsed_); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_ && SchemeIsFileSystem()) { 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_ = 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new GURL(spec_.data(), parsed_.Length(), *parsed_.inner_parsed(), true); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL::GURL(const char* canonical_spec, size_t canonical_spec_len, 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const url_parse::Parsed& parsed, bool is_valid) 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : spec_(canonical_spec, canonical_spec_len), 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_valid_(is_valid), 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parsed_(parsed), 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_(NULL) { 119558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InitializeFromCanonicalSpec(); 120558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 121558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 122558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochGURL::GURL(std::string canonical_spec, 123558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const url_parse::Parsed& parsed, bool is_valid) 124558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch : is_valid_(is_valid), 125558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch parsed_(parsed), 126558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch inner_url_(NULL) { 127558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch spec_.swap(canonical_spec); 128558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InitializeFromCanonicalSpec(); 129558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 130558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 131558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid GURL::InitializeFromCanonicalSpec() { 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_ && SchemeIsFileSystem()) { 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_ = 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new GURL(spec_.data(), parsed_.Length(), *parsed_.inner_parsed(), true); 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef NDEBUG 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // For testing purposes, check that the parsed canonical URL is identical to 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // what we would have produced. Skip checking for invalid URLs have no meaning 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and we can't always canonicalize then reproducabely. 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_) { 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_parse::Component scheme; 143558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!url_util::FindAndCompareScheme(spec_.data(), spec_.length(), 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "filesystem", &scheme) || 145558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch scheme.begin == parsed_.scheme.begin) { 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We can't do this check on the inner_url of a filesystem URL, as 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // canonical_spec actually points to the start of the outer URL, so we'd 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // end up with infinite recursion in this constructor. 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL test_url(spec_); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.is_valid_ == is_valid_); 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.spec_ == spec_); 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.scheme == parsed_.scheme); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.username == parsed_.username); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.password == parsed_.password); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.host == parsed_.host); 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.port == parsed_.port); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.path == parsed_.path); 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.query == parsed_.query); 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.ref == parsed_.ref); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL::~GURL() { 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete inner_url_; 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL& GURL::operator=(const GURL& other) { 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_ = other.spec_; 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_valid_ = other.is_valid_; 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parsed_ = other.parsed_; 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete inner_url_; 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_ = NULL; 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (other.inner_url_) 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_url_ = new GURL(*other.inner_url_); 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Valid filesystem urls should always have an inner_url_. 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!is_valid_ || !SchemeIsFileSystem() || inner_url_); 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *this; 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& GURL::spec() const { 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_ || spec_.empty()) 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return spec_; 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(false) << "Trying to get the spec of an invalid URL!"; 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return EmptyStringForGURL(); 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::Resolve(const std::string& relative) const { 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ResolveWithCharsetConverter(relative, NULL); 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GURL GURL::Resolve(const base::string16& relative) const { 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ResolveWithCharsetConverter(relative, NULL); 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated below (it's inconvenient to use a template here). 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ResolveWithCharsetConverter( 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& relative, 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::CharsetConverter* charset_converter) const { 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::StdStringCanonOutput output(&result.spec_); 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!url_util::ResolveRelative( 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.data(), static_cast<int>(spec_.length()), parsed_, 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) relative.data(), static_cast<int>(relative.length()), 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) charset_converter, &output, &result.parsed_)) { 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Error resolving, return an empty URL. 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.is_valid_ = true; 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.SchemeIsFileSystem()) { 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.inner_url_ = new GURL(result.spec_.data(), result.parsed_.Length(), 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result.parsed_.inner_parsed(), true); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated above (it's inconvenient to use a template here). 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ResolveWithCharsetConverter( 2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::string16& relative, 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::CharsetConverter* charset_converter) const { 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::StdStringCanonOutput output(&result.spec_); 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!url_util::ResolveRelative( 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.data(), static_cast<int>(spec_.length()), parsed_, 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) relative.data(), static_cast<int>(relative.length()), 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) charset_converter, &output, &result.parsed_)) { 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Error resolving, return an empty URL. 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.is_valid_ = true; 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.SchemeIsFileSystem()) { 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.inner_url_ = new GURL(result.spec_.data(), result.parsed_.Length(), 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result.parsed_.inner_parsed(), true); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated below (it's inconvenient to use a template here). 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ReplaceComponents( 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const url_canon::Replacements<char>& replacements) const { 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::StdStringCanonOutput output(&result.spec_); 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.is_valid_ = url_util::ReplaceComponents( 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements, 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NULL, &output, &result.parsed_); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.is_valid_ && result.SchemeIsFileSystem()) { 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.inner_url_ = new GURL(spec_.data(), result.parsed_.Length(), 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result.parsed_.inner_parsed(), true); 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated above (it's inconvenient to use a template here). 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ReplaceComponents( 2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const url_canon::Replacements<base::char16>& replacements) const { 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::StdStringCanonOutput output(&result.spec_); 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.is_valid_ = url_util::ReplaceComponents( 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements, 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NULL, &output, &result.parsed_); 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.is_valid_ && result.SchemeIsFileSystem()) { 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.inner_url_ = new GURL(spec_.data(), result.parsed_.Length(), 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result.parsed_.inner_parsed(), true); 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::GetOrigin() const { 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This doesn't make sense for invalid or nonstandard URLs, so return 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the empty URL 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || !IsStandard()) 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (SchemeIsFileSystem()) 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return inner_url_->GetOrigin(); 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::Replacements<char> replacements; 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearUsername(); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearPassword(); 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearPath(); 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearQuery(); 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearRef(); 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ReplaceComponents(replacements); 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::GetWithEmptyPath() const { 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This doesn't make sense for invalid or nonstandard URLs, so return 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the empty URL. 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || !IsStandard()) 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We could optimize this since we know that the URL is canonical, and we are 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // appending a canonical path, so avoiding re-parsing. 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL other(*this); 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.path.len == 0) 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return other; 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clear everything after the path. 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.parsed_.query.reset(); 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.parsed_.ref.reset(); 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set the path, since the path is longer than one, we can just set the 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // first character and resize. 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.spec_[other.parsed_.path.begin] = '/'; 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.parsed_.path.len = 1; 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.spec_.resize(other.parsed_.path.begin + 1); 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return other; 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::IsStandard() const { 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url_util::IsStandard(spec_.data(), parsed_.scheme); 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::SchemeIs(const char* lower_ascii_scheme) const { 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.scheme.len <= 0) 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return lower_ascii_scheme == NULL; 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url_util::LowerCaseEqualsASCII(spec_.data() + parsed_.scheme.begin, 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.data() + parsed_.scheme.end(), 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) lower_ascii_scheme); 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int GURL::IntPort() const { 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.port.is_nonempty()) 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url_parse::ParsePort(spec_.data(), parsed_.port); 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url_parse::PORT_UNSPECIFIED; 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int GURL::EffectiveIntPort() const { 377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int int_port = IntPort(); 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (int_port == url_parse::PORT_UNSPECIFIED && IsStandard()) 379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url_canon::DefaultPortForScheme(spec_.data() + parsed_.scheme.begin, 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parsed_.scheme.len); 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return int_port; 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GURL::ExtractFileName() const { 385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_parse::Component file_component; 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_parse::ExtractFileName(spec_.data(), parsed_.path, &file_component); 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ComponentString(file_component); 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GURL::PathForRequest() const { 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(parsed_.path.len > 0) << "Canonical path for requests should be non-empty"; 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.ref.len >= 0) { 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clip off the reference when it exists. The reference starts after the # 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // sign, so we have to subtract one to also remove it. 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(spec_, parsed_.path.begin, 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parsed_.ref.begin - parsed_.path.begin - 1); 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Compute the actual path length, rather than depending on the spec's 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // terminator. If we're an inner_url, our spec continues on into our outer 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // url's path/query/ref. 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int path_len = parsed_.path.len; 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.query.is_valid()) 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path_len = parsed_.query.end() - parsed_.path.begin; 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(spec_, parsed_.path.begin, path_len); 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GURL::HostNoBrackets() const { 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If host looks like an IPv6 literal, strip the square brackets. 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_parse::Component h(parsed_.host); 411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (h.len >= 2 && spec_[h.begin] == '[' && spec_[h.end() - 1] == ']') { 412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) h.begin++; 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) h.len -= 2; 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ComponentString(h); 416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::HostIsIPAddress() const { 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || spec_.empty()) 420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::RawCanonOutputT<char, 128> ignored_output; 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::CanonHostInfo host_info; 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_canon::CanonicalizeIPAddress(spec_.c_str(), parsed_.host, 425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &ignored_output, &host_info); 426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return host_info.IsIPAddress(); 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef WIN32 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const GURL& GURL::EmptyGURL() { 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!empty_gurl) { 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create the string. Be careful that we don't break in the case that this 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is being called from multiple threads. 436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL* new_empty_gurl = new GURL; 437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (InterlockedCompareExchangePointer( 438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<PVOID*>(&empty_gurl), new_empty_gurl, NULL)) { 439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The old value was non-NULL, so no replacement was done. Another 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // thread did the initialization out from under us. 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete new_empty_gurl; 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_gurl; 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EmptyGURLOnce(void) { 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) empty_gurl = new GURL; 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const GURL& GURL::EmptyGURL() { 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pthread_once(&empty_gurl_once, EmptyGURLOnce); 456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_gurl; 457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // WIN32 460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::DomainIs(const char* lower_ascii_domain, 462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int domain_len) const { 463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Return false if this URL is not valid or domain is empty. 464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || !domain_len) 465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // FileSystem URLs have empty parsed_.host, so check this first. 468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (SchemeIsFileSystem() && inner_url_) 469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return inner_url_->DomainIs(lower_ascii_domain, domain_len); 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!parsed_.host.is_nonempty()) 472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check whether the host name is end with a dot. If yes, treat it 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the same as no-dot unless the input comparison domain is end 476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // with dot. 477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* last_pos = spec_.data() + parsed_.host.end() - 1; 478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int host_len = parsed_.host.len; 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ('.' == *last_pos && '.' != lower_ascii_domain[domain_len - 1]) { 480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_pos--; 481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) host_len--; 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Return false if host's length is less than domain's length. 485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (host_len < domain_len) 486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Compare this url whether belong specific domain. 489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* start_pos = spec_.data() + parsed_.host.begin + 490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) host_len - domain_len; 491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!url_util::LowerCaseEqualsASCII(start_pos, 493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_pos + 1, 494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) lower_ascii_domain, 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) lower_ascii_domain + domain_len)) 496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check whether host has right domain start with dot, make sure we got 499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // right domain range. For example www.google.com has domain 500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // "google.com" but www.iamnotgoogle.com does not. 501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ('.' != lower_ascii_domain[0] && host_len > domain_len && 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) '.' != *(start_pos - 1)) 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GURL::Swap(GURL* other) { 509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.swap(other->spec_); 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::swap(is_valid_, other->is_valid_); 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::swap(parsed_, other->parsed_); 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::swap(inner_url_, other->inner_url_); 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::ostream& operator<<(std::ostream& out, const GURL& url) { 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return out << url.possibly_invalid_spec(); 517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 518