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"
29namespace 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         */
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         */
295        explicit URLSearchParams() {}
296
297        /**
298         * Virtual destructor of URLSearchParams
299         */
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