1 /*
2 * Copyright (c) 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_http_utils.h"
17
18 #include <chrono>
19 #include <ctime>
20 #include <iomanip>
21 #include <sstream>
22
23 #include "securec.h"
24 #include "netstack_log.h"
25
26 static constexpr const char *GMT_TIME = "%a, %d %b %Y %H:%M:%S GMT";
27
28 static constexpr const int MAX_TIME_LEN = 128;
29
30 namespace OHOS::NetStack::Http {
31
MallocCString(const std::string & origin)32 char* MallocCString(const std::string& origin)
33 {
34 if (origin.empty()) {
35 return nullptr;
36 }
37 auto len = origin.length() + 1;
38 char* res = static_cast<char*>(malloc(sizeof(char) * len));
39 if (res == nullptr) {
40 return nullptr;
41 }
42 return std::char_traits<char>::copy(res, origin.c_str(), len);
43 }
44
RecieveTimer(const char * const type)45 Timer &TimerMap::RecieveTimer(const char *const type)
46 {
47 std::map<const char *const, Timer>::iterator it = timerMap_.find(type);
48 if (it != timerMap_.end()) {
49 return it->second;
50 } else {
51 Timer timer;
52 timer.timerName_ = type;
53 timerMap_.insert(std::pair<const char *const, Timer>(type, timer));
54 return timerMap_[type];
55 }
56 }
57
Timer()58 Timer::Timer() {}
59
Start()60 void Timer::Start()
61 {
62 Timer::Start(0L);
63 }
64
Start(time_t time)65 void Timer::Start(time_t time)
66 {
67 if (time > 0) {
68 startTime_ = time;
69 } else {
70 startTime_ = TimeUtils::GetNowTimeMicroseconds();
71 }
72 }
73
Stop()74 void Timer::Stop()
75 {
76 endTime_ = TimeUtils::GetNowTimeMicroseconds();
77 }
78
Elapsed() const79 double Timer::Elapsed() const
80 {
81 double elapsedTime = TimeUtils::Microseconds2Milliseconds(endTime_ - startTime_);
82 return elapsedTime <= 0 ? 0 : elapsedTime;
83 }
84
GetNowTimeMicroseconds()85 time_t TimeUtils::GetNowTimeMicroseconds()
86 {
87 auto now = std::chrono::system_clock::now();
88 return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
89 }
90
Microseconds2Milliseconds(time_t microseconds)91 double TimeUtils::Microseconds2Milliseconds(time_t microseconds)
92 {
93 if (microseconds == 0) {
94 return 0.0;
95 }
96 return double(microseconds / MICROSECONDS_TO_MILLISECONDS);
97 }
98
99
StrTimeToTimestamp(const std::string & timeStr)100 time_t StrTimeToTimestamp(const std::string &timeStr)
101 {
102 std::tm tm = {0};
103 std::stringstream ss(timeStr);
104 ss >> std::get_time(&tm, GMT_TIME);
105 auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
106
107 auto tmp = std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch());
108 return tmp.count();
109 }
110
GetNowTimeSeconds()111 time_t GetNowTimeSeconds()
112 {
113 auto now = std::chrono::system_clock::now();
114 return std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
115 }
116
GetNowTimeGMT()117 std::string GetNowTimeGMT()
118 {
119 auto now = std::chrono::system_clock::now();
120 time_t timeSeconds = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
121 std::tm timeInfo = {0};
122 #ifdef WINDOWS_PLATFORM
123 if (gmtime_s(&timeInfo, &timeSeconds) == 0) {
124 #else
125 if (gmtime_r(&timeSeconds, &timeInfo) == nullptr) {
126 #endif
127 return {};
128 }
129 char s[MAX_TIME_LEN] = {0};
130 if (strftime(s, sizeof(s), GMT_TIME, &timeInfo) == 0) {
131 return {};
132 }
133 return s;
134 }
135
136 #ifdef __linux__
137 static std::string BASE64_CHARS = /* NOLINT */
138 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
139 "abcdefghijklmnopqrstuvwxyz"
140 "0123456789+/";
141
142 static constexpr const uint32_t CHAR_ARRAY_LENGTH_THREE = 3;
143 static constexpr const uint32_t CHAR_ARRAY_LENGTH_FOUR = 4;
144
145 enum BASE64_ENCODE_CONSTANT : uint8_t {
146 BASE64_ENCODE_MASK1 = 0xfc,
147 BASE64_ENCODE_MASK2 = 0x03,
148 BASE64_ENCODE_MASK3 = 0x0f,
149 BASE64_ENCODE_MASK4 = 0x3f,
150 BASE64_ENCODE_MASK5 = 0xf0,
151 BASE64_ENCODE_MASK6 = 0xc0,
152 BASE64_ENCODE_OFFSET2 = 2,
153 BASE64_ENCODE_OFFSET4 = 4,
154 BASE64_ENCODE_OFFSET6 = 6,
155 BASE64_ENCODE_INDEX0 = 0,
156 BASE64_ENCODE_INDEX1 = 1,
157 BASE64_ENCODE_INDEX2 = 2,
158 };
159
160 enum BASE64_DECODE_CONSTANT : uint8_t {
161 BASE64_DECODE_MASK1 = 0x30,
162 BASE64_DECODE_MASK2 = 0xf,
163 BASE64_DECODE_MASK3 = 0x3c,
164 BASE64_DECODE_MASK4 = 0x3,
165 BASE64_DECODE_OFFSET2 = 2,
166 BASE64_DECODE_OFFSET4 = 4,
167 BASE64_DECODE_OFFSET6 = 6,
168 BASE64_DECODE_INDEX0 = 0,
169 BASE64_DECODE_INDEX1 = 1,
170 BASE64_DECODE_INDEX2 = 2,
171 BASE64_DECODE_INDEX3 = 3,
172 };
173
174 static inline bool IsBase64Char(const char c)
175 {
176 return (isalnum(c) || (c == '+') || (c == '/'));
177 }
178
179 static inline void MakeCharFour(const std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> &charArrayThree,
180 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> &charArrayFour)
181 {
182 const uint8_t table[CHAR_ARRAY_LENGTH_FOUR] = {
183 static_cast<uint8_t>((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK1) >> BASE64_ENCODE_OFFSET2),
184 static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK2) << BASE64_ENCODE_OFFSET4) +
185 ((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK5) >> BASE64_ENCODE_OFFSET4)),
186 static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK3) << BASE64_ENCODE_OFFSET2) +
187 ((charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK6) >> BASE64_ENCODE_OFFSET6)),
188 static_cast<uint8_t>(charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK4),
189 };
190 for (size_t index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) {
191 charArrayFour[index] = table[index];
192 }
193 }
194
195 static inline void MakeCharTree(const std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> &charArrayFour,
196 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> &charArrayThree)
197 {
198 const uint8_t table[CHAR_ARRAY_LENGTH_THREE] = {
199 static_cast<uint8_t>((charArrayFour[BASE64_DECODE_INDEX0] << BASE64_DECODE_OFFSET2) +
200 ((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK1) >> BASE64_DECODE_OFFSET4)),
201 static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK2) << BASE64_DECODE_OFFSET4) +
202 ((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK3) >> BASE64_DECODE_OFFSET2)),
203 static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK4) << BASE64_DECODE_OFFSET6) +
204 charArrayFour[BASE64_DECODE_INDEX3]),
205 };
206 for (size_t index = 0; index < CHAR_ARRAY_LENGTH_THREE; ++index) {
207 charArrayThree[index] = table[index];
208 }
209 }
210
211 #endif
212
213 std::string Encode(const std::string &source)
214 {
215 #ifdef __linux__
216 auto it = source.begin();
217 std::string ret;
218 size_t index = 0;
219 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = {0};
220 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = {0};
221
222 while (it != source.end()) {
223 charArrayThree[index] = *it;
224 ++index;
225 ++it;
226 if (index != CHAR_ARRAY_LENGTH_THREE) {
227 continue;
228 }
229 MakeCharFour(charArrayThree, charArrayFour);
230 for (auto idx : charArrayFour) {
231 ret += BASE64_CHARS[idx];
232 }
233 index = 0;
234 }
235 if (index == 0) {
236 return ret;
237 }
238
239 for (auto i = index; i < CHAR_ARRAY_LENGTH_THREE; ++i) {
240 charArrayThree[i] = 0;
241 }
242 MakeCharFour(charArrayThree, charArrayFour);
243
244 for (size_t i = 0; i < index + 1; ++i) {
245 ret += BASE64_CHARS[charArrayFour[i]];
246 }
247
248 while (index < CHAR_ARRAY_LENGTH_THREE) {
249 ret += '=';
250 ++index;
251 }
252 return ret;
253 #else
254 return {};
255 #endif
256 }
257
258 std::string Decode(const std::string &encoded)
259 {
260 #ifdef __linux__
261 auto it = encoded.begin();
262 size_t index = 0;
263 std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = {0};
264 std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = {0};
265 std::string ret;
266
267 while (it != encoded.end() && IsBase64Char(*it)) {
268 charArrayFour[index] = *it;
269 ++index;
270 ++it;
271 if (index != CHAR_ARRAY_LENGTH_FOUR) {
272 continue;
273 }
274 for (index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) {
275 charArrayFour[index] = BASE64_CHARS.find(static_cast<char>(charArrayFour[index]));
276 }
277 MakeCharTree(charArrayFour, charArrayThree);
278 for (auto idx : charArrayThree) {
279 ret += static_cast<char>(idx);
280 }
281 index = 0;
282 }
283 if (index == 0) {
284 return ret;
285 }
286
287 for (auto i = index; i < CHAR_ARRAY_LENGTH_FOUR; ++i) {
288 charArrayFour[i] = 0;
289 }
290 for (unsigned char &i : charArrayFour) {
291 i = BASE64_CHARS.find(static_cast<char>(i));
292 }
293 MakeCharTree(charArrayFour, charArrayThree);
294
295 for (size_t i = 0; i < index - 1; i++) {
296 ret += static_cast<char>(charArrayThree[i]);
297 }
298 return ret;
299 #else
300 return {};
301 #endif
302 }
303
304 SecureChar::SecureChar() : data_(std::make_unique<char[]>(0)) {}
305
306 SecureChar::~SecureChar()
307 {
308 (void)memset_s(data_.get(), length_, 0, length_);
309 }
310
311 SecureChar::SecureChar(const std::string &secureChar)
312 : length_(secureChar.length()), data_(std::make_unique<char[]>(length_ + 1))
313 {
314 if (length_ == 0) {
315 return;
316 }
317 data_.get()[length_] = 0;
318 if (memcpy_s(data_.get(), length_, secureChar.c_str(), length_) != EOK) {
319 NETSTACK_LOGE("memcpy_s failed!");
320 return;
321 }
322 }
323
324 SecureChar::SecureChar(const uint8_t *secureChar, size_t length)
325 {
326 data_ = std::make_unique<char[]>(length + 1);
327 length_ = length;
328 data_.get()[length_] = 0;
329 if (memcpy_s(data_.get(), length_, secureChar, length_) != EOK) {
330 NETSTACK_LOGE("memcpy_s failed!");
331 }
332 }
333
334 SecureChar::SecureChar(const SecureChar &secureChar)
335 {
336 *this = secureChar;
337 }
338
339 SecureChar &SecureChar::operator=(const SecureChar &secureChar)
340 {
341 if (this != &secureChar) {
342 if (secureChar.Length() == 0) {
343 return *this;
344 }
345 length_ = secureChar.Length();
346 data_ = std::make_unique<char[]>(length_ + 1);
347 data_.get()[length_] = 0;
348 if (memcpy_s(data_.get(), length_, secureChar.Data(), length_) != EOK) {
349 NETSTACK_LOGE("memcpy_s failed!");
350 }
351 }
352 return *this;
353 }
354
355 const char *SecureChar::Data() const
356 {
357 return data_.get();
358 }
359
360 size_t SecureChar::Length() const
361 {
362 return length_;
363 }
364
365 CArrString g_map2CArrString(std::map<std::string, std::string> map)
366 {
367 auto size = map.size() * MAP_TUPLE_SIZE;
368 CArrString ret{ .head = nullptr, .size = 0};
369 if (size <= 0) {
370 return ret;
371 }
372 ret.head = static_cast<char**>(malloc(sizeof(char*) * size));
373 if (ret.head == nullptr) {
374 return ret;
375 }
376 ret.size = static_cast<int64_t>(size);
377 int index = 0;
378 for (const auto& [key, value] : map) {
379 ret.head[index] = MallocCString(key);
380 ret.head[index + 1] = MallocCString(value);
381 index += MAP_TUPLE_SIZE;
382 }
383 return ret;
384 }
385 } // namespace OHOS::NetStack::Http
386