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 <config.h>
17 #include "exif-mnote-data-huawei.h"
18 #include "mnote-huawei-entry.h"
19 #include "mnote-huawei-data-type.h"
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include <libexif/exif-byte-order.h>
26 #include <libexif/exif-utils.h>
27 #include <libexif/exif-data.h>
28
29 #define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || \
30 (offset > datasize - structsize ))
31
32 const int DATA_OR_OFFSET = 4;
33 const int HUAWEI_HEADER_OFFSET = 8;
34 const int MAX_DATA_LOAD_TIMES = 10;
35 const unsigned int MAX_HUAWEI_MNOTE_ENTRY_NUM = 10 * 1000;
36 const char HUAWEI_HEADER[] = { 'H', 'U', 'A', 'W', 'E', 'I', '\0', '\0',
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
38
39 void
exif_mnote_data_huawei_clear(ExifMnoteDataHuawei * n)40 exif_mnote_data_huawei_clear (ExifMnoteDataHuawei *n)
41 {
42 ExifMnoteData *d = (ExifMnoteData *) n;
43
44 if (!n) return;
45
46 if (n->entries) {
47 for (unsigned int i = 0; i < n->count; i++) {
48 if (n->entries[i].data) {
49 exif_mem_free(d->mem, n->entries[i].data);
50 n->entries[i].data = NULL;
51 n->entries[i].size = 0;
52 }
53
54 if (n->entries[i].md) {
55 exif_mnote_data_huawei_clear((ExifMnoteDataHuawei *) n->entries[i].md);
56 exif_mem_free(d->mem, n->entries[i].md);
57 n->entries[i].md = NULL;
58 }
59 }
60
61 exif_mem_free (d->mem, n->entries);
62 n->entries = NULL;
63 n->count = 0;
64 n->is_loaded = 0;
65 }
66
67 if (n->ifd_tag != MNOTE_HUAWEI_INFO) {
68 if (d->priv) {
69 exif_mem_free(d->mem, d->priv);
70 d->priv = NULL;
71 }
72 exif_mem_unref (d->mem);
73 }
74 }
75
76 static void
exif_mnote_data_huawei_free(ExifMnoteData * ne)77 exif_mnote_data_huawei_free (ExifMnoteData *ne)
78 {
79 if (!ne) return;
80 exif_mnote_data_huawei_clear ((ExifMnoteDataHuawei*) ne);
81 }
82
83 static void
exif_mnote_data_huawei_set_byte_order(ExifMnoteData * n,ExifByteOrder o)84 exif_mnote_data_huawei_set_byte_order (ExifMnoteData *n, ExifByteOrder o)
85 {
86 if (n) ((ExifMnoteDataHuawei *) n)->order = o;
87 }
88
89 static void
exif_mnote_data_huawei_set_offset(ExifMnoteData * n,unsigned int o)90 exif_mnote_data_huawei_set_offset (ExifMnoteData *n, unsigned int o)
91 {
92 if (n) ((ExifMnoteDataHuawei *) n)->offset = o;
93 }
94
95 static void
exif_mnote_data_huawei_malloc_size_data(ExifMnoteData * ne,unsigned int * malloc_size)96 exif_mnote_data_huawei_malloc_size_data (ExifMnoteData *ne, unsigned int *malloc_size)
97 {
98 if (!ne) return;
99 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
100 if (!n) {
101 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteHuawei", "n is NULL");
102 *malloc_size = 0;
103 return;
104 }
105
106 unsigned int ifd_size = 2 + n->count * 12 + 4;
107 *malloc_size = *malloc_size + ifd_size;
108
109 if (n->count > MAX_HUAWEI_MNOTE_ENTRY_NUM) {
110 return;
111 }
112 for (unsigned int i = 0; i < n->count; i++) {
113 if (n->entries[i].md) {
114 exif_mnote_data_huawei_malloc_size_data(n->entries[i].md, malloc_size);
115 ExifMnoteDataHuawei *t_n = n->entries[i].md;
116 ifd_size += t_n->ifd_size;
117 }
118 size_t components_size = exif_format_get_size (n->entries[i].format) *
119 n->entries[i].components;
120 if (*malloc_size > 65536) {
121 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteHuawei", "malloc_size: (%d) too big", *malloc_size);
122 *malloc_size = 0;
123 return;
124 }
125
126 if (components_size > DATA_OR_OFFSET) {
127 ifd_size += components_size;
128 *malloc_size = *malloc_size + components_size;
129 }
130 }
131 n->ifd_size = ifd_size;
132 }
133
134 static void
exif_mnote_data_huawei_save_data(ExifMnoteData * ne,unsigned char * buf,unsigned int buf_size,const unsigned char * pOrder)135 exif_mnote_data_huawei_save_data (ExifMnoteData *ne, unsigned char *buf,
136 unsigned int buf_size, const unsigned char *pOrder)
137 {
138
139 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
140 if (!n || !buf || !buf_size || !pOrder) return;
141
142 unsigned int offset=0;
143 const unsigned int ifd_data_offset = 2 + n->count * 12 + 4;
144 unsigned int ifd_data_offset_increment = 0;
145
146 /* Save the number of entries */
147 exif_set_short (buf, n->order, (ExifShort) n->count);
148
149 /* Save each entry */
150 if (n->count > MAX_HUAWEI_MNOTE_ENTRY_NUM) {
151 return;
152 }
153 for (unsigned int i = 0; i < n->count; i++) {
154 offset = 2 + i * 12;
155 exif_set_short (buf + offset + 0, n->order, (ExifShort) n->entries[i].tag);
156 exif_set_short (buf + offset + 2, n->order, (ExifShort) n->entries[i].format);
157 exif_set_long (buf + offset + 4, n->order, n->entries[i].components);
158 offset += 8;
159
160 unsigned int components_size = exif_format_get_size (n->entries[i].format) *
161 n->entries[i].components;
162
163 unsigned int t_offset = buf + ifd_data_offset + ifd_data_offset_increment - pOrder;
164 if (n->entries[i].md) {
165 exif_set_long (buf + offset, n->order, t_offset);
166 ExifMnoteDataHuawei *t_n = n->entries[i].md;
167 exif_mnote_data_huawei_save_data(n->entries[i].md,
168 buf+ifd_data_offset + ifd_data_offset_increment,
169 t_n->ifd_size, pOrder);
170 ifd_data_offset_increment += t_n->ifd_size;
171 exif_set_long (n->entries[i].data, n->order, t_offset);
172 }
173
174 if (components_size > DATA_OR_OFFSET) {
175 // write data offset
176 exif_set_long (buf + offset, n->order, t_offset);
177
178 // write data
179 if (n->entries[i].data) {
180 if (CHECKOVERFLOW(ifd_data_offset + ifd_data_offset_increment, buf_size, components_size)) {
181 continue;
182 }
183 memcpy(buf + ifd_data_offset + ifd_data_offset_increment, n->entries[i].data, components_size);
184 }
185 ifd_data_offset_increment += components_size;
186
187 } else {
188 if (CHECKOVERFLOW(offset, buf_size, components_size)) {
189 continue;
190 }
191 memcpy (buf + offset, n->entries[i].data, components_size);
192 }
193 }
194 }
195
196 static void
exif_mnote_data_huawei_save(ExifMnoteData * ne,unsigned char ** buf,unsigned int * buf_size)197 exif_mnote_data_huawei_save (ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size)
198 {
199
200 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei*) ne;
201 if (!n) return;
202 if (!n->count) {
203 *buf_size = 0;
204 return;
205 }
206
207 unsigned char *t_buf = NULL;
208 unsigned int malloc_size = sizeof(HUAWEI_HEADER);
209
210 exif_mnote_data_huawei_malloc_size_data(ne, &malloc_size);
211 if (!malloc_size) {
212 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteHuawei", "The memory(%d) request failed", malloc_size);
213 return;
214 }
215
216 t_buf = exif_mem_alloc (ne->mem, malloc_size);
217 if (!t_buf) {
218 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteHuawei", malloc_size);
219 return;
220 }
221
222 memcpy(t_buf, HUAWEI_HEADER, 8);
223 if (n->order == EXIF_BYTE_ORDER_INTEL) {
224 (t_buf + 8)[0] = 'I';
225 (t_buf + 8)[1] = 'I';
226 } else {
227 (t_buf + 8)[0] = 'M';
228 (t_buf + 8)[1] = 'M';
229 }
230 exif_set_short (t_buf + 10, n->order, 0x002a);
231 exif_set_long (t_buf + 12, n->order, 8);
232
233 exif_mnote_data_huawei_save_data(ne, t_buf+sizeof(HUAWEI_HEADER), n->ifd_size, t_buf+HUAWEI_HEADER_OFFSET);
234
235 *buf = t_buf;
236 *buf_size = malloc_size;
237 }
238
239 static int
exif_mnote_data_huawei_load_data(ExifMnoteData * ne,const unsigned char * buf,unsigned int buf_size,unsigned int * cur_ifd_data_offset,const unsigned int order_offset,unsigned int load_times)240 exif_mnote_data_huawei_load_data (ExifMnoteData *ne, const unsigned char *buf, unsigned int buf_size,
241 unsigned int* cur_ifd_data_offset, const unsigned int order_offset,
242 unsigned int load_times)
243 {
244 size_t tcount, offset, ifd_size=0;
245 int ret = 0;
246
247 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
248 if (CHECKOVERFLOW(*cur_ifd_data_offset, buf_size, 2) || load_times > MAX_DATA_LOAD_TIMES) {
249 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
250 "ExifMnoteDataHuawei", "MakerNote data is abnormal.");
251 return -1;
252 }
253 const unsigned char *ifd_data = buf + *cur_ifd_data_offset;
254 ExifShort count = exif_get_short (ifd_data, n->order);
255 if (count > 100) {
256 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteHuawei", "Too much tags (%d) in Huawei MakerNote", count);
257 return -1;
258 }
259 offset = 2;
260
261 MnoteHuaweiEntry* entries = exif_mem_alloc (ne->mem, sizeof (MnoteHuaweiEntry) * count);
262 if (!entries) {
263 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteHuawei", sizeof (MnoteHuaweiEntry) * count);
264 return -1;
265 }
266 memset(entries, 0, sizeof (MnoteHuaweiEntry) * count);
267
268 /* Parse the entries */
269 tcount = 0;
270 for (int i = 0; i < count; i++, offset += 12) {
271 if (CHECKOVERFLOW(*cur_ifd_data_offset + offset, buf_size, 12)) {
272 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
273 "ExifMnoteDataHuawei", "Short MakerNote");
274 break;
275 }
276 entries[tcount].tag = exif_get_short (ifd_data + offset, n->order);
277 entries[tcount].format = exif_get_short (ifd_data + offset + 2, n->order);
278 entries[tcount].components = exif_get_long (ifd_data + offset + 4, n->order);
279 entries[tcount].order = n->order;
280 entries[tcount].parent_md = n;
281 entries[tcount].mem = ne->mem;
282
283 size_t components_size = exif_format_get_size (entries[tcount].format) * entries[tcount].components;
284 entries[tcount].size = components_size;
285 if (!components_size) {
286 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
287 "ExifMnoteHuawei",
288 "Invalid zero-length tag size");
289 continue;
290 }
291
292 size_t t_offset = offset + HUAWEI_HEADER_OFFSET;
293 if (components_size > 4) t_offset = exif_get_long (ifd_data + t_offset, n->order) + HUAWEI_HEADER_OFFSET;
294 if (CHECKOVERFLOW(t_offset, buf_size, components_size)) {
295 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
296 "ExifMnoteDataHuawei", "Tag data past end of buffer");
297 continue;
298 }
299 entries[tcount].data = exif_mem_alloc (ne->mem, components_size);
300 if (!entries[tcount].data) {
301 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteHuawei", components_size);
302 continue;
303 }
304
305 unsigned int t_size = 0;
306 if (components_size > 4) {
307 t_size = order_offset + t_offset - HUAWEI_HEADER_OFFSET + components_size;
308 if (CHECKOVERFLOW(t_size, buf_size, components_size)) {
309 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
310 "ExifMnoteDataHuawei", "Tag data past end of buffer");
311 continue;
312 }
313 memcpy (entries[tcount].data, buf + order_offset + t_offset - HUAWEI_HEADER_OFFSET, components_size);
314 } else {
315 if (CHECKOVERFLOW(*cur_ifd_data_offset + t_offset, buf_size, components_size)) {
316 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
317 "ExifMnoteDataHuawei", "Tag data past end of buffer");
318 continue;
319 }
320 memcpy (entries[tcount].data, ifd_data + t_offset, components_size);
321 }
322
323 MnoteHuaweiTag tag = entries[tcount].tag;
324 int needLoadData = (tag == MNOTE_HUAWEI_SCENE_INFO || tag == MNOTE_HUAWEI_FACE_INFO) && components_size >= 4;
325 if (needLoadData) {
326
327 *cur_ifd_data_offset = order_offset + exif_get_long (entries[tcount].data, n->order);
328 if (CHECKOVERFLOW(*cur_ifd_data_offset, buf_size, 2)) {
329 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
330 "ExifMnoteDataHuawei", "Tag data past end of buffer");
331 continue;
332 }
333 ExifMnoteDataHuawei* md = (ExifMnoteDataHuawei*)exif_mnote_data_huawei_new(ne->mem);
334
335 if (!md) {
336 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
337 "ExifMnoteHuawei",
338 "Invalid zero-length tag size");
339 return -1;
340 }
341
342 md->order = n->order;
343 ret = exif_mnote_data_huawei_load_data((ExifMnoteData*)md, buf, buf_size,
344 cur_ifd_data_offset, order_offset, ++load_times);
345 if (ret == -1) {
346 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
347 "ExifMnoteHuawei",
348 "exif_mnote_data_huawei_load_ failed");
349 return ret;
350 }
351 md->ifd_tag = tag;
352 entries[tcount].md = md;
353 }
354
355 ifd_size += offset;
356 ++tcount;
357 }
358 /* Store the count of successfully parsed tags */
359 n->count = tcount;
360 n->entries = entries;
361 n->is_loaded = 1;
362
363 return 0;
364 }
365
366 static void
exif_mnote_data_huawei_load(ExifMnoteData * ne,const unsigned char * buf,unsigned int buf_size)367 exif_mnote_data_huawei_load (ExifMnoteData *ne, const unsigned char *buf, unsigned int buf_size)
368 {
369 if (!ne) return;
370 unsigned int head_offset = 6;
371 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
372 if (!n || !buf || !buf_size) {
373 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
374 "ExifMnoteHuawei", "Short MakerNote");
375 return;
376 }
377
378 n->ifd_tag = MNOTE_HUAWEI_INFO;
379
380 if ((buf[0] == 'I' && buf[1] == 'I') || (buf[0] == 'M' && buf[1] == 'M')) {
381 head_offset = 0;
382 }
383
384 unsigned int order_offset = n->offset + head_offset + HUAWEI_HEADER_OFFSET;
385 if (CHECKOVERFLOW(order_offset, buf_size, 2)) {
386 return;
387 }
388 const void *pOrder = buf + order_offset;
389
390 //read order
391 if (!memcmp (pOrder, "II", 2))
392 n->order = EXIF_BYTE_ORDER_INTEL;
393 else if (!memcmp (pOrder, "MM", 2))
394 n->order = EXIF_BYTE_ORDER_MOTOROLA;
395 else {
396 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
397 "ExifMnoteHuawei", "Unknown order.");
398 return;
399 }
400
401 /* Remove any old entries */
402 exif_mnote_data_huawei_clear (n);
403
404 unsigned int ifd_data_offset= n->offset + head_offset + sizeof(HUAWEI_HEADER);
405 unsigned int load_times = 1;
406 int ret = exif_mnote_data_huawei_load_data(ne, buf, buf_size, &ifd_data_offset, order_offset, load_times);
407 if (ret) {
408 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
409 "ExifMnoteHuawei", "entries exif_mnote_data_huawei_load_ failed");
410 return;
411 }
412 }
413
414 unsigned int
exif_mnote_data_huawei_count_data(ExifMnoteData * ne,MnoteHuaweiEntryCount * ec)415 exif_mnote_data_huawei_count_data (ExifMnoteData *ne, MnoteHuaweiEntryCount* ec)
416 {
417 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
418 if (!ne) return 0;
419
420 if (n->count > MAX_HUAWEI_MNOTE_ENTRY_NUM) {
421 return 0;
422 }
423 unsigned int count = n->count;
424 for (unsigned int i = 0; i < n->count; i++) {
425 if (ec && (ec->size > ec->idx)) {
426 ec->entries[ec->idx] = &n->entries[i];
427 ec->idx += 1;
428 }
429
430 ExifMnoteData *md = n->entries[i].md;
431 if (md) {
432 count += exif_mnote_data_huawei_count_data(md, ec);
433 }
434 }
435 return count;
436 }
437
438 unsigned int
exif_mnote_data_huawei_count(ExifMnoteData * ne)439 exif_mnote_data_huawei_count (ExifMnoteData *ne)
440 {
441 if (!ne) return 0;
442 unsigned int count = exif_mnote_data_huawei_count_data(ne, NULL);
443 return count;
444 };
445
446 MnoteHuaweiEntry*
exif_mnote_data_huawei_get_entry_by_tag_data(ExifMnoteDataHuawei * n,int * idx,const MnoteHuaweiTag tag)447 exif_mnote_data_huawei_get_entry_by_tag_data (ExifMnoteDataHuawei *n, int *idx,
448 const MnoteHuaweiTag tag)
449 {
450 MnoteHuaweiEntry* entry = NULL;
451 if (!n) return NULL;
452
453 for (unsigned int i = 0; i < n->count; i++) {
454 if (n->entries[i].tag == tag) {
455 entry = &n->entries[i];
456 break;
457 }
458 *idx += 1;
459
460 ExifMnoteData *md = n->entries[i].md;
461 if (md) {
462 entry = exif_mnote_data_huawei_get_entry_by_tag_data((ExifMnoteDataHuawei *)md,
463 idx, tag);
464 if (entry) break;
465 }
466 }
467 return entry;
468 }
469
470 MnoteHuaweiEntry*
exif_mnote_data_huawei_get_entry_by_tag(ExifMnoteDataHuawei * n,const MnoteHuaweiTag tag)471 exif_mnote_data_huawei_get_entry_by_tag (ExifMnoteDataHuawei *n, const MnoteHuaweiTag tag)
472 {
473 int i = 0;
474 return exif_mnote_data_huawei_get_entry_by_tag_data(n, &i, tag);
475 }
476
477 MnoteHuaweiEntry*
exif_mnote_data_huawei_get_entry_by_index_data(ExifMnoteDataHuawei * n,int * idx,const int dest_idx)478 exif_mnote_data_huawei_get_entry_by_index_data (ExifMnoteDataHuawei *n, int *idx, const int dest_idx)
479 {
480 MnoteHuaweiEntry* entry = NULL;
481 if (!n) return NULL;
482
483 for (unsigned int i = 0; i < n->count; i++) {
484 if (*idx == dest_idx) {
485 entry = &n->entries[i];
486 break;
487 }
488 *idx += 1;
489
490 ExifMnoteData *md = n->entries[i].md;
491 if (md) {
492 entry = exif_mnote_data_huawei_get_entry_by_index_data((ExifMnoteDataHuawei *)md, idx, dest_idx);
493 if (entry) break;
494 }
495 }
496 return entry;
497 }
498
499 MnoteHuaweiEntry*
exif_mnote_data_huawei_get_entry_by_index(ExifMnoteDataHuawei * n,const int dest_idx)500 exif_mnote_data_huawei_get_entry_by_index (ExifMnoteDataHuawei *n, const int dest_idx)
501 {
502 int i = 0;
503 return exif_mnote_data_huawei_get_entry_by_index_data(n, &i, dest_idx);
504 }
505
506 void
mnote_huawei_get_entry_count(const ExifMnoteDataHuawei * n,MnoteHuaweiEntryCount ** entry_count)507 mnote_huawei_get_entry_count (const ExifMnoteDataHuawei* n, MnoteHuaweiEntryCount** entry_count)
508 {
509 if (!n) return;
510
511 ExifMnoteData* ne = (ExifMnoteData*)n;
512 if (ne->methods.load != exif_mnote_data_huawei_load) return;
513
514 if (entry_count && *entry_count) {
515 mnote_huawei_free_entry_count(*entry_count);
516 *entry_count = NULL;
517 }
518
519 MnoteHuaweiEntryCount* ec = exif_huawei_entry_count_new();
520
521 unsigned int count = exif_mnote_data_huawei_count_data(ne, NULL);
522 if (!count || !ec) {
523 mnote_huawei_free_entry_count(ec);
524 return;
525 }
526
527 ec->entries = exif_mem_alloc (ec->mem, sizeof(MnoteHuaweiEntry*) * count);
528 if (!ec->entries) {
529 mnote_huawei_free_entry_count(ec);
530 return;
531 }
532 ec->size = count;
533
534 exif_mnote_data_huawei_count_data(ne, ec);
535 if (!entry_count) return;
536 *entry_count = ec;
537 }
538
539 void
mnote_huawei_free_entry_count(MnoteHuaweiEntryCount * entry_count)540 mnote_huawei_free_entry_count (MnoteHuaweiEntryCount* entry_count)
541 {
542 exif_huawei_entry_count_free(entry_count);
543 }
544
545 static unsigned int
exif_mnote_data_huawei_get_id(ExifMnoteData * ne,unsigned int i)546 exif_mnote_data_huawei_get_id (ExifMnoteData *ne, unsigned int i)
547 {
548 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
549 if (!n) return 0;
550
551 MnoteHuaweiEntry* entry = exif_mnote_data_huawei_get_entry_by_index (n, i);
552 if (!entry) return 0;
553
554 return entry->tag;
555 }
556
557 static const char *
exif_mnote_data_huawei_get_name(ExifMnoteData * ne,unsigned int i)558 exif_mnote_data_huawei_get_name (ExifMnoteData *ne, unsigned int i)
559 {
560 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
561 if (!n) return NULL;
562
563 MnoteHuaweiEntry* entry = exif_mnote_data_huawei_get_entry_by_index (n, i);
564 if (!entry) return NULL;
565
566 return mnote_huawei_tag_get_name(entry->tag);
567 }
568
569 static const char *
exif_mnote_data_huawei_get_title(ExifMnoteData * ne,unsigned int i)570 exif_mnote_data_huawei_get_title (ExifMnoteData *ne, unsigned int i)
571 {
572 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
573 if (!n) return NULL;
574
575 MnoteHuaweiEntry* entry = exif_mnote_data_huawei_get_entry_by_index (n, i);
576 if (!entry) return NULL;
577
578 return mnote_huawei_tag_get_title(entry->tag);
579 }
580
581 static const char *
exif_mnote_data_huawei_get_description(ExifMnoteData * ne,unsigned int i)582 exif_mnote_data_huawei_get_description (ExifMnoteData *ne, unsigned int i)
583 {
584 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
585 if (!n) return NULL;
586
587 MnoteHuaweiEntry* entry = exif_mnote_data_huawei_get_entry_by_index (n, i);
588 if (!entry) return NULL;
589
590 return mnote_huawei_tag_get_description(entry->tag);
591 }
592
593 static char *
exif_mnote_data_huawei_get_value(ExifMnoteData * ne,unsigned int i,char * val,unsigned int maxlen)594 exif_mnote_data_huawei_get_value (ExifMnoteData *ne, unsigned int i, char *val, unsigned int maxlen)
595 {
596 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
597 if (!n) return NULL;
598
599 MnoteHuaweiEntry* entry = exif_mnote_data_huawei_get_entry_by_index (n, i);
600 if (!entry) return NULL;
601
602 return mnote_huawei_entry_get_value(entry, val, maxlen);
603 }
604
605 ExifByteOrder
exif_mnote_data_huawei_get_byte_order(ExifMnoteData * ne)606 exif_mnote_data_huawei_get_byte_order(ExifMnoteData *ne)
607 {
608 if(!ne && !is_huawei_md(ne))
609 return EXIF_BYTE_ORDER_MOTOROLA;
610 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
611 return n->order;
612 }
613
614 ExifMem *
exif_mnote_data_huawei_get_root_mem(ExifMnoteData * ne)615 exif_mnote_data_huawei_get_root_mem(ExifMnoteData *ne)
616 {
617 if(!ne && !is_huawei_md(ne))
618 return NULL;
619 return ne->mem;
620 }
621
622 MnoteHuaweiEntry *
exif_mnote_data_create_md_entry(ExifMnoteData * ne,MnoteHuaweiTag tag,MnoteHuaweiEntry * sub_entry)623 exif_mnote_data_create_md_entry(ExifMnoteData *ne, MnoteHuaweiTag tag, MnoteHuaweiEntry *sub_entry)
624 {
625 MnoteHuaweiEntry *new_entry = NULL;
626 ExifMnoteDataHuawei *new_md = NULL;
627
628 if (!ne || !sub_entry)
629 goto Failed;
630 if (!(tag == MNOTE_HUAWEI_SCENE_INFO || tag == MNOTE_HUAWEI_FACE_INFO))
631 goto Failed;
632
633 new_entry = mnote_huawei_entry_new(ne);
634 if (!new_entry)
635 goto Failed;
636 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei*) ne;
637 mnote_huawei_entry_initialize(new_entry, tag, n->order);
638
639 new_md = (ExifMnoteDataHuawei *)exif_mnote_data_huawei_new(ne->mem);
640 if (!new_md)
641 goto Failed;
642
643 new_md->count = 1;
644 new_md->ifd_tag = tag;
645 new_md->order = n->order;
646 new_md->entries = sub_entry;
647 new_md->is_loaded = 1;
648 new_entry->md = new_md;
649 return new_entry;
650
651 Failed:
652 if (new_entry)
653 mnote_huawei_entry_free(new_entry);
654 return NULL;
655 }
656
657 int
exif_mnote_data_add_entry(ExifMnoteData * ne,MnoteHuaweiEntry * e)658 exif_mnote_data_add_entry (ExifMnoteData *ne, MnoteHuaweiEntry *e)
659 {
660 int ret = 0;
661 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
662 MnoteHuaweiEntry *find_entry = NULL, *add_entry=NULL;
663 ExifMnoteDataHuawei *parent_md = NULL;
664 MnoteHuaweiEntryCount *ec = NULL;
665
666 if(!is_huawei_md(ne) || (n->ifd_tag != MNOTE_HUAWEI_INFO) || !e) {
667 ret = -1;
668 goto Failed;
669 }
670 MnoteHuaweiTag owner_tag = get_tag_owner_tag(e->tag);
671 if (owner_tag == MNOTE_HUAWEI_INFO)
672 parent_md = n;
673 mnote_huawei_get_entry_count(n, &ec);
674 if (!ec) {
675 ret = -1;
676 goto Failed;
677 }
678
679 for(unsigned int i=0; i<ec->size; i++) {
680 if(ec->entries[i]->tag == e->tag)
681 find_entry = ec->entries[i];
682 if(ec->entries[i]->tag == owner_tag)
683 parent_md = ec->entries[i]->md;
684 }
685 mnote_huawei_free_entry_count(ec);
686
687 if (find_entry) {
688 ret = -1;
689 goto Failed;
690 }
691
692 if (!parent_md) {
693 add_entry = exif_mnote_data_create_md_entry(ne, owner_tag, e);
694 if (!add_entry) {
695 ret = -1;
696 goto Failed;
697 }
698 parent_md = n;
699 } else {
700 add_entry = e;
701 }
702
703 MnoteHuaweiEntry *entries = exif_mem_realloc (ne->mem,
704 parent_md->entries, sizeof (MnoteHuaweiEntry) * (parent_md->count + 1));
705 if (!entries) {
706 ret = -1;
707 goto Failed;
708 }
709 add_entry->parent_md = parent_md;
710 memcpy(&entries[parent_md->count], add_entry, sizeof (MnoteHuaweiEntry));
711 n->entries = entries;
712 parent_md->count += 1;
713 if (add_entry && (add_entry != e))
714 mnote_huawei_entry_free_contour(add_entry);
715 return ret;
716
717 Failed:
718 if (add_entry && (add_entry != e))
719 mnote_huawei_entry_free(add_entry);
720 return ret;
721 }
722
723 void
exif_mnote_data_remove_entry(ExifMnoteData * ne,MnoteHuaweiEntry * e)724 exif_mnote_data_remove_entry (ExifMnoteData *ne, MnoteHuaweiEntry *e)
725 {
726 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *) ne;
727 if(!ne && !is_huawei_md(ne) && !e)
728 return;
729
730 MnoteHuaweiEntry *find_entry = exif_mnote_data_huawei_get_entry_by_tag(n, e->tag);
731 if (find_entry != e || !find_entry)
732 return;
733
734 ExifMnoteDataHuawei *parent_md = find_entry->parent_md;
735
736 unsigned int i=0;
737 MnoteHuaweiEntry *t = NULL;
738
739 /* Search the entry index */
740 for (; i < parent_md->count; i++)
741 if (&parent_md->entries[i] == e)
742 break;
743
744 /* Remove the entry */
745 if (parent_md->count > 1) {
746 t = exif_mem_alloc (ne->mem, sizeof(MnoteHuaweiEntry) * (parent_md->count - 1));
747 if (!t) {
748 return;
749 }
750 memcpy (t, parent_md->entries, sizeof (MnoteHuaweiEntry) * (i));
751 if (parent_md->count-i < 1) {
752 return;
753 }
754 unsigned int tail_count = parent_md->count-i-1;
755 if (tail_count)
756 memcpy (&t[i], &parent_md->entries[i+1], sizeof (MnoteHuaweiEntry) * (tail_count));
757
758 mnote_huawei_entry_free_content(e);
759 exif_mem_free(ne->mem, parent_md->entries);
760 parent_md->entries = t;
761 parent_md->count--;
762 } else {
763 MnoteHuaweiTag owner_tag = get_tag_owner_tag(e->tag);
764 MnoteHuaweiEntry *parent_entry = exif_mnote_data_huawei_get_entry_by_tag(n, owner_tag);
765 exif_mnote_data_remove_entry(ne, parent_entry);
766 }
767 }
768
769 int
exif_mnote_data_huawei_identify(const ExifData * ed,const ExifEntry * e)770 exif_mnote_data_huawei_identify (const ExifData *ed, const ExifEntry *e)
771 {
772 int ret = 0;
773
774 if (!e || e->size < sizeof(HUAWEI_HEADER) || !e->data)
775 return ret;
776 ret = !memcmp(e->data, HUAWEI_HEADER, 8);
777
778 return ret;
779 }
780
781 ExifMnoteData *
exif_mnote_data_huawei_new(ExifMem * mem)782 exif_mnote_data_huawei_new (ExifMem *mem)
783 {
784 ExifMnoteData *ne;
785
786 if (!mem) return NULL;
787
788 ne = exif_mem_alloc (mem, sizeof (ExifMnoteDataHuawei));
789 if (!ne)
790 return NULL;
791
792 memset(ne, 0, sizeof (ExifMnoteDataHuawei));
793 exif_mnote_data_construct (ne, mem);
794
795 /* Set up function pointers */
796 ne->methods.free = exif_mnote_data_huawei_free;
797 ne->methods.set_byte_order = exif_mnote_data_huawei_set_byte_order;
798 ne->methods.set_offset = exif_mnote_data_huawei_set_offset;
799 ne->methods.load = exif_mnote_data_huawei_load;
800 ne->methods.save = exif_mnote_data_huawei_save;
801 ne->methods.count = exif_mnote_data_huawei_count;
802 ne->methods.get_id = exif_mnote_data_huawei_get_id;
803 ne->methods.get_name = exif_mnote_data_huawei_get_name;
804 ne->methods.get_title = exif_mnote_data_huawei_get_title;
805 ne->methods.get_description = exif_mnote_data_huawei_get_description;
806 ne->methods.get_value = exif_mnote_data_huawei_get_value;
807
808 return ne;
809 }
810
811 void
memory_dump(const void * ptr,int len)812 memory_dump(const void *ptr, int len)
813 {
814 printf("%08X: ", 0);
815 for (int i = 0; i < len; i++) {
816 if (i % 8 == 0 && i != 0)
817 printf(" ");
818 if (i % 16 == 0 && i != 0)
819 printf("\n%08X: ", i);
820 printf("%02x ", *((uint8_t *)ptr + i));
821 }
822 printf("\n");
823 }
824
825 void
print_huawei_md(const ExifMnoteDataHuawei * n)826 print_huawei_md(const ExifMnoteDataHuawei *n)
827 {
828 printf("ifd_tag: %04X, count:%u, ifd_size:%u\n", n->ifd_tag, n->count, n->ifd_size);
829 MnoteHuaweiEntry *entries = n->entries;
830 for (int i=0; i<n->count; i++) {
831 printf("idx:%d, tag: %04X, type: %d, components:%lu\n", i, entries[i].tag, entries[i].format, entries[i].components);
832 memory_dump(entries[i].data, entries[i].size);
833 if (entries[i].md) {
834 print_huawei_md((ExifMnoteDataHuawei*) entries[i].md);
835 }
836 }
837 }
838
839 int
is_huawei_md(ExifMnoteData * ne)840 is_huawei_md(ExifMnoteData *ne)
841 {
842 ExifMnoteDataHuawei *n = (ExifMnoteDataHuawei *)ne;
843 if (ne && ne->methods.load == exif_mnote_data_huawei_load) {
844 if (n->is_loaded) return 1;
845 }
846 return 0;
847 }
848