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