• 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 #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