Home | History | Annotate | Download | only in libexif
      1 /* exif-loader.c
      2  *
      3  * Copyright (c) 2002 Lutz Mueller <lutz (at) 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 *
     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
    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
    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
    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 *
    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 *
    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
    347 exif_loader_ref (ExifLoader *loader)
    348 {
    349 	if (loader)
    350 		loader->ref_count++;
    351 }
    352 
    353 static void
    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
    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
    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 *
    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
    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
    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