1 /*
2 * Copyright (c) 2022-2023 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 "file_uri_n_exporter.h"
16
17 #include <string>
18 #include <vector>
19
20 #include "file_uri_entity.h"
21 #include "file_utils.h"
22 #include "log.h"
23 #include "uri.h"
24 #include "sandbox_helper.h"
25
26 using namespace std;
27 namespace OHOS {
28 namespace AppFileService {
29 namespace ModuleFileUri {
30 using namespace FileManagement;
31 using namespace FileManagement::LibN;
32 const std::string MEDIA_AUTHORITY = "media";
Constructor(napi_env env,napi_callback_info info)33 napi_value FileUriNExporter::Constructor(napi_env env, napi_callback_info info)
34 {
35 NFuncArg funcArg(env, info);
36 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
37 LOGE("Number of arguments unmatched");
38 NError(EINVAL).ThrowErr(env);
39 return nullptr;
40 }
41 auto [succPath, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
42 if (!succPath) {
43 LOGE("Failed to get path");
44 NError(EINVAL).ThrowErr(env);
45 return nullptr;
46 }
47 auto fileuriEntity = CreateUniquePtr<FileUriEntity>(string(path.get()));
48 if (fileuriEntity == nullptr) {
49 LOGE("Failed to request heap memory.");
50 NError(ENOMEM).ThrowErr(env);
51 return nullptr;
52 }
53 if (!NClass::SetEntityFor<FileUriEntity>(env, funcArg.GetThisVar(), move(fileuriEntity))) {
54 LOGE("Failed to set file entity");
55 NError(EIO).ThrowErr(env);
56 return nullptr;
57 }
58 return funcArg.GetThisVar();
59 }
60
UriToString(napi_env env,napi_callback_info info)61 napi_value FileUriNExporter::UriToString(napi_env env, napi_callback_info info)
62 {
63 NFuncArg funcArg(env, info);
64 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
65 LOGE("Number of arguments unmatched");
66 NError(EINVAL).ThrowErr(env);
67 return nullptr;
68 }
69 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
70 if (!fileuriEntity) {
71 LOGE("Failed to get file entity");
72 NError(EINVAL).ThrowErr(env);
73 return nullptr;
74 }
75 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.ToString()).val_;
76 }
77
GetFileUriName(napi_env env,napi_callback_info info)78 napi_value FileUriNExporter::GetFileUriName(napi_env env, napi_callback_info info)
79 {
80 NFuncArg funcArg(env, info);
81 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
82 LOGE("Number of arguments unmatched");
83 NError(EINVAL).ThrowErr(env);
84 return nullptr;
85 }
86 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
87 if (!fileuriEntity) {
88 LOGE("Failed to get file entity");
89 NError(EINVAL).ThrowErr(env);
90 return nullptr;
91 }
92 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.GetName()).val_;
93 }
94
GetFullDirectoryUri(napi_env env,napi_callback_info info)95 napi_value FileUriNExporter::GetFullDirectoryUri(napi_env env, napi_callback_info info)
96 {
97 NFuncArg funcArg(env, info);
98 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
99 LOGE("Number of arguments unmatched");
100 NError(E_PARAMS).ThrowErr(env);
101 return nullptr;
102 }
103 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
104 if (!fileuriEntity) {
105 LOGE("Failed to get file entity");
106 NError(EINVAL).ThrowErr(env);
107 return nullptr;
108 }
109 string uri = fileuriEntity->fileUri_.GetFullDirectoryUri();
110 if (uri == "") {
111 LOGE("No such file or directory!");
112 NError(ENOENT).ThrowErr(env);
113 }
114 return NVal::CreateUTF8String(env, uri).val_;
115 }
116
IsRemoteUri(napi_env env,napi_callback_info info)117 napi_value FileUriNExporter::IsRemoteUri(napi_env env, napi_callback_info info)
118 {
119 NFuncArg funcArg(env, info);
120 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
121 LOGE("Number of arguments unmatched");
122 NError(E_PARAMS).ThrowErr(env);
123 return nullptr;
124 }
125 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
126 if (!fileuriEntity) {
127 LOGE("Failed to get file entity");
128 NError(EINVAL).ThrowErr(env);
129 return nullptr;
130 }
131 bool isRemoteUri = fileuriEntity->fileUri_.IsRemoteUri();
132 return NVal::CreateBool(env, isRemoteUri).val_;
133 }
134
GetFileUriPath(napi_env env,napi_callback_info info)135 napi_value FileUriNExporter::GetFileUriPath(napi_env env, napi_callback_info info)
136 {
137 NFuncArg funcArg(env, info);
138 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
139 LOGE("Number of arguments unmatched");
140 NError(EINVAL).ThrowErr(env);
141 return nullptr;
142 }
143 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
144 if (!fileuriEntity) {
145 LOGE("Failed to get file entity");
146 NError(EINVAL).ThrowErr(env);
147 return nullptr;
148 }
149 string bundleName = fileuriEntity->fileUri_.uri_.GetAuthority();
150 if (bundleName == MEDIA_AUTHORITY) {
151 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.GetPath()).val_;
152 }
153 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.GetRealPath()).val_;
154 }
155
Split(const std::string & path,Uri & uri)156 static std::string Split(const std::string &path, Uri &uri)
157 {
158 std::string normalizeUri = "";
159 if (!uri.GetScheme().empty()) {
160 normalizeUri += uri.GetScheme() + ":";
161 }
162 if (uri.GetPath().empty()) {
163 normalizeUri += uri.GetSchemeSpecificPart();
164 } else {
165 if (!uri.GetHost().empty()) {
166 normalizeUri += "//";
167 if (!uri.GetUserInfo().empty()) {
168 normalizeUri += uri.GetUserInfo() + "@";
169 }
170 normalizeUri += uri.GetHost();
171 if (uri.GetPort() != -1) {
172 normalizeUri += ":" + std::to_string(uri.GetPort());
173 }
174 } else if (!uri.GetAuthority().empty()) {
175 normalizeUri += "//" + uri.GetAuthority();
176 }
177 normalizeUri += path;
178 }
179 if (!uri.GetQuery().empty()) {
180 normalizeUri += "?" + uri.GetQuery();
181 }
182 if (!uri.GetFragment().empty()) {
183 normalizeUri += "#" + uri.GetFragment();
184 }
185 return normalizeUri;
186 }
187
NormalizeUri(Uri & uri)188 static std::string NormalizeUri(Uri &uri)
189 {
190 std::vector<std::string> temp;
191 size_t pathLen = uri.GetPath().size();
192 if (pathLen == 0) {
193 return uri.ToString();
194 }
195 size_t pos = 0;
196 size_t left = 0;
197 while ((pos = uri.GetPath().find('/', left)) != std::string::npos) {
198 temp.push_back(uri.GetPath().substr(left, pos - left));
199 left = pos + 1;
200 }
201 if (left != pathLen) {
202 temp.push_back(uri.GetPath().substr(left));
203 }
204 size_t tempLen = temp.size();
205 std::vector<std::string> normalizeTemp;
206 for (size_t i = 0; i < tempLen; ++i) {
207 if (!temp[i].empty() && !(temp[i] == ".") && !(temp[i] == "..")) {
208 normalizeTemp.push_back(temp[i]);
209 }
210 if (temp[i] == "..") {
211 if (!normalizeTemp.empty() && normalizeTemp.back() != "..") {
212 normalizeTemp.pop_back();
213 } else {
214 normalizeTemp.push_back(temp[i]);
215 }
216 }
217 }
218 std::string normalizePath = "";
219 tempLen = normalizeTemp.size();
220 if (tempLen == 0) {
221 normalizePath = "/";
222 } else {
223 for (size_t i = 0; i < tempLen; ++i) {
224 normalizePath += "/" + normalizeTemp[i];
225 }
226 }
227 return Split(normalizePath, uri);
228 }
229
Normalize(napi_env env,napi_callback_info info)230 napi_value FileUriNExporter::Normalize(napi_env env, napi_callback_info info)
231 {
232 NFuncArg funcArg(env, info);
233 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
234 LOGE("Number of arguments unmatched");
235 NError(EINVAL).ThrowErr(env);
236 return nullptr;
237 }
238 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
239 if (!fileuriEntity) {
240 LOGE("Failed to get file entity");
241 NError(EINVAL).ThrowErr(env);
242 return nullptr;
243 }
244
245 napi_value uriObj = NClass::InstantiateClass(env, FileUriNExporter::className,
246 {NVal::CreateUTF8String(env, NormalizeUri(fileuriEntity->fileUri_.uri_)).val_});
247 if (!uriObj) {
248 LOGE("Failed to construct FileUriNExporter.");
249 NError(E_UNKNOWN_ERROR).ThrowErr(env);
250 return nullptr;
251 }
252
253 return uriObj;
254 }
255
Equals(napi_env env,napi_callback_info info)256 napi_value FileUriNExporter::Equals(napi_env env, napi_callback_info info)
257 {
258 NFuncArg funcArg(env, info);
259 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
260 LOGE("Number of arguments unmatched");
261 NError(EINVAL).ThrowErr(env);
262 return nullptr;
263 }
264 auto thisEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
265 if (!thisEntity) {
266 LOGE("Failed to get file entity");
267 NError(EINVAL).ThrowErr(env);
268 return nullptr;
269 }
270
271 auto otherEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg[NARG_POS::FIRST]);
272 if (!otherEntity) {
273 LOGE("Failed to get file entity");
274 NError(EINVAL).ThrowErr(env);
275 return nullptr;
276 }
277
278 return NVal::CreateBool(env, thisEntity->fileUri_.uri_.Equals(otherEntity->fileUri_.uri_)).val_;
279 }
280
EqualsTo(napi_env env,napi_callback_info info)281 napi_value FileUriNExporter::EqualsTo(napi_env env, napi_callback_info info)
282 {
283 NFuncArg funcArg(env, info);
284 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
285 LOGE("Number of arguments unmatched");
286 NError(E_PARAMS).ThrowErr(env);
287 return nullptr;
288 }
289 auto thisEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
290 if (!thisEntity) {
291 LOGE("Failed to get file entity");
292 NError(E_PARAMS).ThrowErr(env);
293 return nullptr;
294 }
295
296 auto otherEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg[NARG_POS::FIRST]);
297 if (!otherEntity) {
298 LOGE("Failed to get file entity");
299 NError(E_PARAMS).ThrowErr(env);
300 return nullptr;
301 }
302 return NVal::CreateBool(env, thisEntity->fileUri_.uri_.Equals(otherEntity->fileUri_.uri_)).val_;
303 }
304
IsAbsolute(napi_env env,napi_callback_info info)305 napi_value FileUriNExporter::IsAbsolute(napi_env env, napi_callback_info info)
306 {
307 NFuncArg funcArg(env, info);
308 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
309 LOGE("Number of arguments unmatched");
310 NError(EINVAL).ThrowErr(env);
311 return nullptr;
312 }
313 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
314 if (!fileuriEntity) {
315 LOGE("Failed to get file entity");
316 NError(EINVAL).ThrowErr(env);
317 return nullptr;
318 }
319 return NVal::CreateBool(env, fileuriEntity->fileUri_.uri_.IsAbsolute()).val_;
320 }
321
GetScheme(napi_env env,napi_callback_info info)322 napi_value FileUriNExporter::GetScheme(napi_env env, napi_callback_info info)
323 {
324 NFuncArg funcArg(env, info);
325 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
326 LOGE("Number of arguments unmatched");
327 NError(EINVAL).ThrowErr(env);
328 return nullptr;
329 }
330 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
331 if (!fileuriEntity) {
332 LOGE("Failed to get file entity");
333 NError(EINVAL).ThrowErr(env);
334 return nullptr;
335 }
336
337 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetScheme()).val_;
338 }
339
GetAuthority(napi_env env,napi_callback_info info)340 napi_value FileUriNExporter::GetAuthority(napi_env env, napi_callback_info info)
341 {
342 NFuncArg funcArg(env, info);
343 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
344 LOGE("Number of arguments unmatched");
345 NError(EINVAL).ThrowErr(env);
346 return nullptr;
347 }
348 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
349 if (!fileuriEntity) {
350 LOGE("Failed to get file entity");
351 NError(EINVAL).ThrowErr(env);
352 return nullptr;
353 }
354
355 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetAuthority()).val_;
356 }
357
GetSsp(napi_env env,napi_callback_info info)358 napi_value FileUriNExporter::GetSsp(napi_env env, napi_callback_info info)
359 {
360 NFuncArg funcArg(env, info);
361 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
362 LOGE("Number of arguments unmatched");
363 NError(EINVAL).ThrowErr(env);
364 return nullptr;
365 }
366 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
367 if (!fileuriEntity) {
368 LOGE("Failed to get file entity");
369 NError(EINVAL).ThrowErr(env);
370 return nullptr;
371 }
372
373 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetSchemeSpecificPart()).val_;
374 }
375
GetUserInfo(napi_env env,napi_callback_info info)376 napi_value FileUriNExporter::GetUserInfo(napi_env env, napi_callback_info info)
377 {
378 NFuncArg funcArg(env, info);
379 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
380 LOGE("Number of arguments unmatched");
381 NError(EINVAL).ThrowErr(env);
382 return nullptr;
383 }
384 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
385 if (!fileuriEntity) {
386 LOGE("Failed to get file entity");
387 NError(EINVAL).ThrowErr(env);
388 return nullptr;
389 }
390
391 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetUserInfo()).val_;
392 }
393
GetHost(napi_env env,napi_callback_info info)394 napi_value FileUriNExporter::GetHost(napi_env env, napi_callback_info info)
395 {
396 NFuncArg funcArg(env, info);
397 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
398 LOGE("Number of arguments unmatched");
399 NError(EINVAL).ThrowErr(env);
400 return nullptr;
401 }
402 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
403 if (!fileuriEntity) {
404 LOGE("Failed to get file entity");
405 NError(EINVAL).ThrowErr(env);
406 return nullptr;
407 }
408
409 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetHost()).val_;
410 }
411
GetPort(napi_env env,napi_callback_info info)412 napi_value FileUriNExporter::GetPort(napi_env env, napi_callback_info info)
413 {
414 NFuncArg funcArg(env, info);
415 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
416 LOGE("Number of arguments unmatched");
417 NError(EINVAL).ThrowErr(env);
418 return nullptr;
419 }
420 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
421 if (!fileuriEntity) {
422 LOGE("Failed to get file entity");
423 NError(EINVAL).ThrowErr(env);
424 return nullptr;
425 }
426
427 return NVal::CreateUTF8String(env, to_string(fileuriEntity->fileUri_.uri_.GetPort())).val_;
428 }
429
GetQuery(napi_env env,napi_callback_info info)430 napi_value FileUriNExporter::GetQuery(napi_env env, napi_callback_info info)
431 {
432 NFuncArg funcArg(env, info);
433 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
434 LOGE("Number of arguments unmatched");
435 NError(EINVAL).ThrowErr(env);
436 return nullptr;
437 }
438 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
439 if (!fileuriEntity) {
440 LOGE("Failed to get file entity");
441 NError(EINVAL).ThrowErr(env);
442 return nullptr;
443 }
444
445 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetQuery()).val_;
446 }
447
GetFragment(napi_env env,napi_callback_info info)448 napi_value FileUriNExporter::GetFragment(napi_env env, napi_callback_info info)
449 {
450 NFuncArg funcArg(env, info);
451 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
452 LOGE("Number of arguments unmatched");
453 NError(EINVAL).ThrowErr(env);
454 return nullptr;
455 }
456 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
457 if (!fileuriEntity) {
458 LOGE("Failed to get file entity");
459 NError(EINVAL).ThrowErr(env);
460 return nullptr;
461 }
462
463 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetFragment()).val_;
464 }
465
Export()466 bool FileUriNExporter::Export()
467 {
468 vector<napi_property_descriptor> props = {
469 NVal::DeclareNapiFunction("toString", UriToString),
470 NVal::DeclareNapiGetter("name", GetFileUriName),
471 NVal::DeclareNapiGetter("path", GetFileUriPath),
472 NVal::DeclareNapiFunction("getFullDirectoryUri", GetFullDirectoryUri),
473 NVal::DeclareNapiFunction("isRemoteUri", IsRemoteUri),
474 NVal::DeclareNapiFunction("normalize", Normalize),
475 NVal::DeclareNapiFunction("equals", Equals),
476 NVal::DeclareNapiFunction("equalsTo", EqualsTo),
477 NVal::DeclareNapiFunction("checkIsAbsolute", IsAbsolute),
478 NVal::DeclareNapiGetter("scheme", GetScheme),
479 NVal::DeclareNapiGetter("authority", GetAuthority),
480 NVal::DeclareNapiGetter("ssp", GetSsp),
481 NVal::DeclareNapiGetter("userInfo", GetUserInfo),
482 NVal::DeclareNapiGetter("host", GetHost),
483 NVal::DeclareNapiGetter("port", GetPort),
484 NVal::DeclareNapiGetter("query", GetQuery),
485 NVal::DeclareNapiGetter("fragment", GetFragment),
486 };
487
488 auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
489 if (!succ) {
490 LOGE("Failed to define class");
491 NError(EIO).ThrowErr(exports_.env_);
492 return false;
493 }
494 succ = NClass::SaveClass(exports_.env_, className, classValue);
495 if (!succ) {
496 LOGE("Failed to save class");
497 NError(EIO).ThrowErr(exports_.env_);
498 return false;
499 }
500
501 return exports_.AddProp(className, classValue);
502 }
503
GetClassName()504 string FileUriNExporter::GetClassName()
505 {
506 return FileUriNExporter::className;
507 }
508
FileUriNExporter(napi_env env,napi_value exports)509 FileUriNExporter::FileUriNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
510
~FileUriNExporter()511 FileUriNExporter::~FileUriNExporter() {}
512 } // namespace ModuleFileUri
513 } // namespace AppFileService
514 } // namespace OHOS
515