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