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 #define MLOG_TAG "DirOperation"
16
17 #include "medialibrary_dir_operations.h"
18
19 #include <algorithm>
20
21 #include "abs_rdb_predicates.h"
22 #include "datashare_predicates.h"
23 #include "datashare_result_set.h"
24 #include "media_log.h"
25 #include "medialibrary_file_operations.h"
26 #include "media_file_utils.h"
27 #include "medialibrary_data_manager_utils.h"
28 #include "medialibrary_errno.h"
29 #include "medialibrary_smartalbum_map_operations.h"
30 #include "medialibrary_object_utils.h"
31 #include "rdb_utils.h"
32 #include "scanner_utils.h"
33
34 using namespace std;
35 using namespace OHOS::NativeRdb;
36 using namespace OHOS::RdbDataShareAdapter;
37
38 namespace OHOS {
39 namespace Media {
40 static const std::string MEDIA_NO_FILE = ".nofile";
41
DeleteDirInfoUtil(const int & parent,const shared_ptr<RdbStore> & rdbStore,const MediaLibraryDirDb & dirDbOprn)42 int32_t MediaLibraryDirOperations::DeleteDirInfoUtil(const int &parent,
43 const shared_ptr<RdbStore> &rdbStore,
44 const MediaLibraryDirDb &dirDbOprn)
45 {
46 shared_ptr<AbsSharedResultSet> queryResultSet, queryParentResultSet;
47 vector<string> columns, selectionArgs;
48 selectionArgs.push_back(to_string(parent));
49 AbsRdbPredicates mediaLibDirAbsPred(MEDIALIBRARY_TABLE);
50 mediaLibDirAbsPred.SetWhereClause(DIR_PARENT_WHERECLAUSE);
51 mediaLibDirAbsPred.SetWhereArgs(selectionArgs);
52 queryResultSet = rdbStore->Query(mediaLibDirAbsPred, columns);
53 int32_t deleteErrorCode = E_FAIL;
54 auto count = 0;
55 auto ret = queryResultSet->GetRowCount(count);
56 if (ret != NativeRdb::E_OK) {
57 MEDIA_ERR_LOG("get rdbstore failed");
58 return E_HAS_DB_ERROR;
59 }
60 MEDIA_INFO_LOG("count = %{public}d", (int)count);
61 if (count == 0) {
62 AbsRdbPredicates mediaLibParentDirAbsPred(MEDIALIBRARY_TABLE);
63 mediaLibParentDirAbsPred.SetWhereClause(DIR_FILE_WHERECLAUSE);
64 mediaLibParentDirAbsPred.SetWhereArgs(selectionArgs);
65 queryParentResultSet = rdbStore->Query(mediaLibParentDirAbsPred, columns);
66 if (queryParentResultSet->GoToNextRow() == NativeRdb::E_OK) {
67 int32_t columnIndexParentId, parentIdVal, columnIndexDir;
68 string dirVal;
69 queryParentResultSet->GetColumnIndex(MEDIA_DATA_DB_PARENT_ID, columnIndexParentId);
70 queryParentResultSet->GetInt(columnIndexParentId, parentIdVal);
71 queryParentResultSet->GetColumnIndex(MEDIA_DATA_DB_FILE_PATH, columnIndexDir);
72 queryParentResultSet->GetString(columnIndexDir, dirVal);
73 if (parentIdVal == 0) {
74 return E_SUCCESS;
75 }
76 MEDIA_INFO_LOG("dirVal = %{private}s", dirVal.c_str());
77 MEDIA_INFO_LOG("parentIdVal = %{public}d", parentIdVal);
78 deleteErrorCode = const_cast<MediaLibraryDirDb &>(dirDbOprn)
79 .DeleteDirInfo(parent, rdbStore);
80 if (deleteErrorCode != E_SUCCESS) {
81 MEDIA_ERR_LOG("rdbstore delete failed");
82 return deleteErrorCode;
83 }
84 if (!MediaFileUtils::DeleteDir(dirVal)) {
85 MEDIA_ERR_LOG("deleteDir failed");
86 return E_DELETE_DIR_FAIL;
87 }
88 DeleteDirInfoUtil(parentIdVal, rdbStore, dirDbOprn);
89 }
90 } else {
91 return E_SUCCESS;
92 }
93 return deleteErrorCode;
94 }
95
DeleteFMSDirInfoUtil(const std::string & relativePath,const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const MediaLibraryDirDb & dirDbOprn)96 int32_t MediaLibraryDirOperations::DeleteFMSDirInfoUtil(const std::string &relativePath,
97 const std::shared_ptr<NativeRdb::RdbStore> &rdbStore,
98 const MediaLibraryDirDb &dirDbOprn)
99 {
100 shared_ptr<AbsSharedResultSet> queryResultSet;
101 vector<string> columns, selectionArgs;
102 int32_t deleteErrorCode = E_FAIL;
103 MEDIA_INFO_LOG("relativePath = %{private}s", relativePath.c_str());
104 string data = ROOT_MEDIA_DIR + relativePath;
105 if (data.substr(data.length() - 1) == "/") {
106 data = data.substr(0, data.length() - 1);
107 }
108 MEDIA_INFO_LOG("data = %{private}s", data.c_str());
109 AbsRdbPredicates mediaLibParentDirAbsPred(MEDIALIBRARY_TABLE);
110 selectionArgs.push_back((relativePath + "%"));
111 selectionArgs.push_back(data);
112 mediaLibParentDirAbsPred.SetWhereClause(DIR_RELATIVEPATH_WHERECLAUSE);
113 mediaLibParentDirAbsPred.SetWhereArgs(selectionArgs);
114 queryResultSet = rdbStore->Query(mediaLibParentDirAbsPred, columns);
115 if (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
116 int32_t columnIndexId, idVal, columnIndexParentId, parentIdVal;
117 queryResultSet->GetColumnIndex(MEDIA_DATA_DB_ID, columnIndexId);
118 queryResultSet->GetInt(columnIndexId, idVal);
119 queryResultSet->GetColumnIndex(MEDIA_DATA_DB_PARENT_ID, columnIndexParentId);
120 queryResultSet->GetInt(columnIndexParentId, parentIdVal);
121 MEDIA_INFO_LOG("DeleteFMSDirInfoUtil idVal = %{public}d", idVal);
122 MEDIA_INFO_LOG("DeleteFMSDirInfoUtil parentIdVal = %{public}d", parentIdVal);
123 if (parentIdVal == 0) {
124 MEDIA_INFO_LOG("Root dir can not delete");
125 return E_SUCCESS;
126 }
127 deleteErrorCode = const_cast<MediaLibraryDirDb &>(dirDbOprn)
128 .DeleteDirInfo(idVal, rdbStore);
129 if (!MediaFileUtils::DeleteDir(data)) {
130 return E_DELETE_DIR_FAIL;
131 } else {
132 DeleteDirInfoUtil(parentIdVal, rdbStore, dirDbOprn);
133 }
134 }
135 return deleteErrorCode;
136 }
137
CheckFileExtension(const int mediaType,string extension,const string & dstMediaType)138 int32_t MediaLibraryDirOperations::CheckFileExtension(const int mediaType, string extension, const string &dstMediaType)
139 {
140 if (!extension.empty() && extension[0] == '.') {
141 extension.erase(extension.begin());
142 }
143 MEDIA_INFO_LOG("extension: %{public}s, media_type: %{public}s", extension.c_str(), dstMediaType.c_str());
144 if (dstMediaType == DIR_ALL_TYPE_VALUES) {
145 return E_SUCCESS;
146 }
147 string mimeType = ScannerUtils::GetMimeTypeFromExtension(extension);
148 MediaType type = ScannerUtils::GetMediatypeFromMimetype(mimeType);
149 if (type != mediaType) {
150 return E_CHECK_MEDIATYPE_FAIL;
151 }
152 if (dstMediaType.find(to_string(type)) != string::npos) {
153 return E_SUCCESS;
154 } else {
155 return E_CHECK_EXTENSION_FAIL;
156 }
157 }
158
GetDirQuerySet(const NativeRdb::ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore,const unordered_map<string,DirAsset> & dirQuerySetMap)159 DirAsset MediaLibraryDirOperations::GetDirQuerySet(const NativeRdb::ValuesBucket &values,
160 const shared_ptr<RdbStore> &rdbStore,
161 const unordered_map<string, DirAsset> &dirQuerySetMap)
162 {
163 string rootDir;
164 ValueObject valueObject;
165 DirAsset dirAsset;
166 vector<string> columns, selectionArgs;
167 if (values.GetObject(CATEGORY_MEDIATYPE_DIRECTORY_DB_DIRECTORY, valueObject)) {
168 valueObject.GetString(rootDir);
169 selectionArgs.push_back(rootDir);
170 }
171 unordered_map<string, DirAsset>::const_iterator iterator = dirQuerySetMap.find(rootDir);
172 if (iterator != dirQuerySetMap.end()) {
173 MEDIA_INFO_LOG("find in dirQuerySetMap");
174 dirAsset = dirQuerySetMap.at(rootDir);
175 }
176 return dirAsset;
177 }
178
CheckDirInfoUtil(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore,const unordered_map<string,DirAsset> & dirQuerySetMap)179 int32_t MediaLibraryDirOperations::CheckDirInfoUtil(const ValuesBucket &values,
180 const shared_ptr<RdbStore> &rdbStore,
181 const unordered_map<string, DirAsset> &dirQuerySetMap)
182 {
183 DirAsset dirAsset = GetDirQuerySet(values, rdbStore, dirQuerySetMap);
184 if (dirAsset.GetDirType() == DEFAULT_DIR_TYPE) {
185 MEDIA_ERR_LOG("Check directory failed");
186 return E_CHECK_DIR_FAIL;
187 }
188 if (dirAsset.GetDirectory() == DOWNLOAD_DIR_VALUES) {
189 return E_SUCCESS;
190 }
191 string extension;
192 ValueObject valueObject;
193 if (values.GetObject(CATEGORY_MEDIATYPE_DIRECTORY_DB_EXTENSION, valueObject)) {
194 valueObject.GetString(extension);
195 } else {
196 MEDIA_ERR_LOG("get extension failed");
197 return E_FAIL;
198 }
199 string path;
200 if (values.GetObject(MEDIA_DATA_DB_FILE_PATH, valueObject)) {
201 valueObject.GetString(path);
202 } else {
203 MEDIA_ERR_LOG("get path failed");
204 return E_FAIL;
205 }
206 if (extension.compare(MEDIA_NO_FILE) == 0) {
207 if (MediaLibraryObjectUtils::IsFileExistInDb(path)) {
208 MEDIA_ERR_LOG("dir is existed");
209 return E_FILE_EXIST;
210 }
211 return E_SUCCESS;
212 }
213 int mediaType = MEDIA_TYPE_ALL;
214 if (values.GetObject(MEDIA_DATA_DB_MEDIA_TYPE, valueObject)) {
215 valueObject.GetInt(mediaType);
216 } else {
217 MEDIA_ERR_LOG("get mediaType failed");
218 return E_FAIL;
219 }
220 return CheckFileExtension(mediaType, extension, dirAsset.GetMediaTypes());
221 }
222
HandleFMSTrashDir(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore,const unordered_map<string,DirAsset> & dirQuerySetMap)223 int32_t MediaLibraryDirOperations::HandleFMSTrashDir(const ValuesBucket &values,
224 const shared_ptr<RdbStore> &rdbStore,
225 const unordered_map<string, DirAsset> &dirQuerySetMap)
226 {
227 ValueObject valueObject;
228 MediaLibrarySmartAlbumMapOperations smartAlbumMapOprn;
229 MediaLibrarySmartAlbumMapDb smartAlbumMapDbOprn;
230 SmartAlbumMapQueryData smartAlbumMapQueryData;
231 smartAlbumMapQueryData.smartAlbumMapDbOprn = smartAlbumMapDbOprn;
232 smartAlbumMapQueryData.values = values;
233 smartAlbumMapQueryData.rdbStore = rdbStore;
234 smartAlbumMapQueryData.dirQuerySetMap = dirQuerySetMap;
235 int32_t dirId = 0;
236 if (values.GetObject(MEDIA_DATA_DB_ID, valueObject)) {
237 valueObject.GetInt(dirId);
238 } else {
239 MEDIA_ERR_LOG("HandleFMSTrashDir invalid id");
240 return E_FAIL;
241 }
242 smartAlbumMapQueryData.values.Clear();
243 smartAlbumMapQueryData.values.PutInt(SMARTALBUMMAP_DB_ALBUM_ID, TRASH_ALBUM_ID_VALUES);
244 smartAlbumMapQueryData.values.PutInt(SMARTALBUMMAP_DB_CHILD_ASSET_ID, dirId);
245 return smartAlbumMapOprn.HandleAddAssetOperations(TRASH_ALBUM_ID_VALUES, dirId, smartAlbumMapQueryData);
246 }
247
GetRootDirAndExtension(string & displayName,string & relativePath,int mediaType,ValuesBucket & outValues)248 int32_t MediaLibraryDirOperations::GetRootDirAndExtension(string &displayName, string &relativePath,
249 int mediaType, ValuesBucket &outValues)
250 {
251 string extension, rootDir;
252 if (!MediaFileUtils::CheckDisplayName(displayName)) {
253 return E_FILE_NAME_INVALID;
254 }
255 size_t dirIndex = relativePath.find("/");
256 if (dirIndex != string::npos) {
257 rootDir = relativePath.substr(0, dirIndex);
258 size_t parentDirIndex = rootDir.find("/");
259 if (parentDirIndex == string::npos) {
260 rootDir = rootDir + "/";
261 }
262 } else {
263 MEDIA_ERR_LOG("get dirIndex failed");
264 return E_CHECK_ROOT_DIR_FAIL;
265 }
266 size_t displayNameIndex = displayName.find(".");
267 if ((displayNameIndex == string::npos) && (mediaType != MEDIA_TYPE_FILE) && (rootDir != DOWNLOAD_DIR_VALUES)) {
268 MEDIA_ERR_LOG("get displayNameIndex failed");
269 return E_FILE_NAME_INVALID;
270 } else if (displayNameIndex != string::npos) {
271 extension = displayName.substr(displayNameIndex);
272 transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
273 }
274 outValues.PutString(CATEGORY_MEDIATYPE_DIRECTORY_DB_EXTENSION, extension);
275 outValues.PutString(CATEGORY_MEDIATYPE_DIRECTORY_DB_DIRECTORY, rootDir);
276 return E_SUCCESS;
277 }
278
HandleDeleteDir(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore)279 int32_t MediaLibraryDirOperations::HandleDeleteDir(const ValuesBucket &values,
280 const shared_ptr<RdbStore> &rdbStore)
281 {
282 ValueObject valueObject;
283 MediaLibraryDirDb dirDbOprn;
284 int parent;
285 if (values.GetObject(MEDIA_DATA_DB_PARENT_ID, valueObject)) {
286 valueObject.GetInt(parent);
287 }
288 int errorCode = DeleteDirInfoUtil(parent, rdbStore, dirDbOprn);
289 return errorCode;
290 }
291
HandleFMSDeleteDir(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore)292 int32_t MediaLibraryDirOperations::HandleFMSDeleteDir(const ValuesBucket &values,
293 const shared_ptr<RdbStore> &rdbStore)
294 {
295 ValueObject valueObject;
296 MediaLibraryDirDb dirDbOprn;
297 string relative;
298 if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
299 valueObject.GetString(relative);
300 }
301 int errorCode = DeleteFMSDirInfoUtil(relative, rdbStore, dirDbOprn);
302 return errorCode;
303 }
304
HandleSpecialMediaType(const int & mediaType)305 static bool HandleSpecialMediaType(const int &mediaType)
306 {
307 if (mediaType == MEDIA_TYPE_NOFILE) {
308 MEDIA_DEBUG_LOG("special type %{public}d, pass check", mediaType);
309 return true;
310 }
311 return false;
312 }
313
HandleCheckDirExtension(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore,const unordered_map<string,DirAsset> & dirQuerySetMap)314 int32_t MediaLibraryDirOperations::HandleCheckDirExtension(const ValuesBucket &values,
315 const shared_ptr<RdbStore> &rdbStore,
316 const unordered_map<string, DirAsset>
317 &dirQuerySetMap)
318 {
319 ValueObject valueObject;
320 string displayName, relativePath;
321 int mediaType = MEDIA_TYPE_FILE;
322 if (values.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
323 valueObject.GetString(displayName);
324 MEDIA_INFO_LOG("displayName = %{private}s", displayName.c_str());
325 }
326 if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
327 valueObject.GetString(relativePath);
328 MEDIA_INFO_LOG("relativePath = %{private}s", relativePath.c_str());
329 }
330 if (values.GetObject(MEDIA_DATA_DB_MEDIA_TYPE, valueObject)) {
331 valueObject.GetInt(mediaType);
332 MEDIA_INFO_LOG("mediaType = %{public}d", mediaType);
333 }
334 if (HandleSpecialMediaType(mediaType)) {
335 return E_SUCCESS;
336 }
337 ValuesBucket GetDirAndExtensionValues;
338 int errorCode = GetRootDirAndExtension(displayName, relativePath, mediaType, GetDirAndExtensionValues);
339 if (errorCode != E_SUCCESS) {
340 MEDIA_ERR_LOG("GetDirAndExtension fail");
341 return errorCode;
342 }
343 string path = ROOT_MEDIA_DIR + relativePath;
344 if ((path.substr(path.length() - 1)).compare("/")) {
345 path = path.substr(0, path.length() - 1);
346 }
347 MEDIA_INFO_LOG("path = %{public}s", path.c_str());
348 GetDirAndExtensionValues.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
349 GetDirAndExtensionValues.PutString(MEDIA_DATA_DB_FILE_PATH, path);
350 errorCode = CheckDirInfoUtil(GetDirAndExtensionValues, rdbStore, dirQuerySetMap);
351
352 return errorCode;
353 }
354
HandleDirOperations(const string & oprn,const ValuesBucket & valuesBucket,const shared_ptr<RdbStore> & rdbStore,const unordered_map<string,DirAsset> & dirQuerySetMap)355 int32_t MediaLibraryDirOperations::HandleDirOperations(const string &oprn,
356 const ValuesBucket &valuesBucket, const shared_ptr<RdbStore> &rdbStore,
357 const unordered_map<string, DirAsset> &dirQuerySetMap)
358 {
359 ValuesBucket values = const_cast<ValuesBucket &>(valuesBucket);
360 int32_t errCode = E_FAIL;
361 ValueObject valueObject;
362 if (oprn == MEDIA_DIROPRN_DELETEDIR) {
363 errCode = HandleDeleteDir(values, rdbStore);
364 } else if (oprn == MEDIA_DIROPRN_CHECKDIR_AND_EXTENSION) {
365 errCode = HandleCheckDirExtension(values, rdbStore, dirQuerySetMap);
366 } else if (oprn == MEDIA_DIROPRN_FMS_CREATEDIR) {
367 values.PutString(MEDIA_DATA_DB_NAME, ".nofile");
368 values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_TYPE_NOFILE);
369 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::CREATE);
370 cmd.SetValueBucket(values);
371 errCode = MediaLibraryFileOperations::CreateFileOperation(cmd);
372 } else if (oprn == MEDIA_DIROPRN_FMS_DELETEDIR) {
373 errCode = HandleFMSDeleteDir(values, rdbStore);
374 } else if (oprn == MEDIA_DIROPRN_FMS_TRASHDIR) {
375 errCode = HandleFMSTrashDir(values, rdbStore, dirQuerySetMap);
376 }
377 MEDIA_INFO_LOG("HandleDirOperations erroCode = %{public}d", errCode);
378 return errCode;
379 }
380 } // namespace Media
381 } // namespace OHOS
382