• 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,unsigned char currentChar,size_t count,unsigned char * chars)52 bool CheckUTF8Enble(const std::string_view inputString, size_t i,
53                     unsigned char currentChar, size_t count, unsigned char* chars)
54 {
55     if (count == 0) {
56         return false;
57     }
58     size_t index = count - 1;
59     chars[index] = currentChar;
60     unsigned char charactor;
61     while (i < inputString.size() && index > 0) {
62         if (PercentCharDecodable(inputString, i, charactor)) {
63             // 6, 0x2, subChar need begin with 10XXXXXX
64             if (((charactor >> 6) ^ 0x2) != 0) {
65                 return false;
66             }
67             i += (HEX_PAIR_LENGTH + 1);
68             index--;
69             chars[index] = charactor;
70         } else {
71             return false;
72         }
73     }
74     return index == 0;
75 }
76 
DecodePercentEncoding(const std::string_view inputString)77 std::string DecodePercentEncoding(const std::string_view inputString)
78 {
79     if (inputString.find("%") == std::string_view::npos) {
80         return std::string(inputString);
81     }
82     std::string result;
83     result.reserve(inputString.size());
84     size_t i = 0;
85     unsigned char chars[CHARS_LENGTH];
86     unsigned char ch;
87     while (i < inputString.size()) {
88         // convert to decimal characters and append to the result
89         if (PercentCharDecodable(inputString, i, ch)) {
90             size_t length = GetCharLength(ch);
91             if (CheckUTF8Enble(inputString, i + HEX_PAIR_LENGTH + 1, ch, length, chars)) {
92                 AppendChars(result, i, length, chars);
93             } else {
94                 result += inputString.substr(i, (HEX_PAIR_LENGTH + 1));
95                 i += (HEX_PAIR_LENGTH + 1);
96             }
97         } else {
98             // normal character
99             result += inputString[i];
100             ++i;
101         }
102     }
103     return result;
104 }
105 
StringAnalyzing(std::string_view inputString,std::vector<KeyValue> & results)106 void StringAnalyzing(std::string_view inputString, std::vector<KeyValue>& results)
107 {
108     if (!inputString.empty() && ('?' == inputString.front() || '&' == inputString.front())) {
109         inputString.remove_prefix(1);
110     }
111     auto segmentProcess = [](const std::string_view current, std::vector<KeyValue>& res) {
112         if (current.empty()) {
113             res.emplace_back("", "");
114             return;
115         }
116         auto equalIndex = current.find('=');
117         std::string name;
118         std::string value;
119         std::string decodeName;
120         std::string decodeValue;
121         if (equalIndex == std::string_view::npos) {
122             name = std::string(current);
123         } else {
124             name = std::string(current.substr(0, equalIndex));
125             value = std::string(current.substr(equalIndex + 1));
126         }
127         std::replace(name.begin(), name.end(), '+', ' ');
128         decodeName = DecodePercentEncoding(name);
129         if (!value.empty()) {
130             std::replace(value.begin(), value.end(), '+', ' ');
131             decodeValue = DecodePercentEncoding(value);
132         }
133         res.emplace_back(decodeName, decodeValue);
134     };
135     while (!inputString.empty()) {
136         auto segmentIndex = inputString.find('&');
137         segmentProcess(inputString.substr(0, segmentIndex), results);
138         inputString.remove_prefix(segmentIndex + 1);
139         if (segmentIndex == std::string_view::npos) {
140             break;
141         }
142     }
143 }
144 } // namespace OHOS::Url