• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* exif-loader.c
2  *
3  * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA.
19  *
20  * SPDX-License-Identifier: LGPL-2.0-or-later
21  */
22 
23 #include <config.h>
24 
25 #include <libexif/exif-loader.h>
26 #include <libexif/exif-utils.h>
27 #include <libexif/i18n.h>
28 
29 #include <sys/types.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 
34 #undef JPEG_MARKER_DCT
35 #define JPEG_MARKER_DCT  0xc0
36 #undef JPEG_MARKER_DHT
37 #define JPEG_MARKER_DHT  0xc4
38 #undef JPEG_MARKER_SOI
39 #define JPEG_MARKER_SOI  0xd8
40 #undef JPEG_MARKER_DQT
41 #define JPEG_MARKER_DQT  0xdb
42 #undef JPEG_MARKER_APP0
43 #define JPEG_MARKER_APP0 0xe0
44 #undef JPEG_MARKER_APP1
45 #define JPEG_MARKER_APP1 0xe1
46 #undef JPEG_MARKER_APP2
47 #define JPEG_MARKER_APP2 0xe2
48 #undef JPEG_MARKER_APP4
49 #define JPEG_MARKER_APP4 0xe4
50 #undef JPEG_MARKER_APP5
51 #define JPEG_MARKER_APP5 0xe5
52 #undef JPEG_MARKER_APP10
53 #define JPEG_MARKER_APP10 0xea
54 #undef JPEG_MARKER_APP11
55 #define JPEG_MARKER_APP11 0xeb
56 #undef JPEG_MARKER_APP13
57 #define JPEG_MARKER_APP13 0xed
58 #undef JPEG_MARKER_APP14
59 #define JPEG_MARKER_APP14 0xee
60 #undef JPEG_MARKER_COM
61 #define JPEG_MARKER_COM 0xfe
62 
63 typedef enum {
64 	EL_READ = 0,
65 	EL_READ_SIZE_BYTE_24,
66 	EL_READ_SIZE_BYTE_16,
67 	EL_READ_SIZE_BYTE_08,
68 	EL_READ_SIZE_BYTE_00,
69 	EL_SKIP_BYTES,
70 	EL_EXIF_FOUND
71 } ExifLoaderState;
72 
73 typedef enum {
74 	EL_DATA_FORMAT_UNKNOWN,
75 	EL_DATA_FORMAT_EXIF,
76 	EL_DATA_FORMAT_JPEG,
77 	EL_DATA_FORMAT_FUJI_RAW
78 } ExifLoaderDataFormat;
79 
80 /*! \internal */
81 struct _ExifLoader {
82 	ExifLoaderState state;
83 	ExifLoaderDataFormat data_format;
84 
85 	/*! Small buffer used for detection of format */
86 	unsigned char b[12];
87 
88 	/*! Number of bytes in the small buffer \c b */
89 	unsigned char b_len;
90 
91 	unsigned int size;
92 	unsigned char *buf;
93 	unsigned int bytes_read;
94 
95 	unsigned int ref_count;
96 
97 	ExifLog *log;
98 	ExifMem *mem;
99 };
100 
101 /*! Magic number for EXIF header */
102 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
103 
104 static void *
exif_loader_alloc(ExifLoader * l,unsigned int i)105 exif_loader_alloc (ExifLoader *l, unsigned int i)
106 {
107 	void *d;
108 
109 	if (!l || !i)
110 		return NULL;
111 
112 	d = exif_mem_alloc (l->mem, i);
113 	if (d)
114 		return d;
115 
116 	EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
117 	return NULL;
118 }
119 
120 void
exif_loader_write_file(ExifLoader * l,const char * path)121 exif_loader_write_file (ExifLoader *l, const char *path)
122 {
123 	FILE *f;
124 	int size;
125 	unsigned char data[1024];
126 
127 	if (!l || !path)
128 		return;
129 
130 	f = fopen (path, "rb");
131 	if (!f) {
132 		exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader",
133 			  _("The file '%s' could not be opened."), path);
134 		return;
135 	}
136 	while (1) {
137 		size = fread (data, 1, sizeof (data), f);
138 		if (size <= 0)
139 			break;
140 		if (!exif_loader_write (l, data, size))
141 			break;
142 	}
143 	fclose (f);
144 }
145 
146 static unsigned int
exif_loader_copy(ExifLoader * eld,unsigned char * buf,unsigned int len)147 exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
148 {
149 	if (!eld || (len && !buf) || (eld->bytes_read >= eld->size))
150 		return 0;
151 
152 	/* If needed, allocate the buffer. */
153 	if (!eld->buf)
154 		eld->buf = exif_loader_alloc (eld, eld->size);
155 	if (!eld->buf)
156 		return 0;
157 
158 	/* Copy memory */
159 	len = MIN (len, eld->size - eld->bytes_read);
160 	memcpy (eld->buf + eld->bytes_read, buf, len);
161 	eld->bytes_read += len;
162 
163 	return (eld->bytes_read >= eld->size) ? 0 : 1;
164 }
165 
166 unsigned char
exif_loader_write(ExifLoader * eld,unsigned char * buf,unsigned int len)167 exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
168 {
169 	unsigned int i;
170 
171 begin:
172 	if (!eld || (len && !buf))
173 		return 0;
174 
175 	switch (eld->state) {
176 	case EL_EXIF_FOUND:
177 		return exif_loader_copy (eld, buf, len);
178 	case EL_SKIP_BYTES:
179 		if (eld->size > len) {
180 			eld->size -= len;
181 			return 1;
182 		}
183 		len -= eld->size;
184 		buf += eld->size;
185 		eld->size = 0;
186 		eld->b_len = 0;
187 		switch (eld->data_format) {
188 		case EL_DATA_FORMAT_FUJI_RAW:
189 			eld->state = EL_READ_SIZE_BYTE_24;
190 			break;
191 		default:
192 			eld->state = EL_READ;
193 			break;
194 		}
195 		break;
196 
197 	case EL_READ:
198 	default:
199 		break;
200 	}
201 
202 	if (!len)
203 		return 1;
204 	exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
205 		  "Scanning %i byte(s) of data...", len);
206 
207 	/*
208 	 * First fill the small buffer. Only continue if the buffer
209 	 * is filled. Note that EXIF data contains at least 12 bytes.
210 	 */
211 	i = MIN (len, sizeof (eld->b) - eld->b_len);
212 	if (i) {
213 		memcpy (&eld->b[eld->b_len], buf, i);
214 		eld->b_len += i;
215 		if (eld->b_len < sizeof (eld->b))
216 			return 1;
217 		buf += i;
218 		len -= i;
219 	}
220 
221 	switch (eld->data_format) {
222 	case EL_DATA_FORMAT_UNKNOWN:
223 
224 		/* Check the small buffer against known formats. */
225 		if (!memcmp (eld->b, "FUJIFILM", 8)) {
226 
227 			/* Skip to byte 84. There is another offset there. */
228 			eld->data_format = EL_DATA_FORMAT_FUJI_RAW;
229 			eld->size = 84;
230 			eld->state = EL_SKIP_BYTES;
231 			eld->size = 84;
232 
233 		} else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) {
234 
235 			/* Read the size (2 bytes). */
236 			eld->data_format = EL_DATA_FORMAT_EXIF;
237 			eld->state = EL_READ_SIZE_BYTE_08;
238 		}
239 	default:
240 		break;
241 	}
242 
243 	for (i = 0; i < sizeof (eld->b); i++) {
244 		switch (eld->state) {
245 		case EL_EXIF_FOUND:
246 			if (!exif_loader_copy (eld, eld->b + i,
247 					sizeof (eld->b) - i))
248 				return 0;
249 			return exif_loader_copy (eld, buf, len);
250 		case EL_SKIP_BYTES:
251 			switch (eld->size) {
252                             case 0:
253 			        eld->state = EL_READ;
254 				i--;   /* reprocess this byte */
255 				break;
256                             case 1:
257                                 eld->size = 0;
258 			        eld->state = EL_READ;
259 				break;
260                             default:
261                                 eld->size--;
262 				break;
263 			}
264 			break;
265 
266 		case EL_READ_SIZE_BYTE_24:
267 			eld->size |= (unsigned int)eld->b[i] << 24;
268 			eld->state = EL_READ_SIZE_BYTE_16;
269 			break;
270 		case EL_READ_SIZE_BYTE_16:
271 			eld->size |= (unsigned int)eld->b[i] << 16;
272 			eld->state = EL_READ_SIZE_BYTE_08;
273 			break;
274 		case EL_READ_SIZE_BYTE_08:
275 			eld->size |= (unsigned int)eld->b[i] << 8;
276 			eld->state = EL_READ_SIZE_BYTE_00;
277 			break;
278 		case EL_READ_SIZE_BYTE_00:
279 			eld->size |= eld->b[i] << 0;
280 			switch (eld->data_format) {
281 			case EL_DATA_FORMAT_JPEG:
282 				eld->state = EL_SKIP_BYTES;
283 				if (eld->size < 2) {
284 				    /* Actually it's malformed... */
285 				    eld->size = 0;
286 				} else
287 				    eld->size -= 2;
288 				break;
289 			case EL_DATA_FORMAT_FUJI_RAW:
290 				eld->data_format = EL_DATA_FORMAT_EXIF;
291 				eld->state = EL_SKIP_BYTES;
292 				if (eld->size < 86) {
293 				    /* Actually it's malformed... */
294 				    eld->size = 0;
295 				} else
296 				    eld->size -= 86;	/* and put this in an else */
297 				break;
298 			case EL_DATA_FORMAT_EXIF:
299 				eld->state = EL_EXIF_FOUND;
300 				break;
301 			default:
302 				break;
303 			}
304 			break;
305 
306 		default:
307 			switch (eld->b[i]) {
308 			case JPEG_MARKER_APP1:
309 			  if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) {
310 					eld->data_format = EL_DATA_FORMAT_EXIF;
311 				} else {
312 					eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
313 				}
314 				eld->size = 0;
315 				eld->state = EL_READ_SIZE_BYTE_08;
316 				break;
317 			case JPEG_MARKER_DCT:
318 			case JPEG_MARKER_DHT:
319 			case JPEG_MARKER_DQT:
320 			case JPEG_MARKER_APP0:
321 			case JPEG_MARKER_APP2:
322 			case JPEG_MARKER_APP4:
323 			case JPEG_MARKER_APP5:
324 			case JPEG_MARKER_APP10:
325 			case JPEG_MARKER_APP11:
326 			case JPEG_MARKER_APP13:
327 			case JPEG_MARKER_APP14:
328 			case JPEG_MARKER_COM:
329 				eld->data_format = EL_DATA_FORMAT_JPEG;
330 				eld->size = 0;
331 				eld->state = EL_READ_SIZE_BYTE_08;
332 				break;
333 			case 0xff:
334 			case JPEG_MARKER_SOI:
335 				break;
336 			default:
337 				exif_log (eld->log,
338 					EXIF_LOG_CODE_CORRUPT_DATA,
339 					"ExifLoader", _("The data supplied "
340 						"does not seem to contain "
341 						"EXIF data."));
342 				exif_loader_reset (eld);
343 				return 0;
344 			}
345 		}
346 	}
347 
348 	/*
349 	 * If we reach this point, the buffer has not been big enough
350 	 * to read all data we need. Fill it with new data.
351 	 */
352 	eld->b_len = 0;
353 	goto begin;
354 }
355 
356 ExifLoader *
exif_loader_new(void)357 exif_loader_new (void)
358 {
359 	ExifMem *mem = exif_mem_new_default ();
360 	ExifLoader *l = exif_loader_new_mem (mem);
361 
362 	exif_mem_unref (mem);
363 
364 	return l;
365 }
366 
367 ExifLoader *
exif_loader_new_mem(ExifMem * mem)368 exif_loader_new_mem (ExifMem *mem)
369 {
370 	ExifLoader *loader;
371 
372 	if (!mem)
373 		return NULL;
374 
375 	loader = exif_mem_alloc (mem, sizeof (ExifLoader));
376 	if (!loader)
377 		return NULL;
378 	loader->ref_count = 1;
379 
380 	loader->mem = mem;
381 	exif_mem_ref (mem);
382 
383 	return loader;
384 }
385 
386 void
exif_loader_ref(ExifLoader * loader)387 exif_loader_ref (ExifLoader *loader)
388 {
389 	if (loader)
390 		loader->ref_count++;
391 }
392 
393 static void
exif_loader_free(ExifLoader * loader)394 exif_loader_free (ExifLoader *loader)
395 {
396 	ExifMem *mem;
397 
398 	if (!loader)
399 		return;
400 
401 	mem = loader->mem;
402 	exif_loader_reset (loader);
403 	exif_log_unref (loader->log);
404 	exif_mem_free (mem, loader);
405 	exif_mem_unref (mem);
406 }
407 
408 void
exif_loader_unref(ExifLoader * loader)409 exif_loader_unref (ExifLoader *loader)
410 {
411 	if (!loader)
412 		return;
413 	if (!--loader->ref_count)
414 		exif_loader_free (loader);
415 }
416 
417 void
exif_loader_reset(ExifLoader * loader)418 exif_loader_reset (ExifLoader *loader)
419 {
420 	if (!loader)
421 		return;
422 	exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
423 	loader->size = 0;
424 	loader->bytes_read = 0;
425 	loader->state = 0;
426 	loader->b_len = 0;
427 	loader->data_format = EL_DATA_FORMAT_UNKNOWN;
428 }
429 
430 ExifData *
exif_loader_get_data(ExifLoader * loader)431 exif_loader_get_data (ExifLoader *loader)
432 {
433 	ExifData *ed;
434 
435 	if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) ||
436 	    !loader->bytes_read)
437 		return NULL;
438 
439 	ed = exif_data_new_mem (loader->mem);
440 	exif_data_log (ed, loader->log);
441 	exif_data_load_data (ed, loader->buf, loader->bytes_read);
442 
443 	return ed;
444 }
445 
446 void
exif_loader_get_buf(ExifLoader * loader,const unsigned char ** buf,unsigned int * buf_size)447 exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf,
448 						  unsigned int *buf_size)
449 {
450 	const unsigned char* b = NULL;
451 	unsigned int s = 0;
452 
453 	if (loader) {
454 		if (loader->data_format == EL_DATA_FORMAT_UNKNOWN) {
455 			exif_log (loader->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
456 					  "Loader format unknown");
457 		} else {
458 			b = loader->buf;
459 			s = loader->bytes_read;
460 		}
461 	}
462 
463 	if (buf)
464 		*buf = b;
465 	if (buf_size)
466 		*buf_size = s;
467 }
468 
469 void
exif_loader_log(ExifLoader * loader,ExifLog * log)470 exif_loader_log (ExifLoader *loader, ExifLog *log)
471 {
472 	if (!loader)
473 		return;
474 	exif_log_unref (loader->log);
475 	loader->log = log;
476 	exif_log_ref (log);
477 }
478