/src/libexif/libexif/exif-loader.c
Line | Count | Source |
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 | | * SPDX-License-Identifier: LGPL-2.0-or-later |
21 | | */ |
22 | | |
23 | | #include <config.h> |
24 | | |
25 | | #include <libexif/exif-loader.h> |
26 | | #include <libexif/exif-utils.h> |
27 | | #include <libexif/i18n.h> |
28 | | |
29 | | #include <sys/types.h> |
30 | | #include <stdlib.h> |
31 | | #include <string.h> |
32 | | #include <stdio.h> |
33 | | |
34 | | #undef JPEG_MARKER_DCT |
35 | 319 | #define JPEG_MARKER_DCT 0xc0 |
36 | | #undef JPEG_MARKER_DHT |
37 | 517 | #define JPEG_MARKER_DHT 0xc4 |
38 | | #undef JPEG_MARKER_SOI |
39 | 832k | #define JPEG_MARKER_SOI 0xd8 |
40 | | #undef JPEG_MARKER_DQT |
41 | 727 | #define JPEG_MARKER_DQT 0xdb |
42 | | #undef JPEG_MARKER_APP0 |
43 | 1.87k | #define JPEG_MARKER_APP0 0xe0 |
44 | | #undef JPEG_MARKER_APP1 |
45 | 1.62k | #define JPEG_MARKER_APP1 0xe1 |
46 | | #undef JPEG_MARKER_APP2 |
47 | 2.56k | #define JPEG_MARKER_APP2 0xe2 |
48 | | #undef JPEG_MARKER_APP4 |
49 | 2.96k | #define JPEG_MARKER_APP4 0xe4 |
50 | | #undef JPEG_MARKER_APP5 |
51 | 3.22k | #define JPEG_MARKER_APP5 0xe5 |
52 | | #undef JPEG_MARKER_APP10 |
53 | 3.76k | #define JPEG_MARKER_APP10 0xea |
54 | | #undef JPEG_MARKER_APP11 |
55 | 4.16k | #define JPEG_MARKER_APP11 0xeb |
56 | | #undef JPEG_MARKER_APP13 |
57 | 4.38k | #define JPEG_MARKER_APP13 0xed |
58 | | #undef JPEG_MARKER_APP14 |
59 | 4.65k | #define JPEG_MARKER_APP14 0xee |
60 | | #undef JPEG_MARKER_COM |
61 | 4.92k | #define JPEG_MARKER_COM 0xfe |
62 | | |
63 | | typedef enum { |
64 | | EL_READ = 0, |
65 | | EL_READ_SIZE_BYTE_24, |
66 | | EL_READ_SIZE_BYTE_16, |
67 | | EL_READ_SIZE_BYTE_08, |
68 | | EL_READ_SIZE_BYTE_00, |
69 | | EL_SKIP_BYTES, |
70 | | EL_EXIF_FOUND |
71 | | } ExifLoaderState; |
72 | | |
73 | | typedef enum { |
74 | | EL_DATA_FORMAT_UNKNOWN, |
75 | | EL_DATA_FORMAT_EXIF, |
76 | | EL_DATA_FORMAT_JPEG, |
77 | | EL_DATA_FORMAT_FUJI_RAW |
78 | | } ExifLoaderDataFormat; |
79 | | |
80 | | /*! \internal */ |
81 | | struct _ExifLoader { |
82 | | ExifLoaderState state; |
83 | | ExifLoaderDataFormat data_format; |
84 | | |
85 | | /*! Small buffer used for detection of format */ |
86 | | unsigned char b[12]; |
87 | | |
88 | | /*! Number of bytes in the small buffer \c b */ |
89 | | unsigned char b_len; |
90 | | |
91 | | unsigned int size; |
92 | | unsigned char *buf; |
93 | | unsigned int bytes_read; |
94 | | |
95 | | unsigned int ref_count; |
96 | | |
97 | | ExifLog *log; |
98 | | ExifMem *mem; |
99 | | }; |
100 | | |
101 | | /*! Magic number for EXIF header */ |
102 | | static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; |
103 | | |
104 | | static void * |
105 | | exif_loader_alloc (ExifLoader *l, unsigned int i) |
106 | 10.9k | { |
107 | 10.9k | void *d; |
108 | | |
109 | 10.9k | if (!l || !i) |
110 | 0 | return NULL; |
111 | | |
112 | 10.9k | d = exif_mem_alloc (l->mem, i); |
113 | 10.9k | if (d) |
114 | 10.9k | return d; |
115 | | |
116 | 0 | EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i); |
117 | 0 | return NULL; |
118 | 10.9k | } |
119 | | |
120 | | void |
121 | | exif_loader_write_file (ExifLoader *l, const char *path) |
122 | 0 | { |
123 | 0 | FILE *f; |
124 | 0 | int size; |
125 | 0 | unsigned char data[1024]; |
126 | |
|
127 | 0 | if (!l || !path) |
128 | 0 | return; |
129 | | |
130 | 0 | f = fopen (path, "rb"); |
131 | 0 | if (!f) { |
132 | 0 | exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader", |
133 | 0 | _("The file '%s' could not be opened."), path); |
134 | 0 | return; |
135 | 0 | } |
136 | 0 | while (1) { |
137 | 0 | size = fread (data, 1, sizeof (data), f); |
138 | 0 | if (size <= 0) |
139 | 0 | break; |
140 | 0 | if (!exif_loader_write (l, data, size)) |
141 | 0 | break; |
142 | 0 | } |
143 | 0 | fclose (f); |
144 | 0 | } |
145 | | |
146 | | static unsigned int |
147 | | exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len) |
148 | 21.6k | { |
149 | 21.6k | if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) |
150 | 2 | return 0; |
151 | | |
152 | | /* If needed, allocate the buffer. */ |
153 | 21.6k | if (!eld->buf) |
154 | 10.9k | eld->buf = exif_loader_alloc (eld, eld->size); |
155 | 21.6k | if (!eld->buf) |
156 | 0 | return 0; |
157 | | |
158 | | /* Copy memory */ |
159 | 21.6k | len = MIN (len, eld->size - eld->bytes_read); |
160 | 21.6k | memcpy (eld->buf + eld->bytes_read, buf, len); |
161 | 21.6k | eld->bytes_read += len; |
162 | | |
163 | 21.6k | return (eld->bytes_read >= eld->size) ? 0 : 1; |
164 | 21.6k | } |
165 | | |
166 | | unsigned char |
167 | | exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len) |
168 | 11.2k | { |
169 | 11.2k | unsigned int i; |
170 | | |
171 | 82.4k | begin: |
172 | 82.4k | if (!eld || (len && !buf)) |
173 | 0 | return 0; |
174 | | |
175 | 82.4k | switch (eld->state) { |
176 | 187 | case EL_EXIF_FOUND: |
177 | 187 | return exif_loader_copy (eld, buf, len); |
178 | 997 | case EL_SKIP_BYTES: |
179 | 997 | if (eld->size > len) { |
180 | 179 | eld->size -= len; |
181 | 179 | return 1; |
182 | 179 | } |
183 | 818 | len -= eld->size; |
184 | 818 | buf += eld->size; |
185 | 818 | eld->size = 0; |
186 | 818 | eld->b_len = 0; |
187 | 818 | switch (eld->data_format) { |
188 | 66 | case EL_DATA_FORMAT_FUJI_RAW: |
189 | 66 | eld->state = EL_READ_SIZE_BYTE_24; |
190 | 66 | break; |
191 | 752 | default: |
192 | 752 | eld->state = EL_READ; |
193 | 752 | break; |
194 | 818 | } |
195 | 818 | break; |
196 | | |
197 | 80.8k | case EL_READ: |
198 | 81.3k | default: |
199 | 81.3k | break; |
200 | 82.4k | } |
201 | | |
202 | 82.1k | if (!len) |
203 | 49 | return 1; |
204 | 82.0k | exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader", |
205 | 82.0k | "Scanning %i byte(s) of data...", len); |
206 | | |
207 | | /* |
208 | | * First fill the small buffer. Only continue if the buffer |
209 | | * is filled. Note that EXIF data contains at least 12 bytes. |
210 | | */ |
211 | 82.0k | i = MIN (len, sizeof (eld->b) - eld->b_len); |
212 | 82.0k | if (i) { |
213 | 82.0k | memcpy (&eld->b[eld->b_len], buf, i); |
214 | 82.0k | eld->b_len += i; |
215 | 82.0k | if (eld->b_len < sizeof (eld->b)) |
216 | 23 | return 1; |
217 | 82.0k | buf += i; |
218 | 82.0k | len -= i; |
219 | 82.0k | } |
220 | | |
221 | 82.0k | switch (eld->data_format) { |
222 | 11.5k | case EL_DATA_FORMAT_UNKNOWN: |
223 | | |
224 | | /* Check the small buffer against known formats. */ |
225 | 11.5k | if (!memcmp (eld->b, "FUJIFILM", 8)) { |
226 | | |
227 | | /* Skip to byte 84. There is another offset there. */ |
228 | 67 | eld->data_format = EL_DATA_FORMAT_FUJI_RAW; |
229 | 67 | eld->size = 84; |
230 | 67 | eld->state = EL_SKIP_BYTES; |
231 | 67 | eld->size = 84; |
232 | | |
233 | 11.4k | } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) { |
234 | | |
235 | | /* Read the size (2 bytes). */ |
236 | 10.6k | eld->data_format = EL_DATA_FORMAT_EXIF; |
237 | 10.6k | eld->state = EL_READ_SIZE_BYTE_08; |
238 | 10.6k | } |
239 | 82.0k | default: |
240 | 82.0k | break; |
241 | 82.0k | } |
242 | | |
243 | 963k | for (i = 0; i < sizeof (eld->b); i++) { |
244 | 891k | switch (eld->state) { |
245 | 10.7k | case EL_EXIF_FOUND: |
246 | 10.7k | if (!exif_loader_copy (eld, eld->b + i, |
247 | 10.7k | sizeof (eld->b) - i)) |
248 | 7 | return 0; |
249 | 10.7k | return exif_loader_copy (eld, buf, len); |
250 | 7.42k | case EL_SKIP_BYTES: |
251 | 7.42k | switch (eld->size) { |
252 | 4.20k | case 0: |
253 | 4.20k | eld->state = EL_READ; |
254 | 4.20k | i--; /* reprocess this byte */ |
255 | 4.20k | break; |
256 | 1.13k | case 1: |
257 | 1.13k | eld->size = 0; |
258 | 1.13k | eld->state = EL_READ; |
259 | 1.13k | break; |
260 | 2.08k | default: |
261 | 2.08k | eld->size--; |
262 | 2.08k | break; |
263 | 7.42k | } |
264 | 7.42k | break; |
265 | | |
266 | 7.42k | case EL_READ_SIZE_BYTE_24: |
267 | 65 | eld->size |= (unsigned int)eld->b[i] << 24; |
268 | 65 | eld->state = EL_READ_SIZE_BYTE_16; |
269 | 65 | break; |
270 | 65 | case EL_READ_SIZE_BYTE_16: |
271 | 65 | eld->size |= (unsigned int)eld->b[i] << 16; |
272 | 65 | eld->state = EL_READ_SIZE_BYTE_08; |
273 | 65 | break; |
274 | 17.2k | case EL_READ_SIZE_BYTE_08: |
275 | 17.2k | eld->size |= (unsigned int)eld->b[i] << 8; |
276 | 17.2k | eld->state = EL_READ_SIZE_BYTE_00; |
277 | 17.2k | break; |
278 | 17.1k | case EL_READ_SIZE_BYTE_00: |
279 | 17.1k | eld->size |= eld->b[i] << 0; |
280 | 17.1k | switch (eld->data_format) { |
281 | 6.20k | case EL_DATA_FORMAT_JPEG: |
282 | 6.20k | eld->state = EL_SKIP_BYTES; |
283 | 6.20k | if (eld->size < 2) { |
284 | | /* Actually it's malformed... */ |
285 | 2.63k | eld->size = 0; |
286 | 2.63k | } else |
287 | 3.56k | eld->size -= 2; |
288 | 6.20k | break; |
289 | 65 | case EL_DATA_FORMAT_FUJI_RAW: |
290 | 65 | eld->data_format = EL_DATA_FORMAT_EXIF; |
291 | 65 | eld->state = EL_SKIP_BYTES; |
292 | 65 | if (eld->size < 86) { |
293 | | /* Actually it's malformed... */ |
294 | 7 | eld->size = 0; |
295 | 7 | } else |
296 | 58 | eld->size -= 86; /* and put this in an else */ |
297 | 65 | break; |
298 | 10.9k | case EL_DATA_FORMAT_EXIF: |
299 | 10.9k | eld->state = EL_EXIF_FOUND; |
300 | 10.9k | break; |
301 | 0 | default: |
302 | 0 | break; |
303 | 17.1k | } |
304 | 17.1k | break; |
305 | | |
306 | 839k | default: |
307 | 839k | switch (eld->b[i]) { |
308 | 1.62k | case JPEG_MARKER_APP1: |
309 | 1.62k | if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) { |
310 | 321 | eld->data_format = EL_DATA_FORMAT_EXIF; |
311 | 1.30k | } else { |
312 | 1.30k | eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/ |
313 | 1.30k | } |
314 | 1.62k | eld->size = 0; |
315 | 1.62k | eld->state = EL_READ_SIZE_BYTE_08; |
316 | 1.62k | break; |
317 | 319 | case JPEG_MARKER_DCT: |
318 | 517 | case JPEG_MARKER_DHT: |
319 | 727 | case JPEG_MARKER_DQT: |
320 | 1.87k | case JPEG_MARKER_APP0: |
321 | 2.56k | case JPEG_MARKER_APP2: |
322 | 2.96k | case JPEG_MARKER_APP4: |
323 | 3.22k | case JPEG_MARKER_APP5: |
324 | 3.76k | case JPEG_MARKER_APP10: |
325 | 4.16k | case JPEG_MARKER_APP11: |
326 | 4.38k | case JPEG_MARKER_APP13: |
327 | 4.65k | case JPEG_MARKER_APP14: |
328 | 4.92k | case JPEG_MARKER_COM: |
329 | 4.92k | eld->data_format = EL_DATA_FORMAT_JPEG; |
330 | 4.92k | eld->size = 0; |
331 | 4.92k | eld->state = EL_READ_SIZE_BYTE_08; |
332 | 4.92k | break; |
333 | 832k | case 0xff: |
334 | 832k | case JPEG_MARKER_SOI: |
335 | 832k | break; |
336 | 93 | default: |
337 | 93 | exif_log (eld->log, |
338 | 93 | EXIF_LOG_CODE_CORRUPT_DATA, |
339 | 93 | "ExifLoader", _("The data supplied " |
340 | 93 | "does not seem to contain " |
341 | 93 | "EXIF data.")); |
342 | 93 | exif_loader_reset (eld); |
343 | 93 | return 0; |
344 | 839k | } |
345 | 891k | } |
346 | 891k | } |
347 | | |
348 | | /* |
349 | | * If we reach this point, the buffer has not been big enough |
350 | | * to read all data we need. Fill it with new data. |
351 | | */ |
352 | 71.2k | eld->b_len = 0; |
353 | 71.2k | goto begin; |
354 | 82.0k | } |
355 | | |
356 | | ExifLoader * |
357 | | exif_loader_new (void) |
358 | 11.2k | { |
359 | 11.2k | ExifMem *mem = exif_mem_new_default (); |
360 | 11.2k | ExifLoader *l = exif_loader_new_mem (mem); |
361 | | |
362 | 11.2k | exif_mem_unref (mem); |
363 | | |
364 | 11.2k | return l; |
365 | 11.2k | } |
366 | | |
367 | | ExifLoader * |
368 | | exif_loader_new_mem (ExifMem *mem) |
369 | 11.2k | { |
370 | 11.2k | ExifLoader *loader; |
371 | | |
372 | 11.2k | if (!mem) |
373 | 0 | return NULL; |
374 | | |
375 | 11.2k | loader = exif_mem_alloc (mem, sizeof (ExifLoader)); |
376 | 11.2k | if (!loader) |
377 | 0 | return NULL; |
378 | 11.2k | loader->ref_count = 1; |
379 | | |
380 | 11.2k | loader->mem = mem; |
381 | 11.2k | exif_mem_ref (mem); |
382 | | |
383 | 11.2k | return loader; |
384 | 11.2k | } |
385 | | |
386 | | void |
387 | | exif_loader_ref (ExifLoader *loader) |
388 | 0 | { |
389 | 0 | if (loader) |
390 | 0 | loader->ref_count++; |
391 | 0 | } |
392 | | |
393 | | static void |
394 | | exif_loader_free (ExifLoader *loader) |
395 | 11.2k | { |
396 | 11.2k | ExifMem *mem; |
397 | | |
398 | 11.2k | if (!loader) |
399 | 0 | return; |
400 | | |
401 | 11.2k | mem = loader->mem; |
402 | 11.2k | exif_loader_reset (loader); |
403 | 11.2k | exif_log_unref (loader->log); |
404 | 11.2k | exif_mem_free (mem, loader); |
405 | 11.2k | exif_mem_unref (mem); |
406 | 11.2k | } |
407 | | |
408 | | void |
409 | | exif_loader_unref (ExifLoader *loader) |
410 | 11.2k | { |
411 | 11.2k | if (!loader) |
412 | 0 | return; |
413 | 11.2k | if (!--loader->ref_count) |
414 | 11.2k | exif_loader_free (loader); |
415 | 11.2k | } |
416 | | |
417 | | void |
418 | | exif_loader_reset (ExifLoader *loader) |
419 | 11.3k | { |
420 | 11.3k | if (!loader) |
421 | 0 | return; |
422 | 11.3k | exif_mem_free (loader->mem, loader->buf); loader->buf = NULL; |
423 | 11.3k | loader->size = 0; |
424 | 11.3k | loader->bytes_read = 0; |
425 | 11.3k | loader->state = 0; |
426 | 11.3k | loader->b_len = 0; |
427 | 11.3k | loader->data_format = EL_DATA_FORMAT_UNKNOWN; |
428 | 11.3k | } |
429 | | |
430 | | ExifData * |
431 | | exif_loader_get_data (ExifLoader *loader) |
432 | 11.2k | { |
433 | 11.2k | ExifData *ed; |
434 | | |
435 | 11.2k | if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) || |
436 | 11.1k | !loader->bytes_read) |
437 | 363 | return NULL; |
438 | | |
439 | 10.9k | ed = exif_data_new_mem (loader->mem); |
440 | 10.9k | exif_data_log (ed, loader->log); |
441 | 10.9k | exif_data_load_data (ed, loader->buf, loader->bytes_read); |
442 | | |
443 | 10.9k | return ed; |
444 | 11.2k | } |
445 | | |
446 | | void |
447 | | exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf, |
448 | | unsigned int *buf_size) |
449 | 0 | { |
450 | 0 | const unsigned char* b = NULL; |
451 | 0 | unsigned int s = 0; |
452 | |
|
453 | 0 | if (loader) { |
454 | 0 | if (loader->data_format == EL_DATA_FORMAT_UNKNOWN) { |
455 | 0 | exif_log (loader->log, EXIF_LOG_CODE_DEBUG, "ExifLoader", |
456 | 0 | "Loader format unknown"); |
457 | 0 | } else { |
458 | 0 | b = loader->buf; |
459 | 0 | s = loader->bytes_read; |
460 | 0 | } |
461 | 0 | } |
462 | |
|
463 | 0 | if (buf) |
464 | 0 | *buf = b; |
465 | 0 | if (buf_size) |
466 | 0 | *buf_size = s; |
467 | 0 | } |
468 | | |
469 | | void |
470 | | exif_loader_log (ExifLoader *loader, ExifLog *log) |
471 | 0 | { |
472 | 0 | if (!loader) |
473 | 0 | return; |
474 | 0 | exif_log_unref (loader->log); |
475 | 0 | loader->log = log; |
476 | 0 | exif_log_ref (log); |
477 | 0 | } |