diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..4a459866a57c25462afad17f3fe0b50d440da080 --- /dev/null +++ b/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/README.en.md b/README.en.md index bb17e30ce94cbcad5da3477d550ef3da1a35d895..0d7b8f4bc585f68e65dc8d31c0c602c7dd63068b 100644 --- a/README.en.md +++ b/README.en.md @@ -1,36 +1,145 @@ -# js_api_module - -#### Description -{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +# js_api_module +# Introduction to URL +The URL interface is used to parse, construct, normalize, and encode URLs. The URL constructor creates a new URL object. In order to make changes to the resolved components of the URL or to the URL. + +Interface introduction + +1.new URL(url: string,base?:string|URL) + +Create and return a URL object that references the URL specified by the absolute URL string, the relative URL string, and the basic URL string. + +2.tostring():string; + +The stringification method returns a USVString containing the complete URL. It is equivalent to the read-only URL.href. + +3.toJSON():string; + +This method returns a USVString, which contains a serialized URL version. + +The usage of each interface is as follows: + +let b = new URL('https://developer.mozilla.org'); // => 'https://developer.mozilla.org/' + +let a = new URL( 'sca/./path/path/../scasa/jjjjj', 'http://www.example.com'); +// => 'http://www.example.com/sca/path/scasa/jjjjj' + +const url = new URL('http://10.0xFF.O400.235:8080/directory/file?query#fragment'); +url.toString() // => 'http://10.0xff.o400.235:8080/directory/file?query#fragment' + +const url = new URL("http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html"); +url.toString() // => 'http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/index.html' + +const url = new URL("http://username:password@host:8080/directory/file?query#fragment"); +url.toString() // => 'http://username:password@host:8080/directory/file?query#fragment' + +const url = new URL("https://developer.mozilla.org/en-US/docs/Web/API/URL/toString"); +url.toJSON(); // => 'https://developer.mozilla.org/en-US/docs/Web/API/URL/toString' + + +####2nd. Introduction to URLSreachParams + +The URLSearchParams interface defines some practical methods to process URL query strings. + +Interface introduction + +1.new URLSearchParams() + +The URLSearchParams() constructor has no parameters. This method creates and returns a new URLSearchParams object. The beginning'?' character will be ignored. + +2.new URLSearchParams(string) + +The input parameter of URLSearchParams(string) constructor is string data type. + +3.new URLSearchParams(obj) + +The input parameter of URLSearchParams(obj) constructor is obj data type. + +4.new URLSearchParams(iterable) + +The input parameter of URLSearchParams(iterable) constructor is iterable data type. + +5.isHas(name: string): boolean + +Retrieve whether the searchParams object contains name. If yes, it returns true, otherwise it returns false. + +6.set(name: string, value string): void + +Retrieve whether the searchParams object contains a key-value pair whose key is name. +If not, add the key-value pair, if any, modify the value corresponding to the first key in the object, and delete the remaining key-value pairs whose key is name. + +7.sort(): void + +According to the Unicode code point of the key, sort all key/value pairs contained in this object and return undefined. + +8.toString(): string + +According to the searchParams object, the query string applicable in the URL is returned. + +9.keys(): iterableIterator + +Return an iterator, which allows iterating through all the key values contained in the object. + +10.values(): iterableIterator + +Returns an iterator, which allows iterating over all the value values contained in the object. + +11.append(name: string, value: string): void + +Insert the name, value key-value pair in the searchParams object. + +12.delete(name: string): void + +Traverse the searchParams object, find all the names, and delete the corresponding key-value pairs. + +13.get(name: string): string + +Retrieve the first name in the searchParams object and return the value corresponding to the name key. + +14.getAll(name: string): string[] + +Retrieve all names in the searchParams object and return all the values corresponding to the name key. + +15.entries(): iterableIterator<[string, string]> + +Returns an iterator that allows iterating through all key/value pairs contained in the searchParams object. + +16.forEach(): void +The callback function is used to traverse the key-value pairs on the URLSearchParams instance object. + +The usage of each interface is as follows: + +let params = new URLSearchParams('foo=1&bar=2'); + +console.log(params.has('bar')); // =>ture + +params.set('baz', 3); + +params .sort(); +console.log(params .toString()); // =>bar=2&baz=3&foo=1' + +for(var key of params.keys()) { + console.log(key); +} + // =>bar baz foo +for(var value of params.values()) { + console.log(value); +} // =>2 3 1 + +params.append('foo', 3); // =>bar=2&baz=3&foo=1&foo=3 + +params.delete('baz'); // => bar=2&foo=1&foo=3 + +params.get('foo'); // => 1 + +params.getAll('foo'); // =>[ '1', '3' ] + +for(var pair of searchParams.entries()) { + console.log(pair[0]+ ', '+ pair[1]); +} // => bar, 2 foo, 1 foo, 3 + +url.searchParams.forEach((value, name, searchParams) => { + console.log(name, value, url.searchParams === searchParams); +}); + +// => foo 1 true +// => bar 2 true diff --git a/README.md b/README.md index 434df23cc3810e4b3b2ad8f00e07aad76be1a646..7d449a873ed3edb2d9d8c7ac8f792a58e14392d6 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,145 @@ -# js_api_module - -#### 介绍 -{**以下是 Gitee 平台说明,您可以替换此简介** -Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 -无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} - -#### 软件架构 -软件架构说明 - - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx - -#### 使用说明 - -1. xxxx -2. xxxx -3. xxxx - -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request - - -#### 特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +#### js_api_module +####一、URL简介 +URL接口用于解析,构造,规范化和编码 URLs。 URL的构造函数创建新的URL对象。 以便对URL的已解析组成部分或对URL进行更改。 + +接口介绍 + +1.new URL(url: string,base?:string|URL) + +创建并返回一个URL对象,该URL对象引用使用绝对URL字符串,相对URL字符串和基本URL字符串指定的URL。 + +2.tostring():string; + +该字符串化方法返回一个包含完整 URL 的 USVString。它的作用等同于只读的 URL.href。 + +3.toJSON():string; + +该方法返回一个USVString,其中包含一个序列化的URL版本。 + +各接口使用方法如下: + +let b = new URL('https://developer.mozilla.org'); // => 'https://developer.mozilla.org/' + +let a = new URL( 'sca/./path/path/../scasa/jjjjj', 'http://www.example.com'); +// => 'http://www.example.com/sca/path/scasa/jjjjj' + +const url = new URL('http://10.0xFF.O400.235:8080/directory/file?query#fragment'); +url.toString() // => 'http://10.0xff.o400.235:8080/directory/file?query#fragment' + +const url = new URL("http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html"); +url.toString() // => 'http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/index.html' + +const url = new URL("http://username:password@host:8080/directory/file?query#fragment"); +url.toString() // => 'http://username:password@host:8080/directory/file?query#fragment' + +const url = new URL("https://developer.mozilla.org/en-US/docs/Web/API/URL/toString"); +url.toJSON(); // => 'https://developer.mozilla.org/en-US/docs/Web/API/URL/toString' + + +####二、URLSreachParams简介 + +URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串。 + +接口介绍 + +1.new URLSearchParams() + +URLSearchParams() 构造器无入参,该方法创建并返回一个新的URLSearchParams 对象。 开头的'?' 字符会被忽略。 + +2.new URLSearchParams(string) + +URLSearchParams(string) 构造器的入参为string数据类型,该方法创建并返回一个新的URLSearchParams 对象。 开头的'?' 字符会被忽略。 + +3.new URLSearchParams(obj) + +URLSearchParams(obj) 构造器的入参为obj数据类型,该方法创建并返回一个新的URLSearchParams 对象。 开头的'?' 字符会被忽略。 + +4.new URLSearchParams(iterable) + +URLSearchParams(iterable) 构造器的入参为iterable数据类型,该方法创建并返回一个新的URLSearchParams 对象。 开头的'?' 字符会被忽略。 + +5.isHas(name: string): boolean + +检索searchParams对象中是否含有name。有则返回ture,否则返回false。 + +6.set(name: string, value string): void + +检索searchParams对象中是否含有key为name的键值对。 +没有的话则添加该键值对,有的话则修改对象中第一个key所对应的value,并删除键为name的其余键值对。 + +7.sort(): void + +根据键的Unicode代码点,对包含在此对象中的所有键/值对进行排序,并返回undefined。 + +8.toString(): string + +根据searchParams对象,返回适用在URL中的查询字符串。 + +9.keys(): iterableIterator + +返回一个iterator,遍历器允许遍历对象中包含的所有key值。 + +10.values(): iterableIterator + +返回一个iterator,遍历器允许遍历对象中包含的所有value值。 + +11.append(name: string, value: string): void + +在searchParams对象中插入name, value键值对。 + +12.delete(name: string): void + +遍历searchParams对象,查找所有的name,删除对应的键值对。 + +13.get(name: string): string + +检索searchParams对象中第一个name,返回name键对应的值。 + +14.getAll(name: string): string[] + +检索searchParams对象中所有name,返回name键对应的所有值。 + +15.entries(): iterableIterator<[string, string]> + +返回一个iterator,允许遍历searchParams对象中包含的所有键/值对。 + +16.forEach(): void +通过回调函数来遍历URLSearchParams实例对象上的键值对. + +各接口使用方法如下: + +let params = new URLSearchParams('foo=1&bar=2'); + +console.log(params.has('bar')); // =>ture + +params.set('baz', 3); + +params .sort(); +console.log(params .toString()); // =>bar=2&baz=3&foo=1' + +for(var key of params.keys()) { + console.log(key); +} + // =>bar baz foo +for(var value of params.values()) { + console.log(value); +} // =>2 3 1 + +params.append('foo', 3); // =>bar=2&baz=3&foo=1&foo=3 + +params.delete('baz'); // => bar=2&foo=1&foo=3 + +params.get('foo'); // => 1 + +params.getAll('foo'); // =>[ '1', '3' ] + +for(var pair of searchParams.entries()) { + console.log(pair[0]+ ', '+ pair[1]); +} // => bar, 2 foo, 1 foo, 3 + +url.searchParams.forEach((value, name, searchParams) => { + console.log(name, value, url.searchParams === searchParams); +}); + +// => foo 1 true +// => bar 2 true diff --git a/ohos.build b/ohos.build new file mode 100644 index 0000000000000000000000000000000000000000..ef9210f0bf3d672693c3fdba9792f4e33c2ba171 --- /dev/null +++ b/ohos.build @@ -0,0 +1,18 @@ +{ + "subsystem": "ccruntime", + "parts": { + "jsapi_api": { + "variants": [ + "wearable", + "phone" + ], + "module_list": [ + "//base/compileruntime/js_api_module/url:url_packages" + ], + "inner_kits": [ + ], + "test_list": [ + ] + } + } +} diff --git a/url/BUILD.gn b/url/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..517e54939250bc9ffeb68aed11e69f3e76f80092 --- /dev/null +++ b/url/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") + +base_output_path = get_label_info(":js_url", "target_out_dir") +js_url_obj_path = base_output_path + "/url.o" +gen_js_obj("js_url") { + input = "//base/compileruntime/js_api_module/url/js_url.js" + output = js_url_obj_path +} + +ohos_shared_library("url") { + include_dirs = [ + "//third_party/icu/icu4c/source/common", + "//third_party/node/src", + "//foundation/ace/napi/interfaces/kits", + "//base/compileruntime/js_api_module/url", + ] + + sources = [ + "js_url.cpp", + "native_module_url.cpp", + ] + + deps = [ + ":js_url", + "//base/compileruntime/js_api_module/url/:js_url", + "//foundation/ace/napi/:ace_napi", + "//foundation/ace/napi/:ace_napi_quickjs", + "//third_party/icu/icu4c:static_icuuc", + "//utils/native/base:utils", + ] + + if (is_standard_system) { + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + } else { + external_deps = [ "hilog:libhilog" ] + } + subsystem_name = "ccruntime" + part_name = "jsapi_api" +} + +group("url_packages") { + deps = [ ":url" ] +} diff --git a/url/js_url.cpp b/url/js_url.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d92e43a1b1fedd49f769b8346158d70fcf00b8a2 --- /dev/null +++ b/url/js_url.cpp @@ -0,0 +1,1980 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "js_url.h" +#include "utils/log.h" +#include "securec.h" +#include + +std::map g_head = { {"ftp:", 21}, {"file:", -1}, {"gopher:", 70}, {"http:", 80}, + {"https:", 443}, {"ws:", 80}, {"wss:", 443} }; + +std::vector g_doubleSegment = { "..", ".%2e", ".%2E", "%2e.", "%2E.", + "%2e%2e", "%2E%2E", "%2e%2E", "%2E%2e" }; + +std::vector g_singlesegment = { ".", "%2e", "%2E" }; + +std::vector g_specialcharacter = { '\0', '\t', '\n', '\r', ' ', '#', '%', '/', ':', '?', '@', '[', '\\', ']' }; + +#define MAXPORT 65535 + +void ReplaceSpecialSymbols(std::string& input,std::string& oldstr,std::string& newstr) +{ + size_t oldlen = oldstr.size(); + while(true) { + size_t pos = 0; + if((pos = input.find(oldstr)) != std::string::npos) { + input.replace(pos,oldlen,newstr); + } else { + break; + } + } +} + +template +bool IsASCIITabOrNewline(const T ch) +{ + return (ch == '\t' || ch == '\n' || ch == '\r'); +} + +template +bool IsHexDigit(const T ch) +{ + if (isdigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) { + return true; + } + return false; +} + +template +unsigned Hex2bin(const T ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } + if (ch >= 'A' && ch <= 'F') { + return 10 + (ch - 'A'); + } + if (ch >= 'a' && ch <= 'f') { + return 10 + (ch - 'a'); + } + return static_cast(-1); +} + +std::string DecodePercent(const char* input, size_t len) +{ + std::string temp; + if (len == 0) { + return temp; + } + temp.reserve(len); + const char* it = input; + const char* end = input + len; + while (it < end) { + const char ch = it[0]; + size_t left = end - it - 1; + if (ch != '%' || left < 2 || (ch == '%' && (!IsHexDigit(it[1]) || !IsHexDigit(it[2])))) { + temp += ch; + it++; + continue; + } else { + unsigned a = Hex2bin(it[1]); + unsigned b = Hex2bin(it[2]); + char c = static_cast(a * 16 + b); // 16:Convert hex + temp += c; + it += 3; + } + } + return temp; +} + +void DeleteC0OrSpace(std::string& str) +{ + if (str.empty()) { + return; + } + size_t i = 0; + size_t strlen = str.size(); + for (; i < strlen;) { + if (str[i] >= '\0' && str[i] <= ' ') { + i++; + } else { + break; + } + } + str = str.substr(i); + strlen = str.size(); + for (i = strlen - 1; i != 0; i--) { + if (str[i] >= '\0' && str[i] <= ' ') { + str.pop_back(); + } else { + break; + } + } +} + +void DeleteTabOrNewline(std::string& str1) +{ + for (auto item = str1.begin(); item != str1.end(); ) { + if (IsASCIITabOrNewline(*item)) { + item = str1.erase(item); + } else { + ++item; + } + } +} + +bool IsSpecial(std::string scheme) +{ + auto temp = g_head.count(scheme); + if (temp > 0) { + return true; + } + return false; +} + +bool AnalysisScheme(std::string& input, std::string& scheme, std::bitset<11>& flags) +{ + if (!isalpha(input[0])) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return false; + } else { + size_t strlen = input.size(); + for (size_t i = 0; i < strlen - 1; ++i) { + if (isalnum(input[i]) || input[i] == '+' || input[i] == '-' || input[i] == '.') { + if (isupper(input[i])) { + input[i] = tolower(input[i]); + } + } else { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return false; + } + } + scheme = input; + if (IsSpecial(scheme)) { + flags.set(1); // 1:Bit 1 Set to true,The protocol is the default protocol + } + return true; + } +} + +void AnalysisFragment(std::string& input, std::string& fragment, std::bitset<11>& flags) +{ + fragment = input; + flags.set(8); // 8:Bit 8 Set to true,The URL has fragment +} + +void AnalysisQuery(std::string& input, std::string& query, std::bitset<11>& flags) +{ + query = input; + flags.set(7); // 7:Bit 7 Set to true,The URL has query +} + +void AnalysisUsernameAndPasswd(std::string& input, std::string& username, std::string& password, + std::bitset<11>& flags) +{ + int pos = input.size() - 1; + for (; pos >= 0; pos--) { + if (input[pos] == '@') { + break; + } + } + std::string userAndPasswd = input.substr(0, pos); + input = input.substr(pos + 1); + if (userAndPasswd.empty()) { + return; + } + if (userAndPasswd.find('@') != std::string::npos) { + while (true) { + size_t i = 0; + if ((i = userAndPasswd.find('@')) != std::string::npos) { + userAndPasswd = userAndPasswd.replace(i, 1, "%40"); + } else { + break; + } + } + } + + if (userAndPasswd.find(':') != std::string::npos) { + size_t i = userAndPasswd.find(':'); + std::string user = userAndPasswd.substr(0, i); + std::string passwd = userAndPasswd.substr(i + 1); + if (!user.empty()) { + username = user; + flags.set(2); // 2:Bit 2 Set to true,The URL has username + } + if (!passwd.empty()) { + password = passwd; + flags.set(3); // 3:Bit 3 Set to true,The URL has password + } + } else { + username = userAndPasswd; + flags.set(2); // 2:Bit 2 Set to true,The URL has username + } +} + +void AnalysisPath(std::string& input, std::vector& path, std::bitset<11>& flags, bool isSpecial) +{ + std::vector temp; + size_t pos = 0; + while (((pos = input.find('/')) != std::string::npos) || + ((pos = input.find('\\')) != std::string::npos && isSpecial)) { + temp.push_back(input.substr(0, pos)); + input = input.substr(pos + 1); + } + temp.push_back(input); + for (size_t it = 0; it < temp.size(); ++it) { + auto result = find(g_doubleSegment.begin(), g_doubleSegment.end(), temp[it]); + if (result != g_doubleSegment.end()) { + if (path.empty()) { + if (it == temp.size() - 1) { + path.emplace_back(""); + flags.set(6); // 6:Bit 6 Set to true,The URL has pathname + } + continue; + } + path.pop_back(); + if (it == temp.size() - 1) { + path.emplace_back(""); + flags.set(6); // 6:Bit 6 Set to true,The URL has pathname + } + continue; + } + result = find(g_singlesegment.begin(), g_singlesegment.end(), temp[it]); + if (result != g_singlesegment.end() && it == temp.size() - 1) { + path.emplace_back(""); + flags.set(6); // 6:Bit 6 Set to true,The URL has pathname + continue; + } + if (result == g_singlesegment.end()) { + path.push_back(temp[it]); + flags.set(6); // 6:Bit 6 Set to true,The URL has pathname + } + } +} + +void AnalysisPort(std::string input, url_data& urlinfo, std::bitset<11>& flags) +{ + for (auto i : input) { + if (!isdigit(i)) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + } + int it = stoi(input); + if (it > MAXPORT) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + flags.set(5);// 5:Bit 5 Set to true,The URL Port is the specially + for (auto i : g_head) { + if (i.first == urlinfo.scheme && i.second == it) { + urlinfo.port = -1; + flags.set(5, 0); // 5:Bit 5 Set to false,The URL Port is the default + return; + } + } + urlinfo.port = it; +} + +void AnalysisOpaqueHost(std::string input, std::string& host, std::bitset<11>& flags) +{ + size_t strlen = input.size(); + for (size_t i = 0; i < strlen; ++i) { + char ch = input[i]; + auto result = find(g_specialcharacter.begin(), g_specialcharacter.end(), ch); + if (ch != '%' && (result != g_specialcharacter.end())) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + } + host = input; + flags.set(4); // 4:Bit 4 Set to true,The URL has hostname +} + +std::string IPv6HostCompress(std::vector& tempIPV6, int flag) +{ + std::string input; + if (flag == 1) { + size_t strlen = tempIPV6.size(); + for (size_t i = 0; i < strlen; ++i) { + if (tempIPV6[i][0] == '?' && tempIPV6[i].size() == 1) { + input += ":"; + } + else { + input += tempIPV6[i]; + if (i != tempIPV6.size() - 1) { + input += ":"; + } + } + } + return input; + } else { + int max = 0; + int count = 0; + size_t maxZeroIndex = 0; + size_t strlen = tempIPV6.size(); + for (size_t i = 0; i < strlen;) { + if (tempIPV6[i] == "0" && (i + 1 < tempIPV6.size() && tempIPV6[i + 1] == "0")) { + int index = i; + while (i < tempIPV6.size() && tempIPV6[i] == "0") { + i++; + count++; + } + max < count ? max = count, maxZeroIndex = index : 0; + } + else { + count = 0; + i++; + } + } + if (count == 8) { // 8:If IPv6 is all 0 + return "::"; + } else if (max == 0) { + strlen = tempIPV6.size(); + for (size_t i = 0; i < strlen; ++i) { + input += tempIPV6[i]; + if (i != strlen - 1) { + input += ":"; + } + } + return input; + } else { + if (maxZeroIndex == 0) { + input += "::"; + strlen = tempIPV6.size(); + for (size_t i = max; i < strlen; ++i) { + input += tempIPV6[i] + ":"; + } + input.pop_back(); + return input; + } else { + for (size_t i = 0; i < maxZeroIndex; ++i) { + input += tempIPV6[i]; + if (i != maxZeroIndex - 1) { + input += ":"; + } + } + input += "::"; + strlen = tempIPV6.size(); + for (size_t i = maxZeroIndex + max; i < strlen; ++i) { + input += tempIPV6[i]; + if (i != strlen - 1) { + input += ":"; + } + } + return input; + } + } + } +} + +void IPv6Host(std::string& input, std::string& host, std::bitset<11>& flags) +{ + if (input.size() == 0) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + std::string strInput = input; + std::stringstream ss; + std::string number_hex; + unsigned val = 0; + unsigned number_flag = 0; + std::vector temp; + std::vector temp_end; + std::vector IPV6; + size_t pos = 0; + int temp_prot[4] = { 0 }; + int n = 0; + int flag = 0; + if ((pos = strInput.find("::", 0)) != std::string::npos) { + flag = 1; + if (strInput.find("::", pos + 2) != std::string::npos) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + } else { + flag = 0; + } + while (((pos = strInput.find(':')) != std::string::npos)) { + temp.push_back(strInput.substr(0, pos)); + strInput = strInput.substr(pos + 1); + } + temp.push_back(strInput); + if (temp.size() > 8) { // 8:The incoming value does not meet the criteria + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + for (size_t i = 0; i < temp.size(); ++i) { + if (temp[i].empty()) { + IPV6.push_back("?"); + } else { + size_t strlen = temp[i].size(); + for (size_t j = 0; j < strlen; ++j) { + if (((temp[i].find('.')) != std::string::npos)) { + number_flag = i; + if (temp.size() == i || temp.size() > 7) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + break; + } else if (IsHexDigit(temp[i][j])) { + val = val * 0x10 + Hex2bin(temp[i][j]); + } + } + ss << std::hex << val; + ss >> number_hex; + IPV6.push_back(number_hex); + ss.clear(); + number_hex.clear(); + val = 0; + } + } + if (number_flag != 0) { + while (((pos = temp[number_flag].find('.')) != std::string::npos)) { + temp_end.push_back(temp[number_flag].substr(0, pos)); + temp[number_flag] = temp[number_flag].substr(pos + 1); + } + temp_end.push_back(temp[number_flag]); + if (temp_end.size() != 4) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } else { + size_t strlen = temp_end.size(); + for (size_t x = 0; x < strlen; ++x) { + val = stoi(temp_end[x]); + if (val > 255) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + temp_prot[n] = val; + n++; + val = 0; + } + } + ss << std::hex << temp_prot[0] * 0x100 + temp_prot[1]; + ss >> number_hex; + IPV6.push_back(number_hex); + ss.clear(); + number_hex.clear(); + ss << std::hex << temp_prot[2] * 0x100 + temp_prot[3]; + ss >> number_hex; + IPV6.push_back(number_hex); + ss.clear(); + number_hex.clear(); + IPV6.erase(IPV6.end() - 3); + } + strInput = IPv6HostCompress(IPV6, flag); + host = '[' + strInput + ']'; + flags.set(4); // 4:Bit 4 Set to true,The URL has host + flags.set(10);// 10:Bit 10 Set to true,The host is IPV6 +} + +int64_t AnalyseNum(std::string parts) +{ + enum NUMERATION + { + OCT = 8, // 8:Octal + DEC = 10, // 10:Decimal + HEX = 16 // 16:Hexadecimal + }; + unsigned num = 10; // 10:Decimal + std::string partsBeg = parts.substr(0, 2); // 2:Take two digits to determine whether it is hexadecimal + size_t partsLen = parts.length(); + if (partsLen >= 2 && (partsBeg == "0X" || partsBeg == "0x")) { + num = 16; + parts = parts.substr(2); // 2:delete '0x' + } else if (num == 10 && partsLen > 1 && parts.substr(0, 1) == "0") { // 0:delete '0' + num = 8; + parts = parts.substr(1); + } + for (size_t i = 0; i < parts.length(); i++) { + if (NUMERATION(num) == OCT) { + if (parts[i] < '0' || parts[i] > '7') { // 0~7:Octal + return -1; + } + } else if (NUMERATION(num) == DEC) { + if (parts[i] < '0' || parts[i] > '9') { // 0~9:Decimal + return -1; + } + } else if (NUMERATION(num) == HEX) { + if (!((parts[i] >= '0' && parts[i] <= '9') || // 0~9, a~f, A~F:Hexadecimal + (parts[i] >= 'A' && parts[i] <= 'F') || + (parts[i] >= 'a' && parts[i] <= 'f'))) { + return -1; + } + } + } + return strtoll(parts.c_str(), nullptr, num); +} + +bool OverHex(std::string input) +{ + size_t size = input.size(); + for (size_t i = 0; i < size; i++) + { + return !IsHexDigit(input[i]); + } + return false; +} + +bool NotAllNum(std::string input) { + + size_t size = input.size(); + for (size_t i = 0; i < size; i++) + { + if (!isdigit(input[i])) + { + return true; + } + } + return false; +} + +bool AnalyseIPv4(const char* instr, size_t len, std::string& host, std::bitset<11>& flags) +{ + int count = 0; + for (const char* ptr = instr; *ptr != '\0'; ptr++) { + if (*ptr == '.') { + if (++count > 3) { //3: The IPV4 address has only four segments + return false; + } + } + } + if (count != 3) { // 3:The IPV4 address has only four segments + return false; + } + + size_t pos = 0; + std::vector strVec; + std::string input = static_cast(instr); + while (((pos = input.find('.')) != std::string::npos)) { + strVec.push_back(input.substr(0, pos)); + input = input.substr(pos + 1); + } + strVec.push_back(input); + size_t size = strVec.size(); + for (size_t i = 0; i < size; i++) { + if (strVec[i].empty()) + { + return false; + } + std::string begStr = strVec[i].substr(0, 2); // Intercept the first two characters + if ((begStr == "0x" || begStr == "0X") && OverHex(strVec[i].substr(2))) + { + return false; + } else if ((begStr == "0x" || begStr == "0X") && !(OverHex(strVec[i].substr(2)))) + { + continue; + } + if (NotAllNum(strVec[i])) + { + return false; + } + } + for (size_t i = 0; i < size; i++) { + int64_t value = AnalyseNum(strVec[i].c_str()); + if ((value < 0) || (value > 255)) { // 255:Only handle numbers between 0 and 255 + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return false; + } else { + host += std::to_string(value); + if (i != size - 1) + { + host += "."; + } + } + } + flags.set(4); // 4:Bit 4 Set to true,The URL has hostname + return true; +} +void AnalysisHost(std::string& input, std::string& host, std::bitset<11>& flags, bool is_Specoal) +{ + if (input.empty()) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + if (input[0] == '[') { + if ((input[input.length() - 1]) == ']') { + size_t b = input.length(); + input = input.substr(1, b - 2); + IPv6Host(input, host, flags); + return; + } else { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + } + if (!is_Specoal) { + AnalysisOpaqueHost(input, host, flags); + return; + } + std::string decodeInput = DecodePercent(input.c_str(), input.length()); + size_t strlen = decodeInput.size(); + for (size_t pos = 0; pos < strlen; ++pos) { + char ch = decodeInput[pos]; + auto result = find(g_specialcharacter.begin(), g_specialcharacter.end(), ch); + if (result != g_specialcharacter.end()) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + } + bool ipv4 = AnalyseIPv4(decodeInput.c_str(), decodeInput.length(), host, flags); + if (ipv4) { + return; + } + host = decodeInput; + flags.set(4); // 4:Bit 4 Set to true,The URL has hostname +} +bool ISFileNohost(const std::string& input) +{ + if ((isalpha(input[0]) && (input[1] == ':' || input[1] == '|'))) { + return true; + } + return false; +} +void AnalysisFilePath(std::string& input, url_data& urlinfo, std::bitset<11>& flags) +{ + std::vector temp; + size_t pos = 0; + while (((pos = input.find('/')) != std::string::npos) || ((pos = input.find('\\')) != std::string::npos)) { + temp.push_back(input.substr(0, pos)); + input = input.substr(pos + 1); + } + temp.push_back(input); + + for (size_t i = 0; i < temp.size(); ++i) { + auto a = find(g_doubleSegment.begin(), g_doubleSegment.end(), temp[i]); + if (a != g_doubleSegment.end()) { + if ((urlinfo.path.size() == 1) && (isalpha(urlinfo.path[0][0]) + && ((urlinfo.path[0][1] == ':') || (urlinfo.path[0][1] == '|')))) { + if (urlinfo.path[0].size() == 2) { + urlinfo.path[0][1] = ':'; + } + } else if (!urlinfo.path.empty()) { + urlinfo.path.pop_back(); + } + if (i == temp.size() - 1) { + urlinfo.path.push_back(""); + } + continue; + } + a = find(g_singlesegment.begin(), g_singlesegment.end(), temp[i]); + if (a != g_singlesegment.end()) { + if (i == temp.size() - 1) { + urlinfo.path.push_back(""); + } + continue; + } + urlinfo.path.push_back(temp[i]); + flags.set(6); // 6:Bit 6 Set to true,The URL has pathname + } + std::string it = urlinfo.path[0]; + if (isalpha(it[0]) && (it[1] == ':' || it[1] == '|')) { + if (it.size() == 2) { + it[1] = ':'; + flags.set(4, 0); // 4:Bit 4 Set to false,The URL not have pathname + urlinfo.host.clear(); + } + } +} + +void AnalysisFile(std::string& input, url_data& urlinfo, std::bitset<11>& flags) +{ + bool is_Specoal = true; + if ((input[0] == '/' || input[0] == '\\') && (input[1] == '/' || input[1] == '\\')) { + std::string temp = input.substr(2); + size_t pos = 0; + if (((pos = temp.find('/')) != std::string::npos) || ((pos = temp.find('\\')) != std::string::npos)) { + if (pos == 0) { + temp = temp.substr(1); + AnalysisFilePath(temp, urlinfo, flags); + } else { + std::string strHost = temp.substr(0, pos); + std::string strPath = temp.substr(pos + 1); + + if (!ISFileNohost(strHost)) { + AnalysisHost(strHost, urlinfo.host, flags, is_Specoal); + if (flags.test(0)) { // 0:Bit 0 is true,The URL Parsing failed + return; + } + AnalysisFilePath(strPath, urlinfo, flags); + } else { + AnalysisFilePath(temp, urlinfo, flags); + } + } + } else { + if (!temp.empty()) { + AnalysisHost(temp, urlinfo.host, flags, is_Specoal); + if (flags.test(0)) { // 0:Bit 0 is true,The URL Parsing failed + return; + } + } + } + } else { + if (input[0] == '/' || input[0] == '\\') { + input = input.substr(1); + } + AnalysisFilePath(input, urlinfo, flags); + } +} + +void AnalysisFilescheme(std::string& input, url_data& urlinfo, std::bitset<11>& flags) +{ + std::string strPath = urlinfo.scheme + input; + urlinfo.scheme = "file:"; + flags.set(1); // 1:Bit 1 Set to true,The protocol is the default protocol + AnalysisFilePath(strPath, urlinfo, flags); +} + +void AnalysisHostAndPath(std::string& input, url_data& urlinfo, std::bitset<11>& flags) +{ + if (flags.test(1)) { // 1:Bit 1 is true,The protocol is the default protocol + size_t pos = 0; + bool is_Special = true; + for (; pos < input.size();) { + if (input[pos] == '/' || input[pos] == '\\') { + pos++; + } else { + break; + } + } + + input = input.substr(pos); + if (input.size() == 0) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } else { + if (input.find('/') != std::string::npos || input.find('\\') != std::string::npos) { + for (pos = 0; pos < input.size(); pos++) { + if (input[pos] == '/' || input[pos] == '\\') { + break; + } + } + std::string strHost = input.substr(0, pos); + std::string strPath = input.substr(pos + 1); + if (strHost.find('@') != std::string::npos) { + AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags); + } + if (strHost.empty()) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + if (strHost[strHost.size() - 1] != ']') { + if ((pos = strHost.find_last_of(':')) != std::string::npos) { + std::string port = strHost.substr(pos + 1); + strHost = strHost.substr(0, pos); + AnalysisPort(port, urlinfo, flags); + if (flags.test(0)) { // 0:Bit 0 is true,The URL Parsing failed + return; + } + } + } + AnalysisHost(strHost, urlinfo.host, flags, is_Special); + AnalysisPath(strPath, urlinfo.path, flags, is_Special); + } else { + std::string strHost = input; + if (strHost.find('@') != std::string::npos) { + AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags); + } + if (strHost.empty()) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + if (strHost[strHost.size() - 1] != ']') { + if ((pos = strHost.find_last_of(':')) != std::string::npos) { + std::string port = strHost.substr(pos + 1); + strHost = strHost.substr(0, pos); + AnalysisPort(port, urlinfo, flags); + if (flags.test(0)) { // 0:Bit 0 is true,The URL Parsing failed + return; + } + } + } + AnalysisHost(strHost, urlinfo.host, flags, is_Special); + } + } + } else { + if (urlinfo.scheme.size() == 2) { + AnalysisFilescheme(input, urlinfo, flags); + return; + } + if (input[0] == '/') { + if (input[1] == '/') { + std::string hostandpath = input.substr(2); + if (hostandpath.empty()) { + return; + } + size_t i = 0; + bool is_Special = false; + if (hostandpath.find('/') != std::string::npos) { + i = hostandpath.find('/'); + std::string strHost = hostandpath.substr(0, i); + std::string strPath = hostandpath.substr(i + 1); + if (strHost.find('@') != std::string::npos) { + AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags); + } + if (strHost.empty()) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + size_t pos = 0; + if (strHost[strHost.size() - 1] != ']') { + if ((pos = strHost.find_last_of(':')) != std::string::npos) { + std::string port = strHost.substr(pos + 1); + strHost = strHost.substr(0, pos); + AnalysisPort(port, urlinfo, flags); + if (flags.test(0)) { // 0:Bit 0 is true,The URL Parsing failed + return; + } + } + } + AnalysisHost(strHost, urlinfo.host, flags, is_Special); + AnalysisPath(strPath, urlinfo.path, flags, is_Special); + } else { + std::string strHost = hostandpath; + if (strHost.find('@') != std::string::npos) { + AnalysisUsernameAndPasswd(strHost, urlinfo.username, urlinfo.password, flags); + } + if (strHost.empty()) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + if (strHost[strHost.size() - 1] != ']') { + if (size_t pos = (strHost.find_last_of(':')) != std::string::npos) { + std::string port = strHost.substr(pos + 1); + strHost = strHost.substr(0, pos); + AnalysisPort(port, urlinfo, flags); + if (flags.test(0)) { // 0:Bit 0 is true,The URL Parsing failed + return; + } + } + } + AnalysisHost(strHost, urlinfo.host, flags, is_Special); + } + } else { + std::string strPath = input.substr(1); + bool is_Special = false; + AnalysisPath(strPath, urlinfo.path, flags, is_Special); + } + } else { + flags.set(9); // 6:Bit 6 Set to true,The URL Can not be base + if (urlinfo.path.empty()) { + urlinfo.path.emplace_back(""); + } + urlinfo.path[0] = input; + flags.set(6); // 6:Bit 6 Set to true,The URL has pathname + } + } +} + +void AnalysisInput(std::string& input, url_data& urlData, std::bitset<11>& flags, std::bitset<11>& baseflags) +{ + if (input.find('#') != std::string::npos) { + size_t i = input.find('#'); + std::string fragment = input.substr(i); + AnalysisFragment(fragment, urlData.fragment, flags); + input = input.substr(0, i); + } + if (input.find('?') != std::string::npos) { + size_t i = input.find('?'); + std::string query = input.substr(i); + AnalysisQuery(query, urlData.query, flags); + input = input.substr(0, i); + } + bool is_Special = (baseflags.test(1) ? true : false); // 1:Bit 1 is true,The URL Default for protocol + AnalysisPath(input, urlData.path, flags, is_Special); +} + +void BaseInfoToUrl(const url_data& baseInfo, const std::bitset<11>& baseflags, url_data& urlData, + std::bitset<11>& flags, bool inputIsEmpty) +{ + urlData.scheme = baseInfo.scheme; + flags.set(1, baseflags.test(1)); // 1:Base flag to the current URL + urlData.host = baseInfo.host; + flags.set(4); // 4:Bit 4 Set to true,The URL has hostname + urlData.username = baseInfo.username; + flags.set(2, baseflags.test(2)); // 2:Base flag to the current URL + urlData.password = baseInfo.password; + flags.set(3, baseflags.test(3)); // 3:Base flag to the current URL + urlData.port = baseInfo.port; + flags.set(5, baseflags.test(5)); // 5:Base flag to the current URL + if (inputIsEmpty) { + urlData.path = baseInfo.path; + flags.set(6, baseflags.test(6)); // 6:Base flag to the current URL + urlData.query = baseInfo.query; + flags.set(7, baseflags.test(7)); // 7:Base flag to the current URL + urlData.fragment = baseInfo.fragment; + flags.set(8, baseflags.test(8)); // 8:Base flag to the current URL + } + flags.set(9,baseflags.test(9)); // 9:Base flag to the current URL + flags.set(10,baseflags.test(10)); // 10:Base flag to the current U +} + +URL::URL(napi_env env, const std::string& input) +{ + env_ = env; + std::string str = input; + DeleteC0OrSpace(str); + DeleteTabOrNewline(str); + InitOnlyInput(str, urlData_, flags_); +} + +URL::URL(napi_env env, const std::string& input, const std::string& base) +{ + env_ = env; + url_data baseInfo; + std::bitset<11> baseflags; + std::string strBase = base; + std::string strInput = input; + if (strBase.empty()) { + baseflags.set(0); // 0:Bit 0 Set to true,The baseURL analysis failed + } + DeleteC0OrSpace(strBase); + DeleteTabOrNewline(strBase); + DeleteC0OrSpace(strInput); + DeleteTabOrNewline(strInput); + InitOnlyInput(strBase, baseInfo, baseflags); + if (baseflags.test(0)) { + flags_.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } else if (!baseflags.test(0)) { // 0:Bit 0 not is true,The baseURL analysis success + InitOnlyInput(strInput, urlData_, flags_); + if (!flags_.test(0)) { // 0:Bit 0 not is true,The URL analysis success + return; + } + if ((input[0] == '/' || input[0] == '\\') && (input[1] == '/' || input[1] == '\\')) { + std::string new_input = baseInfo.scheme + input; + flags_.set(0, 0); // 0:Bit 0 Set to false,The URL analysis success + InitOnlyInput(new_input, urlData_, flags_); + return; + } + if (baseflags.test(4)) { //4:Bit 4 is true,The URL has hostname + flags_.set(0, 0); + BaseInfoToUrl(baseInfo, baseflags, urlData_, flags_, input.empty()); + if (!input.empty()) { + if ((input[0] == '/') || (input[0] == '\\' && flags_.test(1))) { + strInput = input.substr(1); + } + AnalysisInput(strInput, urlData_, flags_, baseflags); + } + } else if (!baseflags.test(4)) { //4:Bit 4 is true,The URL has hostname + flags_.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + } +} + +URL::URL(napi_env env, const std::string& input, const URL& base) +{ + env_ = env; + std::string strInput = input; + url_data baseInfo = base.urlData_; + std::bitset<11> baseflags = base.flags_; + DeleteC0OrSpace(strInput); + DeleteTabOrNewline(strInput); + InitOnlyInput(strInput, urlData_, flags_); + if (!flags_.test(0)) { // 0:Bit 0 not is true,The URL analysis failed + return; + } + if ((input[0] == '/' || input[0] == '\\') && (input[1] == '/' || input[1] == '\\')) { + std::string new_input = baseInfo.scheme + input; + flags_.set(0, 0); // 0:Bit 0 Set to false + InitOnlyInput(new_input, urlData_, flags_); + return; + } + if (baseflags.test(4)) { // 4:Bit 4 is true,The baseURL has host + flags_.set(0, 0); // 0:Bit 0 set to true + BaseInfoToUrl(baseInfo, baseflags, urlData_, flags_, input.empty()); + if (!input.empty()) { + if ((input[0] == '/') || + (input[0] == '\\' && flags_.test(1))) { // 1:Bit 1 is true,The URL Default for protocol + strInput = input.substr(1); + } + AnalysisInput(strInput, urlData_, flags_, baseflags); + } + } else if (!baseflags.test(4)) { // 4:Bit 4 is false,The URL analysis failed + flags_.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } +} + +napi_value URL::GetHostname() const +{ + napi_value result; + const char* temp = nullptr; + if (flags_.test(4)) { // 4:Bit 4 is true,The URL has hostname + temp = urlData_.host.c_str(); + } else { + temp = ""; + } + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetSearch() const +{ + napi_value result; + const char* temp = nullptr; + if (flags_.test(7)) { // 7:Bit 7 is true,The URL has Search + if (urlData_.query.size() == 1) { + temp = ""; + } else { + temp = urlData_.query.c_str(); + } + } else { + temp = ""; + } + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetUsername() const +{ + napi_value result; + const char* temp = nullptr; + if (flags_.test(2)) { // 2:Bit 2 is true,The URL has username + temp = urlData_.username.c_str(); + } else + temp = ""; + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetPassword() const +{ + napi_value result; + const char* temp = nullptr; + if (flags_.test(3)) { // 3:Bit 3 is true,The URL has Password + temp = urlData_.password.c_str(); + } else { + temp = ""; + } + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetFragment() const +{ + napi_value result; + const char* temp = nullptr; + if (flags_.test(8)) { // 8:Bit 8 is true,The URL has Fragment + if (urlData_.fragment.size() == 1) { + temp = ""; + } else { + temp = urlData_.fragment.c_str(); + } + } else { + temp = ""; + } + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetScheme() const +{ + napi_value result; + const char* temp = nullptr; + if (!urlData_.scheme.empty()) { + temp = urlData_.scheme.c_str(); + } else { + temp = ""; + } + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetPath() const +{ + napi_value result; + std::string temp1 = "/"; + const char* temp = nullptr; + if (flags_.test(6)) { // 6:Bit 6 is true,The URL has pathname + for (size_t i = 0; i < urlData_.path.size(); i++) { + if (i < urlData_.path.size() - 1) { + temp1 += urlData_.path[i] + "/"; + } else { + temp1 += urlData_.path[i]; + } + temp = temp1.c_str(); + } + } else { + bool Special = IsSpecial(urlData_.scheme); + if(Special) { + temp = "/"; + } else { + temp = ""; + } + } + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetPort() const +{ + napi_value result; + const char* temp = nullptr; + if (flags_.test(5)) { // 5:Bit 5 is true,The URL has Port + temp = std::to_string(urlData_.port).c_str(); + } else { + temp = ""; + } + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetHost() const +{ + napi_value result; + const char* temp = nullptr; + std::string temp1 = urlData_.host; + if (flags_.test(5)) { // 5:Bit 5 is true,The URL has Port + temp1 += ":"; + temp1 += std::to_string(urlData_.port); + } + temp = temp1.c_str(); + size_t templen = strlen(temp); + NAPI_CALL(env_, napi_create_string_utf8(env_, temp, templen, &result)); + return result; +} + +napi_value URL::GetOnOrOff() const +{ + napi_value result; + if (flags_.test(0)) { // 1:Bit 1 is true,The URL Parsing succeeded + bool flag = false; + NAPI_CALL(env_, napi_get_boolean(env_, flag, &result)); + } else { + bool flag = true; + NAPI_CALL(env_, napi_get_boolean(env_, flag, &result)); + } + return result; +} + +napi_value URL::GetIsIpv6() const +{ + napi_value result; + if (flags_.test(10)) { // 10:Bit 10 is true,The URL is ipv6 + bool flag = true; + NAPI_CALL(env_, napi_get_boolean(env_, flag, &result)); + } else { + bool flag = false; + NAPI_CALL(env_, napi_get_boolean(env_, flag, &result)); + } + return result; +} + +void URL::SetHostname(const std::string& input) +{ + if (flags_.test(9)) { // 9:Bit 9 is true,The URL Can not be base + return; + } + std::string strHost = input; + for (size_t pos = 0; pos < strHost.size(); pos++) { + if ((strHost[pos] == ':') || (strHost[pos] == '?') || (strHost[pos] == '#') || + (strHost[pos] == '/') || (strHost[pos] == '\\')) { + strHost = strHost.substr(0, pos); + break; + } + } + if (strHost.size() == 0) { + return; + } + bool is_Special = IsSpecial(urlData_.scheme); + std::bitset<11> thisflags_; + std::string thisHostname = ""; + AnalysisHost(strHost, thisHostname, thisflags_, is_Special); + if (thisflags_.test(4)) { //4:Bit 4 is true,The URL has hostname + if ((urlData_.scheme == "file:") && (thisHostname == "localhost")) { + thisHostname = ""; + } + urlData_.host = thisHostname; + flags_.set(4); + } +} + +void URL::SetHref(const std::string& input) +{ + std::string str = input; + DeleteC0OrSpace(str); + DeleteTabOrNewline(str); + url_data thisNewUrl; + std::bitset<11> thisNewFlags; + InitOnlyInput(str, thisNewUrl, thisNewFlags); + if (!thisNewFlags.test(0)) { + urlData_ = thisNewUrl; + flags_ = thisNewFlags; + } +} + +void URL::SetPath(const std::string& input) +{ + std::string strPath = input; + if (flags_.test(9)) { + return; + } + if (strPath.empty()) { + return; + } + std::string oldstr = "%3A"; + std::string newstr = ":"; + ReplaceSpecialSymbols(strPath,oldstr,newstr); + bool is_Special = IsSpecial(urlData_.scheme); + if (urlData_.scheme == "file:") { + url_data thisFileDate; + std::bitset<11> thisFileFlag; + if ((strPath[0] == '/') || (strPath[0] == '\\' && flags_.test(1))) { + strPath = strPath.substr(1); + } + AnalysisFilePath(strPath, thisFileDate, thisFileFlag); + if (thisFileFlag.test(6)) { + urlData_.path = thisFileDate.path; + flags_.set(6); + } + } else { + std::vector thisPath_; + std::bitset<11> thisFlags_; + if ((strPath[0] == '/') || (strPath[0] == '\\' && flags_.test(1))) { + strPath = strPath.substr(1); + } + AnalysisPath(strPath, thisPath_, thisFlags_, is_Special); + if (thisFlags_.test(6)) { + urlData_.path = thisPath_; + flags_.set(6); + } + } +} + +void URL::SetHost(const std::string& input) +{ + if (flags_.test(9)) { + return; + } + if(input.empty()) { + return; + } + std::string strHost = input; + std::string port = ""; + size_t strlen = input.size(); + for (size_t pos = 0; pos < strlen; pos++) { + if ((input[pos] == ':') || (input[pos] == '?') || (input[pos] == '#') || + (input[pos] == '/') || (input[pos] == '\\')) { + strHost = input.substr(0, pos); + if (input[pos] == ':') { + pos++; + port = input.substr(pos); + } + break; + } + } + if (strHost.size() == 0) { + return; + } + bool is_Special = IsSpecial(urlData_.scheme); + std::bitset<11> hostnameflags; + std::string thisHostname = ""; + AnalysisHost(strHost, thisHostname, hostnameflags, is_Special); + if (hostnameflags.test(4)) { //4:Bit 4 is true,The URL has hostname + if ((urlData_.scheme == "file:") && (thisHostname == "localhost")) { + thisHostname = ""; + } + urlData_.host = thisHostname; + flags_.set(4); // 4:Bit 4 Set to true,The URL has hostname + } else { + return; + } + if (port.size() > 0) { + strlen = port.size(); + for (size_t pos = 0; pos < strlen; pos++) { + if ((port[pos] == '?') || (port[pos] == '#') || (port[pos] == '/') || (port[pos] == '\\')) { + port = port.substr(0, pos); + break; + } + } + if (port.size() > 0) { + std::bitset<11> thisflags_; + url_data thisport; + AnalysisPort(port, thisport, thisflags_); + if (thisflags_.test(5)) { // 5:Bit 5 is true,The URL has port + flags_.set(5); // 5:Bit 5 get to true,The URL has port + urlData_.port = thisport.port; + } + } + } +} + +void URL::SetPort(const std::string& input) +{ + std::string port = input; + size_t portlen = port.size(); + for (size_t pos = 0; pos < portlen; pos++) { + if ((port[pos] == '?') || (port[pos] == '#') || (port[pos] == '/') || (port[pos] == '\\')) { + port = port.substr(0, pos); + break; + } + } + if (port.size() > 0) { + std::bitset<11> thisflags_; + url_data thisport; + AnalysisPort(port, thisport, thisflags_); + if (thisflags_.test(5)) { // 5:Bit 5 is true,The URL has port + flags_.set(5); // 5:Bit 5 get to true,The URL has port + urlData_.port = thisport.port; + } + } +} + +void URL::SetSearch(const std::string& input) +{ + std::string temp; + if (input.size() == 0) { + urlData_.query = ""; + flags_.set(7, 0); // 7:Bit 7 set to false,The URL not have Search + } else { + if (input[0] != '?') { + temp = "?"; + temp += input; + } else { + temp = input; + } + std::string oldstr = "#"; + std::string newstr = "%23"; + ReplaceSpecialSymbols(temp,oldstr,newstr); + AnalysisQuery(temp, urlData_.query, flags_); + } +} + +void URL::SetFragment(const std::string& input) +{ + std::string temp; + if (input.size() == 0) { + urlData_.fragment = ""; + flags_.set(8, 0); // 8:Bit 8 set to false,The URL not have Fragment + } else { + if (input[0] != '#') { + temp = "#"; + temp += input; + } else { + temp = input; + } + AnalysisFragment(temp, urlData_.fragment, flags_); + } +} + +void URL::SetScheme(const std::string& input) +{ + std::string strInput = input; + bool is_Special = IsSpecial(urlData_.scheme); + bool inputIsSpecial = IsSpecial(input); + if ((is_Special != inputIsSpecial) || ((input == "file") && (flags_.test(2) || + flags_.test(3) || flags_.test(5)))) { //2 3 5:The URL has username password host + return; + } + std::string thisScheme = ""; + std::bitset<11> thisFlags; + if (AnalysisScheme(strInput, thisScheme, thisFlags)) { + if (thisFlags.test(1)) { // 1:Bit 1 is true,The inputURL Default for protocol + flags_.set(1); // 1:Bit 1 set to true,The URL Default for protocol + } + urlData_.scheme = thisScheme; + } +} + +void URL::SetUsername(const std::string& input) +{ + if (input.size() == 0) { + urlData_.username = ""; + flags_.set(2, 0); // 2:Bit 2 set to false,The URL not have username + } else { + if (!input.empty()) { + std::string usname = input; + std::string oldstr = "@"; + std::string newstr = "%40"; + ReplaceSpecialSymbols(usname,oldstr,newstr); + oldstr = "/"; + newstr = "%2F"; + ReplaceSpecialSymbols(usname,oldstr,newstr); + urlData_.username = usname; + flags_.set(2); // 2:Bit 2 set to true,The URL have username + } + } +} + +void URL::SetPassword(const std::string& input) +{ + if (input.size() == 0) { + urlData_.password = ""; + flags_.set(3, 0); // 3:Bit 3 set to false,The URL not have Password + } else { + if (!input.empty()) { + std::string passwd = input; + std::string oldstr = "@"; + std::string newstr = "%40"; + ReplaceSpecialSymbols(passwd,oldstr,newstr); + oldstr = "/"; + newstr = "%2F"; + ReplaceSpecialSymbols(passwd,oldstr,newstr); + urlData_.password = passwd; + flags_.set(3); // 3:Bit 3 set to true,The URL have passwd + } + } +} + +void URL::InitOnlyInput(std::string& input, url_data& urlData, std::bitset<11>& flags) +{ + if (input.empty()) { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } + if (input.find(':') != std::string::npos) { + size_t pos = input.find(':'); + pos++; + std::string scheme_ = input.substr(0, pos); + if (!AnalysisScheme(scheme_, urlData.scheme, flags)) { + return; + } + + if (input.find('#') != std::string::npos) { + size_t i = input.find('#'); + std::string fragment = input.substr(i); + AnalysisFragment(fragment, urlData.fragment, flags); + input = input.substr(0, i); + + } + if (input.find('?') != std::string::npos) { + size_t i = input.find('?'); + std::string query = input.substr(i); + AnalysisQuery(query, urlData.query, flags); + + input = input.substr(0, i); + } + + std::string str = input.substr(pos); + if (urlData.scheme == "file:") { + AnalysisFile(str, urlData, flags); + } else { + AnalysisHostAndPath(str, urlData, flags); + } + } else { + flags.set(0); // 0:Bit 0 Set to true,The URL analysis failed + return; + } +} + +URLSearchParams::URLSearchParams(napi_env env) : env(env) +{ +} +std::wstring strToWstr(const std::string& str) +{ + setlocale(LC_ALL, ""); + const char* addressofS = str.c_str(); + size_t len = str.size() + 1; + wchar_t* wch = new wchar_t[len]; + wmemset(wch, 0, len); + mbstowcs(wch, addressofS, len); + std::wstring wstr = wch; + delete[]wch; + setlocale(LC_ALL, ""); + return wstr; +} +std::string ReviseStr(std::string str, std::string* reviseChar) +{ + const size_t len_Str = str.length(); + if (len_Str == 0) { + return ""; + } + std::string output = ""; + int numOfAscii = 128; // 128:Number of ASCII characters + size_t i = 0; + for (; i < len_Str; i++) + { + int charaEncode = static_cast(str[i]); + if (charaEncode < 0 || charaEncode >= numOfAscii) { + int bytOfSpeChar = 3; // 3:Bytes of special characters in Linux + std::string subStr = str.substr(i, bytOfSpeChar); + i += 2; + const char* firstAddr = subStr.c_str(); + std::wstring wstr = strToWstr(firstAddr); + wchar_t wch = wstr[0]; + charaEncode = static_cast(wch); + } + if (0 <= charaEncode && charaEncode < numOfAscii) { + //2:Defines the escape range of ASCII characters + if ((0 < charaEncode && charaEncode < '*') || + ('*' < charaEncode && charaEncode < '-') || + (charaEncode == '/') || + ('9' < charaEncode && charaEncode < 'A') || + ('Z' < charaEncode && charaEncode < '_') || + (charaEncode == '`') || + (charaEncode > 'z')) { + output += reviseChar[charaEncode]; + } else { + output += str.substr(i, 1); + } + } else if (charaEncode <= 0x000007FF) { // Convert the Unicode code into two bytes + std::string output1 = reviseChar[0x000000C0 | + (charaEncode / 64)]; // Acquisition method of the first byte + std::string output2 = reviseChar[numOfAscii | + (charaEncode & 0x0000003F)]; // Acquisition method of the second byte + output += output1 + output2; + } else if ((charaEncode < 0x0000D800) || + (charaEncode >= 0x0000E000)) { // Convert the Unicode code into three bytes + std::string output1 = reviseChar[0x000000E0 | + (charaEncode / 4096)]; // Acquisition method of the first byte + std::string output2 = reviseChar[numOfAscii | + ((charaEncode / 64) & 0x0000003F)]; // method of the second byte + std::string output3 = reviseChar[numOfAscii | + (charaEncode & 0x0000003F)]; // Acquisition method of the third byte + output += output1 + output2 + output3; + } else { + // 1023:Convert codes greater than 0x000e000 into 4 bytes + const size_t charaEncode1 = static_cast(str[++i]) & 1023; + charaEncode = 65536 + (((charaEncode & 1023) << 10) | + charaEncode1); // Specific transcoding method + std::string output1 = reviseChar[0x000000F0 | + (charaEncode / 262144)]; // Acquisition method of the first byte + std::string output2 = reviseChar[numOfAscii | + ((charaEncode / 4096) & 0x0000003F)]; // Acquisition method of the second byte + std::string output3 = reviseChar[numOfAscii | + ((charaEncode / 64) & 0x0000003F)]; // Acquisition method of the third byte + std::string output4 = reviseChar[numOfAscii | + (charaEncode & 0x0000003F)]; // Acquisition method of the fourth byte + output += output1 + output2 + output3 + output4; + } + } + return output; +} + +napi_value URLSearchParams::ToString() +{ + std::string output = ""; + std::string reviseChar[256]; + for (size_t i = 0; i < 256; ++i) { + std::stringstream ioss; + std::string str1; + size_t j = i; + ioss << std::hex << j; + ioss >> str1; + transform(str1.begin(), str1.end(), str1.begin(), ::toupper); + if (i < 16) { // 16:Total number of 0-F + reviseChar[i] = '%' + ("0" + str1); + } else { + reviseChar[i] = '%' + str1; + } + } + reviseChar[0x20] = "+"; // 0x20:ASCII value of spaces + const size_t len_Str = searchParams.size(); + if (len_Str == 0) { + napi_value result = nullptr; + napi_create_string_utf8(env, output.c_str(), output.size(), &result); + return result; + } + std::string first_StrKey = ReviseStr(searchParams[0], reviseChar); + std::string first_StrValue = ReviseStr(searchParams[1], reviseChar); + output = first_StrKey + "=" + first_StrValue; + if (len_Str % 2 == 0) { + size_t couple = 2; + size_t i = 2; + for (; i < len_Str; i += couple) { + std::string strKey = ReviseStr(searchParams[i], reviseChar); + std::string strValue = ReviseStr(searchParams[i + 1], reviseChar); + output += +"&" + strKey + "=" + strValue; + } + } + napi_value result = nullptr; + napi_create_string_utf8(env, output.c_str(), output.size(), &result); + return result; +} +void URLSearchParams::HandleIllegalChar(std::wstring& inputStr, std::wstring::const_iterator it) +{ + std::wstring::iterator iter = inputStr.begin(); + advance(iter, std::distance(iter, it)); + while (iter != inputStr.end()) { + char16_t ch = *iter; + if (!((ch & 0xF800) == 0xD800)) { + ++iter; + continue; + } else if ((ch & 0x400) != 0 || iter == inputStr.end() - 1) { + *iter = 0xFFFD; + } else { + char16_t dh = *(iter + 1); + if ((dh & 0xFC00) == 0xDC00) { + ++iter; + } else { + *iter = 0xFFFD; + } + } + ++iter; + } +} +std::string URLSearchParams::ToUSVString(std::string inputStr) +{ + size_t strLen = strlen(inputStr.c_str()); + wchar_t* strPtr = nullptr; + int strSize = mbstowcs(strPtr, inputStr.c_str(), 0) + 1; + strPtr = new wchar_t[strSize]; + wmemset(strPtr, 0, strSize); + mbstowcs(strPtr, inputStr.c_str(), strLen); + + const char* expr = "(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])"; + size_t exprLen = strlen(expr); + wchar_t* exprPtr = nullptr; + int exprSize = mbstowcs(exprPtr, expr, 0) + 1; + exprPtr = new wchar_t[exprSize]; + wmemset(exprPtr, 0, exprSize); + mbstowcs(exprPtr, expr, exprLen); + + std::wregex wexpr(exprPtr); + delete[] exprPtr; + std::wsmatch result; + std::wstring winput = strPtr; + delete[] strPtr; + std::wstring::const_iterator iterStart = winput.begin(); + std::wstring::const_iterator iterEnd = winput.end(); + if (!regex_search(iterStart, iterEnd, result, wexpr)) { + return inputStr; + } + HandleIllegalChar(winput, result[0].first); + size_t inputLen = wcslen(winput.c_str()); + char* rePtr = nullptr; + int reSize = wcstombs(rePtr, winput.c_str(), 0) + 1; + rePtr = new char[reSize]; + memset(rePtr, 0, reSize); + wcstombs(rePtr, winput.c_str(), inputLen); + std::string reStr = rePtr; + delete[] rePtr; + return reStr; +} +napi_value URLSearchParams::Get(napi_value buffer) +{ + char* name = nullptr; + size_t nameSize = 0; + napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize); + name = new char[nameSize + 1]; + napi_get_value_string_utf8(env, buffer, name, nameSize + 1, &nameSize); + + std::string sname = ToUSVString(name); + delete[] name; + napi_value result = nullptr; + if(searchParams.size() == 0){ + return result; + } + size_t size = searchParams.size() - 1; + for (size_t i = 0; i < size; i += 2) { + if (searchParams[i] == sname) { + std::string str = searchParams[i + 1]; + napi_create_string_utf8(env, searchParams[i + 1].c_str(), searchParams[i + 1].length(), &result); + return result; + } + } + return result; +} +napi_value URLSearchParams::GetAll(napi_value buffer) +{ + char* name = nullptr; + size_t nameSize = 0; + napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize); + name = new char[nameSize + 1]; + napi_get_value_string_utf8(env, buffer, name, nameSize + 1, &nameSize); + + std::string sname = ToUSVString(name); + delete[] name; + napi_value result = nullptr; + napi_value napiStr = nullptr; + NAPI_CALL(env, napi_create_array(env, &result)); + size_t flag = 0; + if(searchParams.size() == 0){ + return result; + } + size_t size = searchParams.size() -1 ; + for (size_t i = 0; i < size; i += 2) { + if (searchParams[i] == sname) { + napi_create_string_utf8(env, searchParams[i + 1].c_str(), searchParams[i + 1].length(), &napiStr); + napi_status status = napi_set_element(env, result, flag, napiStr); + if (status != napi_ok) { + HILOG_INFO("set element error"); + } + flag++; + } + } + return result; +} +void URLSearchParams::Append(napi_value buffer, napi_value temp) +{ + char* name = nullptr; + size_t nameSize = 0; + napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize); + name = new char[nameSize + 1]; + napi_get_value_string_utf8(env, buffer, name, nameSize + 1, &nameSize); + + char* value = nullptr; + size_t valueSize = 0; + napi_get_value_string_utf8(env, temp, nullptr, 0, &valueSize); + value = new char[valueSize + 1]; + napi_get_value_string_utf8(env, temp, value, valueSize + 1, &valueSize); + searchParams.push_back(name); + searchParams.push_back(value); + delete[] name; + delete[] value; +} +void URLSearchParams::Delete(napi_value buffer) +{ + char* name = nullptr; + size_t nameSize = 0; + napi_get_value_string_utf8(env, buffer, nullptr, 0, &nameSize); + name = new char[nameSize + 1]; + napi_get_value_string_utf8(env, buffer, name, nameSize + 1, &nameSize); + std::string sname = ToUSVString(name); + delete[] name; + for (std::vector::iterator iter = searchParams.begin(); iter != searchParams.end();) { + if (*iter == sname) { + iter = searchParams.erase(iter, iter + 2); + } else { + iter += 2; + } + } +} +napi_value URLSearchParams::Entries() +{ + napi_value resend = nullptr; + napi_value firNapiStr = nullptr; + napi_value secNapiStr = nullptr; + napi_create_array(env, &resend); + if(searchParams.size() == 0) { + return resend; + } + size_t size = searchParams.size() - 1; + for (size_t i = 0; i < size; i += 2) { + napi_value result = nullptr; + napi_create_array(env, &result); + + napi_create_string_utf8(env, searchParams[i].c_str(), searchParams[i].length(), &firNapiStr); + napi_create_string_utf8(env, searchParams[i + 1].c_str(), searchParams[i + 1].length(), &secNapiStr); + napi_set_element(env, result, 0, firNapiStr); + napi_set_element(env, result, 1, secNapiStr); + napi_set_element(env, resend, i / 2, result); + } + return resend; +} +void URLSearchParams::ForEach(napi_value function, napi_value thisVar) +{ + if(searchParams.size() == 0){ + return ; + } + size_t size = searchParams.size() - 1; + for (size_t i = 0; i < size; i += 2) { + napi_value return_val = nullptr; + size_t argc = 3; + napi_value global = nullptr; + napi_get_global(env, &global); + + napi_value key = nullptr; + napi_create_string_utf8(env, searchParams[i].c_str(), strlen(searchParams[i].c_str()), &key); + napi_value value = nullptr; + napi_create_string_utf8(env, searchParams[i + 1].c_str(), strlen(searchParams[i + 1].c_str()), &value); + + napi_value argv[3] = {key, value, thisVar}; + napi_call_function(env, global, function, argc, argv, &return_val); + } +} +napi_value URLSearchParams::IsHas(napi_value name) +{ + char* buffer = nullptr; + size_t bufferSize = 0; + napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize); + buffer = new char[bufferSize + 1]; + napi_get_value_string_utf8(env, name, buffer, bufferSize + 1, &bufferSize); + bool flag = false; + napi_value result; + int lenStr = searchParams.size(); + int couple = 2; + for (size_t i = 0; i != lenStr; i += couple) { + std::string b = buffer; + if (searchParams[i] == b) { + flag = true; + napi_get_boolean(env, flag, &result); + return result; + } + } + delete []buffer; + napi_get_boolean(env, flag, &result); + return result; +} +void URLSearchParams::Set(napi_value name, napi_value value) +{ + char* buffer0 = nullptr; + size_t bufferSize0 = 0; + napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize0); + buffer0 = new char[bufferSize0 + 1]; + napi_get_value_string_utf8(env, name, buffer0, bufferSize0 + 1, &bufferSize0); + char* buffer1 = nullptr; + size_t bufferSize1 = 0; + napi_get_value_string_utf8(env, value, nullptr, 0, &bufferSize1); + buffer1 = new char[bufferSize1 + 1]; + napi_get_value_string_utf8(env, value, buffer1, bufferSize1 + 1, &bufferSize1); + bool flag = false; + std::string cpp_name = buffer0; + std::string cpp_value = buffer1; + delete[] buffer0; + delete[] buffer1; + for (std::vector::iterator it = searchParams.begin(); it < searchParams.end() - 1;) { + if (*it == cpp_name) { + if (!flag) { + *(it + 1) = cpp_value; + flag = true; + it += 2; + } else { + it = searchParams.erase(it, it + 2); + } + } else { + it += 2; + } + } + if (!flag) { + searchParams.push_back(cpp_name); + searchParams.push_back(cpp_value); + } +} +void SortMerge(std::vector out, unsigned int start, int mid, int end, + std::vector lBuffer, std::vector rBuffer) +{ + const unsigned int flag1 = mid - start; + const unsigned int flag2 = end - mid; + unsigned int flag3 = 0; + unsigned int flag4 = 0; + unsigned int flag5 = 0; + for (flag3 = 0; flag3 < flag1; flag3++) { + lBuffer[flag3] = out[start + flag3]; + } + for (flag4 = 0; flag4 < flag2; flag4++) { + rBuffer[flag4] = out[mid + flag4]; + } + flag3 = 0; + flag4 = 0; + flag5 = start; + while (flag3 < flag1 && flag4 < flag2) { + if (lBuffer[flag3] <= rBuffer[flag3]) { + out[flag5++] = lBuffer[flag3++]; + out[flag5++] = lBuffer[flag3++]; + } else { + out[flag5++] = rBuffer[flag4++]; + out[flag5++] = rBuffer[flag4++]; + } + } + while (flag3 < flag1) { + out[flag5++] = lBuffer[flag3++]; + } + while (flag4 < flag2) { + out[flag5++] = rBuffer[flag4++]; + } +} + +void URLSearchParams::Sort() +{ + unsigned int len = searchParams.size(); + if (2 < len && len < 100 && (len % 2 == 0)) { + unsigned int i = 0; + for (; i < len - 2; i += 2) { + unsigned int j = i + 2; + for (; j < len; j += 2) { + if (searchParams[i] > searchParams[j]) { + const std::string curKey = searchParams[i]; + const std::string curVal = searchParams[i + 1]; + searchParams[i] = searchParams[j]; + searchParams[i + 1] = searchParams[j + 1]; + searchParams[j] = curKey; + searchParams[j + 1] = curVal; + } + } + } + } if (len >= 100) { + const std::vector Buffer1; + const std::vector Buffer2; + for (unsigned int i = 2; i < searchParams.size(); i *= 2) { + for (unsigned int j = 0; j < searchParams.size() - 2; j += 2 * i) { + const unsigned int TempMid = j + i; + unsigned int TempEnd = TempMid + i; + TempEnd = TempEnd < len ? TempEnd : len; + if (TempMid > TempEnd) { + continue; + } + SortMerge(searchParams, j, TempMid, TempEnd, Buffer1, Buffer2); + } + } + } +} +napi_value URLSearchParams::IterByKeys() +{ + std::vector toKeys; + napi_value result = nullptr; + napi_value napiStr; + napi_create_array(env, &result); + int lenStr = searchParams.size(); + if (lenStr % 2 == 0) { + int couple = 2; + for (std::vector::iterator it = searchParams.begin(); it != searchParams.end(); it += couple) { + toKeys.push_back(*it); + } + int lenToKeys = toKeys.size(); + for (size_t i = 0; i < lenToKeys; i++) { + napi_create_string_utf8(env, toKeys[i].c_str(), toKeys[i].length(), &napiStr); + napi_set_element(env, result, i, napiStr); + } + } + return result; +} +napi_value URLSearchParams::IterByValues() +{ + std::vector toKeys; + napi_value result = nullptr; + napi_value napiStr; + napi_create_array(env, &result); + int lenStr = searchParams.size(); + if (lenStr % 2 == 0) { + int couple = 2; + for (std::vector::iterator it = searchParams.begin(); it != searchParams.end(); it += couple) { + toKeys.push_back(*(it + 1)); + } + int lenToKeys = toKeys.size(); + for (size_t i = 0; i < lenToKeys; i++) { + napi_create_string_utf8(env, toKeys[i].c_str(), toKeys[i].length(), &napiStr); + napi_set_element(env, result, i, napiStr); + } + } + return result; +} +void URLSearchParams::SetArray(const std::vector vec) +{ + searchParams = vec; +} +napi_value URLSearchParams::GetArray() +{ + napi_value arr = nullptr; + napi_create_array(env, &arr); + size_t length = searchParams.size(); + for (size_t i = 0; i < length; i++) { + napi_value result = nullptr; + napi_create_string_utf8(env, searchParams[i].c_str(), searchParams[i].size(), &result); + napi_set_element(env, arr, i, result); + } + return arr; +} \ No newline at end of file diff --git a/url/js_url.h b/url/js_url.h new file mode 100644 index 0000000000000000000000000000000000000000..d506c7e74c7dd0a659e6236bdad424446c9da4fd --- /dev/null +++ b/url/js_url.h @@ -0,0 +1,104 @@ + /* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +struct url_data { + int port = -1; + std::string scheme; + std::string username; + std::string password; + std::string host; + std::string query; + std::string fragment; + std::vector path; +}; + +class URL +{ +public: + URL(napi_env env, const std::string& input); + URL(napi_env env, const std::string& input, const std::string& base); + URL(napi_env env, const std::string& input, const URL& base); + + napi_value GetHostname() const; + void SetHostname(const std::string& input); + void SetUsername(const std::string& input); + void SetPassword(const std::string& input); + void SetScheme(const std::string& input); + void SetFragment(const std::string& input); + void SetSearch(const std::string& input); + void SetHost(const std::string& input); + void SetPort(const std::string& input); + void SetHref(const std::string& input); + void SetPath(const std::string& input); + + napi_value GetSearch() const; + napi_value GetUsername() const; + napi_value GetPassword() const; + napi_value GetFragment() const; + napi_value GetScheme() const; + napi_value GetPath() const; + napi_value GetPort() const; + napi_value GetOnOrOff() const; + napi_value GetIsIpv6() const; + napi_value GetHost() const; + + static void InitOnlyInput(std::string& input, url_data& urlData, std::bitset<11>& flags); + virtual ~URL() {} +private: + url_data urlData_; + std::bitset<11> flags_; + // bitset<11>:Similar to bool array, each bit status represents the real-time status of current URL parsing + napi_env env_ = nullptr; +}; + +class URLSearchParams { +public: + URLSearchParams(napi_env env); + virtual ~URLSearchParams() {} + napi_value IsHas(napi_value name); + napi_value Get(napi_value buffer); + napi_value GetAll(napi_value buffer); + void Append(napi_value buffer, napi_value temp); + void Delete(napi_value buffer); + void ForEach(napi_value function, napi_value thisVar); + napi_value Entries(); + void Set(napi_value name, napi_value value); + void Sort(); + napi_value ToString(); + napi_value IterByKeys(); + napi_value IterByValues(); + void SetArray(std::vector input); + napi_value GetArray(); + std::vector StringParmas (std::string Stringpar); +private: + std::string ToUSVString(std::string inputStr); + void HandleIllegalChar(std::wstring& inputStr, std::wstring::const_iterator it); + std::vector searchParams; + napi_env env; +}; \ No newline at end of file diff --git a/url/js_url.js b/url/js_url.js new file mode 100644 index 0000000000000000000000000000000000000000..18387e1fd9370cd6044d45e1220f4bd3d4342a99 --- /dev/null +++ b/url/js_url.js @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; +const urlUtil = requireInternal("url"); +let seachParamsArr = []; + +class URLSearchParams { + urlcalss; + constructor(input) { + let out = []; + out = parameterProcessing(input); + this.urlcalss = new urlUtil.URLSearchParams1(); + this.urlcalss.array = out; + } + append(params1, params2) { + this.urlcalss.append(params1, params2); + } + + set(setname, setvalues) { + this.urlcalss.set(setname, setvalues); + } + + sort() { + this.urlcalss.sort(); + } + + has(hasname) { + return this.urlcalss.has(hasname); + } + + toString() { + return this.urlcalss.toString(); + } + + keys() { + return this.urlcalss.keys(); + } + + values() { + return this.urlcalss.values(); + } + + getAll(getAllname) { + return this.urlcalss.getAll(getAllname); + } + + get(getname) { + return this.urlcalss.get(getname); + } + + entries() { + + return this.urlcalss.entries(); + } + + delete(deletename) { + this.urlcalss.delete(deletename); + } + + forEach(objfun) { + return this.urlcalss.forEach(objfun); + } + + [Symbol.iterator]() { + return this.urlcalss.entries(); + } + + updateParams(input) { + let out = []; + out = parameterProcessing(input); + this.urlcalss.array = out; + } +} + +function toHleString(arg) { + return arg.toString(); +} + +function parameterProcessing(input) { + if (input === null || typeof input === 'undefined') { + seachParamsArr = []; + return seachParamsArr; + } else if (typeof input === 'object' || typeof input === 'function') { + return initObjectSeachParams(input); + } else { + return initToStringSeachParams(input); + } +} + +function initObjectSeachParams(input) { + if (typeof input[Symbol.iterator] === 'function') { + return iteratorMethod(input); + } + return recordMethod(input); +} + +function recordMethod(input) { + const keys = Reflect.ownKeys(input); + seachParamsArr = []; + for (let i = 0; i <= keys.length; i++) { + const key = keys[i]; + const desc = Reflect.getOwnPropertyDescriptor(input, key); + if (desc !== undefined && desc.enumerable) { + const typedKey = toHleString(key); + const typedValue = toHleString(input[key]); + seachParamsArr.push(typedKey, typedValue); + } + } + return seachParamsArr; +} + +function iteratorMethod(input) { + let pairs = []; + seachParamsArr = []; + for (const pair of input) { + const convertedPair = []; + for (let element of pair) { + convertedPair.push(element); + } + pairs.push(convertedPair); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + console.log('key-value-is-worong'); + } + seachParamsArr.push(pair[0], pair[1]); + } + return seachParamsArr; +} + +function initToStringSeachParams(input) { + if (input[0] === '?') { + input = input.slice(1); + } + let strVal = decodeURI(input); + seachParamsArr = urlUtil.stringParmas(strVal); + return seachParamsArr; +} + +class URL { + href_; + search_; + origin_; + username_; + password_; + hostname_; + host_; + hash_; + protocol_; + pathname_; + port_; + searchParamsClass_; + c_info; + constructor() { + let nativeUrl; + let inputUrl; + let inputBase; + + if (arguments.length === 1) { + inputUrl = arguments[0]; + if (typeof inputUrl === 'string' && inputUrl.length > 0) { + nativeUrl = new urlUtil.Url(inputUrl); + } else { + console.log('Input parameter error'); + } + } + + if (arguments.length === 2) { + inputUrl = arguments[0]; + inputBase = arguments[1]; + if (typeof inputUrl === 'string') { + if (typeof inputBase === 'string') { + if (inputBase.length > 0) { + nativeUrl = new urlUtil.Url(inputUrl, inputBase); + } else { + console.log('Input parameter error'); + return; + } + } + if (typeof inputBase === 'object') { + let nativeBase = inputBase.get_info(); + nativeUrl = new urlUtil.Url(inputUrl, nativeBase); + } + } + } + this.c_info = nativeUrl; + if (nativeUrl.onOrOff) { + this.search_ = encodeURI(nativeUrl.search); + this.username_ = encodeURI(nativeUrl.username); + this.password_ = encodeURI(nativeUrl.password); + if (nativeUrl.GetIsIpv6) { + this.hostname_ = nativeUrl.hostname; + this.host_ = nativeUrl.host; + } else { + this.hostname_ = encodeURI(nativeUrl.hostname); + this.host_ = encodeURI(nativeUrl.host); + } + this.hash_ = encodeURI(nativeUrl.hash); + this.protocol_ = encodeURI(nativeUrl.protocol); + this.pathname_ = encodeURI(nativeUrl.pathname); + this.port_ = nativeUrl.port; + this.origin_ = nativeUrl.protocol + '//' + nativeUrl.host; + this.searchParamsClass_ = new URLSearchParams(this.search_); + this.set_href(); + } else { + console.log('constructor failed'); + } + } + get_info() { + return this.c_info; + } + set_href() { + let temp = this.protocol_; + if (this.hostname_ !== '') { + temp += '//'; + if (this.password_ !== '' || this.username_ !== '') { + if (this.username_ !== '') { + temp += this.username_; + } + if (this.password_ !== '') { + temp += ':'; + temp += this.password_; + } + temp += '@'; + } + temp += this.hostname_; + if (this.port_ !== '') { + temp += ':'; + temp += this.port_; + } + } else if (this.protocol_ === 'file:') { + temp += '//'; + } + temp += this.pathname_; + if (this.search_) { + temp += this.search_; + } + if (this.hash_) { + temp += this.hash_; + } + this.href_ = temp; + } +} + +Object.defineProperties(URL.prototype, { + + to_string: { + writable: true, + enumerable: true, + configurable: true, + value: function toString() { + return this.href_; + } + }, + origin: { + enumerable: true, + configurable: true, + get() { + let kOpaqueOrigin = 'null'; + switch (this.protocol_) { + case 'ftp:': + case 'gopher:': + case 'http:': + case 'https:': + case 'ws:': + case 'wss:': + return this.origin_; + } + return kOpaqueOrigin; + } + }, + protocol: { + enumerable: true, + configurable: true, + get() { + return this.protocol_; + }, + set(scheme) { + if (scheme.length === 0) { + return; + } + if (this.protocol_ === 'file:' + && (this.host_ === '' || this.host_ == null)) { + return; + } + this.c_info.protocol = scheme; + this.protocol_ = this.c_info.protocol; + this.set_href(); + } + }, + username: { + enumerable: true, + configurable: true, + get() { + return this.username_; + }, + set(input) { + if (this.host_ == null || this.host_ === '' || this.protocol_ === 'file:') { + return; + } + const usname_ = escape(input); + this.c_info.username = usname_; + this.username_ = this.c_info.username; + this.set_href(); + } + }, + password: { + enumerable: true, + configurable: true, + get() { + return this.password_; + }, + set(input) { + if (this.host_ == null || this.host_ === '' || this.protocol_ === 'file:') { + return; + } + const passwd_ = escape(input); + this.c_info.password = passwd_; + this.password_ = this.c_info.password; + this.set_href(); + } + }, + hash: { + enumerable: true, + configurable: true, + get() { + return this.hash_; + }, + set(fragment) { + const fragment_ = encodeURI(fragment); + this.c_info.hash = fragment_; + this.hash_ = this.c_info.hash; + this.set_href(); + } + }, + search: { + enumerable: true, + configurable: true, + get() { + return this.search_; + }, + set(query) { + const query_ = encodeURI(query); + this.c_info.search = query_; + this.search_ = this.c_info.search; + this.searchParamsClass_.updateParams(this.search_); + this.set_href(); + } + }, + hostname: { + enumerable: true, + configurable: true, + get() { + return this.hostname_; + }, + set(hostname) { + this.c_info.hostname = hostname; + if (this.c_info.GetIsIpv6) { + this.hostname_ = this.c_info.hostname; + } else { + this.hostname_ = encodeURI(this.c_info.hostname); + } + this.set_href(); + } + }, + host: { + enumerable: true, + configurable: true, + get() { + return this.host_; + }, + set(host_) { + this.c_info.host = host_; + if (this.c_info.GetIsIpv6) { + this.host_ = this.c_info.host; + this.hostname_ = this.c_info.hostname; + this.port_ = this.c_info.port; + } else { + this.host_ = encodeURI(this.c_info.host); + this.hostname_ = encodeURI(this.c_info.hostname); + this.port_ = this.c_info.port; + } + this.set_href(); + } + }, + port: { + enumerable: true, + configurable: true, + get() { + return this.port_; + }, + set(port) { + if (this.host_ === '' || this.protocol_ === 'file:' || port === '') { + return; + } + this.c_info.port = port; + this.port_ = this.c_info.port; + this.set_href(); + } + }, + href: { + enumerable: true, + configurable: true, + get() { + return this.href_; + }, + set(href_) { + this.c_info.href(href_); + if (this.c_info.onOrOff) { + this.search_ = encodeURI(this.c_info.search); + this.username_ = encodeURI(this.c_info.username); + this.password_ = encodeURI(this.c_info.password); + if (this.c_info.GetIsIpv6) { + this.hostname_ = this.c_info.hostname; + this.host_ = this.c_info.host; + } else { + this.hostname_ = encodeURI(this.c_info.hostname); + this.host_ = encodeURI(this.c_info.host); + } + this.hash_ = encodeURI(this.c_info.hash); + this.protocol_ = encodeURI(this.c_info.protocol); + this.pathname_ = encodeURI(this.c_info.pathname); + this.port_ = this.c_info.port; + this.origin_ = this.protocol_ + '//' + this.host_; + this.searchParamsClass_.updateParams(this.search_); + this.set_href(); + } + return this.href_; + } + }, + pathname: { + enumerable: true, + configurable: true, + get() { + return this.pathname_; + }, + set(path) { + const path_ = encodeURI(path); + this.c_info.pathname = path_; + this.pathname_ = this.c_info.pathname; + this.set_href(); + } + }, + toJSON: { + writable: true, + enumerable: true, + configurable: true, + value: function toJSON() { + return this.href_; + } + }, + searchParams: { + enumerable: true, + configurable: true, + get() { + return this.searchParamsClass_; + } + } +}); + +export default { + URLSearchParams: URLSearchParams, + URL: URL, +} diff --git a/url/native_module_url.cpp b/url/native_module_url.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4aaf0d124b78c505b8e401538215dc2cbf30978 --- /dev/null +++ b/url/native_module_url.cpp @@ -0,0 +1,852 @@ + /* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "js_url.h" +#include "utils/log.h" + +extern const char _binary_js_url_js_start[]; +extern const char _binary_js_url_js_end[]; + +static napi_value UrlConstructor(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + void* data = nullptr; + size_t argc = 0; + napi_value argv[2] = { 0 }; + URL* object = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, &data)); + if (argc == 1) { + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)); + napi_valuetype valuetype; + NAPI_CALL(env,napi_typeof(env, argv[0], &valuetype)); + if (valuetype == napi_string) { + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + object = new URL(env,type); + delete[] type; + } else { + HILOG_INFO("Parameter error"); + } + } else if (argc == 2) { + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)); + napi_valuetype valuetype1; + napi_valuetype valuetype2; + NAPI_CALL(env,napi_typeof(env, argv[0], &valuetype1)); + if (valuetype1 == napi_string) { + char* tem = nullptr; + size_t temlen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &temlen)); + tem = new char[temlen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], tem, temlen + 1, &temlen)); + std::string input_(tem); + delete[] tem; + NAPI_CALL(env,napi_typeof(env, argv[1], &valuetype2)); + if (valuetype2 == napi_string){ + char* type1 = nullptr; + size_t typelen1 = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[1], nullptr, 0, &typelen1)); + type1 = new char[typelen1 + 1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[1], type1, typelen1 + 1, &typelen1)); + std::string base_(type1); + delete[] type1; + object = new URL(env, input_, base_); + } else if (valuetype2 == napi_object) { + URL * temp = nullptr; + NAPI_CALL(env, napi_unwrap(env, argv[1], (void**)&temp)); + object = new URL(env,input_,*temp); + } else { + HILOG_INFO("secondParameter error"); + } + } else { + HILOG_INFO("firstParameter error"); + } + } + NAPI_CALL(env, napi_wrap(env, thisVar, object, + [](napi_env env, void* data, void* hint) { + auto object = (URL*)data; + if (object != nullptr) { + delete object; + } + }, nullptr, nullptr)); + return thisVar; +} + +static napi_value GetHostname(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetHostname(); + return retVal; +} + +static napi_value GetSearch(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetSearch(); + return retVal; +} + +static napi_value GetUsername(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetUsername(); + return retVal; +} + +static napi_value GetPassword(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetPassword(); + return retVal; +} + +static napi_value GetFragment(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetFragment(); + return retVal; +} + +static napi_value GetScheme(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetScheme(); + return retVal; +} + +static napi_value GetPort(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetPort(); + return retVal; +} + +static napi_value GetHost(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetHost(); + return retVal; +} + +static napi_value GetPath(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetPath(); + return retVal; +} + +static napi_value GetOnOrOff(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetOnOrOff(); + return retVal; +} + +static napi_value GetIsIpv6(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetIsIpv6(); + return retVal; +} + +static napi_value SetHref(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetHref(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetHostname(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetHostname(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetPort(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetPort(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetHost(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetHost(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetSearch(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetSearch(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetScheme(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetScheme(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetFragment(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetFragment(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetUsername(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetUsername(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetPath(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetPath(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SetPassword(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + char* type = nullptr; + size_t typelen = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen)); + type = new char[typelen+1]; + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen)); + std::string input(type); + if (type != nullptr) { + delete[] type; + type = nullptr; + } + URL* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetPassword(input); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value SeachParamsConstructor(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + void* data = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data)); + auto object = new URLSearchParams(env); + NAPI_CALL(env, napi_wrap( + env, thisVar, object, + [](napi_env env, void* data, void* hint) { + auto object = (URLSearchParams*)data; + if (object != nullptr) { + delete object; + } + }, + nullptr, nullptr)); + return thisVar; +} + +static napi_value SetArray(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1]; + size_t argc = 1; + uint32_t length = 0; + napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + napi_get_array_length(env, argv[0], &length); + std::vector vec; + char* cstr = nullptr; + size_t arraySize = 0; + napi_value napiStr = nullptr; + for (size_t i = 0; i < length; i++) { + napi_get_element(env, argv[0], i, &napiStr); + napi_get_value_string_utf8(env, napiStr, nullptr, 0, &arraySize); + cstr = new char[arraySize + 1]; + napi_get_value_string_utf8(env, napiStr, cstr, arraySize + 1, &arraySize); + vec.push_back(cstr); + delete []cstr; + cstr = nullptr; + } + URLSearchParams* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + murl->SetArray(vec); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +static napi_value GetArray(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + URLSearchParams* murl = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&murl)); + napi_value retVal = murl->GetArray(); + return retVal; +} + +static napi_value Get(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 1; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + + if(argc != 1) { + HILOG_INFO("One arg needs to be specified"); + return nullptr; + } + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + napi_value result = object->Get(args); + return result; +} + +static napi_value GetAll(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 1; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + + if(argc != 1) { + HILOG_INFO("One arg needs to be specified"); + return nullptr; + } + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + napi_value result = object->GetAll(args); + return result; +} + +static napi_value Append(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 2; + napi_value args[2] = { 0 }; + void* data = nullptr; + napi_get_cb_info(env, info, &argc, args, &thisVar, &data); + + if(argc != 2) { + HILOG_INFO("Two args needs to be specified"); + return nullptr; + } + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + object->Append(args[0], args[1]); + return nullptr; +} + +static napi_value Delete(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 1; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + + if(argc != 1) { + HILOG_INFO("One arg needs to be specified"); + return nullptr; + } + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + object->Delete(args); + return nullptr; +} + +static napi_value ForEach(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 1; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + object->ForEach(args, thisVar); + return nullptr; +} + +static napi_value Entries(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 0; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + napi_value result = object->Entries(); + return result; +} + +static napi_value IsHas(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 1; + napi_value args = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr)); + URLSearchParams* object = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&object)); + napi_value result = object->IsHas(args); + return result; +} + +static napi_value Set(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 2; + napi_value args[2] = { 0 }; + napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr); + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + object->Set(args[0], args[1]); + return nullptr; +} + +static napi_value Sort(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 0; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + object->Sort(); + return nullptr; +} + +static napi_value ToString(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 0; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + napi_value result = object->ToString(); + return result; +} + +static napi_value IterByKeys(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 0; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + napi_value result = object->IterByKeys(); + return result; +} + +static napi_value IterByValues(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = 0; + napi_value args = nullptr; + napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr); + URLSearchParams* object = nullptr; + napi_unwrap(env, thisVar, (void**)&object); + napi_value result = object->IterByValues(); + return result; +} + +std::vector stringParsing (std::string Stringpar) +{ + std::vector seachParasVec; + size_t strStartPos = 0; + size_t strLastPos = 0; + bool isHasSpace = false; + std::string buf = ""; + size_t i; + for(i = 0;i < Stringpar.length(); i++) { + char code = Stringpar[i]; + switch(code) { + case '&' : + { + if (strStartPos == i){ + strLastPos = i + 1; + strStartPos = i + 1; + break; + } + if (strLastPos < i) { + buf += Stringpar.substr(strLastPos, i - strLastPos); + } + seachParasVec.push_back(buf); + if (!isHasSpace) { + seachParasVec.push_back(""); + } + isHasSpace = false; + buf = ""; + strLastPos = i + 1; + strStartPos = i + 1; + break; + } + case '=' : + { + if (isHasSpace) { + break; + } + if (strLastPos < i) { + buf += Stringpar.substr(strLastPos, i- strLastPos); + } + seachParasVec.push_back(buf); + isHasSpace = true; + buf = ""; + strLastPos = i + 1; + break; + } + case '+' : + { + if (strLastPos < i) { + buf += Stringpar.substr(strLastPos, i - strLastPos); + } + buf += ""; + strLastPos = i + 1; + break; + } + default:break; + } + } + if (strStartPos == i) { + return seachParasVec; + } + if (strLastPos < i) { + buf += Stringpar.substr(strLastPos, i - strLastPos); + } + seachParasVec.push_back(buf); + if (!isHasSpace) { + seachParasVec.push_back(""); + } + return seachParasVec; +} + +static napi_value StringParmas(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + napi_value argv[1] = {0}; + size_t argc = 1; + napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + char* type = nullptr; + size_t typelen = 0; + napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen); + type = new char[typelen+1]; + napi_get_value_string_utf8(env, argv[0], type, typelen + 1, &typelen); + std::string input(type); + delete[] type; + std::vector seachParasmsString; + seachParasmsString = stringParsing(input); + napi_value arr = nullptr; + napi_create_array(env, &arr); + for (size_t i = 0; i < seachParasmsString.size(); i++) { + napi_value result = nullptr; + napi_create_string_utf8(env, seachParasmsString[i].c_str(), seachParasmsString[i].size(), &result); + napi_set_element(env, arr, i, result); + } + return arr; +} + +static napi_value SeachParamsInit(napi_env env, napi_value exports) +{ + const char* SeachParamsClassName = "URLSearchParams"; + napi_value SeachParamsInitClass = nullptr; + static napi_property_descriptor UrlDesc[] = + { + DECLARE_NAPI_FUNCTION("has", IsHas), + DECLARE_NAPI_FUNCTION("set", Set), + DECLARE_NAPI_FUNCTION("sort", Sort), + DECLARE_NAPI_FUNCTION("toString", ToString), + DECLARE_NAPI_FUNCTION("keys", IterByKeys), + DECLARE_NAPI_FUNCTION("values", IterByValues), + DECLARE_NAPI_FUNCTION("get", Get), + DECLARE_NAPI_FUNCTION("getAll", GetAll), + DECLARE_NAPI_FUNCTION("append", Append), + DECLARE_NAPI_FUNCTION("delete", Delete), + DECLARE_NAPI_FUNCTION("forEach", ForEach), + DECLARE_NAPI_FUNCTION("entries", Entries), + DECLARE_NAPI_GETTER_SETTER("array", GetArray, SetArray), + }; + NAPI_CALL(env, napi_define_class(env, SeachParamsClassName, strlen(SeachParamsClassName), SeachParamsConstructor, + nullptr, sizeof(UrlDesc) / sizeof(UrlDesc[0]), UrlDesc, &SeachParamsInitClass)); + static napi_property_descriptor desc[] = { + DECLARE_NAPI_PROPERTY("URLSearchParams1", SeachParamsInitClass) + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +}; + +static napi_value UrlInit(napi_env env, napi_value exports) + { + const char* UrlClassName = "Url"; + napi_value UrlClass = nullptr; + static napi_property_descriptor UrlDesc[] = + { + DECLARE_NAPI_GETTER_SETTER("hostname", GetHostname, SetHostname), + DECLARE_NAPI_FUNCTION("href", SetHref), + DECLARE_NAPI_GETTER_SETTER("search", GetSearch, SetSearch), + DECLARE_NAPI_GETTER_SETTER("username", GetUsername, SetUsername), + DECLARE_NAPI_GETTER_SETTER("password", GetPassword, SetPassword), + DECLARE_NAPI_GETTER_SETTER("host", GetHost, SetHost), + DECLARE_NAPI_GETTER_SETTER("hash", GetFragment, SetFragment), + DECLARE_NAPI_GETTER_SETTER("protocol", GetScheme, SetScheme), + DECLARE_NAPI_GETTER_SETTER("pathname", GetPath, SetPath), + DECLARE_NAPI_GETTER_SETTER("port", GetPort, SetPort), + DECLARE_NAPI_GETTER("onOrOff", GetOnOrOff), + DECLARE_NAPI_GETTER("GetIsIpv6", GetIsIpv6), + }; + NAPI_CALL(env, napi_define_class(env, UrlClassName, strlen(UrlClassName), UrlConstructor, + nullptr, sizeof(UrlDesc) / sizeof(UrlDesc[0]), UrlDesc, + &UrlClass)); + static napi_property_descriptor desc[] = { + DECLARE_NAPI_PROPERTY("Url", UrlClass) + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} + +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("stringParmas",StringParmas), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + SeachParamsInit(env, exports); + UrlInit(env, exports); + return exports; +} + +extern "C" +__attribute__((visibility("default"))) void NAPI_url_GetJSCode(const char** buf, int* bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_url_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_js_url_js_end - _binary_js_url_js_start; + } +} + +static napi_module UrlModule = +{ + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "url", + .nm_priv = ((void*)0), + .reserved = {0}, +}; +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&UrlModule); +} \ No newline at end of file