1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "file_data_convertor.h"
17
18 #include <regex>
19 #include <unistd.h>
20 #include <sys/stat.h>
21
22 #include "medialibrary_db_const.h"
23 #include "thumbnail_const.h"
24
25 namespace OHOS {
26 namespace FileManagement {
27 namespace CloudSync {
28 using namespace std;
29 using namespace NativeRdb;
30 using namespace Media;
31 using DriveKit::DKLocalErrorCode;
32
33 /* record type */
34 string FileDataConvertor::recordType_ = "media";
35
36 /* path */
37 string FileDataConvertor::prefix_ = "/data/service/el2/";
38 string FileDataConvertor::suffix_ = "/hmdfs/account/files";
39 string FileDataConvertor::sandboxPrefix_ = "/storage/cloud/files";
40 string FileDataConvertor::prefixLCD_ = "/mnt/hmdfs/";
41 string FileDataConvertor::suffixLCD_ = "/account/device_view/local/files";
42 string FileDataConvertor::prefixCloud_ = "/storage/cloud/";
43 string FileDataConvertor::suffixCloud_ = "/files";
44
FileDataConvertor(int32_t userId,string & bundleName,OperationType type)45 FileDataConvertor::FileDataConvertor(int32_t userId, string &bundleName, OperationType type) : userId_(userId),
46 bundleName_(bundleName), type_(type)
47 {
48 }
49
Convert(DriveKit::DKRecord & record,NativeRdb::ResultSet & resultSet)50 int32_t FileDataConvertor::Convert(DriveKit::DKRecord &record, NativeRdb::ResultSet &resultSet)
51 {
52 DriveKit::DKRecordData data;
53
54 /* process cloud sync unique fileds*/
55 RETURN_ON_ERR(HandleUniqueFileds(data, resultSet));
56
57 /* process compatible fileds shared with gallery or gallery-specific fileds*/
58 RETURN_ON_ERR(HandleCompatibleFileds(data, resultSet));
59 record.SetRecordData(data);
60 record.SetRecordType(recordType_);
61 if (type_ == FILE_CREATE) {
62 record.SetNewCreate(true);
63 } else {
64 int32_t ret = FillRecordId(record, resultSet);
65 if (ret != E_OK) {
66 LOGE("fill record id err %{public}d", ret);
67 return ret;
68 }
69 }
70 return E_OK;
71 }
72
HandleUniqueFileds(DriveKit::DKRecordData & data,NativeRdb::ResultSet & resultSet)73 int32_t FileDataConvertor::HandleUniqueFileds(DriveKit::DKRecordData &data,
74 NativeRdb::ResultSet &resultSet)
75 {
76 DriveKit::DKRecordFieldMap map;
77 /* store media unique fileds in attributes*/
78 RETURN_ON_ERR(HandleAttributes(map, resultSet));
79 data[FILE_ATTRIBUTES] = DriveKit::DKRecordField(map);
80 /* local info */
81 RETURN_ON_ERR(HandleLocalInfo(data, resultSet));
82 return E_OK;
83 }
84
85 /* Cloud sync unique filed processing */
HandleAttributes(DriveKit::DKRecordFieldMap & map,NativeRdb::ResultSet & resultSet)86 int32_t FileDataConvertor::HandleAttributes(DriveKit::DKRecordFieldMap &map,
87 NativeRdb::ResultSet &resultSet)
88 {
89 auto size = CLOUD_SYNC_UNIQUE_COLUMNS.size();
90 for (decltype(size) i = 0; i < size; i++) {
91 const string &key = CLOUD_SYNC_UNIQUE_COLUMNS[i];
92 DataType type = CLOUD_SYNC_UNIQUE_COLUMN_TYPES[i];
93 switch (type) {
94 case DataType::INT: {
95 SET_RECORD_INT(key, resultSet, map);
96 break;
97 }
98 case DataType::LONG: {
99 SET_RECORD_LONG(key, resultSet, map);
100 break;
101 }
102 case DataType::DOUBLE: {
103 SET_RECORD_DOUBLE(key, resultSet, map);
104 break;
105 }
106 case DataType::STRING: {
107 SET_RECORD_STRING(key, resultSet, map);
108 break;
109 }
110 case DataType::BOOL: {
111 SET_RECORD_BOOL(key, resultSet, map);
112 break;
113 }
114 }
115 }
116 RETURN_ON_ERR(HandleThumbSize(map, resultSet));
117 RETURN_ON_ERR(HandleLcdSize(map, resultSet));
118 return E_OK;
119 }
120
HandleCompatibleFileds(DriveKit::DKRecordData & data,NativeRdb::ResultSet & resultSet)121 int32_t FileDataConvertor::HandleCompatibleFileds(DriveKit::DKRecordData &data,
122 NativeRdb::ResultSet &resultSet)
123 {
124 /* gallery-specific or shared fileds */
125 RETURN_ON_ERR(HandleFileName(data, resultSet));
126 RETURN_ON_ERR(HandleCreatedTime(data, resultSet));
127 RETURN_ON_ERR(HandleHash(data, resultSet));
128 RETURN_ON_ERR(HandleSize(data, resultSet));
129 RETURN_ON_ERR(HandleSource(data, resultSet));
130 RETURN_ON_ERR(HandleFileType(data, resultSet));
131 RETURN_ON_ERR(HandleRecycled(data, resultSet));
132 RETURN_ON_ERR(HandleRecycleTime(data, resultSet));
133 RETURN_ON_ERR(HandleFavorite(data, resultSet));
134
135 /* gallery expand fields */
136 RETURN_ON_ERR(HandleProperties(data, resultSet));
137
138 /* cloud sdk extra feature*/
139 RETURN_ON_ERR(HandleAttachments(data, resultSet));
140
141 /* cloudsync-specific fields */
142 RETURN_ON_ERR(HandleMimeType(data, resultSet));
143 RETURN_ON_ERR(HandleEditedTime(data, resultSet));
144 return E_OK;
145 }
146
147 /* properties */
HandleProperties(DriveKit::DKRecordData & data,NativeRdb::ResultSet & resultSet)148 int32_t FileDataConvertor::HandleProperties(DriveKit::DKRecordData &data,
149 NativeRdb::ResultSet &resultSet)
150 {
151 DriveKit::DKRecordFieldMap map;
152
153 /* gallery expand properties */
154 RETURN_ON_ERR(HandleSourceFileName(map, resultSet));
155 RETURN_ON_ERR(HandleFirstUpdateTime(map, resultSet));
156 RETURN_ON_ERR(HandleFileCreateTime(map, resultSet));
157 RETURN_ON_ERR(HandleDetailTime(map, resultSet));
158 RETURN_ON_ERR(HandleSourcePath(map, resultSet));
159 RETURN_ON_ERR(HandleRelativeBucketId(map, resultSet));
160 RETURN_ON_ERR(HandlePosition(map, resultSet));
161 RETURN_ON_ERR(HandleRotate(map, resultSet));
162 RETURN_ON_ERR(HandleDuration(map, resultSet));
163
164 /* Resolution is combined by cloud sdk, just upload height and width */
165 RETURN_ON_ERR(HandleHeight(map, resultSet));
166 RETURN_ON_ERR(HandleWidth(map, resultSet));
167
168 /* set map */
169 data[FILE_PROPERTIES] = DriveKit::DKRecordField(map);
170 return E_OK;
171 }
172
173 /* attachments */
HandleAttachments(DriveKit::DKRecordData & data,NativeRdb::ResultSet & resultSet)174 int32_t FileDataConvertor::HandleAttachments(DriveKit::DKRecordData &data,
175 NativeRdb::ResultSet &resultSet)
176 {
177 if (type_ != FILE_CREATE && type_ != FILE_DATA_MODIFY) {
178 return E_OK;
179 }
180
181 /* path */
182 string path;
183 int32_t ret = GetString(PhotoColumn::MEDIA_FILE_PATH, path, resultSet);
184 if (ret != E_OK) {
185 return ret;
186 }
187
188 /* content */
189 ret = HandleContent(data, path);
190 if (ret != E_OK) {
191 LOGE("handle thumbnail err %{public}d", ret);
192 return ret;
193 }
194 /* thumb */
195 ret = HandleThumbnail(data, path);
196 if (ret != E_OK) {
197 LOGE("handle thumbnail err %{public}d", ret);
198 return ret;
199 }
200 /* lcd */
201 ret = HandleLcd(data, path);
202 if (ret != E_OK) {
203 LOGE("handle lcd err %{public}d", ret);
204 return ret;
205 }
206
207 return E_OK;
208 }
209
210 /* record id */
FillRecordId(DriveKit::DKRecord & record,NativeRdb::ResultSet & resultSet)211 int32_t FileDataConvertor::FillRecordId(DriveKit::DKRecord &record,
212 NativeRdb::ResultSet &resultSet)
213 {
214 string val;
215 int32_t ret = GetString(PhotoColumn::PHOTO_CLOUD_ID, val, resultSet);
216 if (ret != E_OK) {
217 return ret;
218 }
219 record.SetRecordId(val);
220 return E_OK;
221 }
222
HandleThumbSize(DriveKit::DKRecordFieldMap & map,NativeRdb::ResultSet & resultSet)223 int32_t FileDataConvertor::HandleThumbSize(DriveKit::DKRecordFieldMap &map,
224 NativeRdb::ResultSet &resultSet)
225 {
226 if (type_ != FILE_CREATE && type_ != FILE_DATA_MODIFY) {
227 return E_OK;
228 }
229
230 string path;
231 int32_t ret = GetString(PhotoColumn::MEDIA_FILE_PATH, path, resultSet);
232 if (ret != E_OK) {
233 LOGE("get filepath failed");
234 return ret;
235 }
236
237 string thumbnailPath = GetThumbPath(path, THUMB_SUFFIX);
238 struct stat fileStat;
239 int err = stat(thumbnailPath.c_str(), &fileStat);
240 if (err < 0) {
241 LOGE("get thumb size failed errno :%{public}d", errno);
242 return E_INVAL_ARG;
243 }
244
245 map[FILE_THUMB_SIZE] = DriveKit::DKRecordField(int64_t(fileStat.st_size));
246 return E_OK;
247 }
248
HandleLcdSize(DriveKit::DKRecordFieldMap & map,NativeRdb::ResultSet & resultSet)249 int32_t FileDataConvertor::HandleLcdSize(DriveKit::DKRecordFieldMap &map,
250 NativeRdb::ResultSet &resultSet)
251 {
252 if (type_ != FILE_CREATE && type_ != FILE_DATA_MODIFY) {
253 return E_OK;
254 }
255
256 string path;
257 int32_t ret = GetString(PhotoColumn::MEDIA_FILE_PATH, path, resultSet);
258 if (ret != E_OK) {
259 LOGE("get filepath failed");
260 return ret;
261 }
262
263 string lcdPath = GetThumbPath(path, LCD_SUFFIX);
264 struct stat fileStat;
265 int err = stat(lcdPath.c_str(), &fileStat);
266 if (err < 0) {
267 LOGE("get lcd size failed errno :%{public}d", errno);
268 return E_INVAL_ARG;
269 }
270
271 map[FILE_LCD_SIZE] = DriveKit::DKRecordField(int64_t(fileStat.st_size));
272 return E_OK;
273 }
274
HandleDetailTime(DriveKit::DKRecordFieldMap & map,NativeRdb::ResultSet & resultSet)275 int32_t FileDataConvertor::HandleDetailTime(DriveKit::DKRecordFieldMap &map,
276 NativeRdb::ResultSet &resultSet)
277 {
278 int64_t val;
279 int32_t ret = GetLong(Media::PhotoColumn::MEDIA_DATE_ADDED, val, resultSet);
280 if (ret != E_OK) {
281 return ret;
282 }
283 time_t dataAddedStamp = time_t(val);
284 struct tm timeinfo;
285 char buffer[80];
286 localtime_r(&dataAddedStamp, &timeinfo);
287 size_t size = strftime(buffer, sizeof(buffer), "%Y:%m:%d %H:%M:%S", &timeinfo);
288 if (size == 0) {
289 return E_OK;
290 }
291 std::string detailTime(buffer);
292 map[FILE_DETAIL_TIME] = DriveKit::DKRecordField(detailTime);
293 return E_OK;
294 }
295
HandlePosition(DriveKit::DKRecordFieldMap & map,NativeRdb::ResultSet & resultSet)296 int32_t FileDataConvertor::HandlePosition(DriveKit::DKRecordFieldMap &map,
297 NativeRdb::ResultSet &resultSet)
298 {
299 double latitudeVal;
300 double longitudeVal;
301 int32_t ret = GetDouble(Media::PhotoColumn::PHOTO_LATITUDE, latitudeVal, resultSet);
302 if (ret != E_OK) {
303 return ret;
304 }
305 ret = GetDouble(Media::PhotoColumn::PHOTO_LONGITUDE, longitudeVal, resultSet);
306 if (ret != E_OK) {
307 return ret;
308 }
309 std::stringstream latitudestream;
310 std::stringstream longitudestream;
311 latitudestream.precision(15); // 15:precision
312 longitudestream.precision(15); // 15:precision
313 latitudestream << latitudeVal;
314 longitudestream << longitudeVal;
315 std::string position = "{\"x\":\"" + latitudestream.str() + "\",\"y\":\"" + longitudestream.str() +"\"}";
316 map[FILE_POSITION] = DriveKit::DKRecordField(position);
317 return E_OK;
318 }
319
HandleRotate(DriveKit::DKRecordFieldMap & map,NativeRdb::ResultSet & resultSet)320 int32_t FileDataConvertor::HandleRotate(DriveKit::DKRecordFieldMap &map,
321 NativeRdb::ResultSet &resultSet)
322 {
323 int32_t val;
324 int32_t ret = GetInt(Media::PhotoColumn::PHOTO_ORIENTATION, val, resultSet);
325 if (ret != E_OK) {
326 return ret;
327 }
328 switch (val) {
329 case ROTATE_ANGLE_0:
330 val = ORIENTATION_NORMAL;
331 break;
332 case ROTATE_ANGLE_90:
333 val = ORIENTATION_ROTATE_90;
334 break;
335 case ROTATE_ANGLE_180:
336 val = ORIENTATION_ROTATE_180;
337 break;
338 case ROTATE_ANGLE_270:
339 val = ORIENTATION_ROTATE_270;
340 break;
341 default:
342 val = ORIENTATION_NORMAL;
343 break;
344 }
345 map[FILE_ROTATION] = DriveKit::DKRecordField(val);
346 return E_OK;
347 }
348
349 /* properties - general */
HandleGeneral(DriveKit::DKRecordFieldMap & map,NativeRdb::ResultSet & resultSet)350 int32_t FileDataConvertor::HandleGeneral(DriveKit::DKRecordFieldMap &map,
351 NativeRdb::ResultSet &resultSet)
352 {
353 auto size = GALLERY_FILE_COLUMNS.size();
354 for (decltype(size) i = 0; i < size; i++) {
355 const string &key = GALLERY_FILE_COLUMNS[i];
356 DataType type = GALLERY_FILE_COLUMN_TYPES[i];
357 switch (type) {
358 case DataType::INT: {
359 SET_RECORD_INT(key, resultSet, map);
360 break;
361 }
362 case DataType::LONG: {
363 SET_RECORD_LONG(key, resultSet, map);
364 break;
365 }
366 case DataType::DOUBLE: {
367 SET_RECORD_DOUBLE(key, resultSet, map);
368 break;
369 }
370 case DataType::STRING: {
371 SET_RECORD_STRING(key, resultSet, map);
372 break;
373 }
374 case DataType::BOOL: {
375 SET_RECORD_BOOL(key, resultSet, map);
376 break;
377 }
378 }
379 }
380 return E_OK;
381 }
382
383 /* attachments */
HandleContent(DriveKit::DKRecordData & data,string & path)384 int32_t FileDataConvertor::HandleContent(DriveKit::DKRecordData &data,
385 string &path)
386 {
387 string lowerPath = GetLowerPath(path);
388 if (access(lowerPath.c_str(), F_OK)) {
389 LOGE("content %{private}s doesn't exist", lowerPath.c_str());
390 return E_PATH;
391 }
392
393 /* asset */
394 DriveKit::DKAsset content;
395 content.uri = move(lowerPath);
396 content.assetName = FILE_CONTENT;
397 content.operationType = DriveKit::DKAssetOperType::DK_ASSET_ADD;
398 data[FILE_CONTENT] = DriveKit::DKRecordField(content);
399 return E_OK;
400 }
401
HandleThumbnail(DriveKit::DKRecordData & data,string & path)402 int32_t FileDataConvertor::HandleThumbnail(DriveKit::DKRecordData &data,
403 string &path)
404 {
405 string thumbnailPath = GetThumbPath(path, THUMB_SUFFIX);
406 if (access(thumbnailPath.c_str(), F_OK)) {
407 LOGE("thumbnail %{private}s doesn't exist", thumbnailPath.c_str());
408 return E_PATH;
409 }
410
411 /* asset */
412 DriveKit::DKAsset content;
413 content.uri = move(thumbnailPath);
414 content.assetName = FILE_THUMBNAIL;
415 content.operationType = DriveKit::DKAssetOperType::DK_ASSET_ADD;
416 data[FILE_THUMBNAIL] = DriveKit::DKRecordField(content);
417 return E_OK;
418 }
419
HandleLcd(DriveKit::DKRecordData & data,string & path)420 int32_t FileDataConvertor::HandleLcd(DriveKit::DKRecordData &data,
421 string &path)
422 {
423 string lcdPath = GetThumbPath(path, LCD_SUFFIX);
424 if (access(lcdPath.c_str(), F_OK)) {
425 LOGE("lcd %{private}s doesn't exist", lcdPath.c_str());
426 return E_PATH;
427 }
428
429 /* asset */
430 DriveKit::DKAsset content;
431 content.uri = move(lcdPath);
432 content.assetName = FILE_LCD;
433 content.operationType = DriveKit::DKAssetOperType::DK_ASSET_ADD;
434 data[FILE_LCD] = DriveKit::DKRecordField(content);
435 return E_OK;
436 }
437
GetLowerPath(const string & path)438 string FileDataConvertor::GetLowerPath(const string &path)
439 {
440 size_t pos = path.find_first_of(sandboxPrefix_);
441 if (pos == string::npos) {
442 LOGE("invalid path %{private}s", path.c_str());
443 return "";
444 }
445 return prefix_ + to_string(userId_) + suffix_ + path.substr(pos +
446 sandboxPrefix_.size());
447 }
448
GetLowerTmpPath(const string & path)449 string FileDataConvertor::GetLowerTmpPath(const string &path)
450 {
451 size_t pos = path.find_first_of(sandboxPrefix_);
452 if (pos == string::npos) {
453 LOGE("invalid path %{private}s", path.c_str());
454 return "";
455 }
456 return prefix_ + to_string(userId_) + suffix_ + path.substr(pos +
457 sandboxPrefix_.size());
458 }
459
GetSandboxPath(const string & path)460 string FileDataConvertor::GetSandboxPath(const string &path)
461 {
462 string localPrefix = prefix_ + to_string(userId_) + suffix_;
463 size_t pos = path.find_first_of(localPrefix);
464 if (pos == string::npos) {
465 LOGE("invalid path %{private}s", path.c_str());
466 return "";
467 }
468 return sandboxPrefix_ + path.substr(pos + localPrefix.size());
469 }
470
GetThumbPath(const string & path,const string & key)471 string FileDataConvertor::GetThumbPath(const string &path, const string &key)
472 {
473 if (path.length() < ROOT_MEDIA_DIR.length()) {
474 return "";
475 }
476 /* transform sandbox path */
477 return prefixLCD_ + to_string(userId_) + suffixLCD_ + "/" + Media::GetThumbnailPath(path,
478 key).substr(ROOT_MEDIA_DIR.length());
479 }
480
GetHmdfsLocalPath(const string & path)481 string FileDataConvertor::GetHmdfsLocalPath(const string &path)
482 {
483 size_t pos = path.find_first_of(sandboxPrefix_);
484 if (pos == string::npos) {
485 LOGE("invalid path %{private}s", path.c_str());
486 return "";
487 }
488 /* transform sandbox path to hmdfs local path*/
489 return prefixLCD_ + to_string(userId_) + suffixLCD_ + path.substr(pos + sandboxPrefix_.size());
490 }
491
GetThumbPathInCloud(const std::string & path,const std::string & key)492 string FileDataConvertor::GetThumbPathInCloud(const std::string &path, const std::string &key)
493 {
494 if (path.length() < ROOT_MEDIA_DIR.length()) {
495 return "";
496 }
497 return sandboxPrefix_ + "/" + Media::GetThumbnailPath(path, key).substr(ROOT_MEDIA_DIR.length());
498 }
499
GetLocalPathToCloud(const std::string & path)500 string FileDataConvertor::GetLocalPathToCloud(const std::string &path)
501 {
502 string localPrefix = prefixLCD_ + to_string(userId_) + suffixLCD_;
503 size_t pos = path.find_first_of(localPrefix);
504 if (pos == string::npos || pos != 0) {
505 LOGE("invalid path %{private}s", path.c_str());
506 return "";
507 }
508
509 return sandboxPrefix_ + path.substr(localPrefix.length());
510 }
511
IfContainsAttributes(const DriveKit::DKRecord & record)512 bool FileDataConvertor::IfContainsAttributes(const DriveKit::DKRecord &record)
513 {
514 DriveKit::DKRecordData data;
515 record.GetRecordData(data);
516 if (data.find(FILE_ATTRIBUTES) != data.end()) {
517 DriveKit::DKRecordFieldMap attributes;
518 data[FILE_ATTRIBUTES].GetRecordMap(attributes);
519 return !(attributes.find(PhotoColumn::MEDIA_TITLE) == attributes.end());
520 }
521 return false;
522 }
523
Convert(DriveKit::DKRecord & record,NativeRdb::ValuesBucket & valueBucket)524 int32_t FileDataConvertor::Convert(DriveKit::DKRecord &record, NativeRdb::ValuesBucket &valueBucket)
525 {
526 DriveKit::DKRecordData data;
527 record.GetRecordData(data);
528 if (!IfContainsAttributes(record)) {
529 int32_t ret = TryCompensateValue(record, data, valueBucket);
530 if (ret != E_OK) {
531 LOGE("record data lose key value");
532 return ret;
533 }
534 } else {
535 int32_t ret = ExtractAttributeValue(data, valueBucket);
536 if (ret != E_OK) {
537 LOGE("record data donnot have attributes set, need");
538 return ret;
539 }
540 }
541 ExtractCompatibleValue(record, data, valueBucket);
542 return E_OK;
543 }
544
TryCompensateValue(const DriveKit::DKRecord & record,DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)545 int32_t FileDataConvertor::TryCompensateValue(const DriveKit::DKRecord &record,
546 DriveKit::DKRecordData &data, NativeRdb::ValuesBucket &valueBucket)
547 {
548 RETURN_ON_ERR(CompensateData(data, valueBucket));
549 RETURN_ON_ERR(CompensateTitle(data, valueBucket));
550 RETURN_ON_ERR(CompensateMediaType(data, valueBucket));
551 RETURN_ON_ERR(CompensateDataAdded(record, valueBucket));
552 RETURN_ON_ERR(CompensateMetaDateModified(record, valueBucket));
553 RETURN_ON_ERR(CompensateSubtype(data, valueBucket));
554 RETURN_ON_ERR(CompensateDuration(data, valueBucket));
555 return E_OK;
556 }
557
CompensateData(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)558 int32_t FileDataConvertor::CompensateData(DriveKit::DKRecordData &data, NativeRdb::ValuesBucket &valueBucket)
559 {
560 if (data.find(FILE_ATTRIBUTES) == data.end()) {
561 LOGE("record data cannot find attributes or size");
562 return E_INVAL_ARG;
563 }
564 DriveKit::DKRecordFieldMap attributes;
565 data[FILE_ATTRIBUTES].GetRecordMap(attributes);
566 string dataPath;
567 if (attributes[PhotoColumn::MEDIA_FILE_PATH].GetString(dataPath) != DKLocalErrorCode::NO_ERROR) {
568 LOGE("bad file_path in attributes");
569 return E_INVAL_ARG;
570 }
571 valueBucket.PutString(PhotoColumn::MEDIA_FILE_PATH, dataPath);
572 return E_OK;
573 }
574
CompensateTitle(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)575 int32_t FileDataConvertor::CompensateTitle(DriveKit::DKRecordData &data, NativeRdb::ValuesBucket &valueBucket)
576 {
577 if (data.find(FILE_PROPERTIES) == data.end()) {
578 LOGE("record data cannot find properties");
579 return E_INVAL_ARG;
580 }
581 DriveKit::DKRecordFieldMap prop;
582 data[FILE_PROPERTIES].GetRecordMap(prop);
583 if (prop.find(FILE_SOURCE_FILE_NAME) == prop.end()) {
584 LOGE("record data cannot find title, ignore it");
585 return E_OK;
586 }
587 string sourceFileName;
588 if (prop[FILE_SOURCE_FILE_NAME].GetString(sourceFileName) != DKLocalErrorCode::NO_ERROR) {
589 LOGE("bad sourceFileName in props");
590 return E_INVAL_ARG;
591 }
592 string title = sourceFileName;
593 size_t pos = sourceFileName.find_last_of(".");
594 if (pos != string::npos) {
595 title = sourceFileName.substr(0, pos);
596 }
597 valueBucket.PutString(PhotoColumn::MEDIA_TITLE, title);
598 return E_OK;
599 }
600
CompensateMediaType(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)601 int32_t FileDataConvertor::CompensateMediaType(DriveKit::DKRecordData &data,
602 NativeRdb::ValuesBucket &valueBucket)
603 {
604 if (data.find(FILE_FILETYPE) == data.end()) {
605 LOGE("record data cannot find properties");
606 return E_INVAL_ARG;
607 }
608 int32_t fileType;
609 if (data[FILE_FILETYPE].GetInt(fileType) != DKLocalErrorCode::NO_ERROR) {
610 LOGE("record data cannot find fileType");
611 return E_INVAL_ARG;
612 }
613 valueBucket.PutInt(PhotoColumn::MEDIA_TYPE, (fileType == FILE_TYPE_VIDEO) ?
614 MEDIA_TYPE_VIDEO : MEDIA_TYPE_IMAGE);
615 return E_OK;
616 }
617
CompensateDataAdded(const DriveKit::DKRecord & record,NativeRdb::ValuesBucket & valueBucket)618 int32_t FileDataConvertor::CompensateDataAdded(const DriveKit::DKRecord &record,
619 NativeRdb::ValuesBucket &valueBucket)
620 {
621 uint64_t dataAdded = record.GetCreateTime() / MILLISECOND_TO_SECOND;
622 valueBucket.PutLong(PhotoColumn::MEDIA_DATE_ADDED, dataAdded);
623 return E_OK;
624 }
625
CompensateMetaDateModified(const DriveKit::DKRecord & record,NativeRdb::ValuesBucket & valueBucket)626 int32_t FileDataConvertor::CompensateMetaDateModified(const DriveKit::DKRecord &record,
627 NativeRdb::ValuesBucket &valueBucket)
628 {
629 uint64_t metaDataModified = record.GetEditedTime() / MILLISECOND_TO_SECOND;
630
631 // imputed value, may not be accurate
632 valueBucket.PutLong(PhotoColumn::PHOTO_META_DATE_MODIFIED, metaDataModified);
633 return E_OK;
634 }
635
CompensateSubtype(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)636 int32_t FileDataConvertor::CompensateSubtype(DriveKit::DKRecordData &data,
637 NativeRdb::ValuesBucket &valueBucket)
638 {
639 if (data.find(FILE_PROPERTIES) == data.end()) {
640 LOGE("record data cannot find properties");
641 return E_INVAL_ARG;
642 }
643 DriveKit::DKRecordFieldMap prop;
644 data[FILE_PROPERTIES].GetRecordMap(prop);
645 if (prop.find(FILE_SOURCE_PATH) == prop.end()) {
646 valueBucket.PutInt(PhotoColumn::PHOTO_SUBTYPE, PhotoSubType::DEFAULT);
647 return E_OK;
648 }
649 string sourcePath;
650 if (prop[FILE_SOURCE_PATH].GetString(sourcePath) != DKLocalErrorCode::NO_ERROR) {
651 LOGE("bad Subtype in props");
652 valueBucket.PutInt(PhotoColumn::PHOTO_SUBTYPE, PhotoSubType::DEFAULT);
653 return E_OK;
654 }
655 int32_t subType = PhotoSubType::DEFAULT;
656 if (sourcePath.find("DCIM") != string::npos && sourcePath.find("Camera") != string::npos) {
657 subType = PhotoSubType::CAMERA;
658 } else if (sourcePath.find("Screenshots") != string::npos) {
659 subType = PhotoSubType::SCREENSHOT;
660 } else {
661 subType = PhotoSubType::DEFAULT;
662 }
663 valueBucket.PutInt(PhotoColumn::PHOTO_SUBTYPE, subType);
664 return E_OK;
665 }
666
CompensateDuration(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)667 int32_t FileDataConvertor::CompensateDuration(DriveKit::DKRecordData &data,
668 NativeRdb::ValuesBucket &valueBucket)
669 {
670 if (data.find(FILE_PROPERTIES) == data.end()) {
671 LOGE("record data cannot find properties");
672 return E_INVAL_ARG;
673 }
674 DriveKit::DKRecordFieldMap prop;
675 data[FILE_PROPERTIES].GetRecordMap(prop);
676 if (prop.find(FILE_DURATION) == prop.end()) {
677 valueBucket.PutInt(PhotoColumn::MEDIA_DURATION, 0);
678 return E_OK;
679 }
680 int32_t duration = 0;
681 if (prop[FILE_DURATION].GetInt(duration) != DKLocalErrorCode::NO_ERROR) {
682 LOGE("bad duration in props");
683 valueBucket.PutInt(PhotoColumn::MEDIA_DURATION, 0);
684 return E_OK;
685 }
686 valueBucket.PutInt(PhotoColumn::MEDIA_DURATION, duration);
687 return E_OK;
688 }
689
ExtractAttributeValue(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)690 int32_t FileDataConvertor::ExtractAttributeValue(DriveKit::DKRecordData &data,
691 NativeRdb::ValuesBucket &valueBucket)
692 {
693 DriveKit::DKRecordFieldMap attributes = data[FILE_ATTRIBUTES];
694 auto size = CLOUD_SYNC_UNIQUE_COLUMNS.size() - NR_LOCAL_INFO;
695 for (decltype(size) i = 0; i < size; i++) {
696 auto field = CLOUD_SYNC_UNIQUE_COLUMNS[i];
697 auto type = CLOUD_SYNC_UNIQUE_COLUMN_TYPES[i];
698 if (attributes.find(field) == attributes.end()) {
699 LOGE("filed %s not found in record.attributes", field.c_str());
700 continue;
701 }
702 if (HandleField(attributes[field], valueBucket, field, type) != E_OK) {
703 LOGE("HandleField %s failed", field.c_str());
704 }
705 }
706 return E_OK;
707 }
708
ExtractCompatibleValue(const DriveKit::DKRecord & record,DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)709 int32_t FileDataConvertor::ExtractCompatibleValue(const DriveKit::DKRecord &record,
710 DriveKit::DKRecordData &data, NativeRdb::ValuesBucket &valueBucket)
711 {
712 if (data.find(FILE_PROPERTIES) == data.end()) {
713 LOGI("record data cannot find properties");
714 return E_OK;
715 }
716 DriveKit::DKRecordFieldMap prop;
717 data[FILE_PROPERTIES].GetRecordMap(prop);
718
719 /* extract value in properties*/
720 RETURN_ON_ERR(ExtractOrientation(prop, valueBucket));
721 RETURN_ON_ERR(ExtractPosition(prop, valueBucket));
722 RETURN_ON_ERR(ExtractHeight(prop, valueBucket));
723 RETURN_ON_ERR(ExtractWidth(prop, valueBucket));
724
725 /* extract value in first level*/
726 RETURN_ON_ERR(ExtractSize(data, valueBucket));
727 RETURN_ON_ERR(ExtractDisplayName(data, valueBucket));
728 RETURN_ON_ERR(ExtractMimeType(data, valueBucket));
729 RETURN_ON_ERR(ExtractDeviceName(data, valueBucket));
730 RETURN_ON_ERR(ExtractDateModified(record, valueBucket));
731 RETURN_ON_ERR(ExtractDateTaken(record, valueBucket));
732 RETURN_ON_ERR(ExtractFavorite(data, valueBucket));
733 RETURN_ON_ERR(ExtractDateTrashed(data, valueBucket));
734 RETURN_ON_ERR(ExtractCloudId(record, valueBucket));
735 return 0;
736 }
737
ExtractOrientation(DriveKit::DKRecordFieldMap & map,NativeRdb::ValuesBucket & valueBucket)738 int32_t FileDataConvertor::ExtractOrientation(DriveKit::DKRecordFieldMap &map,
739 NativeRdb::ValuesBucket &valueBucket)
740 {
741 if (map.find(FILE_ROTATION) == map.end()) {
742 LOGI("RecordFieldMap cannot find orientation");
743 return E_OK;
744 }
745 int32_t exifRotateValue;
746 if (map[FILE_ROTATION].GetInt(exifRotateValue) != DKLocalErrorCode::NO_ERROR) {
747 LOGE("extract orientation error");
748 return E_INVAL_ARG;
749 }
750 switch (exifRotateValue) {
751 case ORIENTATION_NORMAL:
752 exifRotateValue = ROTATE_ANGLE_0;
753 break;
754 case ORIENTATION_ROTATE_90:
755 exifRotateValue = ROTATE_ANGLE_90;
756 break;
757 case ORIENTATION_ROTATE_180:
758 exifRotateValue = ROTATE_ANGLE_180;
759 break;
760 case ORIENTATION_ROTATE_270:
761 exifRotateValue = ROTATE_ANGLE_270;
762 break;
763 default:
764 exifRotateValue = ROTATE_ANGLE_0;
765 break;
766 }
767 valueBucket.PutInt(PhotoColumn::PHOTO_ORIENTATION, exifRotateValue);
768 return E_OK;
769 }
770
ExtractPosition(DriveKit::DKRecordFieldMap & map,NativeRdb::ValuesBucket & valueBucket)771 int32_t FileDataConvertor::ExtractPosition(DriveKit::DKRecordFieldMap &map,
772 NativeRdb::ValuesBucket &valueBucket)
773 {
774 if (map.find(FILE_POSITION) == map.end()) {
775 LOGI("RecordFieldMap cannot find position");
776 return E_OK;
777 }
778 string position;
779 if (map[FILE_POSITION].GetString(position) != DKLocalErrorCode::NO_ERROR) {
780 LOGE("extract orientation error");
781 return E_INVAL_ARG;
782 }
783 string latitude;
784 string longitude;
785 regex positionPattern("(-?\\d+\\.?\\d+|0).*?(-?\\d+\\.?\\d+|0)");
786 smatch match;
787 if (regex_search(position, match, positionPattern)) {
788 latitude = match[FIRST_MATCH_PARAM];
789 longitude = match[SECOND_MATCH_PARAM];
790 } else {
791 LOGE("extract latitude or longitude error");
792 return E_INVAL_ARG;
793 }
794 stringstream latitudestream(latitude);
795 stringstream longitudestream(longitude);
796 latitudestream.precision(15); // 15:precision
797 longitudestream.precision(15); // 15:precision
798 double latitudeValue;
799 double longitudeValue;
800 latitudestream >> latitudeValue;
801 longitudestream >> longitudeValue;
802
803 valueBucket.PutDouble(PhotoColumn::PHOTO_LATITUDE, latitudeValue);
804 valueBucket.PutDouble(PhotoColumn::PHOTO_LONGITUDE, longitudeValue);
805 return E_OK;
806 }
807
ExtractHeight(DriveKit::DKRecordFieldMap & map,NativeRdb::ValuesBucket & valueBucket)808 int32_t FileDataConvertor::ExtractHeight(DriveKit::DKRecordFieldMap &map,
809 NativeRdb::ValuesBucket &valueBucket)
810 {
811 if (map.find(FILE_HEIGHT) == map.end()) {
812 LOGI("RecordFieldMap cannot find height");
813 return E_OK;
814 }
815 int32_t height;
816 if (map[FILE_HEIGHT].GetInt(height) != DKLocalErrorCode::NO_ERROR) {
817 LOGE("extract height error");
818 return E_INVAL_ARG;
819 }
820 valueBucket.PutInt(PhotoColumn::PHOTO_HEIGHT, height);
821 return E_OK;
822 }
823
ExtractWidth(DriveKit::DKRecordFieldMap & map,NativeRdb::ValuesBucket & valueBucket)824 int32_t FileDataConvertor::ExtractWidth(DriveKit::DKRecordFieldMap &map,
825 NativeRdb::ValuesBucket &valueBucket)
826 {
827 if (map.find(FILE_WIDTH) == map.end()) {
828 LOGI("RecordFieldMap cannot find width");
829 return E_OK;
830 }
831 int32_t width;
832 if (map[FILE_WIDTH].GetInt(width) != DKLocalErrorCode::NO_ERROR) {
833 LOGE("extract height error");
834 return E_INVAL_ARG;
835 }
836 valueBucket.PutInt(PhotoColumn::PHOTO_WIDTH, width);
837 return E_OK;
838 }
839
ExtractSize(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)840 int32_t FileDataConvertor::ExtractSize(DriveKit::DKRecordData &data,
841 NativeRdb::ValuesBucket &valueBucket)
842 {
843 if (data.find(FILE_SIZE) == data.end()) {
844 LOGE("record data cannot find FILE_SIZE");
845 return E_OK;
846 }
847 int64_t size;
848 if (data[FILE_SIZE].GetLong(size) != DKLocalErrorCode::NO_ERROR) {
849 LOGE("extract size error");
850 return E_INVAL_ARG;
851 }
852 valueBucket.PutLong(PhotoColumn::MEDIA_SIZE, size);
853 return E_OK;
854 }
855
ExtractDisplayName(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)856 int32_t FileDataConvertor::ExtractDisplayName(DriveKit::DKRecordData &data,
857 NativeRdb::ValuesBucket &valueBucket)
858 {
859 if (data.find(FILE_FILE_NAME) == data.end()) {
860 LOGI("record data cannot find FILE_FILE_NAME");
861 return E_OK;
862 }
863 string displayName;
864 if (data[FILE_FILE_NAME].GetString(displayName) != DKLocalErrorCode::NO_ERROR) {
865 LOGE("extract displayName error");
866 return E_INVAL_ARG;
867 }
868 valueBucket.PutString(PhotoColumn::MEDIA_NAME, displayName);
869 return E_OK;
870 }
871
ExtractMimeType(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)872 int32_t FileDataConvertor::ExtractMimeType(DriveKit::DKRecordData &data,
873 NativeRdb::ValuesBucket &valueBucket)
874 {
875 if (data.find(FILE_MIME_TYPE) == data.end()) {
876 LOGI("record data cannot find FILE_MIME_TYPE");
877 return E_OK;
878 }
879 string mimeType;
880 if (data[FILE_MIME_TYPE].GetString(mimeType) != DKLocalErrorCode::NO_ERROR) {
881 LOGE("extract mimeType error");
882 return E_INVAL_ARG;
883 }
884 valueBucket.PutString(PhotoColumn::MEDIA_MIME_TYPE, mimeType);
885 return E_OK;
886 }
887
ExtractDeviceName(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)888 int32_t FileDataConvertor::ExtractDeviceName(DriveKit::DKRecordData &data,
889 NativeRdb::ValuesBucket &valueBucket)
890 {
891 if (data.find(FILE_SOURCE) == data.end()) {
892 LOGI("record data cannot find FILE_SOURCE");
893 return E_OK;
894 }
895 string deviceName;
896 if (data[FILE_SOURCE].GetString(deviceName) != DKLocalErrorCode::NO_ERROR) {
897 LOGE("extract deviceName error");
898 return E_INVAL_ARG;
899 }
900 valueBucket.PutString(PhotoColumn::MEDIA_DEVICE_NAME, deviceName);
901 return E_OK;
902 }
903
ExtractDateModified(const DriveKit::DKRecord & record,NativeRdb::ValuesBucket & valueBucket)904 int32_t FileDataConvertor::ExtractDateModified(const DriveKit::DKRecord &record,
905 NativeRdb::ValuesBucket &valueBucket)
906 {
907 uint64_t dateModified = record.GetEditedTime() / MILLISECOND_TO_SECOND;
908 valueBucket.PutLong(PhotoColumn::MEDIA_DATE_MODIFIED, dateModified);
909 return E_OK;
910 }
911
ExtractDateTaken(const DriveKit::DKRecord & record,NativeRdb::ValuesBucket & valueBucket)912 int32_t FileDataConvertor::ExtractDateTaken(const DriveKit::DKRecord &record,
913 NativeRdb::ValuesBucket &valueBucket)
914 {
915 uint64_t dataTaken = record.GetCreateTime() / MILLISECOND_TO_SECOND;
916 valueBucket.PutLong(PhotoColumn::MEDIA_DATE_TAKEN, dataTaken);
917 return E_OK;
918 }
919
ExtractFavorite(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)920 int32_t FileDataConvertor::ExtractFavorite(DriveKit::DKRecordData &data,
921 NativeRdb::ValuesBucket &valueBucket)
922 {
923 if (data.find(FILE_FAVORITE) == data.end()) {
924 LOGI("record data cannot find FILE_FAVORITE");
925 return E_OK;
926 }
927 bool isFavorite;
928 if (data[FILE_FAVORITE].GetBool(isFavorite) != DKLocalErrorCode::NO_ERROR) {
929 LOGE("extract isFavorite error");
930 return E_INVAL_ARG;
931 }
932 valueBucket.PutInt(PhotoColumn::MEDIA_IS_FAV, isFavorite ? 1 : 0);
933 return E_OK;
934 }
935
ExtractDateTrashed(DriveKit::DKRecordData & data,NativeRdb::ValuesBucket & valueBucket)936 int32_t FileDataConvertor::ExtractDateTrashed(DriveKit::DKRecordData &data,
937 NativeRdb::ValuesBucket &valueBucket)
938 {
939 if (data.find(FILE_RECYCLE_TIME) == data.end() && data.find(FILE_RECYCLED) == data.end()) {
940 return E_OK;
941 }
942 bool isRecycle = false;
943 if (data[FILE_RECYCLED].GetBool(isRecycle) != DKLocalErrorCode::NO_ERROR) {
944 LOGE("extract FILE_RECYCLED error");
945 return E_INVAL_ARG;
946 }
947 if (isRecycle) {
948 int64_t dataTrashed = 0;
949 if (data[FILE_RECYCLE_TIME].GetLong(dataTrashed) != DKLocalErrorCode::NO_ERROR) {
950 LOGE("extract dataTrashed error");
951 return E_INVAL_ARG;
952 }
953 valueBucket.PutLong(PhotoColumn::MEDIA_DATE_TRASHED, dataTrashed / MILLISECOND_TO_SECOND);
954 } else {
955 valueBucket.PutLong(PhotoColumn::MEDIA_DATE_TRASHED, 0);
956 }
957 return E_OK;
958 }
959
ExtractCloudId(const DriveKit::DKRecord & record,NativeRdb::ValuesBucket & valueBucket)960 int32_t FileDataConvertor::ExtractCloudId(const DriveKit::DKRecord &record,
961 NativeRdb::ValuesBucket &valueBucket)
962 {
963 string cloudId = record.GetRecordId();
964 valueBucket.PutString(PhotoColumn::PHOTO_CLOUD_ID, cloudId);
965 return E_OK;
966 }
967
968 } // namespace CloudSync
969 } // namespace FileManagement
970 } // namespace OHOS
971