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