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_errno.h"
21 #include "medialibrary_object_utils.h"
22 #include "media_file_utils.h"
23 #include "media_log.h"
24 #include "permission_utils.h"
25 #include "result_set_utils.h"
26
27 using namespace std;
28 using namespace OHOS::NativeRdb;
29 using namespace OHOS::DataShare;
30
31 namespace OHOS {
32 namespace Media {
33
CheckMode(string & mode)34 static bool CheckMode(string& mode)
35 {
36 transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
37 if (MEDIA_OPEN_MODES.find(mode) == MEDIA_OPEN_MODES.end()) {
38 MEDIA_ERR_LOG("mode format is error: %{public}s", mode.c_str());
39 return false;
40 }
41 string tempMode;
42 if (mode.find(MEDIA_FILEMODE_READONLY) != string::npos) {
43 tempMode += MEDIA_FILEMODE_READONLY;
44 }
45 if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos) {
46 tempMode += MEDIA_FILEMODE_WRITEONLY;
47 }
48 mode = tempMode;
49 return true;
50 }
51
HandleUriPermOperations(MediaLibraryCommand & cmd)52 int32_t UriPermissionOperations::HandleUriPermOperations(MediaLibraryCommand &cmd)
53 {
54 string bundleName;
55 bool isSystemApp = false;
56 PermissionUtils::GetClientBundle(IPCSkeleton::GetCallingUid(), bundleName, isSystemApp);
57 if (!isSystemApp) {
58 MEDIA_ERR_LOG("the caller is not system app");
59 return E_PERMISSION_DENIED;
60 }
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,string & mode)74 int32_t UriPermissionOperations::GetUriPermissionMode(const string &fileId, const string &bundleName, string &mode)
75 {
76 MediaLibraryCommand cmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), OperationType::QUERY);
77 cmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, fileId);
78 cmd.GetAbsRdbPredicates()->And()->EqualTo(PERMISSION_BUNDLE_NAME, bundleName);
79 auto queryResult = MediaLibraryObjectUtils::QueryWithCondition(cmd, {}, "");
80 CHECK_AND_RETURN_RET_LOG(queryResult != nullptr, E_HAS_DB_ERROR, "Failed to obtain value from database");
81 int count = -1;
82 CHECK_AND_RETURN_RET_LOG(queryResult->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
83 "Failed to get query result row count");
84 if (count <= 0) {
85 return E_PERMISSION_DENIED;
86 }
87 CHECK_AND_RETURN_RET_LOG(queryResult->GoToFirstRow() == NativeRdb::E_OK, E_HAS_DB_ERROR,
88 "Failed to go to first row");
89 mode = GetStringVal(PERMISSION_MODE, queryResult);
90 return E_SUCCESS;
91 }
92
CheckUriPermValues(ValuesBucket & valuesBucket,int32_t & fileId,string & bundleName,string & inputMode)93 int32_t CheckUriPermValues(ValuesBucket &valuesBucket, int32_t &fileId, string &bundleName, string &inputMode)
94 {
95 ValueObject valueObject;
96 if (valuesBucket.GetObject(PERMISSION_FILE_ID, valueObject)) {
97 valueObject.GetInt(fileId);
98 } else {
99 MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_FILE_ID");
100 return E_INVALID_VALUES;
101 }
102
103 if (valuesBucket.GetObject(PERMISSION_BUNDLE_NAME, valueObject)) {
104 valueObject.GetString(bundleName);
105 } else {
106 MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_BUNDLE_NAME");
107 return E_INVALID_VALUES;
108 }
109
110 if (valuesBucket.GetObject(PERMISSION_MODE, valueObject)) {
111 valueObject.GetString(inputMode);
112 } else {
113 MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_MODE");
114 return E_INVALID_VALUES;
115 }
116 if (!CheckMode(inputMode)) {
117 return E_INVALID_MODE;
118 }
119 valuesBucket.Delete(PERMISSION_MODE);
120 valuesBucket.PutString(PERMISSION_MODE, inputMode);
121 return E_SUCCESS;
122 }
123
HandleUriPermInsert(MediaLibraryCommand & cmd)124 int32_t UriPermissionOperations::HandleUriPermInsert(MediaLibraryCommand &cmd)
125 {
126 int32_t fileId;
127 string bundleName;
128 string inputMode;
129 ValuesBucket &valuesBucket = cmd.GetValueBucket();
130 auto ret = CheckUriPermValues(valuesBucket, fileId, bundleName, inputMode);
131 CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
132
133 string permissionMode;
134 ret = GetUriPermissionMode(to_string(fileId), bundleName, permissionMode);
135 if ((ret != E_SUCCESS) && (ret != E_PERMISSION_DENIED)) {
136 return ret;
137 }
138
139 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
140 CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "uniStore is nullptr!");
141
142 if (ret == E_PERMISSION_DENIED) {
143 int64_t outRowId = -1;
144 return uniStore->Insert(cmd, outRowId);
145 }
146 if (permissionMode.find(inputMode) != string::npos) {
147 return E_SUCCESS;
148 }
149 ValuesBucket updateValues;
150 updateValues.PutString(PERMISSION_MODE, MEDIA_FILEMODE_READWRITE);
151 MediaLibraryCommand updateCmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), updateValues);
152 updateCmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, to_string(fileId))->And()->
153 EqualTo(PERMISSION_BUNDLE_NAME, bundleName);
154 int32_t updatedRows = -1;
155 return uniStore->Update(updateCmd, updatedRows);
156 }
157
CheckUriPermission(const std::string & fileUri,std::string mode)158 int32_t UriPermissionOperations::CheckUriPermission(const std::string &fileUri, std::string mode)
159 {
160 if (!CheckMode(mode)) {
161 return E_INVALID_MODE;
162 }
163 string bundleName;
164 bool isSystemApp = false;
165 PermissionUtils::GetClientBundle(IPCSkeleton::GetCallingUid(), bundleName, isSystemApp);
166 string fileId = MediaLibraryDataManagerUtils::GetIdFromUri(fileUri);
167 string permissionMode;
168 int32_t ret = GetUriPermissionMode(fileId, bundleName, permissionMode);
169 CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
170 return (permissionMode.find(mode) != string::npos) ? E_SUCCESS : E_PERMISSION_DENIED;
171 }
172 } // Media
173 } // OHOS