• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "url_helper.h"
17 
18 #include <chrono>
19 #include <vector>
20 
21 #include "tools/log.h"
22 
23 namespace OHOS::Url {
EncodePercentEncoding(const std::string_view inputString,const uint16_t codeMap[])24 std::string EncodePercentEncoding(const std::string_view inputString, const uint16_t codeMap[])
25 {
26     auto firstToEncode = std::find_if(inputString.begin(), inputString.end(), [codeMap](char current) {
27         uint8_t currentValue = static_cast<uint8_t>(current);
28         return NeedEncode(codeMap, currentValue);
29     });
30     if (firstToEncode == inputString.end()) {
31         return std::string(inputString);
32     }
33     std::string encodeString;
34     encodeString.reserve(inputString.length() * PERCENT_ENCODING_LENGTH);
35     encodeString.append(inputString.data(), firstToEncode - inputString.begin());
36     for (auto index = firstToEncode; index != inputString.end(); ++index) {
37         uint8_t currentValue = static_cast<uint8_t>(*index);
38         if (NeedEncode(codeMap, currentValue)) {
39             encodeString.push_back('%');
40             encodeString.push_back(HEX_CHAR_MAP[currentValue >> SHIFT_SIZE]);
41             encodeString.push_back(HEX_CHAR_MAP[currentValue & 0x0F]);
42         } else {
43             encodeString.push_back(*index);
44         }
45     }
46     return encodeString;
47 }
48 
49 // 110XXXXX 10XXXXXXX
50 // 1110XXXX 10XXXXXXX 10XXXXXXX
51 // 11110XXX 10XXXXXXX 10XXXXXXX 10XXXXXXXX
CheckUTF8Enble(const std::string_view inputString,size_t i,char currentChar,int count,char * chars)52 bool CheckUTF8Enble(const std::string_view inputString, size_t i, char currentChar, int count, char* chars)
53 {
54     if (count <= 0) {
55         return false;
56     }
57     int index = count - 1;
58     chars[index] = currentChar;
59     char charactor;
60     while (i < inputString.size() && index > 0) {
61         if (PercentCharDecodable(inputString, i, charactor)) {
62             // 6, 0x2, subChar need begin with 10XXXXXX
63             if (((charactor >> 6) ^ 0x2) != 0) {
64                 return false;
65             }
66             i += (HEX_PAIR_LENGTH + 1);
67             index--;
68             chars[index] = charactor;
69         } else {
70             return false;
71         }
72     }
73     return index == 0;
74 }
75 
DecodePercentEncoding(const std::string_view inputString)76 std::string DecodePercentEncoding(const std::string_view inputString)
77 {
78     if (inputString.find("%") == std::string_view::npos) {
79         return std::string(inputString);
80     }
81     std::string result;
82     result.reserve(inputString.size());
83     size_t i = 0;
84     char chars[CHARS_LENGTH];
85     char ch;
86     while (i < inputString.size()) {
87         // convert to decimal characters and append to the result
88         if (PercentCharDecodable(inputString, i, ch)) {
89             auto length = GetCharLength(ch);
90             if (CheckUTF8Enble(inputString, i + HEX_PAIR_LENGTH + 1, ch, length, chars)) {
91                 AppendChars(result, i, length, chars);
92             } else {
93                 result += inputString.substr(i, (HEX_PAIR_LENGTH + 1));
94                 i += (HEX_PAIR_LENGTH + 1);
95             }
96         } else {
97             // normal character
98             result += inputString[i];
99             ++i;
100         }
101     }
102     return result;
103 }
104 
StringAnalyzing(std::string_view inputString,std::vector<KeyValue> & results)105 void StringAnalyzing(std::string_view inputString, std::vector<KeyValue>& results)
106 {
107     if (!inputString.empty() && ('?' == inputString.front() || '&' == inputString.front())) {
108         inputString.remove_prefix(1);
109     }
110     auto segmentProcess = [](const std::string_view current, std::vector<KeyValue>& res) {
111         if (current.empty()) {
112             res.emplace_back("", "");
113             return;
114         }
115         auto equalIndex = current.find('=');
116         std::string name;
117         std::string value;
118         std::string decodeName;
119         std::string decodeValue;
120         if (equalIndex == std::string_view::npos) {
121             name = std::string(current);
122         } else {
123             name = std::string(current.substr(0, equalIndex));
124             value = std::string(current.substr(equalIndex + 1));
125         }
126         std::replace(name.begin(), name.end(), '+', ' ');
127         decodeName = DecodePercentEncoding(name);
128         if (!value.empty()) {
129             std::replace(value.begin(), value.end(), '+', ' ');
130             decodeValue = DecodePercentEncoding(value);
131         }
132         res.emplace_back(decodeName, decodeValue);
133     };
134     while (!inputString.empty()) {
135         auto segmentIndex = inputString.find('&');
136         segmentProcess(inputString.substr(0, segmentIndex), results);
137         inputString.remove_prefix(segmentIndex + 1);
138         if (segmentIndex == std::string_view::npos) {
139             break;
140         }
141     }
142 }
143 } // namespace OHOS::Url