1 /* exif-mnote-data-fuji.c
3 * Copyright (c) 2002 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.
26 #include <libexif/exif-byte-order.h>
27 #include <libexif/exif-utils.h>
29 #include "exif-mnote-data-fuji.h"
31 #define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
33 struct _MNoteFujiDataPrivate {
38 exif_mnote_data_fuji_clear (ExifMnoteDataFuji *n)
40 ExifMnoteData *d = (ExifMnoteData *) n;
46 for (i = 0; i < n->count; i++)
47 if (n->entries[i].data) {
48 exif_mem_free (d->mem, n->entries[i].data);
49 n->entries[i].data = NULL;
51 exif_mem_free (d->mem, n->entries);
58 exif_mnote_data_fuji_free (ExifMnoteData *n)
62 exif_mnote_data_fuji_clear ((ExifMnoteDataFuji *) n);
66 exif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
68 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
70 if (!d || !val) return NULL;
71 if (i > n->count -1) return NULL;
73 exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
74 "Querying value for tag '%s'...",
75 mnote_fuji_tag_get_name (n->entries[i].tag));
77 return mnote_fuji_entry_get_value (&n->entries[i], val, maxlen);
81 exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
82 unsigned int *buf_size)
84 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne;
89 if (!n || !buf || !buf_size) return;
92 * Allocate enough memory for all entries and the number
95 *buf_size = 8 + 4 + 2 + n->count * 12 + 4;
96 *buf = exif_mem_alloc (ne->mem, *buf_size);
103 * Header: "FUJIFILM" and 4 bytes offset to the first entry.
104 * As the first entry will start right thereafter, the offset is 12.
106 memcpy (*buf, "FUJIFILM", 8);
107 exif_set_long (*buf + 8, n->order, 12);
109 /* Save the number of entries */
110 exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count);
112 /* Save each entry */
113 for (i = 0; i < n->count; i++) {
114 o = 8 + 4 + 2 + i * 12;
115 exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
116 exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
117 exif_set_long (*buf + o + 4, n->order, n->entries[i].components);
119 s = exif_format_get_size (n->entries[i].format) *
120 n->entries[i].components;
122 /* Corrupt data: EXIF data size is limited to the
123 * maximum size of a JPEG segment (64 kb).
130 /* Ensure even offsets. Set padding bytes to 0. */
132 t = exif_mem_realloc (ne->mem, *buf, ts);
138 doff = *buf_size - s;
139 if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
140 exif_set_long (*buf + o, n->order, doff);
145 * Write the data. Fill unneeded bytes with 0. Do not
146 * crash if data is NULL.
148 if (!n->entries[i].data) memset (*buf + doff, 0, s);
149 else memcpy (*buf + doff, n->entries[i].data, s);
154 exif_mnote_data_fuji_load (ExifMnoteData *en,
155 const unsigned char *buf, unsigned int buf_size)
157 ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en;
159 size_t i, tcount, o, datao;
161 if (!n || !buf || !buf_size) {
162 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
163 "ExifMnoteDataFuji", "Short MakerNote");
166 datao = 6 + n->offset;
167 if (CHECKOVERFLOW(datao, buf_size, 12)) {
168 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
169 "ExifMnoteDataFuji", "Short MakerNote");
173 n->order = EXIF_BYTE_ORDER_INTEL;
175 datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
176 if (CHECKOVERFLOW(datao, buf_size, 2)) {
177 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
178 "ExifMnoteDataFuji", "Short MakerNote");
182 /* Read the number of tags */
183 c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL);
186 /* Remove any old entries */
187 exif_mnote_data_fuji_clear (n);
189 /* Reserve enough space for all the possible MakerNote tags */
190 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c);
192 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c);
196 /* Parse all c entries, storing ones that are successfully parsed */
198 for (i = c, o = datao; i; --i, o += 12) {
201 if (CHECKOVERFLOW(o, buf_size, 12)) {
202 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
203 "ExifMnoteDataFuji", "Short MakerNote");
207 n->entries[tcount].tag = exif_get_short (buf + o, n->order);
208 n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
209 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
210 n->entries[tcount].order = n->order;
212 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
213 "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
214 mnote_fuji_tag_get_name (n->entries[tcount].tag));
216 /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
217 * we will check the buffer sizes closer later. */
218 if ( exif_format_get_size (n->entries[tcount].format) &&
219 buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
221 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
222 "ExifMnoteDataFuji", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
226 * Size? If bigger than 4 bytes, the actual data is not
227 * in the entry but somewhere else (offset).
229 s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components;
230 n->entries[tcount].size = s;
232 size_t dataofs = o + 8;
234 /* The data in this case is merely a pointer */
235 dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset;
237 if (CHECKOVERFLOW(dataofs, buf_size, s)) {
238 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
239 "ExifMnoteDataFuji", "Tag data past end of "
240 "buffer (%u >= %u)", (unsigned)(dataofs + s), buf_size);
244 n->entries[tcount].data = exif_mem_alloc (en->mem, s);
245 if (!n->entries[tcount].data) {
246 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s);
249 memcpy (n->entries[tcount].data, buf + dataofs, s);
252 /* Tag was successfully parsed */
255 /* Store the count of successfully parsed tags */
260 exif_mnote_data_fuji_count (ExifMnoteData *n)
262 return n ? ((ExifMnoteDataFuji *) n)->count : 0;
266 exif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n)
268 ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d;
271 if (note->count <= n) return 0;
272 return note->entries[n].tag;
276 exif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i)
278 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
281 if (i >= n->count) return NULL;
282 return mnote_fuji_tag_get_name (n->entries[i].tag);
286 exif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i)
288 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
291 if (i >= n->count) return NULL;
292 return mnote_fuji_tag_get_title (n->entries[i].tag);
296 exif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i)
298 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
301 if (i >= n->count) return NULL;
302 return mnote_fuji_tag_get_description (n->entries[i].tag);
306 exif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
308 ExifByteOrder o_orig;
309 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
316 for (i = 0; i < n->count; i++) {
317 if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
319 n->entries[i].order = o;
320 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
321 n->entries[i].components, o_orig, o);
326 exif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o)
328 if (n) ((ExifMnoteDataFuji *) n)->offset = o;
332 exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e)
334 (void) ed; /* unused */
335 return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8));
339 exif_mnote_data_fuji_new (ExifMem *mem)
343 if (!mem) return NULL;
345 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji));
348 exif_mnote_data_construct (d, mem);
350 /* Set up function pointers */
351 d->methods.free = exif_mnote_data_fuji_free;
352 d->methods.set_byte_order = exif_mnote_data_fuji_set_byte_order;
353 d->methods.set_offset = exif_mnote_data_fuji_set_offset;
354 d->methods.load = exif_mnote_data_fuji_load;
355 d->methods.save = exif_mnote_data_fuji_save;
356 d->methods.count = exif_mnote_data_fuji_count;
357 d->methods.get_id = exif_mnote_data_fuji_get_id;
358 d->methods.get_name = exif_mnote_data_fuji_get_name;
359 d->methods.get_title = exif_mnote_data_fuji_get_title;
360 d->methods.get_description = exif_mnote_data_fuji_get_description;
361 d->methods.get_value = exif_mnote_data_fuji_get_value;