1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "medialibrary_file_operations.h"
17 #include "media_log.h"
18 #include "media_file_utils.h"
19 #include "medialibrary_smartalbum_map_db.h"
20
21 using namespace std;
22 using namespace OHOS::NativeRdb;
23
24 namespace OHOS {
25 namespace Media {
UpdateDateModifiedForAlbum(const shared_ptr<RdbStore> & rdbStore,const string & albumPath)26 void UpdateDateModifiedForAlbum(const shared_ptr<RdbStore> &rdbStore, const string &albumPath)
27 {
28 if (!albumPath.empty()) {
29 int32_t count(0);
30 vector<string> whereArgs = { albumPath };
31 ValuesBucket valuesBucket;
32 valuesBucket.PutLong(MEDIA_DATA_DB_DATE_MODIFIED,
33 MediaLibraryDataAbilityUtils::GetAlbumDateModified(albumPath));
34
35 int32_t updateResult = rdbStore->Update(count, MEDIALIBRARY_TABLE, valuesBucket,
36 MEDIA_DATA_DB_FILE_PATH + " = ?", whereArgs);
37 if (updateResult != E_OK) {
38 MEDIA_ERR_LOG("Update failed for album");
39 }
40 }
41 }
42
HandleCreateAsset(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore)43 int32_t MediaLibraryFileOperations::HandleCreateAsset(const ValuesBucket &values,
44 const shared_ptr<RdbStore> &rdbStore)
45 {
46 string relativePath(""), path(""), displayName("");
47 int32_t errCode = DATA_ABILITY_FAIL;
48 int32_t mediaType = static_cast<int32_t>(MEDIA_TYPE_FILE);
49 FileAsset fileAsset;
50 MediaLibraryFileDb fileDbOprn;
51 ValueObject valueObject;
52 NativeAlbumAsset nativeAlbumAsset;
53 // Obtain file displayName
54 if (values.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
55 valueObject.GetString(displayName);
56 }
57
58 // Obtain relative path
59 if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
60 valueObject.GetString(relativePath);
61 path = ROOT_MEDIA_DIR + relativePath + displayName;
62 }
63
64 // Obtain mediatype
65 if (values.GetObject(MEDIA_DATA_DB_MEDIA_TYPE, valueObject)) {
66 valueObject.GetInt(mediaType);
67 fileAsset.SetMediaType(static_cast<MediaType>(mediaType));
68 }
69
70 vector<int32_t> outIds;
71 nativeAlbumAsset = MediaLibraryDataAbilityUtils::CreateDirectorys(relativePath, rdbStore, outIds);
72 if (nativeAlbumAsset.GetAlbumId() < 0) {
73 return nativeAlbumAsset.GetAlbumId();
74 }
75 nativeAlbumAsset = MediaLibraryDataAbilityUtils::GetAlbumAsset(to_string(nativeAlbumAsset.GetAlbumId()), rdbStore);
76 if (MediaLibraryDataAbilityUtils::isFileExistInDb(path, rdbStore)) {
77 if (fileAsset.IsFileExists(path)) {
78 return DATA_ABILITY_DUPLICATE_CREATE;
79 } else {
80 int32_t deletedRows(FILE_OPERATION_ERR);
81 vector<string> whereArgs = { path };
82 int32_t deleteResult = rdbStore->Delete(deletedRows, MEDIALIBRARY_TABLE, "data = ?", whereArgs);
83 if (deleteResult != E_OK) {
84 return errCode;
85 }
86 }
87 }
88 errCode = fileAsset.CreateAsset(path);
89 if (errCode == DATA_ABILITY_SUCCESS) {
90 // Fill basic file information into DB
91 ValuesBucket updatedAssetInfo = UpdateBasicAssetDetails(mediaType, displayName, relativePath, path);
92 updatedAssetInfo.PutInt(MEDIA_DATA_DB_BUCKET_ID, nativeAlbumAsset.GetAlbumId());
93 updatedAssetInfo.PutInt(MEDIA_DATA_DB_PARENT_ID, nativeAlbumAsset.GetAlbumId());
94 updatedAssetInfo.PutString(MEDIA_DATA_DB_BUCKET_NAME, nativeAlbumAsset.GetAlbumName());
95 // will return row id
96 return fileDbOprn.Insert(updatedAssetInfo, rdbStore);
97 }
98 return errCode;
99 }
100
HandleCloseAsset(string & uriStr,string & srcPath,const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore)101 int32_t MediaLibraryFileOperations::HandleCloseAsset(string &uriStr, string &srcPath, const ValuesBucket &values,
102 const shared_ptr<RdbStore> &rdbStore)
103 {
104 int32_t errorCode = MediaLibraryDataAbilityUtils::setFilePending(uriStr, false, rdbStore);
105 if (errorCode == DATA_ABILITY_FAIL) {
106 MEDIA_ERR_LOG("HandleCloseAsset Set file to pending DB error");
107 return DATA_ABILITY_FAIL;
108 }
109
110 string fileName;
111
112 if (!srcPath.empty() && ((fileName = MediaLibraryDataAbilityUtils::GetFileName(srcPath)).length() != 0) &&
113 (fileName.at(0) != '.')) {
114 string albumPath = MediaLibraryDataAbilityUtils::GetParentPath(srcPath);
115 UpdateDateModifiedForAlbum(rdbStore, albumPath);
116 }
117
118 return DATA_ABILITY_SUCCESS;
119 }
120
HandleGetAlbumCapacity(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore)121 int32_t MediaLibraryFileOperations::HandleGetAlbumCapacity(const ValuesBucket &values,
122 const shared_ptr<RdbStore> &rdbStore)
123 {
124 MEDIA_INFO_LOG("HandleGetAlbumCapacity IN");
125 int32_t errorCode = DATA_ABILITY_FAIL;
126 unique_ptr<AbsSharedResultSet> resultSet = nullptr;
127 ValueObject valueObject;
128 bool isFavourite = false;
129 if (values.GetObject(MEDIA_DATA_DB_IS_FAV, valueObject)) {
130 valueObject.GetBool(isFavourite);
131 }
132
133 bool isTrash = false;
134 if (values.GetObject(MEDIA_DATA_DB_IS_TRASH, valueObject)) {
135 valueObject.GetBool(isTrash);
136 }
137
138 if (isFavourite) {
139 MEDIA_INFO_LOG("HandleGetAlbumCapacity isFavourite");
140 resultSet= MediaLibraryDataAbilityUtils::QueryFavFiles(rdbStore);
141 } else if (isTrash) {
142 MEDIA_INFO_LOG("HandleGetAlbumCapacity isTrash");
143 resultSet= MediaLibraryDataAbilityUtils::QueryTrashFiles(rdbStore);
144 }
145
146 if (resultSet != nullptr) {
147 resultSet->GetRowCount(errorCode);
148 MEDIA_INFO_LOG("HandleGetAlbumCapacity GetRowCount %{public}d", errorCode);
149 }
150
151 MEDIA_INFO_LOG("HandleGetAlbumCapacity OUT");
152 return errorCode;
153 }
ModifyDisName(const string & dstFileName,const string & destAlbumPath,const string & srcPath,const shared_ptr<RdbStore> & rdbStore)154 int ModifyDisName(const string &dstFileName,
155 const string &destAlbumPath, const string &srcPath, const shared_ptr<RdbStore> &rdbStore)
156 {
157 int32_t errCode = DATA_ABILITY_SUCCESS;
158 if (dstFileName == ".nomedia") {
159 int32_t deletedRows(ALBUM_OPERATION_ERR);
160 vector<string> whereArgs = {(destAlbumPath.back() != '/' ?
161 (destAlbumPath + "/%") : (destAlbumPath + "%")), destAlbumPath};
162
163 int32_t deleteResult = rdbStore->Delete(deletedRows, MEDIALIBRARY_TABLE,
164 MEDIA_DATA_DB_FILE_PATH + " LIKE ? OR " + MEDIA_DATA_DB_FILE_PATH + " = ?", whereArgs);
165 if (deleteResult != E_OK) {
166 MEDIA_ERR_LOG("Delete rows for the hidden album failed");
167 }
168 whereArgs.clear();
169 whereArgs.push_back(srcPath);
170 deleteResult = rdbStore->Delete(deletedRows, MEDIALIBRARY_TABLE, MEDIA_DATA_DB_FILE_PATH + " = ?", whereArgs);
171 if (deleteResult != E_OK) {
172 MEDIA_ERR_LOG("Delete rows for the old path failed");
173 }
174 errCode = DATA_ABILITY_FAIL;
175 }
176
177 if ((!dstFileName.empty()) && (dstFileName.at(0) == '.')) {
178 int32_t deletedRows(ALBUM_OPERATION_ERR);
179 vector<string> whereArgs = { srcPath };
180
181 int32_t deleteResult = rdbStore->Delete(deletedRows, MEDIALIBRARY_TABLE,
182 MEDIA_DATA_DB_FILE_PATH + " = ?", whereArgs);
183 if (deleteResult != E_OK) {
184 MEDIA_ERR_LOG("Delete rows failed");
185 }
186 errCode = DATA_ABILITY_FAIL;
187 }
188 return errCode;
189 }
HandleModifyAsset(const string & rowNum,const string & srcPath,const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore)190 int32_t MediaLibraryFileOperations::HandleModifyAsset(const string &rowNum, const string &srcPath,
191 const ValuesBucket &values, const shared_ptr<RdbStore> &rdbStore)
192 {
193 string dstFilePath, dstReFilePath, dstFileName, destAlbumPath, bucketName;
194 int32_t errCode = DATA_ABILITY_SUCCESS;
195 int32_t bucketId = 0;
196 ValueObject valueObject;
197 FileAsset fileAsset;
198 MediaLibraryFileDb fileDbOprn;
199 if (values.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
200 valueObject.GetString(dstFileName);
201 }
202 if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
203 valueObject.GetString(dstReFilePath);
204 }
205 dstFilePath = ROOT_MEDIA_DIR + dstReFilePath + dstFileName;
206 destAlbumPath = ROOT_MEDIA_DIR + dstReFilePath;
207 if (destAlbumPath.back() == '/') {
208 destAlbumPath = destAlbumPath.substr(0, destAlbumPath.length() - 1);
209 }
210 MEDIA_ERR_LOG("HandleModifyAsset destAlbumPath = %{public}s", destAlbumPath.c_str());
211 bucketId = MediaLibraryDataAbilityUtils::GetParentIdFromDb(destAlbumPath, rdbStore);
212 if ((!dstReFilePath.empty()) && (bucketId == 0)) {
213 vector<int32_t> outIds;
214 NativeAlbumAsset nativeAlbumAsset = MediaLibraryDataAbilityUtils::CreateDirectorys(dstReFilePath,
215 rdbStore, outIds);
216 if (nativeAlbumAsset.GetAlbumId() < 0) {
217 MEDIA_ERR_LOG("Failed to CreateDirectorys err:%{public}d", nativeAlbumAsset.GetAlbumId());
218 return nativeAlbumAsset.GetAlbumId();
219 }
220 bucketId = nativeAlbumAsset.GetAlbumId();
221 }
222
223 bucketName = MediaLibraryDataAbilityUtils::GetParentDisplayNameFromDb(bucketId, rdbStore);
224 MEDIA_ERR_LOG("HandleModifyAsset bucketId = %{public}d bucketName = %{public}s", bucketId, bucketName.c_str());
225 if (srcPath.compare(dstFilePath) != 0) {
226 errCode = fileAsset.ModifyAsset(srcPath, dstFilePath);
227 if (errCode == DATA_ABILITY_MODIFY_DATA_FAIL) {
228 MEDIA_ERR_LOG("Failed to modify the file in the device");
229 return errCode;
230 }
231 errCode = ModifyDisName(dstFileName, destAlbumPath, srcPath, rdbStore);
232 if (errCode == DATA_ABILITY_FAIL) {
233 return errCode;
234 }
235 if (fileDbOprn.Modify(rowNum, dstFilePath, bucketId, bucketName, rdbStore) > 0) {
236 UpdateDateModifiedForAlbum(rdbStore, destAlbumPath);
237 string srcAlbumPath = MediaLibraryDataAbilityUtils::GetParentPath(srcPath);
238 UpdateDateModifiedForAlbum(rdbStore, srcAlbumPath);
239 }
240 }
241 return errCode;
242 }
243
HandleDeleteAsset(const string & rowNum,const string & srcPath,const shared_ptr<RdbStore> & rdbStore)244 int32_t MediaLibraryFileOperations::HandleDeleteAsset(const string &rowNum, const string &srcPath,
245 const shared_ptr<RdbStore> &rdbStore)
246 {
247 int32_t errCode = DATA_ABILITY_FAIL;
248 FileAsset fileAsset;
249 MediaLibraryFileDb fileDbOprn;
250 MediaLibrarySmartAlbumMapDb smartAlbumMapDbOprn;
251 if (!srcPath.empty()) {
252 errCode = fileAsset.DeleteAsset(srcPath);
253 }
254
255 if (errCode == DATA_ABILITY_SUCCESS) {
256 errCode = fileDbOprn.Delete(rowNum, rdbStore);
257 if (errCode > 0) {
258 string albumPath = MediaLibraryDataAbilityUtils::GetParentPath(srcPath);
259 UpdateDateModifiedForAlbum(rdbStore, albumPath);
260 smartAlbumMapDbOprn.DeleteAllAssetsMapInfo(std::stoi(rowNum), rdbStore);
261 }
262 }
263
264 return errCode;
265 }
CreateThumbnail(const shared_ptr<RdbStore> & rdbStore,const shared_ptr<MediaLibraryThumbnail> & mediaThumbnail,string id)266 void CreateThumbnail(const shared_ptr<RdbStore> &rdbStore,
267 const shared_ptr<MediaLibraryThumbnail> &mediaThumbnail, string id)
268 {
269 if (!id.empty()) {
270 string kvId;
271 ThumbRdbOpt opts = {
272 .store = rdbStore,
273 .table = MEDIALIBRARY_TABLE,
274 .row = id
275 };
276
277 if (!mediaThumbnail->CreateThumbnail(opts, kvId)) {
278 MEDIA_ERR_LOG("Create thumbnail error");
279 }
280 }
281 }
HandleIsDirectoryAsset(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore)282 int32_t MediaLibraryFileOperations::HandleIsDirectoryAsset(const ValuesBucket &values,
283 const shared_ptr<RdbStore> &rdbStore)
284 {
285 int32_t errCode = DATA_ABILITY_FAIL;
286 ValueObject valueObject;
287 int32_t id = 0;
288 unique_ptr<AbsSharedResultSet> queryResultSet;
289 std::vector<std::string> columns;
290 int32_t columnIndex;
291 string path = "";
292 columns.push_back(MEDIA_DATA_DB_FILE_PATH);
293 if (values.GetObject(MEDIA_DATA_DB_ID, valueObject)) {
294 valueObject.GetInt(id);
295 }
296 MEDIA_ERR_LOG("HandleIsDirectoryAsset id = %{public}d", id);
297 if (id != 0) {
298 AbsRdbPredicates mediaLibAbsPredFile(MEDIALIBRARY_TABLE);
299 mediaLibAbsPredFile.EqualTo(MEDIA_DATA_DB_ID, std::to_string(id));
300 queryResultSet = rdbStore->Query(mediaLibAbsPredFile, columns);
301 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
302 queryResultSet->GetColumnIndex(MEDIA_DATA_DB_FILE_PATH, columnIndex);
303 queryResultSet->GetString(columnIndex, path);
304 MEDIA_ERR_LOG("HandleIsDirectoryAsset path = %{public}s", path.c_str());
305 }
306 if (MediaFileUtils::IsDirectory(path)) {
307 errCode = SUCCESS;
308 }
309 }
310 return errCode;
311 }
HandleFileOperation(const string & oprn,const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore,const std::shared_ptr<MediaLibraryThumbnail> & mediaThumbnail)312 int32_t MediaLibraryFileOperations::HandleFileOperation(const string &oprn, const ValuesBucket &values,
313 const shared_ptr<RdbStore> &rdbStore, const std::shared_ptr<MediaLibraryThumbnail> &mediaThumbnail)
314 {
315 int32_t errCode = DATA_ABILITY_FAIL;
316
317 if (oprn == MEDIA_FILEOPRN_CREATEASSET) {
318 return HandleCreateAsset(values, rdbStore);
319 } else if (oprn == MEDIA_FILEOPRN_ISDIRECTORY) {
320 return HandleIsDirectoryAsset(values, rdbStore);
321 } else if (oprn == MEDIA_FILEOPRN_GETALBUMCAPACITY) {
322 return HandleGetAlbumCapacity(values, rdbStore);
323 }
324
325 string actualUri;
326 ValueObject valueObject;
327
328 if (values.GetObject(MEDIA_DATA_DB_URI, valueObject)) {
329 valueObject.GetString(actualUri);
330 }
331 string srcPath;
332 string networkId = MediaLibraryDataAbilityUtils::GetNetworkIdFromUri(actualUri);
333 if (!networkId.empty()) {
334 if (oprn == MEDIA_FILEOPRN_CLOSEASSET) {
335 return HandleCloseAsset(actualUri, srcPath, values, rdbStore);
336 } else {
337 return errCode;
338 }
339 }
340
341 string id = MediaLibraryDataAbilityUtils::GetIdFromUri(actualUri);
342 srcPath = MediaLibraryDataAbilityUtils::GetPathFromDb(id, rdbStore);
343 CHECK_AND_RETURN_RET_LOG(!srcPath.empty(), DATA_ABILITY_FAIL, "Failed to obtain path from Database");
344
345 if (oprn == MEDIA_FILEOPRN_MODIFYASSET) {
346 errCode = HandleModifyAsset(id, srcPath, values, rdbStore);
347 } else if (oprn == MEDIA_FILEOPRN_DELETEASSET) {
348 errCode = HandleDeleteAsset(id, srcPath, rdbStore);
349 } else if (oprn == MEDIA_FILEOPRN_CLOSEASSET) {
350 errCode = HandleCloseAsset(actualUri, srcPath, values, rdbStore);
351 }
352 if (oprn == MEDIA_FILEOPRN_CLOSEASSET) {
353 CreateThumbnail(rdbStore, mediaThumbnail, id);
354 }
355
356 return errCode;
357 }
358
UpdateBasicAssetDetails(int32_t mediaType,const string & fileName,const string & relPath,const string & path)359 ValuesBucket MediaLibraryFileOperations::UpdateBasicAssetDetails(int32_t mediaType,
360 const string &fileName,
361 const string &relPath,
362 const string &path)
363 {
364 ValuesBucket assetInfoBucket;
365 assetInfoBucket.PutString(Media::MEDIA_DATA_DB_RELATIVE_PATH, relPath);
366 assetInfoBucket.PutString(Media::MEDIA_DATA_DB_NAME, fileName);
367 assetInfoBucket.PutString(Media::MEDIA_DATA_DB_TITLE, MediaLibraryDataAbilityUtils::GetFileTitle(fileName));
368 struct stat statInfo {};
369 if (stat(path.c_str(), &statInfo) == 0) {
370 assetInfoBucket.PutLong(Media::MEDIA_DATA_DB_SIZE, statInfo.st_size);
371 assetInfoBucket.PutLong(Media::MEDIA_DATA_DB_DATE_ADDED, statInfo.st_ctime);
372 }
373 assetInfoBucket.PutInt(Media::MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
374 assetInfoBucket.PutString(Media::MEDIA_DATA_DB_FILE_PATH, path);
375 return assetInfoBucket;
376 }
377 } // namespace Media
378 } // namespace OHOS
379