Revert "Resolving memory leak issue in Reply function of AppControl"
[platform/framework/web/crosswalk-tizen.git] / common / url.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include "common/url.h"
18
19 #include <algorithm>
20 #include <stdexcept>
21
22 #include "common/logger.h"
23 #include "common/string_utils.h"
24
25 namespace common {
26
27 namespace {
28
29 const char* kSchemeTypeFile = "file";
30 const char* kSchemeTypeHttp = "http";
31 const char* kSchemeTypeHttps = "https";
32 const char* kSchemeTypeSsh = "ssh";
33 const char* kSchemeTypeFtp = "ftp";
34
35 // length of scheme identifier ://
36 const int kSchemeIdLen = 3;
37 int kPortHttp = 80;
38 int kPortHttps = 443;
39 int kPortSsh = 22;
40 int kPortFtp = 21;
41 int kPortDefault = 0;
42
43 int GetDefaultPort(const std::string& scheme) {
44   if (scheme == kSchemeTypeHttp) return kPortHttp;
45   else if (scheme == kSchemeTypeHttps) return kPortHttps;
46   else if (scheme == kSchemeTypeSsh) return kPortSsh;
47   else if (scheme == kSchemeTypeFtp) return kPortFtp;
48   else
49     return kPortDefault;
50 }
51
52 }  // namespace
53
54 class URLImpl {
55  public:
56   explicit URLImpl(const std::string& url);
57   URLImpl();
58
59   std::string url() const { return url_; }
60   std::string scheme() const { return scheme_; }
61   std::string domain() const { return domain_; }
62   int port() const { return port_; }
63   std::string path() const { return path_; }
64
65  private:
66   std::string url_;
67   std::string scheme_;
68   std::string domain_;
69   int port_;
70   std::string path_;
71
72   bool ExtractScheme();
73   void ExtractDomain();
74   void ExtractDomainPort();
75   void ExtractPath();
76 };
77
78 URLImpl::URLImpl() : port_(0) {
79 }
80
81 URLImpl::URLImpl(const std::string& url) : port_(0) {
82   if (url.empty())
83     return;
84
85   url_ = url;
86   if (!ExtractScheme()) {
87     ExtractDomain();
88     ExtractPath();
89     return;
90   }
91
92   if (scheme_ != kSchemeTypeFile)
93     ExtractDomainPort();
94
95   ExtractPath();
96 }
97
98 bool URLImpl::ExtractScheme() {
99   size_t end_of_scheme = 0;
100   if (url_.find("://") != std::string::npos) {
101     end_of_scheme = url_.find("://");
102     std::string scheme = url_.substr(0, end_of_scheme);
103     std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower);
104     scheme_ = scheme;
105     return true;
106   } else {
107     return false;
108   }
109 }
110
111 void URLImpl::ExtractDomain() {
112   size_t start_of_domain = scheme_.empty() ?
113                            0 : scheme_.length() + kSchemeIdLen;
114   size_t end_of_domain = url_.find_first_of('/', start_of_domain);
115   size_t at = url_.find_first_of('@', start_of_domain);
116   if (at < end_of_domain) {
117     start_of_domain = at + 1;
118   }
119   domain_ =
120     url_.substr(start_of_domain, end_of_domain == std::string::npos ?
121                 std::string::npos : end_of_domain - start_of_domain);
122   LOGGER(INFO) << "Extract Domain is " << domain_;
123 }
124
125 void URLImpl::ExtractDomainPort() {
126   ExtractDomain();
127   std::string domain = domain_;
128
129   // Decide start position to find port considering IPv6 case
130   size_t start_pos = domain.find('@');
131   start_pos = (start_pos != std::string::npos) ? start_pos + 1 : 0;
132   if (domain[start_pos] == '[')
133     start_pos = domain.find(']', start_pos+1);
134
135   size_t port_separator =
136     domain.find_first_of(':', start_pos != std::string::npos ? start_pos : 0);
137   if (port_separator != std::string::npos) {
138     domain_ = domain.substr(0, port_separator);
139     std::string port = domain.substr(port_separator+1);
140     if (port.empty()) {
141       port_ = GetDefaultPort(scheme_);
142     } else {
143       try {
144         port_ = std::stoi(port);
145       } catch (...) {
146         port_ = GetDefaultPort(scheme_);
147       }
148     }
149   } else {
150     domain_ = domain;
151     port_ = GetDefaultPort(scheme_);
152   }
153 }
154
155 void URLImpl::ExtractPath() {
156   std::string sub_url = url_.substr(scheme_.empty() ?
157                                     0 : scheme_.length() + kSchemeIdLen);
158   if (domain_.empty()) {
159     path_ = sub_url;
160   } else {
161     size_t start_of_path = sub_url.find_first_of('/');
162     if (start_of_path != std::string::npos)
163       path_ = sub_url.substr(start_of_path);
164   }
165 }
166
167 URL::URL(const std::string& url) {
168   impl_ = new URLImpl(url);
169 }
170
171 std::string URL::url() const { return impl_->url(); }
172 std::string URL::scheme() const { return impl_->scheme(); }
173 std::string URL::domain() const { return impl_->domain(); }
174 int URL::port() const { return impl_->port(); }
175 std::string URL::path() const { return impl_->path(); }
176
177 URL::~URL() {
178   delete impl_;
179 }
180
181 }  // namespace common