/*! 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); } }
static void exif_data_save_data_entry (ExifData *data, ExifEntry *e, unsigned char **d, unsigned int *ds, unsigned int offset) { unsigned int doff, s; unsigned int ts; if (!data || !data->priv) return; /* * Each entry is 12 bytes long. The memory for the entry has * already been allocated. */ exif_set_short (*d + 6 + offset + 0, data->priv->order, (ExifShort) e->tag); exif_set_short (*d + 6 + offset + 2, data->priv->order, (ExifShort) e->format); if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) { /* If this is the maker note tag, update it. */ if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) { /* TODO: this is using the wrong ExifMem to free e->data */ exif_mem_free (data->priv->mem, e->data); e->data = NULL; e->size = 0; exif_mnote_data_set_offset (data->priv->md, *ds - 6); exif_mnote_data_save (data->priv->md, &e->data, &e->size); e->components = e->size; } } exif_set_long (*d + 6 + offset + 4, data->priv->order, e->components); /* * Size? If bigger than 4 bytes, the actual data is not in * the entry but somewhere else. */ s = exif_format_get_size (e->format) * e->components; if (s > 4) { unsigned char *t; doff = *ds - 6; ts = *ds + s; /* * According to the TIFF specification, * the offset must be an even number. If we need to introduce * a padding byte, we set it to 0. */ if (s & 1) ts++; t = exif_mem_realloc (data->priv->mem, *d, ts); if (!t) { EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); return; } *d = t; *ds = ts; exif_set_long (*d + 6 + offset + 8, data->priv->order, doff); if (s & 1) *(*d + *ds - 1) = '\0'; } else doff = offset + 8; /* Write the data. Fill unneeded bytes with 0. Do not crash with * e->data is NULL */ if (e->data) { memcpy (*d + 6 + doff, e->data, s); } else { memset (*d + 6 + doff, 0, s); } if (s < 4) memset (*d + 6 + doff + s, 0, (4 - s)); }
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); }