1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *    http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "native_module_uri.h"
16
17#include "js_uri.h"
18#include "securec.h"
19#include "tools/log.h"
20#include "napi/native_api.h"
21#include "napi/native_node_api.h"
22
23extern const char _binary_js_uri_js_start[];
24extern const char _binary_js_uri_js_end[];
25extern const char _binary_uri_abc_start[];
26extern const char _binary_uri_abc_end[];
27
28namespace OHOS::Uri {
29    static napi_value UriConstructor(napi_env env, napi_callback_info info)
30    {
31        napi_value thisVar = nullptr;
32        void *data = nullptr;
33        size_t argc = 1;
34        napi_value argv[1] = { 0 };
35        Uri *object = nullptr;
36        NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
37        napi_valuetype valuetype;
38        NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
39        if (valuetype == napi_string) {
40            std::string type = "";
41            size_t typelen = 0;
42            NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typelen));
43            type.resize(typelen);
44            NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type.data(), typelen + 1, &typelen));
45            object = new (std::nothrow) Uri(type);
46            if (object == nullptr) {
47                HILOG_ERROR("UriConstructor:: object is nullptr");
48                return nullptr;
49            }
50        }
51        NAPI_CALL(env, napi_wrap(env, thisVar, object,
52            [](napi_env environment, void *data, void *hint) {
53            auto obj = reinterpret_cast<Uri*>(data);
54            if (obj != nullptr) {
55                delete obj;
56            }
57        }, nullptr, nullptr));
58        return thisVar;
59    }
60
61    static napi_value Normalize(napi_env env, napi_callback_info info)
62    {
63        napi_value thisVar = nullptr;
64        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
65        Uri *muri = nullptr;
66        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
67        std::string normalizeUri = muri->Normalize();
68        napi_value result = nullptr;
69        size_t tempLen = normalizeUri.size();
70        NAPI_CALL(env, napi_create_string_utf8(env, normalizeUri.c_str(), tempLen, &result));
71        return result;
72    }
73
74    static napi_value Equals(napi_env env, napi_callback_info info)
75    {
76        napi_value thisVar = nullptr;
77        napi_value result = nullptr;
78        size_t argc = 1;
79        napi_value argv[1] = { 0 };
80        NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
81
82        Uri *muri = nullptr;
83        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
84        Uri *other = nullptr;
85        NAPI_CALL(env, napi_unwrap(env, argv[0], reinterpret_cast<void**>(&other)));
86
87        bool flag = muri->Equals(*other);
88        NAPI_CALL(env, napi_get_boolean(env, flag, &result));
89        return result;
90    }
91
92    static napi_value IsAbsolute(napi_env env, napi_callback_info info)
93    {
94        napi_value thisVar = nullptr;
95        napi_value result = nullptr;
96        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
97        Uri *muri = nullptr;
98        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
99        bool flag = muri->IsAbsolute();
100        NAPI_CALL(env, napi_get_boolean(env, flag, &result));
101        return result;
102    }
103
104    static napi_value IsFailed(napi_env env, napi_callback_info info)
105    {
106        napi_value thisVar = nullptr;
107        napi_value result = nullptr;
108        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
109        Uri *muri = nullptr;
110        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
111        std::string temp = muri->IsFailed();
112        size_t templen = temp.size();
113        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
114        return result;
115    }
116
117    static napi_value UriToString(napi_env env, napi_callback_info info)
118    {
119        napi_value thisVar = nullptr;
120        napi_value result = nullptr;
121        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
122        Uri *muri = nullptr;
123        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
124        std::string temp = muri->ToString();
125        size_t templen = temp.size();
126        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
127        return result;
128    }
129
130    static napi_value IsRelative(napi_env env, napi_callback_info info)
131    {
132        napi_value thisVar = nullptr;
133        napi_value result = nullptr;
134        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
135        Uri *muri = nullptr;
136        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
137        bool flag = muri->IsRelative();
138        NAPI_CALL(env, napi_get_boolean(env, flag, &result));
139        return result;
140    }
141
142    static napi_value IsOpaque(napi_env env, napi_callback_info info)
143    {
144        napi_value thisVar = nullptr;
145        napi_value result = nullptr;
146        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
147        Uri *muri = nullptr;
148        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
149        bool flag = muri->IsOpaque();
150        NAPI_CALL(env, napi_get_boolean(env, flag, &result));
151        return result;
152    }
153
154    static napi_value IsHierarchical(napi_env env, napi_callback_info info)
155    {
156        napi_value thisVar = nullptr;
157        napi_value result = nullptr;
158        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
159        Uri *muri = nullptr;
160        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
161        bool flag = muri->IsHierarchical();
162        NAPI_CALL(env, napi_get_boolean(env, flag, &result));
163        return result;
164    }
165
166    static napi_value AddQueryValue(napi_env env, napi_callback_info info)
167    {
168        napi_value thisVar = nullptr;
169        napi_value result = nullptr;
170        size_t argc = 2;
171        napi_value argv[2] = { nullptr };
172        NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
173        Uri *muri = nullptr;
174        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
175        std::string key = "";
176        size_t keyLen = 0;
177        NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &keyLen));
178        key.resize(keyLen);
179        NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], key.data(), keyLen + 1, &keyLen));
180        std::string value = "";
181        size_t valueLen = 0;
182        NAPI_CALL(env, napi_get_value_string_utf8(env, argv[1], nullptr, 0, &valueLen));
183        value.resize(valueLen);
184        NAPI_CALL(env, napi_get_value_string_utf8(env, argv[1], value.data(), valueLen + 1, &valueLen));
185        std::string temp = muri->AddQueryValue(key, value);
186        if (temp.empty()) {
187            napi_get_null(env, &result);
188            return result;
189        }
190        size_t templen = temp.size();
191        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
192        return result;
193    }
194
195    static napi_value AddSegment(napi_env env, napi_callback_info info)
196    {
197        napi_value thisVar = nullptr;
198        napi_value result = nullptr;
199        size_t argc = 1;
200        napi_value argv[1] = { nullptr };
201        NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
202        Uri *muri = nullptr;
203        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
204        std::string segment = "";
205        size_t segmentLen = 0;
206        NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &segmentLen));
207        segment.resize(segmentLen);
208        NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], segment.data(), segmentLen + 1, &segmentLen));
209        std::string temp = muri->AddSegment(segment);
210        if (temp.empty()) {
211            napi_get_null(env, &result);
212            return result;
213        }
214        size_t tempLen = temp.size();
215        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), tempLen, &result));
216        return result;
217    }
218
219    static napi_value GetSegment(napi_env env, napi_callback_info info)
220    {
221        napi_value thisVar = nullptr;
222        napi_value result = nullptr;
223        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
224        Uri *muri = nullptr;
225        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
226        std::vector<std::string> temp = muri->GetSegment();
227        if (temp.empty()) {
228            napi_get_null(env, &result);
229            return result;
230        }
231        napi_value segment = nullptr;
232        napi_create_array(env, &result);
233        size_t size = temp.size();
234        for (size_t i = 0; i < size; i++) {
235            napi_create_string_utf8(env, temp[i].c_str(), temp[i].length(), &segment);
236            napi_set_element(env, result, i, segment);
237        }
238        return result;
239    }
240
241    static napi_value GetScheme(napi_env env, napi_callback_info info)
242    {
243        napi_value thisVar = nullptr;
244        napi_value result = nullptr;
245        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
246        Uri *muri = nullptr;
247        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
248        std::string temp = muri->GetScheme();
249        if (temp.empty()) {
250            napi_get_null(env, &result);
251            return result;
252        }
253        size_t templen = temp.size();
254        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
255        return result;
256    }
257
258    static napi_value GetAuthority(napi_env env, napi_callback_info info)
259    {
260        napi_value thisVar = nullptr;
261        napi_value result = nullptr;
262        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
263        Uri *muri = nullptr;
264        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
265        std::string temp = muri->GetAuthority();
266        if (temp.empty()) {
267            napi_get_null(env, &result);
268            return result;
269        }
270        size_t templen = temp.size();
271        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
272        return result;
273    }
274
275    static napi_value GetSsp(napi_env env, napi_callback_info info)
276    {
277        napi_value thisVar = nullptr;
278        napi_value result = nullptr;
279        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
280        Uri *muri = nullptr;
281        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
282        std::string temp = muri->GetSsp();
283        size_t templen = temp.size();
284        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
285        return result;
286    }
287
288    static napi_value GetUserinfo(napi_env env, napi_callback_info info)
289    {
290        napi_value thisVar = nullptr;
291        napi_value result = nullptr;
292        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
293        Uri *muri = nullptr;
294        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
295        std::string temp = muri->GetUserinfo();
296        if (temp.empty()) {
297            napi_get_null(env, &result);
298            return result;
299        }
300        size_t templen = temp.size();
301        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
302        return result;
303    }
304
305    static napi_value GetHost(napi_env env, napi_callback_info info)
306    {
307        napi_value thisVar = nullptr;
308        napi_value result = nullptr;
309        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
310        Uri *muri = nullptr;
311        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
312        std::string temp = muri->GetHost();
313        if (temp.empty()) {
314            napi_get_null(env, &result);
315            return result;
316        }
317        size_t templen = temp.size();
318        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
319        return result;
320    }
321
322    static napi_value GetPort(napi_env env, napi_callback_info info)
323    {
324        napi_value thisVar = nullptr;
325        napi_value result = nullptr;
326        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
327        Uri *muri = nullptr;
328        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
329        std::string temp = muri->GetPort();
330        size_t templen = temp.size();
331        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
332        return result;
333    }
334
335    static napi_value GetPath(napi_env env, napi_callback_info info)
336    {
337        napi_value thisVar = nullptr;
338        napi_value result = nullptr;
339        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
340        Uri *muri = nullptr;
341        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
342        std::string temp = muri->GetPath();
343        if (temp.empty()) {
344            napi_get_null(env, &result);
345            return result;
346        }
347        size_t templen = temp.size();
348        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
349        return result;
350    }
351
352    static napi_value GetQuery(napi_env env, napi_callback_info info)
353    {
354        napi_value thisVar = nullptr;
355        napi_value result = nullptr;
356        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
357        Uri *muri = nullptr;
358        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
359        std::string temp = muri->GetQuery();
360        if (temp.empty()) {
361            napi_get_null(env, &result);
362            return result;
363        }
364        size_t templen = temp.size();
365        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
366        return result;
367    }
368
369    static napi_value GetFragment(napi_env env, napi_callback_info info)
370    {
371        napi_value thisVar = nullptr;
372        napi_value result = nullptr;
373        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
374        Uri *muri = nullptr;
375        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
376        std::string temp = muri->GetFragment();
377        if (temp.empty()) {
378            napi_get_null(env, &result);
379            return result;
380        }
381        size_t templen = temp.size();
382        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result));
383        return result;
384    }
385
386    static napi_value ClearQuery(napi_env env, napi_callback_info info)
387    {
388        napi_value thisVar = nullptr;
389        napi_value result = nullptr;
390        NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
391        Uri *muri = nullptr;
392        NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&muri)));
393        std::string temp = muri->ClearQuery();
394        if (temp.empty()) {
395            napi_get_null(env, &result);
396            return result;
397        }
398        size_t tempLen = temp.size();
399        NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), tempLen, &result));
400        return result;
401    }
402
403    napi_value UriInit(napi_env env, napi_value exports)
404    {
405        const char *uriClassName = "uri";
406        napi_value uriClass = nullptr;
407        napi_property_descriptor uriDesc[] = {
408            DECLARE_NAPI_FUNCTION("normalize", Normalize),
409            DECLARE_NAPI_FUNCTION("equals", Equals),
410            DECLARE_NAPI_FUNCTION("checkIsAbsolute", IsAbsolute),
411            DECLARE_NAPI_FUNCTION("toString", UriToString),
412            DECLARE_NAPI_FUNCTION("checkIsRelative", IsRelative),
413            DECLARE_NAPI_FUNCTION("checkIsOpaque", IsOpaque),
414            DECLARE_NAPI_FUNCTION("checkIsHierarchical", IsHierarchical),
415            DECLARE_NAPI_FUNCTION("addQueryValue", AddQueryValue),
416            DECLARE_NAPI_FUNCTION("getSegment", GetSegment),
417            DECLARE_NAPI_FUNCTION("addSegment", AddSegment),
418            DECLARE_NAPI_FUNCTION("clearQuery", ClearQuery),
419            DECLARE_NAPI_GETTER("scheme", GetScheme),
420            DECLARE_NAPI_GETTER("authority", GetAuthority),
421            DECLARE_NAPI_GETTER("ssp", GetSsp),
422            DECLARE_NAPI_GETTER("userInfo", GetUserinfo),
423            DECLARE_NAPI_GETTER("host", GetHost),
424            DECLARE_NAPI_GETTER("port", GetPort),
425            DECLARE_NAPI_GETTER("path", GetPath),
426            DECLARE_NAPI_GETTER("query", GetQuery),
427            DECLARE_NAPI_GETTER("fragment", GetFragment),
428            DECLARE_NAPI_GETTER("isFailed", IsFailed),
429        };
430        NAPI_CALL(env, napi_define_class(env, uriClassName, strlen(uriClassName), UriConstructor,
431                                         nullptr, sizeof(uriDesc) / sizeof(uriDesc[0]), uriDesc, &uriClass));
432        napi_property_descriptor desc[] = {
433            DECLARE_NAPI_PROPERTY("Uri", uriClass)
434        };
435        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
436        return exports;
437    }
438
439    extern "C"
440    __attribute__((visibility("default"))) void NAPI_uri_GetJSCode(const char **buf, int *bufLen)
441    {
442        if (buf != nullptr) {
443            *buf = _binary_js_uri_js_start;
444        }
445        if (bufLen != nullptr) {
446            *bufLen = _binary_js_uri_js_end - _binary_js_uri_js_start;
447        }
448    }
449    extern "C"
450    __attribute__((visibility("default"))) void NAPI_uri_GetABCCode(const char** buf, int* buflen)
451    {
452        if (buf != nullptr) {
453            *buf = _binary_uri_abc_start;
454        }
455        if (buflen != nullptr) {
456            *buflen = _binary_uri_abc_end - _binary_uri_abc_start;
457        }
458    }
459
460    static napi_module_with_js UriModule = {
461        .nm_version = 1,
462        .nm_flags = 0,
463        .nm_filename = nullptr,
464        .nm_register_func = UriInit,
465        .nm_modname = "uri",
466        .nm_priv = reinterpret_cast<void*>(0),
467        .nm_get_abc_code = NAPI_uri_GetABCCode,
468        .nm_get_js_code = NAPI_uri_GetJSCode,
469    };
470    extern "C" __attribute__((constructor)) void UriRegisterModule()
471    {
472        napi_module_with_js_register(&UriModule);
473    }
474} // namespace OHOS::Uri
475