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