diff --git a/file_api.gni b/file_api.gni index 7fc94ace62004264471a75000deb0900070d3727..9d00c6fe019ab6f170301f6267b7e8eed99d0a70 100644 --- a/file_api.gni +++ b/file_api.gni @@ -23,3 +23,4 @@ utils_path = "${file_api_path}/utils" use_mac = "${current_os}_${current_cpu}" == "mac_x64" || "${current_os}_${current_cpu}" == "mac_arm64" use_mingw_win = "${current_os}_${current_cpu}" == "mingw_x86_64" +use_android = "${current_os}" \ No newline at end of file diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 444fb9c07fe99c6055a115a22981904cf5bfed91..d26a8e72d319023611f9c5cf8ad43cb1b6172bc2 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -181,6 +181,9 @@ ohos_shared_library("fs") { if (use_mac) { defines = [ "IOS_PLATFORM" ] } + if (use_android) { + defines = [ "ANDROID_PLATFORM" ] + } external_deps = [ "hilog:libhilog", diff --git a/interfaces/kits/js/src/mod_fs/common_func.cpp b/interfaces/kits/js/src/mod_fs/common_func.cpp index 4c0855fe8d9a0277dd29cee2c19fb3459d652542..a6e3e4d7b8fb153d584d17778e65a0d4f5fd7a65 100644 --- a/interfaces/kits/js/src/mod_fs/common_func.cpp +++ b/interfaces/kits/js/src/mod_fs/common_func.cpp @@ -34,6 +34,10 @@ #include "filemgmt_libhilog.h" #include "filemgmt_libn.h" #include "file_utils.h" +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) +#include "ipc_skeleton.h" +#include "tokenid_kit.h" +#endif namespace OHOS { namespace FileManagement { @@ -346,6 +350,71 @@ string CommonFunc::Decode(const std::string &uri) return outPutStream.str(); } +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) +bool IsNumeric(const string &str) +{ + if (str.empty()) { + return false; + } + for (char const &c : str) { + if (!isdigit(c)) { + return false; + } + } + return true; +} + +void SetQueryMap(Uri* uri, std::unordered_map &queryMap) +{ + // file://media/image/12?networkid=xxxx&api_version=xxxx?times=xxx&user=101 + string query = uri->GetQuery(); + string pairString; + stringstream queryStream(query); + + while (getline(queryStream, pairString, '&')) { + size_t splitIndex = pairString.find('='); + if (splitIndex == string::npos || splitIndex == (pairString.length() - 1)) { + HILOGE("failed to parse query, query field is %{private}s!", pairString.c_str()); + continue; + } + queryMap[pairString.substr(0, splitIndex)] = pairString.substr(splitIndex + 1); + } + return; +} + +bool CommonFunc::GetAndCheckUserId(Uri* uri, string &userId) +{ + if (uri->ToString().find("user=") == string::npos) { + return false; + } + + std::unordered_map queryMap; + SetQueryMap(uri, queryMap); + auto it = queryMap.find("user"); + if (it != queryMap.end()) { + userId = it->second; + if (!IsNumeric(userId)) { + HILOGE("IsNumeric check fail"); + return false; + } + return true; + } else { + HILOGE("GetAndCheckUserId no match userId"); + } + return false; +} + +/* + * For compatibility considerations, filtering system applications require non permission verification +*/ +bool CommonFunc::IsSystemApp() +{ + uint64_t fullTokenId = OHOS::IPCSkeleton::GetSelfTokenID(); + return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId); +} +#endif + tuple, unique_ptr> CommonFunc::GetCopyPathArg(napi_env env, napi_value srcPath, napi_value dstPath) diff --git a/interfaces/kits/js/src/mod_fs/common_func.h b/interfaces/kits/js/src/mod_fs/common_func.h index 1fa132f271190f4d1ffa88e7f0fd5de8fb71b3a6..15b5b98a612dc654b01fb7655c8108e865533f3d 100644 --- a/interfaces/kits/js/src/mod_fs/common_func.h +++ b/interfaces/kits/js/src/mod_fs/common_func.h @@ -19,8 +19,9 @@ #include "fd_guard.h" #include "n_val.h" #include "uv.h" -#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) #include "iremote_broker.h" +#include "file_uri.h" #endif namespace OHOS { @@ -63,7 +64,7 @@ struct FileInfo { std::unique_ptr fdg = { nullptr }; }; -#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) class FileIoToken : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"ohos.fileio.open"); @@ -101,6 +102,10 @@ struct CommonFunc { static std::string GetModeFromFlags(unsigned int flags); static bool CheckPublicDirPath(const std::string &sandboxPath); static std::string Decode(const std::string &uri); +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + static bool GetAndCheckUserId(Uri* uri, std::string &userId); + static bool IsSystemApp(); +#endif }; } // namespace ModuleFileIO } // namespace FileManagement diff --git a/interfaces/kits/js/src/mod_fs/properties/copy.cpp b/interfaces/kits/js/src/mod_fs/properties/copy.cpp index 6e9ce72b3dd835973e29a5979596c30d4d118d67..1c876b809f85977a48e61efbb471d78e020710f9 100644 --- a/interfaces/kits/js/src/mod_fs/properties/copy.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/copy.cpp @@ -40,6 +40,7 @@ #include "ipc_skeleton.h" #include "system_ability_definition.h" #include "trans_listener.h" +#include "common_func.h" namespace OHOS { namespace FileManagement { @@ -69,7 +70,18 @@ static int OpenSrcFile(const string &srcPth, std::shared_ptr infos, i HILOGE("Failed to get remote object"); return ENOMEM; } + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + string userId; + if (CommonFunc::GetAndCheckUserId(&uri, userId) && CommonFunc::IsSystemApp()) { + dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), + MEDIALIBRARY_DATA_URI + "?user=" + userId); + } else { + dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI); + } +#else dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI); +#endif if (!dataShareHelper) { HILOGE("Failed to connect to datashare"); return E_PERMISSION; diff --git a/interfaces/kits/js/src/mod_fs/properties/open.cpp b/interfaces/kits/js/src/mod_fs/properties/open.cpp index 922467cd76def3dff8536d732a0e7b6bfd9dcb61..7b5280059ddbd6bea3b4cdcd5608e45565439d64 100644 --- a/interfaces/kits/js/src/mod_fs/properties/open.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/open.cpp @@ -148,6 +148,26 @@ static int OpenFileByPath(const string &path, unsigned int mode) #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +static int OpenFileByDatashareHasUserId(const string &path, unsigned int flags, const string &userId) +{ + std::shared_ptr dataShareHelper = nullptr; + sptr remote = new (std::nothrow) IRemoteStub(); + if (!remote) { + HILOGE("Failed to get remote object"); + return -ENOMEM; + } + + dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), + MEDIALIBRARY_DATA_URI + "?user=" + userId); + if (!dataShareHelper) { + HILOGE("Failed to connect to datashare"); + return -E_PERMISSION; + } + Uri uri(path); + int fd = dataShareHelper->OpenFile(uri, CommonFunc::GetModeFromFlags(flags)); + return fd; +} + static int OpenFileByDatashare(const string &path, unsigned int flags) { std::shared_ptr dataShareHelper = nullptr; @@ -173,11 +193,20 @@ static tuple OpenByFileDataUri(Uri &uri, const string &uriStr, unsi AppFileService::ModuleFileUri::FileUri fileUri(uriStr); string realPath = fileUri.GetRealPath(); if (bundleName == MEDIA) { - int res = OpenFileByDatashare(uri.ToString(), mode); - if (res < 0) { - HILOGE("Failed to open file by Datashare error %{public}d", res); + string userId; + if (CommonFunc::GetAndCheckUserId(&uri, userId) && CommonFunc::IsSystemApp()) { + int res = OpenFileByDatashareHasUserId(uri.ToString(), mode, userId); + if (res < 0) { + HILOGE("Failed to open file by DatashareHasUserId error %{public}d", res); + } + return { res, uri.ToString() }; + } else { + int res = OpenFileByDatashare(uri.ToString(), mode); + if (res < 0) { + HILOGE("Failed to open file by Datashare error %{public}d", res); + } + return { res, uri.ToString() }; } - return { res, uri.ToString() }; } else if (bundleName == DOCS && access(realPath.c_str(), F_OK) != 0) { int res = OpenFileByDatashare(uri.ToString(), mode); if (res < 0) {