• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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