1 /*
2 * Copyright (c) 2023 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_proxy_adapter_impl.h"
17
18 #include <vector>
19
20 #include "nweb_log.h"
21 #include "parameter.h"
22
23 namespace OHOS::NWeb {
24 static constexpr const char* DEFAULT_HTTP_PROXY_HOST = "NONE";
25 static constexpr const char* DEFAULT_HTTP_PROXY_EXCLUSION_LIST = "NONE";
26 static constexpr const char* EMPTY_HTTP_PROXY_HOST = "";
27
28 namespace Base64 {
29 static std::string BASE64_CHARS = /* NOLINT */
30 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
31 "abcdefghijklmnopqrstuvwxyz"
32 "0123456789+/";
33
34 static constexpr const uint32_t CHAR_ARRAY_LENGTH_THREE = 3;
35 static constexpr const uint32_t CHAR_ARRAY_LENGTH_FOUR = 4;
36
37 enum BASE64_ENCODE_CONSTANT : uint8_t {
38 BASE64_ENCODE_MASK1 = 0xfc,
39 BASE64_ENCODE_MASK2 = 0x03,
40 BASE64_ENCODE_MASK3 = 0x0f,
41 BASE64_ENCODE_MASK4 = 0x3f,
42 BASE64_ENCODE_MASK5 = 0xf0,
43 BASE64_ENCODE_MASK6 = 0xc0,
44 BASE64_ENCODE_OFFSET2 = 2,
45 BASE64_ENCODE_OFFSET4 = 4,
46 BASE64_ENCODE_OFFSET6 = 6,
47 BASE64_ENCODE_INDEX0 = 0,
48 BASE64_ENCODE_INDEX1 = 1,
49 BASE64_ENCODE_INDEX2 = 2,
50 };
51
52 enum BASE64_DECODE_CONSTANT : uint8_t {
53 BASE64_DECODE_MASK1 = 0x30,
54 BASE64_DECODE_MASK2 = 0xf,
55 BASE64_DECODE_MASK3 = 0x3c,
56 BASE64_DECODE_MASK4 = 0x3,
57 BASE64_DECODE_OFFSET2 = 2,
58 BASE64_DECODE_OFFSET4 = 4,
59 BASE64_DECODE_OFFSET6 = 6,
60 BASE64_DECODE_INDEX0 = 0,
61 BASE64_DECODE_INDEX1 = 1,
62 BASE64_DECODE_INDEX2 = 2,
63 BASE64_DECODE_INDEX3 = 3,
64 };
65
IsBase64Char(const char c)66 static inline bool IsBase64Char(const char c)
67 {
68 return (isalnum(c) || (c == '+') || (c == '/'));
69 }
70
MakeCharFour(const std::array<uint8_t,CHAR_ARRAY_LENGTH_THREE> & charArrayThree,std::array<uint8_t,CHAR_ARRAY_LENGTH_FOUR> & charArrayFour)71 static inline void MakeCharFour(const std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE>& charArrayThree,
72 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR>& charArrayFour)
73 {
74 const uint8_t table[CHAR_ARRAY_LENGTH_FOUR] = {
75 static_cast<uint8_t>((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK1) >> BASE64_ENCODE_OFFSET2),
76 static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK2) << BASE64_ENCODE_OFFSET4) +
77 ((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK5) >> BASE64_ENCODE_OFFSET4)),
78 static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK3) << BASE64_ENCODE_OFFSET2) +
79 ((charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK6) >> BASE64_ENCODE_OFFSET6)),
80 static_cast<uint8_t>(charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK4),
81 };
82 for (size_t index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) {
83 charArrayFour[index] = table[index];
84 }
85 }
86
MakeCharTree(const std::array<uint8_t,CHAR_ARRAY_LENGTH_FOUR> & charArrayFour,std::array<uint8_t,CHAR_ARRAY_LENGTH_THREE> & charArrayThree)87 static inline void MakeCharTree(const std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR>& charArrayFour,
88 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE>& charArrayThree)
89 {
90 const uint8_t table[CHAR_ARRAY_LENGTH_THREE] = {
91 static_cast<uint8_t>((charArrayFour[BASE64_DECODE_INDEX0] << BASE64_DECODE_OFFSET2) +
92 ((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK1) >> BASE64_DECODE_OFFSET4)),
93 static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK2) << BASE64_DECODE_OFFSET4) +
94 ((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK3) >> BASE64_DECODE_OFFSET2)),
95 static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK4) << BASE64_DECODE_OFFSET6) +
96 charArrayFour[BASE64_DECODE_INDEX3]),
97 };
98 for (size_t index = 0; index < CHAR_ARRAY_LENGTH_THREE; ++index) {
99 charArrayThree[index] = table[index];
100 }
101 }
102
Encode(const std::string & source)103 std::string Encode(const std::string& source)
104 {
105 auto it = source.begin();
106 std::string ret;
107 size_t index = 0;
108 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = { 0 };
109 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = { 0 };
110
111 while (it != source.end()) {
112 charArrayThree[index] = *it;
113 ++index;
114 ++it;
115 if (index != CHAR_ARRAY_LENGTH_THREE) {
116 continue;
117 }
118 MakeCharFour(charArrayThree, charArrayFour);
119 std::for_each(charArrayFour.begin(), charArrayFour.end(), [&ret](uint8_t idx) { ret += BASE64_CHARS[idx]; });
120 index = 0;
121 }
122 if (index == 0) {
123 return ret;
124 }
125
126 for (auto i = index; i < CHAR_ARRAY_LENGTH_THREE; ++i) {
127 charArrayThree[i] = 0;
128 }
129 MakeCharFour(charArrayThree, charArrayFour);
130
131 for (size_t i = 0; i < index + 1; ++i) {
132 ret += BASE64_CHARS[charArrayFour[i]];
133 }
134
135 while (index < CHAR_ARRAY_LENGTH_THREE) {
136 ret += '=';
137 ++index;
138 }
139 return ret;
140 }
141
Decode(const std::string & encoded)142 std::string Decode(const std::string& encoded)
143 {
144 auto it = encoded.begin();
145 size_t index = 0;
146 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = { 0 };
147 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = { 0 };
148 std::string ret;
149
150 while (it != encoded.end() && IsBase64Char(*it)) {
151 charArrayFour[index] = *it;
152 ++index;
153 ++it;
154 if (index != CHAR_ARRAY_LENGTH_FOUR) {
155 continue;
156 }
157 for (index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) {
158 charArrayFour[index] = BASE64_CHARS.find(static_cast<char>(charArrayFour[index]));
159 }
160 MakeCharTree(charArrayFour, charArrayThree);
161 std::for_each(
162 charArrayThree.begin(), charArrayThree.end(), [&ret](uint8_t idx) { ret += static_cast<char>(idx); });
163 index = 0;
164 }
165 if (index == 0) {
166 return ret;
167 }
168
169 for (auto i = index; i < CHAR_ARRAY_LENGTH_FOUR; ++i) {
170 charArrayFour[i] = 0;
171 }
172 for (unsigned char& i : charArrayFour) {
173 std::string::size_type idx = BASE64_CHARS.find(static_cast<char>(i));
174 if (idx != std::string::npos) {
175 i = static_cast<unsigned char>(idx);
176 }
177 }
178 MakeCharTree(charArrayFour, charArrayThree);
179
180 for (size_t i = 0; i < index - 1; i++) {
181 ret += static_cast<char>(charArrayThree[i]);
182 }
183 return ret;
184 }
185 } // namespace Base64
186
NetProxyEventSubscriber(EventFwk::CommonEventSubscribeInfo & in,std::shared_ptr<NetProxyEventCallbackAdapter> cb)187 NetProxyEventSubscriber::NetProxyEventSubscriber(
188 EventFwk::CommonEventSubscribeInfo& in, std::shared_ptr<NetProxyEventCallbackAdapter> cb)
189 : EventFwk::CommonEventSubscriber(in), eventCallback_(cb)
190 {}
191
GetInstance()192 NetProxyAdapterImpl& NetProxyAdapterImpl::GetInstance()
193 {
194 static NetProxyAdapterImpl instance;
195 return instance;
196 }
197
RegNetProxyEvent(std::shared_ptr<NetProxyEventCallbackAdapter> eventCallback)198 void NetProxyAdapterImpl::RegNetProxyEvent(std::shared_ptr<NetProxyEventCallbackAdapter> eventCallback)
199 {
200 WVLOG_I("reg netproxy event");
201 cb_ = std::move(eventCallback);
202 if (!cb_) {
203 WVLOG_E("reg netproxy event, callback is null");
204 }
205 }
206
Changed()207 void NetProxyAdapterImpl::Changed()
208 {
209 if (listen_) {
210 return;
211 }
212 WVLOG_I("start NetProxy changed");
213 listen_ = true;
214
215 std::string host;
216 uint16_t port;
217 std::string pacUrl;
218 std::vector<std::string> exclusionList;
219 std::string exclusion;
220
221 GetProperty(host, port, pacUrl, exclusion);
222 exclusionList.push_back(exclusion);
223 if (cb_) {
224 cb_->Changed(host, port, "", exclusionList);
225 }
226 }
227
StartListen()228 bool NetProxyAdapterImpl::StartListen()
229 {
230 WVLOG_I("start netproxy listen");
231 Changed();
232 EventFwk::MatchingSkills skill = EventFwk::MatchingSkills();
233 skill.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_HTTP_PROXY_CHANGE);
234 EventFwk::CommonEventSubscribeInfo info(skill);
235 info.SetPriority(1); //The higher the value, the higher the priority
236 if (!cb_) {
237 WVLOG_E("start netproxy listen, callback is null");
238 return false;
239 }
240 commonEventSubscriber_ = std::make_shared<NetProxyEventSubscriber>(info, cb_);
241 if (!commonEventSubscriber_) {
242 WVLOG_E("start netproxy listen, common event subscriber is null");
243 return false;
244 }
245
246 bool ret = EventFwk::CommonEventManager::SubscribeCommonEvent(commonEventSubscriber_);
247 if (ret == false) {
248 WVLOG_E("start netproxy listen, subscribe common event failed");
249 return false;
250 }
251
252 StartListenAppProxy();
253 return true;
254 }
255
StartListenAppProxy()256 void NetProxyAdapterImpl::StartListenAppProxy()
257 {
258 std::function<void(const NetManagerStandard::HttpProxy& httpProxy)> callback =
259 [this](const NetManagerStandard::HttpProxy& receiveHttpProxy) {
260 NetManagerStandard::HttpProxy httpProxy = receiveHttpProxy;
261 WVLOG_D("App netproxy config change, receive host is %{public}s, port is %{public}d",
262 httpProxy.GetHost().c_str(), httpProxy.GetPort());
263 std::string host;
264 host.assign(httpProxy.GetHost());
265 if (host == EMPTY_HTTP_PROXY_HOST) {
266 WVLOG_D("App netproxy config change, clear proxy");
267 NetManagerStandard::HttpProxy tempHttpProxy;
268 int32_t ret = NetManagerStandard::NetConnClient::GetInstance().GetDefaultHttpProxy(tempHttpProxy);
269 if (ret != NetManagerStandard::NET_CONN_SUCCESS) {
270 WVLOG_E("App netproxy config change, get default http proxy from OH network failed");
271 return;
272 }
273 WVLOG_D("App netproxy config clear, GetDefaultHttpProxy host is %{public}s, port is %{public}d",
274 tempHttpProxy.GetHost().c_str(), tempHttpProxy.GetPort());
275 httpProxy = tempHttpProxy;
276 host.assign(httpProxy.GetHost());
277 }
278
279 if (host == DEFAULT_HTTP_PROXY_HOST) {
280 WVLOG_W("get netproxy property failed, host is null");
281 host = std::string();
282 }
283 std::vector<std::string> exclusionList;
284 auto exclusion = httpProxy.GetExclusionList();
285 exclusionList.assign(exclusion.begin(), exclusion.end());
286 uint16_t port = httpProxy.GetPort();
287
288 for (auto it : exclusionList) {
289 WVLOG_D("App netproxy config change, exclusion is %{public}s", it.c_str());
290 }
291 if (cb_) {
292 WVLOG_D("App netproxy config change, host is %{public}s, port is %{public}d", host.c_str(), port);
293 cb_->Changed(host, port, "", exclusionList);
294 }
295 };
296 uint32_t appId;
297 NetManagerStandard::NetConnClient::GetInstance().RegisterAppHttpProxyCallback(callback, appId);
298 appProxyCallbackId_ = appId;
299 WVLOG_D("App netproxy config change, fromNet , appId =is %{public}d", appId);
300 }
301
StopListen()302 void NetProxyAdapterImpl::StopListen()
303 {
304 WVLOG_I("stop netproxy listen");
305 if (commonEventSubscriber_) {
306 bool result = EventFwk::CommonEventManager::UnSubscribeCommonEvent(commonEventSubscriber_);
307 if (result) {
308 commonEventSubscriber_ = nullptr;
309 } else {
310 WVLOG_E("stop netproxy listen, unsubscribe common event failed");
311 }
312 }
313
314 WVLOG_D("App netproxy,UnregisterAppHttpProxyCallback, appId is %{public}d", appProxyCallbackId_);
315 NetManagerStandard::NetConnClient::GetInstance().UnregisterAppHttpProxyCallback(appProxyCallbackId_);
316 }
317
OnReceiveEvent(const EventFwk::CommonEventData & data)318 void NetProxyEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& data)
319 {
320 const std::string action = data.GetWant().GetAction();
321 WVLOG_D("netproxy config change, netproxy action: %{public}s", action.c_str());
322 if (action != EventFwk::CommonEventSupport::COMMON_EVENT_HTTP_PROXY_CHANGE) {
323 WVLOG_E("netproxy config change, action error, action is %{public}s", action.c_str());
324 return;
325 }
326
327 NetManagerStandard::HttpProxy httpProxy;
328 int32_t ret = NetManagerStandard::NetConnClient::GetInstance().GetDefaultHttpProxy(httpProxy);
329 if (ret != NetManagerStandard::NET_CONN_SUCCESS) {
330 WVLOG_E("netproxy config change, get default http proxy from OH network failed");
331 return;
332 }
333
334 WVLOG_D("netproxy config change, host is %{public}s, port is %{public}d", httpProxy.GetHost().c_str(),
335 httpProxy.GetPort());
336 for (auto it : httpProxy.GetExclusionList()) {
337 WVLOG_D("netproxy config change, exclusion is %{public}s", it.c_str());
338 }
339
340 std::string host;
341 uint16_t port;
342 std::vector<std::string> exclusionList;
343 host.assign(httpProxy.GetHost());
344 port = httpProxy.GetPort();
345 auto exclusion = httpProxy.GetExclusionList();
346 exclusionList.assign(exclusion.begin(), exclusion.end());
347
348 if (!eventCallback_) {
349 WVLOG_E("netproxy config change, event callback is null");
350 return;
351 }
352
353 eventCallback_->Changed(host, port, "", exclusionList);
354 }
355
GetProperty(std::string & host,uint16_t & port,std::string & pacUrl,std::string & exclusion)356 void NetProxyAdapterImpl::GetProperty(std::string& host, uint16_t& port, std::string& pacUrl, std::string& exclusion)
357 {
358 std::string httpProxyExclusions;
359 NetManagerStandard::HttpProxy httpProxy;
360 int32_t ret = NetManagerStandard::NetConnClient::GetInstance().GetDefaultHttpProxy(httpProxy);
361 if (ret != NetManagerStandard::NET_CONN_SUCCESS) {
362 WVLOG_E("netproxy config change, get default http proxy from OH network failed");
363 return;
364 }
365
366 host = httpProxy.GetHost();
367 if (host == DEFAULT_HTTP_PROXY_HOST) {
368 WVLOG_E("get netproxy property failed, host is null");
369 host = std::string();
370 }
371
372 for (const auto& s : httpProxy.GetExclusionList()) {
373 httpProxyExclusions.append(s + ",");
374 }
375 if (!httpProxyExclusions.empty()) {
376 httpProxyExclusions.pop_back();
377 }
378
379 exclusion = httpProxyExclusions;
380 if (exclusion == DEFAULT_HTTP_PROXY_EXCLUSION_LIST) {
381 WVLOG_E("get netproxy property failed, exclusion is null");
382 exclusion = std::string();
383 }
384
385 port = httpProxy.GetPort();
386
387 WVLOG_D("get netproxy property, host is %{public}s, port is %{public}d, exclusion is %{public}s", host.c_str(),
388 port, exclusion.c_str());
389 }
390 } // namespace OHOS::NWeb
391