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