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 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.GetRealPath()).val_;
150 }
151
Split(const std::string & path,Uri & uri)152 static std::string Split(const std::string &path, Uri &uri)
153 {
154 std::string normalizeUri = "";
155 if (!uri.GetScheme().empty()) {
156 normalizeUri += uri.GetScheme() + ":";
157 }
158 if (uri.GetPath().empty()) {
159 normalizeUri += uri.GetSchemeSpecificPart();
160 } else {
161 if (!uri.GetHost().empty()) {
162 normalizeUri += "//";
163 if (!uri.GetUserInfo().empty()) {
164 normalizeUri += uri.GetUserInfo() + "@";
165 }
166 normalizeUri += uri.GetHost();
167 if (uri.GetPort() != -1) {
168 normalizeUri += ":" + std::to_string(uri.GetPort());
169 }
170 } else if (!uri.GetAuthority().empty()) {
171 normalizeUri += "//" + uri.GetAuthority();
172 }
173 normalizeUri += path;
174 }
175 if (!uri.GetQuery().empty()) {
176 normalizeUri += "?" + uri.GetQuery();
177 }
178 if (!uri.GetFragment().empty()) {
179 normalizeUri += "#" + uri.GetFragment();
180 }
181 return normalizeUri;
182 }
183
NormalizeUri(Uri & uri)184 static std::string NormalizeUri(Uri &uri)
185 {
186 std::vector<std::string> temp;
187 size_t pathLen = uri.GetPath().size();
188 if (pathLen == 0) {
189 return uri.ToString();
190 }
191 size_t pos = 0;
192 size_t left = 0;
193 while ((pos = uri.GetPath().find('/', left)) != std::string::npos) {
194 temp.emplace_back(uri.GetPath().substr(left, pos - left));
195 left = pos + 1;
196 }
197 if (left != pathLen) {
198 temp.emplace_back(uri.GetPath().substr(left));
199 }
200 size_t tempLen = temp.size();
201 std::vector<std::string> normalizeTemp;
202 for (size_t i = 0; i < tempLen; ++i) {
203 if (!temp[i].empty() && !(temp[i] == ".") && !(temp[i] == "..")) {
204 normalizeTemp.emplace_back(temp[i]);
205 }
206 if (temp[i] == "..") {
207 if (!normalizeTemp.empty() && normalizeTemp.back() != "..") {
208 normalizeTemp.pop_back();
209 } else {
210 normalizeTemp.emplace_back(temp[i]);
211 }
212 }
213 }
214 std::string normalizePath = "";
215 tempLen = normalizeTemp.size();
216 if (tempLen == 0) {
217 normalizePath = "/";
218 } else {
219 for (size_t i = 0; i < tempLen; ++i) {
220 normalizePath += "/" + normalizeTemp[i];
221 }
222 }
223 return Split(normalizePath, uri);
224 }
225
Normalize(napi_env env,napi_callback_info info)226 napi_value FileUriNExporter::Normalize(napi_env env, napi_callback_info info)
227 {
228 NFuncArg funcArg(env, info);
229 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
230 LOGE("Number of arguments unmatched");
231 NError(EINVAL).ThrowErr(env);
232 return nullptr;
233 }
234 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
235 if (!fileuriEntity) {
236 LOGE("Failed to get file entity");
237 NError(EINVAL).ThrowErr(env);
238 return nullptr;
239 }
240
241 napi_value uriObj = NClass::InstantiateClass(env, FileUriNExporter::className,
242 {NVal::CreateUTF8String(env, NormalizeUri(fileuriEntity->fileUri_.uri_)).val_});
243 if (!uriObj) {
244 LOGE("Failed to construct FileUriNExporter.");
245 NError(E_UNKNOWN_ERROR).ThrowErr(env);
246 return nullptr;
247 }
248
249 return uriObj;
250 }
251
Equals(napi_env env,napi_callback_info info)252 napi_value FileUriNExporter::Equals(napi_env env, napi_callback_info info)
253 {
254 NFuncArg funcArg(env, info);
255 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
256 LOGE("Number of arguments unmatched");
257 NError(EINVAL).ThrowErr(env);
258 return nullptr;
259 }
260 auto thisEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
261 if (!thisEntity) {
262 LOGE("Failed to get file entity");
263 NError(EINVAL).ThrowErr(env);
264 return nullptr;
265 }
266
267 auto otherEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg[NARG_POS::FIRST]);
268 if (!otherEntity) {
269 LOGE("Failed to get file entity");
270 NError(EINVAL).ThrowErr(env);
271 return nullptr;
272 }
273
274 return NVal::CreateBool(env, thisEntity->fileUri_.uri_.Equals(otherEntity->fileUri_.uri_)).val_;
275 }
276
EqualsTo(napi_env env,napi_callback_info info)277 napi_value FileUriNExporter::EqualsTo(napi_env env, napi_callback_info info)
278 {
279 NFuncArg funcArg(env, info);
280 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
281 LOGE("Number of arguments unmatched");
282 NError(E_PARAMS).ThrowErr(env);
283 return nullptr;
284 }
285 auto thisEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
286 if (!thisEntity) {
287 LOGE("Failed to get file entity");
288 NError(E_PARAMS).ThrowErr(env);
289 return nullptr;
290 }
291
292 auto otherEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg[NARG_POS::FIRST]);
293 if (!otherEntity) {
294 LOGE("Failed to get file entity");
295 NError(E_PARAMS).ThrowErr(env);
296 return nullptr;
297 }
298 return NVal::CreateBool(env, thisEntity->fileUri_.uri_.Equals(otherEntity->fileUri_.uri_)).val_;
299 }
300
IsAbsolute(napi_env env,napi_callback_info info)301 napi_value FileUriNExporter::IsAbsolute(napi_env env, napi_callback_info info)
302 {
303 NFuncArg funcArg(env, info);
304 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
305 LOGE("Number of arguments unmatched");
306 NError(EINVAL).ThrowErr(env);
307 return nullptr;
308 }
309 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
310 if (!fileuriEntity) {
311 LOGE("Failed to get file entity");
312 NError(EINVAL).ThrowErr(env);
313 return nullptr;
314 }
315 return NVal::CreateBool(env, fileuriEntity->fileUri_.uri_.IsAbsolute()).val_;
316 }
317
GetScheme(napi_env env,napi_callback_info info)318 napi_value FileUriNExporter::GetScheme(napi_env env, napi_callback_info info)
319 {
320 NFuncArg funcArg(env, info);
321 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
322 LOGE("Number of arguments unmatched");
323 NError(EINVAL).ThrowErr(env);
324 return nullptr;
325 }
326 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
327 if (!fileuriEntity) {
328 LOGE("Failed to get file entity");
329 NError(EINVAL).ThrowErr(env);
330 return nullptr;
331 }
332
333 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetScheme()).val_;
334 }
335
GetAuthority(napi_env env,napi_callback_info info)336 napi_value FileUriNExporter::GetAuthority(napi_env env, napi_callback_info info)
337 {
338 NFuncArg funcArg(env, info);
339 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
340 LOGE("Number of arguments unmatched");
341 NError(EINVAL).ThrowErr(env);
342 return nullptr;
343 }
344 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
345 if (!fileuriEntity) {
346 LOGE("Failed to get file entity");
347 NError(EINVAL).ThrowErr(env);
348 return nullptr;
349 }
350
351 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetAuthority()).val_;
352 }
353
GetSsp(napi_env env,napi_callback_info info)354 napi_value FileUriNExporter::GetSsp(napi_env env, napi_callback_info info)
355 {
356 NFuncArg funcArg(env, info);
357 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
358 LOGE("Number of arguments unmatched");
359 NError(EINVAL).ThrowErr(env);
360 return nullptr;
361 }
362 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
363 if (!fileuriEntity) {
364 LOGE("Failed to get file entity");
365 NError(EINVAL).ThrowErr(env);
366 return nullptr;
367 }
368
369 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetSchemeSpecificPart()).val_;
370 }
371
GetUserInfo(napi_env env,napi_callback_info info)372 napi_value FileUriNExporter::GetUserInfo(napi_env env, napi_callback_info info)
373 {
374 NFuncArg funcArg(env, info);
375 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
376 LOGE("Number of arguments unmatched");
377 NError(EINVAL).ThrowErr(env);
378 return nullptr;
379 }
380 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
381 if (!fileuriEntity) {
382 LOGE("Failed to get file entity");
383 NError(EINVAL).ThrowErr(env);
384 return nullptr;
385 }
386
387 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetUserInfo()).val_;
388 }
389
GetHost(napi_env env,napi_callback_info info)390 napi_value FileUriNExporter::GetHost(napi_env env, napi_callback_info info)
391 {
392 NFuncArg funcArg(env, info);
393 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
394 LOGE("Number of arguments unmatched");
395 NError(EINVAL).ThrowErr(env);
396 return nullptr;
397 }
398 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
399 if (!fileuriEntity) {
400 LOGE("Failed to get file entity");
401 NError(EINVAL).ThrowErr(env);
402 return nullptr;
403 }
404
405 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetHost()).val_;
406 }
407
GetPort(napi_env env,napi_callback_info info)408 napi_value FileUriNExporter::GetPort(napi_env env, napi_callback_info info)
409 {
410 NFuncArg funcArg(env, info);
411 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
412 LOGE("Number of arguments unmatched");
413 NError(EINVAL).ThrowErr(env);
414 return nullptr;
415 }
416 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
417 if (!fileuriEntity) {
418 LOGE("Failed to get file entity");
419 NError(EINVAL).ThrowErr(env);
420 return nullptr;
421 }
422
423 return NVal::CreateUTF8String(env, to_string(fileuriEntity->fileUri_.uri_.GetPort())).val_;
424 }
425
GetQuery(napi_env env,napi_callback_info info)426 napi_value FileUriNExporter::GetQuery(napi_env env, napi_callback_info info)
427 {
428 NFuncArg funcArg(env, info);
429 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
430 LOGE("Number of arguments unmatched");
431 NError(EINVAL).ThrowErr(env);
432 return nullptr;
433 }
434 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
435 if (!fileuriEntity) {
436 LOGE("Failed to get file entity");
437 NError(EINVAL).ThrowErr(env);
438 return nullptr;
439 }
440
441 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetQuery()).val_;
442 }
443
GetFragment(napi_env env,napi_callback_info info)444 napi_value FileUriNExporter::GetFragment(napi_env env, napi_callback_info info)
445 {
446 NFuncArg funcArg(env, info);
447 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
448 LOGE("Number of arguments unmatched");
449 NError(EINVAL).ThrowErr(env);
450 return nullptr;
451 }
452 auto fileuriEntity = NClass::GetEntityOf<FileUriEntity>(env, funcArg.GetThisVar());
453 if (!fileuriEntity) {
454 LOGE("Failed to get file entity");
455 NError(EINVAL).ThrowErr(env);
456 return nullptr;
457 }
458
459 return NVal::CreateUTF8String(env, fileuriEntity->fileUri_.uri_.GetFragment()).val_;
460 }
461
Export()462 bool FileUriNExporter::Export()
463 {
464 vector<napi_property_descriptor> props = {
465 NVal::DeclareNapiFunction("toString", UriToString),
466 NVal::DeclareNapiGetter("name", GetFileUriName),
467 NVal::DeclareNapiGetter("path", GetFileUriPath),
468 NVal::DeclareNapiFunction("getFullDirectoryUri", GetFullDirectoryUri),
469 NVal::DeclareNapiFunction("isRemoteUri", IsRemoteUri),
470 NVal::DeclareNapiFunction("normalize", Normalize),
471 NVal::DeclareNapiFunction("equals", Equals),
472 NVal::DeclareNapiFunction("equalsTo", EqualsTo),
473 NVal::DeclareNapiFunction("checkIsAbsolute", IsAbsolute),
474 NVal::DeclareNapiGetter("scheme", GetScheme),
475 NVal::DeclareNapiGetter("authority", GetAuthority),
476 NVal::DeclareNapiGetter("ssp", GetSsp),
477 NVal::DeclareNapiGetter("userInfo", GetUserInfo),
478 NVal::DeclareNapiGetter("host", GetHost),
479 NVal::DeclareNapiGetter("port", GetPort),
480 NVal::DeclareNapiGetter("query", GetQuery),
481 NVal::DeclareNapiGetter("fragment", GetFragment),
482 };
483
484 auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
485 if (!succ) {
486 LOGE("Failed to define class");
487 NError(EIO).ThrowErr(exports_.env_);
488 return false;
489 }
490 succ = NClass::SaveClass(exports_.env_, className, classValue);
491 if (!succ) {
492 LOGE("Failed to save class");
493 NError(EIO).ThrowErr(exports_.env_);
494 return false;
495 }
496
497 return exports_.AddProp(className, classValue);
498 }
499
GetClassName()500 string FileUriNExporter::GetClassName()
501 {
502 return FileUriNExporter::className;
503 }
504
FileUriNExporter(napi_env env,napi_value exports)505 FileUriNExporter::FileUriNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
506
~FileUriNExporter()507 FileUriNExporter::~FileUriNExporter() {}
508 } // namespace ModuleFileUri
509 } // namespace AppFileService
510 } // namespace OHOS
511