• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #include "file_share_exporter.h"
17 
18 #include <cerrno>
19 #include <climits>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <dirent.h>
24 #include <fcntl.h>
25 #include <stack>
26 #include <sys/sendfile.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <vector>
31 
32 #include "../common/ability_helper.h"
33 #include "../common/common_func.h"
34 #include "../common/napi/n_class.h"
35 #include "../common/napi/n_func_arg.h"
36 #include "../common/napi/n_val.h"
37 #include "../common/uni_error.h"
38 #include "file_share_ability.h"
39 #include "uri.h"
40 
41 using Uri = OHOS::Uri;
42 using namespace std;
43 namespace OHOS {
44 namespace DistributedFS {
45 namespace ModuleFMSExpoter {
46 const int OTHER_ARGUMENT_ERROR = 202;
47 const int URI_PARAMER_ERROR = 302;
48 const int FILE_IO_ERROR = 300;
49 const int FILE_PATH_ERROR = 301;
50 const int SUCCESS = 0;
51 const int FAILED = -1;
52 enum COMMON_NUM {
53     ZERO = 0,
54     ONE = 1,
55     TWO = 2,
56     THREE = 3,
57 };
58 
CallBackSuccess(napi_env env,napi_ref successFuncRef,int32_t count,napi_value obj)59 void CallBackSuccess(napi_env env, napi_ref successFuncRef, int32_t count, napi_value obj)
60 {
61     napi_value results = nullptr;
62     napi_value successFunc = nullptr;
63     napi_value global = nullptr;
64     napi_get_global(env, &global);
65     napi_get_reference_value(env, successFuncRef, &successFunc);
66     if (successFunc == nullptr) {
67         return;
68     }
69     napi_call_function(env, global, successFunc, count, &obj, &results);
70 }
71 
CallBackError(napi_env env,napi_ref failFuncRef,string errorProp,int errorCode)72 void CallBackError(napi_env env, napi_ref failFuncRef, string errorProp, int errorCode)
73 {
74     napi_value argvFail[2] = { 0 };
75     napi_value results = nullptr;
76     napi_value failFunc = nullptr;
77     napi_value global = nullptr;
78     napi_get_global(env, &global);
79     argvFail[0] = NVal::CreateUTF8String(env, errorProp).val_;
80     argvFail[1] = NVal::CreateInt32(env, errorCode).val_;
81     napi_get_reference_value(env, failFuncRef, &failFunc);
82     if (failFunc == nullptr) {
83         return;
84     }
85     napi_call_function(env, global, failFunc, COMMON_NUM::TWO, argvFail, &results);
86 }
87 
CallComplete(napi_env env,napi_ref completeFuncRef)88 void CallComplete(napi_env env, napi_ref completeFuncRef)
89 {
90     napi_value completeFunc = nullptr;
91     napi_value results = nullptr;
92     napi_value global = nullptr;
93     napi_get_global(env, &global);
94     napi_get_reference_value(env, completeFuncRef, &completeFunc);
95     if (completeFunc == nullptr) {
96         return;
97     }
98     napi_call_function(env, global, completeFunc, COMMON_NUM::ZERO, nullptr, &results);
99 }
100 
CheckUri(AppExecFwk::Ability * ability,napi_env env,string & path)101 bool CheckUri(AppExecFwk::Ability *ability, napi_env env, string &path)
102 {
103     string pathOrigin = path;
104     vector<string> uriSplit;
105     string pattern = "/";
106     if (path == "") {
107         return false;
108     }
109     string pathTmp = pathOrigin + pattern;
110     size_t pos = pathTmp.find(pattern);
111     while (pos != pathTmp.npos) {
112         string temp = pathTmp.substr(COMMON_NUM::ZERO, pos);
113         uriSplit.push_back(temp);
114         pathTmp = pathTmp.substr(pos + 1, pathTmp.size());
115         pos = pathTmp.find(pattern);
116     }
117     if (uriSplit[COMMON_NUM::ZERO] != "internal:" || uriSplit[COMMON_NUM::ONE] != "" ||
118         uriSplit.size() <= COMMON_NUM::TWO) {
119         return false;
120     }
121     if (uriSplit[COMMON_NUM::TWO] == "app") {
122         path = ability->GetDataDir();
123     } else if (uriSplit[COMMON_NUM::TWO] == "cache") {
124         path = ability->GetCacheDir();
125     } else {
126         return false;
127     }
128     for (size_t i = COMMON_NUM::THREE; i < uriSplit.size(); ++i) {
129         path = path + "/" + uriSplit[i];
130     }
131     return true;
132 }
133 
GetRealPath(string & path)134 int GetRealPath(string &path)
135 {
136     unique_ptr<char[]> absPath = make_unique<char[]>(PATH_MAX + 1);
137     if (realpath(path.c_str(), absPath.get()) == nullptr) {
138         return errno;
139     }
140     path = absPath.get();
141     return SUCCESS;
142 }
143 
CallbackUriResult(napi_env env,napi_ref napiFailFun,napi_ref napiSuccFun,string uriRet)144 void CallbackUriResult(napi_env env, napi_ref napiFailFun, napi_ref napiSuccFun, string uriRet)
145 {
146     if (uriRet == "") {
147         CallBackError(env, napiFailFun, "error: fuzzyFileToUri failed", FILE_IO_ERROR);
148     } else if (uriRet == "ERROR_AUTHORITY") {
149         CallBackError(env, napiFailFun, "error: authority is not exist", OTHER_ARGUMENT_ERROR);
150     } else if (uriRet == "ERROR_JSON_CONFIG") {
151         CallBackError(env, napiFailFun, "error: invalid json config", FILE_IO_ERROR);
152     } else {
153         CallBackSuccess(env, napiSuccFun, COMMON_NUM::ONE, NVal::CreateUTF8String(env, uriRet).val_);
154     }
155 }
156 
CheckArgumentsError(napi_env env,napi_ref napiFailFun,string deviceIdStr,string authorityStr)157 int CheckArgumentsError(napi_env env, napi_ref napiFailFun, string deviceIdStr, string authorityStr)
158 {
159     if (deviceIdStr == "" || authorityStr == "") {
160         CallBackError(env, napiFailFun, "error: illegal arguments", OTHER_ARGUMENT_ERROR);
161         return FAILED;
162     }
163     return SUCCESS;
164 }
165 
CheckUriError(napi_env env,napi_ref napiFailFun,AppExecFwk::Ability * ability,int checkPathResult,string path)166 int CheckUriError(napi_env env, napi_ref napiFailFun, AppExecFwk::Ability *ability, int checkPathResult, string path)
167 {
168     if (!checkPathResult) {
169         CallBackError(env, napiFailFun, "error: illegal uri", URI_PARAMER_ERROR);
170         return FAILED;
171     } else if (path.find(ability->GetDataDir()) != 0 && path.find(ability->GetCacheDir()) != 0) {
172         CallBackError(env, napiFailFun, "error: uri cannot out of this package", URI_PARAMER_ERROR);
173         return FAILED;
174     }
175     return SUCCESS;
176 }
177 
CheckFilePathError(napi_env env,napi_ref napiFailFun,int realPathResult)178 int CheckFilePathError(napi_env env, napi_ref napiFailFun, int realPathResult)
179 {
180     if (realPathResult == ENOENT) {
181         CallBackError(env, napiFailFun, "error: file or directory not exist", FILE_PATH_ERROR);
182         return FAILED;
183     }
184     return SUCCESS;
185 }
186 
CheckIOError(napi_env env,napi_ref napiFailFun,int realPathResult,string path)187 int CheckIOError(napi_env env, napi_ref napiFailFun, int realPathResult, string path)
188 {
189     struct stat buf;
190     if (realPathResult != SUCCESS) {
191         CallBackError(env, napiFailFun, "error: invalid uri", FILE_IO_ERROR);
192         return FAILED;
193     } else if (stat(path.c_str(), &buf) != SUCCESS || (buf.st_mode & S_IFMT) != S_IFREG) {
194         CallBackError(env, napiFailFun, "error: uri cannot be a directory", FILE_IO_ERROR);
195         return FAILED;
196     }
197     return SUCCESS;
198 }
199 
FuzzyFileToUri(napi_env env,napi_callback_info info)200 napi_value FileShareExporter::FuzzyFileToUri(napi_env env, napi_callback_info info)
201 {
202     NFuncArg funcArg(env, info);
203     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
204         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
205         return nullptr;
206     }
207     bool succ = false;
208     napi_ref napiSuccFun, napiCompFun, napiFailFun;
209     tie(succ, napiSuccFun, napiFailFun, napiCompFun) =
210         CommonFunc::GetCallbackHandles(env, funcArg[NARG_POS::FIRST]);
211 
212     unique_ptr<char[]> uri = nullptr;
213     tie(succ, uri, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("uri").ToUTF8String();
214 
215     unique_ptr<char[]> deviceId = nullptr;
216     tie(succ, deviceId, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("deviceId").ToUTF8String();
217 
218     unique_ptr<char[]> authority = nullptr;
219     tie(succ, authority, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("authority").ToUTF8String();
220 
221     unique_ptr<char[]> displayname = nullptr;
222     tie(succ, displayname, ignore) =
223         NVal(env, funcArg[NARG_POS::FIRST]).GetProp("displayName").ToUTF8String();
224     string path = (uri == nullptr) ? "" : uri.get();
225     string deviceIdStr = (deviceId == nullptr) ? "" : deviceId.get();
226     string authorityStr = (authority == nullptr) ? "" : authority.get();
227     string displaynameStr = (displayname == nullptr) ? "" : displayname.get();
228 
229     AppExecFwk::Ability *ability = AbilityHelper::GetJsAbility(env);
230     if (ability == nullptr) {
231         return nullptr;
232     }
233     bool checkPathResult = CheckUri(ability, env, path);
234     int realPathResult = GetRealPath(path);
235     if (CheckArgumentsError(env, napiFailFun, deviceIdStr, authorityStr) == FAILED ||
236         CheckUriError(env, napiFailFun, ability, checkPathResult, path) == FAILED ||
237         CheckFilePathError(env, napiFailFun, realPathResult) == FAILED ||
238         CheckIOError(env, napiFailFun, realPathResult, path) == FAILED) {
239         CallComplete(env, napiCompFun);
240         napi_delete_reference(env, napiSuccFun);
241         napi_delete_reference(env, napiFailFun);
242         napi_delete_reference(env, napiCompFun);
243         return nullptr;
244     }
245 
246     Uri uriObj("");
247     uriObj = FileManager::FileShareAbility::FuzzyFileToUri(ability, deviceIdStr, authorityStr, path, displaynameStr);
248 
249     string uriRet = uriObj.ToString();
250     CallbackUriResult(env, napiFailFun, napiSuccFun, uriRet);
251 
252     CallComplete(env, napiCompFun);
253     napi_delete_reference(env, napiSuccFun);
254     napi_delete_reference(env, napiFailFun);
255     napi_delete_reference(env, napiCompFun);
256     return NVal::CreateUndefined(env).val_;
257 }
258 
Export()259 bool FileShareExporter::Export()
260 {
261     return exports_.AddProp({
262         NVal::DeclareNapiFunction("fuzzyFileToUri", FuzzyFileToUri),
263     });
264 }
265 
GetClassName()266 string FileShareExporter::GetClassName()
267 {
268     return FileShareExporter::className_;
269 }
270 
FileShareExporter(napi_env env,napi_value exports)271 FileShareExporter::FileShareExporter(napi_env env, napi_value exports)
272     : NExporter(env, exports)
273 {}
274 
~FileShareExporter()275 FileShareExporter::~FileShareExporter() {}
276 } // namespace ModuleFMSExpoter
277 } // namespace DistributedFS
278 } // namespace OHOS