1 /*
2 * Copyright (C) 2024 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 #define MLOG_TAG "DbPermissionHandler"
17
18 #include "db_permission_handler.h"
19
20 #include <cstdlib>
21
22 #include "media_app_uri_permission_column.h"
23 #include "media_file_uri.h"
24 #include "media_file_utils.h"
25 #include "medialibrary_bundle_manager.h"
26 #include "medialibrary_rdbstore.h"
27 #include "rdb_utils.h"
28 #include "medialibrary_uripermission_operations.h"
29 #include "permission_utils.h"
30 #include "medialibrary_type_const.h"
31 #include "medialibrary_data_manager.h"
32 #include "media_column.h"
33
34 using namespace std;
35 using namespace OHOS::RdbDataShareAdapter;
36
37 namespace OHOS::Media {
38
39 static string UFM_PHOTO_PREFIX = "datashare:///media/userfilemgr_photo_operation";
40 static string UFM_AUDIO_PREFIX = "datashare:///media/userfilemgr_audio_operation";
41 static string PATH_PHOTO_PREFIX = "datashare:///media/phaccess_photo_operation";
42
ParseFileIdFromPredicates(const DataShare::DataSharePredicates & predicates,string & fileId)43 static bool ParseFileIdFromPredicates(const DataShare::DataSharePredicates &predicates, string &fileId)
44 {
45 // parse fileId from operationList
46 constexpr int32_t FIELD_IDX = 0;
47 constexpr int32_t VALUE_IDX = 1;
48 constexpr int32_t OPERATION_SIZE = 2;
49 auto operationItems = predicates.GetOperationList();
50 for (DataShare::OperationItem item : operationItems) {
51 if (item.singleParams.size() < OPERATION_SIZE) {
52 continue;
53 }
54 if (!MediaLibraryDataManagerUtils::IsNumber(static_cast<string>(item.GetSingle(VALUE_IDX)))) {
55 continue;
56 }
57 if (static_cast<string>(item.GetSingle(FIELD_IDX)) == MediaColumn::MEDIA_ID) {
58 fileId = static_cast<string>(item.GetSingle(VALUE_IDX));
59 return true;
60 }
61 }
62
63 // parse fileId from whereClause
64 const string &clause = predicates.GetWhereClause();
65 const vector<string> &values = predicates.GetWhereArgs();
66 size_t pos = clause.find(MediaColumn::MEDIA_ID);
67 if (pos == string::npos) {
68 MEDIA_ERR_LOG("whereClause not include fileId");
69 return false;
70 }
71 size_t argIndex = 0;
72 constexpr char placeholder = '?';
73 for (size_t i = 0; i < pos; ++i) {
74 if (clause[i] == placeholder) {
75 ++argIndex;
76 }
77 }
78
79 CHECK_AND_RETURN_RET_LOG(argIndex < values.size(), false, "argIndex should less than values size");
80 fileId = values[argIndex];
81 CHECK_AND_RETURN_RET_LOG(MediaLibraryDataManagerUtils::IsNumber(fileId), false,
82 "whereArgs fileId=%{public}s is not num", fileId.c_str());
83 return true;
84 }
85
ParseInfoFromCmd(MediaLibraryCommand & cmd,string & fileId,int32_t & uriType)86 static bool ParseInfoFromCmd(MediaLibraryCommand &cmd, string &fileId, int32_t &uriType)
87 {
88 if (MediaFileUtils::StartsWith(cmd.GetUri().ToString(), PhotoColumn::PHOTO_URI_PREFIX)) {
89 uriType = static_cast<int32_t>(TableType::TYPE_PHOTOS);
90 fileId = MediaFileUtils::GetIdFromUri(cmd.GetUri().ToString());
91 return true;
92 }
93 if (MediaFileUtils::StartsWith(cmd.GetUri().ToString(), AudioColumn::AUDIO_URI_PREFIX)) {
94 uriType = static_cast<int32_t>(TableType::TYPE_AUDIOS);
95 fileId = MediaFileUtils::GetIdFromUri(cmd.GetUri().ToString());
96 return true;
97 }
98
99 if (cmd.IsDataSharePredNull()) {
100 MEDIA_DEBUG_LOG("DataSharePred is nullptr");
101 return false;
102 }
103 bool isPhotoType = MediaFileUtils::StartsWith(cmd.GetUri().ToString(), UFM_PHOTO_PREFIX)
104 || MediaFileUtils::StartsWith(cmd.GetUri().ToString(), PATH_PHOTO_PREFIX);
105 if (isPhotoType) {
106 uriType = static_cast<int32_t>(TableType::TYPE_PHOTOS);
107 return ParseFileIdFromPredicates(cmd.GetDataSharePred(), fileId);
108 }
109 if (MediaFileUtils::StartsWith(cmd.GetUri().ToString(), UFM_AUDIO_PREFIX)) {
110 uriType = static_cast<int32_t>(TableType::TYPE_AUDIOS);
111 return ParseFileIdFromPredicates(cmd.GetDataSharePred(), fileId);
112 }
113 MEDIA_ERR_LOG("parse fileId and uriType from cmd fail");
114 return false;
115 }
116
ExecuteCheckPermission(MediaLibraryCommand & cmd,PermParam & permParam)117 int32_t DbPermissionHandler::ExecuteCheckPermission(MediaLibraryCommand &cmd, PermParam &permParam)
118 {
119 MEDIA_DEBUG_LOG("DbPermissionHandler enter");
120 bool isWrite = permParam.isWrite;
121 string appId = GetClientAppId();
122 uint32_t tokenId = PermissionUtils::GetTokenId();
123 string fileId = "";
124 int32_t uriType = 0;
125 if (!ParseInfoFromCmd(cmd, fileId, uriType)) {
126 return E_INVALID_URI;
127 }
128 MEDIA_DEBUG_LOG("isWrite=%{public}d,appId=%{public}s,tokenId=%{public}u,fileId=%{public}s,uriType=%{public}d",
129 isWrite, appId.c_str(), tokenId, fileId.c_str(), uriType);
130 bool cond = ((appId.empty() && !tokenId) || fileId.empty());
131 CHECK_AND_RETURN_RET_LOG(!cond, E_INVALID_FILEID, "invalid input");
132
133 DataShare::DataSharePredicates predicates;
134 predicates.EqualTo(AppUriPermissionColumn::FILE_ID, fileId);
135 predicates.EqualTo(AppUriPermissionColumn::URI_TYPE, uriType);
136 predicates.And()->BeginWrap()->EqualTo(AppUriPermissionColumn::APP_ID, appId)
137 ->Or()->EqualTo(AppUriPermissionColumn::TARGET_TOKENID, to_string(tokenId))->EndWrap();
138 if (isWrite) {
139 predicates.In(FIELD_PERMISSION_TYPE, AppUriPermissionColumn::PERMISSION_TYPES_WRITE_STR);
140 } else {
141 predicates.In(FIELD_PERMISSION_TYPE, AppUriPermissionColumn::PERMISSION_TYPES_READ_STR);
142 }
143 vector<string> columns;
144 auto queryResultSet =
145 MediaLibraryRdbStore::QueryWithFilter(RdbUtils::ToPredicates(predicates, TABLE_PERMISSION), columns);
146 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, E_PERMISSION_DENIED, "queryResultSet is nullptr");
147 int count = 0;
148 auto ret = queryResultSet->GetRowCount(count);
149 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK && count > 0, E_PERMISSION_DENIED, "db is no permission record");
150 return E_SUCCESS;
151 }
152
153 } // namespace name