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