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