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