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