Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / tools / flip_server / url_utilities.cc
blob735fb8e9069ab75d5da10f466a76edd3dabc7039
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/tools/flip_server/url_utilities.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
11 namespace net {
13 std::string UrlUtilities::GetUrlHost(const std::string& url) {
14 size_t b = url.find("//");
15 if (b == std::string::npos)
16 b = 0;
17 else
18 b += 2;
19 size_t next_slash = url.find_first_of('/', b);
20 size_t next_colon = url.find_first_of(':', b);
21 if (next_slash != std::string::npos && next_colon != std::string::npos &&
22 next_colon < next_slash) {
23 return std::string(url, b, next_colon - b);
25 if (next_slash == std::string::npos) {
26 if (next_colon != std::string::npos) {
27 return std::string(url, b, next_colon - b);
28 } else {
29 next_slash = url.size();
32 return std::string(url, b, next_slash - b);
35 std::string UrlUtilities::GetUrlHostPath(const std::string& url) {
36 size_t b = url.find("//");
37 if (b == std::string::npos)
38 b = 0;
39 else
40 b += 2;
41 return std::string(url, b);
44 std::string UrlUtilities::GetUrlPath(const std::string& url) {
45 size_t b = url.find("//");
46 if (b == std::string::npos)
47 b = 0;
48 else
49 b += 2;
50 b = url.find("/", b);
51 if (b == std::string::npos)
52 return "/";
54 size_t e = url.find("#", b + 1);
55 if (e != std::string::npos)
56 return std::string(url, b, (e - b));
57 return std::string(url, b);
60 namespace {
62 // Parsing states for UrlUtilities::Unescape
63 enum UnescapeState {
64 NORMAL, // We are not in the middle of parsing an escape.
65 ESCAPE1, // We just parsed % .
66 ESCAPE2 // We just parsed %X for some hex digit X.
69 } // namespace
71 std::string UrlUtilities::Unescape(const std::string& escaped_url) {
72 std::string unescaped_url, escape_text;
73 int escape_value;
74 UnescapeState state = NORMAL;
75 std::string::const_iterator iter = escaped_url.begin();
76 while (iter < escaped_url.end()) {
77 char c = *iter;
78 switch (state) {
79 case NORMAL:
80 if (c == '%') {
81 escape_text.clear();
82 state = ESCAPE1;
83 } else {
84 unescaped_url.push_back(c);
86 ++iter;
87 break;
88 case ESCAPE1:
89 if (base::IsHexDigit(c)) {
90 escape_text.push_back(c);
91 state = ESCAPE2;
92 ++iter;
93 } else {
94 // Unexpected, % followed by non-hex chars, pass it through.
95 unescaped_url.push_back('%');
96 state = NORMAL;
98 break;
99 case ESCAPE2:
100 if (base::IsHexDigit(c)) {
101 escape_text.push_back(c);
102 bool ok = base::HexStringToInt(escape_text, &escape_value);
103 DCHECK(ok);
104 unescaped_url.push_back(static_cast<unsigned char>(escape_value));
105 state = NORMAL;
106 ++iter;
107 } else {
108 // Unexpected, % followed by non-hex chars, pass it through.
109 unescaped_url.push_back('%');
110 unescaped_url.append(escape_text);
111 state = NORMAL;
113 break;
116 // Unexpected, % followed by end of string, pass it through.
117 if (state == ESCAPE1 || state == ESCAPE2) {
118 unescaped_url.push_back('%');
119 unescaped_url.append(escape_text);
121 return unescaped_url;
124 } // namespace net