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
49typedef 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
59typedef 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 */
67struct _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 */
88static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
89
90static void *
91exif_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
106void
107exif_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
132static unsigned int
133exif_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
152unsigned char
153exif_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
316ExifLoader *
317exif_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
327ExifLoader *
328exif_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
346void
347exif_loader_ref (ExifLoader *loader)
348{
349	if (loader)
350		loader->ref_count++;
351}
352
353static void
354exif_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
368void
369exif_loader_unref (ExifLoader *loader)
370{
371	if (!loader)
372		return;
373	if (!--loader->ref_count)
374		exif_loader_free (loader);
375}
376
377void
378exif_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
390ExifData *
391exif_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
406void
407exif_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
426void
427exif_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