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