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 "medialibrary_uripermission_operations.h"
17
18 #include "common_func.h"
19 #include "ipc_skeleton.h"
20 #include "medialibrary_bundle_manager.h"
21 #include "medialibrary_errno.h"
22 #include "medialibrary_object_utils.h"
23 #include "medialibrary_type_const.h"
24 #include "media_file_utils.h"
25 #include "media_log.h"
26 #include "permission_utils.h"
27 #include "result_set_utils.h"
28
29 namespace OHOS {
30 namespace Media {
31
32 using namespace std;
33 using namespace OHOS::NativeRdb;
34 using namespace OHOS::DataShare;
35
CheckMode(string & mode)36 static bool CheckMode(string& mode)
37 {
38 transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
39 if (MEDIA_OPEN_MODES.find(mode) == MEDIA_OPEN_MODES.end()) {
40 MEDIA_ERR_LOG("mode format is error: %{public}s", mode.c_str());
41 return false;
42 }
43 string tempMode;
44 if (mode.find(MEDIA_FILEMODE_READONLY) != string::npos) {
45 tempMode += MEDIA_FILEMODE_READONLY;
46 }
47 if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos) {
48 tempMode += MEDIA_FILEMODE_WRITEONLY;
49 }
50 mode = tempMode;
51 return true;
52 }
53
HandleUriPermOperations(MediaLibraryCommand & cmd)54 int32_t UriPermissionOperations::HandleUriPermOperations(MediaLibraryCommand &cmd)
55 {
56 if (!PermissionUtils::CheckIsSystemAppByUid()) {
57 MEDIA_ERR_LOG("the caller is not system app");
58 return E_PERMISSION_DENIED;
59 }
60 string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
61
62 int32_t errCode = E_FAIL;
63 switch (cmd.GetOprnType()) {
64 case OperationType::INSERT_PERMISSION:
65 errCode = HandleUriPermInsert(cmd);
66 break;
67 default:
68 MEDIA_ERR_LOG("unknown operation type %{public}d", cmd.GetOprnType());
69 break;
70 }
71 return errCode;
72 }
73
GetUriPermissionMode(const string & fileId,const string & bundleName,int32_t tableType,string & mode)74 int32_t UriPermissionOperations::GetUriPermissionMode(const string &fileId, const string &bundleName,
75 int32_t tableType, string &mode)
76 {
77 MediaLibraryCommand cmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), OperationType::QUERY);
78 cmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, fileId);
79 cmd.GetAbsRdbPredicates()->And()->EqualTo(PERMISSION_BUNDLE_NAME, bundleName);
80 cmd.GetAbsRdbPredicates()->And()->EqualTo(PERMISSION_TABLE_TYPE, to_string(tableType));
81 auto queryResult = MediaLibraryObjectUtils::QueryWithCondition(cmd, {}, "");
82 CHECK_AND_RETURN_RET_LOG(queryResult != nullptr, E_HAS_DB_ERROR, "Failed to obtain value from database");
83 int count = -1;
84 CHECK_AND_RETURN_RET_LOG(queryResult->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
85 "Failed to get query result row count");
86 if (count <= 0) {
87 return E_PERMISSION_DENIED;
88 }
89 CHECK_AND_RETURN_RET_LOG(queryResult->GoToFirstRow() == NativeRdb::E_OK, E_HAS_DB_ERROR,
90 "Failed to go to first row");
91 mode = GetStringVal(PERMISSION_MODE, queryResult);
92 return E_SUCCESS;
93 }
94
CheckUriPermValues(ValuesBucket & valuesBucket,int32_t & fileId,string & bundleName,int32_t & tableType,string & inputMode)95 int32_t CheckUriPermValues(ValuesBucket &valuesBucket, int32_t &fileId, string &bundleName, int32_t &tableType,
96 string &inputMode)
97 {
98 ValueObject valueObject;
99 if (valuesBucket.GetObject(PERMISSION_FILE_ID, valueObject)) {
100 valueObject.GetInt(fileId);
101 } else {
102 MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_FILE_ID");
103 return E_INVALID_VALUES;
104 }
105
106 if (valuesBucket.GetObject(PERMISSION_BUNDLE_NAME, valueObject)) {
107 valueObject.GetString(bundleName);
108 } else {
109 MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_BUNDLE_NAME");
110 return E_INVALID_VALUES;
111 }
112
113 if (valuesBucket.GetObject(PERMISSION_MODE, valueObject)) {
114 valueObject.GetString(inputMode);
115 } else {
116 MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_MODE");
117 return E_INVALID_VALUES;
118 }
119
120 if (valuesBucket.GetObject(PERMISSION_TABLE_TYPE, valueObject)) {
121 valueObject.GetInt(tableType);
122 } else {
123 MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_TABLE_TYPE");
124 return E_INVALID_VALUES;
125 }
126 if (!CheckMode(inputMode)) {
127 return E_INVALID_MODE;
128 }
129 valuesBucket.Delete(PERMISSION_MODE);
130 valuesBucket.PutString(PERMISSION_MODE, inputMode);
131 return E_SUCCESS;
132 }
133
134 #ifdef MEDIALIBRARY_COMPATIBILITY
ConvertVirtualIdToRealId(ValuesBucket & valuesBucket,int32_t & fileId,int32_t tableType)135 static void ConvertVirtualIdToRealId(ValuesBucket &valuesBucket, int32_t &fileId, int32_t tableType)
136 {
137 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
138 fileId = MediaFileUtils::GetRealIdByTable(fileId, PhotoColumn::PHOTOS_TABLE);
139 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
140 fileId = MediaFileUtils::GetRealIdByTable(fileId, AudioColumn::AUDIOS_TABLE);
141 } else {
142 fileId = MediaFileUtils::GetRealIdByTable(fileId, MEDIALIBRARY_TABLE);
143 }
144
145 valuesBucket.Delete(PERMISSION_FILE_ID);
146 valuesBucket.PutInt(PERMISSION_FILE_ID, fileId);
147 }
148 #endif
149
150
HandleUriPermInsert(MediaLibraryCommand & cmd)151 int32_t UriPermissionOperations::HandleUriPermInsert(MediaLibraryCommand &cmd)
152 {
153 int32_t fileId;
154 string bundleName;
155 string inputMode;
156 int32_t tableType;
157 ValuesBucket &valuesBucket = cmd.GetValueBucket();
158 auto ret = CheckUriPermValues(valuesBucket, fileId, bundleName, tableType, inputMode);
159 CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
160
161 #ifdef MEDIALIBRARY_COMPATIBILITY
162 if (cmd.GetApi() != MediaLibraryApi::API_10) {
163 ConvertVirtualIdToRealId(valuesBucket, fileId, tableType);
164 }
165 #endif
166
167 string permissionMode;
168 ret = GetUriPermissionMode(to_string(fileId), bundleName, tableType, permissionMode);
169 if ((ret != E_SUCCESS) && (ret != E_PERMISSION_DENIED)) {
170 return ret;
171 }
172
173 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
174 CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "uniStore is nullptr!");
175
176 if (ret == E_PERMISSION_DENIED) {
177 int64_t outRowId = -1;
178 return uniStore->Insert(cmd, outRowId);
179 }
180 if (permissionMode.find(inputMode) != string::npos) {
181 return E_SUCCESS;
182 }
183 ValuesBucket updateValues;
184 updateValues.PutString(PERMISSION_MODE, MEDIA_FILEMODE_READWRITE);
185 MediaLibraryCommand updateCmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), updateValues);
186 updateCmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, to_string(fileId))->And()->
187 EqualTo(PERMISSION_BUNDLE_NAME, bundleName);
188 int32_t updatedRows = -1;
189 return uniStore->Update(updateCmd, updatedRows);
190 }
191
GetTableTypeFromTableName(const std::string & tableName)192 static inline int32_t GetTableTypeFromTableName(const std::string &tableName)
193 {
194 if (tableName == PhotoColumn::PHOTOS_TABLE) {
195 return static_cast<int32_t>(TableType::TYPE_PHOTOS);
196 } else if (tableName == AudioColumn::AUDIOS_TABLE) {
197 return static_cast<int32_t>(TableType::TYPE_AUDIOS);
198 } else {
199 return static_cast<int32_t>(TableType::TYPE_FILES);
200 }
201 }
202
InsertBundlePermission(const int32_t & fileId,const std::string & bundleName,const std::string & mode,const std::string & tableName)203 int32_t UriPermissionOperations::InsertBundlePermission(const int32_t &fileId, const std::string &bundleName,
204 const std::string &mode, const std::string &tableName)
205 {
206 string curMode;
207 int32_t tableType = GetTableTypeFromTableName(tableName);
208 auto ret = GetUriPermissionMode(to_string(fileId), bundleName, tableType, curMode);
209 if ((ret != E_SUCCESS) && (ret != E_PERMISSION_DENIED)) {
210 return ret;
211 }
212 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
213 CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "uniStore is nullptr!");
214 if (ret == E_PERMISSION_DENIED) {
215 ValuesBucket addValues;
216 addValues.PutInt(PERMISSION_FILE_ID, fileId);
217 addValues.PutString(PERMISSION_BUNDLE_NAME, bundleName);
218 addValues.PutString(PERMISSION_MODE, mode);
219 addValues.PutInt(PERMISSION_TABLE_TYPE, tableType);
220 MediaLibraryCommand cmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), addValues);
221 int64_t outRowId = -1;
222 return uniStore->Insert(cmd, outRowId);
223 }
224 if (curMode.find(mode) != string::npos) {
225 return E_SUCCESS;
226 }
227 ValuesBucket updateValues;
228 updateValues.PutString(PERMISSION_MODE, mode);
229 MediaLibraryCommand updateCmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), updateValues);
230 updateCmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, to_string(fileId))->And()->
231 EqualTo(PERMISSION_BUNDLE_NAME, bundleName)->And()->
232 EqualTo(PERMISSION_TABLE_TYPE, to_string(tableType));
233 int32_t updatedRows = -1;
234 return uniStore->Update(updateCmd, updatedRows);
235 }
236
DeleteBundlePermission(const std::string & fileId,const std::string & bundleName,const std::string & tableName)237 int32_t UriPermissionOperations::DeleteBundlePermission(const std::string &fileId, const std::string &bundleName,
238 const std::string &tableName)
239 {
240 int32_t tableType = GetTableTypeFromTableName(tableName);
241
242 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
243 CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "uniStore is nullptr!");
244 Uri uri(MEDIALIBRARY_BUNDLEPERM_URI);
245 MediaLibraryCommand deleteCmd(uri);
246 deleteCmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, fileId)->And()->
247 EqualTo(PERMISSION_BUNDLE_NAME, bundleName)->And()->
248 EqualTo(PERMISSION_TABLE_TYPE, to_string(tableType));
249 int32_t deleteRows = -1;
250 int32_t ret = uniStore->Delete(deleteCmd, deleteRows);
251 if (deleteRows > 0 && ret == NativeRdb::E_OK) {
252 MEDIA_DEBUG_LOG("DeleteBundlePermission success:fileId:%{private}s, bundleName:%{private}s, table:%{private}s",
253 fileId.c_str(), bundleName.c_str(), tableName.c_str());
254 return E_OK;
255 }
256 return E_HAS_DB_ERROR;
257 }
258
CheckUriPermission(const std::string & fileUri,std::string mode)259 int32_t UriPermissionOperations::CheckUriPermission(const std::string &fileUri, std::string mode)
260 {
261 if (!CheckMode(mode)) {
262 return E_INVALID_MODE;
263 }
264 string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
265 string fileId = MediaLibraryDataManagerUtils::GetIdFromUri(fileUri);
266 TableType tableType = TableType::TYPE_FILES;
267 static map<string, TableType> tableMap = {
268 { MEDIALIBRARY_TYPE_IMAGE_URI, TableType::TYPE_PHOTOS },
269 { MEDIALIBRARY_TYPE_VIDEO_URI, TableType::TYPE_PHOTOS },
270 { MEDIALIBRARY_TYPE_AUDIO_URI, TableType::TYPE_AUDIOS },
271 { MEDIALIBRARY_TYPE_FILE_URI, TableType::TYPE_FILES },
272 { PhotoColumn::PHOTO_TYPE_URI, TableType::TYPE_PHOTOS },
273 { AudioColumn::AUDIO_TYPE_URI, TableType::TYPE_AUDIOS }
274 };
275 for (const auto &iter : tableMap) {
276 if (fileUri.find(iter.first) != string::npos) {
277 tableType = iter.second;
278 }
279 }
280 string permissionMode;
281 int32_t ret = GetUriPermissionMode(fileId, bundleName, static_cast<int32_t>(tableType), permissionMode);
282 CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
283 return (permissionMode.find(mode) != string::npos) ? E_SUCCESS : E_PERMISSION_DENIED;
284 }
285 } // Media
286 } // OHOS