/*! If MakerNote is recognized, load it. * * \param[in,out] data #ExifData * \param[in] d pointer to raw EXIF data * \param[in] ds length of data at d */ static void interpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds) { int mnoteid; ExifEntry* e = exif_data_get_entry (data, EXIF_TAG_MAKER_NOTE); if (!e) return; if ((mnoteid = exif_mnote_data_olympus_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Olympus MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_olympus_new (data->priv->mem); } else if ((mnoteid = exif_mnote_data_canon_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Canon MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options); } else if ((mnoteid = exif_mnote_data_fuji_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Fuji MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_fuji_new (data->priv->mem); /* NOTE: Must do Pentax detection last because some of the * heuristics are pretty general. */ } else if ((mnoteid = exif_mnote_data_pentax_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Pentax MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_pentax_new (data->priv->mem); } /* * If we are able to interpret the maker note, do so. */ if (data->priv->md) { exif_mnote_data_log (data->priv->md, data->priv->log); exif_mnote_data_set_byte_order (data->priv->md, data->priv->order); exif_mnote_data_set_offset (data->priv->md, data->priv->offset_mnote); exif_mnote_data_load (data->priv->md, d, ds); } }
void exif_data_load_data (ExifData *data, const unsigned char *d_orig, unsigned int ds_orig) { unsigned int l; ExifLong offset; ExifShort n; const unsigned char *d = d_orig; unsigned int ds = ds_orig, len; if (!data || !data->priv || !d || !ds) return; exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Parsing %i byte(s) EXIF data...\n", ds); /* * It can be that the data starts with the EXIF header. If it does * not, search the EXIF marker. */ if (ds < 6) { LOG_TOO_SMALL; return; } if (!memcmp (d, ExifHeader, 6)) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Found EXIF header."); } else { while (1) { while ((d[0] == 0xff) && ds) { d++; ds--; } /* JPEG_MARKER_SOI */ if (d[0] == JPEG_MARKER_SOI) { d++; ds--; continue; } /* JPEG_MARKER_APP0 */ if (d[0] == JPEG_MARKER_APP0) { d++; ds--; l = (d[0] << 8) | d[1]; if (l > ds) return; d += l; ds -= l; continue; } /* JPEG_MARKER_APP1 */ if (d[0] == JPEG_MARKER_APP1) break; /* Unknown marker or data. Give up. */ exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", _("EXIF marker not found.")); return; } d++; ds--; if (ds < 2) { LOG_TOO_SMALL; return; } len = (d[0] << 8) | d[1]; exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "We have to deal with %i byte(s) of EXIF data.", len); d += 2; ds -= 2; } /* * Verify the exif header * (offset 2, length 6). */ if (ds < 6) { LOG_TOO_SMALL; return; } if (memcmp (d, ExifHeader, 6)) { exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", _("EXIF header not found.")); return; } exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Found EXIF header."); /* Byte order (offset 6, length 2) */ if (ds < 14) return; if (!memcmp (d + 6, "II", 2)) data->priv->order = EXIF_BYTE_ORDER_INTEL; else if (!memcmp (d + 6, "MM", 2)) data->priv->order = EXIF_BYTE_ORDER_MOTOROLA; else { exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", _("Unknown encoding.")); return; } /* Fixed value */ if (exif_get_short (d + 8, data->priv->order) != 0x002a) return; /* IFD 0 offset */ offset = exif_get_long (d + 10, data->priv->order); exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "IFD 0 at %i.", (int) offset); /* Parse the actual exif data (usually offset 14 from start) */ exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0); /* IFD 1 offset */ if (offset + 6 + 2 > ds) { return; } n = exif_get_short (d + 6 + offset, data->priv->order); if (offset + 6 + 2 + 12 * n + 4 > ds) { return; } offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order); if (offset) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "IFD 1 at %i.", (int) offset); /* Sanity check. */ if (offset > ds - 6) { exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", "Bogus offset of IFD1."); } else { exif_data_load_data_content (data, EXIF_IFD_1, d + 6, ds - 6, offset, 0); } } /* * If we got an EXIF_TAG_MAKER_NOTE, try to interpret it. Some * cameras use pointers in the maker note tag that point to the * space between IFDs. Here is the only place where we have access * to that data. */ switch (exif_data_get_type_maker_note (data)) { case EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS: case EXIF_DATA_TYPE_MAKER_NOTE_NIKON: data->priv->md = exif_mnote_data_olympus_new (data->priv->mem); break; case EXIF_DATA_TYPE_MAKER_NOTE_PENTAX: case EXIF_DATA_TYPE_MAKER_NOTE_CASIO: data->priv->md = exif_mnote_data_pentax_new (data->priv->mem); break; case EXIF_DATA_TYPE_MAKER_NOTE_CANON: data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options); break; case EXIF_DATA_TYPE_MAKER_NOTE_FUJI: data->priv->md = exif_mnote_data_fuji_new (data->priv->mem); break; default: break; } /* * If we are able to interpret the maker note, do so. */ if (data->priv->md) { exif_mnote_data_log (data->priv->md, data->priv->log); exif_mnote_data_set_byte_order (data->priv->md, data->priv->order); exif_mnote_data_set_offset (data->priv->md, data->priv->offset_mnote); exif_mnote_data_load (data->priv->md, d, ds); } if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION) exif_data_fix (data); }