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