• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 <iostream>
17 #include <map>
18 #include <numeric>
19 #include <ostream>
20 #include <set>
21 #include <sstream>
22 #include <vector>
23 #include <string_view>
24 
25 #include "exif_metadata.h"
26 #include "exif_metadata_formatter.h"
27 #include "image_log.h"
28 #include "libexif/exif-format.h"
29 #include "libexif/exif-mem.h"
30 #include "libexif/exif-tag.h"
31 #include "libexif/huawei/exif-mnote-data-huawei.h"
32 #include "libexif/huawei/mnote-huawei-entry.h"
33 #include "libexif/huawei/mnote-huawei-tag.h"
34 #include "libexif/huawei/mnote-huawei-data-type.h"
35 #include "media_errors.h"
36 #include "securec.h"
37 #include "string_ex.h"
38 #include "tiff_parser.h"
39 
40 #undef LOG_DOMAIN
41 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
42 
43 #undef LOG_TAG
44 #define LOG_TAG "ExifMetadata"
45 
46 namespace OHOS {
47 namespace Media {
48 const auto KEY_SIZE = 2;
49 const auto TAG_VALUE_SIZE = 1024;
50 const auto MAX_TAG_VALUE_SIZE_FOR_STR = 64 * 1024;
51 const auto TERMINATOR_SIZE = 1;
52 const auto EXIF_HEAD_SIZE = 6;
53 const int NUMERATOR_SIZE = 4; // 4 bytes for numeratior
54 const static std::string DEFAULT_EXIF_VALUE = "default_exif_value";
55 const static std::string HW_CAPTURE_MODE = "HwMnoteCaptureMode";
56 const static std::string HW_FOCUS_MODE_EXIF = "HwMnoteFocusModeExif";
57 const static std::string MAKER_NOTE_TAG = "MakerNote";
58 const static uint64_t MAX_EXIFMETADATA_MAX_SIZE = 1024 * 1024;
59 const std::set<std::string_view> HW_SPECIAL_KEYS = {
60     "MovingPhotoId",
61     "MovingPhotoVersion",
62     "MicroVideoPresentationTimestampUS",
63     "HwUnknow",
64 };
65 const unsigned char INIT_HW_DATA[] = {
66     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x55, 0x41, 0x57, 0x45, 0x49, 0x00,
67     0x00, 0x4D, 0x4D, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x02, 0x00,
68     0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69     0x00
70 };
71 
72 static const int GET_SUPPORT_MAKERNOTE_COUNT = 1;
73 static const int INIT_HW_DATA_HEAD_LENGTH = 8;
OutputRational(std::istream & is,T & r)74 template <typename T, typename U> std::istream &OutputRational(std::istream &is, T &r)
75 {
76     U nominator = 0;
77     U denominator = 0;
78     char c('\0');
79     is >> nominator >> c >> denominator;
80     if (c != '/') {
81         is.setstate(std::ios::failbit);
82     }
83     if (is) {
84         r = { nominator, denominator };
85     }
86     return is;
87 }
88 
operator >>(std::istream & is,ExifRational & r)89 std::istream &operator >> (std::istream &is, ExifRational &r)
90 {
91     return OutputRational<ExifRational, uint32_t>(is, r);
92 }
93 
operator >>(std::istream & is,ExifSRational & r)94 std::istream &operator >> (std::istream &is, ExifSRational &r)
95 {
96     return OutputRational<ExifSRational, int32_t>(is, r);
97 }
98 
99 std::set<ExifTag> UndefinedByte = { EXIF_TAG_SCENE_TYPE, EXIF_TAG_COMPONENTS_CONFIGURATION, EXIF_TAG_FILE_SOURCE };
100 
ExifMetadata()101 ExifMetadata::ExifMetadata() : exifData_(nullptr) {}
102 
ExifMetadata(ExifData * exifData)103 ExifMetadata::ExifMetadata(ExifData *exifData) : exifData_(exifData) {}
104 
~ExifMetadata()105 ExifMetadata::~ExifMetadata()
106 {
107     if (exifData_ != nullptr) {
108         exif_data_unref(exifData_);
109         exifData_ = nullptr;
110     }
111 }
112 
GetValue(const std::string & key,std::string & value) const113 int ExifMetadata::GetValue(const std::string &key, std::string &value) const
114 {
115     value.clear();
116     IMAGE_LOGD("Retrieving value for key: %{public}s", key.c_str());
117     bool cond = exifData_ == nullptr;
118     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DECODE_EXIF_UNSUPPORT,
119                                "Exif data is null for key: %{public}s", key.c_str());
120     if (!ExifMetadatFormatter::IsKeySupported(key)) {
121         IMAGE_LOGD("Key is not supported.");
122         return ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
123     }
124     if (key == MAKER_NOTE_TAG) {
125         return HandleMakerNote(value);
126     }
127 
128     if ((key.size() > KEY_SIZE && key.substr(0, KEY_SIZE) == "Hw") || IsSpecialHwKey(key)) {
129         return HandleHwMnote(key, value);
130     } else {
131         auto tag = exif_tag_from_name(key.c_str());
132         ExifEntry *entry = GetEntry(key);
133         if (entry == nullptr) {
134             IMAGE_LOGD("Exif data entry returned null for key: %{public}s, tag: %{public}d", key.c_str(), tag);
135             return ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
136         }
137         IMAGE_LOGD("Using exif_entry_get_value for key: %{public}s, tag: %{public}d", key.c_str(), entry->tag);
138 
139         unsigned int tagValueSizeTmp = 0;
140         if (entry->size >= TAG_VALUE_SIZE && (entry->format == EXIF_FORMAT_ASCII ||
141             entry->format == EXIF_FORMAT_UNDEFINED)) {
142             tagValueSizeTmp = entry->size + TERMINATOR_SIZE > MAX_TAG_VALUE_SIZE_FOR_STR ?
143                 MAX_TAG_VALUE_SIZE_FOR_STR : entry->size + TERMINATOR_SIZE;
144         } else {
145             tagValueSizeTmp = TAG_VALUE_SIZE;
146         }
147         char tagValueChar[tagValueSizeTmp];
148 
149         exif_entry_get_value(entry, tagValueChar, sizeof(tagValueChar));
150         value = tagValueChar;
151     }
152     if (ExifMetadatFormatter::IsSensitiveInfo(key)) {
153         IMAGE_LOGD("Retrieved value for key: %{public}s success", key.c_str());
154     } else {
155         IMAGE_LOGD("Retrieved value for key: %{public}s is: %{public}s", key.c_str(), value.c_str());
156     }
157     return SUCCESS;
158 }
159 
GetAllProperties()160 const ImageMetadata::PropertyMapPtr ExifMetadata::GetAllProperties()
161 {
162     ImageMetadata::PropertyMapPtr result = std::make_shared<ImageMetadata::PropertyMap>();
163     std::string value;
164     auto rwKeys = ExifMetadatFormatter::GetRWKeys();
165     for (const auto& key : rwKeys) {
166         if (GetValue(key, value) == SUCCESS) {
167             result->insert(std::make_pair(key, value));
168         }
169     }
170     auto roKeys = ExifMetadatFormatter::GetROKeys();
171     for (const auto& key : roKeys) {
172         if (GetValue(key, value) == SUCCESS) {
173             result->insert(std::make_pair(key, value));
174         }
175     }
176     IMAGE_LOGD("Get record arguments success.");
177     return result;
178 }
179 
CloneMetadata()180 std::shared_ptr<ImageMetadata> ExifMetadata::CloneMetadata()
181 {
182     return Clone();
183 }
184 
HandleMakerNote(std::string & value) const185 int ExifMetadata::HandleMakerNote(std::string &value) const
186 {
187     value.clear();
188     std::vector<char> tagValueChar(TAG_VALUE_SIZE, 0);
189     ExifMnoteData *md = exif_data_get_mnote_data(exifData_);
190     bool cond = false;
191     if (md == nullptr) {
192         IMAGE_LOGD("Exif data mnote data md is a nullptr.");
193     }
194     if (!is_huawei_md(md)) {
195         return GetUserMakerNote(value);
196     }
197     MnoteHuaweiEntryCount *ec = nullptr;
198     mnote_huawei_get_entry_count(reinterpret_cast<ExifMnoteDataHuawei *>(md), &ec);
199     cond = ec == nullptr;
200     CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DECODE_EXIF_UNSUPPORT);
201 
202     for (unsigned int i = 0; i < ec->size; i++) {
203         MnoteHuaweiEntry *entry = ec->entries[i];
204         const char *mnoteKey = mnote_huawei_tag_get_name(entry->tag);
205         if (HW_SPECIAL_KEYS.find(mnoteKey) != HW_SPECIAL_KEYS.end()) {
206             continue;
207         }
208         mnote_huawei_entry_get_value(entry, tagValueChar.data(), tagValueChar.size());
209         value += std::string(mnoteKey) + ":" + tagValueChar.data() + ",";
210     }
211 
212     // Check if the last character of value is a comma and remove it
213     if (value.length() > 1 && value[value.length() - 1] == ',') {
214         value = value.substr(0, value.length() - 1);
215     }
216     mnote_huawei_free_entry_count(ec);
217 
218     return SUCCESS;
219 }
220 
HandleHwMnote(const std::string & key,std::string & value) const221 int ExifMetadata::HandleHwMnote(const std::string &key, std::string &value) const
222 {
223     value = DEFAULT_EXIF_VALUE;
224     char tagValueChar[TAG_VALUE_SIZE];
225     if (key == HW_FOCUS_MODE_EXIF) {
226         auto entry = exif_data_get_entry_ext(exifData_, EXIF_TAG_MAKER_NOTE);
227         exif_entry_get_value(entry, tagValueChar, sizeof(tagValueChar));
228         value = tagValueChar;
229         bool cond = value.empty();
230         CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DECODE_EXIF_UNSUPPORT);
231         return SUCCESS;
232     }
233     ExifMnoteData *md = exif_data_get_mnote_data(exifData_);
234     bool cond = false;
235     cond = md == nullptr;
236     CHECK_DEBUG_RETURN_RET_LOG(cond, SUCCESS, "Exif data mnote data md is nullptr");
237     cond = !is_huawei_md(md);
238     CHECK_ERROR_RETURN_RET_LOG(cond, SUCCESS, "Exif data returned null for key: %{public}s", key.c_str());
239     MnoteHuaweiEntryCount *ec = nullptr;
240     mnote_huawei_get_entry_count(reinterpret_cast<ExifMnoteDataHuawei *>(md), &ec);
241     cond = ec == nullptr;
242     CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DECODE_EXIF_UNSUPPORT);
243     for (unsigned int i = 0; i < ec->size; i++) {
244         MnoteHuaweiEntry *entry = ec->entries[i];
245         if (entry == nullptr) {
246             continue;
247         }
248         if (key == mnote_huawei_tag_get_name(entry->tag)) {
249             mnote_huawei_entry_get_value(entry, tagValueChar, sizeof(tagValueChar));
250             value = tagValueChar;
251             break;
252         }
253     }
254     mnote_huawei_free_entry_count(ec);
255     return SUCCESS;
256 }
257 
GetExifData()258 ExifData *ExifMetadata::GetExifData()
259 {
260     return exifData_;
261 }
262 
CreateExifdata()263 bool ExifMetadata::CreateExifdata()
264 {
265     if (exifData_ != nullptr) {
266         exif_data_unref(exifData_);
267         exifData_ = nullptr;
268         exifData_ = exif_data_new();
269         if (exifData_ == nullptr) {
270             IMAGE_LOGE("Failed to recreate exif data after unref.");
271             return false;
272         }
273 
274         // Set the image options
275         exif_data_set_option(exifData_, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
276         exif_data_set_data_type(exifData_, EXIF_DATA_TYPE_COMPRESSED);
277         exif_data_set_byte_order(exifData_, EXIF_BYTE_ORDER_INTEL);
278 
279         // Create the mandatory EXIF fields with default data
280         exif_data_fix(exifData_);
281         return true;
282     }
283     exifData_ = exif_data_new();
284     bool cond = exifData_ == nullptr;
285     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Failed to create new exif data.");
286 
287     // Set the image options
288     exif_data_set_option(exifData_, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
289     exif_data_set_data_type(exifData_, EXIF_DATA_TYPE_COMPRESSED);
290     exif_data_set_byte_order(exifData_, EXIF_BYTE_ORDER_INTEL);
291 
292     // Create the mandatory EXIF fields with default data
293     exif_data_fix(exifData_);
294     IMAGE_LOGD("New exif data created.");
295     return true;
296 }
297 
Clone()298 std::shared_ptr<ExifMetadata> ExifMetadata::Clone()
299 {
300     ExifData *exifData = this->GetExifData();
301 
302     unsigned char *dataBlob = nullptr;
303     uint32_t size = 0;
304     TiffParser::Encode(&dataBlob, size, exifData);
305     if (dataBlob == nullptr) {
306         return nullptr;
307     }
308 
309     if (size > MAX_EXIFMETADATA_MAX_SIZE) {
310         IMAGE_LOGE("Failed to clone, the size of exif metadata exceeds the maximum limit %{public}llu.",
311             static_cast<unsigned long long>(MAX_EXIFMETADATA_MAX_SIZE));
312         return nullptr;
313     }
314     ExifData *newExifData = nullptr;
315     TiffParser::Decode(dataBlob, size, &newExifData);
316     bool cond = newExifData == nullptr;
317     CHECK_ERROR_RETURN_RET(cond, nullptr);
318     std::shared_ptr<ExifMetadata> exifDataPtr = std::make_shared<ExifMetadata>(newExifData);
319     if (dataBlob != nullptr) {
320         free(dataBlob);
321         dataBlob = nullptr;
322     }
323     return exifDataPtr;
324 }
325 
CreateEntry(const std::string & key,const ExifTag & tag,const size_t valueLen)326 ExifEntry *ExifMetadata::CreateEntry(const std::string &key, const ExifTag &tag, const size_t valueLen)
327 {
328     ExifEntry *entry = exif_entry_new();
329     bool cond = false;
330     cond = entry == nullptr;
331     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "Failed to create new ExifEntry.");
332     entry->tag = tag; // tag must be set before calling exif_content_add_entry
333     auto ifdindex = exif_ifd_from_name(key.c_str());
334     exif_content_add_entry(exifData_->ifd[ifdindex], entry);
335     exif_entry_initialize(entry, tag);
336 
337     if (entry->format == EXIF_FORMAT_UNDEFINED && entry->size != valueLen) {
338         exif_content_remove_entry(exifData_->ifd[ifdindex], entry);
339 
340         // Create a memory allocator to manage this ExifEntry
341         ExifMem *exifMem = exif_mem_new_default();
342         cond = exifMem == nullptr;
343         CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "Failed to create memory allocator for ExifEntry.");
344 
345         // Create a new ExifEntry using our allocator
346         entry = exif_entry_new_mem(exifMem);
347         if (entry == nullptr) {
348             IMAGE_LOGE("Failed to create new ExifEntry using memory allocator.");
349             exif_mem_unref(exifMem);
350             return nullptr;
351         }
352 
353         // Allocate memory to use for holding the tag data
354         void *buffer = exif_mem_alloc(exifMem, valueLen);
355         if (buffer == nullptr) {
356             IMAGE_LOGE("Failed to allocate memory for tag data.");
357             exif_entry_unref(entry);
358             exif_mem_unref(exifMem);
359             return nullptr;
360         }
361 
362         // Fill in the entry
363         entry->data = static_cast<unsigned char *>(buffer);
364         entry->size = valueLen;
365         entry->tag = tag;
366         entry->components = valueLen;
367         entry->format = EXIF_FORMAT_UNDEFINED;
368 
369         // Attach the ExifEntry to an IFD
370         exif_content_add_entry(exifData_->ifd[ifdindex], entry);
371 
372         // The ExifMem and ExifEntry are now owned elsewhere
373         exif_mem_unref(exifMem);
374         exif_entry_unref(entry);
375     }
376     return entry;
377 }
378 
CreateHwEntry(const std::string & key)379 MnoteHuaweiEntry *ExifMetadata::CreateHwEntry(const std::string &key)
380 {
381     ExifMnoteData *md = exif_data_get_mnote_data (exifData_);
382     bool cond = false;
383     cond = !is_huawei_md(md);
384     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "Failed to create MnoteHuaweiEntry is not Huawei MakeNote.");
385 
386     ExifByteOrder order = exif_mnote_data_huawei_get_byte_order(md);
387     MnoteHuaweiEntry* entry = mnote_huawei_entry_new(md);
388     cond = !entry;
389     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "Failed to create MnoteHuaweiEntry.");
390 
391     MnoteHuaweiTag tag = mnote_huawei_tag_from_name(key.c_str());
392     mnote_huawei_entry_initialize(entry, tag, order);
393     return entry;
394 }
395 
ReallocEntry(ExifEntry * ptrEntry,const size_t valueLen)396 void ExifMetadata::ReallocEntry(ExifEntry *ptrEntry, const size_t valueLen)
397 {
398     // Create a memory allocator to manage this ExifEntry
399     ExifMem *exifMem = exif_mem_new_default();
400     bool cond = exifMem == nullptr;
401     CHECK_ERROR_RETURN_LOG(cond, "Failed to create memory allocator for ExifEntry. Value length: %{public}zu",
402                            valueLen);
403     auto buf = exif_mem_realloc(exifMem, ptrEntry->data, valueLen);
404     if (buf != nullptr) {
405         ptrEntry->data = static_cast<unsigned char *>(buf);
406         ptrEntry->size = exif_format_get_size(ptrEntry->format) * valueLen;
407         ptrEntry->components = exif_format_get_size(ptrEntry->format) * valueLen;
408     } else {
409         IMAGE_LOGE("Failed to reallocate memory for ExifEntry. Requested size: %{public}zu", valueLen);
410     }
411     exif_mem_unref(exifMem);
412 }
413 
GetEntry(const std::string & key,const size_t valueLen)414 ExifEntry *ExifMetadata::GetEntry(const std::string &key, const size_t valueLen)
415 {
416     IMAGE_LOGD("GetEntry key is %{public}s.", key.c_str());
417     ExifTag tag = exif_tag_from_name(key.c_str());
418     ExifEntry *entry;
419     if (tag == 0x0001 || tag == 0x0002) {
420         ExifIfd ifd = exif_ifd_from_name(key.c_str());
421         entry = exif_content_get_entry(exifData_->ifd[ifd], tag);
422     } else {
423         entry = exif_data_get_entry(exifData_, tag);
424     }
425 
426     if (entry == nullptr) {
427         IMAGE_LOGD("GetEntry entry is nullptr and try to create entry.");
428         entry = CreateEntry(key, tag, valueLen);
429     }
430 
431     bool cond = entry == nullptr;
432     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "GetEntry entry is nullptr fail.");
433 
434     if ((entry->format == EXIF_FORMAT_UNDEFINED || entry->format == EXIF_FORMAT_ASCII) &&
435         (entry->size != static_cast<unsigned int>(valueLen))) {
436         ReallocEntry(entry, valueLen);
437     }
438     return entry;
439 }
440 
GetEntry(const std::string & key) const441 ExifEntry *ExifMetadata::GetEntry(const std::string &key) const
442 {
443     IMAGE_LOGD("GetEntry by key is %{public}s.", key.c_str());
444     ExifTag tag = exif_tag_from_name(key.c_str());
445     ExifEntry *entry = nullptr;
446     if (tag == 0x0001 || tag == 0x0002) {
447         ExifIfd ifd = exif_ifd_from_name(key.c_str());
448         entry = exif_content_get_entry(exifData_->ifd[ifd], tag);
449     } else {
450         entry = exif_data_get_entry(exifData_, tag);
451     }
452     return entry;
453 }
454 
SetShort(ExifEntry * ptrEntry,const ExifByteOrder & order,const std::string & value)455 bool ExifMetadata::SetShort(ExifEntry *ptrEntry, const ExifByteOrder &order, const std::string &value)
456 {
457     std::istringstream is(value);
458     unsigned long icount = 0;
459     ExifShort tmp;
460     bool cond = false;
461     while (!is.eof() && ptrEntry->components > icount) {
462         is >> tmp;
463         cond = is.fail();
464         CHECK_ERROR_RETURN_RET_LOG(cond, false,
465                                    "Failed to read ExifShort from string. Current count: %{public}lu", icount);
466         exif_set_short(ptrEntry->data + icount * exif_format_get_size(ptrEntry->format), order, tmp);
467         icount++;
468     }
469     return true;
470 }
471 
SetLong(ExifEntry * ptrEntry,const ExifByteOrder & order,const std::string & value)472 bool ExifMetadata::SetLong(ExifEntry *ptrEntry, const ExifByteOrder &order, const std::string &value)
473 {
474     std::istringstream is(value);
475     unsigned long icount = 0;
476     ExifLong tmp;
477     bool cond = false;
478     while (!is.eof() && ptrEntry->components > icount) {
479         is >> tmp;
480         cond = is.fail();
481         CHECK_ERROR_RETURN_RET_LOG(cond, false,
482                                    "Failed to read ExifLong from string. Current count: %{public}lu", icount);
483         exif_set_long(ptrEntry->data + icount * exif_format_get_size(ptrEntry->format), order, tmp);
484         icount++;
485     }
486     return true;
487 }
488 
SetSShort(ExifEntry * ptrEntry,const ExifByteOrder & order,const std::string & value)489 bool ExifMetadata::SetSShort(ExifEntry *ptrEntry, const ExifByteOrder &order, const std::string &value)
490 {
491     std::istringstream is(value);
492     unsigned long icount = 0;
493     ExifSShort tmp;
494     bool cond = false;
495     while (!is.eof() && ptrEntry->components > icount) {
496         is >> tmp;
497         cond = is.fail();
498         CHECK_ERROR_RETURN_RET_LOG(cond, false,
499                                    "Failed to read ExifSShort from string. Current count: %{public}lu", icount);
500         exif_set_sshort(ptrEntry->data + icount * exif_format_get_size(ptrEntry->format), order, tmp);
501         icount++;
502     }
503     return true;
504 }
505 
SetSLong(ExifEntry * ptrEntry,const ExifByteOrder & order,const std::string & value)506 bool ExifMetadata::SetSLong(ExifEntry *ptrEntry, const ExifByteOrder &order, const std::string &value)
507 {
508     std::istringstream is(value);
509     unsigned long icount = 0;
510     ExifSLong tmp;
511     bool cond = false;
512     while (!is.eof() && ptrEntry->components > icount) {
513         is >> tmp;
514         cond = is.fail();
515         CHECK_ERROR_RETURN_RET_LOG(cond, false,
516                                    "Failed to read ExifSLong from string. Current count: %{public}lu", icount);
517         exif_set_slong(ptrEntry->data + icount * exif_format_get_size(ptrEntry->format), order, tmp);
518         icount++;
519     }
520     return true;
521 }
522 
SetRational(ExifEntry * ptrEntry,const ExifByteOrder & order,const std::string & value)523 bool ExifMetadata::SetRational(ExifEntry *ptrEntry, const ExifByteOrder &order, const std::string &value)
524 {
525     std::istringstream is(value);
526     unsigned long icount = 0;
527     ExifRational rat;
528     bool cond = false;
529     while (!is.eof() && ptrEntry->components > icount) {
530         is >> rat;
531         cond = is.fail();
532         CHECK_ERROR_RETURN_RET_LOG(cond, false,
533                                    "Failed to read ExifRational from string. Current count: %{public}lu", icount);
534         unsigned long offset = icount * exif_format_get_size(ptrEntry->format);
535         exif_set_rational(ptrEntry->data + offset, order, rat);
536         icount++;
537     }
538     return true;
539 }
540 
SetSRational(ExifEntry * ptrEntry,const ExifByteOrder & order,const std::string & value)541 bool ExifMetadata::SetSRational(ExifEntry *ptrEntry, const ExifByteOrder &order, const std::string &value)
542 {
543     std::istringstream is(value);
544     unsigned long icount = 0;
545     ExifSRational rat;
546     bool cond = false;
547     while (!is.eof() && ptrEntry->components > icount) {
548         is >> rat;
549         cond = is.fail();
550         CHECK_ERROR_RETURN_RET_LOG(cond, false,
551                                    "Failed to read ExifSRational from string. Current count: %{public}lu", icount);
552         unsigned long offset = icount * exif_format_get_size(ptrEntry->format);
553         exif_set_srational(ptrEntry->data + offset, order, rat);
554         icount++;
555     }
556     return true;
557 }
558 
SetByte(ExifEntry * ptrEntry,const std::string & value)559 bool ExifMetadata::SetByte(ExifEntry *ptrEntry, const std::string &value)
560 {
561     std::string result = std::accumulate(value.begin(), value.end(), std::string(), [](std::string res, char a) {
562         if (a != ' ') {
563             return res += a;
564         }
565         return res;
566     });
567     const char *p = result.c_str();
568     int valueLen = static_cast<int>(result.length());
569     for (int i = 0; i < valueLen && i < static_cast<int>(ptrEntry->size); i++) {
570         *(ptrEntry->data + i) = p[i] - '0';
571     }
572     return true;
573 }
574 
SetMem(ExifEntry * ptrEntry,const std::string & value,const size_t valueLen)575 bool ExifMetadata::SetMem(ExifEntry *ptrEntry, const std::string &value, const size_t valueLen)
576 {
577     if (UndefinedByte.find(ptrEntry->tag) != UndefinedByte.end()) {
578         return SetByte(ptrEntry, value);
579     }
580     if (memcpy_s((ptrEntry)->data, valueLen, value.c_str(), valueLen) != 0) {
581         IMAGE_LOGE("Failed to copy memory for ExifEntry. Requested size: %{public}zu", valueLen);
582         return false;
583     }
584     return true;
585 }
586 
SetValue(const std::string & key,const std::string & value)587 bool ExifMetadata::SetValue(const std::string &key, const std::string &value)
588 {
589     bool cond = exifData_ == nullptr;
590     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Exif data is null. Cannot set value for key: %{public}s", key.c_str());
591     if (value.empty()) {
592         IMAGE_LOGE("Set empty value.");
593         return false;
594     }
595     auto result = ExifMetadatFormatter::Format(key, value);
596     if (result.first) {
597         IMAGE_LOGE("Failed to validate and convert value for key: %{public}s", key.c_str());
598         return false;
599     }
600 
601     if ((key.size() > KEY_SIZE && key.substr(0, KEY_SIZE) == "Hw") ||
602         IsSpecialHwKey(key)) {
603         IMAGE_LOGD("Set HwMoteValue %{public}s", value.c_str());
604         return SetHwMoteValue(key, result.second);
605     }
606     if (key == MAKER_NOTE_TAG) {
607         IMAGE_LOGD("Set MakerNote %{public}s", value.c_str());
608         return SetMakerNoteValue(value);
609     }
610 
611     return SetCommonValue(key, result.second);
612 }
613 
SetMakerNoteValue(const std::string & value)614 bool ExifMetadata::SetMakerNoteValue(const std::string &value)
615 {
616     bool cond = exifData_ == nullptr;
617     CHECK_ERROR_RETURN_RET_LOG(cond, false, "exifData_ is nullptr");
618     cond = value.length() >= MAX_TAG_VALUE_SIZE_FOR_STR;
619     CHECK_ERROR_RETURN_RET_LOG(cond, false, "value length is too long. length: %{public}zu", value.length());
620     //clear all makernote data.
621     ExifEntry *entry = nullptr;
622     do {
623         entry = exif_data_get_entry(exifData_, EXIF_TAG_MAKER_NOTE);
624         if (entry != nullptr) {
625             exif_content_remove_entry(entry->parent, entry);
626         }
627     } while (entry != nullptr);
628 
629     auto md = exif_data_get_mnote_data(exifData_);
630     if (md != nullptr) {
631         exif_mnote_data_unref(md);
632         exif_data_set_priv_md(exifData_, nullptr);
633     }
634 
635     size_t valueLen = value.length();
636     entry = CreateEntry(MAKER_NOTE_TAG, EXIF_TAG_MAKER_NOTE, valueLen);
637     cond = entry == nullptr;
638     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Create entry is nullptr");
639     if (memcpy_s(entry->data, entry->size, value.c_str(), valueLen) != 0) {
640         IMAGE_LOGE("Failed to copy memory for ExifEntry. Requested size: %{public}zu", valueLen);
641         return false;
642     }
643 
644     bool isHwHead = entry->size > INIT_HW_DATA_HEAD_LENGTH &&
645                         memcmp(entry->data, INIT_HW_DATA + EXIF_HEAD_SIZE, INIT_HW_DATA_HEAD_LENGTH) == 0;
646     if (isHwHead) {
647         uint32_t tempSize = EXIF_HEAD_SIZE + entry->size;
648         std::vector<unsigned char> tempData(tempSize, 0);
649         cond = memcpy_s(tempData.data() + EXIF_HEAD_SIZE, tempSize - EXIF_HEAD_SIZE, entry->data, entry->size) != EOK;
650         CHECK_ERROR_RETURN_RET_LOG(cond, false, "memcpy is failed");
651         auto mem = exif_data_get_priv_mem(exifData_);
652         auto hwMd = exif_mnote_data_huawei_new(mem);
653         if (hwMd != nullptr) {
654             exif_data_set_priv_md(exifData_, hwMd);
655             exif_mnote_data_set_offset(hwMd, 0);
656             exif_mnote_data_load(hwMd, tempData.data(), tempSize);
657             IMAGE_LOGD("value is hw makernote data. load finished! res:%{public}d", is_huawei_md(hwMd));
658         }
659     }
660     return true;
661 }
662 
SetHwMoteValue(const std::string & key,const std::string & value)663 bool ExifMetadata::SetHwMoteValue(const std::string &key, const std::string &value)
664 {
665     bool isNewMaker = false;
666     if (key == HW_FOCUS_MODE_EXIF) {
667         auto entry = exif_data_get_entry_ext(exifData_, EXIF_TAG_MAKER_NOTE);
668         if (entry == nullptr) {
669             entry = CreateEntry(key, EXIF_TAG_MAKER_NOTE, value.size() + 1);
670         }
671         if (entry != nullptr) {
672             if ((entry->format == EXIF_FORMAT_UNDEFINED || entry->format == EXIF_FORMAT_ASCII) &&
673             (entry->size != static_cast<unsigned int>(value.size() + 1))) {
674                 ReallocEntry(entry, value.size() + 1);
675             }
676             SetMem(entry, value, value.size() + 1);
677         }
678     }
679     ExifMnoteData *md = GetHwMnoteData(isNewMaker);
680     bool cond = false;
681     cond = !is_huawei_md(md);
682     CHECK_DEBUG_RETURN_RET_LOG(cond, false, "Makernote is not huawei makernote.");
683 
684     MnoteHuaweiTag hwTag = mnote_huawei_tag_from_name(key.c_str());
685     cond = hwTag == MNOTE_HUAWEI_INFO;
686     CHECK_DEBUG_RETURN_RET_LOG(cond, false, "The key: %{public}s is unknow hwTag", key.c_str());
687 
688     auto *entry = exif_mnote_data_huawei_get_entry_by_tag(reinterpret_cast<ExifMnoteDataHuawei *>(md), hwTag);
689     if (!entry) {
690         entry = CreateHwEntry(key);
691         cond = !entry;
692         CHECK_ERROR_RETURN_RET(cond, false);
693         auto ret = exif_mnote_data_add_entry(md, entry);
694         if (ret) {
695             mnote_huawei_entry_free(entry);
696             IMAGE_LOGE("Add new hw entry failed.");
697             return false;
698         }
699 
700         mnote_huawei_entry_free_contour(entry);
701         entry = exif_mnote_data_huawei_get_entry_by_tag(reinterpret_cast<ExifMnoteDataHuawei *>(md), hwTag);
702     }
703 
704     const char *data = value.c_str();
705     int dataLen = value.length();
706     int ret = mnote_huawei_entry_set_value(entry, data, dataLen);
707     if (ret == 0 && isNewMaker && hwTag != MNOTE_HUAWEI_CAPTURE_MODE) {
708         IMAGE_LOGD("Remve default initialized hw entry.");
709         RemoveEntry(HW_CAPTURE_MODE);
710     }
711     return ret == 0 ? true : false;
712 }
713 
GetHwMnoteData(bool & isNewMaker)714 ExifMnoteData* ExifMetadata::GetHwMnoteData(bool &isNewMaker)
715 {
716     bool cond = false;
717     cond = exifData_ == nullptr;
718     CHECK_ERROR_RETURN_RET(cond, nullptr);
719     ExifMnoteData *md = exif_data_get_mnote_data(exifData_);
720     if (md != nullptr) {
721         return md;
722     }
723     IMAGE_LOGD("Makenote not exist & ready to init makernote with hw entry.");
724     ExifMem *mem = exif_data_get_priv_mem(exifData_);
725     cond = mem == nullptr;
726     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "GetHwMnoteData exif data with no ExifMem.");
727     md = exif_mnote_data_huawei_new(mem);
728     cond = md == nullptr || md->methods.load == nullptr;
729     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "GetHwMnoteData new mnote hw data failed.");
730     exif_data_set_priv_md(exifData_, (ExifMnoteData *)md);
731     unsigned long hwsize = sizeof(INIT_HW_DATA) / sizeof(INIT_HW_DATA[0]);
732     md->methods.load(md, INIT_HW_DATA, hwsize);
733     auto makernote = CreateEntry(MAKER_NOTE_TAG, EXIF_TAG_MAKER_NOTE, hwsize);
734     cond = makernote == nullptr;
735     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "GetHwMnoteData create maker note failed.");
736     cond = memcpy_s(makernote->data, hwsize - EXIF_HEAD_SIZE, INIT_HW_DATA + EXIF_HEAD_SIZE,
737                     hwsize - EXIF_HEAD_SIZE) != 0;
738     CHECK_ERROR_PRINT_LOG(cond, "Failed to copy memory for ExifEntry. Requested size: %{public}lu", hwsize);
739     isNewMaker = true;
740     return md;
741 }
742 
SetCommonValue(const std::string & key,const std::string & value)743 bool ExifMetadata::SetCommonValue(const std::string &key, const std::string &value)
744 {
745     size_t valueLen = value.length();
746     ExifEntry *ptrEntry = GetEntry(key, valueLen);
747     bool cond = ptrEntry == nullptr;
748     CHECK_ERROR_RETURN_RET(cond, false);
749     cond = ptrEntry->parent == nullptr;
750     CHECK_ERROR_RETURN_RET(cond, false);
751     ExifByteOrder order = exif_data_get_byte_order(ptrEntry->parent->parent);
752     bool isSetSuccess = false;
753     switch (ptrEntry->format) {
754         case EXIF_FORMAT_SHORT:
755             isSetSuccess = SetShort(ptrEntry, order, value);
756             break;
757         case EXIF_FORMAT_LONG:
758             isSetSuccess = SetLong(ptrEntry, order, value);
759             break;
760         case EXIF_FORMAT_SSHORT:
761             isSetSuccess = SetSShort(ptrEntry, order, value);
762             break;
763         case EXIF_FORMAT_SLONG:
764             isSetSuccess = SetSLong(ptrEntry, order, value);
765             break;
766         case EXIF_FORMAT_RATIONAL:
767             isSetSuccess = SetRational(ptrEntry, order, value);
768             break;
769         case EXIF_FORMAT_SRATIONAL:
770             isSetSuccess = SetSRational(ptrEntry, order, value);
771             break;
772         case EXIF_FORMAT_BYTE:
773             isSetSuccess = SetByte(ptrEntry, value);
774             break;
775         case EXIF_FORMAT_UNDEFINED:
776         case EXIF_FORMAT_ASCII:
777             isSetSuccess = SetMem(ptrEntry, value, valueLen);
778             break;
779         default:
780             IMAGE_LOGE("Unsupported Exif format for key: %{public}s", key.c_str());
781             break;
782     }
783     return isSetSuccess;
784 }
785 
RemoveEntry(const std::string & key)786 bool ExifMetadata::RemoveEntry(const std::string &key)
787 {
788     bool isSuccess = false;
789     bool cond = false;
790     cond = !(exifData_ && ExifMetadatFormatter::IsModifyAllowed(key));
791     CHECK_DEBUG_RETURN_RET_LOG(cond, isSuccess,
792                                "RemoveEntry failed, can not remove entry for key: %{public}s", key.c_str());
793 
794     if ((key.size() > KEY_SIZE && key.substr(0, KEY_SIZE) == "Hw") ||
795         IsSpecialHwKey(key)) {
796         return RemoveHwEntry(key);
797     }
798 
799     ExifEntry *entry = GetEntry(key);
800     cond = !entry;
801     CHECK_DEBUG_RETURN_RET_LOG(cond, isSuccess,
802                                "RemoveEntry failed, can not find entry for key: %{public}s", key.c_str());
803 
804     IMAGE_LOGD("RemoveEntry for key: %{public}s", key.c_str());
805     exif_content_remove_entry(entry->parent, entry);
806     isSuccess = true;
807     return isSuccess;
808 }
809 
RemoveHwEntry(const std::string & key)810 bool ExifMetadata::RemoveHwEntry(const std::string &key)
811 {
812     ExifMnoteData *md = exif_data_get_mnote_data(exifData_);
813 
814     bool cond = false;
815     cond = !is_huawei_md(md);
816     CHECK_DEBUG_RETURN_RET_LOG(cond, false, "Exif makernote is not huawei makernote");
817 
818     MnoteHuaweiTag tag = mnote_huawei_tag_from_name(key.c_str());
819     auto *entry = exif_mnote_data_huawei_get_entry_by_tag((ExifMnoteDataHuawei*) md, tag);
820     cond = !entry;
821     CHECK_ERROR_RETURN_RET_LOG(cond, false,
822                                "Get entry by tag failed, there is no entry for key: %{public}s", key.c_str());
823 
824     exif_mnote_data_remove_entry(md, entry);
825     return true;
826 }
827 
IsSpecialHwKey(const std::string & key) const828 bool ExifMetadata::IsSpecialHwKey(const std::string &key) const
829 {
830     auto iter = HW_SPECIAL_KEYS.find(key);
831     return (iter != HW_SPECIAL_KEYS.end());
832 }
833 
GetFilterArea(const std::vector<std::string> & exifKeys,std::vector<std::pair<uint32_t,uint32_t>> & ranges)834 void ExifMetadata::GetFilterArea(const std::vector<std::string> &exifKeys,
835                                  std::vector<std::pair<uint32_t, uint32_t>> &ranges)
836 {
837     if (exifData_ == nullptr) {
838         IMAGE_LOGD("Exif data is null");
839         return ;
840     }
841     auto size = exifKeys.size();
842     for (unsigned long keySize = 0; keySize < size; keySize++) {
843         ExifTag tag = exif_tag_from_name(exifKeys[keySize].c_str());
844         FindRanges(tag, ranges);
845     }
846 }
847 
848 // If the tag is a rational or srational, we need to store the offset and size of the numerator
FindRationalRanges(ExifContent * content,std::vector<std::pair<uint32_t,uint32_t>> & ranges,int index)849 void ExifMetadata::FindRationalRanges(ExifContent *content,
850     std::vector<std::pair<uint32_t, uint32_t>> &ranges, int index)
851 {
852     for (unsigned long i = 0; i < content->entries[index]->components; i++) {
853         std::pair<uint32_t, uint32_t> range =
854             std::make_pair(content->entries[index]->offset +
855             static_cast<unsigned long>(exif_format_get_size(content->entries[index]->format)) * i, NUMERATOR_SIZE);
856         ranges.push_back(range);
857     }
858     return;
859 }
860 
FindRanges(const ExifTag & tag,std::vector<std::pair<uint32_t,uint32_t>> & ranges)861 void ExifMetadata::FindRanges(const ExifTag &tag, std::vector<std::pair<uint32_t, uint32_t>> &ranges)
862 {
863     bool hasRange = false;
864 
865     int ifd = 0;
866     while (ifd < EXIF_IFD_COUNT && !hasRange) {
867         ExifContent *content = exifData_->ifd[ifd];
868         if (!content) {
869             IMAGE_LOGD("IFD content is null, ifd: %{public}d.", ifd);
870             return ;
871         }
872 
873         int i = 0;
874         while (i < static_cast<int>(content->count) && !hasRange) {
875             if (tag == content->entries[i]->tag) {
876                 (content->entries[i]->format == EXIF_FORMAT_RATIONAL ||
877                     content->entries[i]->format == EXIF_FORMAT_SRATIONAL)
878                     ? FindRationalRanges(content, ranges, i)
879                     : ranges.push_back(std::make_pair(content->entries[i]->offset, content->entries[i]->size));
880                 hasRange = true;
881             }
882             ++i;
883         }
884         ++ifd;
885     }
886 }
887 
Marshalling(Parcel & parcel) const888 bool ExifMetadata::Marshalling(Parcel &parcel) const
889 {
890     if (exifData_ == nullptr) {
891         return false;
892     }
893 
894     unsigned char *data = nullptr;
895     unsigned int size = 0;
896     exif_data_save_data(exifData_, &data, &size);
897     bool cond = false;
898 
899     if (!parcel.WriteBool(data != nullptr && size != 0)) {
900         IMAGE_LOGE("Failed to write exif data buffer existence value.");
901         return false;
902     }
903 
904     cond = size > MAX_EXIFMETADATA_MAX_SIZE;
905     CHECK_ERROR_RETURN_RET_LOG(cond, false, "The size of exif metadata exceeds the maximum limit.");
906 
907     if (data != nullptr && size != 0) {
908         std::unique_ptr<unsigned char[]> exifData(data);
909         if (!parcel.WriteUint32(static_cast<uint32_t>(size))) {
910             return false;
911         }
912         cond = !parcel.WriteUnpadBuffer(exifData.get(), size);
913         CHECK_ERROR_RETURN_RET(cond, false);
914         return true;
915     }
916     return false;
917 }
918 
Unmarshalling(Parcel & parcel)919 ExifMetadata *ExifMetadata::Unmarshalling(Parcel &parcel)
920 {
921     PICTURE_ERR error;
922     ExifMetadata* dstExifMetadata = ExifMetadata::Unmarshalling(parcel, error);
923     if (dstExifMetadata == nullptr || error.errorCode != SUCCESS) {
924         IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
925             error.errorCode, error.errorInfo.c_str());
926     }
927     return dstExifMetadata;
928 }
929 
Unmarshalling(Parcel & parcel,PICTURE_ERR & error)930 ExifMetadata *ExifMetadata::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
931 {
932     bool hasExifDataBuffer = parcel.ReadBool();
933     bool cond = false;
934     if (hasExifDataBuffer) {
935         uint32_t size = 0;
936         if (!parcel.ReadUint32(size)) {
937             return nullptr;
938         }
939 
940         cond = size > MAX_EXIFMETADATA_MAX_SIZE;
941         CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "The size of exif metadata exceeds the maximum limit.");
942 
943         const uint8_t *data = parcel.ReadUnpadBuffer(static_cast<size_t>(size));
944         if (!data) {
945             return nullptr;
946         }
947         ExifData *ptrData = exif_data_new();
948         cond = ptrData == nullptr;
949         CHECK_ERROR_RETURN_RET(cond, nullptr);
950         exif_data_unset_option(ptrData, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
951         exif_data_load_data(ptrData, static_cast<const unsigned char *>(data), static_cast<unsigned int>(size));
952         ExifMetadata *exifMetadata = new(std::nothrow) ExifMetadata(ptrData);
953         return exifMetadata;
954     }
955     return nullptr;
956 }
957 
RemoveExifThumbnail()958 bool ExifMetadata::RemoveExifThumbnail()
959 {
960     bool cond = exifData_ == nullptr;
961     CHECK_ERROR_RETURN_RET(cond, false);
962     exifData_->remove_thumbnail = 1;
963     return true;
964 }
965 
GetUserMakerNote(std::string & value) const966 int ExifMetadata::GetUserMakerNote(std::string& value) const
967 {
968     bool cond{false};
969     std::vector<char> userValueChar(MAX_TAG_VALUE_SIZE_FOR_STR, 0);
970     int count = exif_data_get_maker_note_entry_count(exifData_);
971     cond = count != GET_SUPPORT_MAKERNOTE_COUNT;
972     CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DECODE_EXIF_UNSUPPORT);
973     ExifEntry *entry = exif_data_get_entry(exifData_, EXIF_TAG_MAKER_NOTE);
974     cond = entry == nullptr;
975     CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DECODE_EXIF_UNSUPPORT);
976     cond = entry->size >= MAX_TAG_VALUE_SIZE_FOR_STR;
977     CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DECODE_EXIF_UNSUPPORT);
978     exif_entry_get_value(entry, userValueChar.data(), userValueChar.size());
979     value.assign(userValueChar.data(), entry->size);
980     return SUCCESS;
981 }
982 } // namespace Media
983 } // namespace OHOS
984