- add sources.
[platform/framework/web/crosswalk.git] / src / net / base / url_util.cc
1 // Copyright 2013 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.
4
5 #include "net/base/url_util.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/strings/string_piece.h"
11 #include "net/base/escape.h"
12 #include "url/gurl.h"
13
14 namespace net {
15
16 GURL AppendQueryParameter(const GURL& url,
17                           const std::string& name,
18                           const std::string& value) {
19   std::string query(url.query());
20
21   if (!query.empty())
22     query += "&";
23
24   query += (EscapeQueryParamValue(name, true) + "=" +
25             EscapeQueryParamValue(value, true));
26   GURL::Replacements replacements;
27   replacements.SetQueryStr(query);
28   return url.ReplaceComponents(replacements);
29 }
30
31 GURL AppendOrReplaceQueryParameter(const GURL& url,
32                                    const std::string& name,
33                                    const std::string& value) {
34   bool replaced = false;
35   std::string param_name = EscapeQueryParamValue(name, true);
36   std::string param_value = EscapeQueryParamValue(value, true);
37
38   const std::string input = url.query();
39   url_parse::Component cursor(0, input.size());
40   std::string output;
41   url_parse::Component key_range, value_range;
42   while (url_parse::ExtractQueryKeyValue(
43              input.data(), &cursor, &key_range, &value_range)) {
44     const base::StringPiece key(
45         input.data() + key_range.begin, key_range.len);
46     const base::StringPiece value(
47         input.data() + value_range.begin, value_range.len);
48     std::string key_value_pair;
49     // Check |replaced| as only the first pair should be replaced.
50     if (!replaced && key == param_name) {
51       replaced = true;
52       key_value_pair = (param_name + "=" + param_value);
53     } else {
54       key_value_pair.assign(input.data(),
55                             key_range.begin,
56                             value_range.end() - key_range.begin);
57     }
58     if (!output.empty())
59       output += "&";
60
61     output += key_value_pair;
62   }
63   if (!replaced) {
64     if (!output.empty())
65       output += "&";
66
67     output += (param_name + "=" + param_value);
68   }
69   GURL::Replacements replacements;
70   replacements.SetQueryStr(output);
71   return url.ReplaceComponents(replacements);
72 }
73
74 QueryIterator::QueryIterator(const GURL& url)
75     : url_(url),
76       at_end_(!url.is_valid()) {
77   if (!at_end_) {
78     query_ = url.parsed_for_possibly_invalid_spec().query;
79     Advance();
80   }
81 }
82
83 QueryIterator::~QueryIterator() {
84 }
85
86 std::string QueryIterator::GetKey() const {
87   DCHECK(!at_end_);
88   if (key_.is_nonempty())
89     return url_.spec().substr(key_.begin, key_.len);
90   return std::string();
91 }
92
93 std::string QueryIterator::GetValue() const {
94   DCHECK(!at_end_);
95   if (value_.is_nonempty())
96     return url_.spec().substr(value_.begin, value_.len);
97   return std::string();
98 }
99
100 const std::string& QueryIterator::GetUnescapedValue() {
101   DCHECK(!at_end_);
102   if (value_.is_nonempty() && unescaped_value_.empty()) {
103     unescaped_value_ = UnescapeURLComponent(
104         GetValue(),
105         UnescapeRule::SPACES |
106         UnescapeRule::URL_SPECIAL_CHARS |
107         UnescapeRule::REPLACE_PLUS_WITH_SPACE);
108   }
109   return unescaped_value_;
110 }
111
112 bool QueryIterator::IsAtEnd() const {
113   return at_end_;
114 }
115
116 void QueryIterator::Advance() {
117   DCHECK (!at_end_);
118   key_.reset();
119   value_.reset();
120   unescaped_value_.clear();
121   at_end_ = !url_parse::ExtractQueryKeyValue(url_.spec().c_str(),
122                                              &query_,
123                                              &key_,
124                                              &value_);
125 }
126
127 bool GetValueForKeyInQuery(const GURL& url,
128                            const std::string& search_key,
129                            std::string* out_value) {
130   for (QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
131     if (it.GetKey() == search_key) {
132       *out_value = it.GetUnescapedValue();
133       return true;
134     }
135   }
136   return false;
137 }
138
139 }  // namespace net