1  /*
2   * Copyright (c) 2021-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  
16  #include "environment_n_exporter.h"
17  #include "accesstoken_kit.h"
18  #include "account_error_no.h"
19  #include "filemgmt_libhilog.h"
20  #include "ipc_skeleton.h"
21  #include "os_account_manager.h"
22  #include "parameter.h"
23  #include "tokenid_kit.h"
24  #include <string>
25  #include <unistd.h>
26  namespace OHOS {
27  namespace FileManagement {
28  namespace ModuleEnvironment {
29  using namespace OHOS::FileManagement::LibN;
30  namespace {
31  const std::string STORAGE_DATA_PATH = "/data";
32  const std::string PC_STORAGE_PATH = "/storage/Users/";
33  const std::string EXTERNAL_STORAGE_PATH = "/storage/External";
34  const std::string USER_APP_DATA_PATH = "/appdata";
35  const std::string READ_WRITE_DOWNLOAD_PERMISSION = "ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY";
36  const std::string READ_WRITE_DESKTOP_PERMISSION = "ohos.permission.READ_WRITE_DESKTOP_DIRECTORY";
37  const std::string READ_WRITE_DOCUMENTS_PERMISSION = "ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY";
38  const std::string FILE_ACCESS_MANAGER_PERMISSION = "ohos.permission.FILE_ACCESS_MANAGER";
39  const std::string DOWNLOAD_PATH = "/Download";
40  const std::string DESKTOP_PATH = "/Desktop";
41  const std::string DOCUMENTS_PATH = "/Documents";
42  const std::string DEFAULT_USERNAME = "currentUser";
43  const char *g_fileManagerFullMountEnableParameter = "const.filemanager.full_mount.enable";
IsSystemApp()44  static bool IsSystemApp()
45  {
46      uint64_t fullTokenId = OHOS::IPCSkeleton::GetCallingFullTokenID();
47      return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
48  }
49  
CheckCallingPermission(const std::string & permission)50  static bool CheckCallingPermission(const std::string &permission)
51  {
52      Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
53      int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
54      if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
55          HILOGE("ModuleUserDirectory::CheckCallingPermission have no fileAccess permission");
56          return false;
57      }
58      return true;
59  }
60  
GetUserName()61  static std::string GetUserName()
62  {
63      std::string userName;
64      ErrCode errCode = OHOS::AccountSA::OsAccountManager::GetOsAccountShortName(userName);
65      if (errCode != ERR_OK || userName.empty()) {
66          HILOGE("Get userName Failed");
67      }
68      userName = DEFAULT_USERNAME;
69      return userName;
70  }
71  
GetPublicPath(const std::string & directoryName)72  static std::string GetPublicPath(const std::string &directoryName)
73  {
74      return PC_STORAGE_PATH + GetUserName() + directoryName;
75  }
76  
CheckFileManagerFullMountEnable()77  static bool CheckFileManagerFullMountEnable()
78  {
79      char value[] = "false";
80      int retSystem = GetParameter(g_fileManagerFullMountEnableParameter, "false", value, sizeof(value));
81      if (retSystem > 0 && !std::strcmp(value, "true")) {
82          return true;
83      }
84      HILOGE("Not supporting all mounts");
85      return false;
86  }
87  
CheckInvalidAccess(const std::string & permission,napi_env env)88  static bool CheckInvalidAccess(const std::string &permission, napi_env env)
89  {
90      if (!CheckFileManagerFullMountEnable()) {
91          HILOGE("Capability not supported");
92          NError(E_DEVICENOTSUPPORT).ThrowErr(env);
93          return true;
94      }
95      if (permission == FILE_ACCESS_MANAGER_PERMISSION) {
96          if (!IsSystemApp()) {
97              NError(E_PERMISSION_SYS).ThrowErr(env);
98              return true;
99          }
100      }
101      if (!CheckCallingPermission(permission)) {
102          HILOGE("No Permission");
103          NError(E_PERMISSION).ThrowErr(env);
104          return true;
105      }
106      return false;
107  }
108  }
109  
GetStorageDataDir(napi_env env,napi_callback_info info)110  napi_value GetStorageDataDir(napi_env env, napi_callback_info info)
111  {
112      if (!IsSystemApp()) {
113          NError(E_PERMISSION_SYS).ThrowErr(env);
114          return nullptr;
115      }
116      NFuncArg funcArg(env, info);
117      if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
118          HILOGE("Number of arguments unmatched");
119          NError(EINVAL).ThrowErr(env);
120          return nullptr;
121      }
122  
123      auto cbExec = []() -> NError {
124          return NError(ERRNO_NOERR);
125      };
126      auto cbComplete = [](napi_env env, NError err) -> NVal {
127          if (err) {
128              return { env, err.GetNapiErr(env) };
129          }
130          return NVal::CreateUTF8String(env, STORAGE_DATA_PATH);
131      };
132  
133      static const std::string PROCEDURE_NAME = "GetStorageDataDir";
134      NVal thisVar(env, funcArg.GetThisVar());
135      if (funcArg.GetArgc() == NARG_CNT::ZERO) {
136          return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
137      }
138  
139      NVal cb(env, funcArg[NARG_POS::FIRST]);
140      return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
141  }
142  
GetUserId()143  int GetUserId()
144  {
145      return 0;
146  }
147  
GetUserDataDir(napi_env env,napi_callback_info info)148  napi_value GetUserDataDir(napi_env env, napi_callback_info info)
149  {
150      if (!IsSystemApp()) {
151          NError(E_PERMISSION_SYS).ThrowErr(env);
152          return nullptr;
153      }
154      NFuncArg funcArg(env, info);
155      if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
156          HILOGE("Number of arguments unmatched");
157          NError(EINVAL).ThrowErr(env);
158          return nullptr;
159      }
160  
161      auto userDataPath = std::make_shared<std::string>();
162      auto cbExec = [userDataPath]() -> NError {
163          (*userDataPath).append("/storage/media/").append(std::to_string(GetUserId())).append("/local");
164          return NError(ERRNO_NOERR);
165      };
166      auto cbComplete = [userDataPath](napi_env env, NError err) -> NVal {
167          if (err) {
168              return { env, err.GetNapiErr(env) };
169          }
170          return NVal::CreateUTF8String(env, *userDataPath);
171      };
172  
173      static const std::string PROCEDURE_NAME = "GetUserDataDir";
174      NVal thisVar(env, funcArg.GetThisVar());
175      if (funcArg.GetArgc() == NARG_CNT::ZERO) {
176          return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
177      }
178  
179      NVal cb(env, funcArg[NARG_POS::FIRST]);
180      return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
181  }
182  
GetUserDownloadDir(napi_env env,napi_callback_info info)183  napi_value GetUserDownloadDir(napi_env env, napi_callback_info info)
184  {
185      if (!CheckFileManagerFullMountEnable()) {
186          HILOGE("Capability not supported");
187          NError(E_DEVICENOTSUPPORT).ThrowErr(env);
188          return nullptr;
189      }
190      NFuncArg funcArg(env, info);
191      if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
192          HILOGE("Number of arguments unmatched");
193          NError(E_PARAMS).ThrowErr(env);
194          return nullptr;
195      }
196      static std::string downloadPath = GetPublicPath(DOWNLOAD_PATH);
197      if (downloadPath.empty()) {
198          HILOGE("Unknown error");
199          NError(E_UNKNOWN_ERROR).ThrowErr(env);
200          return nullptr;
201      }
202      return NVal::CreateUTF8String(env, downloadPath).val_;
203  }
204  
GetUserDesktopDir(napi_env env,napi_callback_info info)205  napi_value GetUserDesktopDir(napi_env env, napi_callback_info info)
206  {
207      if (!CheckFileManagerFullMountEnable()) {
208          HILOGE("Capability not supported");
209          NError(E_DEVICENOTSUPPORT).ThrowErr(env);
210          return nullptr;
211      }
212      NFuncArg funcArg(env, info);
213      if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
214          HILOGE("Number of arguments unmatched");
215          NError(E_PARAMS).ThrowErr(env);
216          return nullptr;
217      }
218      static std::string desktopPath = GetPublicPath(DESKTOP_PATH);
219      if (desktopPath.empty()) {
220          HILOGE("Unknown error");
221          NError(E_UNKNOWN_ERROR).ThrowErr(env);
222          return nullptr;
223      }
224      return NVal::CreateUTF8String(env, desktopPath).val_;
225  }
226  
GetUserDocumentDir(napi_env env,napi_callback_info info)227  napi_value GetUserDocumentDir(napi_env env, napi_callback_info info)
228  {
229      if (!CheckFileManagerFullMountEnable()) {
230          HILOGE("Capability not supported");
231          NError(E_DEVICENOTSUPPORT).ThrowErr(env);
232          return nullptr;
233      }
234      NFuncArg funcArg(env, info);
235      if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
236          HILOGE("Number of arguments unmatched");
237          NError(E_PARAMS).ThrowErr(env);
238          return nullptr;
239      }
240      static std::string documentsPath = GetPublicPath(DOCUMENTS_PATH);
241      if (documentsPath.empty()) {
242          HILOGE("Unknown error");
243          NError(E_UNKNOWN_ERROR).ThrowErr(env);
244          return nullptr;
245      }
246      return NVal::CreateUTF8String(env, documentsPath).val_;
247  }
248  
GetExternalStorageDir(napi_env env,napi_callback_info info)249  napi_value GetExternalStorageDir(napi_env env, napi_callback_info info)
250  {
251      if (CheckInvalidAccess(FILE_ACCESS_MANAGER_PERMISSION, env)) {
252          return nullptr;
253      }
254      NFuncArg funcArg(env, info);
255      if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
256          HILOGE("Number of arguments unmatched");
257          NError(E_PARAMS).ThrowErr(env);
258          return nullptr;
259      }
260      return NVal::CreateUTF8String(env, EXTERNAL_STORAGE_PATH).val_;
261  }
262  
GetUserHomeDir(napi_env env,napi_callback_info info)263  napi_value GetUserHomeDir(napi_env env, napi_callback_info info)
264  {
265      if (CheckInvalidAccess(FILE_ACCESS_MANAGER_PERMISSION, env)) {
266          return nullptr;
267      }
268      NFuncArg funcArg(env, info);
269      if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
270          HILOGE("Number of arguments unmatched");
271          NError(E_PARAMS).ThrowErr(env);
272          return nullptr;
273      }
274      static std::string userName = GetUserName();
275      if (userName.empty()) {
276          HILOGE("Unknown error");
277          NError(E_UNKNOWN_ERROR).ThrowErr(env);
278          return nullptr;
279      }
280      return NVal::CreateUTF8String(env, PC_STORAGE_PATH + userName).val_;
281  }
282  } // namespace ModuleEnvironment
283  } // namespace FileManagement
284  } // namespace OHOS