1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "net_mgr_log_wrapper.h"
17 #include "http_proxy.h"
18 
19 #include <cstdint>
20 #include <cstdlib>
21 #include <sstream>
22 
23 namespace OHOS {
24 namespace NetManagerStandard {
25 static const size_t MAX_EXCLUSION_SIZE = 500;
26 static const size_t MAX_URL_SIZE = 2048;
27 static const size_t BASE_DEC = 10;
28 
HttpProxy()29 HttpProxy::HttpProxy() : port_(0) {}
30 
HttpProxy(std::string host,uint16_t port,const std::list<std::string> & exclusionList)31 HttpProxy::HttpProxy(std::string host, uint16_t port, const std::list<std::string> &exclusionList) : port_(0)
32 {
33     if (host.size() <= MAX_URL_SIZE) {
34         host_ = std::move(host);
35         port_ = port;
36         for (const auto &s : exclusionList) {
37             if (s.size() <= MAX_URL_SIZE) {
38                 exclusionList_.push_back(s);
39             }
40             if (exclusionList_.size() >= MAX_EXCLUSION_SIZE) {
41                 break;
42             }
43         }
44     } else {
45         NETMGR_LOG_E("HttpProxy: host length is invalid");
46     }
47 }
48 
GetHost() const49 std::string HttpProxy::GetHost() const
50 {
51     return host_;
52 }
53 
GetPort() const54 uint16_t HttpProxy::GetPort() const
55 {
56     return port_;
57 }
58 
GetUsername() const59 SecureData HttpProxy::GetUsername() const
60 {
61     return username_;
62 }
63 
GetPassword() const64 SecureData HttpProxy::GetPassword() const
65 {
66     return password_;
67 }
68 
GetExclusionList() const69 std::list<std::string> HttpProxy::GetExclusionList() const
70 {
71     return exclusionList_;
72 }
73 
operator ==(const HttpProxy & httpProxy) const74 bool HttpProxy::operator==(const HttpProxy &httpProxy) const
75 {
76     return (host_ == httpProxy.host_ && port_ == httpProxy.port_ && exclusionList_ == httpProxy.exclusionList_ &&
77             username_ == httpProxy.username_ && password_ == httpProxy.password_);
78 }
79 
operator !=(const HttpProxy & httpProxy) const80 bool HttpProxy::operator!=(const HttpProxy &httpProxy) const
81 {
82     return !(httpProxy == *this);
83 }
84 
Marshalling(Parcel & parcel) const85 bool HttpProxy::Marshalling(Parcel &parcel) const
86 {
87     if (!parcel.WriteString(host_)) {
88         return false;
89     }
90 
91     if (!parcel.WriteUint16(port_)) {
92         return false;
93     }
94 
95     if (!parcel.WriteUint32(static_cast<uint32_t>(std::min(MAX_EXCLUSION_SIZE, exclusionList_.size())))) {
96         return false;
97     }
98 
99     uint32_t size = 0;
100     for (const auto &s : exclusionList_) {
101         if (!parcel.WriteString(s)) {
102             return false;
103         }
104         ++size;
105         if (size >= MAX_EXCLUSION_SIZE) {
106             return true;
107         }
108     }
109     parcel.WriteString(username_);
110     parcel.WriteString(password_);
111     return true;
112 }
113 
Unmarshalling(Parcel & parcel,HttpProxy & httpProxy)114 bool HttpProxy::Unmarshalling(Parcel &parcel, HttpProxy &httpProxy)
115 {
116     std::string host;
117     if (!parcel.ReadString(host)) {
118         return false;
119     }
120     if (host.size() > MAX_URL_SIZE) {
121         NETMGR_LOG_E("HttpProxy: Unmarshalling: host length is invalid");
122         return false;
123     }
124 
125     uint16_t port = 0;
126     if (!parcel.ReadUint16(port)) {
127         return false;
128     }
129 
130     uint32_t size = 0;
131     if (!parcel.ReadUint32(size)) {
132         return false;
133     }
134 
135     if (size == 0) {
136         httpProxy = {host, port, {}};
137         return true;
138     }
139 
140     if (size > static_cast<uint32_t>(MAX_EXCLUSION_SIZE)) {
141         size = MAX_EXCLUSION_SIZE;
142     }
143 
144     std::list<std::string> exclusionList;
145     for (uint32_t i = 0; i < size; ++i) {
146         std::string s;
147         if (!parcel.ReadString(s)) {
148             return false;
149         }
150         if (s.size() <= MAX_URL_SIZE) {
151             exclusionList.push_back(s);
152         }
153     }
154 
155     httpProxy = {host, port, exclusionList};
156     parcel.ReadString(httpProxy.username_);
157     parcel.ReadString(httpProxy.password_);
158     return true;
159 }
160 
ToString() const161 std::string HttpProxy::ToString() const
162 {
163     std::string s;
164     std::string tab = "\t";
165     s.append(host_);
166     s.append(tab);
167     s.append(std::to_string(port_));
168     s.append(tab);
169     for (const auto &e : exclusionList_) {
170         s.append(e);
171         s.append(",");
172     }
173     return s;
174 }
175 
176 struct Parser {
ParserOHOS::NetManagerStandard::Parser177     Parser(std::string::const_iterator begin, std::string::const_iterator end) : begin(begin), end(end) {}
178 
ParsePortOHOS::NetManagerStandard::Parser179     static std::optional<uint16_t> ParsePort(const std::string &portStr)
180     {
181         char *strEnd = nullptr;
182         auto port = std::strtol(portStr.c_str(), &strEnd, BASE_DEC);
183         if (strEnd == portStr.c_str() || port < 0 || port > std::numeric_limits<uint16_t>::max()) {
184             return std::nullopt;
185         }
186         return static_cast<uint16_t>(port);
187     }
188 
ParseProxyExclusionListOHOS::NetManagerStandard::Parser189     static std::list<std::string> ParseProxyExclusionList(const std::string &exclusionList)
190     {
191         std::list<std::string> exclusionItems;
192         std::stringstream ss(exclusionList);
193         std::string item;
194 
195         while (std::getline(ss, item, ',')) {
196             size_t start = item.find_first_not_of(" \t");
197             size_t end = item.find_last_not_of(" \t");
198             if (start != std::string::npos && end != std::string::npos) {
199                 item = item.substr(start, end - start + 1);
200             }
201             exclusionItems.push_back(item);
202         }
203         return exclusionItems;
204     }
205 
GetHostOHOS::NetManagerStandard::Parser206     std::optional<std::string> GetHost()
207     {
208         if (auto hostEnd = std::find(begin, end, '\t'); hostEnd != end) {
209             auto host = std::string(begin, hostEnd);
210             begin = hostEnd + 1;
211             return host;
212         }
213         return std::nullopt;
214     }
215 
GetPortOHOS::NetManagerStandard::Parser216     std::optional<uint16_t> GetPort()
217     {
218         if (auto portEnd = std::find(begin, end, '\t'); portEnd != end) {
219             auto host = std::string(begin, portEnd);
220             auto port = ParsePort(std::string(begin, portEnd));
221             begin = portEnd + 1;
222             return port;
223         }
224         return std::nullopt;
225     }
226 
GetExclusionListOHOS::NetManagerStandard::Parser227     std::list<std::string> GetExclusionList()
228     {
229         if (begin != end) {
230             auto list = ParseProxyExclusionList(std::string(begin, end));
231             begin = end;
232             return list;
233         }
234         return {};
235     }
236 
237     std::string::const_iterator begin;
238     std::string::const_iterator end;
239 };
240 
FromString(const std::string & str)241 std::optional<HttpProxy> HttpProxy::FromString(const std::string &str)
242 {
243     Parser parser(str.cbegin(), str.cend());
244     auto host = parser.GetHost();
245     auto port = parser.GetPort();
246     if (!host || !port) {
247         return std::nullopt;
248     }
249     return NetManagerStandard::HttpProxy(*host, *port, parser.GetExclusionList());
250 }
251 } // namespace NetManagerStandard
252 } // namespace OHOS
253