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