• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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