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