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