1548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/* exif-mnote-data-fuji.c 2548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 3548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net> 4548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 5548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * This library is free software; you can redistribute it and/or 6548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * modify it under the terms of the GNU Lesser General Public 7548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * License as published by the Free Software Foundation; either 8548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * version 2 of the License, or (at your option) any later version. 9548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 10548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * This library is distributed in the hope that it will be useful, 11548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * but WITHOUT ANY WARRANTY; without even the implied warranty of 12548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Lesser General Public License for more details. 14548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 15548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * You should have received a copy of the GNU Lesser General Public 16548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * License along with this library; if not, write to the 17548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Boston, MA 02110-1301 USA. 19548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 20548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 21548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <stdlib.h> 22548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <string.h> 23548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 24548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 25548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <config.h> 26548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-byte-order.h> 27548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-utils.h> 28548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 29548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include "exif-mnote-data-fuji.h" 30548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 31548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstruct _MNoteFujiDataPrivate { 32548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifByteOrder order; 33548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen}; 34548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 35548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 36548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_clear (ExifMnoteDataFuji *n) 37548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 38548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteData *d = (ExifMnoteData *) n; 39548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 40548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 41548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return; 42548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 43548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (n->entries) { 44548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < n->count; i++) 45548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (n->entries[i].data) { 46548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (d->mem, n->entries[i].data); 47548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].data = NULL; 48548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 49548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (d->mem, n->entries); 50548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries = NULL; 51548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->count = 0; 52548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 53548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 54548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 55548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 56548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_free (ExifMnoteData *n) 57548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 58548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return; 59548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 60548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_fuji_clear ((ExifMnoteDataFuji *) n); 61548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 62548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 63548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic char * 64548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen) 65548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 66548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; 67548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 68548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!d || !val) return NULL; 69548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (i > n->count -1) return NULL; 70548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/* 71548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji", 72548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Querying value for tag '%s'...", 73548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen mnote_fuji_tag_get_name (n->entries[i].tag)); 74548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen*/ 75548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_fuji_entry_get_value (&n->entries[i], val, maxlen); 76548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 77548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 78548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 79548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf, 80548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int *buf_size) 81548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 82548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne; 83548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t i, o, s, doff; 84548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned char *t; 85548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t ts; 86548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 87548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n || !buf || !buf_size) return; 88548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 89548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 90548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Allocate enough memory for all entries and the number 91548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * of entries. 92548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 93548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf_size = 8 + 4 + 2 + n->count * 12 + 4; 94548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf = exif_mem_alloc (ne->mem, *buf_size); 95548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!*buf) { 96548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf_size = 0; 97548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 98548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 99548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 100548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 101548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Header: "FUJIFILM" and 4 bytes offset to the first entry. 102548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * As the first entry will start right thereafter, the offset is 12. 103548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 104548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (*buf, "FUJIFILM", 8); 105548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*buf + 8, n->order, 12); 106548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 107548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Save the number of entries */ 108548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count); 109548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 110548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Save each entry */ 111548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < n->count; i++) { 112548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o = 8 + 4 + 2 + i * 12; 113548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag); 114548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); 115548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*buf + o + 4, n->order, n->entries[i].components); 116548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o += 8; 117548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen s = exif_format_get_size (n->entries[i].format) * 118548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].components; 119548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 65536) { 120548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Corrupt data: EXIF data size is limited to the 121548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * maximum size of a JPEG segment (64 kb). 122548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 123548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 124548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 125548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 4) { 126548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ts = *buf_size + s; 127548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 128548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Ensure even offsets. Set padding bytes to 0. */ 129548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s & 1) ts += 1; 130548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen t = exif_mem_realloc (ne->mem, *buf, ts); 131548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!t) { 132548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 133548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 134548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf = t; 135548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf_size = ts; 136548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = *buf_size - s; 137548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; } 138548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*buf + o, n->order, doff); 139548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else 140548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = o; 141548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 142548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 143548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Write the data. Fill unneeded bytes with 0. Do not 144548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * crash if data is NULL. 145548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 146548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n->entries[i].data) memset (*buf + doff, 0, s); 147548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen else memcpy (*buf + doff, n->entries[i].data, s); 148548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 149548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 150548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 151548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 152548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_load (ExifMnoteData *en, 153548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen const unsigned char *buf, unsigned int buf_size) 154548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 155548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en; 156548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifLong c; 157548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t i, tcount, o, datao; 158548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 159548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n || !buf || !buf_size) { 160548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, 161548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteDataFuji", "Short MakerNote"); 162548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 163548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 164548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen datao = 6 + n->offset; 165548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((datao + 12 < datao) || (datao + 12 < 12) || (datao + 12 > buf_size)) { 166548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, 167548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteDataFuji", "Short MakerNote"); 168548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 169548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 170548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 171548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->order = EXIF_BYTE_ORDER_INTEL; 172548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL); 173548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((datao + 2 < datao) || (datao + 2 < 2) || 174548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen (datao + 2 > buf_size)) { 175548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, 176548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteDataFuji", "Short MakerNote"); 177548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 178548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 179548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 180548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Read the number of tags */ 181548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL); 182548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen datao += 2; 183548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 184548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Remove any old entries */ 185548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_fuji_clear (n); 186548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 187548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Reserve enough space for all the possible MakerNote tags */ 188548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c); 189548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n->entries) { 190548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c); 191548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 192548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 193548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 194548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Parse all c entries, storing ones that are successfully parsed */ 195548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen tcount = 0; 196548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = c, o = datao; i; --i, o += 12) { 197548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t s; 198548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) { 199548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, 200548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteDataFuji", "Short MakerNote"); 201548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 202548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 203548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 204548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].tag = exif_get_short (buf + o, n->order); 205548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); 206548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); 207548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].order = n->order; 208548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 209548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji", 210548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, 211548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen mnote_fuji_tag_get_name (n->entries[tcount].tag)); 212548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 213548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 214548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Size? If bigger than 4 bytes, the actual data is not 215548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * in the entry but somewhere else (offset). 216548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 217548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components; 218548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].size = s; 219548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s) { 220548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t dataofs = o + 8; 221548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 4) 222548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* The data in this case is merely a pointer */ 223548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset; 224548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((dataofs + s < dataofs) || (dataofs + s < s) || 225548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen (dataofs + s >= buf_size)) { 226548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, 227548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteDataFuji", "Tag data past end of " 228548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "buffer (%u >= %u)", dataofs + s, buf_size); 229548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 230548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 231548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 232548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].data = exif_mem_alloc (en->mem, s); 233548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n->entries[tcount].data) { 234548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s); 235548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 236548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 237548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (n->entries[tcount].data, buf + dataofs, s); 238548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 239548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 240548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Tag was successfully parsed */ 241548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ++tcount; 242548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 243548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Store the count of successfully parsed tags */ 244548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->count = tcount; 245548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 246548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 247548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic unsigned int 248548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_count (ExifMnoteData *n) 249548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 250548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return n ? ((ExifMnoteDataFuji *) n)->count : 0; 251548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 252548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 253548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic unsigned int 254548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n) 255548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 256548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d; 257548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 258548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!note) return 0; 259548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (note->count <= n) return 0; 260548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return note->entries[n].tag; 261548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 262548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 263548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const char * 264548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i) 265548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 266548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; 267548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 268548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return NULL; 269548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (i >= n->count) return NULL; 270548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_fuji_tag_get_name (n->entries[i].tag); 271548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 272548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 273548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const char * 274548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i) 275548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 276548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; 277548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 278548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return NULL; 279548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (i >= n->count) return NULL; 280548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_fuji_tag_get_title (n->entries[i].tag); 281548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 282548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 283548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const char * 284548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i) 285548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 286548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; 287548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 288548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return NULL; 289548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (i >= n->count) return NULL; 290548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_fuji_tag_get_description (n->entries[i].tag); 291548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 292548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 293548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 294548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o) 295548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 296548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifByteOrder o_orig; 297548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d; 298548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 299548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 300548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return; 301548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 302548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o_orig = n->order; 303548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->order = o; 304548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < n->count; i++) { 305548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].order = o; 306548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, 307548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].components, o_orig, o); 308548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 309548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 310548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 311548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 312548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o) 313548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 314548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (n) ((ExifMnoteDataFuji *) n)->offset = o; 315548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 316548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 317548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenint 318548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e) 319548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 320548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8)); 321548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 322548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 323548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifMnoteData * 324548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_fuji_new (ExifMem *mem) 325548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 326548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteData *d; 327548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 328548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!mem) return NULL; 329548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 330548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji)); 331548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!d) return NULL; 332548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 333548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_construct (d, mem); 334548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 335548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Set up function pointers */ 336548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.free = exif_mnote_data_fuji_free; 337548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.set_byte_order = exif_mnote_data_fuji_set_byte_order; 338548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.set_offset = exif_mnote_data_fuji_set_offset; 339548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.load = exif_mnote_data_fuji_load; 340548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.save = exif_mnote_data_fuji_save; 341548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.count = exif_mnote_data_fuji_count; 342548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_id = exif_mnote_data_fuji_get_id; 343548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_name = exif_mnote_data_fuji_get_name; 344548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_title = exif_mnote_data_fuji_get_title; 345548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_description = exif_mnote_data_fuji_get_description; 346548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_value = exif_mnote_data_fuji_get_value; 347548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 348548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return d; 349548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 350