static ExifEntry* allocateEntry(int tag, ExifFormat format, unsigned int numComponents) { ExifMem* mem = exif_mem_new_default(); ExifEntry* entry = exif_entry_new_mem(mem); unsigned int size = numComponents * exif_format_get_size(format); entry->data = reinterpret_cast<unsigned char*>(exif_mem_alloc(mem, size)); entry->size = size; entry->tag = static_cast<ExifTag>(tag); entry->components = numComponents; entry->format = format; exif_mem_unref(mem); return entry; }
ExifEntry *create_tag_in_content(ExifContent *content, ExifTag tag, size_t len, ExifFormat exifFormat) { void *buf; ExifEntry *entry; size_t size; /* Create a memory allocator to manage this ExifEntry */ ExifMem *mem = exif_mem_new_default(); if (!mem) return NULL; /* Create a new ExifEntry using our allocator */ entry = exif_entry_new_mem (mem); if (entry) { /* Allocate memory to use for holding the tag data */ size = len * exif_format_get_size(exifFormat); buf = exif_mem_alloc(mem, size); if (buf) { /* Fill in the entry */ entry->data = (unsigned char*)buf; entry->size = size; entry->tag = tag; entry->components = len; entry->format = exifFormat; /* Attach the ExifEntry to an IFD */ exif_content_add_entry (content, entry); } exif_entry_unref(entry); } exif_mem_unref(mem); return entry; }
/*! Load data for an IFD. * * \param[in,out] data #ExifData * \param[in] ifd IFD to load * \param[in] d pointer to buffer containing raw IFD data * \param[in] ds size of raw data in buffer at \c d * \param[in] offset offset into buffer at \c d at which IFD starts * \param[in] recursion_depth number of times this function has been * recursively called without returning */ static void exif_data_load_data_content (ExifData *data, ExifIfd ifd, const unsigned char *d, unsigned int ds, unsigned int offset, unsigned int recursion_depth) { ExifLong o, thumbnail_offset = 0, thumbnail_length = 0; ExifShort n; ExifEntry *entry; unsigned int i; ExifTag tag; if (!data || !data->priv) return; /* check for valid ExifIfd enum range */ if ((((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT)) return; if (recursion_depth > 30) { exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", "Deep recursion detected!"); return; } /* Read the number of entries */ if ((offset + 2 < offset) || (offset + 2 < 2) || (offset + 2 > ds)) { exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", "Tag data past end of buffer (%u > %u)", offset+2, ds); return; } n = exif_get_short (d + offset, data->priv->order); exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Loading %hu entries...", n); offset += 2; /* Check if we have enough data. */ if (offset + 12 * n > ds) { n = (ds - offset) / 12; exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Short data; only loading %hu entries...", n); } for (i = 0; i < n; i++) { tag = exif_get_short (d + offset + 12 * i, data->priv->order); switch (tag) { case EXIF_TAG_EXIF_IFD_POINTER: case EXIF_TAG_GPS_INFO_IFD_POINTER: case EXIF_TAG_INTEROPERABILITY_IFD_POINTER: case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: case EXIF_TAG_JPEG_INTERCHANGE_FORMAT: o = exif_get_long (d + offset + 12 * i + 8, data->priv->order); /* FIXME: IFD_POINTER tags aren't marked as being in a * specific IFD, so exif_tag_get_name_in_ifd won't work */ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Sub-IFD entry 0x%x ('%s') at %u.", tag, exif_tag_get_name(tag), o); switch (tag) { case EXIF_TAG_EXIF_IFD_POINTER: CHECK_REC (EXIF_IFD_EXIF); exif_data_load_data_content (data, EXIF_IFD_EXIF, d, ds, o, recursion_depth + 1); break; case EXIF_TAG_GPS_INFO_IFD_POINTER: CHECK_REC (EXIF_IFD_GPS); exif_data_load_data_content (data, EXIF_IFD_GPS, d, ds, o, recursion_depth + 1); break; case EXIF_TAG_INTEROPERABILITY_IFD_POINTER: CHECK_REC (EXIF_IFD_INTEROPERABILITY); exif_data_load_data_content (data, EXIF_IFD_INTEROPERABILITY, d, ds, o, recursion_depth + 1); break; case EXIF_TAG_JPEG_INTERCHANGE_FORMAT: thumbnail_offset = o; if (thumbnail_offset && thumbnail_length) exif_data_load_data_thumbnail (data, d, ds, thumbnail_offset, thumbnail_length); break; case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: thumbnail_length = o; if (thumbnail_offset && thumbnail_length) exif_data_load_data_thumbnail (data, d, ds, thumbnail_offset, thumbnail_length); break; default: return; } break; default: /* * If we don't know the tag, don't fail. It could be that new * versions of the standard have defined additional tags. Note that * 0 is a valid tag in the GPS IFD. */ if (!exif_tag_get_name_in_ifd (tag, ifd)) { /* * Special case: Tag and format 0. That's against specification * (at least up to 2.2). But Photoshop writes it anyways. */ if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Skipping empty entry at position %u in '%s'.", i, exif_ifd_get_name (ifd)); break; } exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Unknown tag 0x%04x (entry %u in '%s'). Please report this tag " "to <*****@*****.**>.", tag, i, exif_ifd_get_name (ifd)); if (data->priv->options & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS) break; } entry = exif_entry_new_mem (data->priv->mem); if (exif_data_load_data_entry (data, entry, d, ds, offset + 12 * i)) exif_content_add_entry (data->ifd[ifd], entry); exif_entry_unref (entry); break; } } }