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