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