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