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_url.h"
17#include <regex>
18#include <sstream>
19#include "securec.h"
20#include "unicode/stringpiece.h"
21#include "unicode/unistr.h"
22#include "tools/log.h"
23namespace OHOS::Url {
24    std::map<std::string, int> g_head = {
25        {"ftp:", 21}, {"file:", -1}, {"gopher:", 70}, {"http:", 80},
26        {"https:", 443}, {"ws:", 80}, {"wss:", 443}
27    };
28
29    std::vector<std::string> g_doubleSegment = {
30        "..", ".%2e", ".%2E", "%2e.", "%2E.",
31        "%2e%2e", "%2E%2E", "%2e%2E", "%2E%2e"
32    };
33
34    std::vector<std::string> g_singlesegment = { ".", "%2e", "%2E" };
35    std::vector<std::string> g_specialSymbols = {
36        "@", "%40", "#", "%23", "=", "%3D", ":", "%3A",
37        "/", "%2F", ";", "%3B", "?", "%3F"
38    };
39    std::vector<char> g_specialcharacter = {
40        '\0', '\t', '\n', '\r', ' ', '#', '%', '/', ':', '?',
41        '@', '[', '\\', ']'
42    };
43
44    std::bitset<static_cast<size_t>(BitsetStatusFlag::MAX_BIT_SIZE)> g_specialCharForBit;
45
46    void PreliminaryWork()
47    {
48        std::vector<char> g_specialSymbolsTmp = {'#', '%', '/', ':', '?', '@', '[', '\\', ']', '<', '>', '^', '|'};
49        size_t invalidCharLength = static_cast<size_t>(BitsetStatusFlag::BIT_ASCII_32);
50        for (size_t i = 0; i <= invalidCharLength; ++i) {
51            g_specialCharForBit.set(i);
52        }
53        size_t len = g_specialSymbolsTmp.size();
54        for (size_t i = 0; i < len; ++i) {
55            g_specialCharForBit.set(g_specialSymbolsTmp[i]);
56        }
57        g_specialCharForBit.set(static_cast<size_t>(BitsetStatusFlag::BIT_ASCII_127));
58    }
59
60    bool CheckCharacter(std::string data, std::bitset<static_cast<size_t>(BitsetStatusFlag::MAX_BIT_SIZE)> rule)
61    {
62        size_t dataLen = data.size();
63        for (size_t i = 0; i < dataLen; ++i) {
64            if (static_cast<int>(data[i]) >= 0 &&
65                static_cast<int>(data[i]) < static_cast<int>(BitsetStatusFlag::MAX_BIT_SIZE)) {
66                bool IsIllegal = rule.test(data[i]);
67                if (IsIllegal) {
68                    return false;
69                }
70            }
71        }
72        return true;
73    }
74
75    void ReplaceSpecialSymbols(std::string& input, std::string& oldstr, std::string& newstr)
76    {
77        size_t oldlen = oldstr.size();
78        while (true) {
79            size_t pos = 0;
80            if ((pos = input.find(oldstr)) != std::string::npos) {
81                input.replace(pos, oldlen, newstr);
82                continue;
83            }
84            break;
85        }
86    }
87
88    template<typename T>
89    bool IsASCIITabOrNewline(const T ch)
90    {
91        return (ch == '\t' || ch == '\n' || ch == '\r');
92    }
93
94    bool IsHexDigit(const char& ch)
95    {
96        if (isdigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) {
97            return true;
98        }
99        return false;
100    }
101
102    std::string DecodeSpecialChars(std::string input)
103    {
104        std::string temp = input;
105        size_t len = temp.size();
106        if (input.empty()) {
107            return temp;
108        }
109        size_t pos = temp.find("%");
110        while (pos != std::string::npos && pos < len - 2) { // 2:end subscript backspace
111            if (IsHexDigit(temp[pos + 1]) && IsHexDigit(temp[pos + 2])) { // 2:Determine the second character after %
112                std::string subStr = temp.substr(pos + 1, 2); // 2:Truncate the last two digits of the %
113                int octNum = 0;
114                if (sscanf_s(subStr.c_str(), "%x", &octNum) == -1) {
115                    HILOG_ERROR("sscanf_s is falie");
116                    return temp;
117                }
118                std::string convertedChar(1, static_cast<char>(octNum));
119                temp.replace(pos, 3, convertedChar); // 3:Replace the percent character with the corresponding char
120                len = len - 2; // 2:After the replacement, the length of the string is reduced by two
121            }
122            pos = temp.find("%", pos + 1);
123        }
124        return temp;
125    }
126
127    void DeleteC0OrSpace(std::string& str)
128    {
129        if (str.empty()) {
130            return;
131        }
132        size_t i = 0;
133        size_t strlen = str.size();
134        while (i < strlen) {
135            if (str[i] >= '\0' && str[i] <= ' ') {
136                i++;
137                continue;
138            }
139            break;
140        }
141        str = str.substr(i);
142        strlen = str.size();
143        if (strlen == 0) {
144            return;
145        }
146        for (i = strlen - 1; i != 0; i--) {
147            if (str[i] >= '\0' && str[i] <= ' ') {
148                str.pop_back();
149                continue;
150            }
151            break;
152        }
153    }
154
155    void DeleteTabOrNewline(std::string& str1)
156    {
157        for (auto item = str1.begin(); item != str1.end();) {
158            if (IsASCIITabOrNewline(*item)) {
159                item = str1.erase(item);
160            } else {
161                ++item;
162            }
163        }
164    }
165
166    bool IsSpecial(std::string scheme)
167    {
168        auto temp = g_head.count(scheme);
169        if (temp > 0) {
170            return true;
171        }
172        return false;
173    }
174
175    bool AnalysisScheme(std::string& input, std::string& scheme,
176        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
177    {
178        if (!isalpha(input[0])) {
179            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
180            return false;
181        } else {
182            size_t strlen = input.size();
183            for (size_t i = 0; i < strlen - 1; ++i) {
184                if ((isalnum(input[i]) || input[i] == '+' || input[i] == '-' || input[i] == '.') &&
185                    isupper(input[i])) {
186                        input[i] = static_cast<size_t>(tolower(input[i]));
187                }
188                if (!isalnum(input[i]) && input[i] != '+' && input[i] != '-' && input[i] != '.') {
189                    flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
190                    // 0:Bit 0 Set to true,The URL analysis failed
191                    return false;
192                }
193            }
194            scheme = input;
195            if (IsSpecial(scheme)) {
196                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT1));
197            }
198            return true;
199        }
200    }
201
202    void AnalysisFragment(const std::string& input, std::string& fragment,
203        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
204    {
205        fragment = input;
206        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT8));
207    }
208
209    void AnalysisQuery(const std::string& input, std::string& query,
210        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
211    {
212        query = input;
213        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT7));
214    }
215    void AnalysisUsernameAndPasswd(std::string& input, std::string& username, std::string& password,
216        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
217    {
218        int pos = static_cast<int>(input.size()) - 1;
219        for (; pos >= 0; pos--) {
220            if (input[pos] == '@') {
221                break;
222            }
223        }
224        std::string userAndPasswd = input.substr(0, pos);
225        input = input.substr(pos + 1);
226        if (userAndPasswd.empty()) {
227            return;
228        }
229        if (userAndPasswd.find('@') != std::string::npos) {
230            while (true) {
231                size_t posTmp = 0;
232                if ((posTmp = userAndPasswd.find('@')) != std::string::npos) {
233                    userAndPasswd = userAndPasswd.replace(posTmp, 1, "%40");
234                } else {
235                    break;
236                }
237            }
238        }
239        if (userAndPasswd.find(':') != std::string::npos) {
240            size_t position = userAndPasswd.find(':');
241            std::string user = userAndPasswd.substr(0, position);
242            std::string keyWord = userAndPasswd.substr(position + 1);
243            if (!user.empty()) {
244                username = user;
245                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT2));
246            }
247            if (!keyWord.empty()) {
248                password = keyWord;
249                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT3));
250            }
251        } else {
252            username = userAndPasswd;
253            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT2));
254        }
255    }
256
257    void AnalysisPath(std::string& input, std::vector<std::string>& path,
258        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags, bool isSpecial)
259    {
260        std::vector<std::string> temp;
261        size_t pos = 0;
262        while (((pos = input.find('/')) != std::string::npos) ||
263            ((pos = input.find('\\')) != std::string::npos && isSpecial)) {
264            temp.push_back(input.substr(0, pos));
265            input = input.substr(pos + 1);
266        }
267        temp.push_back(input);
268        size_t length = temp.size();
269        for (size_t it = 0; it < length; ++it) {
270            auto result = find(g_doubleSegment.begin(), g_doubleSegment.end(), temp[it]);
271            if (result != g_doubleSegment.end()) {
272                if (path.empty() && it == length - 1) {
273                    path.emplace_back("");
274                    flags.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
275                }
276                if (path.empty()) {
277                    continue;
278                }
279                path.pop_back();
280                if (it == length - 1) {
281                    path.emplace_back("");
282                    flags.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
283                }
284                continue;
285            }
286            result = find(g_singlesegment.begin(), g_singlesegment.end(), temp[it]);
287            if (result != g_singlesegment.end() && it == length - 1) {
288                path.emplace_back("");
289                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
290                continue;
291            }
292            if (result == g_singlesegment.end()) {
293                path.push_back(temp[it]);
294                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
295            }
296        }
297    }
298
299    void AnalysisPort(std::string input, UrlData& urlinfo,
300        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
301    {
302        if (input.size() == 0) {
303            return;
304        }
305        for (auto i : input) {
306            if (!isdigit(i)) {
307                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
308                return;
309            }
310        }
311        if (input.size() >= 6) { //6:Maximum port number size
312            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
313            return;
314        }
315        int it = stoi(input);
316        const int maxPort = 65535; // 65535:Maximum port number
317        if (it > maxPort) {
318            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
319            return;
320        }
321        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT5));
322        for (auto i : g_head) {
323            if (i.first == urlinfo.scheme && i.second == it) {
324                urlinfo.port = -1;
325                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT5), 0);
326                return;
327            }
328        }
329        urlinfo.port = it;
330    }
331
332    void AnalysisOpaqueHost(std::string input, std::string& host,
333        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
334    {
335        size_t strlen = input.size();
336        for (size_t i = 0; i < strlen; ++i) {
337            char ch = input[i];
338            auto result = find(g_specialcharacter.begin(), g_specialcharacter.end(), ch);
339            if (ch != '%' && (result != g_specialcharacter.end())) {
340                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
341                return;
342            }
343        }
344        host = input;
345        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
346    }
347
348    std::string DealIpv4(std::string str)
349    {
350        std::vector<std::string> temp;
351        size_t pos = str.rfind(":");
352        size_t index = pos;
353        size_t left = pos + 1;
354        char hexVal[3] = { 0 };
355        std::string val = "";
356        while ((pos = str.find(".", left)) != std::string::npos) {
357            val = str.substr(left, pos - left);
358            if (sprintf_s(hexVal, sizeof(hexVal), "%02x", stoi(val)) == -1) {
359                HILOG_ERROR("sprintf_s is falie");
360                return val;
361            }
362
363            temp.push_back(hexVal);
364            left = pos + 1;
365        }
366        val = str.substr(left);
367        if (sprintf_s(hexVal, sizeof(hexVal), "%02x", stoi(val)) == -1) {
368            HILOG_ERROR("sprintf_s is falie");
369            return val;
370        }
371        temp.push_back(hexVal);
372        std::string res = str.substr(0, index);
373        res = res + ":" + temp[0] + temp[1] + ":" + temp[2] + temp[3]; // 2:subscript 3:subscript
374        return res;
375    }
376
377    void FormatIpv6(std::string& str)
378    {
379        size_t pos = str.find("::");
380        size_t index = pos;
381        if (pos != std::string::npos) {
382            size_t left = 0;
383            int count = 0;
384            while ((pos = str.find(":", left)) != std::string::npos) {
385                count++;
386                left = pos + 1;
387            }
388            int size = 7 - (count - 2); // 7:point number 2:Continuous colon number
389            std::string temp = "";
390            for (int i = 0; i < size - 1; ++i) {
391                temp += ":0";
392            }
393            temp += ":";
394            str.replace(index, 2, temp); // 2:jump"::"
395            if (index == 0) {
396                str = "0" + str;
397            }
398        }
399    }
400
401    void RemoveLeadingZeros(std::vector<std::string> &ipv6)
402    {
403        size_t len = ipv6.size();
404        for (size_t i = 0; i < len; ++i) {
405            size_t strLen = ipv6[i].size();
406            size_t count = 0;
407            size_t j = 0;
408            for (j = 0; j < strLen; ++j) {
409                if (ipv6[i][j] != '0') {
410                    break;
411                }
412                count++;
413            }
414            if (count == strLen) {
415                ipv6[i] = "0";
416            } else if (count != 0) {
417                ipv6[i] = ipv6[i].substr(j);
418            }
419        }
420    }
421
422    std::string ZeroCompression(std::vector<std::string> &ipv6)
423    {
424        size_t maxIndex = 0;
425        size_t maxSize = 0;
426        size_t index = 0;
427        size_t size = 0;
428        bool isNeedZeroCompression = false;
429        size_t len = ipv6.size();
430        for (size_t i = 0; i < len; ++i) {
431            index = i;
432            size = 0;
433            while (i < len && ipv6[i] == "0") {
434                isNeedZeroCompression = true;
435                size++;
436                i++;
437            }
438            if (maxSize < size) {
439                maxSize = size;
440                maxIndex = index;
441            }
442        }
443        std::string res = "";
444        size_t ipv6Len = ipv6.size();
445        for (size_t i = 0; i < ipv6Len; ++i) {
446            if (isNeedZeroCompression && i == maxIndex) {
447                if (maxIndex == 0) {
448                    res += "::";
449                } else {
450                    res += ":";
451                }
452                i += maxSize - 1;
453                continue;
454            }
455            res += ipv6[i];
456            i != (ipv6Len - 1) ? res += ":" : "";
457        }
458        return res;
459    }
460
461    void ToLower(std::string &str)
462    {
463        size_t strLen = str.size();
464        for (size_t i = 0; i < strLen; ++i) {
465            if (isupper(str[i])) {
466                str[i] = static_cast<size_t>(tolower(str[i]));
467            }
468        }
469    }
470
471    std::string Compress(std::string str)
472    {
473        std::vector<std::string> temp;
474        size_t pos = 0;
475        size_t left = 0;
476        while ((pos = str.find(":", left)) != std::string::npos) {
477            temp.push_back(str.substr(left, pos - left));
478            left = pos + 1;
479        }
480        temp.push_back(str.substr(left));
481        RemoveLeadingZeros(temp);
482        std::string res = ZeroCompression(temp);
483        ToLower(res);
484        return res;
485    }
486
487    void IPv6Host(std::string& input, std::string& host,
488        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
489    {
490        std::regex ipv6("(::|(:((:[0-9A-Fa-f]{1,4}){1,7}))|(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|"
491                        "(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(([0-9A-Fa-f]{1,4}:){2}"
492                        "(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})"
493                        "|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){5}"
494                        "(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|"
495                        "(((:(:[0-9A-Fa-f]{1,4}){0,5}:)|(([0-9A-Fa-f]{1,4}:){1}(:[0-9A-Fa-f]{1,4}){0,4}:)"
496                        "|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:)|(([0-9A-Fa-f]{1,4}:){3}"
497                        "(:[0-9A-Fa-f]{1,4}){0,2}:)|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4})?:)|"
498                        "(([0-9A-Fa-f]{1,4}:){5}:)|(([0-9A-Fa-f]{1,4}:){6}))((25[0-5]|2[0-4]\\d|1\\d{2}|"
499                        "[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)))(%[a-zA-Z0-9._]+)?");
500        if (!std::regex_match(input, ipv6)) {
501            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
502            return;
503        }
504        size_t pos = 0;
505        pos = input.find('.');
506        if (pos != std::string::npos) {
507            input = DealIpv4(input);
508        }
509        FormatIpv6(input);
510        input = Compress(input);
511        host = "[" + input + "]";
512        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
513        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT10));
514    }
515
516    bool IsRadix(std::string num, std::string radix)
517    {
518        size_t len = num.size();
519        for (size_t i = 0; i < len; ++i) {
520            if (radix.find(num[i]) == std::string::npos) {
521                return false;
522            }
523        }
524        return true;
525    }
526
527    bool IsNumber(std::string num, int &radix)
528    {
529        size_t len = num.size();
530        if (len >= 2 && num[0] == '0' && (num[1] == 'x' || num[1] == 'X')) { // 2:hex head length
531            radix = 16; // 16:hex
532            std::string subStr = num.substr(2); // 2:jump 0x
533            if (subStr.empty()) {
534                return true;
535            }
536            return IsRadix(subStr, "0123456789abcdefABCDEF");
537        } else if (len >= 1 && num[0] == '0') {
538            radix = 8; // 8:octal
539            std::string subStr = num.substr(1);
540            if (subStr.empty()) {
541                return true;
542            }
543            return IsRadix(num.substr(1), "01234567");
544        } else if (IsRadix(num, "0123456789")) {
545            radix = 10; // 10:decimal
546            return true;
547        }
548        return false;
549    }
550
551    std::string BinaryConversion(std::string num, int radix)
552    {
553        int val = 0;
554        if (radix == 16) { // 16:hex
555            if (num.substr(2).empty()) { // 2:jump 0x
556                return "0";
557            }
558            if (sscanf_s(num.c_str(), "%x", &val) == -1) {
559                HILOG_ERROR("sscanf_s is falie");
560                return num;
561            }
562            return std::to_string(val);
563        } else if (radix == 8) { // 8:octal
564            if (num.substr(1).empty()) {
565                return "0";
566            }
567            if (sscanf_s(num.c_str(), "%o", &val) == -1) {
568                HILOG_ERROR("sscanf_s is falie");
569                return num;
570            }
571            return std::to_string(val);
572        } else {
573            return num;
574        }
575    }
576
577    bool RemovalIpv4(std::vector<std::string> &temp, std::string str,
578                     std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags)
579    {
580        size_t pos = 0;
581        size_t left = 0;
582        while ((pos = str.find(".", left)) != std::string::npos) {
583            temp.push_back(str.substr(left, pos - left));
584            left = pos + 1;
585        }
586
587        if (left != str.size()) {
588            temp.push_back(str.substr(left));
589        }
590
591        size_t tmpLen = temp.size();
592        std::vector<std::string> res;
593        for (size_t i = 0; i < tmpLen; ++i) {
594            int radix = 0;
595            if (IsNumber(temp[i], radix)) {
596                res.push_back(BinaryConversion(temp[i], radix));
597            } else {
598                return false;
599            }
600        }
601        temp = res;
602        bool isIpv4 = true;
603        for (size_t i = 0; i < tmpLen; ++i) {
604            if (temp[i] == "") {
605                isIpv4 = false;
606                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
607                if (i == tmpLen - 1) {
608                    temp.push_back("");
609                    flags.reset(static_cast<size_t>(BitsetStatusFlag::BIT0));
610                }
611            }
612        }
613        return isIpv4;
614    }
615
616    int IsFormatIpv4(std::vector<std::string> nums)
617    {
618        size_t len = nums.size();
619        for (size_t i = 0; i < len; ++i) {
620            if (nums[i].size() > 8) { // 8:ipv4 max value size
621                return i;
622            }
623            if (!nums[i].empty() && stoi(nums[i]) > 255) { // 255:ipv4 max value
624                return i;
625            }
626        }
627        return -1;
628    }
629
630    std::string SplitNum(std::string num, size_t& number)
631    {
632        if (num.size() > 8) { // 8:ipv4 max value size
633            number = num.size();
634            return num;
635        }
636        int val = stoi(num);
637        std::vector<std::string> nums;
638        std::string res = "";
639        while (val > 0) {
640            int numConver = val % 256; // 256:ipv4 max value
641            nums.push_back(std::to_string(numConver));
642            val /= 256; // 256:ipv4 max value
643        }
644        for (int i = static_cast<int>(nums.size()) - 1; i >= 0; --i) {
645            res += nums[i] + ".";
646        }
647        number = nums.size();
648        return res.substr(0, res.size() - 1);
649    }
650
651    void FormatIpv4(std::vector<std::string> nums, std::string& host,
652        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags)
653    {
654        size_t len = nums.size();
655        int index = IsFormatIpv4(nums);
656        std::string res = "";
657        if (index == -1) {
658            for (size_t i = 0; i < len - 1; ++i) {
659                res += nums[i] + ".";
660            }
661            for (size_t i = 0; i < 4 - len; ++i) { // 4:ipv4 max size
662                res += "0.";
663            }
664            res += nums[len - 1];
665            host = res;
666            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
667        } else if (index == static_cast<int>(len - 1)) {
668            for (size_t i = 0; i < len - 1; ++i) {
669                res += nums[i] + ".";
670            }
671            size_t number = 0;
672            std::string temp = SplitNum(nums[index], number);
673            if (number + (len - 1) > 4) { // 4:ipv4 max size
674                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
675                return;
676            }
677            for (size_t i = 0; i < 4 - (len - 1 + number); ++i) { // 4:ipv4 max size
678                temp = "0." + temp;
679            }
680            host = res + temp;
681            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
682        } else {
683            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
684            return;
685        }
686    }
687
688    void AnalyseIPv4(const std::string& input, std::string& host,
689        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
690    {
691        bool isipv4 = false;
692        std::vector<std::string> temp;
693        isipv4 = RemovalIpv4(temp, input, flags);
694        size_t tempLen = temp.size();
695        size_t lastSize = temp[tempLen - 1].size();
696        if (isipv4 == true && lastSize > 8) { // 8: ipv4 last number size
697            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
698            return;
699        }
700        std::string res = "";
701        for (size_t i = 0; i < tempLen; ++i) {
702            res += temp[i];
703            if (i != tempLen - 1) {
704                res += ".";
705            }
706        }
707        if (isipv4) {
708            if (tempLen > 4) { // 4:ipv4 max size
709                ToLower(res);
710                host = res;
711                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
712            } else if (tempLen == 4) { // 4:ipv4 max size
713                if (IsFormatIpv4(temp) == -1) {
714                    host = res;
715                    flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
716                } else {
717                    flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
718                }
719            } else {
720                FormatIpv4(temp, host, flags);
721            }
722        } else {
723            ToLower(res);
724            host = res;
725            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
726        }
727    }
728
729    void AnalysisHost(std::string& input, std::string& host,
730        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags, bool special)
731    {
732        if (input.empty()) {
733            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
734            return;
735        }
736        if (input[0] == '[') {
737            if ((input[input.length() - 1]) == ']') {
738                size_t  b = input.length();
739                input = input.substr(1, b - 2); // 2:Truncating Strings
740                IPv6Host(input, host, flags);
741                return;
742            } else {
743                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
744                return;
745            }
746        }
747        if (!special) {
748            AnalysisOpaqueHost(input, host, flags);
749            return;
750        }
751        std::string decodeInput = DecodeSpecialChars(input);
752        if (!CheckCharacter(decodeInput, g_specialCharForBit)) {
753            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
754            return;
755        }
756        AnalyseIPv4(decodeInput, host, flags);
757    }
758
759    bool ISFileNohost(const std::string& input)
760    {
761        if ((isalpha(input[0]) && (input[1] == ':' || input[1] == '|'))) {
762            return true;
763        }
764        return false;
765    }
766
767    void AnalysisFilePath(std::string& input, UrlData& urlinfo,
768        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
769    {
770        std::vector<std::string> temp;
771        size_t pos = 0;
772        while (((pos = input.find('/')) != std::string::npos) || ((pos = input.find('\\')) != std::string::npos)) {
773            temp.push_back(input.substr(0, pos));
774            input = input.substr(pos + 1);
775        }
776        temp.push_back(input);
777        size_t length = temp.size();
778        for (size_t i = 0; i < length; ++i) {
779            auto a = find(g_doubleSegment.begin(), g_doubleSegment.end(), temp[i]);
780            if (a != g_doubleSegment.end()) {
781                if ((urlinfo.path.size() == 1) && ISFileNohost(urlinfo.path[0]) &&
782                    urlinfo.path[0].size() == 2) { // 2:The interception length is 2
783                    urlinfo.path[0][1] = ':';
784                } else if (!urlinfo.path.empty()) {
785                    urlinfo.path.pop_back();
786                }
787                if (i == temp.size() - 1) {
788                    urlinfo.path.push_back("");
789                }
790                continue;
791            }
792            a = find(g_singlesegment.begin(), g_singlesegment.end(), temp[i]);
793            if (a != g_singlesegment.end()) {
794                if (i == temp.size() - 1) {
795                    urlinfo.path.push_back("");
796                }
797                continue;
798            }
799            urlinfo.path.push_back(temp[i]);
800            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
801        }
802        std::string it = urlinfo.path[0];
803        if (isalpha(it[0]) && (it[1] == ':' || it[1] == '|')) {
804            if (it.size() == 2) { // 2:The length is 2
805                it[1] = ':';
806                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4), 0);
807                urlinfo.host.clear();
808            }
809        }
810    }
811
812    void AnalysisSpecialFile(std::string& temp, size_t pos, UrlData& urlinfo,
813        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
814    {
815        std::string strHost = temp.substr(0, pos);
816        std::string strPath = temp.substr(pos + 1);
817        bool special = true;
818        if (!ISFileNohost(strHost)) {
819            AnalysisHost(strHost, urlinfo.host, flags, special);
820        } else if (!ISFileNohost(strHost) && flags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
821            return;
822        }
823        if (!ISFileNohost(strHost)) {
824            AnalysisFilePath(strPath, urlinfo, flags);
825        } else {
826            AnalysisFilePath(temp, urlinfo, flags);
827        }
828    }
829    void AnalysisFile(std::string& input, UrlData& urlinfo,
830        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
831    {
832        bool special = true;
833        if ((input[0] == '/' || input[0] == '\\') && (input[1] == '/' || input[1] == '\\')) {
834            std::string temp = input.substr(2); // 2:Intercept from 2 subscripts
835            size_t pos = 0;
836            if ((((pos = temp.find('/')) != std::string::npos) ||
837                ((pos = temp.find('\\')) != std::string::npos)) && pos == 0) {
838                temp = temp.substr(1);
839                AnalysisFilePath(temp, urlinfo, flags);
840            } else if ((((pos = temp.find('/')) != std::string::npos) ||
841                ((pos = temp.find('\\')) != std::string::npos)) && pos != 0) {
842                AnalysisSpecialFile(temp, pos, urlinfo, flags);
843            } else {
844                if (!temp.empty() && flags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
845                    AnalysisHost(temp, urlinfo.host, flags, special);
846                } else if (!temp.empty() && !flags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
847                    AnalysisHost(temp, urlinfo.host, flags, special);
848                    return;
849                }
850            }
851        } else {
852            if (input[0] == '/' || input[0] == '\\') {
853                input = input.substr(1);
854            }
855            AnalysisFilePath(input, urlinfo, flags);
856        }
857    }
858
859    void AnalysisFilescheme(const std::string& input, UrlData& urlinfo,
860        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
861    {
862        std::string strPath = urlinfo.scheme + input;
863        urlinfo.scheme = "file:";
864        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT1));
865        AnalysisFilePath(strPath, urlinfo, flags);
866    }
867
868    void AnalyInfoPath(std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags,
869        UrlData& urlinfo, const std::string& input)
870    {
871        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT9));
872        if (urlinfo.path.empty()) {
873            urlinfo.path.emplace_back("");
874        }
875        urlinfo.path[0] = input;
876        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
877        return;
878    }
879
880    void AnalyHostPath(std::string &strHost, std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags,
881        UrlData& urlinfo)
882    {
883        size_t pos = 0;
884        if (strHost[strHost.size() - 1] != ']' && (pos = strHost.find_last_of(':')) != std::string::npos) {
885            std::string port = strHost.substr(pos + 1);
886            strHost = strHost.substr(0, pos);
887            AnalysisPort(port, urlinfo, flags);
888            if (flags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
889                return;
890            }
891        }
892    }
893    void AnalyStrHost(std::string &strHost, UrlData& urlinfo,
894        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags)
895    {
896        if (strHost.find('@') != std::string::npos) {
897            AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags);
898        }
899        if (strHost.empty()) {
900            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
901            return;
902        }
903    }
904
905    void AnalysisNoDefaultProtocol(std::string& input, UrlData& urlinfo,
906        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
907    {
908        if (urlinfo.scheme.size() == 2) { // 2:The length is 2
909            AnalysisFilescheme(input, urlinfo, flags);
910            return;
911        }
912        if (input[0] == '/' && input[1] == '/' && input[2] != '/') { // 2:The third character of the input
913            std::string hostandpath = input.substr(2); // 2:Intercept from 2 subscripts
914            if (hostandpath.empty()) {
915                return;
916            }
917            size_t i = 0;
918            bool special = false;
919            std::string strHost = "";
920            if (hostandpath.find('/') != std::string::npos) {
921                i = hostandpath.find('/');
922                strHost = hostandpath.substr(0, i);
923                std::string strPath = hostandpath.substr(i + 1);
924                if (strHost.find('@') != std::string::npos) {
925                    AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags);
926                }
927                if (strHost.empty()) {
928                    flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
929                    return;
930                }
931                size_t pos = 0;
932                if (strHost[strHost.size() - 1] != ']' && (pos = strHost.find_last_of(':')) != std::string::npos) {
933                    std::string port = strHost.substr(pos + 1);
934                    strHost = strHost.substr(0, pos);
935                    AnalysisPort(port, urlinfo, flags);
936                }
937                if (strHost[strHost.size() - 1] != ']' && (pos = strHost.find_last_of(':')) != std::string::npos &&
938                    flags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
939                    return;
940                }
941                AnalysisHost(strHost, urlinfo.host, flags, special);
942                AnalysisPath(strPath, urlinfo.path, flags, special);
943            } else {
944                strHost = hostandpath;
945                AnalyStrHost(strHost, urlinfo, flags);
946                AnalyHostPath(strHost, flags, urlinfo);
947                AnalysisHost(strHost, urlinfo.host, flags, special);
948            }
949        } else if (input[0] == '/' && input[1] == '/') {
950            std::string strOfPath = input.substr(1);
951            AnalysisPath(strOfPath, urlinfo.path, flags, false);
952        } else {
953            AnalyInfoPath(flags, urlinfo, input);
954        }
955    }
956
957    void AnalysisOnlyHost(const std::string& input, UrlData& urlinfo,
958        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags, size_t pos)
959    {
960        std::string strHost = input;
961        if (strHost.find('@') != std::string::npos) {
962            AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags);
963        }
964        if (strHost.empty()) {
965            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
966            return;
967        }
968        if (strHost[strHost.size() - 1] != ']') {
969            if ((pos = strHost.find_last_of(':')) != std::string::npos) {
970                std::string port = strHost.substr(pos + 1);
971                strHost = strHost.substr(0, pos);
972                AnalysisPort(port, urlinfo, flags);
973            }
974            if ((pos = strHost.find_last_of(':')) != std::string::npos &&
975                flags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
976                return;
977            }
978        }
979        AnalysisHost(strHost, urlinfo.host, flags, true);
980    }
981
982    void JudgePos(size_t &pos, const size_t &length, const std::string& input)
983    {
984        for (pos = 0; pos < length; pos++) {
985            if (input[pos] == '/' || input[pos] == '\\') {
986                break;
987            }
988        }
989    }
990
991    void SkipSlashSymbol(std::string& input, size_t& pos)
992    {
993        size_t inputLen = input.size();
994        while (pos < inputLen) {
995            if (input[pos] == '/' || input[pos] == '\\') {
996                pos++;
997                continue;
998            }
999                break;
1000        }
1001        input = input.substr(pos);
1002    }
1003
1004    void ParsingHostAndPath(std::string& input, UrlData& urlinfo, size_t& pos,
1005        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
1006    {
1007        bool special = true;
1008        size_t length = input.size();
1009        JudgePos(pos, length, input);
1010        std::string strHost = input.substr(0, pos);
1011        std::string strPath = input.substr(pos + 1);
1012        if (strHost.find('@') != std::string::npos) {
1013            AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags);
1014        }
1015        if (strHost.empty()) {
1016            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1017            return;
1018        }
1019        if (strHost[strHost.size() - 1] != ']' && (pos = strHost.find_last_of(':')) != std::string::npos) {
1020            pos = strHost.find_last_of(':');
1021            if (pos != std::string::npos) {
1022                std::string port = strHost.substr(pos + 1);
1023                strHost = strHost.substr(0, pos);
1024                AnalysisPort(port, urlinfo, flags);
1025            }
1026        }
1027        if (strHost[strHost.size() - 1] != ']' && strHost.find_last_of(':') != std::string::npos &&
1028            flags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
1029            return;
1030        }
1031        AnalysisHost(strHost, urlinfo.host, flags, special);
1032        AnalysisPath(strPath, urlinfo.path, flags, special);
1033    }
1034
1035    void AnalysisHostAndPath(std::string& input, UrlData& urlinfo,
1036        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
1037    {
1038        if (flags.test(static_cast<size_t>(BitsetStatusFlag::BIT1))) {
1039            size_t pos = 0;
1040            SkipSlashSymbol(input, pos);
1041            if (input.size() == 0) {
1042                flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1043                return;
1044            } else if ((input.find('/') != std::string::npos || input.find('\\') != std::string::npos)) {
1045                ParsingHostAndPath(input, urlinfo, pos, flags);
1046            } else if (input.size() != 0 && input.find('/') == std::string::npos &&
1047                input.find('\\') == std::string::npos) {
1048                AnalysisOnlyHost(input, urlinfo, flags, pos);
1049            }
1050        } else {
1051            size_t inputLen = input.size();
1052            if (inputLen > 0) {
1053                urlinfo.isSpecialPath = input[0] != '/' ? true : false;
1054            }
1055            AnalysisNoDefaultProtocol(input, urlinfo, flags);
1056        }
1057    }
1058
1059    void AnalysisInput(std::string& input, UrlData& urlData,
1060        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
1061    {
1062        size_t pos = 0;
1063        if (input.find('#') != std::string::npos) {
1064            pos = input.find('#');
1065            std::string fragment = input.substr(pos);
1066            AnalysisFragment(fragment, urlData.fragment, flags);
1067            input = input.substr(0, pos);
1068        }
1069        if (input.find('?') != std::string::npos) {
1070            pos = input.find('?');
1071            std::string query = input.substr(pos);
1072            AnalysisQuery(query, urlData.query, flags);
1073            input = input.substr(0, pos);
1074        }
1075        bool special = (flags.test(static_cast<size_t>(BitsetStatusFlag::BIT1)) ? true : false);
1076        std::string pathStr = input;
1077        AnalysisPath(pathStr, urlData.path, flags, special);
1078    }
1079
1080    void BaseInfoToUrl(const UrlData& baseInfo,
1081        const std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& baseflags, UrlData& urlData,
1082        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags, bool inputIsEmpty)
1083    {
1084        urlData.scheme = baseInfo.scheme;
1085        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT1),
1086            baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT1)));
1087        urlData.host = baseInfo.host;
1088        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
1089        urlData.username = baseInfo.username;
1090        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT2),
1091            baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT2)));
1092        urlData.password = baseInfo.password;
1093        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT3),
1094            baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT3)));
1095        urlData.port = baseInfo.port;
1096        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT5),
1097            baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT5)));
1098        if (inputIsEmpty) {
1099            urlData.path = baseInfo.path;
1100            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT6),
1101                baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT6)));
1102            urlData.query = baseInfo.query;
1103            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT7),
1104                baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT7)));
1105            urlData.fragment = baseInfo.fragment;
1106            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT8),
1107                baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT8)));
1108        }
1109        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT9),
1110            baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT9)));
1111        flags.set(static_cast<size_t>(BitsetStatusFlag::BIT10),
1112            baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT10)));
1113    }
1114
1115    void ShorteningPath(UrlData& urlData, UrlData& baseData, bool isFile)
1116    {
1117        if (baseData.path.empty()) {
1118            return;
1119        }
1120        if (urlData.path.size() == 1 && urlData.path[0].empty()) {
1121            urlData.path.pop_back();
1122            return;
1123        }
1124        if ((baseData.path.size() == 1) && isFile &&
1125            isalpha(baseData.path[0][0]) && (baseData.path[0][1] == ':')) {
1126            return;
1127        }
1128        baseData.path.pop_back();
1129    }
1130
1131    void InitOnlyInput(std::string& input, UrlData& urlData,
1132        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags)
1133    {
1134        if (input.empty()) {
1135            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1136            return;
1137        }
1138        if (input.find(':') != std::string::npos) {
1139            size_t pos = input.find(':');
1140            pos++;
1141            std::string scheme = input.substr(0, pos);
1142            if (!AnalysisScheme(scheme, urlData.scheme, flags)) {
1143                return;
1144            }
1145            if (input.find('#') != std::string::npos) {
1146                size_t posTmp = input.find('#');
1147                std::string fragment = input.substr(posTmp);
1148                AnalysisFragment(fragment, urlData.fragment, flags);
1149                input = input.substr(0, posTmp);
1150            }
1151            if (input.find('?') != std::string::npos) {
1152                size_t position = input.find('?');
1153                std::string query = input.substr(position);
1154                AnalysisQuery(query, urlData.query, flags);
1155                input = input.substr(0, position);
1156            }
1157            std::string str = input.substr(pos);
1158            if (urlData.scheme == "file:") {
1159                AnalysisFile(str, urlData, flags);
1160            } else {
1161                AnalysisHostAndPath(str, urlData, flags);
1162            }
1163        } else {
1164            flags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1165            return;
1166        }
1167    }
1168
1169    void ToolHasBase(std::string input, std::string &strInput, UrlData &urlData,
1170        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags)
1171    {
1172        if (!input.empty() && input[0] == '/') {
1173            strInput = input.substr(1);
1174            AnalysisInput(strInput, urlData, flags);
1175        } else if (!input.empty() && input[0] != '/') {
1176            AnalysisInput(strInput, urlData, flags);
1177        }
1178    }
1179
1180    std::string BasePathToStr(UrlData &urlData)
1181    {
1182        std::string temp = "";
1183        size_t length = urlData.path.size();
1184        for (size_t i = 0; i < length; i++) {
1185            if (i < length - 1) {
1186                temp += urlData.path[i] + "/";
1187            } else {
1188                temp += urlData.path[i];
1189            }
1190        }
1191        return temp;
1192    }
1193
1194    URL::URL(const std::string& input)
1195    {
1196        std::string str = input;
1197        PreliminaryWork();
1198        DeleteC0OrSpace(str);
1199        DeleteTabOrNewline(str);
1200        InitOnlyInput(str, urlData_, flags_);
1201    }
1202
1203    void DelCont(std::string strBase, std::string &strInput, UrlData &baseInfo,
1204        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &baseflags)
1205    {
1206        DeleteC0OrSpace(strBase);
1207        DeleteTabOrNewline(strBase);
1208        DeleteC0OrSpace(strInput);
1209        DeleteTabOrNewline(strInput);
1210        InitOnlyInput(strBase, baseInfo, baseflags);
1211    }
1212
1213    URL::URL(const std::string& input, const std::string& base)
1214    {
1215        UrlData baseInfo;
1216        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> baseflags;
1217        std::string strBase = base;
1218        std::string strInput = input;
1219        if (strBase.empty()) {
1220            baseflags.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1221        }
1222        DelCont(strBase, strInput, baseInfo, baseflags);
1223        if (baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
1224            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1225            return;
1226        } else if (!baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
1227            InitOnlyInput(strInput, urlData_, flags_);
1228            if (!flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
1229                return;
1230            }
1231            if ((input[0] == '/') && (input[1] == '/' || (input[1] == '\\' &&
1232                baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT1))))) {
1233                std::string newInput = baseInfo.scheme + input;
1234                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT0), 0);
1235                InitOnlyInput(newInput, urlData_, flags_);
1236                return;
1237            }
1238            if (!baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT9))) {
1239                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT0), 0);
1240                BaseInfoToUrl(baseInfo, baseflags, urlData_, flags_, input.empty());
1241                ToolHasBase(input, strInput, urlData_, flags_);
1242                if (!input.empty() && input[0] != '/' && urlData_.path.empty()) {
1243                    urlData_.path = baseInfo.path;
1244                    flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT6),
1245                        baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT6)));
1246                }
1247                if (!input.empty() && input[0] != '/' && !urlData_.path.empty()) {
1248                    bool isFile = ((urlData_.scheme == "file:") ? true : false);
1249                    ShorteningPath(urlData_, baseInfo, isFile);
1250                    std::string basePathStr = BasePathToStr(baseInfo);
1251                    basePathStr == "" ? basePathStr = strInput : basePathStr += "/" + strInput;
1252                    urlData_.path.clear();
1253                    AnalysisInput(basePathStr, urlData_, flags_);
1254                    flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
1255                }
1256            } else if (baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT9))) {
1257                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1258                return;
1259            }
1260        }
1261    }
1262
1263    URL::URL(const std::string& input, const URL& base)
1264    {
1265        std::string strInput = input;
1266        UrlData baseInfo = base.urlData_;
1267        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> baseflags = base.flags_;
1268        DeleteC0OrSpace(strInput);
1269        DeleteTabOrNewline(strInput);
1270        InitOnlyInput(strInput, urlData_, flags_);
1271        if (!flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
1272            return;
1273        }
1274        if ((input[0] == '/') && (input[1] == '/' || (input[1] == '\\' &&
1275            baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT1))))) {
1276            std::string newInput = baseInfo.scheme + input;
1277            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT0), 0);
1278            InitOnlyInput(newInput, urlData_, flags_);
1279            return;
1280        }
1281        if (!baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT9))) {
1282            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT0), 0);
1283            BaseInfoToUrl(baseInfo, baseflags, urlData_, flags_, input.empty());
1284            ToolHasBase(input, strInput, urlData_, flags_);
1285            if (!input.empty() && input[0] != '/' && urlData_.path.empty()) {
1286                urlData_.path = baseInfo.path;
1287                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT6),
1288                    baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT6)));
1289            }
1290            if (!input.empty() && input[0] != '/' && !urlData_.path.empty()) {
1291                bool isFile = ((urlData_.scheme == "file:") ? true : false);
1292                ShorteningPath(urlData_, baseInfo, isFile);
1293                std::string basePathStr = BasePathToStr(baseInfo);
1294                basePathStr == "" ? basePathStr = strInput : basePathStr += "/" + strInput;
1295                urlData_.path.clear();
1296                AnalysisInput(basePathStr, urlData_, flags_);
1297                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
1298            }
1299        } else if (baseflags.test(static_cast<size_t>(BitsetStatusFlag::BIT9))) {
1300            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT0));
1301            return;
1302        }
1303    }
1304
1305    napi_value URL::GetHostname(napi_env env) const
1306    {
1307        napi_value result;
1308        std::string temp = "";
1309        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT4))) {
1310            temp = urlData_.host;
1311        }
1312        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1313        return result;
1314    }
1315
1316    napi_value URL::GetSearch(napi_env env) const
1317    {
1318        napi_value result;
1319        std::string temp = "";
1320        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT7)) && !(urlData_.query.size() == 1)) {
1321            temp = urlData_.query;
1322        }
1323        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1324        return result;
1325    }
1326
1327    napi_value URL::GetUsername(napi_env env) const
1328    {
1329        napi_value result;
1330        std::string temp = "";
1331        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT2))) {
1332            temp = urlData_.username;
1333        }
1334        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1335        return result;
1336    }
1337
1338    napi_value URL::GetPassword(napi_env env) const
1339    {
1340        napi_value result;
1341        std::string temp = "";
1342        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT3))) {
1343            temp = urlData_.password;
1344        }
1345        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1346        return result;
1347    }
1348
1349    napi_value URL::GetFragment(napi_env env) const
1350    {
1351        napi_value result;
1352        std::string temp = "";
1353        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT8)) && !(urlData_.fragment.size() == 1)) {
1354            temp = urlData_.fragment;
1355        }
1356        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1357        return result;
1358    }
1359
1360    napi_value URL::GetScheme(napi_env env) const
1361    {
1362        napi_value result;
1363        std::string temp = "";
1364        if (!urlData_.scheme.empty()) {
1365            temp = urlData_.scheme;
1366        }
1367        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1368        return result;
1369    }
1370
1371    napi_value URL::GetPath(napi_env env) const
1372    {
1373        napi_value result;
1374        std::string temp = "/";
1375        if (urlData_.isSpecialPath) {
1376            temp = "";
1377        }
1378        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT6))) {
1379            size_t length = urlData_.path.size();
1380            for (size_t i = 0; i < length; i++) {
1381                if (i < length - 1) {
1382                    temp += urlData_.path[i] + "/";
1383                } else {
1384                    temp += urlData_.path[i];
1385                }
1386            }
1387        } else {
1388            bool special = IsSpecial(urlData_.scheme);
1389            if (!special) {
1390                temp = "";
1391            }
1392        }
1393        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1394        return result;
1395    }
1396
1397
1398    napi_value URL::GetPort(napi_env env) const
1399    {
1400        napi_value result;
1401        std::string temp = "";
1402        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT5))) {
1403            temp = std::to_string(urlData_.port);
1404        }
1405        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1406        return result;
1407    }
1408
1409    napi_value URL::GetHost(napi_env env) const
1410    {
1411        napi_value result;
1412        std::string temp = urlData_.host;
1413        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT5))) {
1414            temp += ":";
1415            temp += std::to_string(urlData_.port);
1416        }
1417        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), temp.size(), &result));
1418        return result;
1419    }
1420
1421    napi_value URL::GetOnOrOff(napi_env env) const
1422    {
1423        napi_value result;
1424        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
1425            bool flag = false;
1426            NAPI_CALL(env, napi_get_boolean(env, flag, &result));
1427        } else {
1428            bool flag = true;
1429            NAPI_CALL(env, napi_get_boolean(env, flag, &result));
1430        }
1431        return result;
1432    }
1433
1434    napi_value URL::GetIsIpv6(napi_env env) const
1435    {
1436        napi_value result;
1437        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT10))) {
1438            NAPI_CALL(env, napi_get_boolean(env, true, &result));
1439        } else {
1440            NAPI_CALL(env, napi_get_boolean(env, false, &result));
1441        }
1442        return result;
1443    }
1444
1445    void URL::SetHostname(const std::string& input)
1446    {
1447        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT9))) {
1448            return;
1449        }
1450        std::string strHost = input;
1451        size_t length = strHost.size();
1452        for (size_t pos = 0; pos < length; pos++) {
1453            if ((strHost[pos] == ':') || (strHost[pos] == '?') || (strHost[pos] == '#') ||
1454                (strHost[pos] == '/') || (strHost[pos] == '\\')) {
1455                strHost = strHost.substr(0, pos);
1456                break;
1457            }
1458        }
1459        if (strHost.size() == 0) {
1460            return;
1461        }
1462        bool special = IsSpecial(urlData_.scheme);
1463        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> thisFlags;
1464        std::string thisHostname = "";
1465        AnalysisHost(strHost, thisHostname, thisFlags, special);
1466        if (thisFlags.test(static_cast<size_t>(BitsetStatusFlag::BIT4))) {
1467            if ((urlData_.scheme == "file:") && (thisHostname == "localhost")) {
1468                thisHostname = "";
1469            }
1470            urlData_.host = thisHostname;
1471            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
1472        }
1473    }
1474
1475    void URL::SetHref(const std::string& input)
1476    {
1477        std::string str = input;
1478        DeleteC0OrSpace(str);
1479        DeleteTabOrNewline(str);
1480        UrlData thisNewUrl;
1481        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> thisNewFlags;
1482        InitOnlyInput(str, thisNewUrl, thisNewFlags);
1483        if (!thisNewFlags.test(static_cast<size_t>(BitsetStatusFlag::BIT0))) {
1484            urlData_ = thisNewUrl;
1485            flags_ = thisNewFlags;
1486        }
1487    }
1488
1489    void URL::SetPath(const std::string& input)
1490    {
1491        std::string strPath = input;
1492        if (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT9)) || strPath.empty()) {
1493            return;
1494        }
1495        std::string oldstr = "%3A";
1496        std::string newstr = ":";
1497        ReplaceSpecialSymbols(strPath, oldstr, newstr);
1498        bool special = IsSpecial(urlData_.scheme);
1499        if (urlData_.scheme == "file:") {
1500            UrlData thisFileDate;
1501            std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> thisFileFlag;
1502            if ((strPath[0] == '/') || (strPath[0] == '\\' &&
1503                flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT1)))) {
1504                strPath = strPath.substr(1);
1505            }
1506            AnalysisFilePath(strPath, thisFileDate, thisFileFlag);
1507            if (thisFileFlag.test(static_cast<size_t>(BitsetStatusFlag::BIT6))) {
1508                urlData_.path = thisFileDate.path;
1509                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
1510            }
1511        } else {
1512            std::vector<std::string> thisPath;
1513            std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> thisFlags;
1514            if ((strPath[0] == '/') || (strPath[0] == '\\' &&
1515                flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT1)))) {
1516                strPath = strPath.substr(1);
1517            }
1518            AnalysisPath(strPath, thisPath, thisFlags, special);
1519            if (thisFlags.test(static_cast<size_t>(BitsetStatusFlag::BIT6))) {
1520                urlData_.path = thisPath;
1521                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT6));
1522            }
1523        }
1524    }
1525
1526    void SplitString(const std::string& input, std::string& strHost, std::string& port)
1527    {
1528        size_t strlen = input.size();
1529        for (size_t pos = 0; pos < strlen; pos++) {
1530            if ((input[pos] == ':') || (input[pos] == '?') || (input[pos] == '#') ||
1531                (input[pos] == '/') || (input[pos] == '\\')) {
1532                strHost = input.substr(0, pos);
1533                if (input[pos] == ':') {
1534                    pos++;
1535                    port = input.substr(pos);
1536                }
1537                break;
1538            }
1539        }
1540    }
1541
1542    void URL::SetHost(const std::string& input)
1543    {
1544        if (input.empty() || flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT9))) {
1545            return;
1546        }
1547        std::string strHost = input;
1548        std::string port = "";
1549        SplitString(input, strHost, port);
1550        if (strHost.size() == 0) {
1551            return;
1552        }
1553        bool special = IsSpecial(urlData_.scheme);
1554        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> hostnameflags;
1555        std::string thisHostname = "";
1556        AnalysisHost(strHost, thisHostname, hostnameflags, special);
1557        if (hostnameflags.test(static_cast<size_t>(BitsetStatusFlag::BIT4))) {
1558            if ((urlData_.scheme == "file:") && (thisHostname == "localhost")) {
1559                thisHostname = "";
1560            }
1561            urlData_.host = thisHostname;
1562            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT4));
1563        } else {
1564            return;
1565        }
1566        if (port.size() > 0) {
1567            size_t strlen = port.size();
1568            for (size_t pos = 0; pos < strlen; pos++) {
1569                if ((port[pos] == '?') || (port[pos] == '#') || (port[pos] == '/') || (port[pos] == '\\')) {
1570                    port = port.substr(0, pos);
1571                    break;
1572                }
1573            }
1574            if (port.size() > 0) {
1575                std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> thisFlags;
1576                UrlData thisport;
1577                AnalysisPort(port, thisport, thisFlags);
1578                if (thisFlags.test(static_cast<size_t>(BitsetStatusFlag::BIT5))) {
1579                    flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT5));
1580                    urlData_.port = thisport.port;
1581                }
1582            }
1583        }
1584    }
1585
1586    void URL::SetPort(const std::string& input)
1587    {
1588        std::string port = input;
1589        size_t portlen = port.size();
1590        for (size_t pos = 0; pos < portlen; pos++) {
1591            if ((port[pos] == '?') || (port[pos] == '#') || (port[pos] == '/') || (port[pos] == '\\')) {
1592                port = port.substr(0, pos);
1593                break;
1594            }
1595        }
1596        if (port.size() > 0) {
1597            std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> thisFlags;
1598            UrlData thisport;
1599            AnalysisPort(port, thisport, thisFlags);
1600            if (thisFlags.test(static_cast<size_t>(BitsetStatusFlag::BIT5))) {
1601                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT5));
1602                urlData_.port = thisport.port;
1603            }
1604        }
1605    }
1606
1607    void URL::SetSearch(const std::string& input)
1608    {
1609        std::string temp;
1610        if (input.size() == 0) {
1611            urlData_.query = "";
1612            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT7), 0);
1613        } else {
1614            if (input[0] != '?') {
1615                temp = "?";
1616                temp += input;
1617            } else {
1618                temp = input;
1619            }
1620            std::string oldstr = "#";
1621            std::string newstr = "%23";
1622            ReplaceSpecialSymbols(temp, oldstr, newstr);
1623            AnalysisQuery(temp, urlData_.query, flags_);
1624        }
1625    }
1626
1627    void URL::SetFragment(const std::string& input)
1628    {
1629        std::string temp;
1630        if (input.size() == 0) {
1631            urlData_.fragment = "";
1632            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT8), 0);
1633        } else {
1634            if (input[0] != '#') {
1635                temp = "#";
1636                temp += input;
1637            } else {
1638                temp = input;
1639            }
1640            AnalysisFragment(temp, urlData_.fragment, flags_);
1641        }
1642    }
1643
1644    void URL::SetScheme(const std::string& input)
1645    {
1646        std::string strInput = input;
1647        bool special = IsSpecial(urlData_.scheme);
1648        bool inputIsSpecial = IsSpecial(input);
1649        if ((special != inputIsSpecial) || ((input == "file") &&
1650            (flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT2)) ||
1651            flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT3)) ||
1652            flags_.test(static_cast<size_t>(BitsetStatusFlag::BIT5))))) {
1653            return;
1654        }
1655        std::string thisScheme = "";
1656        std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> thisFlags;
1657        if (AnalysisScheme(strInput, thisScheme, thisFlags)) {
1658            if (thisFlags.test(static_cast<size_t>(BitsetStatusFlag::BIT1))) {
1659                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT1));
1660            }
1661            urlData_.scheme = thisScheme;
1662        }
1663    }
1664
1665    void URL::SetUsername(const std::string& input)
1666    {
1667        if (input.size() == 0) {
1668            urlData_.username = "";
1669            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT2), 0);
1670        } else {
1671                std::string usname = input;
1672            size_t len = g_specialSymbols.size() - 2; // 2:Maximum position of subscript
1673            for (size_t i = 0; i <= len; i += 2) { // 2:Shift subscript right 2
1674            ReplaceSpecialSymbols(usname, g_specialSymbols[i], g_specialSymbols[i + 1]);
1675            }
1676                urlData_.username = usname;
1677                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT2));
1678        }
1679    }
1680
1681    void URL::SetPassword(const std::string& input)
1682    {
1683        if (input.size() == 0) {
1684            urlData_.password = "";
1685            flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT3), 0);
1686        } else {
1687                std::string keyWord = input;
1688            size_t len = g_specialSymbols.size() - 2; // 2:Maximum position of subscript
1689            for (size_t i = 0; i <= len; i += 2) { // 2:Shift subscript right 2
1690            ReplaceSpecialSymbols(keyWord, g_specialSymbols[i], g_specialSymbols[i + 1]);
1691            }
1692                urlData_.password = keyWord;
1693                flags_.set(static_cast<size_t>(BitsetStatusFlag::BIT3));
1694        }
1695    }
1696
1697    bool ContainsWideOrUnicodeChars(const std::string& str)
1698    {
1699        for (char c : str) {
1700            if (static_cast<unsigned char>(c) > 127) { // 127:Value range for non ASCII characters
1701                return true;
1702            }
1703        }
1704        return false;
1705    }
1706
1707    void URLSearchParams::HandleIllegalChar(std::wstring& inputStr, std::wstring::const_iterator it)
1708    {
1709        std::wstring::iterator iter = inputStr.begin();
1710        advance(iter, std::distance<std::wstring::const_iterator>(iter, it));
1711        while (iter != inputStr.end()) {
1712            char16_t ch = *iter;
1713            if (!((ch & 0xF800) == 0xD800)) {
1714                ++iter;
1715                continue;
1716            } else if ((ch & 0x400) != 0 || iter == inputStr.end() - 1) {
1717                *iter = 0xFFFD;
1718            } else {
1719                char16_t dh = *(iter + 1);
1720                if ((dh & 0xFC00) == 0xDC00) {
1721                    ++iter;
1722                } else {
1723                    *iter = 0xFFFD;
1724                }
1725            }
1726            ++iter;
1727        }
1728    }
1729    std::string URLSearchParams::ToUSVString(std::string inputStr)
1730    {
1731        std::wstring winput(inputStr.length(), L' ');
1732        std::copy(inputStr.begin(), inputStr.end(), winput.begin());
1733        std::wregex wexpr(L"(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])");
1734        std::wsmatch result;
1735        std::wstring::const_iterator iterStart = winput.begin();
1736        std::wstring::const_iterator iterEnd = winput.end();
1737        if (!regex_search(iterStart, iterEnd, result, wexpr)) {
1738            return inputStr;
1739        }
1740        HandleIllegalChar(winput, result[0].first);
1741        size_t inputLen = wcslen(winput.c_str());
1742        char *rePtr = nullptr;
1743        std::string reStr = "";
1744        size_t reSize = wcstombs(rePtr, winput.c_str(), 0) + 1;
1745        if (reSize > 0) {
1746            rePtr = new (std::nothrow) char[reSize];
1747            if (rePtr == nullptr) {
1748                HILOG_ERROR("URLSearchParams:: rePtr is nullptr");
1749                return reStr;
1750            }
1751            if (memset_s(rePtr, reSize, 0, reSize) != EOK) {
1752                HILOG_ERROR("ToUSVString memset_s failed");
1753                delete[] rePtr;
1754                return reStr;
1755            } else {
1756                wcstombs(rePtr, winput.c_str(), inputLen);
1757                reStr = rePtr;
1758            }
1759        }
1760        delete[] rePtr;
1761        return reStr;
1762    }
1763    napi_value URLSearchParams::Get(napi_env env, napi_value buffer)
1764    {
1765        std::string name = "";
1766        size_t nameSize = 0;
1767        if (napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize) != napi_ok) {
1768            HILOG_ERROR("can not get buffer size");
1769            return nullptr;
1770        }
1771        name.reserve(nameSize);
1772        name.resize(nameSize);
1773        if (napi_get_value_string_utf8(env, buffer, name.data(), nameSize + 1, &nameSize) != napi_ok) {
1774            HILOG_ERROR("can not get buffer value");
1775            return nullptr;
1776        }
1777        std::string sname = name;
1778        if (ContainsWideOrUnicodeChars(name)) {
1779            sname = ToUSVString(name);
1780        }
1781        napi_value result = nullptr;
1782        if (searchParams.size() == 0) {
1783            return result;
1784        }
1785        size_t size = searchParams.size() - 1;
1786        for (size_t i = 0; i < size; i += 2) { // 2:Searching for the number and number of keys and values
1787            if (searchParams[i] == sname) {
1788                napi_create_string_utf8(env, searchParams[i + 1].c_str(), searchParams[i + 1].length(), &result);
1789                return result;
1790            }
1791        }
1792        return result;
1793    }
1794    napi_value URLSearchParams::GetAll(napi_env env, napi_value buffer)
1795    {
1796        std::string name = "";
1797        size_t nameSize = 0;
1798        if (napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize) != napi_ok) {
1799            HILOG_ERROR("can not get buffer size");
1800            return nullptr;
1801        }
1802        name.reserve(nameSize);
1803        name.resize(nameSize);
1804        if (napi_get_value_string_utf8(env, buffer, name.data(), nameSize + 1, &nameSize) != napi_ok) {
1805            HILOG_ERROR("can not get buffer value");
1806            return nullptr;
1807        }
1808        std::string sname = name;
1809        if (ContainsWideOrUnicodeChars(name)) {
1810            sname = ToUSVString(name);
1811        }
1812        napi_value result = nullptr;
1813        napi_value napiStr = nullptr;
1814        NAPI_CALL(env, napi_create_array(env, &result));
1815        size_t flag = 0;
1816        if (searchParams.size() == 0) {
1817            return result;
1818        }
1819        size_t size = searchParams.size() - 1;
1820        for (size_t i = 0; i < size; i += 2) { // 2:Searching for the number and number of keys and values
1821            if (searchParams[i] == sname) {
1822                napi_create_string_utf8(env, searchParams[i + 1].c_str(), searchParams[i + 1].length(), &napiStr);
1823                NAPI_CALL(env, napi_set_element(env, result, flag, napiStr));
1824                flag++;
1825            }
1826        }
1827        return result;
1828    }
1829    void URLSearchParams::Append(napi_env env, napi_value buffer, napi_value temp)
1830    {
1831        std::string name = "";
1832        size_t nameSize = 0;
1833        if (napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize) != napi_ok) {
1834            HILOG_ERROR("can not get buffer size");
1835            return;
1836        }
1837        name.reserve(nameSize);
1838        name.resize(nameSize);
1839        if (napi_get_value_string_utf8(env, buffer, name.data(), nameSize + 1, &nameSize) != napi_ok) {
1840            HILOG_ERROR("can not get buffer value");
1841            return;
1842        }
1843        std::string tempName = name;
1844        std::string value = "";
1845        size_t valueSize = 0;
1846        if (napi_get_value_string_utf8(env, temp, nullptr, 0, &valueSize) != napi_ok) {
1847            HILOG_ERROR("can not get temp size");
1848            return;
1849        }
1850        value.reserve(valueSize);
1851        value.resize(valueSize);
1852        if (napi_get_value_string_utf8(env, temp, value.data(), valueSize + 1, &valueSize) != napi_ok) {
1853            HILOG_ERROR("can not get temp value");
1854            return;
1855        }
1856        std::string tempValue = value;
1857        searchParams.push_back(tempName);
1858        searchParams.push_back(tempValue);
1859    }
1860    void URLSearchParams::Delete(napi_env env, napi_value buffer)
1861    {
1862        std::string name = "";
1863        size_t nameSize = 0;
1864        if (napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize) != napi_ok) {
1865            HILOG_ERROR("can not get buffer size");
1866            return;
1867        }
1868        name.reserve(nameSize);
1869        name.resize(nameSize);
1870        if (napi_get_value_string_utf8(env, buffer, name.data(), nameSize + 1, &nameSize) != napi_ok) {
1871            HILOG_ERROR("can not get buffer value");
1872            return;
1873        }
1874        std::string sname = name;
1875        if (ContainsWideOrUnicodeChars(name)) {
1876            sname = ToUSVString(name);
1877        }
1878        for (auto iter = searchParams.begin(); iter != searchParams.end();) {
1879            if (*iter == sname) {
1880                iter = searchParams.erase(iter, iter + 2); // 2:Searching for the number and number of keys and values
1881            } else {
1882                iter += 2; // 2:Searching for the number and number of keys and values
1883            }
1884        }
1885    }
1886    napi_value URLSearchParams::Entries(napi_env env) const
1887    {
1888        napi_value resend = nullptr;
1889        napi_value firNapiStr = nullptr;
1890        napi_value secNapiStr = nullptr;
1891        napi_create_array(env, &resend);
1892        if (searchParams.size() == 0) {
1893            return resend;
1894        }
1895        size_t size = searchParams.size() - 1;
1896        for (size_t i = 0; i < size; i += 2) { // 2:Searching for the number and number of keys and values
1897            napi_value result = nullptr;
1898            napi_create_array(env, &result);
1899            napi_create_string_utf8(env, searchParams[i].c_str(), searchParams[i].length(), &firNapiStr);
1900            napi_create_string_utf8(env, searchParams[i + 1].c_str(), searchParams[i + 1].length(), &secNapiStr);
1901            napi_set_element(env, result, 0, firNapiStr);
1902            napi_set_element(env, result, 1, secNapiStr);
1903            napi_set_element(env, resend, i / 2, result); // 2:Find the number of keys
1904        }
1905        return resend;
1906    }
1907
1908    napi_value URLSearchParams::IsHas(napi_env env, napi_value name) const
1909    {
1910        size_t bufferSize = 0;
1911        if (napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize) != napi_ok) {
1912            HILOG_ERROR("can not get name size");
1913            return nullptr;
1914        }
1915        std::string buf = "";
1916        buf.resize(bufferSize);
1917        if (napi_get_value_string_utf8(env, name, buf.data(), bufferSize + 1, &bufferSize) != napi_ok) {
1918            HILOG_ERROR("can not get name value");
1919            return nullptr;
1920        }
1921        bool flag = false;
1922        napi_value result = nullptr;
1923        size_t lenStr = searchParams.size();
1924        for (size_t i = 0; i != lenStr; i += 2) { // 2:Searching for the number and number of keys and values
1925            if (searchParams[i] == buf) {
1926                flag = true;
1927                napi_get_boolean(env, flag, &result);
1928                return result;
1929            }
1930        }
1931        napi_get_boolean(env, flag, &result);
1932        return result;
1933    }
1934    void URLSearchParams::Set(napi_env env, napi_value name, napi_value value)
1935    {
1936        std::string buffer = "";
1937        size_t bufferSize = 0;
1938        if (napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize) != napi_ok) {
1939            HILOG_ERROR("can not get name size");
1940            return;
1941        }
1942        buffer.reserve(bufferSize);
1943        buffer.resize(bufferSize);
1944        if (napi_get_value_string_utf8(env, name, buffer.data(), bufferSize + 1, &bufferSize) != napi_ok) {
1945            HILOG_ERROR("can not get name value");
1946            return;
1947        }
1948        std::string cppName = buffer;
1949        std::string temp = "";
1950        size_t tempSize = 0;
1951        if (napi_get_value_string_utf8(env, value, nullptr, 0, &tempSize) != napi_ok) {
1952            HILOG_ERROR("can not get value size");
1953            return;
1954        }
1955        temp.reserve(tempSize);
1956        temp.resize(tempSize);
1957        if (napi_get_value_string_utf8(env, value, temp.data(), tempSize + 1, &tempSize) != napi_ok) {
1958            HILOG_ERROR("can not get value value");
1959            return;
1960        }
1961        std::string cppValue = temp;
1962        bool flag = false;
1963        for (auto it = searchParams.begin(); it < (searchParams.end() - 1) && !searchParams.empty();) {
1964            if (*it == cppName) {
1965                if (!flag) {
1966                    *(it + 1) = cppValue;
1967                    flag = true;
1968                    it += 2; // 2:Searching for the number and number of keys and values
1969                } else {
1970                    it = searchParams.erase(it, it + 2); // 2:Searching for the number and number of keys and values
1971                }
1972            } else {
1973                it += 2; // 2:Searching for the number and number of keys and values
1974            }
1975        }
1976        if (!flag) {
1977            searchParams.push_back(cppName);
1978            searchParams.push_back(cppValue);
1979        }
1980    }
1981    void URLSearchParams::Sort()
1982    {
1983        size_t len = searchParams.size();
1984        if (len <= 2 || (len % 2 != 0)) { // 2: Iterate over key-value pairs
1985            return;
1986        }
1987        size_t i = 0;
1988        for (; i < len - 2; i += 2) { // 2:Iterate over key-value pairs
1989            size_t j = i + 2; // 2:Iterate over key-value pairs
1990            for (; j < len; j += 2) { // 2:Iterate over key-value pairs
1991                bool tmp = (searchParams[i] > searchParams[j]);
1992                if (tmp) {
1993                    const std::string curKey = searchParams[i];
1994                    const std::string curVal = searchParams[i + 1];
1995                    searchParams[i] = searchParams[j];
1996                    searchParams[i + 1] = searchParams[j + 1];
1997                    searchParams[j] = curKey;
1998                    searchParams[j + 1] = curVal;
1999                }
2000            }
2001        }
2002    }
2003    napi_value URLSearchParams::IterByKeys(napi_env env)
2004    {
2005        std::vector<std::string> toKeys;
2006        napi_value result = nullptr;
2007        napi_value napiStr = nullptr;
2008        napi_create_array(env, &result);
2009        size_t stepSize = 2; // 2:Searching for the number and number of keys and values
2010        size_t lenStr = searchParams.size();
2011        if (lenStr % 2 == 0) { // 2:Get the number of values
2012            for (auto it = searchParams.begin(); it != searchParams.end(); it += stepSize) {
2013                toKeys.push_back(*it);
2014            }
2015            size_t lenToKeys = toKeys.size();
2016            for (size_t i = 0; i < lenToKeys; i++) {
2017                napi_create_string_utf8(env, toKeys[i].c_str(), toKeys[i].length(), &napiStr);
2018                napi_set_element(env, result, i, napiStr);
2019            }
2020        }
2021        return result;
2022    }
2023    napi_value URLSearchParams::IterByValues(napi_env env)
2024    {
2025        std::vector<std::string> toKeys;
2026        napi_value result = nullptr;
2027        napi_value napiStr = nullptr;
2028        napi_create_array(env, &result);
2029        size_t stepSize = 2; // 2:Searching for the number and number of keys and values
2030        size_t lenStr = searchParams.size();
2031        if (lenStr % 2 == 0) { // 2:Get the number of values
2032            for (auto it = searchParams.begin();
2033                it != searchParams.end();
2034                it += stepSize) {
2035                toKeys.push_back(*(it + 1));
2036            }
2037            size_t lenToKeys = toKeys.size();
2038            for (size_t i = 0; i < lenToKeys; i++) {
2039                napi_create_string_utf8(env, toKeys[i].c_str(), toKeys[i].length(), &napiStr);
2040                napi_set_element(env, result, i, napiStr);
2041            }
2042        }
2043        return result;
2044    }
2045    void URLSearchParams::SetArray(napi_env env, const std::vector<std::string> vec)
2046    {
2047        searchParams = vec;
2048    }
2049    napi_value URLSearchParams::GetArray(napi_env env) const
2050    {
2051        napi_value arr = nullptr;
2052        napi_create_array(env, &arr);
2053        size_t length = searchParams.size();
2054        for (size_t i = 0; i < length; i++) {
2055            napi_value result = nullptr;
2056            napi_create_string_utf8(env, searchParams[i].c_str(), searchParams[i].size(), &result);
2057            napi_set_element(env, arr, i, result);
2058        }
2059        return arr;
2060    }
2061} // namespace OHOS::Url
2062