diff --git a/bundle.json b/bundle.json index dbf37010436d05a9fb0fa3a8048b1a292aa0d541..dd6270ec6da3808fa448c15a91f99848b0345317 100644 --- a/bundle.json +++ b/bundle.json @@ -31,6 +31,8 @@ "common_event_service", "c_utils", "data_share", + "device_manager", + "dfs_service", "eventhandler", "hilog", "ipc", diff --git a/file_api.gni b/file_api.gni index d843a2cc7f817eead8afa6e17faea12b57604bff..65ca0707cf7e42275953508e11d2bda28ee690c5 100644 --- a/file_api.gni +++ b/file_api.gni @@ -18,6 +18,7 @@ file_api_path = "//foundation/filemanagement/file_api" hiviewdfx_hilog_path = "//base/hiviewdfx/hilog" src_path = "${file_api_path}/interfaces/kits/js/src" utils_path = "${file_api_path}/utils" +filemanagement_service_path = "//foundation/filemanagement/dfs_service/services" use_mac = "${current_os}_${current_cpu}" == "mac_x64" || "${current_os}_${current_cpu}" == "mac_arm64" diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index d279adaebba72cb542177e4c24ad1522762d7559..f91ae3ad021c842a91469e3932bb154798e346bc 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -109,6 +109,7 @@ ohos_shared_library("fs") { relative_install_dir = "module/file" include_dirs = [ + "${filemanagement_service_path}/distributedfiledaemon/include/ipc", "${src_path}/common", "${src_path}/common/file_helper", "${src_path}/mod_fs", @@ -182,8 +183,11 @@ ohos_shared_library("fs") { "src/mod_fs/properties/watcher.cpp", ] external_deps += [ + "ability_base:want", "ability_base:zuri", "ability_runtime:abilitykit_native", + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "app_file_service:fileuri_native", "bundle_framework:appexecfwk_base", @@ -191,6 +195,8 @@ ohos_shared_library("fs") { "c_utils:utils", "data_share:datashare_common", "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", "ipc:ipc_core", "samgr:samgr_proxy", ] diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_file.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_file.cpp index 71bb328b3d3d4161c803ac2b4569ecda17072ffb..85e59e8649818f714b8874ce93bb66837d3d4087 100644 --- a/interfaces/kits/js/src/mod_fs/properties/copy_file.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/copy_file.cpp @@ -23,15 +23,84 @@ #include #include +#include "accesstoken_kit.h" +#include "bundle_mgr_client_impl.h" #include "common_func.h" +#include "distributed_file_daemon_manager.h" #include "file_utils.h" #include "filemgmt_libhilog.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "uri.h" +#include "uri_permission_manager_client.h" +#include "want.h" namespace OHOS { namespace FileManagement { namespace ModuleFileIO { using namespace std; using namespace OHOS::FileManagement::LibN; +using namespace OHOS::AppExecFwk; +const std::string FILE_PREFIX_NAME = "file://"; +const std::string NETWORK_PARA = "?networkid="; + +static sptr GetBundleMgr() +{ + sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityManager == nullptr) { + HILOGE("systemAbilityManager is nullptr"); + return nullptr; + } + sptr remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (remoteObject == nullptr) { + HILOGE("remoteObject is nullptr"); + return nullptr; + } + return iface_cast(remoteObject); +} + +static std::string GetCurrentBundleName() +{ + HILOGI("tyx::GetCurrentBundleName in."); + auto bundleMgr = GetBundleMgr(); + if (bundleMgr == nullptr) { + HILOGE("failed to get bunlde manager sa"); + return ""; + } + AppExecFwk::BundleInfo bundleInfo; + auto ret = bundleMgr->GetBundleInfoForSelf(0, bundleInfo); + HILOGI("tyx::GetCurrentBundleName GetBundleInfoForSelf end, ret = %{public}d.", ret); + HILOGI("tyx::GetCurrentBundleName GetBundleInfoForSelf end, bundleInfo.name = %{public}s.", bundleInfo.name.c_str()); + return bundleInfo.name; +} + +static bool IsValidUri(const std::string &uri) +{ + HILOGI("tyx::IsValidUri uri."); + if (uri.find(FILE_PREFIX_NAME) != 0) { + return false; + } + // 1、获取当前应用信息 + std::string currentBundleName = GetCurrentBundleName(); + // 2、检查是否为当前应用沙箱下的uri + std::string temp = uri.substr(FILE_PREFIX_NAME.size(), uri.size()); + return temp.find(currentBundleName) == 0; +} + +static bool IsRemoteUri(const std::string &uri) +{ + // NETWORK_PARA + return uri.find(NETWORK_PARA) != uri.npos; +} + +static std::string GetNetworkIdFromUri(const std::string &uri) +{ + HILOGI("tyx::GetNetworkIdFromUri uri."); + return uri.substr(uri.find(NETWORK_PARA) + NETWORK_PARA.size(), uri.size()); +} static NError IsAllPath(FileInfo& srcFile, FileInfo& destFile) { @@ -60,6 +129,40 @@ static NError IsAllPath(FileInfo& srcFile, FileInfo& destFile) return NError(ERRNO_NOERR); } +static NError CopyFileFromSoftBus(const char *remoteUri, const char *destPath) +{ + HILOGI("tyx::CopyFileFromSoftBus in."); +#if 0 + // todo 1、Uri鉴权-元能力 + auto &permissionClient = AAFwk::UriPermissionManagerClient::GetInstance(); + // bool VerifyUriPermission(const Uri &uri, uint32_t flag, uint32_t tokenId) + OHOS::Uri uri(srcFile.uri); + auto isVerified = permissionClient.VerifyUriPermission(uri, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, + IPCSkeleton::GetCallingTokenID()); + if (!isVerified) { + // todo uri权限校验失败,抛出错误码。 + return NError(-1); + } +#endif + // todo 2、建链-dfs_service-软总线 + auto packageName = GetCurrentBundleName(); + if (packageName.empty()) { + // todo 抛出错误码, + return NError(-1); + } + + auto networkId = GetNetworkIdFromUri(remoteUri); // 复制端的设备id,粘贴端调用此接口 + HILOGI("tyx::CopyFileFromSoftBus, networkId = %{public}s.", networkId.c_str()); + auto ret = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PrepareSession( + remoteUri, destPath, networkId); + HILOGI("tyx::PrepareSession, ret = %{public}d.", ret); + if (ret != 0) { + // todo 建联过程中的错误,抛出错误码 + return NError(-1); + } + return NError(ERRNO_NOERR); +} + static NError SendFileCore(FileInfo& srcFdg, FileInfo& destFdg, struct stat& statbf) { std::unique_ptr sendfile_req = { @@ -161,6 +264,32 @@ static NError OpenFile(FileInfo& srcFile, FileInfo& destFile) return SendFileCore(srcFile, destFile, statbf); } +static tuple GetModeFromOptionArg(napi_env env, const NFuncArg& funcArg) +{ + int32_t mode = 0; + bool succ = false; + if (funcArg.GetArgc() >= NARG_CNT::THREE) { + NVal op(env, funcArg[NARG_POS::THIRD]); + + if (op.HasProp("mode") && !op.GetProp("mode").TypeIs(napi_undefined)) { + tie(succ, mode) = op.GetProp("mode").ToInt32(); + if (!succ || mode != 0) { + HILOGE("Illegal options.mode parameter"); + return { false, mode, NVal() }; + } + } + + if (op.HasProp("progressListener") && !op.GetProp("progressListener").TypeIs(napi_undefined)) { + if (!op.GetProp("progressListener").TypeIs(napi_function)) { + HILOGE("Illegal options.progressListener type"); + return { false, mode, NVal() }; + } + return { true, mode, op.GetProp("progressListener") }; + } + } + return { true, mode, NVal() }; +} + static tuple ParseJsMode(napi_env env, const NFuncArg& funcArg) { bool succ = false; @@ -174,10 +303,47 @@ static tuple ParseJsMode(napi_env env, const NFuncArg& funcArg) return { true, mode }; } +static bool IsDirectory(char* path) +{ + struct stat buf; + int ret = stat(path, &buf); + if (ret == -1) { + HILOGI("tyx::stat failed, errno is %{public}d, ", errno); + return false; + } + return (buf.st_mode & S_IFMT) == S_IFDIR; +} + +static bool IsFile(char* path) +{ + struct stat buf; + int ret = stat(path, &buf); + if (ret == -1) { + HILOGI("tyx::stat failed, errno is %{public}d, ", errno); + return false; + } + return (buf.st_mode & S_IFMT) == S_IFREG; +} + +static bool CheckValidParam(FileInfo &src, FileInfo &dest) +{ + if (src.isPath && dest.isPath) { + return IsValidUri(src.path.get()) ? IsRemoteUri(src.path.get()) && IsDirectory(dest.path.get()) + : IsFile(src.path.get()) && IsFile(dest.path.get()); + } + + if (src.isPath) { + return IsFile(src.path.get()); + } + return dest.isPath ? IsFile(dest.path.get()) : true; +} + static tuple ParseJsOperand(napi_env env, NVal pathOrFdFromJsArg) { + HILOGI("tyx::ParseJsOperand in."); auto [isPath, path, ignore] = pathOrFdFromJsArg.ToUTF8String(); if (isPath) { + HILOGI("tyx::isPath. path = %{public}s", path.get()); return { true, FileInfo { true, move(path), {} } }; } @@ -191,9 +357,8 @@ static tuple ParseJsOperand(napi_env env, NVal pathOrFdFromJsArg } return { true, FileInfo { false, {}, move(fdg) } }; } - return { false, FileInfo { false, {}, {} } }; -}; +} napi_value CopyFile::Sync(napi_env env, napi_callback_info info) { @@ -237,6 +402,7 @@ napi_value CopyFile::Sync(napi_env env, napi_callback_info info) napi_value CopyFile::Async(napi_env env, napi_callback_info info) { + HILOGI("tyx::CopyFile::Async in."); NFuncArg funcArg(env, info); if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::FOUR)) { HILOGE("Number of arguments unmatched"); @@ -245,7 +411,9 @@ napi_value CopyFile::Async(napi_env env, napi_callback_info info) } auto [succSrc, src] = ParseJsOperand(env, { env, funcArg[NARG_POS::FIRST] }); + HILOGI("tyx::CopyFile::Async ParseJsOperand src end."); auto [succDest, dest] = ParseJsOperand(env, { env, funcArg[NARG_POS::SECOND] }); + HILOGI("tyx::CopyFile::Async ParseJsOperand dest end."); if (!succSrc || !succDest) { HILOGE("The first/second argument requires filepath/fd"); NError(EINVAL).ThrowErr(env); @@ -253,8 +421,21 @@ napi_value CopyFile::Async(napi_env env, napi_callback_info info) } auto [succMode, mode] = ParseJsMode(env, funcArg); + HILOGI("tyx::CopyFile::Async ParseJsOperand mode end."); if (!succMode) { HILOGE("Failed to convert mode to int32"); + auto [succOptions, mode, listener] = GetModeFromOptionArg(env, funcArg); + if (!succOptions) { + HILOGE("Failed to convert options"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + // 注册listener + } + + bool validParam = CheckValidParam(src, dest); + if (!validParam) { + HILOGE("tyx::Param is not valid."); NError(EINVAL).ThrowErr(env); return nullptr; } @@ -266,6 +447,9 @@ napi_value CopyFile::Async(napi_env env, napi_callback_info info) return nullptr; } auto cbExec = [para]() -> NError { + if (IsRemoteUri(para->src_.path.get()) && IsDirectory(para->dest_.path.get())) { + return CopyFileFromSoftBus(para->src_.path.get(), para->dest_.path.get()); + } if (para->src_.isPath && para->dest_.isPath) { return IsAllPath(para->src_, para->dest_); }