• 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-tag.h"
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
25 
26 #include <libexif/exif-format.h>
27 #include <libexif/exif-utils.h>
28 #include <libexif/i18n.h>
29 
30 char *
mnote_huawei_entry_get_value(MnoteHuaweiEntry * e,char * v,unsigned int maxlen)31 mnote_huawei_entry_get_value(MnoteHuaweiEntry *e, char *v, unsigned int maxlen)
32 {
33 	if (!v)
34 		return NULL;
35 
36 	memset(v, 0, maxlen);
37 	int write_pos = 0;
38 	ExifLong data = 0;
39 
40 	if (e->format == EXIF_FORMAT_ASCII) {
41 		snprintf(v, maxlen, _("%s"), e->data);
42 		return v;
43 	}
44 
45 	if (e->tag == MNOTE_MICRO_VIDEO_PRESENTATION_TIMESTAMP_US) {
46 		for (int i = 0; i < e->components && write_pos < maxlen; i++) {
47 			int offset = i * exif_format_get_size(e->format);
48 			ExifRational r = exif_get_rational(e->data + offset, e->order);
49 			if (r.denominator == 0) {
50 				write_pos += snprintf(v + write_pos, maxlen - write_pos, "%u ",
51 									  r.numerator);
52 			} else {
53 				write_pos += snprintf(v + write_pos, maxlen - write_pos, "%u%u ",
54 									  r.numerator, r.denominator);
55 			}
56 		}
57 		*(v + write_pos - 1) = 0;
58 		return v;
59 	}
60 
61 	for (int i = 0; i < e->components && write_pos < maxlen; i++) {
62 		if (e->format == EXIF_FORMAT_UNDEFINED) {
63 			data = (e->data + i)[0];
64 		} else if (e->format == EXIF_FORMAT_SLONG) {
65 			data = exif_get_slong(e->data + i * 4, e->order);
66 		} else if (e->format == EXIF_FORMAT_LONG) {
67 			data = exif_get_long(e->data + i * 4, e->order);
68 		} else {
69 			snprintf(v, maxlen, _("unsupported data types: %d"), e->format);
70 			return NULL;
71 		}
72 
73 		write_pos += snprintf(v + write_pos, maxlen - write_pos, "%d ", data);
74 	}
75 
76 	*(v + write_pos - 1) = 0;
77 	return v;
78 }
79 
80 int
mnote_huawei_entry_rational_timestamp_process(char * buff,const int buff_size,const char * v,int strlen,int * components,ExifMem * mem,ExifByteOrder order)81 mnote_huawei_entry_rational_timestamp_process(char *buff, const int buff_size, const char *v, int strlen,
82 									 		   int *components, ExifMem *mem, ExifByteOrder order)
83 {
84 	char *token = NULL, *pv = NULL;
85 	int components_local = 0, components_size = 0, ret = 0;
86 	const int increment = 8;
87 
88 	pv = exif_mem_alloc(mem, strlen + 1);
89 	if (!pv) {
90 		ret = -1;
91 		goto FINISH;
92 	}
93 	*(pv + strlen) = 0;
94 	memcpy(pv, v, strlen);
95 
96 	token = strtok(pv, " ");
97 	for (; token && components_size < buff_size;) {
98 		int offset = increment * components_local;
99 		char timestamp_buff[11] = {0};
100 		snprintf(timestamp_buff, sizeof(timestamp_buff), "%s", token);
101 		unsigned long numerator = strtoul(timestamp_buff, NULL, 10);
102 
103 		snprintf(timestamp_buff, 8, "%s", token+10);
104 		unsigned long denominator = strtoul(timestamp_buff, NULL, 10);
105 
106 		ExifRational r = {
107 			.numerator = numerator,
108 			.denominator = denominator,
109 		};
110 
111 		exif_set_rational((unsigned char*)buff + offset, order, r);
112 		components_local++;
113 		components_size = components_local * increment;
114 		token = strtok(NULL, " ");
115 	}
116 
117 FINISH:
118 	*components = components_local;
119 	if (!components_local)
120 		ret = -1;
121 	if (pv)
122 		exif_mem_free(mem, pv);
123 	return ret;
124 }
125 
126 int
mnote_huawei_entry_string_process(char * buff,const int buff_size,const char * v,int strlen,int * components)127 mnote_huawei_entry_string_process(char *buff, const int buff_size, const char *v, int strlen,
128 									  int *components)
129 {
130 	int ret = 0;
131 	*components = snprintf(buff, buff_size, _("%s"), v);
132 	if (!(*components))
133 		ret = -1;
134 	else {
135 		*components = *components + 1;
136 	}
137 	return ret;
138 }
139 
140 int
mnote_huawei_entry_value_process(char * buff,const int buff_size,const char * v,int strlen,const int increment,int * components,ExifMem * mem,ExifByteOrder order)141 mnote_huawei_entry_value_process(char *buff, const int buff_size, const char *v, int strlen,
142 									 const int increment, int *components, ExifMem *mem, ExifByteOrder order)
143 {
144 	char *token = NULL, *pv = NULL;
145 	int components_local = 0, components_size = 0, ret = 0;
146 
147 	pv = exif_mem_alloc(mem, strlen + 1);
148 	if (!pv) {
149 		ret = -1;
150 		goto FINISH;
151 	}
152 	*(pv + strlen) = 0;
153 	memcpy(pv, v, strlen);
154 
155 	token = strtok(pv, " ");
156 	for (; token && components_size < buff_size;) {
157 		int value = atoi(token);
158 		int offset = increment * components_local;
159 		if (increment == 1) {
160 			if (value > 0xff || value < 0) {
161 				ret = -1;
162 				goto FINISH;
163 			}
164 			*(buff + offset) = value;
165 		} else {
166 			exif_set_slong((unsigned char*)(buff + offset), order, value);
167 		}
168 		components_local++;
169 		components_size = components_local * increment;
170 		token = strtok(NULL, " ");
171 	}
172 
173 FINISH:
174 	*components = components_local;
175 	if (!components_local)
176 		ret = -1;
177 	if (pv)
178 		exif_mem_free(mem, pv);
179 	return ret;
180 }
181 
182 int
mnote_huawei_entry_set_value(MnoteHuaweiEntry * e,const char * v,int strlen)183 mnote_huawei_entry_set_value(MnoteHuaweiEntry *e, const char *v, int strlen)
184 {
185 	char data[1024] = {0};
186 	int increment = 0, components = 0, components_size = 0, ret = 0;
187 
188 	if (!e || !v || e->md) {
189 		ret = -1;
190 		goto FINISH;
191 	}
192 
193 	if (e->format == EXIF_FORMAT_UNDEFINED || e->format == EXIF_FORMAT_ASCII) {
194 		increment = 1;
195 	} else if (e->format == EXIF_FORMAT_SLONG || e->format == EXIF_FORMAT_LONG) {
196 		increment = 4;
197 	} else if (e->format == EXIF_FORMAT_RATIONAL || e->format == EXIF_FORMAT_SRATIONAL) {
198 		increment = 8;
199 	} else {
200 		ret = -1;
201 		goto FINISH;
202 	}
203 
204 	if (e->tag == MNOTE_MICRO_VIDEO_PRESENTATION_TIMESTAMP_US) {
205 		ret = mnote_huawei_entry_rational_timestamp_process(data, sizeof(data), v, strlen,
206 															&components, e->mem, e->order);
207 	} else if (e->format == EXIF_FORMAT_ASCII) {
208 		ret = mnote_huawei_entry_string_process(data, sizeof(data), v, strlen, &components);
209 	} else {
210 		ret = mnote_huawei_entry_value_process(data, sizeof(data), v, strlen, increment,
211 											   &components, e->mem, e->order);
212 	}
213 
214 	if (ret) {
215 		goto FINISH;
216 	}
217 
218 	components_size = increment * components;
219 	if (e->size < components_size) {
220 		unsigned char *realloc = exif_mem_realloc(e->mem, e->data, components_size);
221 		if (!realloc) {
222 			ret = -1;
223 			goto FINISH;
224 		}
225 		e->data = realloc;
226 		e->size = components_size;
227 	}
228 
229 	e->components = components;
230 	memcpy(e->data, data, components_size);
231 
232 FINISH:
233 	return ret;
234 }
235 
236 MnoteHuaweiEntry *
mnote_huawei_entry_new(ExifMnoteData * n)237 mnote_huawei_entry_new(ExifMnoteData *n)
238 {
239 	if (!is_huawei_md(n))
240 		return NULL;
241 	ExifMem *mem = n->mem;
242 	MnoteHuaweiEntry *e = exif_mem_alloc(mem, sizeof(MnoteHuaweiEntry));
243 	if (!e)
244 		return e;
245 	e->mem = mem;
246 	return e;
247 }
248 
249 void
mnote_huawei_entry_replace_mem(MnoteHuaweiEntry * e,ExifMem * mem)250 mnote_huawei_entry_replace_mem(MnoteHuaweiEntry *e, ExifMem *mem)
251 {
252 	if (!e || !mem)
253 		return;
254 	if (e->mem == mem)
255 		return;
256 	exif_mem_unref(e->mem);
257 	e->mem = mem;
258 	return;
259 }
260 
261 void
mnote_huawei_entry_free_content(MnoteHuaweiEntry * e)262 mnote_huawei_entry_free_content(MnoteHuaweiEntry *e)
263 {
264 	if (!e)
265 		return;
266 	if (e->data)
267 		exif_mem_free(e->mem, e->data);
268 	if (e->md)
269 		exif_mnote_data_huawei_clear((ExifMnoteDataHuawei*) e->md);
270 }
271 
272 void
mnote_huawei_entry_free_contour(MnoteHuaweiEntry * e)273 mnote_huawei_entry_free_contour(MnoteHuaweiEntry *e)
274 {
275 	if (!e)
276 		return;
277 	exif_mem_free(e->mem, e);
278 }
279 
280 void
mnote_huawei_entry_free(MnoteHuaweiEntry * e)281 mnote_huawei_entry_free(MnoteHuaweiEntry *e)
282 {
283 	if (!e)
284 		return;
285 	mnote_huawei_entry_free_content(e);
286 	exif_mem_free(e->mem, e);
287 }
288 
289 static void *
mnote_huawei_entry_alloc(MnoteHuaweiEntry * e,unsigned int i)290 mnote_huawei_entry_alloc (MnoteHuaweiEntry *e, unsigned int i)
291 {
292 	if (!e || !i) return NULL;
293 	void *p = exif_mem_alloc (e->mem, i);
294 	if (p) memset(p, 0, i);
295 	return p;
296 }
297 
298 static void
clear_mnote_huawei_entry(MnoteHuaweiEntry * e)299 clear_mnote_huawei_entry (MnoteHuaweiEntry *e)
300 {
301 	e->components = 0;
302 	e->size = 0;
303 }
304 
305 void
mnote_huawei_entry_initialize(MnoteHuaweiEntry * e,MnoteHuaweiTag tag,ExifByteOrder order)306 mnote_huawei_entry_initialize(MnoteHuaweiEntry *e, MnoteHuaweiTag tag, ExifByteOrder order)
307 {
308 	if (!e || e->data)
309 		return;
310 	e->tag = tag;
311 	e->order = order;
312 	switch (tag) {
313 		case MNOTE_HUAWEI_SCENE_INFO:
314 		case MNOTE_HUAWEI_FACE_INFO:
315 		case MNOTE_HUAWEI_CAPTURE_MODE:
316 		case MNOTE_HUAWEI_BURST_NUMBER:
317 		case MNOTE_HUAWEI_FRONT_CAMERA:
318 		case MNOTE_HUAWEI_PHYSICAL_APERTURE:
319 		case MNOTE_MOVING_PHOTO_VERSION:
320 		case MNOTE_HUAWEI_FACE_VERSION:
321 		case MNOTE_HUAWEI_FACE_COUNT:
322 		case MNOTE_HUAWEI_FACE_CONF:
323 		case MNOTE_HUAWEI_SCENE_VERSION:
324 		case MNOTE_HUAWEI_SCENE_FOOD_CONF:
325 		case MNOTE_HUAWEI_SCENE_STAGE_CONF:
326 		case MNOTE_HUAWEI_SCENE_BLUESKY_CONF:
327 		case MNOTE_HUAWEI_SCENE_GREENPLANT_CONF:
328 		case MNOTE_HUAWEI_SCENE_BEACH_CONF:
329 		case MNOTE_HUAWEI_SCENE_SNOW_CONF:
330 		case MNOTE_HUAWEI_SCENE_SUNSET_CONF:
331 		case MNOTE_HUAWEI_SCENE_FLOWERS_CONF:
332 		case MNOTE_HUAWEI_SCENE_NIGHT_CONF:
333 		case MNOTE_HUAWEI_SCENE_TEXT_CONF:
334 			e->components = 1;
335 			e->format = EXIF_FORMAT_LONG;
336 			e->size = e->components * exif_format_get_size(e->format);
337 			e->data = mnote_huawei_entry_alloc(e, e->size);
338 			if (!e->data) { clear_mnote_huawei_entry(e); break; }
339 			break;
340 		case MNOTE_HUAWEI_ROLL_ANGLE:
341 		case MNOTE_HUAWEI_PITCH_ANGLE:
342 		case MNOTE_HUAWEI_FOCUS_MODE:
343 			e->components = 1;
344 			e->format = EXIF_FORMAT_SLONG;
345 			e->size = e->components * exif_format_get_size(e->format);
346 			e->data = mnote_huawei_entry_alloc(e, e->size);
347 			if (!e->data) { clear_mnote_huawei_entry(e); break; }
348 			break;
349 
350 		case MNOTE_MOVING_PHOTO_ID:
351 			e->components = sizeof("[None]");
352 			e->format = EXIF_FORMAT_ASCII;
353 			e->size = e->components * exif_format_get_size(e->format);
354 			e->data = mnote_huawei_entry_alloc(e, e->size);
355 			if (!e->data) { clear_mnote_huawei_entry(e); break; }
356 			snprintf((char*)e->data, e->size, "%s", "[None]");
357 			break;
358 
359 		case MNOTE_MICRO_VIDEO_PRESENTATION_TIMESTAMP_US:
360 			e->components = 8;
361 			e->format = EXIF_FORMAT_RATIONAL;
362 			e->size = e->components * exif_format_get_size(e->format);
363 			e->data = mnote_huawei_entry_alloc(e, e->size);
364 			if (!e->data) { clear_mnote_huawei_entry(e); break; }
365 			memset(e->data, 0, e->size);
366 			break;
367 
368 		case MNOTE_HUAWEI_FACE_SMILE_SCORE:
369 		case MNOTE_HUAWEI_FACE_RECT:
370 		case MNOTE_HUAWEI_FACE_LEYE_CENTER:
371 		case MNOTE_HUAWEI_FACE_REYE_CENTER:
372 		case MNOTE_HUAWEI_FACE_MOUTH_CENTER:
373 			e->components = 1;
374 			e->format = EXIF_FORMAT_UNDEFINED;
375 			e->size = e->components * exif_format_get_size(e->format);
376 			e->data = mnote_huawei_entry_alloc(e, e->size);
377 			if (!e->data) { clear_mnote_huawei_entry(e); break; }
378 			break;
379 
380 		default:
381 			e->components = 0;
382 			e->format = EXIF_FORMAT_UNDEFINED;
383 			e->size = 0;
384 			e->data = NULL;
385 			break;
386 	}
387 }