• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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