1548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/* exif-mnote-data-canon.c 2548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 3548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net> 4548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Copyright (c) 2003 Matthieu Castet <mat-c@users.sourceforge.net> 5548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 6548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * This library is free software; you can redistribute it and/or 7548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * modify it under the terms of the GNU Lesser General Public 8548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * License as published by the Free Software Foundation; either 9548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * version 2 of the License, or (at your option) any later version. 10548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 11548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * This library is distributed in the hope that it will be useful, 12548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * but WITHOUT ANY WARRANTY; without even the implied warranty of 13548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Lesser General Public License for more details. 15548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 16548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * You should have received a copy of the GNU Lesser General Public 17548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * License along with this library; if not, write to the 18548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Boston, MA 02110-1301 USA. 20548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 21548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 22548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <config.h> 23548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include "exif-mnote-data-canon.h" 24548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 25548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <stdlib.h> 26548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <stdio.h> 27548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <string.h> 28548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 29548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-byte-order.h> 30548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-utils.h> 31548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-data.h> 32548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 33548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#define DEBUG 34548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 35548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 36548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_clear (ExifMnoteDataCanon *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_canon_free (ExifMnoteData *n) 57548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 58548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return; 59548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 60548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_canon_clear ((ExifMnoteDataCanon *) n); 61548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 62548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 63548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 64548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_get_tags (ExifMnoteDataCanon *dc, unsigned int n, 65548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int *m, unsigned int *s) 66548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 67548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int from = 0, to; 68548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 69548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!dc || !m) return; 70548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (*m = 0; *m < dc->count; (*m)++) { 71548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen to = from + mnote_canon_entry_count_values (&dc->entries[*m]); 72548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (to > n) { 73548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s) *s = n - from; 74548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 75548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 76548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen from = to; 77548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 78548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 79548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 80548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic char * 81548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_get_value (ExifMnoteData *note, unsigned int n, char *val, unsigned int maxlen) 82548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 83548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; 84548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int m, s; 85548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 86548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!dc) return NULL; 87548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_canon_get_tags (dc, n, &m, &s); 88548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (m >= dc->count) return NULL; 89548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_canon_entry_get_value (&dc->entries[m], s, val, maxlen); 90548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 91548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 92548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 93548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_set_byte_order (ExifMnoteData *d, ExifByteOrder o) 94548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 95548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifByteOrder o_orig; 96548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) d; 97548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 98548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 99548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n) return; 100548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 101548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o_orig = n->order; 102548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->order = o; 103548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < n->count; i++) { 104548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].order = o; 105548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, 106548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].components, o_orig, o); 107548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 108548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 109548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 110548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 111548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_set_offset (ExifMnoteData *n, unsigned int o) 112548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 113548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (n) ((ExifMnoteDataCanon *) n)->offset = o; 114548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 115548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 116548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 117548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_save (ExifMnoteData *ne, 118548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned char **buf, unsigned int *buf_size) 119548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 120548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; 121548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t i, o, s, doff; 122548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned char *t; 123548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t ts; 124548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 125548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n || !buf || !buf_size) return; 126548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 127548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 128548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Allocate enough memory for all entries and the number 129548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * of entries. 130548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 131548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf_size = 2 + n->count * 12 + 4; 132548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size); 133548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!*buf) { 134548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size); 135548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 136548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 137548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 138548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Save the number of entries */ 139548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*buf, n->order, (ExifShort) n->count); 140548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 141548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Save each entry */ 142548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < n->count; i++) { 143548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o = 2 + i * 12; 144548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag); 145548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format); 146548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*buf + o + 4, n->order, 147548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].components); 148548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o += 8; 149548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen s = exif_format_get_size (n->entries[i].format) * 150548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[i].components; 151548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 65536) { 152548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Corrupt data: EXIF data size is limited to the 153548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * maximum size of a JPEG segment (64 kb). 154548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 155548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 156548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 157548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 4) { 158548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ts = *buf_size + s; 159548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 160548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Ensure even offsets. Set padding bytes to 0. */ 161548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s & 1) ts += 1; 162548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen t = exif_mem_realloc (ne->mem, *buf, 163548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen sizeof (char) * ts); 164548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!t) { 165548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts); 166548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 167548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 168548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf = t; 169548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *buf_size = ts; 170548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = *buf_size - s; 171548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; } 172548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*buf + o, n->order, n->offset + doff); 173548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else 174548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = o; 175548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 176548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 177548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Write the data. Fill unneeded bytes with 0. Do not 178548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * crash if data is NULL. 179548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 180548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n->entries[i].data) memset (*buf + doff, 0, s); 181548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen else memcpy (*buf + doff, n->entries[i].data, s); 182548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s < 4) memset (*buf + doff + s, 0, (4 - s)); 183548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 184548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 185548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 186548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/* XXX 187548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * FIXME: exif_mnote_data_canon_load() may fail and there is no 188548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * semantics to express that. 189548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * See bug #1054323 for details, especially the comment by liblit 190548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * after it has supposedly been fixed: 191548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 192548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * https://sourceforge.net/tracker/?func=detail&aid=1054323&group_id=12272&atid=112272 193548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Unfortunately, the "return" statements aren't commented at 194548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * all, so it isn't trivial to find out what is a normal 195548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * return, and what is a reaction to an error condition. 196548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 197548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 198548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 199548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_load (ExifMnoteData *ne, 200548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen const unsigned char *buf, unsigned int buf_size) 201548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 202548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne; 203548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifShort c; 204548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t i, tcount, o, datao; 205548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 206548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n || !buf || !buf_size) { 207548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, 208548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteCanon", "Short MakerNote"); 209548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 210548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 211548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen datao = 6 + n->offset; 212548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((datao + 2 < datao) || (datao + 2 < 2) || (datao + 2 > buf_size)) { 213548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, 214548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteCanon", "Short MakerNote"); 215548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 216548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 217548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 218548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Read the number of tags */ 219548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen c = exif_get_short (buf + datao, n->order); 220548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen datao += 2; 221548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 222548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Remove any old entries */ 223548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_canon_clear (n); 224548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 225548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Reserve enough space for all the possible MakerNote tags */ 226548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries = exif_mem_alloc (ne->mem, sizeof (MnoteCanonEntry) * c); 227548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n->entries) { 228548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", sizeof (MnoteCanonEntry) * c); 229548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 230548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 231548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 232548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Parse the entries */ 233548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen tcount = 0; 234548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = c, o = datao; i; --i, o += 12) { 235548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t s; 236548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) { 237548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, 238548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteCanon", "Short MakerNote"); 239548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 240548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 241548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 242548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].tag = exif_get_short (buf + o, n->order); 243548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); 244548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); 245548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].order = n->order; 246548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 247548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (ne->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteCanon", 248548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, 249548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen mnote_canon_tag_get_name (n->entries[tcount].tag)); 250548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 251548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 252548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Size? If bigger than 4 bytes, the actual data is not 253548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * in the entry but somewhere else (offset). 254548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 255548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen s = exif_format_get_size (n->entries[tcount].format) * 256548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].components; 257548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].size = s; 258548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!s) { 259548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, 260548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteCanon", 261548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Invalid zero-length tag size"); 262548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 263548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 264548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else { 265548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen size_t dataofs = o + 8; 266548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 4) dataofs = exif_get_long (buf + dataofs, n->order) + 6; 267548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((dataofs + s < s) || (dataofs + s < dataofs) || (dataofs + s > buf_size)) { 268548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (ne->log, EXIF_LOG_CODE_DEBUG, 269548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifMnoteCanon", 270548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Tag data past end of buffer (%u > %u)", 271548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen dataofs + s, buf_size); 272548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 273548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 274548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 275548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->entries[tcount].data = exif_mem_alloc (ne->mem, s); 276548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!n->entries[tcount].data) { 277548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", s); 278548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 279548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 280548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (n->entries[tcount].data, buf + dataofs, s); 281548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 282548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 283548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Tag was successfully parsed */ 284548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ++tcount; 285548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 286548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Store the count of successfully parsed tags */ 287548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n->count = tcount; 288548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 289548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 290548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic unsigned int 291548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_count (ExifMnoteData *n) 292548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 293548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) n; 294548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i, c; 295548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 296548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = c = 0; dc && (i < dc->count); i++) 297548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen c += mnote_canon_entry_count_values (&dc->entries[i]); 298548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return c; 299548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 300548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 301548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic unsigned int 302548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_get_id (ExifMnoteData *d, unsigned int i) 303548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 304548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) d; 305548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int m; 306548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 307548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!dc) return 0; 308548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_canon_get_tags (dc, i, &m, NULL); 309548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (m >= dc->count) return 0; 310548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return dc->entries[m].tag; 311548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 312548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 313548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const char * 314548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_get_name (ExifMnoteData *note, unsigned int i) 315548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 316548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; 317548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int m, s; 318548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 319548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!dc) return NULL; 320548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_canon_get_tags (dc, i, &m, &s); 321548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (m >= dc->count) return NULL; 322548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_canon_tag_get_name_sub (dc->entries[m].tag, s, dc->options); 323548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 324548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 325548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const char * 326548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_get_title (ExifMnoteData *note, unsigned int i) 327548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 328548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; 329548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int m, s; 330548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 331548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!dc) return NULL; 332548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_canon_get_tags (dc, i, &m, &s); 333548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (m >= dc->count) return NULL; 334548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_canon_tag_get_title_sub (dc->entries[m].tag, s, dc->options); 335548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 336548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 337548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const char * 338548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_get_description (ExifMnoteData *note, unsigned int i) 339548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 340548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note; 341548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int m; 342548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 343548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!dc) return NULL; 344548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_canon_get_tags (dc, i, &m, NULL); 345548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (m >= dc->count) return NULL; 346548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return mnote_canon_tag_get_description (dc->entries[m].tag); 347548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 348548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 349548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenint 350548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_identify (const ExifData *ed, const ExifEntry *e) 351548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 352548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen char value[8]; 353548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE); 354548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!em) 355548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return 0; 356548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon"); 357548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 358548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 359548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifMnoteData * 360548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o) 361548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 362548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteData *d; 363548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteDataCanon *dc; 364548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 365548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!mem) return NULL; 366548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 367548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d = exif_mem_alloc (mem, sizeof (ExifMnoteDataCanon)); 368548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!d) 369548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return NULL; 370548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 371548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_construct (d, mem); 372548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 373548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Set up function pointers */ 374548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.free = exif_mnote_data_canon_free; 375548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.set_byte_order = exif_mnote_data_canon_set_byte_order; 376548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.set_offset = exif_mnote_data_canon_set_offset; 377548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.load = exif_mnote_data_canon_load; 378548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.save = exif_mnote_data_canon_save; 379548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.count = exif_mnote_data_canon_count; 380548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_id = exif_mnote_data_canon_get_id; 381548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_name = exif_mnote_data_canon_get_name; 382548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_title = exif_mnote_data_canon_get_title; 383548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_description = exif_mnote_data_canon_get_description; 384548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->methods.get_value = exif_mnote_data_canon_get_value; 385548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 386548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen dc = (ExifMnoteDataCanon*)d; 387548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen dc->options = o; 388548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return d; 389548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 390