• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "js_base64.h"
17 #include <cstring>
18 #include <sys/types.h>
19 #include "utils/log.h"
20 #include "securec.h"
21 #include "napi/native_api.h"
22 #include "napi/native_node_api.h"
23 
24 namespace OHOS::Util {
25     namespace {
26         static const size_t TRAGET_TWO = 2;
27         static const size_t TRAGET_THREE = 3;
28         static const size_t TRAGET_FOUR = 4;
29         static const size_t TRAGET_SIX = 6;
30         static const size_t TRAGET_EIGHT = 8;
31         static const size_t TRAGET_SIXTYFIVE = 65;
32         const char BASE[] = {
33             65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
34             83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105,
35             106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
36             121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 61
37         };
38     }
39 
40     /* base64 encode */
EncodeSync(napi_env env,napi_value src)41     napi_value Base64::EncodeSync(napi_env env, napi_value src)
42     {
43         napi_typedarray_type type;
44         size_t byteOffset = 0;
45         size_t length = 0;
46         void *resultData = nullptr;
47         napi_value resultBuffer = nullptr;
48         NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &resultData, &resultBuffer, &byteOffset));
49         inputEncode_ = static_cast<const unsigned char*>(resultData);
50         unsigned char *rets = EncodeAchieve(inputEncode_, length);
51         if (rets == nullptr) {
52             napi_throw_error(env, "-1", "encode input is null");
53             return nullptr;
54         }
55         void *data = nullptr;
56         napi_value arrayBuffer = nullptr;
57         size_t bufferSize = outputLen;
58         napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer);
59         if (memcpy_s(data, bufferSize, reinterpret_cast<const void*>(rets), bufferSize) != EOK) {
60             FreeMemory(rets);
61             HILOG_ERROR("copy ret to arraybuffer error");
62             return nullptr;
63         }
64         napi_value result = nullptr;
65         napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result);
66         FreeMemory(rets);
67         return result;
68     }
69 
70     /* base64 encodeToString */
EncodeToStringSync(napi_env env,napi_value src)71     napi_value Base64::EncodeToStringSync(napi_env env, napi_value src)
72     {
73         napi_typedarray_type type;
74         size_t byteOffset = 0;
75         size_t length = 0;
76         void *resultData = nullptr;
77         napi_value resultBuffer = nullptr;
78         NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &resultData, &resultBuffer, &byteOffset));
79         inputEncode_ = static_cast<const unsigned char*>(resultData);
80         unsigned char *ret = EncodeAchieve(inputEncode_, length);
81         if (ret == nullptr) {
82             FreeMemory(ret);
83             napi_throw_error(env, "-1", "encodeToString input is null");
84             return nullptr;
85         }
86         const char *encString = reinterpret_cast<const char*>(ret);
87         napi_value resultStr = nullptr;
88         napi_create_string_utf8(env, encString, strlen(encString), &resultStr);
89         FreeMemory(ret);
90         return resultStr;
91     }
92 
EncodeAchieve(const unsigned char * input,size_t inputLen)93     unsigned char *Base64::EncodeAchieve(const unsigned char *input, size_t inputLen)
94     {
95         size_t inp = 0;
96         size_t temp = 0;
97         size_t bitWise = 0;
98         unsigned char *ret = nullptr;
99         size_t index = 0;
100         outputLen = (inputLen / TRAGET_THREE) * TRAGET_FOUR;
101         if ((inputLen % TRAGET_THREE) > 0) {
102             outputLen += TRAGET_FOUR;
103         }
104         if (outputLen > 0) {
105             ret = new unsigned char[outputLen + 1];
106             if (memset_s(ret, outputLen + 1, '\0', outputLen + 1) != EOK) {
107                 HILOG_ERROR("encode ret memset_s failed");
108                 FreeMemory(ret);
109                 return nullptr;
110             }
111         } else {
112             HILOG_ERROR("outputLen is error");
113             return nullptr;
114         }
115         if (ret == nullptr) {
116             return ret;
117         }
118         while (inp < inputLen) {
119             temp = 0;
120             bitWise = 0;
121             while (temp < TRAGET_THREE) {
122                 if (inp >= inputLen) {
123                     break;
124                 }
125                 bitWise = ((bitWise << TRAGET_EIGHT) | (input[inp] & XFF_FLG));
126                 inp++;
127                 temp++;
128             }
129             bitWise = (bitWise << ((TRAGET_THREE - temp) * TRAGET_EIGHT));
130             for (size_t i = 0; i < TRAGET_FOUR; i++) {
131                 if (temp < i) {
132                     ret[index++] = BASE[BIT_FLG];
133                 } else {
134                     ret[index++] = BASE[(bitWise >> ((TRAGET_THREE - i) * TRAGET_SIX)) & SIXTEEN_FLG];
135                 }
136             }
137         }
138         ret[index] = 0;
139         return ret;
140     }
141 
142     /* base64 decode */
DecodeSync(napi_env env,napi_value src)143     napi_value Base64::DecodeSync(napi_env env, napi_value src)
144     {
145         napi_valuetype valuetype = napi_undefined;
146         napi_typeof(env, src, &valuetype);
147         napi_typedarray_type type;
148         size_t byteOffset = 0;
149         size_t length = 0;
150         void *resultData = nullptr;
151         napi_value resultBuffer = nullptr;
152         char *inputString = nullptr;
153         if (valuetype != napi_valuetype::napi_string) {
154             NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &resultData, &resultBuffer, &byteOffset));
155         }
156         if (valuetype == napi_valuetype::napi_string) {
157             size_t prolen = 0;
158             napi_get_value_string_utf8(env, src, nullptr, 0, &prolen);
159             if (prolen > 0) {
160                 inputString = new char[prolen + 1];
161                 if (memset_s(inputString, prolen + 1, '\0', prolen + 1) != EOK) {
162                     FreeMemory(inputString);
163                     napi_throw_error(env, "-1", "decode inputString memset_s failed");
164                     return nullptr;
165                 }
166             } else {
167                 napi_throw_error(env, "-2", "prolen is error !");
168                 return nullptr;
169             }
170             if (inputString != nullptr) {
171                 napi_get_value_string_utf8(env, src, inputString, prolen + 1, &prolen);
172                 pret = DecodeAchieve(env, inputString, prolen);
173             }
174         } else if (type == napi_typedarray_type::napi_uint8_array) {
175             inputDecode_ = static_cast<const char*>(resultData);
176             pret = DecodeAchieve(env, inputDecode_, length);
177         }
178         if (pret == nullptr) {
179             if (inputString != nullptr) {
180                 FreeMemory(inputString);
181             }
182             return nullptr;
183         }
184         void *data = nullptr;
185         napi_value arrayBuffer = nullptr;
186         size_t bufferSize = decodeOutLen;
187         napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer);
188         if (memcpy_s(data, bufferSize, reinterpret_cast<const void*>(pret), bufferSize) != EOK) {
189             FreeMemory(inputString);
190             FreeMemory(pret);
191             HILOG_ERROR("copy retDecode to arraybuffer error");
192             return nullptr;
193         }
194         napi_value result = nullptr;
195         napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result);
196         FreeMemory(inputString);
197         FreeMemory(pret);
198         return result;
199     }
200 
DecodeAchieve(napi_env env,const char * input,size_t inputLen)201     unsigned char *Base64::DecodeAchieve(napi_env env, const char *input, size_t inputLen)
202     {
203         retLen = (inputLen / TRAGET_FOUR) * TRAGET_THREE;
204         decodeOutLen = retLen;
205         size_t equalCount = 0;
206         size_t index = 0;
207         size_t inp = 0;
208         size_t temp = 0;
209         size_t bitWise = 0;
210         if (*(input + inputLen - 1) == '=') {
211             equalCount++;
212         }
213         if (*(input + inputLen - TRAGET_TWO) == '=') {
214             equalCount++;
215         }
216         if (*(input + inputLen - TRAGET_THREE) == '=') {
217             equalCount++;
218         }
219         retLen = DecodeOut(equalCount, retLen);
220         if (retLen > 0) {
221             retDecode = new unsigned char[retLen + 1];
222             if (memset_s(retDecode, retLen + 1, '\0', retLen + 1) != EOK) {
223                 FreeMemory(retDecode);
224                 napi_throw_error(env, "-1", "decode retDecode memset_s failed");
225                 return nullptr;
226             }
227         } else {
228             napi_throw_error(env, "-2", "retLen is error !");
229             return nullptr;
230         }
231         if (retDecode == nullptr) {
232             return retDecode;
233         }
234         while (inp < (inputLen - equalCount)) {
235             temp = 0;
236             bitWise = 0;
237             while (temp < TRAGET_FOUR) {
238                 if (inp >= (inputLen - equalCount)) {
239                     break;
240                 }
241                 int findsData = Finds(env, input[inp]);
242                 if (findsData == -1) {
243                     FreeMemory(retDecode);
244                     return nullptr;
245                 }
246                 bitWise = (bitWise << TRAGET_SIX) | static_cast<size_t>(findsData);
247                 inp++;
248                 temp++;
249             }
250             bitWise = bitWise << ((TRAGET_FOUR - temp) * TRAGET_SIX);
251             for (size_t i = 0; i < TRAGET_THREE; i++) {
252                 if (i == temp) {
253                     break;
254                 }
255                 retDecode[index++] = static_cast<char>((bitWise >> ((TRAGET_TWO - i) * TRAGET_EIGHT)) & XFF_FLG);
256             }
257         }
258         retDecode[index] = 0;
259         return retDecode;
260     }
261 
DecodeOut(size_t equalCount,size_t retLen)262     size_t Base64::DecodeOut(size_t equalCount, size_t retLen)
263     {
264         size_t temp = retLen;
265         if (equalCount == 1) {
266             decodeOutLen -= 1;
267         }
268         if (equalCount == TRAGET_TWO) {
269             decodeOutLen -= TRAGET_TWO;
270         }
271         switch (equalCount) {
272             case 0:
273                 temp += TRAGET_FOUR;
274                 break;
275             case 1:
276                 temp += TRAGET_FOUR;
277                 break;
278             case TRAGET_TWO:
279                 temp += TRAGET_THREE;
280                 break;
281             default:
282                 temp += TRAGET_TWO;
283                 break;
284         }
285         return temp;
286     }
287 
288     /* Decoding lookup function */
Finds(napi_env env,char ch)289     int Base64::Finds(napi_env env, char ch)
290     {
291         int couts = 0;
292         // 65:Number of elements in the encoding table.
293         for (int i = 0; i < 65; i++) {
294             if (BASE[i] == ch) {
295                 couts = i;
296                 break;
297             }
298             // 64:Number of elements in the encoding table.
299             if (i == 64 && BASE[i] != ch) {
300                 napi_throw_error(env, "-1", "The input string contains unsupported characters");
301                 return -1;
302             }
303         }
304         return couts;
305     }
306 
Encode(napi_env env,napi_value src)307     napi_value Base64::Encode(napi_env env, napi_value src)
308     {
309         napi_typedarray_type type;
310         size_t byteOffset = 0;
311         size_t length = 0;
312         void *resultData = nullptr;
313         napi_value resultBuffer = nullptr;
314         NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &resultData, &resultBuffer, &byteOffset));
315         unsigned char *inputEncode = nullptr;
316         inputEncode = static_cast<unsigned char*>(resultData);
317         CreateEncodePromise(env, inputEncode, length);
318         return stdEncodeInfo_->promise;
319     }
320 
EncodeToString(napi_env env,napi_value src)321     napi_value Base64::EncodeToString(napi_env env, napi_value src)
322     {
323         napi_typedarray_type type;
324         size_t byteOffset = 0;
325         size_t length = 0;
326         void *resultData = nullptr;
327         napi_value resultBuffer = nullptr;
328         NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &resultData, &resultBuffer, &byteOffset));
329         unsigned char *inputEncode = nullptr;
330         inputEncode = static_cast<unsigned char*>(resultData);
331         CreateEncodeToStringPromise(env, inputEncode, length);
332         return stdEncodeInfo_->promise;
333     }
334 
CreateEncodePromise(napi_env env,unsigned char * inputDecode,size_t length)335     void Base64::CreateEncodePromise(napi_env env, unsigned char *inputDecode, size_t length)
336     {
337         napi_value resourceName = nullptr;
338         stdEncodeInfo_ = new EncodeInfo();
339         stdEncodeInfo_->sinputEncode = inputDecode;
340         stdEncodeInfo_->slength = length;
341         stdEncodeInfo_->env = env;
342         napi_create_promise(env, &stdEncodeInfo_->deferred, &stdEncodeInfo_->promise);
343         napi_create_string_utf8(env, "ReadStdEncode", NAPI_AUTO_LENGTH, &resourceName);
344         napi_create_async_work(env, nullptr, resourceName, ReadStdEncode, EndStdEncode,
345                                reinterpret_cast<void*>(stdEncodeInfo_), &stdEncodeInfo_->worker);
346         napi_queue_async_work_with_qos(env, stdEncodeInfo_->worker, napi_qos_user_initiated);
347     }
348 
CreateEncodeToStringPromise(napi_env env,unsigned char * inputDecode,size_t length)349     void Base64::CreateEncodeToStringPromise(napi_env env, unsigned char *inputDecode, size_t length)
350     {
351         napi_value resourceName = nullptr;
352         stdEncodeInfo_ = new EncodeInfo();
353         stdEncodeInfo_->sinputEncode = inputDecode;
354         stdEncodeInfo_->slength = length;
355         napi_create_promise(env, &stdEncodeInfo_->deferred, &stdEncodeInfo_->promise);
356         napi_create_string_utf8(env, "ReadStdEncodeToString", NAPI_AUTO_LENGTH, &resourceName);
357         napi_create_async_work(env, nullptr, resourceName, ReadStdEncodeToString, EndStdEncodeToString,
358                                reinterpret_cast<void*>(stdEncodeInfo_), &stdEncodeInfo_->worker);
359         napi_queue_async_work_with_qos(env, stdEncodeInfo_->worker, napi_qos_user_initiated);
360     }
361 
EncodeAchieves(napi_env env,EncodeInfo * encodeInfo)362     unsigned char *EncodeAchieves(napi_env env, EncodeInfo *encodeInfo)
363     {
364         const unsigned char *input = encodeInfo->sinputEncode;
365         size_t inputLen = encodeInfo->slength;
366         size_t inp = 0;
367         size_t temp = 0;
368         size_t bitWise = 0;
369         unsigned char *ret = nullptr;
370         size_t index = 0;
371         size_t outputLen = 0;
372         outputLen = (inputLen / TRAGET_THREE) * TRAGET_FOUR;
373         if ((inputLen % TRAGET_THREE) > 0) {
374             outputLen += TRAGET_FOUR;
375         }
376         encodeInfo->soutputLen = outputLen;
377         if (outputLen > 0) {
378             ret = new unsigned char[outputLen + 1];
379             if (memset_s(ret, outputLen + 1, '\0', outputLen + 1) != EOK) {
380                 FreeMemory(ret);
381                 napi_throw_error(encodeInfo->env, "-1", "ret path memset_s failed");
382                 return nullptr;
383             }
384         } else {
385             napi_throw_error(encodeInfo->env, "-2", "outputLen is error !");
386             return nullptr;
387         }
388         if (ret == nullptr) {
389             return ret;
390         }
391         while (inp < inputLen) {
392             temp = 0;
393             bitWise = 0;
394             while (temp < TRAGET_THREE) {
395                 if (inp >= inputLen) {
396                     break;
397                 }
398                 bitWise = ((bitWise << TRAGET_EIGHT) | (input[inp] & XFF_FLG));
399                 inp++;
400                 temp++;
401             }
402             bitWise = (bitWise << ((TRAGET_THREE - temp) * TRAGET_EIGHT));
403             for (size_t i = 0; i < TRAGET_FOUR; i++) {
404                 if (temp < i) {
405                     ret[index++] = BASE[BIT_FLG];
406                 } else {
407                     ret[index++] = BASE[(bitWise >> ((TRAGET_THREE - i) * TRAGET_SIX)) & SIXTEEN_FLG];
408                 }
409             }
410         }
411         ret[index] = 0;
412         return ret;
413     }
414 
ReadStdEncode(napi_env env,void * data)415     void Base64::ReadStdEncode(napi_env env, void *data)
416     {
417         auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(data);
418         unsigned char *rets = EncodeAchieves(env, stdEncodeInfo);
419         stdEncodeInfo->sinputEncoding = rets;
420     }
421 
EndStdEncode(napi_env env,napi_status status,void * buffer)422     void Base64::EndStdEncode(napi_env env, napi_status status, void *buffer)
423     {
424         auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(buffer);
425         void *data = nullptr;
426         napi_handle_scope scope = nullptr;
427         napi_open_handle_scope(env, &scope);
428         if (scope == nullptr) {
429             return;
430         }
431         napi_value arrayBuffer = nullptr;
432         size_t bufferSize = stdEncodeInfo->soutputLen;
433         napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer);
434         if (memcpy_s(data, bufferSize,
435             reinterpret_cast<const void*>(stdEncodeInfo->sinputEncoding), bufferSize) != EOK) {
436             HILOG_ERROR("copy ret to arraybuffer error");
437             napi_delete_async_work(env, stdEncodeInfo->worker);
438             return;
439         }
440         napi_value result = nullptr;
441         napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result);
442         napi_resolve_deferred(env, stdEncodeInfo->deferred, result);
443         napi_delete_async_work(env, stdEncodeInfo->worker);
444         napi_close_handle_scope(env, scope);
445         delete[] stdEncodeInfo->sinputEncoding;
446         delete stdEncodeInfo;
447     }
448 
ReadStdEncodeToString(napi_env env,void * data)449     void Base64::ReadStdEncodeToString(napi_env env, void *data)
450     {
451         auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(data);
452         unsigned char *rets = EncodeAchieves(env, stdEncodeInfo);
453         stdEncodeInfo->sinputEncoding = rets;
454     }
455 
EndStdEncodeToString(napi_env env,napi_status status,void * buffer)456     void Base64::EndStdEncodeToString(napi_env env, napi_status status, void *buffer)
457     {
458         auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(buffer);
459         napi_handle_scope scope = nullptr;
460         napi_open_handle_scope(env, &scope);
461         if (scope == nullptr) {
462             return;
463         }
464         const char *encString = reinterpret_cast<const char*>(stdEncodeInfo->sinputEncoding);
465         napi_value resultStr = nullptr;
466         napi_create_string_utf8(env, encString, strlen(encString), &resultStr);
467         napi_resolve_deferred(env, stdEncodeInfo->deferred, resultStr);
468         napi_delete_async_work(env, stdEncodeInfo->worker);
469         napi_close_handle_scope(env, scope);
470         delete[] stdEncodeInfo->sinputEncoding;
471         delete stdEncodeInfo;
472     }
473 
Decode(napi_env env,napi_value src)474     napi_value Base64::Decode(napi_env env, napi_value src)
475     {
476         napi_valuetype valuetype = napi_undefined;
477         napi_typeof(env, src, &valuetype);
478         napi_typedarray_type type;
479         size_t byteOffset = 0;
480         size_t length = 0;
481         void *resultData = nullptr;
482         napi_value resultBuffer = nullptr;
483         char *inputString = nullptr;
484         char *inputDecode = nullptr;
485         if (valuetype != napi_valuetype::napi_string) {
486             NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &resultData, &resultBuffer, &byteOffset));
487         }
488         if (valuetype == napi_valuetype::napi_string) {
489             size_t prolen = 0;
490             napi_get_value_string_utf8(env, src, nullptr, 0, &prolen);
491             if (prolen > 0) {
492                 inputString = new char[prolen + 1];
493                 if (memset_s(inputString, prolen + 1, '\0', prolen + 1) != EOK) {
494                     napi_throw_error(env, "-1", "decode inputString memset_s failed");
495                     return nullptr;
496                 }
497             } else {
498                 napi_throw_error(env, "-2", "prolen is error !");
499                 return nullptr;
500             }
501             napi_get_value_string_utf8(env, src, inputString, prolen + 1, &prolen);
502             CreateDecodePromise(env, inputString, prolen);
503         } else if (type == napi_typedarray_type::napi_uint8_array) {
504             inputDecode = static_cast<char*>(resultData);
505             CreateDecodePromise(env, inputDecode, length);
506         }
507         return stdDecodeInfo_->promise;
508     }
509 
CreateDecodePromise(napi_env env,char * inputDecode,size_t length)510     void Base64::CreateDecodePromise(napi_env env, char *inputDecode, size_t length)
511     {
512         napi_value resourceName = nullptr;
513         stdDecodeInfo_ = new DecodeInfo();
514         stdDecodeInfo_->sinputDecode = inputDecode;
515         stdDecodeInfo_->slength = length;
516         stdDecodeInfo_->env = env;
517         napi_create_promise(env, &stdDecodeInfo_->deferred, &stdDecodeInfo_->promise);
518         napi_create_string_utf8(env, "ReadStdDecode", NAPI_AUTO_LENGTH, &resourceName);
519         napi_create_async_work(env, nullptr, resourceName, ReadStdDecode, EndStdDecode,
520                                reinterpret_cast<void*>(stdDecodeInfo_), &stdDecodeInfo_->worker);
521         napi_queue_async_work_with_qos(env, stdDecodeInfo_->worker, napi_qos_user_initiated);
522     }
523 
Finds(char ch)524     size_t Finds(char ch)
525     {
526         size_t couts = 0;
527         for (size_t i = 0; i < TRAGET_SIXTYFIVE; i++) {
528             if (BASE[i] == ch) {
529                 couts = i;
530             }
531         }
532         return couts;
533     }
DecodeOut(size_t equalCount,size_t retLen,DecodeInfo * decodeInfo)534     size_t DecodeOut(size_t equalCount, size_t retLen, DecodeInfo *decodeInfo)
535     {
536         if (equalCount == 1) {
537             decodeInfo->decodeOutLen -= 1;
538         }
539         if (equalCount == TRAGET_TWO) {
540             decodeInfo->decodeOutLen -= TRAGET_TWO;
541         }
542         switch (equalCount) {
543             case 0:
544                 retLen += TRAGET_FOUR;
545                 break;
546             case 1:
547                 retLen += TRAGET_FOUR;
548                 break;
549             case TRAGET_TWO:
550                 retLen += TRAGET_THREE;
551                 break;
552             default:
553                 retLen += TRAGET_TWO;
554                 break;
555         }
556         return retLen;
557     }
558 
DecodeAchieves(napi_env env,DecodeInfo * decodeInfo)559     unsigned char *DecodeAchieves(napi_env env, DecodeInfo *decodeInfo)
560     {
561         const char *input = decodeInfo->sinputDecode;
562         size_t inputLen = decodeInfo->slength;
563         size_t retLen = 0;
564         retLen = (inputLen / TRAGET_FOUR) * TRAGET_THREE;
565         decodeInfo->decodeOutLen = retLen;
566         size_t equalCount = 0;
567         size_t inp = 0;
568         size_t temp = 0;
569         size_t bitWise = 0;
570         size_t index = 0;
571         unsigned char *retDecode = nullptr;
572         if (*(input + inputLen - 1) == '=') {
573             equalCount++;
574         }
575         if (*(input + inputLen - TRAGET_TWO) == '=') {
576             equalCount++;
577         }
578         retLen = DecodeOut(equalCount, retLen, decodeInfo);
579         if (retLen > 0) {
580             retDecode = new unsigned char[retLen + 1];
581             if (memset_s(retDecode, retLen + 1, '\0', retLen + 1) != EOK) {
582                 FreeMemory(retDecode);
583                 napi_throw_error(decodeInfo->env, "-1", "decode retDecode memset_s failed");
584                 return nullptr;
585             }
586         } else {
587             napi_throw_error(decodeInfo->env, "-2", "retLen is error !");
588             return nullptr;
589         }
590         while (inp < (inputLen - equalCount)) {
591             temp = 0;
592             bitWise = 0;
593             while (temp < TRAGET_FOUR) {
594                 if (inp >= (inputLen - equalCount)) {
595                     break;
596                 }
597                 bitWise = (bitWise << TRAGET_SIX) | (Finds(input[inp]));
598                 inp++;
599                 temp++;
600             }
601             bitWise = bitWise << ((TRAGET_FOUR - temp) * TRAGET_SIX);
602             for (size_t i = 0; i < TRAGET_THREE; i++) {
603                 if (i == temp) {
604                     break;
605                 }
606                 retDecode[index++] = static_cast<char>((bitWise >> ((TRAGET_TWO - i) * TRAGET_EIGHT)) & XFF_FLG);
607             }
608         }
609         retDecode[index] = 0;
610         return retDecode;
611     }
612 
ReadStdDecode(napi_env env,void * data)613     void Base64::ReadStdDecode(napi_env env, void *data)
614     {
615         auto stdDecodeInfo = reinterpret_cast<DecodeInfo*>(data);
616         unsigned char *rets = DecodeAchieves(env, stdDecodeInfo);
617         stdDecodeInfo->sinputDecoding = rets;
618     }
EndStdDecode(napi_env env,napi_status status,void * buffer)619     void Base64::EndStdDecode(napi_env env, napi_status status, void *buffer)
620     {
621         auto stdDecodeInfo = reinterpret_cast<DecodeInfo*>(buffer);
622         void *data = nullptr;
623         napi_handle_scope scope = nullptr;
624         napi_open_handle_scope(env, &scope);
625         if (scope == nullptr) {
626             return;
627         }
628         napi_value arrayBuffer = nullptr;
629         size_t bufferSize = stdDecodeInfo->decodeOutLen;
630         napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer);
631         if (memcpy_s(data, bufferSize,
632             reinterpret_cast<const void*>(stdDecodeInfo->sinputDecoding), bufferSize) != EOK) {
633             HILOG_ERROR("copy ret to arraybuffer error");
634             napi_delete_async_work(env, stdDecodeInfo->worker);
635             return;
636         }
637         napi_value result = nullptr;
638         napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result);
639         napi_resolve_deferred(env, stdDecodeInfo->deferred, result);
640         napi_delete_async_work(env, stdDecodeInfo->worker);
641         napi_close_handle_scope(env, scope);
642         delete[] stdDecodeInfo->sinputDecoding;
643         delete stdDecodeInfo;
644     }
645 
646     /* Memory cleanup function */
FreeMemory(char * address)647     void FreeMemory(char *address)
648     {
649         if (address != nullptr) {
650             delete[] address;
651         }
652     }
FreeMemory(unsigned char * address)653     void FreeMemory(unsigned char *address)
654     {
655         if (address != nullptr) {
656             delete[] address;
657         }
658     }
659 }
660