• 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 #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