1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define MLOG_TAG "Media_Client"
16
17 #include "cloud_file_data_convert.h"
18
19 #include <string>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23
24 #include "directory_ex.h"
25 #include "exif_rotate_utils.h"
26 #include "file_ex.h"
27 #include "media_log.h"
28 #include "cloud_media_sync_const.h"
29 #include "mdk_record_photos_data.h"
30 #include "media_file_utils.h"
31 #include "moving_photo_file_utils.h"
32 #include "photo_file_utils.h"
33 #include "cloud_report_utils.h"
34 #include "nlohmann/json.hpp"
35
36 namespace OHOS::Media::CloudSync {
37
38 /* path */
39 std::string CloudFileDataConvert::prefixLCD_ = "/mnt/hmdfs/";
40 std::string CloudFileDataConvert::sandboxPrefix_ = "/storage/cloud/files";
41 std::string CloudFileDataConvert::prefix_ = "/data/service/el2/";
42 std::string CloudFileDataConvert::suffixLCD_ = "/account/device_view/local/files";
43 std::string CloudFileDataConvert::suffix_ = "/hmdfs/account/files";
44 const std::string CloudFileDataConvert::recordType_ = "media";
45 constexpr off_t THUMB_LIMIT_SIZE = 2 * 1024 * 1024;
46
CloudFileDataConvert(CloudOperationType type,int32_t userId)47 CloudFileDataConvert::CloudFileDataConvert(CloudOperationType type, int32_t userId) : userId_(userId), type_(type)
48 {}
49
GetThumbnailPath(const std::string & path,const std::string & key)50 static inline std::string GetThumbnailPath(const std::string &path, const std::string &key)
51 {
52 if (path.length() < ROOT_MEDIA_DIR.length()) {
53 return "";
54 }
55 std::string suffix = (key == "THM_ASTC") ? ".astc" : ".jpg";
56 return ROOT_MEDIA_DIR + ".thumbs/" + path.substr(ROOT_MEDIA_DIR.length()) + "/" + key + suffix;
57 }
58
GetThumbPath(const std::string & path,const std::string & key)59 std::string CloudFileDataConvert::GetThumbPath(const std::string &path, const std::string &key)
60 {
61 if (path.length() < ROOT_MEDIA_DIR.length()) {
62 return "";
63 }
64 /* transform sandbox path */
65 return prefixLCD_ + std::to_string(userId_) + suffixLCD_ + "/" +
66 GetThumbnailPath(path, key).substr(ROOT_MEDIA_DIR.length());
67 }
68
CheckFileSize(const std::string & thumbSuffix,const int64_t & fileSize)69 int32_t CloudFileDataConvert::CheckFileSize(const std::string &thumbSuffix, const int64_t &fileSize)
70 {
71 if (fileSize <= 0) {
72 MEDIA_ERR_LOG("ReportFailure: get size err, size is %{public}" PRId64, fileSize);
73 return (thumbSuffix == THUMB_SUFFIX) ? E_THM_SIZE_IS_ZERO : E_LCD_SIZE_IS_ZERO;
74 }
75 if (fileSize >= THUMB_LIMIT_SIZE) {
76 MEDIA_ERR_LOG("ReportFailure: size is too large, size is %{public}" PRId64, fileSize);
77 return (thumbSuffix == THUMB_SUFFIX) ? E_THM_IS_TOO_LARGE : E_LCD_IS_TOO_LARGE;
78 }
79 return E_OK;
80 }
81
GetFileSize(const std::string & path,const std::string & thumbSuffix,int64_t & fileSize)82 int32_t CloudFileDataConvert::GetFileSize(const std::string &path, const std::string &thumbSuffix, int64_t &fileSize)
83 {
84 std::string thumbExSuffix = (thumbSuffix == THUMB_SUFFIX) ? THUMB_EX_SUFFIX : LCD_EX_SUFFIX;
85 /* try get file size on xxxjpg/THM_EX/THM.jpg */
86 std::string thumbnailPath = GetThumbPath(path, thumbExSuffix);
87 struct stat fileStat;
88 MEDIA_INFO_LOG("GetFileSize stat %{public}s", thumbnailPath.c_str());
89 int32_t err = stat(thumbnailPath.c_str(), &fileStat);
90 int32_t ret = E_OK;
91 if (err < 0) {
92 UTIL_SYNC_FAULT_REPORT({bundleName_,
93 UtilCloud::FaultScenarioCode::CLOUD_FULL_SYNC,
94 UtilCloud::FaultType::FILE,
95 err,
96 "get thumb size failed errno : " + std::to_string(errno) + ", path " +
97 ReportUtils::GetAnonyString(thumbnailPath)});
98 MEDIA_ERR_LOG("get thumb size failed errno :%{public}d, %{public}s", errno, thumbnailPath.c_str());
99 } else {
100 fileSize = fileStat.st_size;
101 ret = this->CheckFileSize(thumbSuffix, fileSize);
102 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "CheckFileSize ret, %{public}d", ret);
103 return E_OK;
104 }
105 /* try get file size on xxxjpg/THM.jpg */
106 thumbnailPath = GetThumbPath(path, thumbSuffix);
107 err = stat(thumbnailPath.c_str(), &fileStat);
108 if (err < 0) {
109 int32_t errNum = errno;
110 UTIL_SYNC_FAULT_REPORT({bundleName_,
111 UtilCloud::FaultScenarioCode::CLOUD_FULL_SYNC,
112 UtilCloud::FaultType::FILE,
113 err,
114 "get thumb size failed errno : " + std::to_string(errno) + ", path " +
115 ReportUtils::GetAnonyString(thumbnailPath)});
116 MEDIA_ERR_LOG("get thumb size failed errno :%{public}d, %{public}s", errno, thumbnailPath.c_str());
117 return ((thumbSuffix == THUMB_SUFFIX) ? E_THM_SOURCE_BASIC : E_LCD_SOURCE_BASIC) + errNum;
118 }
119 fileSize = fileStat.st_size;
120 ret = this->CheckFileSize(thumbSuffix, fileSize);
121 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "CheckFileSize err, %{public}d", ret);
122 MEDIA_INFO_LOG("GetFileSize stat end thumbnailPath: %{public}s, err: %{public}d, size: %{public}" PRId64,
123 thumbnailPath.c_str(),
124 err,
125 fileSize);
126 return E_OK;
127 }
128
HandleThumbSize(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotosVo & upLoadRecord)129 int32_t CloudFileDataConvert::HandleThumbSize(
130 std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotosVo &upLoadRecord)
131 {
132 if (type_ != FILE_CREATE && type_ != FILE_DATA_MODIFY) {
133 return E_OK;
134 }
135 std::string path = upLoadRecord.data;
136 CHECK_AND_RETURN_RET_LOG(!path.empty(), E_QUERY_CONTENT_IS_EMPTY, "HandleThumbSize failed to get filepath");
137 int64_t fileSize;
138 int32_t ret = GetFileSize(path, THUMB_SUFFIX, fileSize);
139 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "GetFileSize err: %{public}d", ret);
140 map["thumb_size"] = MDKRecordField(fileSize);
141 return E_OK;
142 }
143
HandleLcdSize(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotosVo & upLoadRecord)144 int32_t CloudFileDataConvert::HandleLcdSize(
145 std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotosVo &upLoadRecord)
146 {
147 if (type_ != FILE_CREATE && type_ != FILE_DATA_MODIFY) {
148 return E_OK;
149 }
150 std::string path = upLoadRecord.data;
151 int64_t fileSize;
152 int32_t ret = GetFileSize(path, LCD_SUFFIX, fileSize);
153 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "GetFileSize err: %{public}d", ret);
154 map["lcd_size"] = MDKRecordField(fileSize);
155 return E_OK;
156 }
157
HandleFormattedDate(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotosVo & upLoadRecord)158 int32_t CloudFileDataConvert::HandleFormattedDate(
159 std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotosVo &upLoadRecord)
160 {
161 std::string year = upLoadRecord.dateYear;
162 std::string month = upLoadRecord.dateMonth;
163 std::string day = upLoadRecord.dateDay;
164 if (year.empty() || month.empty() || day.empty()) {
165 MEDIA_INFO_LOG("HandleFormattedDate year month day is empty");
166 int64_t createTime = upLoadRecord.dateTaken;
167 createTime = createTime / MILLISECOND_TO_SECOND;
168 year = MediaFileUtils::StrCreateTime(PhotoColumn::PHOTO_DATE_YEAR_FORMAT, createTime);
169 month = MediaFileUtils::StrCreateTime(PhotoColumn::PHOTO_DATE_MONTH_FORMAT, createTime);
170 day = MediaFileUtils::StrCreateTime(PhotoColumn::PHOTO_DATE_DAY_FORMAT, createTime);
171 }
172 map[PhotoColumn::PHOTO_DATE_YEAR] = MDKRecordField(year);
173 map[PhotoColumn::PHOTO_DATE_MONTH] = MDKRecordField(month);
174 map[PhotoColumn::PHOTO_DATE_DAY] = MDKRecordField(day);
175 return E_OK;
176 }
177
HandleExifRotate(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotosVo & upLoadRecord)178 int32_t CloudFileDataConvert::HandleExifRotate(std::map<std::string, MDKRecordField> &map,
179 const CloudMdkRecordPhotosVo &upLoadRecord)
180 {
181 if (upLoadRecord.exifRotate == 0) {
182 MEDIA_INFO_LOG("Upload meta data, do not upload exif rotate uncertain");
183 return E_OK;
184 }
185 map[PhotoColumn::PHOTO_EXIF_ROTATE] = MDKRecordField(upLoadRecord.exifRotate);
186 return E_OK;
187 }
188
HandleUniqueFileds(std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotosVo & upLoadRecord)189 int32_t CloudFileDataConvert::HandleUniqueFileds(
190 std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotosVo &upLoadRecord)
191 {
192 std::map<std::string, MDKRecordField> map;
193 /* store media unique fileds in attributes */
194 map[PhotoColumn::MEDIA_TITLE] = MDKRecordField(upLoadRecord.title);
195 map[PhotoColumn::MEDIA_TYPE] = MDKRecordField(upLoadRecord.mediaType);
196 map[PhotoColumn::MEDIA_DURATION] = MDKRecordField(upLoadRecord.duration);
197 map[PhotoColumn::MEDIA_HIDDEN] = MDKRecordField(upLoadRecord.hidden);
198 map[PhotoColumn::PHOTO_HIDDEN_TIME] = MDKRecordField(upLoadRecord.hiddenTime);
199 map[PhotoColumn::MEDIA_RELATIVE_PATH] = MDKRecordField(upLoadRecord.relativePath);
200 map[PhotoColumn::MEDIA_VIRTURL_PATH] = MDKRecordField(upLoadRecord.virtualPath);
201 map[PhotoColumn::PHOTO_META_DATE_MODIFIED] = MDKRecordField(upLoadRecord.metaDateModified);
202 map[PhotoColumn::PHOTO_SUBTYPE] = MDKRecordField(upLoadRecord.subtype);
203 map[PhotoColumn::PHOTO_BURST_COVER_LEVEL] = MDKRecordField(upLoadRecord.burstCoverLevel);
204 map[PhotoColumn::PHOTO_BURST_KEY] = MDKRecordField(upLoadRecord.burstKey);
205 map[PhotoColumn::PHOTO_DATE_YEAR] = MDKRecordField(upLoadRecord.dateYear);
206 map[PhotoColumn::PHOTO_DATE_MONTH] = MDKRecordField(upLoadRecord.dateMonth);
207 map[PhotoColumn::PHOTO_DATE_DAY] = MDKRecordField(upLoadRecord.dateDay);
208 map[PhotoColumn::PHOTO_SHOOTING_MODE] = MDKRecordField(upLoadRecord.shootingMode);
209 map[PhotoColumn::PHOTO_SHOOTING_MODE_TAG] = MDKRecordField(upLoadRecord.shootingModeTag);
210 map[PhotoColumn::PHOTO_DYNAMIC_RANGE_TYPE] = MDKRecordField(upLoadRecord.dynamicRangeType);
211 map[PhotoColumn::PHOTO_FRONT_CAMERA] = MDKRecordField(upLoadRecord.frontCamera);
212 map[PhotoColumn::PHOTO_EDIT_TIME] = MDKRecordField(upLoadRecord.editTime);
213 map[PhotoColumn::PHOTO_ORIGINAL_SUBTYPE] = MDKRecordField(upLoadRecord.originalSubtype);
214 map[PhotoColumn::PHOTO_COVER_POSITION] = MDKRecordField(upLoadRecord.coverPosition);
215 map[PhotoColumn::PHOTO_IS_RECTIFICATION_COVER] = MDKRecordField(upLoadRecord.isRectificationCover);
216 map[PhotoColumn::MOVING_PHOTO_EFFECT_MODE] = MDKRecordField(upLoadRecord.movingPhotoEffectMode);
217 map[PhotoColumn::SUPPORTED_WATERMARK_TYPE] = MDKRecordField(upLoadRecord.supportedWatermarkType);
218 map[PhotoColumn::PHOTO_STRONG_ASSOCIATION] = MDKRecordField(upLoadRecord.strongAssociation);
219 map[MediaColumn::MEDIA_ID] = MDKRecordField(upLoadRecord.fileId);
220 map[PhotoColumn::MEDIA_FILE_PATH] = MDKRecordField(upLoadRecord.data);
221 map[PhotoColumn::MEDIA_DATE_ADDED] = MDKRecordField((upLoadRecord.dateAdded) / MILLISECOND_TO_SECOND);
222 map[PhotoColumn::MEDIA_DATE_MODIFIED] = MDKRecordField((upLoadRecord.dateModified) / MILLISECOND_TO_SECOND);
223 map[PhotoColumn::PHOTO_SUBTYPE] = MDKRecordField(upLoadRecord.subtype);
224 map[PhotoColumn::PHOTO_BURST_COVER_LEVEL] = MDKRecordField(upLoadRecord.burstCoverLevel);
225 map[PhotoColumn::PHOTO_BURST_KEY] = MDKRecordField(upLoadRecord.burstKey);
226 map[PhotoColumn::PHOTO_OWNER_ALBUM_ID] = MDKRecordField(upLoadRecord.ownerAlbumId);
227 map[FILE_FIX_VERSION] = MDKRecordField(0);
228 map["editedTime_ms"] = MDKRecordField(upLoadRecord.dateModified);
229 int32_t ret = HandleThumbSize(map, upLoadRecord);
230 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleThumbSize err: %{public}d", ret);
231 ret = HandleLcdSize(map, upLoadRecord);
232 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleLcdSize err: %{public}d", ret);
233 ret = HandleFormattedDate(map, upLoadRecord);
234 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleFormattedDate err: %{public}d", ret);
235 ret = HandleExifRotate(map, upLoadRecord);
236 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleExifRotate err: %{public}d", ret);
237 data[FILE_ATTRIBUTES] = MDKRecordField(map);
238 data[FILE_LOCAL_ID] = MDKRecordField(upLoadRecord.fileId);
239 return ret;
240 }
241
HandleFileType(std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotosVo & upLoadRecord)242 int32_t CloudFileDataConvert::HandleFileType(
243 std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotosVo &upLoadRecord)
244 {
245 MEDIA_DEBUG_LOG("enter HandleFileType %{public}d, %{public}d", upLoadRecord.subtype, upLoadRecord.dirty);
246 if (upLoadRecord.subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
247 data["fileType"] = MDKRecordField(FILE_TYPE_LIVEPHOTO);
248 return E_OK;
249 }
250 // 2. fill fileType with Image/Video when create file
251 if (upLoadRecord.dirty == static_cast<int32_t>(DirtyType::TYPE_NEW)) {
252 data["fileType"] =
253 MDKRecordField(upLoadRecord.mediaType == Media::MEDIA_TYPE_VIDEO ? FILE_TYPE_VIDEO : FILE_TYPE_IMAGE);
254 return E_OK;
255 }
256 // 3. fill fileType with Image when it's a Graffiti
257 if (upLoadRecord.subtype == static_cast<int32_t>(PhotoSubType::DEFAULT) &&
258 upLoadRecord.originalSubtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
259 data["fileType"] = MDKRecordField(FILE_TYPE_IMAGE);
260 }
261 return E_OK;
262 }
263
HandlePosition(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotosVo & upLoadRecord)264 int32_t CloudFileDataConvert::HandlePosition(
265 std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotosVo &upLoadRecord)
266 {
267 CHECK_AND_RETURN_RET(!(upLoadRecord.latitude == 0 && upLoadRecord.longitude == 0), E_OK);
268 std::stringstream latitudestream;
269 std::stringstream longitudestream;
270 latitudestream.precision(15); // 15:precision
271 longitudestream.precision(15); // 15:precision
272 latitudestream << upLoadRecord.latitude;
273 longitudestream << upLoadRecord.longitude;
274 std::string position = "{\"x\":\"" + latitudestream.str() + "\",\"y\":\"" + longitudestream.str() + "\"}";
275 map["position"] = MDKRecordField(position);
276 return E_OK;
277 }
278
HandleRotate(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotosVo & upLoadRecord)279 int32_t CloudFileDataConvert::HandleRotate(
280 std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotosVo &upLoadRecord)
281 {
282 MEDIA_DEBUG_LOG("enter HandleRotate orientation: %{public}d", upLoadRecord.orientation);
283 int32_t val;
284 switch (upLoadRecord.orientation) {
285 case ROTATE_ANGLE_0:
286 val = ORIENTATION_NORMAL;
287 break;
288 case ROTATE_ANGLE_90:
289 val = ORIENTATION_ROTATE_90;
290 break;
291 case ROTATE_ANGLE_180:
292 val = ORIENTATION_ROTATE_180;
293 break;
294 case ROTATE_ANGLE_270:
295 val = ORIENTATION_ROTATE_270;
296 break;
297 default:
298 val = ORIENTATION_NORMAL;
299 break;
300 }
301 map["rotate"] = MDKRecordField(val);
302 return E_OK;
303 }
304
HandleSourcePath(std::map<std::string,MDKRecordField> & properties,const CloudMdkRecordPhotosVo & upLoadRecord)305 int32_t CloudFileDataConvert::HandleSourcePath(
306 std::map<std::string, MDKRecordField> &properties, const CloudMdkRecordPhotosVo &upLoadRecord)
307 {
308 if (!upLoadRecord.sourcePath.empty()) {
309 properties["sourcePath"] = MDKRecordField(upLoadRecord.sourcePath);
310 }
311 return E_OK;
312 }
313
HandleProperties(std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotosVo & upLoadRecord)314 int32_t CloudFileDataConvert::HandleProperties(
315 std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotosVo &upLoadRecord)
316 {
317 std::map<std::string, MDKRecordField> properties;
318 this->HandleSourcePath(properties, upLoadRecord);
319 properties["sourceFileName"] = MDKRecordField(upLoadRecord.displayName);
320 properties["first_update_time"] = MDKRecordField(std::to_string(upLoadRecord.dateAdded));
321 properties["fileCreateTime"] = MDKRecordField(std::to_string(upLoadRecord.dateTaken));
322 properties["detail_time"] = MDKRecordField(upLoadRecord.detailTime);
323 properties["duration"] = MDKRecordField(upLoadRecord.duration);
324 this->HandleWidthAndHeight(properties, upLoadRecord);
325 HandlePosition(properties, upLoadRecord);
326 HandleRotate(properties, upLoadRecord);
327 data[FILE_PROPERTIES] = MDKRecordField(properties);
328 return E_OK;
329 }
330
GetLowerPath(const std::string & path)331 std::string CloudFileDataConvert::GetLowerPath(const std::string &path)
332 {
333 size_t pos = path.find(sandboxPrefix_);
334 if (pos == std::string::npos) {
335 MEDIA_ERR_LOG("invalid path");
336 return "";
337 }
338 return prefix_ + std::to_string(userId_) + suffix_ + path.substr(pos + sandboxPrefix_.size());
339 }
340
DeleteTmpFile(bool needDelete,const std::string & path)341 static void DeleteTmpFile(bool needDelete, const std::string &path)
342 {
343 if (!needDelete) {
344 return;
345 }
346 if (unlink(path.c_str()) < 0) {
347 MEDIA_ERR_LOG("unlink temp file fail, err: %{public}d", errno);
348 }
349 }
350
HandleRawFile(std::map<std::string,MDKRecordField> & data,std::string & path,bool isMovingPhoto)351 int32_t CloudFileDataConvert::HandleRawFile(
352 std::map<std::string, MDKRecordField> &data, std::string &path, bool isMovingPhoto)
353 {
354 std::string rawFilePath = PhotoFileUtils::GetEditDataSourcePath(path, userId_);
355 MEDIA_INFO_LOG("HandleEditData rawFilePath %{public}s", rawFilePath.c_str());
356 if (rawFilePath.empty()) {
357 return E_OK;
358 }
359 struct stat fileStat;
360 int err = stat(rawFilePath.c_str(), &fileStat);
361 if (err < 0 && errno == ENOENT) {
362 return E_OK;
363 }
364 if (err < 0 && errno != ENOENT) {
365 int errNum = errno;
366 MEDIA_ERR_LOG("get raw size failed errno: %{public}d", errNum);
367 return E_CONTENT_SOURCE_BASIC + errNum;
368 }
369
370 if (fileStat.st_size <= 0) {
371 MEDIA_ERR_LOG("raw size err");
372 return E_CONTENT_RAW_SIZE_IS_ZERO;
373 }
374 if (isMovingPhoto) {
375 if (MovingPhotoFileUtils::ConvertToSourceLivePhoto(path, rawFilePath, userId_) != E_OK) {
376 MEDIA_ERR_LOG("ConvertToSourceLivePhoto failed %{public}s", path.c_str());
377 return E_PATH;
378 }
379 }
380 MDKAsset content;
381 content.uri = move(rawFilePath);
382 content.assetName = FILE_RAW;
383 content.operationType = MDKAssetOperType::DK_ASSET_ADD;
384 data[FILE_RAW] = MDKRecordField(content);
385 return E_OK;
386 }
387
HandleEditData(std::map<std::string,MDKRecordField> & data,std::string & path)388 int32_t CloudFileDataConvert::HandleEditData(std::map<std::string, MDKRecordField> &data, std::string &path)
389 {
390 MEDIA_INFO_LOG("enter HandleEditData editDataPath %{public}s", path.c_str());
391 std::string editDataPath = PhotoFileUtils::GetEditDataPath(path, userId_);
392 MEDIA_INFO_LOG("HandleEditData editDataPath %{public}s", editDataPath.c_str());
393 if (!editDataPath.empty()) {
394 MDKAsset content;
395 struct stat fileStat;
396 if (stat(editDataPath.c_str(), &fileStat) == 0 && fileStat.st_size > 0) {
397 MEDIA_INFO_LOG("HandleEditData editDataPath is not empty and stat success");
398 content.uri = move(editDataPath);
399 content.assetName = FILE_EDIT_DATA;
400 content.operationType = MDKAssetOperType::DK_ASSET_ADD;
401 data[FILE_EDIT_DATA] = MDKRecordField(content);
402 }
403 }
404 return E_OK;
405 }
406
HandleEditDataCamera(std::map<std::string,MDKRecordField> & data,std::string & path)407 int32_t CloudFileDataConvert::HandleEditDataCamera(std::map<std::string, MDKRecordField> &data, std::string &path)
408 {
409 MEDIA_INFO_LOG("enter HandleEditData editDataPath %{public}s", path.c_str());
410 std::string editDataCameraPath = PhotoFileUtils::GetEditDataCameraPath(path, userId_);
411
412 // -- editDataCamera as properties, append to FILE_ATTRIBUTES --
413 MEDIA_INFO_LOG("HandleEditData editDataCameraPath %{public}s", editDataCameraPath.c_str());
414 if (!editDataCameraPath.empty() && access(editDataCameraPath.c_str(), F_OK) == 0) {
415 MEDIA_INFO_LOG("HandleEditData editDataCameraPath is not empty and access success");
416 if (data.find(FILE_ATTRIBUTES) == data.end()) {
417 MEDIA_ERR_LOG("Cannot add edit_data_camera to properties.");
418 return E_INVALID_ARGUMENTS;
419 }
420 std::string buf;
421 if (!LoadStringFromFile(editDataCameraPath, buf)) {
422 MEDIA_ERR_LOG("editDataCameraPath read from file failed.");
423 return E_INVALID_ARGUMENTS;
424 }
425 std::map<std::string, MDKRecordField> map;
426 data[FILE_ATTRIBUTES].GetRecordMap(map);
427 map[FILE_EDIT_DATA_CAMERA] = MDKRecordField(buf);
428 data[FILE_ATTRIBUTES] = MDKRecordField(map);
429 }
430 return E_OK;
431 }
432
HandleEditData(std::map<std::string,MDKRecordField> & data,std::string & path,bool isMovingPhoto)433 int32_t CloudFileDataConvert::HandleEditData(
434 std::map<std::string, MDKRecordField> &data, std::string &path, bool isMovingPhoto)
435 {
436 MEDIA_INFO_LOG("enter HandleEditData editDataPath %{public}s, %{public}d", path.c_str(), isMovingPhoto);
437 int32_t ret = this->HandleRawFile(data, path, isMovingPhoto);
438 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleEditData HandleRawFile err: %{public}d", ret);
439 this->HandleEditData(data, path);
440 this->HandleEditDataCamera(data, path);
441 return E_OK;
442 }
443
CheckContentLivePhoto(const CloudMdkRecordPhotosVo & upLoadRecord,std::string & lowerPath)444 int32_t CloudFileDataConvert::CheckContentLivePhoto(const CloudMdkRecordPhotosVo &upLoadRecord, std::string &lowerPath)
445 {
446 std::string path = upLoadRecord.data;
447 int64_t coverPosition = upLoadRecord.coverPosition;
448 bool isMovingPhoto = MovingPhotoFileUtils::IsMovingPhoto(
449 upLoadRecord.subtype, upLoadRecord.movingPhotoEffectMode, upLoadRecord.originalSubtype);
450 bool isGraffiti = MovingPhotoFileUtils::IsGraffiti(upLoadRecord.subtype, upLoadRecord.originalSubtype);
451 CHECK_AND_PRINT_LOG(!isMovingPhoto && !isGraffiti,
452 "HandleContent isMovingPhoto: %{public}d, isGraffiti: %{public}d", isMovingPhoto, isGraffiti);
453 if (isMovingPhoto && !isGraffiti) {
454 if (MovingPhotoFileUtils::ConvertToLivePhoto(path, coverPosition, lowerPath, userId_) != E_OK) {
455 MEDIA_ERR_LOG("covert to live photo fail");
456 return E_CONTENT_COVERT_LIVE_PHOTO;
457 }
458 } else {
459 lowerPath = GetLowerPath(path);
460 }
461 return E_OK;
462 }
463
CheckContentFile(const CloudMdkRecordPhotosVo & upLoadRecord,const std::string & lowerPath)464 int32_t CloudFileDataConvert::CheckContentFile(const CloudMdkRecordPhotosVo &upLoadRecord, const std::string &lowerPath)
465 {
466 bool isMovingPhoto = MovingPhotoFileUtils::IsMovingPhoto(
467 upLoadRecord.subtype, upLoadRecord.movingPhotoEffectMode, upLoadRecord.originalSubtype);
468 bool isGraffiti = MovingPhotoFileUtils::IsGraffiti(upLoadRecord.subtype, upLoadRecord.originalSubtype);
469 struct stat fileStat;
470 int err = stat(lowerPath.c_str(), &fileStat);
471 if (err < 0) {
472 int32_t errNum = errno;
473 UTIL_SYNC_FAULT_REPORT({bundleName_,
474 UtilCloud::FaultScenarioCode::CLOUD_FULL_SYNC,
475 UtilCloud::FaultType::FILE,
476 errNum,
477 "get context size failed errno : " + std::to_string(errNum)});
478 MEDIA_ERR_LOG("HandleContent errno : %{public}d, path : %{public}s, %{public}d, %{public}d",
479 errno,
480 lowerPath.c_str(),
481 isMovingPhoto,
482 isGraffiti);
483 DeleteTmpFile(isMovingPhoto && !isGraffiti, lowerPath);
484 return E_CONTENT_SOURCE_BASIC + errNum;
485 }
486 if (fileStat.st_size <= 0) {
487 MEDIA_ERR_LOG("HandleContent content size err");
488 DeleteTmpFile(isMovingPhoto && !isGraffiti, lowerPath);
489 return E_CONTENT_SIZE_IS_ZERO;
490 }
491 return E_OK;
492 }
493
HandleContent(std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotosVo & upLoadRecord)494 int32_t CloudFileDataConvert::HandleContent(
495 std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotosVo &upLoadRecord)
496 {
497 std::string path = upLoadRecord.data;
498 std::string lowerPath = "";
499 bool isMovingPhoto = MovingPhotoFileUtils::IsMovingPhoto(
500 upLoadRecord.subtype, upLoadRecord.movingPhotoEffectMode, upLoadRecord.originalSubtype);
501 bool isGraffiti = MovingPhotoFileUtils::IsGraffiti(upLoadRecord.subtype, upLoadRecord.originalSubtype);
502 CHECK_AND_PRINT_LOG(!isMovingPhoto && !isGraffiti,
503 "HandleContent isMovingPhoto: %{public}d, isGraffiti: %{public}d", isMovingPhoto, isGraffiti);
504 int32_t ret = this->CheckContentLivePhoto(upLoadRecord, lowerPath);
505 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleContent CheckContentLivePhoto err: %{public}d", ret);
506 ret = this->CheckContentFile(upLoadRecord, lowerPath);
507 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleContent err: %{public}d", ret);
508 /* asset */
509 MDKAsset content;
510 content.uri = move(lowerPath);
511 content.assetName = FILE_CONTENT;
512 content.operationType = MDKAssetOperType::DK_ASSET_ADD;
513 data[FILE_CONTENT] = MDKRecordField(content);
514 ret = HandleEditData(data, path, isMovingPhoto);
515 if (ret != E_OK) {
516 MEDIA_ERR_LOG("HandleContent handle EditData err %{public}d", ret);
517 DeleteTmpFile(isMovingPhoto && !isGraffiti, lowerPath);
518 return ret;
519 }
520 return E_OK;
521 }
522
HandleThumbnail(std::map<std::string,MDKRecordField> & recordData,std::string & path,bool needUseExDir)523 int32_t CloudFileDataConvert::HandleThumbnail(
524 std::map<std::string, MDKRecordField> &recordData, std::string &path, bool needUseExDir)
525 {
526 std::string thumbnailUploadPath;
527 std::string thumbnailExPath = GetThumbPath(path, THUMB_EX_SUFFIX);
528 if (!needUseExDir) {
529 std::string thumbnailPath = GetThumbPath(path, THUMB_SUFFIX);
530 if (access(thumbnailPath.c_str(), F_OK)) {
531 UTIL_SYNC_FAULT_REPORT({bundleName_,
532 UtilCloud::FaultScenarioCode::CLOUD_FULL_SYNC,
533 UtilCloud::FaultType::FILE,
534 F_OK,
535 "thumbnailPath " + ReportUtils::GetAnonyString(thumbnailPath) + " doesn't exist"});
536 MEDIA_ERR_LOG("ReportFailure: thumnail doesn't exist %{public}s", thumbnailPath.c_str());
537 return E_THM_SOURCE_BASIC + ENOENT;
538 }
539 thumbnailUploadPath = thumbnailPath;
540 } else {
541 if (access(thumbnailExPath.c_str(), F_OK)) {
542 UTIL_SYNC_FAULT_REPORT({bundleName_,
543 UtilCloud::FaultScenarioCode::CLOUD_FULL_SYNC,
544 UtilCloud::FaultType::FILE,
545 F_OK,
546 "thumbnailExPath " + ReportUtils::GetAnonyString(thumbnailExPath) + " doesn't exist"});
547 MEDIA_ERR_LOG("ReportFailure: thumbnailEx doesn't exist %{public}s", thumbnailExPath.c_str());
548 return E_THM_SOURCE_BASIC + ENOENT;
549 }
550 thumbnailUploadPath = thumbnailExPath;
551 }
552 /* asset */
553 MDKAsset content;
554 content.uri = move(thumbnailUploadPath);
555 content.assetName = FILE_THUMBNAIL;
556 content.operationType = MDKAssetOperType::DK_ASSET_ADD;
557 recordData["thumbnail"] = MDKRecordField(content);
558 return E_OK;
559 }
560
GetParentPath(const std::string & path)561 std::string CloudFileDataConvert::GetParentPath(const std::string &path)
562 {
563 std::string name;
564 size_t slashIndex = path.rfind("/");
565 if (slashIndex != std::string::npos) {
566 name = path.substr(0, slashIndex);
567 }
568 return name;
569 }
570
HandleLcd(std::map<std::string,MDKRecordField> & recordData,std::string & path,bool needUseExDir)571 int32_t CloudFileDataConvert::HandleLcd(
572 std::map<std::string, MDKRecordField> &recordData, std::string &path, bool needUseExDir)
573 {
574 std::string lcdUploadPath;
575 std::string lcdExPath = GetThumbPath(path, LCD_EX_SUFFIX);
576 std::string lcdExDir = GetParentPath(lcdExPath);
577 if (!needUseExDir) {
578 std::string lcdPath = GetThumbPath(path, LCD_SUFFIX);
579 if (access(lcdPath.c_str(), F_OK)) {
580 UTIL_SYNC_FAULT_REPORT({bundleName_,
581 UtilCloud::FaultScenarioCode::CLOUD_FULL_SYNC,
582 UtilCloud::FaultType::FILE,
583 F_OK,
584 "lcdPath " + ReportUtils::GetAnonyString(lcdPath) + " doesn't exist"});
585 MEDIA_ERR_LOG("ReportFailure: HandleLcd lcd path doesn't exist %{public}s", lcdPath.c_str());
586 return E_LCD_SOURCE_BASIC + ENOENT;
587 }
588 lcdUploadPath = lcdPath;
589 } else {
590 if (access(lcdExPath.c_str(), F_OK)) {
591 UTIL_SYNC_FAULT_REPORT({bundleName_,
592 UtilCloud::FaultScenarioCode::CLOUD_FULL_SYNC,
593 UtilCloud::FaultType::FILE,
594 F_OK,
595 "lcdExPath " + ReportUtils::GetAnonyString(lcdExPath) + " doesn't exist"});
596 MEDIA_ERR_LOG("ReportFailure: HandleLcd lcdEx path doesn't exist %{public}s", lcdExPath.c_str());
597 return E_LCD_SOURCE_BASIC + ENOENT;
598 }
599 lcdUploadPath = lcdExPath;
600 }
601 /* asset */
602 MDKAsset content;
603 content.uri = move(lcdUploadPath);
604 content.assetName = FILE_LCD;
605 content.operationType = MDKAssetOperType::DK_ASSET_ADD;
606 recordData[FILE_LCD] = MDKRecordField(content);
607 return E_OK;
608 }
609
HandleAttachments(std::map<std::string,MDKRecordField> & recordData,const CloudMdkRecordPhotosVo & upLoadRecord)610 int32_t CloudFileDataConvert::HandleAttachments(
611 std::map<std::string, MDKRecordField> &recordData, const CloudMdkRecordPhotosVo &upLoadRecord)
612 {
613 bool needUseExDir;
614 if (upLoadRecord.mediaType == MEDIA_TYPE_IMAGE) {
615 needUseExDir = upLoadRecord.exifRotate > static_cast<int32_t>(ExifRotateType::TOP_LEFT);
616 } else {
617 needUseExDir = false;
618 }
619 /* content */
620 int32_t ret = E_OK;
621 if (upLoadRecord.dirty == -1 || upLoadRecord.dirty != static_cast<int32_t>(DirtyType::TYPE_TDIRTY)) {
622 MEDIA_INFO_LOG("handle content when not TDIRTY");
623 ret = HandleContent(recordData, upLoadRecord);
624 CHECK_AND_PRINT_LOG(ret == E_OK, "failed to handle content");
625 }
626
627 /* thumb */
628 std::string path = upLoadRecord.data;
629 ret = HandleThumbnail(recordData, path, needUseExDir);
630 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleThumbnail failed. ret: %{public}d.", ret);
631 /* lcd */
632 ret = HandleLcd(recordData, path, needUseExDir);
633 return ret;
634 }
635
HandleSize(std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotosVo & upLoadRecord)636 int32_t CloudFileDataConvert::HandleSize(
637 std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotosVo &upLoadRecord)
638 {
639 if (upLoadRecord.size <= 0) {
640 MEDIA_ERR_LOG("ReportFailure: size is invalid");
641 return E_DB_SIZE_IS_ZERO;
642 }
643 data["size"] = MDKRecordField(upLoadRecord.size);
644 return E_OK;
645 }
646
HandleWidthAndHeight(std::map<std::string,MDKRecordField> & properties,const CloudMdkRecordPhotosVo & upLoadRecord)647 int32_t CloudFileDataConvert::HandleWidthAndHeight(
648 std::map<std::string, MDKRecordField> &properties, const CloudMdkRecordPhotosVo &upLoadRecord)
649 {
650 bool isValid = upLoadRecord.height != 0 && upLoadRecord.width != 0;
651 CHECK_AND_PRINT_LOG(isValid, "Get local height or local width is 0 ");
652 /* Resolution is combined by cloud sdk, just upload height and width */
653 if (upLoadRecord.height != 0) {
654 properties["height"] = MDKRecordField(upLoadRecord.height);
655 }
656 if (upLoadRecord.width != 0) {
657 properties["width"] = MDKRecordField(upLoadRecord.width);
658 }
659 return E_OK;
660 }
661
HandleCompatibleFileds(std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotosVo & upLoadRecord)662 int32_t CloudFileDataConvert::HandleCompatibleFileds(
663 std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotosVo &upLoadRecord)
664 {
665 /* gallery-specific or shared fileds */
666 data["fileName"] = MDKRecordField(upLoadRecord.displayName);
667 data["createdTime"] = MDKRecordField(upLoadRecord.dateTaken);
668 data["hashId"] = MDKRecordField("Md5_default_hash");
669 int32_t ret = this->HandleSize(data, upLoadRecord);
670 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleSize failed, ret: %{public}d", ret);
671 data["source"] = MDKRecordField(upLoadRecord.deviceName);
672 data["recycled"] = MDKRecordField(!!(upLoadRecord.dateTrashed));
673 data["recycledTime"] = MDKRecordField(std::to_string(upLoadRecord.dateTrashed));
674 data["favorite"] = MDKRecordField(!!(upLoadRecord.isFavorite));
675 data["description"] = MDKRecordField(upLoadRecord.userComment);
676 HandleFileType(data, upLoadRecord);
677
678 /* gallery expand fields */
679 HandleProperties(data, upLoadRecord);
680
681 /* cloud sdk extra feature */
682 if (type_ != CloudOperationType::FILE_METADATA_MODIFY) {
683 ret = HandleAttachments(data, upLoadRecord);
684 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleAttachments failed, ret: %{public}d.", ret);
685 }
686
687 /* cloudsync-specific fields */
688 data["mimeType"] = MDKRecordField(upLoadRecord.mimeType);
689 data["editedTime"] = MDKRecordField(std::to_string(upLoadRecord.dateModified));
690 return E_OK;
691 }
692
SetSourceAlbum(MDKRecord & record,const CloudMdkRecordPhotosVo & upLoadRecord)693 int32_t CloudFileDataConvert::SetSourceAlbum(MDKRecord &record, const CloudMdkRecordPhotosVo &upLoadRecord)
694 {
695 std::map<std::string, MDKRecordField> data;
696 record.GetRecordData(data);
697 std::string displayName = upLoadRecord.displayName;
698 int32_t hidden = upLoadRecord.hidden;
699 std::string albumCloudId = upLoadRecord.albumCloudId;
700 std::string albumLPath = upLoadRecord.albumLPath;
701 if (hidden == 1) {
702 data["albumId"] = MDKRecordField("default-album-4");
703 // Upload: hidden === 0, Download: hidden = 1 when albumId default-album-4
704 if (data.find(FILE_ATTRIBUTES) != data.end()) {
705 std::map<std::string, MDKRecordField> attrs = data[FILE_ATTRIBUTES];
706 attrs[MediaColumn::MEDIA_HIDDEN] = MDKRecordField(0);
707 data[FILE_ATTRIBUTES] = MDKRecordField(attrs);
708 }
709 } else if (!albumCloudId.empty()) {
710 data["albumId"] = MDKRecordField(albumCloudId);
711 }
712 MEDIA_DEBUG_LOG("SetSourceAlbum Hidden:%{public}d, albumCloudId:%{public}s, albumLPath::%{public}s",
713 hidden,
714 albumCloudId.c_str(),
715 albumLPath.c_str());
716 data["isLogic"] = MDKRecordField(false);
717 // pictures should be found an albumid except for hidden and recycle
718 bool isRecycle = upLoadRecord.dateTrashed != 0;
719 if (!isRecycle && !hidden && albumCloudId.empty()) {
720 record.SetRecordData(data);
721 MEDIA_ERR_LOG("visible media, but albumid is empty");
722 return E_DB_ALBUM_NOT_FOUND;
723 }
724 if (!albumLPath.empty()) {
725 if (data.find(FILE_PROPERTIES) == data.end()) {
726 MEDIA_ERR_LOG("record data donnot have properties set");
727 record.SetRecordData(data);
728 return E_CLOUD_SYNC_DATA;
729 }
730 std::map<std::string, MDKRecordField> properties = data[FILE_PROPERTIES];
731 std::string sourcePath;
732 if (albumCloudId == "default-album-2") {
733 sourcePath = SCREENSHOT_ALBUM_PATH + displayName;
734 } else {
735 sourcePath = "/storage/emulated/0" + albumLPath + "/" + displayName;
736 }
737 properties.erase("sourcePath");
738 properties["sourcePath"] = MDKRecordField(sourcePath);
739 data[FILE_PROPERTIES] = MDKRecordField(properties);
740 }
741 record.SetRecordData(data);
742 return E_OK;
743 }
744
InsertAlbumIdChanges(MDKRecord & record,std::vector<MDKRecord> & records,const CloudMdkRecordPhotosVo & upLoadRecord)745 int32_t CloudFileDataConvert::InsertAlbumIdChanges(
746 MDKRecord &record, std::vector<MDKRecord> &records, const CloudMdkRecordPhotosVo &upLoadRecord)
747 {
748 MDKRecord tmp = record;
749 std::map<std::string, MDKRecordField> data;
750 tmp.GetRecordData(data);
751 std::string albumCloudId;
752 if (data.find("albumId") == data.end() || data["albumId"].GetString(albumCloudId) != MDKLocalErrorCode::NO_ERROR) {
753 MEDIA_ERR_LOG("get albumId failed");
754 }
755 std::vector<MDKRecordField> rmList;
756 /* remove */
757 std::vector<std::string> removeId = upLoadRecord.removeAlbumCloudId;
758 for (auto &id : removeId) {
759 rmList.push_back(MDKRecordField(MDKReference{id, "album"}));
760 }
761 if (!rmList.empty()) {
762 data.erase("albumId");
763 data["isLogic"] = MDKRecordField(true);
764 data["FILE_RM_LOGIC_ALBUM_IDS"] = MDKRecordField(rmList);
765 tmp.SetRecordData(data);
766 records.push_back(tmp);
767 }
768 return E_OK;
769 }
770
ConvertToMdkRecord(const CloudMdkRecordPhotosVo & upLoadRecord,MDKRecord & record)771 int32_t CloudFileDataConvert::ConvertToMdkRecord(const CloudMdkRecordPhotosVo &upLoadRecord, MDKRecord &record)
772 {
773 MEDIA_INFO_LOG("CloudFileDataConvert::ConvertToMdkRecord type:%{public}d, cloudId: %{public}s",
774 static_cast<int32_t>(type_),
775 upLoadRecord.cloudId.c_str());
776 record.SetRecordType(recordType_);
777 if (type_ == CloudOperationType::FILE_CREATE) {
778 record.SetNewCreate(true);
779 }
780 record.SetRecordId(upLoadRecord.cloudId);
781 if (type_ == CloudOperationType::FILE_DELETE) {
782 return E_OK;
783 }
784 std::map<std::string, MDKRecordField> data;
785 int32_t ret = HandleUniqueFileds(data, upLoadRecord);
786 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleUniqueFileds failed, ret: %{public}d", ret);
787 ret = HandleCompatibleFileds(data, upLoadRecord);
788 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "HandleCompatibleFileds failed, ret: %{public}d", ret);
789 record.SetRecordData(data);
790 ret = SetSourceAlbum(record, upLoadRecord);
791 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "SetSourceAlbum failed, ret: %{public}d", ret);
792 return E_OK;
793 }
794
BuildCopyRecord(const std::string & cloudId,const MDKRecordOperResult & result,OnCopyRecord & record)795 int32_t CloudFileDataConvert::BuildCopyRecord(
796 const std::string &cloudId, const MDKRecordOperResult &result, OnCopyRecord &record)
797 {
798 MDKRecordPhotosData photosData = MDKRecordPhotosData(result.GetDKRecord());
799 std::optional<std::string> optionalCloudId = photosData.GetCloudId();
800 record.cloudId = cloudId;
801 std::optional<std::string> optPath = photosData.GetFilePath();
802 record.path = optPath.value_or("");
803 std::optional<int32_t> optFileId = photosData.GetFileId();
804 record.fileId = optFileId.value_or(-1);
805 std::optional<std::string> optFileName = photosData.GetFileName();
806 record.fileName = optFileName.value_or("");
807 std::optional<int64_t> optSize = photosData.GetSize();
808 record.size = optSize.value_or(-1);
809 std::optional<int64_t> optSingleEditTime = photosData.GetDateModified().value_or(0);
810 int64_t singleEditTime = optSingleEditTime.value();
811 int64_t dualEditTime = static_cast<int64_t>(result.GetDKRecord().GetEditedTime());
812 record.modifyTime = dualEditTime > singleEditTime ? dualEditTime : singleEditTime;
813 record.createTime = static_cast<int64_t>(result.GetDKRecord().GetCreateTime());
814 int32_t rotate = photosData.GetRotate().value_or(ORIENTATION_NORMAL);
815 if (FILE_ROTATIONS.find(rotate) != FILE_ROTATIONS.end()) {
816 record.rotation = FILE_ROTATIONS.find(rotate)->second;
817 }
818 std::optional<int32_t> optFileType = photosData.GetFileType();
819 record.fileType = optFileType.value_or(-1);
820 std::optional<std::string> optSourcePath = photosData.GetSourcePath();
821 record.sourcePath = optSourcePath.value_or("");
822 record.version = result.GetDKRecord().GetVersion();
823 record.serverErrorCode = result.GetDKError().serverErrorCode;
824 record.errorType = static_cast<ErrorType>(static_cast<int32_t>(result.GetDKError().errorType));
825 record.isSuccess = result.IsSuccess();
826 ConvertErrorTypeDetails(result, record.errorDetails);
827 return E_OK;
828 }
829
ConvertErrorTypeDetails(const MDKRecordOperResult & result,std::vector<CloudErrorDetail> & errorDetails)830 void CloudFileDataConvert::ConvertErrorTypeDetails(
831 const MDKRecordOperResult &result, std::vector<CloudErrorDetail> &errorDetails)
832 {
833 auto errorType = result.GetDKError();
834 if (errorType.errorDetails.empty()) {
835 return;
836 }
837 for (const auto &element : errorType.errorDetails) {
838 CloudErrorDetail detail;
839 detail.domain = element.domain;
840 detail.reason = element.reason;
841 detail.errorCode = element.errorCode;
842 detail.description = element.description;
843 detail.errorPos = element.errorPos;
844 detail.errorParam = element.errorParam;
845 detail.detailCode = element.detailCode;
846 errorDetails.push_back(detail);
847 }
848 }
849
BuildModifyRecord(const std::string & cloudId,const MDKRecordOperResult & result,OnModifyRecord & record)850 int32_t CloudFileDataConvert::BuildModifyRecord(
851 const std::string &cloudId, const MDKRecordOperResult &result, OnModifyRecord &record)
852 {
853 MDKRecordPhotosData photosData = MDKRecordPhotosData(result.GetDKRecord());
854 std::optional<std::string> optionalCloudId = photosData.GetCloudId();
855 record.cloudId = cloudId;
856 record.path = photosData.GetFilePath().value_or("");
857 record.fileName = photosData.GetFileName().value_or("");
858 record.fileId = photosData.GetFileId().value_or(-1);
859 int64_t singleEditTime = photosData.GetDateModified().value_or(0);
860 int64_t dualEditTime = static_cast<int64_t>(result.GetDKRecord().GetEditedTime());
861 record.modifyTime = dualEditTime > singleEditTime ? dualEditTime : singleEditTime;
862 record.metaDateModified = photosData.GetPhotoMetaDateModified().value_or(-1);
863 record.version = result.GetDKRecord().GetVersion();
864 record.isSuccess = result.IsSuccess();
865 record.serverErrorCode = result.GetDKError().serverErrorCode;
866 ConvertErrorTypeDetails(result, record.errorDetails);
867 return E_OK;
868 }
869
ConvertFdirtyRecord(const std::string & cloudId,const MDKRecordOperResult & result,OnFileDirtyRecord & record)870 int32_t CloudFileDataConvert::ConvertFdirtyRecord(
871 const std::string &cloudId, const MDKRecordOperResult &result, OnFileDirtyRecord &record)
872 {
873 MDKRecordPhotosData photosData = MDKRecordPhotosData(result.GetDKRecord());
874 record.cloudId = cloudId;
875 record.fileId = photosData.GetFileId().value_or(-1);
876 auto metaDateModifiedOpt = photosData.GetPhotoMetaDateModified();
877 if (metaDateModifiedOpt.has_value()) {
878 record.metaDateModified = metaDateModifiedOpt.value();
879 } else {
880 record.metaDateModified = -1;
881 }
882 record.path = photosData.GetFilePath().value_or("");
883 record.livePhotoCachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(record.path, userId_);
884 record.isSuccess = result.IsSuccess();
885 record.version = result.GetDKRecord().GetVersion();
886 record.serverErrorCode = result.GetDKError().serverErrorCode;
887 ConvertErrorTypeDetails(result, record.errorDetails);
888 return E_OK;
889 }
890
ConvertToOnCreateRecord(const std::string & cloudId,const MDKRecordOperResult & result,OnCreateRecord & record)891 int32_t CloudFileDataConvert::ConvertToOnCreateRecord(
892 const std::string &cloudId, const MDKRecordOperResult &result, OnCreateRecord &record)
893 {
894 MDKRecordPhotosData photosData = MDKRecordPhotosData(result.GetDKRecord());
895 record.cloudId = cloudId;
896 record.fileId = photosData.GetFileId().value_or(-1);
897 record.path = photosData.GetFilePath().value_or("");
898 record.fileName = photosData.GetFileName().value_or("");
899 record.localId = photosData.GetLocalId().value_or(-1);
900 record.fileType = photosData.GetFileType().value_or(-1);
901 record.size = photosData.GetSize().value_or(-1);
902 record.createTime = photosData.GetCreatedTime().value_or(-1);
903 record.editedTimeMs = photosData.GetEditTimeMs().value_or(-1);
904 record.metaDateModified = photosData.GetPhotoMetaDateModified().value_or(-1);
905 record.version = result.GetDKRecord().GetVersion();
906 record.isSuccess = result.IsSuccess();
907 record.livePhotoCachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(record.path, userId_);
908 record.serverErrorCode = result.GetDKError().serverErrorCode;
909 ConvertErrorTypeDetails(result, record.errorDetails);
910 return E_OK;
911 }
912
ExtractPosition(const std::string & position,double & latitude,double & longitude)913 int32_t CloudFileDataConvert::ExtractPosition(const std::string &position, double &latitude, double &longitude)
914 {
915 CHECK_AND_RETURN_RET_LOG(!position.empty(), E_INVAL_ARG, "position is empty.");
916 auto json = nlohmann::json::parse(position, nullptr, false);
917 bool isValid = !json.is_discarded();
918 CHECK_AND_RETURN_RET_LOG(isValid, E_INVAL_ARG, "position json parse error, %{private}s", position.c_str());
919 isValid = json.contains("x") && json.contains("y");
920 CHECK_AND_RETURN_RET_LOG(isValid, E_INVAL_ARG, "position miss x or y fields, %{private}s", position.c_str());
921 isValid = json["x"].is_string() && json["y"].is_string();
922 CHECK_AND_RETURN_RET_LOG(isValid, E_INVAL_ARG, "position x or y is not string, %{private}s", position.c_str());
923 std::string latitudeStr = json["x"].get<std::string>();
924 std::string longitudeStr = json["y"].get<std::string>();
925 std::stringstream latitudestream(latitudeStr);
926 std::stringstream longitudestream(longitudeStr);
927 latitudestream.precision(15); // 15:precision
928 longitudestream.precision(15); // 15:precision
929 latitude = 0.0;
930 longitude = 0.0;
931 latitudestream >> latitude;
932 longitudestream >> longitude;
933 return E_OK;
934 }
935
ExtractPosition(MDKRecordPhotosData & data,OnFetchPhotosVo & onFetchPhotoVo)936 int32_t CloudFileDataConvert::ExtractPosition(MDKRecordPhotosData &data, OnFetchPhotosVo &onFetchPhotoVo)
937 {
938 std::string position = data.GetPosition().value_or("");
939 return ExtractPosition(position, onFetchPhotoVo.latitude, onFetchPhotoVo.longitude);
940 }
941
ConvertProperties(MDKRecordPhotosData & data,OnFetchPhotosVo & onFetchPhotoVo)942 void CloudFileDataConvert::ConvertProperties(MDKRecordPhotosData &data, OnFetchPhotosVo &onFetchPhotoVo)
943 {
944 onFetchPhotoVo.hasproperties = data.hasProperties();
945 int32_t rotate = data.GetRotate().value_or(ORIENTATION_NORMAL);
946 CHECK_AND_PRINT_LOG(!(FILE_ROTATIONS.find(rotate) == FILE_ROTATIONS.end()), "not find mdkRecord Rotate");
947 onFetchPhotoVo.rotation = FILE_ROTATIONS.find(rotate)->second;
948 onFetchPhotoVo.fileSourcePath = data.GetSourcePath().value_or("");
949 onFetchPhotoVo.firstVisitTime = data.GetFirstUpdateTime().value_or("");
950 onFetchPhotoVo.photoHeight = data.GetHeight().value_or(0);
951 onFetchPhotoVo.photoWidth = data.GetWidth().value_or(0);
952 onFetchPhotoVo.detailTime = data.GetDetailTime().value_or("");
953 ExtractPosition(data, onFetchPhotoVo);
954 }
955
ConvertAttributes(MDKRecordPhotosData & data,OnFetchPhotosVo & onFetchPhotoVo)956 void CloudFileDataConvert::ConvertAttributes(MDKRecordPhotosData &data, OnFetchPhotosVo &onFetchPhotoVo)
957 {
958 onFetchPhotoVo.hasAttributes = data.hasAttributes();
959 onFetchPhotoVo.fileId = data.GetCloudFileId().value_or(0L);
960 onFetchPhotoVo.localPath = data.GetFilePath().value_or("");
961 onFetchPhotoVo.lcdSize = data.GetLcdSize().value_or(0L);
962 onFetchPhotoVo.thmSize = data.GetThmSize().value_or(0L);
963 onFetchPhotoVo.metaDateModified = data.GetPhotoMetaDateModified().value_or(0L);
964 onFetchPhotoVo.editedTimeMs = data.GetEditTimeMs().value_or(0L);
965 onFetchPhotoVo.fixVersion = data.GetFixVersion().value_or(-1);
966 onFetchPhotoVo.frontCamera = data.GetFrontCamera().value_or("");
967 onFetchPhotoVo.editDataCamera = data.GetEditDataCamera().value_or("");
968 onFetchPhotoVo.title = data.GetTitle().value_or("");
969 onFetchPhotoVo.mediaType = data.GetMediaType().value_or(-1);
970 onFetchPhotoVo.hidden = data.GetHidden().value_or(0);
971 onFetchPhotoVo.hiddenTime = data.GetHiddenTime().value_or(0L);
972 onFetchPhotoVo.relativePath = data.GetRelativePath().value_or("");
973 onFetchPhotoVo.virtualPath = data.GetVirtualPath().value_or("");
974 onFetchPhotoVo.dateYear = data.GetDateYear().value_or("");
975 onFetchPhotoVo.dateMonth = data.GetDateMonth().value_or("");
976 onFetchPhotoVo.dateDay = data.GetDateDay().value_or("");
977 onFetchPhotoVo.shootingMode = data.GetShootingMode().value_or("");
978 onFetchPhotoVo.shootingModeTag = data.GetShootingModeTag().value_or("");
979 onFetchPhotoVo.burstKey = data.GetBurstKey().value_or("");
980 onFetchPhotoVo.burstCoverLevel = data.GetBurstCoverLevel().value_or(1);
981 onFetchPhotoVo.subtype = data.GetSubType().value_or(0);
982 onFetchPhotoVo.originalSubtype = data.GetOriginalSubType().value_or(0);
983 onFetchPhotoVo.dynamicRangeType = data.GetDynamicRangeType().value_or(0);
984 onFetchPhotoVo.movingPhotoEffectMode = data.GetMovingPhotoEffectMode().value_or(0);
985 onFetchPhotoVo.editTime = data.GetEditTime().value_or(0);
986 onFetchPhotoVo.coverPosition = data.GetCoverPosition().value_or(0);
987 onFetchPhotoVo.isRectificationCover = data.GetIsRectificationCover().value_or(0);
988 onFetchPhotoVo.exifRotate = data.GetExifRotate().value_or(0);
989 onFetchPhotoVo.supportedWatermarkType = data.GetSupportedWatermarkType().value_or(0);
990 onFetchPhotoVo.strongAssociation = data.GetStrongAssociation().value_or(0);
991 }
992
ConvertSourceAlbumIds(const MDKRecord & mdkRecord,OnFetchPhotosVo & onFetchPhotoVo)993 void CloudFileDataConvert::ConvertSourceAlbumIds(const MDKRecord &mdkRecord, OnFetchPhotosVo &onFetchPhotoVo)
994 {
995 std::map<std::string, MDKRecordField> data;
996 std::vector<MDKRecordField> list;
997 mdkRecord.GetRecordData(data);
998 if (data.find("albumIds") != data.end()) {
999 if (data["albumIds"].GetRecordList(list) != MDKLocalErrorCode::NO_ERROR) {
1000 MEDIA_WARN_LOG("cannot get album ids from record");
1001 }
1002 } else {
1003 MEDIA_WARN_LOG("not find albumIds from record");
1004 }
1005 if (list.size() > 0) {
1006 for (const auto &it : list) {
1007 MDKReference ref;
1008 if (it.GetReference(ref) != MDKLocalErrorCode::NO_ERROR) {
1009 continue;
1010 }
1011 onFetchPhotoVo.sourceAlbumIds.emplace_back(ref.recordId);
1012 }
1013 } else {
1014 MEDIA_WARN_LOG("albumIds list size is 0");
1015 }
1016 }
1017
ConverMDKRecordToOnFetchPhotosVo(const MDKRecord & mdkRecord,OnFetchPhotosVo & onFetchPhotoVo)1018 int32_t CloudFileDataConvert::ConverMDKRecordToOnFetchPhotosVo(
1019 const MDKRecord &mdkRecord, OnFetchPhotosVo &onFetchPhotoVo)
1020 {
1021 MDKRecordPhotosData photosData = MDKRecordPhotosData(mdkRecord);
1022 onFetchPhotoVo.cloudId = mdkRecord.GetRecordId();
1023 onFetchPhotoVo.fileName = photosData.GetFileName().value_or("");
1024 onFetchPhotoVo.size = photosData.GetSize().value_or(0L);
1025 onFetchPhotoVo.dualEditTime = static_cast<int64_t>(mdkRecord.GetEditedTime());
1026 onFetchPhotoVo.createTime = static_cast<int64_t>(mdkRecord.GetCreateTime());
1027 onFetchPhotoVo.fileType = photosData.GetFileType().value_or(0L);
1028 onFetchPhotoVo.version = mdkRecord.GetVersion();
1029 onFetchPhotoVo.isDelete = mdkRecord.GetIsDelete();
1030 onFetchPhotoVo.mimeType = photosData.GetMimeType().value_or("");
1031 onFetchPhotoVo.isFavorite = photosData.GetFavorite().value_or(false);
1032 onFetchPhotoVo.isRecycle = photosData.GetRecycled().value_or(false);
1033 if (onFetchPhotoVo.isRecycle) {
1034 onFetchPhotoVo.recycledTime = photosData.GetRecycledTime().value_or(0L);
1035 }
1036 onFetchPhotoVo.description = photosData.GetDescription().value_or("");
1037 onFetchPhotoVo.source = photosData.GetSource().value_or("");
1038 onFetchPhotoVo.duration = photosData.GetDuration().value_or(0);
1039 if (onFetchPhotoVo.duration == 0) {
1040 onFetchPhotoVo.duration = photosData.GetPropertiesDuration().value_or(0);
1041 }
1042 ConvertSourceAlbumIds(mdkRecord, onFetchPhotoVo);
1043 ConvertAttributes(photosData, onFetchPhotoVo);
1044 ConvertProperties(photosData, onFetchPhotoVo);
1045 return E_OK;
1046 }
1047 } // namespace OHOS::Media::CloudSync