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 #ifndef URL_JS_URL_H
17 #define URL_JS_URL_H
18 
19 #include <algorithm>
20 #include <bitset>
21 #include <cmath>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <map>
25 #include <string>
26 #include <vector>
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 namespace OHOS::Url {
30     enum class BitsetStatusFlag {
31         BIT0 = 0, // 0:Bit 0 Set to true,The URL analysis failed
32         BIT1 = 1, // 1:Bit 1 Set to true,The protocol is the default protocol
33         BIT2 = 2, // 2:Bit 2 Set to true,The URL has username
34         BIT3 = 3, // 3:Bit 3 Set to true,The URL has password
35         BIT4 = 4, // 4:Bit 4 Set to true,The URL has hostname
36         BIT5 = 5, // 5:Bit 5 Set to true,The URL Port is the specially
37         BIT6 = 6, // 6:Bit 6 Set to true,The URL has pathname
38         BIT7 = 7, // 7:Bit 7 Set to true,The URL has query
39         BIT8 = 8, // 8:Bit 8 Set to true,The URL has fragment
40         BIT9 = 9, // 9:Bit 9 Set to true,The URL Can not be base
41         BIT10 = 10, // 10:Bit 10 Set to true,The host is IPV6
42         BIT_STATUS_11 = 11, // 11:Each bit of a BIT represents a different parsing state.
43         BIT_ASCII_32 = 32, // 32:32-bit previously invalid control characters in ascii
44         BIT_ASCII_127 = 127, // 127:127 bits in ascii are DEL characters
45         MAX_BIT_SIZE = 128 // 128:ascii max range
46     };
47 
48     struct UrlData {
49         int port = -1;
50         bool isSpecialPath = false;
51         std::vector<std::string> path;
52         std::string password = "";
53         std::string scheme = "";
54         std::string query = "";
55         std::string username = "";
56         std::string fragment = "";
57         std::string host = "";
58     };
59 
60     bool IsHexDigit(const char& ch);
61     std::string DecodeSpecialChars(std::string input);
62     void DeleteC0OrSpace(std::string& str);
63     void DeleteTabOrNewline(std::string& str1);
64     std::string DealIpv4(std::string str);
65     std::string SplitNum(std::string num, size_t& number);
66     void FormatIpv6(std::string& str);
67     bool ISFileNohost(const std::string& input);
68     bool AnalysisScheme(std::string& input, std::string& scheme,
69         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
70     void AnalysisUsernameAndPasswd(std::string& input, std::string& username, std::string& password,
71         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
72     void AnalysisPath(std::string& input, std::vector<std::string>& path,
73         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags, bool isSpecial);
74     void AnalysisOpaqueHost(std::string input, std::string& host,
75         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
76     void AnalyseIPv4(const std::string& input, std::string& host,
77         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
78     void AnalysisHost(std::string& input, std::string& host,
79         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags, bool special);
80     void AnalysisFilePath(std::string& input, UrlData& urlinfo,
81         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
82     void AnalysisFilescheme(const std::string& input, UrlData& urlinfo,
83         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
84     void AnalyInfoPath(std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags,
85         UrlData& urlinfo, const std::string& input);
86     void AnalyHostPath(std::string &strHost, std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags,
87         UrlData& urlinfo);
88     void AnalyStrHost(std::string &strHost, UrlData& urlinfo,
89         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags);
90     void AnalysisNoDefaultProtocol(std::string& input, UrlData& urlinfo,
91         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
92     void AnalysisOnlyHost(const std::string& input, UrlData& urlinfo,
93         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags, size_t pos);
94     void FormatIpv4(std::vector<std::string> nums, std::string& host,
95                     std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> &flags);
96     void AnalysisSpecialFile(std::string& temp, size_t pos, UrlData& urlinfo,
97                              std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
98     void AnalysisFile(std::string& input, UrlData& urlinfo,
99                       std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
100     void ParsingHostAndPath(std::string& input, UrlData& urlinfo, size_t& pos,
101                             std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
102     void ShorteningPath(UrlData& urlData, UrlData& baseData, bool isFile);
103     void RemoveLeadingZeros(std::vector<std::string> &ipv6);
104     void IPv6Host(std::string& input, std::string& host,
105                   std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)>& flags);
106     std::string BasePathToStr(UrlData& urlData);
107     class URL {
108     public:
109         /**
110          * URI constructor, which is used to instantiate a URI object.
111          *
112          * @param input Constructs a URI by parsing a given string.
113          */
114         explicit URL(const std::string& input);
115 
116         /**
117          * URI constructor, which is used to instantiate a URI object.
118          *
119          * @param input Constructs a URI by parsing a given string.
120          * @param base The input parameter is a character string.
121          */
122         URL(const std::string& input, const std::string& base);
123 
124         /**
125          * URI constructor, which is used to instantiate a URI object.
126          *
127          * @param input Constructs a URI by parsing a given string.
128          * @param base The input parameter is the URL object.
129          */
130         URL(const std::string& input, const URL& base);
131 
132         /**
133          *
134          * @param env NAPI environment parameters.
135          * Gets the host name portion of the URL��not include the port.
136          */
137         napi_value GetHostname(napi_env env) const;
138 
139         /**
140          * Sets the host name portion of the URL��not include the port.
141          *
142          * @param input Constructs a URI by parsing a given string.
143          */
144         void SetHostname(const std::string& input);
145 
146         /**
147          * Sets the username name portion of the URL��not include the port.
148          *
149          * @param input Constructs a URI by parsing a given string.
150          */
151         void SetUsername(const std::string& input);
152 
153         /**
154          * Sets the password portion of the URL��not include the port.
155          *
156          * @param input Constructs a URI by parsing a given string.
157          */
158         void SetPassword(const std::string& input);
159 
160         /**
161          * Sets the scheme portion of the URL��not include the port.
162          *
163          * @param input Constructs a URI by parsing a given string.
164          */
165         void SetScheme(const std::string& input);
166 
167         /**
168          * Sets the fragment portion of the URL��not include the port.
169          *
170          * @param input Constructs a URI by parsing a given string.
171          */
172         void SetFragment(const std::string& input);
173 
174         /**
175          * Sets the search portion of the URL��not include the port.
176          *
177          * @param input Constructs a URI by parsing a given string.
178          */
179         void SetSearch(const std::string& input);
180 
181         /**
182          * Sets the host portion of the URL��not include the port.
183          *
184          * @param input Constructs a URI by parsing a given string.
185          */
186         void SetHost(const std::string& input);
187 
188         /**
189          * Sets the port portion of the URL��not include the port.
190          *
191          * @param input Constructs a URI by parsing a given string.
192          */
193         void SetPort(const std::string& input);
194 
195         /**
196          * Sets the href portion of the URL��not include the port.
197          *
198          * @param input Constructs a URI by parsing a given string.
199          */
200         void SetHref(const std::string& input);
201 
202         /**
203          * Sets the path portion of the URL��not include the port.
204          *
205          * @param input Constructs a URI by parsing a given string.
206          */
207         void SetPath(const std::string& input);
208 
209         /**
210          * Gets the search portion of the URL��not include the port.
211          *
212          * @param env NAPI environment parameters.
213          */
214         napi_value GetSearch(napi_env env) const;
215 
216         /**
217          * Gets the username portion of the URL��not include the port.
218          *
219          * @param env NAPI environment parameters.
220          */
221         napi_value GetUsername(napi_env env) const;
222 
223         /**
224          * Gets the password portion of the URL��not include the port.
225          *
226          * @param env NAPI environment parameters.
227          */
228         napi_value GetPassword(napi_env env) const;
229 
230         /**
231          * Gets the fragment portion of the URL��not include the port.
232          *
233          * @param env NAPI environment parameters.
234          */
235         napi_value GetFragment(napi_env env) const;
236 
237         /**
238          * Gets the scheme portion of the URL��not include the port.
239          *
240          * @param env NAPI environment parameters.
241          */
242         napi_value GetScheme(napi_env env) const;
243 
244         /**
245          * Gets the path portion of the URL��not include the port.
246          *
247          * @param env NAPI environment parameters.
248          */
249         napi_value GetPath(napi_env env) const;
250 
251         /**
252          * Gets the port portion of the URL��not include the port.
253          *
254          * @param env NAPI environment parameters.
255          */
256         napi_value GetPort(napi_env env) const;
257 
258         /**
259          * Judge whether it's on or off.
260          *
261          * @param env NAPI environment parameters.
262          */
263         napi_value GetOnOrOff(napi_env env) const;
264 
265         /**
266          * Judge whether it's Ipv6.
267          *
268          * @param env NAPI environment parameters.
269          */
270         napi_value GetIsIpv6(napi_env env) const;
271 
272         /**
273          * Gets the host name portion of the URL��not include the port.
274          *
275          * @param env NAPI environment parameters.
276          */
277         napi_value GetHost(napi_env env) const;
278 
279         /**
280          * The destructor of the url
281          */
~URL()282         virtual ~URL() {}
283 
284     private:
285         UrlData urlData_;
286         std::bitset<static_cast<size_t>(BitsetStatusFlag::BIT_STATUS_11)> flags_;
287         // bitset<11>:Similar to bool array, each bit status represents the real-time status of current URL parsing
288     };
289 
290     class URLSearchParams {
291     public:
292         /**
293          * A parameterized constructor used to create an URLSearchParams instance.
294          */
URLSearchParams()295         explicit URLSearchParams() {}
296 
297         /**
298          * Virtual destructor of URLSearchParams
299          */
~URLSearchParams()300         virtual ~URLSearchParams() {}
301 
302         /**
303          * Returns a Boolean that indicates whether a parameter with the specified name exists.
304          *
305          * @param env NAPI environment parameters.
306          * @param name Specifies the name of a key-value pair.
307          */
308         napi_value IsHas(napi_env env, napi_value  name) const;
309 
310         /**
311          * Returns the first value associated to the given search parameter.
312          *
313          * @param env NAPI environment parameters.
314          * @param buffer Returns the first value associated to the given search parameter.
315          */
316         napi_value Get(napi_env env, napi_value buffer);
317 
318         /**
319          * Returns all key-value pairs associated with a given search parameter as an array.
320          *
321          * @param env NAPI environment parameters.
322          * @param buffer Specifies the name of a key value.
323          */
324         napi_value GetAll(napi_env env, napi_value buffer);
325 
326         /**
327          * Appends a specified key/value pair as a new search parameter.
328          *
329          * @param env NAPI environment parameters.
330          * @param buffer Key name of the search parameter to be inserted.
331          * @param temp Values of search parameters to be inserted.
332          */
333         void Append(napi_env env, napi_value buffer, napi_value temp);
334 
335         /**
336          * Deletes the given search parameter and its associated value,from the list of all search parameters.
337          *
338          * @param env NAPI environment parameters.
339          * @param buffer Name of the key-value pair to be deleted.
340          */
341         void Delete(napi_env env, napi_value buffer);
342 
343         /**
344          * Returns an ES6 iterator. Each item of the iterator is a JavaScript Array.
345          *
346          * @param env NAPI environment parameters.
347          */
348         napi_value Entries(napi_env env) const;
349 
350         /**
351          * Sets the value associated with a given search parameter to the
352          * given value. If there were several matching values, this method
353          * deletes the others. If the search parameter doesn't exist, this
354          * method creates it.
355          *
356          * @param env NAPI environment parameters.
357          * @param name Key name of the parameter to be set.
358          * @param value Indicates the parameter value to be set.
359          */
360         void Set(napi_env env, napi_value name, napi_value value);
361 
362         /**
363          * Sort all key/value pairs contained in this object in place and return undefined.
364          */
365         void Sort();
366 
367         /**
368          * Returns an iterator allowing to go through all keys contained in this object.
369          *
370          * @param env NAPI environment parameters.
371          */
372         napi_value IterByKeys(napi_env env);
373 
374         /**
375          * Returns an iterator allowing to go through all values contained in this object.
376          *
377          * @param env NAPI environment parameters.
378          */
379         napi_value IterByValues(napi_env env);
380 
381         /**
382          * Sets the string array of searchParams.
383          *
384          * @param env NAPI environment parameters.
385          * @param input String array.
386          */
387         void SetArray(napi_env env, std::vector<std::string> input);
388 
389         /**
390          * Gets the string array of searchParams.
391          *
392          * @param env NAPI environment parameters.
393          */
394         napi_value GetArray(napi_env env) const;
395 
396         /**
397          * This function will decode the string and put the parsed key and value values into the
398          * vector container of urlsearchparams class according to the rules.
399          *
400          * @param env NAPI environment parameters.
401          * @param Stringpar The input parameter of urlsearchparams is string.
402          */
403         std::vector<std::string> StringParmas(napi_env env, std::string Stringpar);
404 
405     private:
406         std::string ToUSVString(std::string inputStr);
407         void HandleIllegalChar(std::wstring& inputStr, std::wstring::const_iterator it);
408         std::vector<std::string> searchParams {};
409     };
410 } // namespace OHOS::Url
411 #endif // URL_JS_URL_H
412