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