1 /* exif-mnote-data-olympus.c
3 * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
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.
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.
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.
22 #include "exif-mnote-data-olympus.h"
28 #include <libexif/exif-utils.h>
29 #include <libexif/exif-data.h>
31 /* Uncomment this to fix a problem with Sanyo MakerNotes. It's probably best
32 * not to in most cases because it seems to only affect the thumbnail tag
33 * which is duplicated in IFD 1, and fixing the offset could actually cause
34 * problems with other software that expects the broken form.
36 /*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */
38 #define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
40 static enum OlympusVersion
41 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
42 unsigned int buf_size);
46 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
48 ExifMnoteData *d = (ExifMnoteData *) n;
54 for (i = 0; i < n->count; i++)
55 if (n->entries[i].data) {
56 exif_mem_free (d->mem, n->entries[i].data);
57 n->entries[i].data = NULL;
59 exif_mem_free (d->mem, n->entries);
66 exif_mnote_data_olympus_free (ExifMnoteData *n)
70 exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
74 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
76 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
78 if (!d || !val) return NULL;
79 if (i > n->count -1) return NULL;
81 exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
82 "Querying value for tag '%s'...",
83 mnote_olympus_tag_get_name (n->entries[i].tag));
85 return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
92 * @brief save the MnoteData from ne to buf
94 * @param ne extract the data from this structure
95 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
96 * @param buf_size the size of the buffer
99 exif_mnote_data_olympus_save (ExifMnoteData *ne,
100 unsigned char **buf, unsigned int *buf_size)
102 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
103 size_t i, o, s, doff, base = 0, o2 = 6 + 2;
108 if (!n || !buf || !buf_size) return;
111 * Allocate enough memory for all entries and the number of entries.
113 *buf_size = 6 + 2 + 2 + n->count * 12;
114 switch (n->version) {
118 *buf = exif_mem_alloc (ne->mem, *buf_size);
120 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
124 /* Write the header and the number of entries. */
125 strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
126 (n->version==epsonV1?"EPSON":"OLYMP"));
127 exif_set_short (*buf + 6, n->order, (ExifShort) 1);
132 *buf_size += 8-6 + 4;
133 *buf = exif_mem_alloc (ne->mem, *buf_size);
135 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
139 /* Write the header and the number of entries. */
140 strcpy ((char *)*buf, "OLYMPUS");
141 exif_set_short (*buf + 8, n->order, (ExifShort) (
142 (n->order == EXIF_BYTE_ORDER_INTEL) ?
145 exif_set_short (*buf + 10, n->order, (ExifShort) 3);
150 base = MNOTE_NIKON1_TAG_BASE;
152 /* v1 has offsets based to main IFD, not makernote IFD */
153 datao += n->offset + 10;
154 /* subtract the size here, so the increment in the next case will not harm us */
156 /* Fall through to nikonV2 handler */
158 /* Write out V0 files in V2 format */
161 *buf_size += 4; /* Next IFD pointer */
162 *buf = exif_mem_alloc (ne->mem, *buf_size);
164 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
168 /* Write the header and the number of entries. */
169 strcpy ((char *)*buf, "Nikon");
170 (*buf)[6] = n->version;
172 if (n->version != nikonV1) {
173 exif_set_short (*buf + 10, n->order, (ExifShort) (
174 (n->order == EXIF_BYTE_ORDER_INTEL) ?
177 exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
178 exif_set_long (*buf + 14, n->order, (ExifShort) 8);
182 /* Reset next IFD pointer */
183 exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
190 exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
193 /* Save each entry */
194 for (i = 0; i < n->count; i++) {
196 exif_set_short (*buf + o + 0, n->order,
197 (ExifShort) (n->entries[i].tag - base));
198 exif_set_short (*buf + o + 2, n->order,
199 (ExifShort) n->entries[i].format);
200 exif_set_long (*buf + o + 4, n->order,
201 n->entries[i].components);
203 s = exif_format_get_size (n->entries[i].format) *
204 n->entries[i].components;
206 /* Corrupt data: EXIF data size is limited to the
207 * maximum size of a JPEG segment (64 kb).
214 t = exif_mem_realloc (ne->mem, *buf,
217 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
222 exif_set_long (*buf + o, n->order, datao + doff);
226 /* Write the data. */
227 if (n->entries[i].data) {
228 memcpy (*buf + doff, n->entries[i].data, s);
230 /* Most certainly damaged input file */
231 memset (*buf + doff, 0, s);
237 exif_mnote_data_olympus_load (ExifMnoteData *en,
238 const unsigned char *buf, unsigned int buf_size)
240 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
242 size_t i, tcount, o, o2, datao = 6, base = 0;
244 if (!n || !buf || !buf_size) {
245 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
246 "ExifMnoteDataOlympus", "Short MakerNote");
249 o2 = 6 + n->offset; /* Start of interesting data */
250 if (CHECKOVERFLOW(o2,buf_size,10)) {
251 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
252 "ExifMnoteDataOlympus", "Short MakerNote");
257 * Olympus headers start with "OLYMP" and need to have at least
258 * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
259 * number of entries, and 12 for one entry.
261 * Sanyo format is identical and uses identical tags except that
262 * header starts with "SANYO".
264 * Epson format is identical and uses identical tags except that
265 * header starts with "EPSON".
267 * Nikon headers start with "Nikon" (6 bytes including '\0'),
268 * version number (1 or 2).
270 * Version 1 continues with 0, 1, 0, number_of_tags,
271 * or just with number_of_tags (models D1H, D1X...).
273 * Version 2 continues with an unknown byte (0 or 10),
274 * two unknown bytes (0), "MM" or "II", another byte 0 and
277 n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2);
278 switch (n->version) {
282 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
283 "Parsing Olympus/Sanyo/Epson maker note v1...");
285 /* The number of entries is at position 8. */
286 if (buf[o2 + 6] == 1)
287 n->order = EXIF_BYTE_ORDER_INTEL;
288 else if (buf[o2 + 6 + 1] == 1)
289 n->order = EXIF_BYTE_ORDER_MOTOROLA;
291 c = exif_get_short (buf + o2, n->order);
292 if ((!(c & 0xFF)) && (c > 0x500)) {
293 if (n->order == EXIF_BYTE_ORDER_INTEL) {
294 n->order = EXIF_BYTE_ORDER_MOTOROLA;
296 n->order = EXIF_BYTE_ORDER_INTEL;
302 /* Olympus S760, S770 */
305 if (CHECKOVERFLOW(o2,buf_size,4)) return;
306 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
307 "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
308 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
310 if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
311 n->order = EXIF_BYTE_ORDER_INTEL;
312 else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
313 n->order = EXIF_BYTE_ORDER_MOTOROLA;
315 /* The number of entries is at position 8+4. */
321 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
322 "Parsing Nikon maker note v1 (0x%02x, %02x, %02x, "
324 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
326 /* Skip version number */
329 /* Skip an unknown byte (00 or 0A). */
332 base = MNOTE_NIKON1_TAG_BASE;
333 /* Fix endianness, if needed */
334 c = exif_get_short (buf + o2, n->order);
335 if ((!(c & 0xFF)) && (c > 0x500)) {
336 if (n->order == EXIF_BYTE_ORDER_INTEL) {
337 n->order = EXIF_BYTE_ORDER_MOTOROLA;
339 n->order = EXIF_BYTE_ORDER_INTEL;
346 if (CHECKOVERFLOW(o2,buf_size,12)) return;
347 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
348 "Parsing Nikon maker note v2 (0x%02x, %02x, %02x, "
349 "%02x, %02x, %02x, %02x, %02x)...",
350 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
351 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
353 /* Skip version number */
356 /* Skip an unknown byte (00 or 0A). */
359 /* Skip 2 unknown bytes (00 00). */
363 * Byte order. From here the data offset
367 if (!strncmp ((char *)&buf[o2], "II", 2))
368 n->order = EXIF_BYTE_ORDER_INTEL;
369 else if (!strncmp ((char *)&buf[o2], "MM", 2))
370 n->order = EXIF_BYTE_ORDER_MOTOROLA;
372 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
373 "ExifMnoteDataOlympus", "Unknown "
374 "byte order '%c%c'", buf[o2],
380 /* Skip 2 unknown bytes (00 2A). */
383 /* Go to where the number of entries is. */
384 o2 = datao + exif_get_long (buf + o2, n->order);
388 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
389 "Parsing Nikon maker note v0 (0x%02x, %02x, %02x, "
390 "%02x, %02x, %02x, %02x, %02x)...",
391 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
392 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
393 /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
394 n->order = EXIF_BYTE_ORDER_MOTOROLA;
398 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
399 "Unknown Olympus variant %i.", n->version);
403 /* Sanity check the offset */
404 if (CHECKOVERFLOW(o2,buf_size,2)) {
405 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
406 "ExifMnoteOlympus", "Short MakerNote");
410 /* Read the number of tags */
411 c = exif_get_short (buf + o2, n->order);
414 /* Remove any old entries */
415 exif_mnote_data_olympus_clear (n);
417 /* Reserve enough space for all the possible MakerNote tags */
418 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
420 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
424 /* Parse all c entries, storing ones that are successfully parsed */
426 for (i = c, o = o2; i; --i, o += 12) {
428 if (CHECKOVERFLOW(o, buf_size, 12)) {
429 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
430 "ExifMnoteOlympus", "Short MakerNote");
434 n->entries[tcount].tag = exif_get_short (buf + o, n->order) + base;
435 n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
436 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
437 n->entries[tcount].order = n->order;
439 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
440 "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
441 mnote_olympus_tag_get_name (n->entries[tcount].tag));
442 /* exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
444 n->entries[tcount].tag,
445 n->entries[tcount].format,
446 n->entries[tcount].components,
447 (int)exif_format_get_size(n->entries[tcount].format)); */
449 /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
450 * we will check the buffer sizes closer later. */
451 if (exif_format_get_size (n->entries[tcount].format) &&
452 buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
454 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
458 * Size? If bigger than 4 bytes, the actual data is not
459 * in the entry but somewhere else (offset).
461 s = exif_format_get_size (n->entries[tcount].format) *
462 n->entries[tcount].components;
463 n->entries[tcount].size = s;
465 size_t dataofs = o + 8;
467 /* The data in this case is merely a pointer */
468 dataofs = exif_get_long (buf + dataofs, n->order) + datao;
469 #ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
470 /* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
471 * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
472 * tag in its MakerNote. The offset is actually the absolute
473 * position in the file instead of the position within the IFD.
475 if (dataofs > (buf_size - s) && n->version == sanyoV1) {
477 dataofs -= datao + 6;
478 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
480 "Inconsistent thumbnail tag offset; attempting to recover");
484 if (CHECKOVERFLOW(dataofs, buf_size, s)) {
485 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
487 "Tag data past end of buffer (%u > %u)",
488 (unsigned)(dataofs + s), buf_size);
492 n->entries[tcount].data = exif_mem_alloc (en->mem, s);
493 if (!n->entries[tcount].data) {
494 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
497 memcpy (n->entries[tcount].data, buf + dataofs, s);
500 /* Tag was successfully parsed */
503 /* Store the count of successfully parsed tags */
508 exif_mnote_data_olympus_count (ExifMnoteData *n)
510 return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
514 exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
516 ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
519 if (note->count <= n) return 0;
520 return note->entries[n].tag;
524 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
526 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
529 if (i >= n->count) return NULL;
530 return mnote_olympus_tag_get_name (n->entries[i].tag);
534 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
536 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
539 if (i >= n->count) return NULL;
540 return mnote_olympus_tag_get_title (n->entries[i].tag);
544 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
546 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
549 if (i >= n->count) return NULL;
550 return mnote_olympus_tag_get_description (n->entries[i].tag);
554 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
556 ExifByteOrder o_orig;
557 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
564 for (i = 0; i < n->count; i++) {
565 if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
567 n->entries[i].order = o;
568 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
569 n->entries[i].components, o_orig, o);
574 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
576 if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
579 static enum OlympusVersion
580 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
581 unsigned int buf_size)
583 /* Olympus, Nikon, Sanyo, Epson */
585 /* Match the terminating NUL character, too */
586 if (!memcmp (buf, "OLYMPUS", 8))
588 else if (!memcmp (buf, "OLYMP", 6))
590 else if (!memcmp (buf, "SANYO", 6))
592 else if (!memcmp (buf, "EPSON", 6))
594 else if (!memcmp (buf, "Nikon", 6)) {
596 case 1: return nikonV1;
597 case 2: return nikonV2;
598 default: return 0; /* Unrecognized Nikon variant */
603 /* Another variant of Nikon */
604 if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) {
612 exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e)
614 int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size);
616 if (variant == nikonV0) {
617 /* This variant needs some extra checking with the Make */
619 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
620 variant = unrecognized;
623 const char *v = exif_entry_get_value (em, value, sizeof(value));
624 if (v && (!strncmp (v, "Nikon", sizeof(value)) ||
625 !strncmp (v, "NIKON", sizeof(value)) ))
626 /* When saved, this variant will be written out like the
627 * alternative nikonV2 form above instead
638 exif_mnote_data_olympus_new (ExifMem *mem)
642 if (!mem) return NULL;
644 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
647 exif_mnote_data_construct (d, mem);
649 /* Set up function pointers */
650 d->methods.free = exif_mnote_data_olympus_free;
651 d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order;
652 d->methods.set_offset = exif_mnote_data_olympus_set_offset;
653 d->methods.load = exif_mnote_data_olympus_load;
654 d->methods.save = exif_mnote_data_olympus_save;
655 d->methods.count = exif_mnote_data_olympus_count;
656 d->methods.get_id = exif_mnote_data_olympus_get_id;
657 d->methods.get_name = exif_mnote_data_olympus_get_name;
658 d->methods.get_title = exif_mnote_data_olympus_get_title;
659 d->methods.get_description = exif_mnote_data_olympus_get_description;
660 d->methods.get_value = exif_mnote_data_olympus_get_value;