1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "url/scheme_host_port.h"
#include <string.h>
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "url/gurl.h"
#include "url/url_canon.h"
#include "url/url_canon_stdstring.h"
#include "url/url_constants.h"
#include "url/url_util.h"
namespace url {
SchemeHostPort::SchemeHostPort() : port_(0) {
}
SchemeHostPort::SchemeHostPort(base::StringPiece scheme,
base::StringPiece host,
uint16 port)
: scheme_(scheme.data(), scheme.length()),
host_(host.data(), host.length()),
port_(port) {
// Try to canonicalize the host (copy/pasted from net/base. :( ).
const url::Component raw_host_component(0, static_cast<int>(host.length()));
std::string canon_host;
url::StdStringCanonOutput canon_host_output(&canon_host);
url::CanonHostInfo host_info;
url::CanonicalizeHostVerbose(host.data(), raw_host_component,
&canon_host_output, &host_info);
if (host_info.out_host.is_nonempty() &&
host_info.family != url::CanonHostInfo::BROKEN) {
// Success! Assert that there's no extra garbage.
canon_host_output.Complete();
DCHECK_EQ(host_info.out_host.len, static_cast<int>(canon_host.length()));
} else {
// Empty host, or canonicalization failed.
canon_host.clear();
}
// Return an invalid SchemeHostPort object if any of the following conditions
// hold:
//
// 1. The provided scheme is non-standard, 'blob:', or 'filesystem:'.
// 2. The provided host is non-canonical.
// 3. The scheme is 'file' and the port is non-zero.
// 4. The scheme is not 'file', and the port is zero or the host is empty.
bool isUnsupportedScheme =
!url::IsStandard(scheme.data(),
url::Component(0, static_cast<int>(scheme.length()))) ||
scheme == kFileSystemScheme || scheme == kBlobScheme;
bool isNoncanonicalHost = host != canon_host;
bool isFileSchemeWithPort = scheme == kFileScheme && port != 0;
bool isNonFileSchemeWithoutPortOrHost =
scheme != kFileScheme && (port == 0 || host.empty());
if (isUnsupportedScheme || isNoncanonicalHost || isFileSchemeWithPort ||
isNonFileSchemeWithoutPortOrHost) {
scheme_.clear();
host_.clear();
port_ = 0;
}
}
SchemeHostPort::SchemeHostPort(const GURL& url) : port_(0) {
if (!url.is_valid() || !url.IsStandard())
return;
// These schemes do not follow the generic URL syntax, so we treat them as
// invalid (scheme, host, port) tuples (even though such URLs' _Origin_ might
// have a (scheme, host, port) tuple, they themselves do not).
if (url.SchemeIsBlob() || url.SchemeIsFileSystem())
return;
scheme_ = url.scheme();
host_ = url.host();
port_ = url.EffectiveIntPort() == url::PORT_UNSPECIFIED
? 0
: url.EffectiveIntPort();
}
SchemeHostPort::~SchemeHostPort() {
}
bool SchemeHostPort::IsInvalid() const {
return scheme_.empty() && host_.empty() && !port_;
}
std::string SchemeHostPort::Serialize() const {
std::string result;
if (IsInvalid())
return result;
bool is_default_port =
port_ == url::DefaultPortForScheme(scheme_.data(),
static_cast<int>(scheme_.length()));
result.append(scheme_);
result.append(kStandardSchemeSeparator);
result.append(host_);
if (scheme_ != kFileScheme && !is_default_port) {
result.push_back(':');
result.append(base::IntToString(port_));
}
return result;
}
bool SchemeHostPort::Equals(const SchemeHostPort& other) const {
return port_ == other.port() && scheme_ == other.scheme() &&
host_ == other.host();
}
bool SchemeHostPort::operator<(const SchemeHostPort& other) const {
if (port_ != other.port_)
return port_ < other.port_;
if (scheme_ != other.scheme_)
return scheme_ < other.scheme_;
if (host_ != other.host_)
return host_ < other.host_;
return false;
}
} // namespace url
|