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