• 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 			eld->size--;
237 			if (!eld->size)
238 				eld->state = EL_READ;
239 			break;
240 
241 		case EL_READ_SIZE_BYTE_24:
242 			eld->size |= eld->b[i] << 24;
243 			eld->state = EL_READ_SIZE_BYTE_16;
244 			break;
245 		case EL_READ_SIZE_BYTE_16:
246 			eld->size |= eld->b[i] << 16;
247 			eld->state = EL_READ_SIZE_BYTE_08;
248 			break;
249 		case EL_READ_SIZE_BYTE_08:
250 			eld->size |= eld->b[i] << 8;
251 			eld->state = EL_READ_SIZE_BYTE_00;
252 			break;
253 		case EL_READ_SIZE_BYTE_00:
254 			eld->size |= eld->b[i] << 0;
255 			switch (eld->data_format) {
256 			case EL_DATA_FORMAT_JPEG:
257 				eld->state = EL_SKIP_BYTES;
258 				eld->size -= 2;
259 				break;
260 			case EL_DATA_FORMAT_FUJI_RAW:
261 				eld->data_format = EL_DATA_FORMAT_EXIF;
262 				eld->state = EL_SKIP_BYTES;
263 				eld->size -= 86;
264 				break;
265 			case EL_DATA_FORMAT_EXIF:
266 				eld->state = EL_EXIF_FOUND;
267 				break;
268 			default:
269 				break;
270 			}
271 			break;
272 
273 		default:
274 			switch (eld->b[i]) {
275 			case JPEG_MARKER_APP1:
276 			  if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) {
277 					eld->data_format = EL_DATA_FORMAT_EXIF;
278 				} else {
279 					eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
280 				}
281 				eld->size = 0;
282 				eld->state = EL_READ_SIZE_BYTE_08;
283 				break;
284 			case JPEG_MARKER_DHT:
285 			case JPEG_MARKER_DQT:
286 			case JPEG_MARKER_APP0:
287 			case JPEG_MARKER_APP2:
288 			case JPEG_MARKER_APP13:
289 			case JPEG_MARKER_COM:
290 				eld->data_format = EL_DATA_FORMAT_JPEG;
291 				eld->size = 0;
292 				eld->state = EL_READ_SIZE_BYTE_08;
293 				break;
294 			case 0xff:
295 			case JPEG_MARKER_SOI:
296 				break;
297 			default:
298 				exif_log (eld->log,
299 					EXIF_LOG_CODE_CORRUPT_DATA,
300 					"ExifLoader", _("The data supplied "
301 						"does not seem to contain "
302 						"EXIF data."));
303 				exif_loader_reset (eld);
304 				return 0;
305 			}
306 		}
307 
308 	/*
309 	 * If we reach this point, the buffer has not been big enough
310 	 * to read all data we need. Fill it with new data.
311 	 */
312 	eld->b_len = 0;
313 	return exif_loader_write (eld, buf, len);
314 }
315 
316 ExifLoader *
exif_loader_new(void)317 exif_loader_new (void)
318 {
319 	ExifMem *mem = exif_mem_new_default ();
320 	ExifLoader *l = exif_loader_new_mem (mem);
321 
322 	exif_mem_unref (mem);
323 
324 	return l;
325 }
326 
327 ExifLoader *
exif_loader_new_mem(ExifMem * mem)328 exif_loader_new_mem (ExifMem *mem)
329 {
330 	ExifLoader *loader;
331 
332 	if (!mem)
333 		return NULL;
334 
335 	loader = exif_mem_alloc (mem, sizeof (ExifLoader));
336 	if (!loader)
337 		return NULL;
338 	loader->ref_count = 1;
339 
340 	loader->mem = mem;
341 	exif_mem_ref (mem);
342 
343 	return loader;
344 }
345 
346 void
exif_loader_ref(ExifLoader * loader)347 exif_loader_ref (ExifLoader *loader)
348 {
349 	if (loader)
350 		loader->ref_count++;
351 }
352 
353 static void
exif_loader_free(ExifLoader * loader)354 exif_loader_free (ExifLoader *loader)
355 {
356 	ExifMem *mem;
357 
358 	if (!loader)
359 		return;
360 
361 	mem = loader->mem;
362 	exif_loader_reset (loader);
363 	exif_log_unref (loader->log);
364 	exif_mem_free (mem, loader);
365 	exif_mem_unref (mem);
366 }
367 
368 void
exif_loader_unref(ExifLoader * loader)369 exif_loader_unref (ExifLoader *loader)
370 {
371 	if (!loader)
372 		return;
373 	if (!--loader->ref_count)
374 		exif_loader_free (loader);
375 }
376 
377 void
exif_loader_reset(ExifLoader * loader)378 exif_loader_reset (ExifLoader *loader)
379 {
380 	if (!loader)
381 		return;
382 	exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
383 	loader->size = 0;
384 	loader->bytes_read = 0;
385 	loader->state = 0;
386 	loader->b_len = 0;
387 	loader->data_format = EL_DATA_FORMAT_UNKNOWN;
388 }
389 
390 ExifData *
exif_loader_get_data(ExifLoader * loader)391 exif_loader_get_data (ExifLoader *loader)
392 {
393 	ExifData *ed;
394 
395 	if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) ||
396 	    !loader->bytes_read)
397 		return NULL;
398 
399 	ed = exif_data_new_mem (loader->mem);
400 	exif_data_log (ed, loader->log);
401 	exif_data_load_data (ed, loader->buf, loader->bytes_read);
402 
403 	return ed;
404 }
405 
406 void
exif_loader_get_buf(ExifLoader * loader,const unsigned char ** buf,unsigned int * buf_size)407 exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf,
408 						  unsigned int *buf_size)
409 {
410 	const unsigned char* b = NULL;
411 	unsigned int s = 0;
412 
413 	if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN)) {
414 		exif_log (loader->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
415 			  "Loader format unknown");
416 	} else {
417 		b = loader->buf;
418 		s = loader->bytes_read;
419 	}
420 	if (buf)
421 		*buf = b;
422 	if (buf_size)
423 		*buf_size = s;
424 }
425 
426 void
exif_loader_log(ExifLoader * loader,ExifLog * log)427 exif_loader_log (ExifLoader *loader, ExifLog *log)
428 {
429 	if (!loader)
430 		return;
431 	exif_log_unref (loader->log);
432 	loader->log = log;
433 	exif_log_ref (log);
434 }
435