• 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_album_data_convert.h"
18 
19 #include <string>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <unistd.h>
23 
24 #include "directory_ex.h"
25 #include "file_ex.h"
26 #include "media_log.h"
27 #include "medialibrary_errno.h"
28 #include "cloud_media_sync_const.h"
29 #include "media_file_utils.h"
30 #include "moving_photo_file_utils.h"
31 #include "photo_file_utils.h"
32 
33 namespace OHOS::Media::CloudSync {
34 const std::string CloudAlbumDataConvert::recordType_ = "album";
CloudAlbumDataConvert(CloudAlbumOperationType type)35 CloudAlbumDataConvert::CloudAlbumDataConvert(CloudAlbumOperationType type) : type_(type)
36 {}
37 
HandleAlbumName(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotoAlbumVo & albumData)38 int32_t CloudAlbumDataConvert::HandleAlbumName(
39     std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotoAlbumVo &albumData)
40 {
41     int32_t albumType = albumData.albumType;
42     if (albumType == AlbumType::SOURCE) {
43         std::string lpath = albumData.lpath;
44         if (albumData.isInWhiteList) {
45             std::string dualName = albumData.dualAlbumName;
46             std::string albumNameEn = albumData.albumNameEn;
47             map["localPath"] = MDKRecordField(lpath);
48             if (!dualName.empty()) {
49                 map["albumName"] = MDKRecordField(dualName);
50                 return E_OK;
51             }
52             if (!albumNameEn.empty()) {
53                 map["albumName"] = MDKRecordField(albumNameEn);
54                 return E_OK;
55             }
56         }
57     }
58     map["albumName"] = MDKRecordField(albumData.albumName);
59     return E_OK;
60 }
61 
62 /* properties - general */
HandleGeneral(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotoAlbumVo & albumData)63 int32_t CloudAlbumDataConvert::HandleGeneral(
64     std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotoAlbumVo &albumData)
65 {
66     map[PhotoAlbumColumns::ALBUM_TYPE] = MDKRecordField(albumData.albumType);
67     map[PhotoAlbumColumns::ALBUM_SUBTYPE] = MDKRecordField(albumData.albumSubtype);
68     map[PhotoAlbumColumns::ALBUM_DATE_MODIFIED] = MDKRecordField(albumData.dateModified);
69     map[PhotoAlbumColumns::ALBUM_DATE_ADDED] = MDKRecordField(albumData.dateAdded);
70     map[PhotoAlbumColumns::ALBUM_BUNDLE_NAME] = MDKRecordField(albumData.bundleName);
71     map[PhotoAlbumColumns::ALBUM_LOCAL_LANGUAGE] = MDKRecordField(albumData.localLanguage);
72     map[PhotoAlbumColumns::COVER_URI_SOURCE] = MDKRecordField(albumData.coverUriSource);
73     return E_OK;
74 }
75 
HandleProperties(std::shared_ptr<MDKRecord> & record,std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotoAlbumVo & albumData)76 int32_t CloudAlbumDataConvert::HandleProperties(std::shared_ptr<MDKRecord> &record,
77     std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotoAlbumVo &albumData)
78 {
79     std::map<std::string, MDKRecordField> map;
80     /* general */
81     CHECK_AND_RETURN_RET(HandleGeneral(map, albumData) == E_OK, E_HANDLE_GENERAL_FAILED);
82     /* set map */
83     data["properties"] = MDKRecordField(map);
84     return E_OK;
85 }
86 
HandleAttributes(std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotoAlbumVo & albumData)87 int32_t CloudAlbumDataConvert::HandleAttributes(std::map<std::string, MDKRecordField> &data,
88     const CloudMdkRecordPhotoAlbumVo &albumData)
89 {
90     std::map<std::string, MDKRecordField> map;
91     if (albumData.coverUriSource == CoverUriSource::MANUAL_CLOUD_COVER) {
92         map[PhotoAlbumColumns::COVER_URI_SOURCE] = MDKRecordField(albumData.coverUriSource);
93         map[PhotoAlbumColumns::COVER_CLOUD_ID] = MDKRecordField(albumData.coverCloudId);
94     }
95     /* set map */
96     data["attributes"] = MDKRecordField(map);
97     return E_OK;
98 }
99 
HandleAlbumLogicType(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotoAlbumVo & albumData)100 int32_t CloudAlbumDataConvert::HandleAlbumLogicType(
101     std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotoAlbumVo &albumData)
102 {
103     map["logicType"] = MDKRecordField(LogicType::PHYSICAL);
104     return E_OK;
105 }
106 
HandleType(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotoAlbumVo & albumData)107 int32_t CloudAlbumDataConvert::HandleType(
108     std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotoAlbumVo &albumData)
109 {
110     map["type"] = MDKRecordField(AlbumType::NORMAL);
111     return E_OK;
112 }
113 
HandleAlbumId(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotoAlbumVo & albumData)114 int32_t CloudAlbumDataConvert::HandleAlbumId(
115     std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotoAlbumVo &albumData)
116 {
117     map["albumId"] = MDKRecordField(albumData.albumId);
118     return E_OK;
119 }
120 
HandleHashCode(const std::string & str)121 int32_t HandleHashCode(const std::string &str) __attribute__((no_sanitize("signed-integer-overflow")))
122 {
123     int32_t hash = 0;
124     for (uint32_t i = 0; i < str.length(); i++) {
125         char c = str.at(i);
126         hash = hash * HASH_VLAUE + c;
127     }
128     return hash;
129 }
130 
HandleRecordId(std::shared_ptr<MDKRecord> record,const CloudMdkRecordPhotoAlbumVo & albumData)131 int32_t CloudAlbumDataConvert::HandleRecordId(
132     std::shared_ptr<MDKRecord> record, const CloudMdkRecordPhotoAlbumVo &albumData)
133 {
134     std::map<std::string, MDKRecordField> data;
135     record->GetRecordData(data);
136     std::string recordId = albumData.cloudId;
137     if (!recordId.empty()) {
138         record->SetRecordId(recordId);
139         return E_OK;
140     }
141     std::string lpath = albumData.lpath;
142     if (albumData.isInWhiteList) {
143         std::string cloudId = albumData.albumPluginCloudId;
144         if (!cloudId.empty()) {
145             record->SetRecordId(cloudId);
146             return E_OK;
147         }
148     }
149     int64_t timeadded = albumData.dateAdded;
150     if (timeadded == 0) {
151         struct timeval tv;
152         gettimeofday(&tv, nullptr);
153         timeadded = tv.tv_sec * MILLISECOND_TO_SECOND + tv.tv_usec / MILLISECOND_TO_SECOND;
154     }
155     std::transform(lpath.begin(), lpath.end(), lpath.begin(), ::tolower);
156     int32_t hashValue = HandleHashCode(lpath);
157     std::string cloudId = "default-album-200-" + std::to_string(hashValue) + "-" + std::to_string(timeadded);
158     MEDIA_INFO_LOG("lpath is %{public}s, cloudid is %{private}s", lpath.c_str(), cloudId.c_str());
159     record->SetRecordId(cloudId);
160     return E_OK;
161 }
162 
HandlePath(std::map<std::string,MDKRecordField> & map,const CloudMdkRecordPhotoAlbumVo & albumData)163 int32_t CloudAlbumDataConvert::HandlePath(
164     std::map<std::string, MDKRecordField> &map, const CloudMdkRecordPhotoAlbumVo &albumData)
165 {
166     std::string val = albumData.lpath;
167     if (!val.empty()) {
168         map["isLogic"] = MDKRecordField(false);
169     }
170     map["localPath"] = MDKRecordField(val);
171     return E_OK;
172 }
173 
174 /* record id */
FillRecordId(std::shared_ptr<MDKRecord> record,const CloudMdkRecordPhotoAlbumVo & albumData)175 int32_t CloudAlbumDataConvert::FillRecordId(
176     std::shared_ptr<MDKRecord> record, const CloudMdkRecordPhotoAlbumVo &albumData)
177 {
178     std::string val = albumData.cloudId;
179     record->SetRecordId(val);
180     return E_OK;
181 }
182 
HandleEmptyShow(std::shared_ptr<MDKRecord> record,std::map<std::string,MDKRecordField> & data,const CloudMdkRecordPhotoAlbumVo & albumData)183 void CloudAlbumDataConvert::HandleEmptyShow(std::shared_ptr<MDKRecord> record,
184     std::map<std::string, MDKRecordField> &data, const CloudMdkRecordPhotoAlbumVo &albumData)
185 {
186     if (record->GetRecordId() == DEFAULT_HIDE_ALBUM_CLOUDID) {
187         std::map<std::string, MDKRecordField> map = data["properties"];
188         map["emptyShow"] = MDKRecordField("1");
189         data["properties"] = MDKRecordField(map);
190         record->SetRecordData(data);
191     }
192 }
193 
ConvertToDoubleScreenshot(std::shared_ptr<MDKRecord> record,std::map<std::string,MDKRecordField> & data)194 int32_t CloudAlbumDataConvert::ConvertToDoubleScreenshot(
195     std::shared_ptr<MDKRecord> record, std::map<std::string, MDKRecordField> &data)
196 {
197     std::string lPath;
198     if (data.find("localPath") == data.end() || data.at("localPath").GetString(lPath) != MDKLocalErrorCode::NO_ERROR) {
199         MEDIA_ERR_LOG("ConvertToDoubleScreenshot  lpath error");
200         return E_MEDIA_CLOUD_ARGS_INVAILD;
201     }
202 
203     MEDIA_INFO_LOG("ConvertToDoubleScreenshot lpath:%{public}s", lPath.c_str());
204     if (lPath == DEFAULT_SCREENSHOT_LPATH_EN) {
205         data["albumName"] = MDKRecordField(SCREEN_SHOT_AND_RECORDER_EN);
206         record->SetRecordId(DEFAULT_SCREENSHOT_CLOUDID);
207     }
208 
209     if (lPath == DEFAULT_SCREENRECORDS_LPATH) {
210         data["localPath"] = MDKRecordField(DEFAULT_SCREENSHOT_LPATH_EN);
211         data["albumName"] = MDKRecordField(SCREEN_SHOT_AND_RECORDER_EN);
212         record->SetRecordId(DEFAULT_SCREENSHOT_CLOUDID);
213     }
214     return E_OK;
215 }
216 
ConvertToMdkRecord(const CloudMdkRecordPhotoAlbumVo & upLoadRecord)217 std::shared_ptr<MDKRecord> CloudAlbumDataConvert::ConvertToMdkRecord(const CloudMdkRecordPhotoAlbumVo &upLoadRecord)
218 {
219     std::shared_ptr<MDKRecord> record = std::make_shared<MDKRecord>();
220     std::map<std::string, MDKRecordField> data;
221     /* basic */
222     CHECK_AND_RETURN_RET_LOG(HandleAlbumName(data, upLoadRecord) == E_OK, nullptr, "HandleAlbumName failed");
223     CHECK_AND_RETURN_RET_LOG(HandleAlbumLogicType(data, upLoadRecord) == E_OK, nullptr, "HandleAlbumLogicType failed");
224     CHECK_AND_RETURN_RET_LOG(HandleType(data, upLoadRecord) == E_OK, nullptr, "HandleType failed");
225 
226     /* properties */
227     CHECK_AND_RETURN_RET_LOG(HandleProperties(record, data, upLoadRecord) == E_OK, nullptr, "HandleProperties failed");
228     /* attributes */
229     CHECK_AND_RETURN_RET_LOG(HandleAttributes(data, upLoadRecord) == E_OK, nullptr, "HandleAttributes failed");
230     /* control info */
231     record->SetRecordType(recordType_);
232     if (type_ == PHOTO_ALBUM_CREATE) {
233         record->SetNewCreate(true);
234         CHECK_AND_RETURN_RET_LOG(HandleAlbumId(data, upLoadRecord) == E_OK, nullptr, "HandleAlbumId failed");
235         CHECK_AND_RETURN_RET_LOG(HandleRecordId(record, upLoadRecord) == E_OK, nullptr, "HandleRecordId failed");
236         CHECK_AND_RETURN_RET_LOG(HandlePath(data, upLoadRecord) == E_OK, nullptr, "HandlePath failed");
237     } else {
238         int32_t ret = FillRecordId(record, upLoadRecord);
239         if (ret != E_OK) {
240             MEDIA_ERR_LOG("fill record id err %{public}d", ret);
241             return nullptr;
242         }
243         data["albumId"] = MDKRecordField(record->GetRecordId());
244     }
245     HandleEmptyShow(record, data, upLoadRecord);
246     /* set data */
247     ConvertToDoubleScreenshot(record, data);
248     record->SetRecordData(data);
249 
250     return record;
251 }
252 
ConvertErrorTypeDetails(const MDKRecordOperResult & result,std::vector<CloudErrorDetail> & errorDetails)253 void CloudAlbumDataConvert::ConvertErrorTypeDetails(
254     const MDKRecordOperResult &result, std::vector<CloudErrorDetail> &errorDetails)
255 {
256     auto errorType = result.GetDKError();
257     if (errorType.errorDetails.empty()) {
258         return;
259     }
260     for (const auto &element : errorType.errorDetails) {
261         CloudErrorDetail detail;
262         detail.domain = element.domain;
263         detail.reason = element.reason;
264         detail.errorCode = element.errorCode;
265         detail.description = element.description;
266         detail.errorPos = element.errorPos;
267         detail.errorParam = element.errorParam;
268         detail.detailCode = element.detailCode;
269         errorDetails.push_back(detail);
270     }
271 }
272 
ConvertToOnCreateRecord(const std::string & cloudId,const MDKRecordOperResult & result,OnCreateRecordsAlbumReqBodyAlbumData & record)273 int32_t CloudAlbumDataConvert::ConvertToOnCreateRecord(
274     const std::string &cloudId, const MDKRecordOperResult &result, OnCreateRecordsAlbumReqBodyAlbumData &record)
275 {
276     MDKRecordAlbumData data = MDKRecordAlbumData(result.GetDKRecord());
277     record.cloudId = cloudId;
278     std::string newCloudId = data.GetCloudId().value_or("");
279     record.newCloudId = newCloudId;
280     record.isSuccess = result.IsSuccess();
281     record.serverErrorCode = result.GetDKError().serverErrorCode;
282     ConvertErrorTypeDetails(result, record.errorDetails);
283     return E_OK;
284 }
285 
286 
BuildModifyRecord(const std::string & cloudId,const MDKRecordOperResult & result,OnMdirtyAlbumRecord & record)287 int32_t CloudAlbumDataConvert::BuildModifyRecord(
288     const std::string &cloudId, const MDKRecordOperResult &result, OnMdirtyAlbumRecord &record)
289 {
290     MDKRecordAlbumData data = MDKRecordAlbumData(result.GetDKRecord());
291     record.cloudId = cloudId;
292     record.isSuccess = result.IsSuccess();
293     record.serverErrorCode = result.GetDKError().serverErrorCode;
294     ConvertErrorTypeDetails(result, record.errorDetails);
295     return E_OK;
296 }
297 }  // namespace OHOS::Media::CloudSync