1 /*
2  * Copyright (C) 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 #include "medialibrary_db_const.h"
16 #define MLOG_TAG "ObjectUtils"
17 
18 #include "medialibrary_object_utils.h"
19 
20 #include <algorithm>
21 #include <cerrno>
22 #include <sys/sendfile.h>
23 #include <unistd.h>
24 #include "album_asset.h"
25 #include "datashare_predicates.h"
26 #ifdef DISTRIBUTED
27 #include "device_manager.h"
28 #endif
29 #include "directory_ex.h"
30 #include "fetch_result.h"
31 #include "file_asset.h"
32 #include "ipc_skeleton.h"
33 #include "media_file_utils.h"
34 #include "media_column.h"
35 #include "media_container_types.h"
36 #include "media_directory_type_column.h"
37 #include "media_log.h"
38 #include "media_scanner_manager.h"
39 #include "media_smart_album_column.h"
40 #include "media_smart_map_column.h"
41 #include "medialibrary_bundle_manager.h"
42 #include "medialibrary_data_manager.h"
43 #include "medialibrary_data_manager_utils.h"
44 #include "medialibrary_dir_operations.h"
45 #include "medialibrary_notify.h"
46 #include "medialibrary_smartalbum_map_operations.h"
47 #include "medialibrary_errno.h"
48 #include "medialibrary_inotify.h"
49 #include "medialibrary_smartalbum_map_operations.h"
50 #include "media_privacy_manager.h"
51 #include "mimetype_utils.h"
52 #include "parameter.h"
53 #include "permission_utils.h"
54 #include "photo_album_column.h"
55 #include "result_set_utils.h"
56 #include "sandbox_helper.h"
57 #include "string_ex.h"
58 #include "thumbnail_service.h"
59 #include "value_object.h"
60 #include "medialibrary_tracer.h"
61 #include "picture_handle_service.h"
62 #include "post_event_utils.h"
63 #include "dfx_utils.h"
64 
65 using namespace std;
66 using namespace OHOS::NativeRdb;
67 
68 namespace OHOS {
69 namespace Media {
70 static const string ASSET_RECYCLE_SUFFIX = "-copy";
71 static const string NO_MEDIA_TAG = ".nomedia";
CreateDirWithPath(const string & dirPath)72 int32_t MediaLibraryObjectUtils::CreateDirWithPath(const string &dirPath)
73 {
74     if (dirPath.empty()) {
75         return E_INVALID_PATH;
76     }
77 
78     int64_t rowId = -1;
79     ValuesBucket values;
80     values.PutString(MEDIA_DATA_DB_FILE_PATH, dirPath);
81     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ALBUM, OperationType::CREATE, values);
82     int32_t ret = CreateDirObj(cmd, rowId);
83     if (ret == E_FILE_EXIST || ret == E_SUCCESS) {
84         return rowId;
85     }
86     return ret;
87 }
88 
GetDirAsset(const string & path)89 NativeAlbumAsset MediaLibraryObjectUtils::GetDirAsset(const string &path)
90 {
91     NativeAlbumAsset dirAsset;
92     if (path.empty()) {
93         MEDIA_ERR_LOG("Path is empty, create failed!");
94         dirAsset.SetAlbumId(E_INVALID_PATH);
95         return dirAsset;
96     }
97 
98     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
99     if (uniStore == nullptr) {
100         MEDIA_ERR_LOG("uniStore is nullptr!");
101         dirAsset.SetAlbumId(E_HAS_DB_ERROR);
102         return dirAsset;
103     }
104 
105     int32_t dirId = CreateDirWithPath(path);
106     MEDIA_DEBUG_LOG("After CreateDirWithPath, get dirId = %{private}d!", dirId);
107     dirAsset.SetAlbumId(dirId);
108     if (dirId < 0) {
109         return dirAsset;
110     }
111 
112     string nameVal = GetStringColumnByIdFromDb(to_string(dirId), MEDIA_DATA_DB_NAME);
113     if (nameVal.empty()) {
114         MEDIA_ERR_LOG("Get dir name failed!");
115         return dirAsset;
116     }
117     dirAsset.SetAlbumName(nameVal);
118     MEDIA_DEBUG_LOG("bucketId = %{private}d bucketName = %{private}s", dirId, nameVal.c_str());
119     return dirAsset;
120 }
121 
DeleteInvalidRowInDb(const string & path)122 int32_t MediaLibraryObjectUtils::DeleteInvalidRowInDb(const string &path)
123 {
124     if (GetIdByPathFromDb(path) < 0) {
125         // path is not in database, no need to delete
126         return E_SUCCESS;
127     }
128 
129     if (MediaFileUtils::IsFileExists(path)) {
130         // File aready exist, not need to create again
131         return E_SUCCESS;
132     }
133 
134     MediaLibraryCommand deleteCmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
135     if (DeleteInfoByPathInDb(deleteCmd, path) != E_SUCCESS) {
136         // Delete the record in database if file is not in filesystem any more
137         MEDIA_ERR_LOG("CreateFileAsset: delete info in db failed");
138         return E_DELETE_DIR_FAIL;
139     }
140     return E_SUCCESS;
141 }
142 
InsertFileInDb(MediaLibraryCommand & cmd,const FileAsset & fileAsset,const NativeAlbumAsset & dirAsset)143 int32_t MediaLibraryObjectUtils::InsertFileInDb(MediaLibraryCommand &cmd,
144     const FileAsset &fileAsset, const NativeAlbumAsset &dirAsset)
145 {
146     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
147     if (uniStore == nullptr) {
148         MEDIA_ERR_LOG("uniStore is nullptr!");
149         return E_HAS_DB_ERROR;
150     }
151 
152     // Fill basic file information into DB
153     string displayName = fileAsset.GetDisplayName();
154     ValuesBucket assetInfo;
155     assetInfo.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, fileAsset.GetMediaType());
156     assetInfo.PutString(MEDIA_DATA_DB_URI, MediaFileUtils::GetMediaTypeUri(fileAsset.GetMediaType()));
157     string extension = ScannerUtils::GetFileExtension(displayName);
158     assetInfo.PutString(MEDIA_DATA_DB_MIME_TYPE, MimeTypeUtils::GetMimeTypeFromExtension(extension));
159     assetInfo.PutString(MEDIA_DATA_DB_RELATIVE_PATH, fileAsset.GetRelativePath());
160     assetInfo.PutString(MEDIA_DATA_DB_NAME, displayName);
161     assetInfo.PutString(MEDIA_DATA_DB_TITLE, MediaFileUtils::GetTitleFromDisplayName(displayName));
162     struct stat statInfo {};
163     if (stat(fileAsset.GetPath().c_str(), &statInfo) == 0) {
164         assetInfo.PutLong(MEDIA_DATA_DB_SIZE, statInfo.st_size);
165         assetInfo.PutLong(MEDIA_DATA_DB_DATE_ADDED, MediaFileUtils::UTCTimeMilliSeconds());
166         assetInfo.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, MediaFileUtils::Timespec2Millisecond(statInfo.st_mtim));
167     }
168     assetInfo.PutString(MEDIA_DATA_DB_FILE_PATH, fileAsset.GetPath());
169     assetInfo.PutInt(MEDIA_DATA_DB_BUCKET_ID, dirAsset.GetAlbumId());
170     assetInfo.PutInt(MEDIA_DATA_DB_PARENT_ID, dirAsset.GetAlbumId());
171     assetInfo.PutString(MEDIA_DATA_DB_BUCKET_NAME, dirAsset.GetAlbumName());
172     assetInfo.PutString(MEDIA_DATA_DB_OWNER_PACKAGE, cmd.GetBundleName());
173     assetInfo.PutString(MEDIA_DATA_DB_OWNER_APPID, PermissionUtils::GetAppIdByBundleName(cmd.GetBundleName()));
174     if (!cmd.GetBundleName().empty()) {
175         assetInfo.PutString(MEDIA_DATA_DB_PACKAGE_NAME,
176             PermissionUtils::GetPackageNameByBundleName(cmd.GetBundleName()));
177     }
178 
179     assetInfo.PutString(MEDIA_DATA_DB_DEVICE_NAME, cmd.GetDeviceName());
180     assetInfo.PutLong(MEDIA_DATA_DB_TIME_PENDING, fileAsset.GetTimePending());
181     cmd.SetValueBucket(assetInfo);
182     int64_t outRowId = -1;
183     int32_t errCode = uniStore->Insert(cmd, outRowId);
184     return (errCode == NativeRdb::E_OK) ? outRowId : errCode;
185 }
186 
GetRelativePathFromValues(ValuesBucket & values,string & relativePath,int32_t mediaType)187 void GetRelativePathFromValues(ValuesBucket &values, string &relativePath, int32_t mediaType)
188 {
189     ValueObject valueObject;
190     if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
191         valueObject.GetString(relativePath);
192         return;
193     }
194     if (values.GetObject(MEDIA_DATA_DB_URI, valueObject)) {
195         string albumUri;
196         valueObject.GetString(albumUri);
197         auto albumAsset = MediaLibraryObjectUtils::GetFileAssetFromUri(albumUri);
198         if (albumAsset != nullptr) {
199             relativePath = albumAsset->GetRelativePath() + albumAsset->GetDisplayName() + SLASH_CHAR;
200         }
201     } else {
202         MediaLibraryObjectUtils::GetDefaultRelativePath(mediaType, relativePath);
203     }
204 }
205 
BuildFileAsset(MediaLibraryCommand & cmd,FileAsset & fileAsset,NativeAlbumAsset & dirAsset,string & path,int32_t & mediaType)206 int32_t MediaLibraryObjectUtils::BuildFileAsset(MediaLibraryCommand &cmd, FileAsset &fileAsset,
207     NativeAlbumAsset &dirAsset, string &path, int32_t &mediaType)
208 {
209     string relativePath;
210     string displayName;
211 
212     ValueObject valueObject;
213     ValuesBucket &values = cmd.GetValueBucket();
214     if (!values.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
215         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
216             {KEY_OPT_TYPE, OptType::CREATE}};
217         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
218         return E_HAS_DB_ERROR;
219     }
220     valueObject.GetString(displayName);
221     fileAsset.SetDisplayName(displayName);
222     if (!values.GetObject(MEDIA_DATA_DB_MEDIA_TYPE, valueObject)) {
223         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
224             {KEY_OPT_TYPE, OptType::CREATE}};
225         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
226         return E_HAS_DB_ERROR;
227     }
228     valueObject.GetInt(mediaType);
229     fileAsset.SetMediaType(static_cast<MediaType>(mediaType));
230     GetRelativePathFromValues(values, relativePath, mediaType);
231     if (!relativePath.empty()) {
232         values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath);
233         path = ROOT_MEDIA_DIR + relativePath + displayName;
234         fileAsset.SetRelativePath(relativePath);
235         fileAsset.SetPath(path);
236     }
237 
238     // check dir and extension
239     int32_t errCode = CheckDirExtension(relativePath, displayName);
240     if (errCode != E_SUCCESS) {
241         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
242             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::CREATE}};
243         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
244     }
245     CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS, errCode, "CreateFileAsset: check file asset failed");
246     dirAsset = GetDirAsset(ROOT_MEDIA_DIR + relativePath);
247     if (dirAsset.GetAlbumId() < 0) {
248         return dirAsset.GetAlbumId();
249     }
250     fileAsset.SetTimePending(0);
251     return E_SUCCESS;
252 }
253 
254 // create
CreateFileObj(MediaLibraryCommand & cmd)255 int32_t MediaLibraryObjectUtils::CreateFileObj(MediaLibraryCommand &cmd)
256 {
257     FileAsset fileAsset;
258     NativeAlbumAsset dirAsset;
259     string path;
260     int32_t mediaType = static_cast<int32_t>(MEDIA_TYPE_FILE);
261     int errCode = BuildFileAsset(cmd, fileAsset, dirAsset, path, mediaType);
262     if (errCode != E_SUCCESS) {
263         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
264             {KEY_OPT_TYPE, OptType::CREATE}};
265         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
266         MEDIA_ERR_LOG("Build file asset error");
267         return errCode;
268     }
269     // delete rows in database but not in real filesystem
270     errCode = DeleteInvalidRowInDb(path);
271     if (errCode != E_SUCCESS) {
272         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
273             {KEY_OPT_TYPE, OptType::CREATE}};
274         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
275         MEDIA_ERR_LOG("Delete invalid row in database failed");
276         return errCode;
277     }
278 
279     errCode = MediaFileUtils::CreateAsset(path);
280     if (errCode != E_SUCCESS) {
281         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
282             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::CREATE}};
283         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
284         MEDIA_ERR_LOG("CreateFileAsset: create file asset failed");
285         return errCode;
286     }
287 
288     if (mediaType == MEDIA_TYPE_NOFILE) {
289         errCode = UpdateDateModified(MediaFileUtils::GetParentPath(MediaFileUtils::GetParentPath(fileAsset.GetPath())));
290         if (errCode == E_HAS_DB_ERROR) {
291             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
292                 {KEY_OPT_TYPE, OptType::CREATE}};
293             PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
294         }
295         return dirAsset.GetAlbumId();
296     }
297     auto ret = InsertFileInDb(cmd, fileAsset, dirAsset);
298     if (ret > 0) {
299         UpdateDateModified(MediaFileUtils::GetParentPath(fileAsset.GetPath()));
300     } else if (ret < 0) {
301         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
302             {KEY_OPT_TYPE, OptType::CREATE}};
303         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
304     }
305     return ret;
306 }
307 
GetLastDirExistInDb(const string & dirPath)308 NativeAlbumAsset MediaLibraryObjectUtils::GetLastDirExistInDb(const string &dirPath)
309 {
310     NativeAlbumAsset dirAsset;
311     string lastPath = dirPath;
312     if (lastPath.back() == '/') {
313         lastPath.pop_back();
314     }
315     int32_t dirId = 0;
316     int32_t lastPathId = -1;
317     do {
318         size_t slashIndex = lastPath.rfind(SLASH_CHAR);
319         if (slashIndex == string::npos || lastPath.length() <= ROOT_MEDIA_DIR.length()) {
320             break;
321         }
322         lastPath = lastPath.substr(0, slashIndex);
323         lastPathId = GetIdByPathFromDb(lastPath);
324         if (lastPathId >= 0) {
325             dirId = lastPathId;
326         }
327     } while (lastPathId < 0);
328     MEDIA_DEBUG_LOG("GetLastAlbumExistInDb lastPath = %{private}s", lastPath.c_str());
329     dirAsset.SetAlbumId(dirId);
330     dirAsset.SetAlbumPath(lastPath);
331     return dirAsset;
332 }
333 
DeleteRows(const vector<int64_t> & rowIds)334 int32_t MediaLibraryObjectUtils::DeleteRows(const vector<int64_t> &rowIds)
335 {
336     int32_t errCode = 0;
337 
338     for (auto id : rowIds) {
339         MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
340         errCode = DeleteInfoByIdInDb(cmd, to_string(id));
341     }
342     return errCode;
343 }
344 
SetDirValuesByPath(ValuesBucket & values,const string & path,int32_t parentId)345 int32_t SetDirValuesByPath(ValuesBucket &values, const string &path, int32_t parentId)
346 {
347     string title = MediaFileUtils::GetFileName(path);
348     if (MediaFileUtils::CheckDentryName(title) < 0) {
349         MEDIA_ERR_LOG("Check display name failed!");
350         return E_INVALID_DISPLAY_NAME;
351     }
352 
353     string relativePath;
354     string parentPath = MediaFileUtils::GetParentPath(path);
355     if (parentPath.length() > ROOT_MEDIA_DIR.length()) {
356         relativePath = parentPath.substr(ROOT_MEDIA_DIR.length()) + "/";
357     }
358 
359     values.PutString(MEDIA_DATA_DB_FILE_PATH, path);
360     values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath);
361     values.PutString(MEDIA_DATA_DB_TITLE, title);
362     values.PutString(MEDIA_DATA_DB_NAME, title);
363     values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, MediaType::MEDIA_TYPE_ALBUM);
364     values.PutInt(MEDIA_DATA_DB_PARENT_ID, parentId);
365     values.PutLong(MEDIA_DATA_DB_DATE_ADDED, MediaFileUtils::UTCTimeMilliSeconds());
366 
367     struct stat statInfo {};
368     if (stat(path.c_str(), &statInfo) == 0) {
369         values.PutLong(MEDIA_DATA_DB_SIZE, statInfo.st_size);
370         if (statInfo.st_mtime == 0) {
371             values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
372         } else {
373             values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, MediaFileUtils::Timespec2Millisecond(statInfo.st_mtim));
374         }
375     }
376     return E_SUCCESS;
377 }
378 
InsertDirToDbRecursively(const string & dirPath,int64_t & rowId)379 int32_t MediaLibraryObjectUtils::InsertDirToDbRecursively(const string &dirPath, int64_t &rowId)
380 {
381     CHECK_AND_RETURN_RET_LOG(!dirPath.empty(), E_VIOLATION_PARAMETERS, "Input parameter dirPath is empty!");
382 
383     NativeAlbumAsset dirAsset = GetLastDirExistInDb(dirPath);
384     string parentPath = dirAsset.GetAlbumPath();
385     int32_t parentId = dirAsset.GetAlbumId();
386     if ((parentId == 0) && ((parentPath + "/") != ROOT_MEDIA_DIR)) {
387         return E_INVALID_PATH;
388     }
389     vector<int64_t> outIds;
390     rowId = parentId;
391     string path = dirPath;
392     if (path.back() != '/') {
393         path.append("/");
394     }
395     while (parentPath.length() < (path.length() - 1)) {
396         size_t index = path.find("/", parentPath.length() + 1);
397         string currentPath = path.substr(0, index);
398         ValuesBucket values;
399         auto ret = SetDirValuesByPath(values, currentPath, parentId);
400         if (ret == E_INVALID_DISPLAY_NAME) {
401             DeleteRows(outIds);
402         }
403         if (ret != E_SUCCESS) {
404             return ret;
405         }
406 
407         MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ALBUM, OperationType::CREATE, values);
408         rowId = InsertInDb(cmd);
409         if (rowId <= 0) {
410             rowId = parentId;
411             return E_HAS_DB_ERROR;
412         }
413         parentId = rowId;
414         parentPath = currentPath;
415         outIds.push_back(rowId);
416     }
417     return E_SUCCESS;
418 }
419 
CreateDirObj(MediaLibraryCommand & cmd,int64_t & rowId)420 int32_t MediaLibraryObjectUtils::CreateDirObj(MediaLibraryCommand &cmd, int64_t &rowId)
421 {
422     string dirPath;
423     ValueObject valueObject;
424     const ValuesBucket &values = cmd.GetValueBucket();
425     if (values.GetObject(MEDIA_DATA_DB_FILE_PATH, valueObject)) {
426         valueObject.GetString(dirPath);
427     }
428     if (dirPath.empty()) {
429         MEDIA_ERR_LOG("Dir path is empty!");
430         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_INVALID_PATH},
431             {KEY_OPT_TYPE, OptType::CREATE}};
432         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
433         return E_INVALID_PATH;
434     }
435 
436     rowId = GetIdByPathFromDb(dirPath);
437     MEDIA_DEBUG_LOG("dirPath %{private}s id in database is %{private}d", dirPath.c_str(), static_cast<int>(rowId));
438     if ((rowId < 0) || (!MediaFileUtils::IsDirectory(dirPath))) {
439         if ((!MediaFileUtils::CreateDirectory(dirPath)) && (errno != EEXIST)) {
440             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, -errno},
441                 {KEY_OPT_FILE, dirPath}, {KEY_OPT_TYPE, OptType::CREATE}};
442             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
443             return E_FAIL;
444         }
445         auto ret = InsertDirToDbRecursively(dirPath, rowId);
446         if (ret != E_SUCCESS) {
447             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
448                 {KEY_OPT_TYPE, OptType::CREATE}};
449             PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
450         }
451         return ret;
452     }
453     return E_FILE_EXIST;
454 }
455 
InitQueryParentResultSet(int32_t dirId,int32_t & parentIdVal,string & dirVal,shared_ptr<MediaLibraryRdbStore> uniStore)456 int32_t InitQueryParentResultSet(int32_t dirId, int32_t &parentIdVal, string &dirVal,
457     shared_ptr<MediaLibraryRdbStore> uniStore)
458 {
459     if (MediaLibraryObjectUtils::IsColumnValueExist(to_string(dirId), MEDIA_DATA_DB_PARENT_ID)) {
460         return E_SUCCESS;
461     }
462 
463     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
464     cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(dirId));
465     shared_ptr<NativeRdb::ResultSet> queryParentResultSet = uniStore->Query(cmd, {});
466     if (queryParentResultSet == nullptr || queryParentResultSet->GoToNextRow() != NativeRdb::E_OK) {
467         return E_SUCCESS;
468     }
469     int32_t colIndex = 0;
470     queryParentResultSet->GetColumnIndex(MEDIA_DATA_DB_PARENT_ID, colIndex);
471     queryParentResultSet->GetInt(colIndex, parentIdVal);
472     queryParentResultSet->GetColumnIndex(MEDIA_DATA_DB_FILE_PATH, colIndex);
473     queryParentResultSet->GetString(colIndex, dirVal);
474     queryParentResultSet.reset();
475     if (parentIdVal == 0) {
476         return E_SUCCESS;
477     }
478     MEDIA_DEBUG_LOG("dirVal = %{private}s, parentIdVal = %{public}d", dirVal.c_str(), parentIdVal);
479     return E_ERR;
480 }
481 
DeleteEmptyDirsRecursively(int32_t dirId)482 int32_t MediaLibraryObjectUtils::DeleteEmptyDirsRecursively(int32_t dirId)
483 {
484     if (dirId <= 0) {
485         return E_INVALID_FILEID;
486     }
487     shared_ptr<MediaLibraryRdbStore> uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
488     if (uniStore == nullptr) {
489         MEDIA_ERR_LOG("uniStore is nullptr!");
490         return E_HAS_DB_ERROR;
491     }
492 
493     int err = E_ERR;
494     const int32_t MAX_DIR_DEPTH = 15;
495     int depth = 0;
496     while ((depth++ < MAX_DIR_DEPTH) && (dirId > 0)) {
497         int32_t parentIdVal = 0;
498         string dirVal;
499         int32_t state = InitQueryParentResultSet(dirId, parentIdVal, dirVal, uniStore);
500         if (state == E_SUCCESS) {
501             return state;
502         }
503         // Do not delete user created dir
504         if (MediaFileUtils::IsFileExists(dirVal + "/" + ".nofile")) {
505             return E_SUCCESS;
506         }
507         if (!MediaFileUtils::IsDirEmpty(dirVal)) {
508             return E_SUCCESS;
509         }
510 
511         if (!MediaFileUtils::DeleteDir(dirVal)) {
512             MEDIA_ERR_LOG("Delete dir in filesystem failed, errno = %{public}d", errno);
513             err = E_HAS_FS_ERROR;
514             break;
515         }
516         MediaLibraryCommand deleteDirCmd(OperationObject::FILESYSTEM_DIR, OperationType::DELETE);
517         int32_t deletedRows = DeleteInfoByIdInDb(deleteDirCmd, to_string(dirId));
518         if (deletedRows < 0) {
519             MEDIA_ERR_LOG("Delete dir info failed, err: %{public}d", deletedRows);
520             err = deletedRows;
521             break;
522         } else if (deletedRows == 0) {
523             MEDIA_ERR_LOG("Failed to delete dir in db!");
524             return E_HAS_DB_ERROR;
525         }
526         dirId = parentIdVal;
527     }
528     return err;
529 }
530 
InvalidateThumbnail(const string & id,const string & tableName,const string & path)531 void MediaLibraryObjectUtils::InvalidateThumbnail(const string &id, const string &tableName, const string &path)
532 {
533     ThumbnailService::GetInstance()->HasInvalidateThumbnail(id, tableName, path);
534 }
535 
DeleteMisc(const int32_t fileId,const string & filePath,const int32_t parentId)536 int32_t MediaLibraryObjectUtils::DeleteMisc(const int32_t fileId, const string &filePath, const int32_t parentId)
537 {
538     // 1) update parent's modify time
539     string parentPath = MediaFileUtils::GetParentPath(filePath);
540     auto updatedRows = UpdateDateModified(parentPath);
541     if (updatedRows <= 0) {
542         MEDIA_ERR_LOG("Update album date_modified failed, path: %{private}s", parentPath.c_str());
543     }
544     // 2) recursively delete empty parent dirs
545     if (DeleteEmptyDirsRecursively(parentId) != E_SUCCESS) {
546         return E_DELETE_DIR_FAIL;
547     }
548     // 3) delete relative records in smart album
549     MediaLibraryCommand deleteSmartMapCmd(OperationObject::SMART_ALBUM_MAP, OperationType::DELETE);
550     deleteSmartMapCmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUMMAP_DB_CHILD_ASSET_ID, to_string(fileId));
551     return DeleteInfoByIdInDb(deleteSmartMapCmd);
552 }
553 
554 // Restriction: input param cmd MUST have file id in either uri or valuebucket
DeleteFileObj(const shared_ptr<FileAsset> & fileAsset)555 int32_t MediaLibraryObjectUtils::DeleteFileObj(const shared_ptr<FileAsset> &fileAsset)
556 {
557     // delete file in filesystem
558     string filePath = fileAsset->GetPath();
559     if (!MediaFileUtils::DeleteFile(filePath)) {
560         MEDIA_ERR_LOG("Delete file asset failed, errno: %{public}d", errno);
561         return E_HAS_FS_ERROR;
562     }
563 
564     // delete thumbnail
565     int32_t fileId = fileAsset->GetId();
566     InvalidateThumbnail(to_string(fileId));
567 
568     // delete file in db
569     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
570     cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(fileId));
571     int32_t deleteRows = DeleteInfoByIdInDb(cmd);
572     if (deleteRows <= 0) {
573         MEDIA_ERR_LOG("Delete file info in database failed!");
574         return deleteRows;
575     }
576 
577     return DeleteMisc(fileId, filePath, fileAsset->GetParent());
578 }
579 
DeleteInfoRecursively(const shared_ptr<FileAsset> & fileAsset)580 int32_t MediaLibraryObjectUtils::DeleteInfoRecursively(const shared_ptr<FileAsset> &fileAsset)
581 {
582     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
583     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "UniStore is nullptr");
584 
585     string fileId = to_string(fileAsset->GetId());
586     if (fileAsset->GetMediaType() == MEDIA_TYPE_ALBUM) {
587         MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
588         queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_PARENT_ID, fileId);
589         if (fileAsset->GetIsTrash() == NOT_TRASHED) {
590             queryCmd.GetAbsRdbPredicates()->And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
591         } else {
592             queryCmd.GetAbsRdbPredicates()->And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(TRASHED_DIR_CHILD));
593         }
594         vector<string> columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_IS_TRASH };
595         auto result = uniStore->Query(queryCmd, columns);
596         CHECK_AND_RETURN_RET_LOG(result != nullptr, E_DB_FAIL, "Get child assets failed.");
597 
598         while (result->GoToNextRow() == NativeRdb::E_OK) {
599             auto childAsset = make_shared<FileAsset>();
600             childAsset->SetId(GetInt32Val(MEDIA_DATA_DB_ID, result));
601             childAsset->SetMediaType(static_cast<MediaType>(GetInt32Val(MEDIA_DATA_DB_MEDIA_TYPE, result)));
602             childAsset->SetIsTrash(GetInt32Val(MEDIA_DATA_DB_IS_TRASH, result));
603             auto ret = DeleteInfoRecursively(childAsset);
604             CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret,
605                 "Delete file info in database failed, file_id: %{public}d, ret: %{public}d", childAsset->GetId(), ret);
606         }
607     }
608 
609     InvalidateThumbnail(fileId);
610     MediaLibraryCommand deleteCmd(Uri(MEDIALIBRARY_DATA_URI), OperationType::DELETE);
611     int32_t deleteRows = MediaLibraryObjectUtils::DeleteInfoByIdInDb(deleteCmd, fileId);
612     if (deleteRows <= 0) {
613         MEDIA_ERR_LOG("Delete file info in database failed, file_id: %{private}s", fileId.c_str());
614         return E_DB_FAIL;
615     }
616     return E_SUCCESS;
617 }
618 
DeleteDirObj(const shared_ptr<FileAsset> & dirAsset)619 int32_t MediaLibraryObjectUtils::DeleteDirObj(const shared_ptr<FileAsset> &dirAsset)
620 {
621     // delete dir in filesystem
622     string dirPath = dirAsset->GetPath();
623     if (!MediaFileUtils::DeleteDir(dirPath)) {
624         MEDIA_ERR_LOG("Delete album asset failed, errno: %{public}d", errno);
625         return E_HAS_FS_ERROR;
626     }
627 
628     // delete dir and children in db
629     auto ret = DeleteInfoRecursively(dirAsset);
630     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret,
631         "Delete file info in database failed, file_id: %{public}d, ret: %{public}d", dirAsset->GetId(), ret);
632 
633     return DeleteMisc(dirAsset->GetId(), dirPath, dirAsset->GetParent());
634 }
635 
636 // Restriction: input param cmd MUST have id in uri
RenameFileObj(MediaLibraryCommand & cmd,const string & srcFilePath,const string & dstFilePath)637 int32_t MediaLibraryObjectUtils::RenameFileObj(MediaLibraryCommand &cmd,
638     const string &srcFilePath, const string &dstFilePath)
639 {
640     if (srcFilePath.empty() || dstFilePath.empty()) {
641         MEDIA_ERR_LOG("srcFilePath or dstFilePath is empty, rename failed!");
642         return E_INVALID_PATH;
643     }
644     if (srcFilePath.compare(dstFilePath) == 0) {
645         MEDIA_DEBUG_LOG("Skip modify the file, the path of new file is the same as old");
646         return E_SUCCESS;
647     }
648     auto errCode = CheckDirExtension(dstFilePath);
649     CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS, errCode, "CreateFileAsset: check file asset failed");
650     if (errCode != E_SUCCESS) {
651         return errCode;
652     }
653 
654     string dstAlbumPath = MediaFileUtils::GetParentPath(dstFilePath);
655     NativeAlbumAsset dirAsset = GetDirAsset(dstAlbumPath);
656     if (dirAsset.GetAlbumId() <= 0) {
657         MEDIA_ERR_LOG("Failed to get or create directory");
658         return dirAsset.GetAlbumId();
659     }
660 
661     errCode = MediaFileUtils::ModifyAsset(srcFilePath, dstFilePath);
662     if (errCode != E_SUCCESS) {
663         if (errCode != E_FILE_EXIST) {
664             MEDIA_ERR_LOG("Failed to modify the file in the device, errCode = %{public}d", errCode);
665         }
666         return errCode;
667     }
668     InvalidateThumbnail(cmd.GetOprnFileId());
669     string dstFileName = MediaFileUtils::GetFileName(dstFilePath);
670     if ((ProcessNoMediaFile(dstFileName, dstAlbumPath) == E_SUCCESS) ||
671         (ProcessHiddenFile(dstFileName, srcFilePath) == E_SUCCESS)) {
672         MEDIA_ERR_LOG("New file is a .nomedia file or hidden file.");
673         // why: return fail insteal of success
674         return E_FAIL;
675     }
676 
677     auto ret = UpdateFileInfoInDb(cmd, dstFilePath, dirAsset.GetAlbumId(), dirAsset.GetAlbumName());
678     if (ret > 0) {
679         UpdateDateModified(dstAlbumPath);
680         string srcAlbumPath = MediaFileUtils::GetParentPath(srcFilePath);
681         UpdateDateModified(srcAlbumPath);
682     }
683     return ret;
684 }
685 
686 // Restriction: input param cmd MUST have id in uri
RenameDirObj(MediaLibraryCommand & cmd,const string & srcDirPath,const string & dstDirPath)687 int32_t MediaLibraryObjectUtils::RenameDirObj(MediaLibraryCommand &cmd,
688     const string &srcDirPath, const string &dstDirPath)
689 {
690     MEDIA_DEBUG_LOG("enter, srcDirPath = %{private}s, dstDirPath = %{private}s",
691         srcDirPath.c_str(), dstDirPath.c_str());
692     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
693     if (uniStore == nullptr) {
694         MEDIA_ERR_LOG("uniStore is nullptr!");
695         return E_HAS_DB_ERROR;
696     }
697 
698     if (srcDirPath.empty() || dstDirPath.empty()) {
699         MEDIA_ERR_LOG("srcDirPath or dstDirPath is empty, rename failed!");
700         return E_INVALID_PATH;
701     }
702     if (!MediaFileUtils::RenameDir(srcDirPath, dstDirPath)) {
703         MEDIA_ERR_LOG("Rename directory failed!");
704         return E_HAS_FS_ERROR;
705     }
706     string dstDirName = MediaFileUtils::GetFileName(dstDirPath);
707     if (ProcessHiddenDir(dstDirName, srcDirPath) == E_SUCCESS) {
708         MEDIA_ERR_LOG("New album is a hidden album.");
709         return E_SUCCESS;
710     }
711 
712     ValuesBucket &values = cmd.GetValueBucket();
713     values.PutString(Media::MEDIA_DATA_DB_RELATIVE_PATH, MediaFileUtils::GetParentPath(dstDirPath));
714     values.PutString(Media::MEDIA_DATA_DB_FILE_PATH, dstDirPath);
715     values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, MediaFileUtils::GetAlbumDateModified(dstDirPath));
716     int32_t retVal = ModifyInfoByIdInDb(cmd);
717     if (retVal <= 0) {
718         return retVal;
719     }
720 
721     // Update the path, relative path and album Name for internal files
722     const string modifyAlbumInternalsStmt =
723         "UPDATE " + MEDIALIBRARY_TABLE + " SET " + MEDIA_DATA_DB_FILE_PATH + " = replace(" +
724         MEDIA_DATA_DB_FILE_PATH + ", '" + srcDirPath + "/' , '" + dstDirPath + "/'), " +
725         MEDIA_DATA_DB_RELATIVE_PATH + " = replace(" + MEDIA_DATA_DB_RELATIVE_PATH + ", '" + srcDirPath + "', '" +
726         dstDirPath + "'), " + MEDIA_DATA_DB_ALBUM_NAME + " = replace(" + MEDIA_DATA_DB_ALBUM_NAME + ", '" +
727         MediaFileUtils::GetFileName(srcDirPath) + "', '" + dstDirName + "')" + "where " +
728         MEDIA_DATA_DB_FILE_PATH + " LIKE '" + srcDirPath + "/%'";
729     if (uniStore->ExecuteSql(modifyAlbumInternalsStmt) != NativeRdb::E_OK) {
730         MEDIA_ERR_LOG("Album update sql failed");
731         return E_HAS_DB_ERROR;
732     }
733     return E_SUCCESS;
734 }
735 
OpenAsset(const string & filePath,const string & mode,const string & fileId)736 static int32_t OpenAsset(const string &filePath, const string &mode, const string &fileId)
737 {
738     MediaLibraryTracer tracer;
739     tracer.Start("OpenAsset");
740 
741     string absFilePath;
742     if (!PathToRealPath(filePath, absFilePath)) {
743         MEDIA_ERR_LOG("Failed to get real path: %{private}s", filePath.c_str());
744         return E_ERR;
745     }
746     MEDIA_DEBUG_LOG("File absFilePath is %{private}s", absFilePath.c_str());
747 
748     return MediaPrivacyManager(absFilePath, mode, fileId).Open();
749 }
750 
CheckIsOwner(const string & bundleName)751 static bool CheckIsOwner(const string &bundleName)
752 {
753     string clientBundle = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
754     if (strcmp(bundleName.c_str(), clientBundle.c_str()) == 0) {
755         return true;
756     }
757     return false;
758 }
759 
OpenDocument(const string & uri,const string & mode)760 static int32_t OpenDocument(const string &uri, const string &mode)
761 {
762     static constexpr uint32_t BASE_USER_RANGE = 200000;
763     uid_t uid = getuid() / BASE_USER_RANGE;
764     string realPath;
765     int32_t ret = AppFileService::SandboxHelper::GetPhysicalPath(uri, to_string(uid), realPath);
766     if (ret != E_OK || !AppFileService::SandboxHelper::CheckValidPath(realPath)) {
767         MEDIA_ERR_LOG("file not exist, uri=%{private}s, realPath=%{private}s",
768                       uri.c_str(), realPath.c_str());
769         return E_INVALID_URI;
770     }
771     return MediaFileUtils::OpenFile(realPath, mode);
772 }
773 
IsDocumentUri(const std::string & uriString)774 static bool IsDocumentUri(const std::string &uriString)
775 {
776     Uri uri(uriString);
777     return uri.GetAuthority() == DOCUMENT_URI_AUTHORITY;
778 }
779 
OpenFile(MediaLibraryCommand & cmd,const string & mode)780 int32_t MediaLibraryObjectUtils::OpenFile(MediaLibraryCommand &cmd, const string &mode)
781 {
782     MediaLibraryTracer tracer;
783     tracer.Start("MediaLibraryObjectUtils::OpenFile");
784 
785     string uriString = cmd.GetUri().ToString();
786     MEDIA_DEBUG_LOG("MediaLibraryObjectUtils OpenFile uriString:%{public}s", uriString.c_str());
787     if (cmd.GetOprnObject() == OperationObject::THUMBNAIL) {
788         return ThumbnailService::GetInstance()->GetThumbnailFd(uriString);
789     } else if (cmd.GetOprnObject() == OperationObject::THUMBNAIL_ASTC) {
790         return ThumbnailService::GetInstance()->GetThumbnailFd(uriString, true);
791     } else if (cmd.GetOprnObject() == OperationObject::REQUEST_PICTURE) {
792         std::string fileId = cmd.GetQuerySetParam(MediaColumn::MEDIA_ID);
793         int32_t fd;
794         PictureHandlerService::OpenPicture(fileId, fd);
795         return fd;
796     } else if (cmd.GetOprnObject() == OperationObject::PHOTO_REQUEST_PICTURE_BUFFER) {
797         std::string fd = cmd.GetQuerySetParam("fd");
798         return PictureHandlerService::RequestBufferHandlerFd(fd);
799     } else if (IsDocumentUri(uriString)) {
800         return OpenDocument(uriString, mode);
801     }
802 
803     shared_ptr<FileAsset> fileAsset = GetFileAssetFromUri(uriString);
804     if (fileAsset == nullptr) {
805         MEDIA_ERR_LOG("Failed to obtain path from Database");
806         return E_INVALID_URI;
807     }
808 
809     if (fileAsset->GetTimePending() != 0) {
810         if (!CheckIsOwner(fileAsset->GetOwnerPackage().c_str())) {
811             MEDIA_ERR_LOG("Failed to open fileId:%{public}d, it is not owner", fileAsset->GetId());
812             return E_IS_PENDING_ERROR;
813         }
814     }
815 
816     string path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
817     string fileId = MediaFileUtils::GetIdFromUri(fileAsset->GetUri());
818     int32_t fd = OpenAsset(path, mode, fileId);
819     if (fd < 0) {
820         MEDIA_ERR_LOG("open file fd %{private}d, errno %{private}d", fd, errno);
821         return E_HAS_FS_ERROR;
822     }
823 
824     if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos) {
825         auto watch = MediaLibraryInotify::GetInstance();
826         if (watch != nullptr) {
827             MEDIA_INFO_LOG("enter inotify, path = %{public}s, fileId = %{public}d",
828                 DfxUtils::GetSafePath(path).c_str(), fileAsset->GetId());
829             watch->AddWatchList(path, fileAsset->GetUri());
830         }
831     }
832     MEDIA_DEBUG_LOG("MediaLibraryDataManager OpenFile: Success");
833     return fd;
834 }
835 
ScanFileAsync(const string & path,const string & id,MediaLibraryApi api)836 void MediaLibraryObjectUtils::ScanFileAsync(const string &path, const string &id, MediaLibraryApi api)
837 {
838     string tableName;
839     if (MediaFileUtils::IsFileTablePath(path)) {
840         tableName = MEDIALIBRARY_TABLE;
841     } else if (MediaFileUtils::IsPhotoTablePath(path)) {
842         tableName = PhotoColumn::PHOTOS_TABLE;
843     } else {
844         tableName = AudioColumn::AUDIOS_TABLE;
845     }
846 
847     InvalidateThumbnail(id, tableName);
848 
849     shared_ptr<ScanFileCallback> scanFileCb = make_shared<ScanFileCallback>();
850     if (scanFileCb == nullptr) {
851         MEDIA_ERR_LOG("Failed to create scan file callback object");
852         return ;
853     }
854     int ret = MediaScannerManager::GetInstance()->ScanFile(path, scanFileCb, api);
855     if (ret != 0) {
856         MEDIA_ERR_LOG("Scan file failed!");
857     }
858 }
859 
ScanFileSyncWithoutAlbumUpdate(const string & path,const string & id,MediaLibraryApi api)860 void MediaLibraryObjectUtils::ScanFileSyncWithoutAlbumUpdate(const string &path, const string &id, MediaLibraryApi api)
861 {
862     string tableName;
863     if (MediaFileUtils::IsFileTablePath(path)) {
864         tableName = MEDIALIBRARY_TABLE;
865     } else if (MediaFileUtils::IsPhotoTablePath(path)) {
866         tableName = PhotoColumn::PHOTOS_TABLE;
867     } else {
868         tableName = AudioColumn::AUDIOS_TABLE;
869     }
870 
871     InvalidateThumbnail(id, tableName);
872 
873     shared_ptr<ScanFileCallback> scanFileCb = make_shared<ScanFileCallback>();
874     if (scanFileCb == nullptr) {
875         MEDIA_ERR_LOG("Failed to create scan file callback object");
876         return ;
877     }
878     int ret = MediaScannerManager::GetInstance()->ScanFileSyncWithoutAlbumUpdate(path, scanFileCb, api, true);
879     if (ret != 0) {
880         MEDIA_ERR_LOG("Scan file failed!");
881     }
882 }
883 
CloseFile(MediaLibraryCommand & cmd)884 int32_t MediaLibraryObjectUtils::CloseFile(MediaLibraryCommand &cmd)
885 {
886     string strFileId = cmd.GetOprnFileId();
887     if (strFileId.empty()) {
888         MEDIA_ERR_LOG("Get id from uri or valuesBucket failed!");
889         return E_INVALID_FILEID;
890     }
891 
892     auto fileAsset = GetFileAssetFromId(strFileId);
893     if (fileAsset == nullptr) {
894         MEDIA_ERR_LOG("Get fileAsset from database fail!");
895         return E_INVALID_FILEID;
896     }
897     string srcPath = fileAsset->GetPath();
898     string fileName = MediaFileUtils::GetFileName(srcPath);
899     if ((fileName.length() != 0) && (fileName.at(0) != '.')) {
900         string dirPath = MediaFileUtils::GetParentPath(srcPath);
901         UpdateDateModified(dirPath);
902     }
903 
904     // remove inotify event since there is close cmd
905     auto watch = MediaLibraryInotify::GetInstance();
906     if (watch != nullptr) {
907         watch->RemoveByFileUri(fileAsset->GetUri());
908     }
909     InvalidateThumbnail(strFileId);
910     ScanFile(srcPath);
911     return E_SUCCESS;
912 }
913 
ScanFile(const string & path,MediaLibraryApi api)914 void MediaLibraryObjectUtils::ScanFile(const string &path, MediaLibraryApi api)
915 {
916     MEDIA_DEBUG_LOG("enter, path = %{private}s, api = %{public}d", path.c_str(), static_cast<int>(api));
917     shared_ptr<ScanFileCallback> scanFileCb = make_shared<ScanFileCallback>();
918     if (scanFileCb == nullptr) {
919         MEDIA_ERR_LOG("Failed to create scan file callback object");
920         return ;
921     }
922     int ret = MediaScannerManager::GetInstance()->ScanFileSync(path, scanFileCb, api);
923     if (ret != 0) {
924         MEDIA_ERR_LOG("Scan file failed!");
925     }
926 }
927 
ProcessNoMediaFile(const string & dstFileName,const string & dstAlbumPath)928 int32_t MediaLibraryObjectUtils::ProcessNoMediaFile(const string &dstFileName, const string &dstAlbumPath)
929 {
930     MEDIA_DEBUG_LOG("enter, dstFileName = %{private}s, dstAlbumPath = %{private}s",
931         dstFileName.c_str(), dstAlbumPath.c_str());
932     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
933     if (uniStore == nullptr) {
934         MEDIA_ERR_LOG("uniStore is nullptr!");
935         return E_HAS_DB_ERROR;
936     }
937 
938     if (dstFileName.empty() || dstAlbumPath.empty() || dstFileName != NO_MEDIA_TAG) {
939         MEDIA_INFO_LOG("Not a .nomedia file, no need to do anything.");
940         return E_INVALID_ARGUMENTS;
941     }
942 
943     // the whole folder containing .nomedia file is invisible in database
944     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
945     string dstAlbumPathPrefix = dstAlbumPath.back() != '/' ? (dstAlbumPath + "/") : dstAlbumPath;
946     cmd.GetAbsRdbPredicates()->BeginsWith(MEDIA_DATA_DB_FILE_PATH, dstAlbumPathPrefix);
947     cmd.GetAbsRdbPredicates()->Or()->EqualTo(MEDIA_DATA_DB_FILE_PATH, dstAlbumPath);
948 
949     int32_t deletedRows = -1;
950     if (uniStore->Delete(cmd, deletedRows) != NativeRdb::E_OK) {
951         MEDIA_ERR_LOG("Delete rows for the hidden album failed");
952     }
953     return E_SUCCESS;
954 }
955 
ProcessHiddenFile(const string & dstFileName,const string & srcPath)956 int32_t MediaLibraryObjectUtils::ProcessHiddenFile(const string &dstFileName, const string &srcPath)
957 {
958     MEDIA_DEBUG_LOG("enter, dstFileName = %{private}s, srcPath = %{private}s",
959         dstFileName.c_str(), srcPath.c_str());
960     if (dstFileName.empty() || srcPath.empty() || dstFileName.at(0) != '.') {
961         MEDIA_INFO_LOG("Not a hidden file (file name begin with \'.\'), no need to do anything.");
962         return E_INVALID_ARGUMENTS;
963     }
964     MediaLibraryCommand deleteCmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
965     if (DeleteInfoByPathInDb(deleteCmd, srcPath) != E_SUCCESS) {
966         MEDIA_ERR_LOG("Delete rows for the old path failed");
967     }
968     return E_SUCCESS;
969 }
970 
ProcessHiddenDir(const string & dstDirName,const string & srcDirPath)971 int32_t MediaLibraryObjectUtils::ProcessHiddenDir(const string &dstDirName, const string &srcDirPath)
972 {
973     if (dstDirName.empty() || srcDirPath.empty() || dstDirName.at(0) != '.') {
974         MEDIA_INFO_LOG("Not a hidden dir(name begin with \'.\'), no need to do anything.");
975         return E_INVALID_PATH;
976     }
977     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
978     if (uniStore == nullptr) {
979         MEDIA_ERR_LOG("uniStore is nullptr!");
980         return E_HAS_DB_ERROR;
981     }
982 
983     MediaLibraryCommand deleteCmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
984     string dstAlbumPathPrefix = srcDirPath.back() != '/' ? (srcDirPath + "/") : srcDirPath;
985     deleteCmd.GetAbsRdbPredicates()->BeginsWith(MEDIA_DATA_DB_FILE_PATH, dstAlbumPathPrefix);
986     deleteCmd.GetAbsRdbPredicates()->Or()->EqualTo(MEDIA_DATA_DB_FILE_PATH, srcDirPath);
987 
988     int32_t deletedRows = -1;
989     if (uniStore->Delete(deleteCmd, deletedRows) != NativeRdb::E_OK) {
990         MEDIA_ERR_LOG("Delete src dir in database failed!");
991         return E_HAS_DB_ERROR;
992     }
993     return E_SUCCESS;
994 }
995 
UpdateDateModified(const string & dirPath)996 int32_t MediaLibraryObjectUtils::UpdateDateModified(const string &dirPath)
997 {
998     if (dirPath.empty()) {
999         MEDIA_ERR_LOG("Path is empty, update failed!");
1000         return E_INVALID_PATH;
1001     }
1002 
1003     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE);
1004     ValuesBucket valuesBucket;
1005     int64_t dateModified = MediaFileUtils::GetAlbumDateModified(dirPath);
1006 #ifdef MEDIALIBRARY_COMPATIBILITY
1007     if (dateModified == 0) {
1008         return 0;
1009     }
1010 #endif
1011     valuesBucket.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, dateModified);
1012 
1013     cmd.SetValueBucket(valuesBucket);
1014 
1015     return ModifyInfoByPathInDb(cmd, dirPath);
1016 }
1017 
GetFileAssetByPredicates(const NativeRdb::AbsRdbPredicates & predicates,const vector<string> & columns)1018 unique_ptr<FileAsset> MediaLibraryObjectUtils::GetFileAssetByPredicates(const NativeRdb::AbsRdbPredicates &predicates,
1019     const vector<string> &columns)
1020 {
1021     auto absResultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
1022     if (absResultSet == nullptr) {
1023         return nullptr;
1024     }
1025     auto resultSetBridge = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(absResultSet);
1026     auto resultSet = make_shared<DataShare::DataShareResultSet>(resultSetBridge);
1027     auto fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
1028     return fetchResult->GetFirstObject();
1029 }
1030 
GetFileAssetFromId(const string & id,const string & networkId)1031 shared_ptr<FileAsset> MediaLibraryObjectUtils::GetFileAssetFromId(const string &id, const string &networkId)
1032 {
1033     if ((id.empty()) || (!MediaLibraryDataManagerUtils::IsNumber(id)) || (stoi(id) == -1)) {
1034         MEDIA_ERR_LOG("Id for the path is incorrect: %{private}s", id.c_str());
1035         return nullptr;
1036     }
1037 
1038     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY, networkId);
1039     cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, id);
1040 
1041     auto resultSet = QueryWithCondition(cmd, {});
1042     if (resultSet == nullptr) {
1043         MEDIA_ERR_LOG("Failed to obtain file asset from database");
1044         return nullptr;
1045     }
1046 
1047     shared_ptr<FetchResult<FileAsset>> fetchFileResult = make_shared<FetchResult<FileAsset>>();
1048     if (fetchFileResult == nullptr) {
1049         MEDIA_ERR_LOG("Failed to obtain fetch file result");
1050         return nullptr;
1051     }
1052     fetchFileResult->SetNetworkId(networkId);
1053     return fetchFileResult->GetObjectFromRdb(resultSet, 0);
1054 }
1055 
GetFileAssetFromUri(const string & uriStr)1056 shared_ptr<FileAsset> MediaLibraryObjectUtils::GetFileAssetFromUri(const string &uriStr)
1057 {
1058     string id = MediaFileUtils::GetIdFromUri(uriStr);
1059     string networkId = MediaFileUtils::GetNetworkIdFromUri(uriStr);
1060 
1061     return GetFileAssetFromId(id, networkId);
1062 }
1063 
GetDefaultRelativePath(const int32_t mediaType,string & relativePath)1064 void MediaLibraryObjectUtils::GetDefaultRelativePath(const int32_t mediaType, string &relativePath)
1065 {
1066     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_DIR, OperationType::QUERY);
1067     cmd.GetAbsRdbPredicates()->EqualTo(DIRECTORY_DB_MEDIA_TYPE, to_string(mediaType));
1068 
1069     auto resultSet = QueryWithCondition(cmd, {});
1070     if (resultSet == nullptr) {
1071         MEDIA_ERR_LOG("Failed to obtain file asset from database, mediaType: %{public}d", static_cast<int>(mediaType));
1072         return;
1073     }
1074 
1075     if (resultSet->GoToFirstRow() == NativeRdb::E_OK) {
1076         relativePath = get<string>(ResultSetUtils::GetValFromColumn(DIRECTORY_DB_DIRECTORY, resultSet, TYPE_STRING));
1077     }
1078 }
1079 
GetRelativePathFromFilePath(const string & path)1080 string GetRelativePathFromFilePath(const string &path)
1081 {
1082     string relativePath;
1083     if (path.length() > ROOT_MEDIA_DIR.length()) {
1084         relativePath = path.substr(ROOT_MEDIA_DIR.length());
1085     }
1086     size_t pos = relativePath.rfind('/');
1087     if (pos != string::npos) {
1088         relativePath = relativePath.substr(0, pos + 1);
1089     }
1090     return relativePath;
1091 }
1092 
UpdateFileInfoInDb(MediaLibraryCommand & cmd,const string & dstPath,const int32_t & bucketId,const string & bucketName)1093 int32_t MediaLibraryObjectUtils::UpdateFileInfoInDb(MediaLibraryCommand &cmd, const string &dstPath,
1094     const int32_t &bucketId, const string &bucketName)
1095 {
1096     MEDIA_DEBUG_LOG("enter, dstPath: %{private}s,", dstPath.c_str());
1097     if (dstPath.empty()) {
1098         MEDIA_ERR_LOG("Input argument is empty.");
1099         return E_INVALID_PATH;
1100     }
1101 
1102     // dispName doesn't be used, maybe forget
1103     size_t found = dstPath.rfind("/");
1104     string dispName;
1105     if (found != string::npos) {
1106         dispName = dstPath.substr(found + 1);
1107     }
1108 
1109     struct stat statInfo;
1110     if (stat(dstPath.c_str(), &statInfo) != 0) {
1111         MEDIA_ERR_LOG("dstPath %{private}s is invalid. Modify failed!", dstPath.c_str());
1112         return E_HAS_FS_ERROR;
1113     }
1114     string fileId = cmd.GetOprnFileId();
1115     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(ScannerUtils::GetFileExtension(dstPath));
1116     MediaType mediaType = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1117     string displayName = MediaLibraryDataManagerUtils::GetDisPlayNameFromPath(dstPath);
1118     ValuesBucket values;
1119     values.PutString(MEDIA_DATA_DB_NAME, displayName);
1120     values.PutString(MEDIA_DATA_DB_TITLE, MediaFileUtils::GetTitleFromDisplayName(displayName));
1121     values.PutString(MEDIA_DATA_DB_FILE_PATH, dstPath);
1122     values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, GetRelativePathFromFilePath(dstPath));
1123     values.PutString(MEDIA_DATA_DB_BUCKET_NAME, bucketName);
1124     values.PutString(MEDIA_DATA_DB_MIME_TYPE, mimeType);
1125     values.PutString(MEDIA_DATA_DB_URI, MediaFileUtils::GetMediaTypeUri(mediaType));
1126     values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
1127     values.PutInt(MEDIA_DATA_DB_BUCKET_ID, bucketId);
1128     values.PutInt(MEDIA_DATA_DB_PARENT_ID, bucketId);
1129     cmd.SetValueBucket(values);
1130 
1131     return ModifyInfoByIdInDb(cmd, fileId);
1132 }
1133 
GetPathByIdFromDb(const string & id,const bool isDelete)1134 string MediaLibraryObjectUtils::GetPathByIdFromDb(const string &id, const bool isDelete)
1135 {
1136     return GetStringColumnByIdFromDb(id, MEDIA_DATA_DB_FILE_PATH, isDelete);
1137 }
1138 
GetStringColumnByIdFromDb(const string & id,const string & column,const bool isDelete)1139 string MediaLibraryObjectUtils::GetStringColumnByIdFromDb(const string &id, const string &column, const bool isDelete)
1140 {
1141     string value;
1142     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1143     if (uniStore == nullptr) {
1144         MEDIA_ERR_LOG("uniStore is nullptr!");
1145         return value;
1146     }
1147 
1148     if ((id.empty()) || (!MediaLibraryDataManagerUtils::IsNumber(id)) || (stoi(id) == -1)) {
1149         MEDIA_ERR_LOG("Id for the path is incorrect or rdbStore is null");
1150         return value;
1151     }
1152 
1153     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1154     if (isDelete) {
1155         cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, id);
1156     } else {
1157         cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, id)->And()->
1158             EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1159     }
1160     vector<string> columns;
1161     columns.push_back(column);
1162 
1163     auto queryResultSet = uniStore->Query(cmd, columns);
1164     CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, value, "Failed to obtain value from database");
1165 
1166     auto ret = queryResultSet->GoToFirstRow();
1167     CHECK_AND_RETURN_RET_LOG(ret == 0, value, "Failed to shift at first row");
1168     int32_t columnIndex = 0;
1169     ret = queryResultSet->GetColumnIndex(column, columnIndex);
1170     CHECK_AND_RETURN_RET_LOG(ret == 0, value, "Failed to obtain column index");
1171 
1172     ret = queryResultSet->GetString(columnIndex, value);
1173     CHECK_AND_RETURN_RET_LOG(ret == 0, value, "Failed to obtain value");
1174 
1175     return value;
1176 }
1177 
GetIdByPathFromDb(const string & path)1178 int32_t MediaLibraryObjectUtils::GetIdByPathFromDb(const string &path)
1179 {
1180     MEDIA_DEBUG_LOG("enter, path = %{private}s", path.c_str());
1181     if (path.empty()) {
1182         return E_INVALID_PATH;
1183     }
1184     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1185     if (uniStore == nullptr) {
1186         MEDIA_ERR_LOG("uniStore is nullptr!");
1187         return E_HAS_DB_ERROR;
1188     }
1189 
1190     int32_t columnIndex = 0;
1191     string newPath = path;
1192     if (newPath.back() == '/') {
1193         newPath.pop_back();
1194     }
1195     int32_t fileId = E_INVALID_FILEID;
1196 
1197     vector<string> columns;
1198     columns.push_back(MEDIA_DATA_DB_ID);
1199 
1200     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1201     cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, newPath)->And()->
1202         EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1203     auto queryResultSet = uniStore->Query(cmd, columns);
1204     CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, fileId, "Failed to obtain path from database");
1205 
1206     auto ret = queryResultSet->GoToFirstRow();
1207     CHECK_AND_RETURN_RET(ret == 0, fileId);
1208 
1209     ret = queryResultSet->GetColumnIndex(MEDIA_DATA_DB_ID, columnIndex);
1210     CHECK_AND_RETURN_RET_LOG(ret == 0, fileId, "Failed to obtain column index");
1211 
1212     ret = queryResultSet->GetInt(columnIndex, fileId);
1213     CHECK_AND_RETURN_RET_LOG(ret == 0, fileId, "Failed to obtain file id");
1214 
1215     return fileId;
1216 }
1217 
InsertInDb(MediaLibraryCommand & cmd)1218 int32_t MediaLibraryObjectUtils::InsertInDb(MediaLibraryCommand &cmd)
1219 {
1220     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1221     if (uniStore == nullptr) {
1222         MEDIA_ERR_LOG("uniStore is nullptr!");
1223         return E_HAS_DB_ERROR;
1224     }
1225 
1226     int64_t outRowId = E_HAS_DB_ERROR;
1227     int32_t result = uniStore->Insert(cmd, outRowId);
1228     if (result != NativeRdb::E_OK) {
1229         MEDIA_ERR_LOG("Insert operation failed. Result %{public}d. Deleted %{public}d",
1230             result, static_cast<int32_t>(outRowId));
1231         return E_HAS_DB_ERROR;
1232     }
1233     return static_cast<int32_t>(outRowId);
1234 }
1235 
DeleteInfoByPathInDb(MediaLibraryCommand & cmd,const string & path)1236 int32_t MediaLibraryObjectUtils::DeleteInfoByPathInDb(MediaLibraryCommand &cmd, const string &path)
1237 {
1238     MEDIA_DEBUG_LOG("enter, path = %{private}s", path.c_str());
1239     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1240     if (uniStore == nullptr) {
1241         MEDIA_ERR_LOG("uniStore is nullptr!");
1242         return E_HAS_DB_ERROR;
1243     }
1244 
1245     int32_t deletedRows = E_HAS_DB_ERROR;
1246     cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, path);
1247     int32_t result = uniStore->Delete(cmd, deletedRows);
1248     if (result != NativeRdb::E_OK) {
1249         MEDIA_ERR_LOG("Delete operation failed. Result %{public}d. Deleted %{public}d", result, deletedRows);
1250         return E_HAS_DB_ERROR;
1251     }
1252 
1253     return E_SUCCESS;
1254 }
1255 
DeleteInfoByIdInDb(MediaLibraryCommand & cmd,const string & fileId)1256 int32_t MediaLibraryObjectUtils::DeleteInfoByIdInDb(MediaLibraryCommand &cmd, const string &fileId)
1257 {
1258     MEDIA_DEBUG_LOG("enter, fileId = %{private}s", fileId.c_str());
1259     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1260     if (uniStore == nullptr) {
1261         MEDIA_ERR_LOG("uniStore is nullptr!");
1262         return E_HAS_DB_ERROR;
1263     }
1264 
1265     string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1266     if (strDeleteCondition.empty()) {
1267         string strRow = fileId.empty() ? cmd.GetOprnFileId() : fileId;
1268         if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow)) {
1269             MEDIA_ERR_LOG("MediaLibraryObjectUtils DeleteFile: Index not digit");
1270             return E_INVALID_FILEID;
1271         }
1272         cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, strRow);
1273     }
1274 
1275     int32_t deletedRows = E_HAS_DB_ERROR;
1276     int32_t result = uniStore->Delete(cmd, deletedRows);
1277     if (result != NativeRdb::E_OK) {
1278         MEDIA_ERR_LOG("Delete operation failed. Result %{public}d. Deleted %{public}d", result, deletedRows);
1279     }
1280 
1281     return deletedRows;
1282 }
1283 
ModifyInfoByPathInDb(MediaLibraryCommand & cmd,const string & path)1284 int32_t MediaLibraryObjectUtils::ModifyInfoByPathInDb(MediaLibraryCommand &cmd, const string &path)
1285 {
1286     MEDIA_DEBUG_LOG("enter, path = %{private}s", path.c_str());
1287     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1288     if (uniStore == nullptr) {
1289         MEDIA_ERR_LOG("uniStore is nullptr!");
1290         return E_HAS_DB_ERROR;
1291     }
1292 
1293     cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, path);
1294     int32_t updatedRows = E_HAS_DB_ERROR;
1295     int32_t result = uniStore->Update(cmd, updatedRows);
1296     if (result != NativeRdb::E_OK || updatedRows <= 0) {
1297         MEDIA_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updatedRows);
1298     }
1299 
1300     return updatedRows;
1301 }
1302 
ModifyInfoByIdInDb(MediaLibraryCommand & cmd,const string & fileId)1303 int32_t MediaLibraryObjectUtils::ModifyInfoByIdInDb(MediaLibraryCommand &cmd, const string &fileId)
1304 {
1305     MEDIA_DEBUG_LOG("enter, fileId = %{private}s", fileId.c_str());
1306     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1307     if (uniStore == nullptr) {
1308         MEDIA_ERR_LOG("uniStore is nullptr!");
1309         return E_HAS_DB_ERROR;
1310     }
1311 
1312     string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1313     if (strDeleteCondition.empty()) {
1314         string strRow = fileId.empty() ? cmd.GetOprnFileId() : fileId;
1315         if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow) || (stoi(strRow) == -1)) {
1316             MEDIA_ERR_LOG("DeleteFile: Index not digit");
1317             return E_INVALID_FILEID;
1318         }
1319         cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, strRow);
1320     }
1321 
1322     int32_t updatedRows = E_HAS_DB_ERROR;
1323     int32_t result = uniStore->Update(cmd, updatedRows);
1324     if (result != NativeRdb::E_OK || updatedRows <= 0) {
1325         MEDIA_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updatedRows);
1326     }
1327 
1328     return updatedRows;
1329 }
1330 
QueryWithCondition(MediaLibraryCommand & cmd,const vector<string> & columns,const string & conditionColumn)1331 shared_ptr<ResultSet> MediaLibraryObjectUtils::QueryWithCondition(MediaLibraryCommand &cmd,
1332     const vector<string> &columns, const string &conditionColumn)
1333 {
1334     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1335     if (uniStore == nullptr) {
1336         MEDIA_ERR_LOG("uniStore is nullptr!");
1337         return nullptr;
1338     }
1339 
1340     string strQueryCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1341     if (strQueryCondition.empty()) {
1342         if (conditionColumn.empty()) {
1343             return uniStore->QuerySql("SELECT * FROM " + cmd.GetTableName());
1344         }
1345         string strFileId = cmd.GetOprnFileId();
1346         if (strFileId.empty()) {
1347             MEDIA_ERR_LOG("Get file id from uri or valuebucket failed!");
1348             return nullptr;
1349         }
1350         cmd.GetAbsRdbPredicates()->EqualTo(conditionColumn, strFileId);
1351     }
1352 
1353     return uniStore->Query(cmd, columns);
1354 }
1355 
IsColumnValueExist(const string & value,const string & column)1356 bool MediaLibraryObjectUtils::IsColumnValueExist(const string &value, const string &column)
1357 {
1358     if (column.empty()) {
1359         MEDIA_ERR_LOG("Empty column param");
1360         return false;
1361     }
1362     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1363     if (uniStore == nullptr) {
1364         MEDIA_ERR_LOG("uniStore is nullptr!");
1365         return false;
1366     }
1367 
1368     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1369     cmd.GetAbsRdbPredicates()->EqualTo(column, value);
1370     vector<string> columns;
1371     columns.push_back(column);
1372     auto queryResultSet = uniStore->Query(cmd, columns);
1373     if (queryResultSet != nullptr) {
1374         int32_t count = 0;
1375         queryResultSet->GetRowCount(count);
1376         if (count > 0) {
1377             return true;
1378         }
1379     }
1380     return false;
1381 }
1382 
IsAssetExistInDb(const int32_t id,const bool isIncludeTrash)1383 bool MediaLibraryObjectUtils::IsAssetExistInDb(const int32_t id, const bool isIncludeTrash)
1384 {
1385     if (id <= 0) {
1386         MEDIA_ERR_LOG("Invalid id param");
1387         return false;
1388     }
1389     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1390     if (isIncludeTrash) {
1391         cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(id));
1392     } else {
1393         cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(id))->And()->
1394             EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1395     }
1396     vector<string> columns;
1397     auto queryResultSet = QueryWithCondition(cmd, columns);
1398     if (queryResultSet != nullptr && queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1399         return true;
1400     }
1401     return false;
1402 }
1403 
IsFileExistInDb(const string & path)1404 bool MediaLibraryObjectUtils::IsFileExistInDb(const string &path)
1405 {
1406     if (path.empty()) {
1407         MEDIA_ERR_LOG("path is incorrect");
1408         return false;
1409     }
1410 
1411     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1412     cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, path)
1413         ->And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1414 
1415     vector<string> columns;
1416     columns.push_back(MEDIA_DATA_DB_FILE_PATH);
1417     auto queryResultSet = QueryWithCondition(cmd, columns);
1418     if (queryResultSet != nullptr && queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1419         return true;
1420     }
1421 
1422     return false;
1423 }
1424 
CheckUriPending(const std::string & uri)1425 bool MediaLibraryObjectUtils::CheckUriPending(const std::string &uri)
1426 {
1427     if (!uri.empty()) {
1428         size_t positon = uri.find_first_of('?');
1429         string tempUri = uri.substr(0, positon);
1430         auto fileAsset = GetFileAssetFromUri(tempUri);
1431         if ((fileAsset != nullptr) && (fileAsset->GetTimePending() != 0)) {
1432             return true;
1433         }
1434     }
1435     return false;
1436 }
1437 
CopyAsset(const shared_ptr<FileAsset> & srcFileAsset,const string & relativePath)1438 int32_t MediaLibraryObjectUtils::CopyAsset(const shared_ptr<FileAsset> &srcFileAsset,
1439     const string &relativePath)
1440 {
1441     if (srcFileAsset == nullptr) {
1442         MEDIA_ERR_LOG("Failed to obtain path from Database");
1443         return E_INVALID_URI;
1444     }
1445     string srcPath = MediaFileUtils::UpdatePath(srcFileAsset->GetPath(), srcFileAsset->GetUri());
1446     string fileId = MediaFileUtils::GetIdFromUri(srcFileAsset->GetUri());
1447     int32_t srcFd = OpenAsset(srcPath, MEDIA_FILEMODE_READWRITE, fileId);
1448     // dest asset
1449     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::CREATE);
1450     ValuesBucket values;
1451     values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath);
1452     string displayName = srcFileAsset->GetDisplayName();
1453     values.PutString(MEDIA_DATA_DB_NAME, displayName);
1454     values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, srcFileAsset->GetMediaType());
1455     cmd.SetValueBucket(values);
1456     int32_t outRow = CreateFileObj(cmd);
1457     while (outRow == E_FILE_EXIST) {
1458         displayName = displayName + ASSET_RECYCLE_SUFFIX;
1459         values.PutString(MEDIA_DATA_DB_NAME, displayName);
1460         outRow = CreateFileObj(cmd);
1461     }
1462     if (outRow < 0) {
1463         MEDIA_ERR_LOG("Failed to obtain CreateFileObj");
1464         return outRow;
1465     }
1466     shared_ptr<FileAsset> destFileAsset = GetFileAssetFromId(to_string(outRow));
1467     if (destFileAsset == nullptr) {
1468         MEDIA_ERR_LOG("Failed to obtain path from Database");
1469         return E_INVALID_URI;
1470     }
1471     string destPath = MediaFileUtils::UpdatePath(destFileAsset->GetPath(), destFileAsset->GetUri());
1472     string destFileId = MediaFileUtils::GetIdFromUri(destFileAsset->GetUri());
1473     int32_t destFd = OpenAsset(destPath, MEDIA_FILEMODE_READWRITE, destFileId);
1474     return CopyAssetByFd(srcFd, srcFileAsset->GetId(), destFd, outRow);
1475 }
1476 
CopyAssetByFd(int32_t srcFd,int32_t srcId,int32_t destFd,int32_t destId)1477 int32_t MediaLibraryObjectUtils::CopyAssetByFd(int32_t srcFd, int32_t srcId, int32_t destFd, int32_t destId)
1478 {
1479     struct stat statSrc;
1480     if (fstat(srcFd, &statSrc) == -1) {
1481         CloseFileById(srcId);
1482         MEDIA_ERR_LOG("File get stat failed, %{public}d", errno);
1483         return E_FILE_OPER_FAIL;
1484     }
1485 
1486     if (sendfile(destFd, srcFd, nullptr, statSrc.st_size) == -1) {
1487         CloseFileById(srcId);
1488         CloseFileById(destId);
1489         MEDIA_ERR_LOG("copy file fail %{public}d ", errno);
1490         return E_FILE_OPER_FAIL;
1491     }
1492     CloseFileById(srcId);
1493     CloseFileById(destId);
1494     return destId;
1495 }
1496 
CloseFileById(int32_t fileId)1497 void MediaLibraryObjectUtils::CloseFileById(int32_t fileId)
1498 {
1499     ValuesBucket values;
1500     values.PutInt(MEDIA_DATA_DB_ID, fileId);
1501     MediaLibraryCommand closeCmd(OperationObject::FILESYSTEM_ASSET, OperationType::CLOSE, values);
1502     CloseFile(closeCmd);
1503 }
1504 
GetFileResult(shared_ptr<NativeRdb::ResultSet> & resultSet,int count,const string & relativePath,const string & displayName)1505 int32_t MediaLibraryObjectUtils::GetFileResult(shared_ptr<NativeRdb::ResultSet> &resultSet,
1506     int count, const string &relativePath, const string &displayName)
1507 {
1508     shared_ptr<FetchResult<FileAsset>> fetchFileResult = make_shared<FetchResult<FileAsset>>();
1509     int errCode = E_SUCCESS;
1510     for (int32_t row = 0; row < count; row++) {
1511         unique_ptr<FileAsset> fileAsset = fetchFileResult->GetObjectFromRdb(resultSet, row);
1512         if (fileAsset == nullptr) {
1513             MEDIA_ERR_LOG("get fileAsset failed");
1514             continue;
1515         }
1516         if (fileAsset->GetMediaType() == MEDIA_TYPE_ALBUM) {
1517             errCode = CopyDir(move(fileAsset), relativePath + displayName + "/");
1518             CHECK_AND_RETURN_RET_LOG(errCode > 0, errCode, "failed to copy dir");
1519         } else {
1520             errCode = CopyAsset(move(fileAsset), relativePath + displayName + "/");
1521             CHECK_AND_RETURN_RET_LOG(errCode > 0, errCode, "failed to copy asset");
1522         }
1523     }
1524     return errCode;
1525 }
1526 
CopyDir(const shared_ptr<FileAsset> & srcDirAsset,const string & relativePath)1527 int32_t MediaLibraryObjectUtils::CopyDir(const shared_ptr<FileAsset> &srcDirAsset,
1528     const string &relativePath)
1529 {
1530     if (srcDirAsset == nullptr) {
1531         MEDIA_ERR_LOG("Failed to obtain path from Database");
1532         return E_INVALID_URI;
1533     }
1534     ValuesBucket values;
1535     values.PutString(MEDIA_DATA_DB_NAME, ".nofile");
1536     values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_TYPE_NOFILE);
1537     string displayName = srcDirAsset->GetDisplayName();
1538     values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath + displayName + "/");
1539     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::CREATE);
1540     cmd.SetValueBucket(values);
1541     int32_t outRow = CreateFileObj(cmd);
1542     while (outRow == E_FILE_EXIST) {
1543         displayName = displayName + ASSET_RECYCLE_SUFFIX;
1544         values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath + displayName + "/");
1545         outRow = CreateFileObj(cmd);
1546     }
1547     if (outRow < 0) {
1548         MEDIA_ERR_LOG("Failed to obtain CreateFileObj");
1549         return outRow;
1550     }
1551     MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1552     queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_PARENT_ID, to_string(srcDirAsset->GetId()))->And()->
1553         EqualTo(MEDIA_DATA_DB_IS_TRASH, "0")->And()->NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_NOFILE));
1554     auto resultSet = QueryWithCondition(queryCmd, {});
1555     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "query rdbstore failed");
1556     auto count = 0;
1557     auto ret = resultSet->GetRowCount(count);
1558     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR, "get rdbstore failed");
1559     if (count == 0) {
1560         MEDIA_ERR_LOG("have no copy file");
1561         return E_SUCCESS;
1562     }
1563 
1564     int err = GetFileResult(resultSet, count, relativePath, displayName);
1565     resultSet.reset();
1566     if (err <= 0) {
1567         return err;
1568     }
1569     Uri srcUri(MEDIALIBRARY_DATA_URI + "/" + to_string(outRow));
1570     string srcUriString = srcUri.ToString();
1571     shared_ptr<FileAsset> srcAsset = MediaLibraryObjectUtils::GetFileAssetFromUri(srcUriString);
1572     if (srcAsset == nullptr) {
1573         MEDIA_ERR_LOG("Failed to obtain parentAsset from Database");
1574         return E_INVALID_URI;
1575     }
1576     return srcAsset->GetParent();
1577 }
1578 
GetRelativePathFromPath(const string & path)1579 static string GetRelativePathFromPath(const string &path)
1580 {
1581     string relativePath;
1582     if (path.find(ROOT_MEDIA_DIR) == 0) {
1583         relativePath = path.substr(ROOT_MEDIA_DIR.length());
1584     }
1585     auto pos = relativePath.rfind('/');
1586     if (pos == string::npos) {
1587         return "";
1588     }
1589     return relativePath.substr(0, pos + 1);
1590 }
1591 
CheckDirExtension(const string & destFilePath)1592 int32_t MediaLibraryObjectUtils::CheckDirExtension(const string &destFilePath)
1593 {
1594     string relativePath = GetRelativePathFromPath(destFilePath);
1595     string displayName = MediaLibraryDataManagerUtils::GetDisPlayNameFromPath(destFilePath);
1596     return CheckDirExtension(relativePath, displayName);
1597 }
1598 
GetRootDirAssetByRelativePath(const string & relativePath,DirAsset & dirAsset)1599 static int32_t GetRootDirAssetByRelativePath(const string &relativePath, DirAsset &dirAsset)
1600 {
1601     auto pos = relativePath.find('/');
1602     if (pos == string::npos) {
1603         return E_CHECK_EXTENSION_FAIL;
1604     }
1605     string rootDir = relativePath.substr(0, pos + 1);
1606     auto dirMap = MediaLibraryDataManager::GetDirQuerySetMap();
1607     if (dirMap.find(rootDir) == dirMap.end()) {
1608         return E_CHECK_EXTENSION_FAIL;
1609     }
1610     dirAsset = dirMap.at(rootDir);
1611     return E_SUCCESS;
1612 }
1613 
UpdateAnalysisProp(const std::string value)1614 void MediaLibraryObjectUtils::UpdateAnalysisProp(const std::string value)
1615 {
1616     int ret = SetParameter("persist.multimedia.media_analysis_service.hasdata", value.c_str());
1617     if (ret != 0) {
1618         MEDIA_ERR_LOG("Failed to UpdateAnalysisProp, result:%{public}d", ret);
1619     }
1620 }
1621 
CheckDirExtension(const string & relativePath,const string & displayName)1622 int32_t MediaLibraryObjectUtils::CheckDirExtension(const string &relativePath, const string &displayName)
1623 {
1624     if (relativePath.empty() || displayName.empty()) {
1625         return E_INVALID_ARGUMENTS;
1626     }
1627     if (displayName.compare(MEDIA_NO_FILE) == 0) {
1628         return E_SUCCESS;
1629     }
1630     if (MediaFileUtils::CheckFileDisplayName(displayName) < 0) {
1631         MEDIA_ERR_LOG("Check File DisplayName failed, displayName: %{private}s", displayName.c_str());
1632         return E_FILE_NAME_INVALID;
1633     }
1634     DirAsset rootDirAsset;
1635     auto ret = GetRootDirAssetByRelativePath(relativePath, rootDirAsset);
1636     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret, "get root dir from relativePath failed, path: %{private}s",
1637         relativePath.c_str());
1638     string dirMediaTypes = rootDirAsset.GetMediaTypes();
1639     if (dirMediaTypes == DIR_ALL_TYPE_VALUES) {
1640         return E_SUCCESS;
1641     }
1642     string fileExtension = MediaFileUtils::GetExtensionFromPath(displayName);
1643     string fileMimeType = MimeTypeUtils::GetMimeTypeFromExtension(fileExtension);
1644     string fileMediaType = to_string(static_cast<int32_t>(MimeTypeUtils::GetMediaTypeFromMimeType(fileMimeType)));
1645     if (dirMediaTypes.find(fileMediaType) == string::npos) {
1646         MEDIA_ERR_LOG("CheckDirExtension failed, file extension: %{private}s, root dir media_type: %{private}s",
1647             fileExtension.c_str(), dirMediaTypes.c_str());
1648         return E_CHECK_EXTENSION_FAIL;
1649     }
1650     return E_SUCCESS;
1651 }
1652 
IsSmartAlbumExistInDb(const int32_t id)1653 bool MediaLibraryObjectUtils::IsSmartAlbumExistInDb(const int32_t id)
1654 {
1655     MediaLibraryCommand querySmartAlbumCmd(OperationObject::SMART_ALBUM, OperationType::QUERY);
1656     querySmartAlbumCmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUM_DB_ID, to_string(id));
1657     auto queryResultSet = QuerySmartAlbum(querySmartAlbumCmd);
1658     if (queryResultSet != nullptr) {
1659         if (queryResultSet->GoToFirstRow() == NativeRdb::E_OK) {
1660             return true;
1661         }
1662     } else {
1663         MEDIA_ERR_LOG("QuerySmartAlbum failed");
1664     }
1665     return false;
1666 }
1667 
IsParentSmartAlbum(const int32_t id,const bool isInclude)1668 bool MediaLibraryObjectUtils::IsParentSmartAlbum(const int32_t id, const bool isInclude)
1669 {
1670     MediaLibraryCommand querySmartAlbumCmd(OperationObject::SMART_ALBUM_MAP, OperationType::QUERY);
1671     querySmartAlbumCmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUMMAP_DB_ALBUM_ID, to_string(id));
1672     if (isInclude) {
1673         auto queryResultSet = QuerySmartAlbum(querySmartAlbumCmd);
1674         if (queryResultSet != nullptr) {
1675             if (queryResultSet->GoToFirstRow() != NativeRdb::E_OK) {
1676                 return true;
1677             }
1678             queryResultSet.reset();
1679         } else {
1680             MEDIA_ERR_LOG("QuerySmartAlbum failed");
1681             return false;
1682         }
1683     }
1684     querySmartAlbumCmd.GetAbsRdbPredicates()->IsNotNull(SMARTALBUMMAP_DB_CHILD_ALBUM_ID);
1685     auto queryResultSet = QuerySmartAlbum(querySmartAlbumCmd);
1686     if (queryResultSet != nullptr) {
1687         if (queryResultSet->GoToFirstRow() == NativeRdb::E_OK) {
1688             return true;
1689         }
1690     }
1691     return false;
1692 }
1693 
QuerySmartAlbum(MediaLibraryCommand & cmd)1694 shared_ptr<ResultSet> MediaLibraryObjectUtils::QuerySmartAlbum(MediaLibraryCommand &cmd)
1695 {
1696     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1697     if (uniStore == nullptr) {
1698         MEDIA_ERR_LOG("UniStore is nullptr");
1699         return nullptr;
1700     }
1701     vector<string> columns;
1702     return uniStore->Query(cmd, columns);
1703 }
1704 } // namespace Media
1705 } // namespace OHOS
1706