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