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