1/* exif-mnote-data-olympus.c
2 *
3 * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA  02110-1301  USA.
19 */
20
21#include <config.h>
22#include "exif-mnote-data-olympus.h"
23
24#include <stdlib.h>
25#include <string.h>
26#include <stdio.h>
27
28#include <libexif/exif-utils.h>
29#include <libexif/exif-data.h>
30
31#define DEBUG
32
33/* Uncomment this to fix a problem with Sanyo MakerNotes. It's probably best
34 * not to in most cases because it seems to only affect the thumbnail tag
35 * which is duplicated in IFD 1, and fixing the offset could actually cause
36 * problems with other software that expects the broken form.
37 */
38/*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */
39
40static void
41exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
42{
43	ExifMnoteData *d = (ExifMnoteData *) n;
44	unsigned int i;
45
46	if (!n) return;
47
48	if (n->entries) {
49		for (i = 0; i < n->count; i++)
50			if (n->entries[i].data) {
51				exif_mem_free (d->mem, n->entries[i].data);
52				n->entries[i].data = NULL;
53			}
54		exif_mem_free (d->mem, n->entries);
55		n->entries = NULL;
56		n->count = 0;
57	}
58}
59
60static void
61exif_mnote_data_olympus_free (ExifMnoteData *n)
62{
63	if (!n) return;
64
65	exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
66}
67
68static char *
69exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
70{
71	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
72
73	if (!d || !val) return NULL;
74	if (i > n->count -1) return NULL;
75	exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
76		  "Querying value for tag '%s'...",
77		  mnote_olympus_tag_get_name (n->entries[i].tag));
78	return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
79}
80
81
82
83
84/**
85 * @brief save the MnoteData from ne to buf
86 *
87 * @param ne extract the data from this structure
88 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
89 * @param buf_size the size of the buffer
90 */
91static void
92exif_mnote_data_olympus_save (ExifMnoteData *ne,
93		unsigned char **buf, unsigned int *buf_size)
94{
95	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
96	size_t i, o, s, doff, base = 0, o2 = 6 + 2;
97	size_t datao = 0;
98	unsigned char *t;
99	size_t ts;
100
101	if (!n || !buf || !buf_size) return;
102
103	/*
104	 * Allocate enough memory for all entries and the number of entries.
105	 */
106	*buf_size = 6 + 2 + 2 + n->count * 12;
107	switch (n->version) {
108	case olympusV1:
109	case sanyoV1:
110	case epsonV1:
111		*buf = exif_mem_alloc (ne->mem, *buf_size);
112		if (!*buf) {
113			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
114			return;
115		}
116
117		/* Write the header and the number of entries. */
118		strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
119					(n->version==epsonV1?"EPSON":"OLYMP"));
120		exif_set_short (*buf + 6, n->order, (ExifShort) 1);
121		datao = n->offset;
122		break;
123	case olympusV2:
124		*buf_size += 8-6 + 4;
125		*buf = exif_mem_alloc (ne->mem, *buf_size);
126		if (!*buf) {
127			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
128			return;
129		}
130
131		/* Write the header and the number of entries. */
132		strcpy ((char *)*buf, "OLYMPUS");
133		exif_set_short (*buf + 8, n->order, (ExifShort) (
134			(n->order == EXIF_BYTE_ORDER_INTEL) ?
135			('I' << 8) | 'I' :
136			('M' << 8) | 'M'));
137		exif_set_short (*buf + 10, n->order, (ExifShort) 3);
138		o2 += 4;
139		break;
140	case nikonV1:
141		base = MNOTE_NIKON1_TAG_BASE;
142
143		/* v1 has offsets based to main IFD, not makernote IFD */
144		datao += n->offset + 10;
145		/* subtract the size here, so the increment in the next case will not harm us */
146		*buf_size -= 8 + 2;
147		/* Fall through */
148	case nikonV2:
149		*buf_size += 8 + 2;
150		*buf_size += 4; /* Next IFD pointer */
151		*buf = exif_mem_alloc (ne->mem, *buf_size);
152		if (!*buf) {
153			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
154			return;
155		}
156
157		/* Write the header and the number of entries. */
158		strcpy ((char *)*buf, "Nikon");
159		(*buf)[6] = n->version;
160
161		if (n->version == nikonV2) {
162			exif_set_short (*buf + 10, n->order, (ExifShort) (
163				(n->order == EXIF_BYTE_ORDER_INTEL) ?
164				('I' << 8) | 'I' :
165				('M' << 8) | 'M'));
166			exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
167			exif_set_long (*buf + 14, n->order, (ExifShort) 8);
168			o2 += 2 + 8;
169		}
170		datao -= 10;
171		/* Reset next IFD pointer */
172		exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
173		break;
174
175	default:
176		return;
177	}
178
179	exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
180	o2 += 2;
181
182	/* Save each entry */
183	for (i = 0; i < n->count; i++) {
184		o = o2 + i * 12;
185		exif_set_short (*buf + o + 0, n->order,
186				(ExifShort) (n->entries[i].tag - base));
187		exif_set_short (*buf + o + 2, n->order,
188				(ExifShort) n->entries[i].format);
189		exif_set_long  (*buf + o + 4, n->order,
190				n->entries[i].components);
191		o += 8;
192		s = exif_format_get_size (n->entries[i].format) *
193						n->entries[i].components;
194		if (s > 65536) {
195			/* Corrupt data: EXIF data size is limited to the
196			 * maximum size of a JPEG segment (64 kb).
197			 */
198			continue;
199		}
200		if (s > 4) {
201			doff = *buf_size;
202			ts = *buf_size + s;
203			t = exif_mem_realloc (ne->mem, *buf,
204						 sizeof (char) * ts);
205			if (!t) {
206				EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
207				return;
208			}
209			*buf = t;
210			*buf_size = ts;
211			exif_set_long (*buf + o, n->order, datao + doff);
212		} else
213			doff = o;
214
215		/* Write the data. */
216		if (n->entries[i].data) {
217			memcpy (*buf + doff, n->entries[i].data, s);
218		} else {
219			/* Most certainly damaged input file */
220			memset (*buf + doff, 0, s);
221		}
222	}
223}
224
225static void
226exif_mnote_data_olympus_load (ExifMnoteData *en,
227			      const unsigned char *buf, unsigned int buf_size)
228{
229	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
230	ExifShort c;
231	size_t i, tcount, o, o2, datao = 6, base = 0;
232
233	if (!n || !buf || !buf_size) {
234		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
235			  "ExifMnoteDataOlympus", "Short MakerNote");
236		return;
237	}
238	o2 = 6 + n->offset; /* Start of interesting data */
239	if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
240		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
241			  "ExifMnoteDataOlympus", "Short MakerNote");
242		return;
243	}
244
245	/*
246	 * Olympus headers start with "OLYMP" and need to have at least
247	 * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
248	 * number of entries, and 12 for one entry.
249	 *
250	 * Sanyo format is identical and uses identical tags except that
251	 * header starts with "SANYO".
252	 *
253	 * Epson format is identical and uses identical tags except that
254	 * header starts with "EPSON".
255	 *
256	 * Nikon headers start with "Nikon" (6 bytes including '\0'),
257	 * version number (1 or 2).
258	 *
259	 * Version 1 continues with 0, 1, 0, number_of_tags,
260	 * or just with number_of_tags (models D1H, D1X...).
261	 *
262	 * Version 2 continues with an unknown byte (0 or 10),
263	 * two unknown bytes (0), "MM" or "II", another byte 0 and
264	 * lastly 0x2A.
265	 */
266	if (!memcmp (buf + o2, "OLYMP", 6) || !memcmp (buf + o2, "SANYO", 6) ||
267	    !memcmp (buf + o2, "EPSON", 6)) {
268		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
269			"Parsing Olympus/Sanyo/Epson maker note v1...");
270
271		/* The number of entries is at position 8. */
272		if (!memcmp (buf + o2, "SANYO", 6))
273			n->version = sanyoV1;
274		else if (!memcmp (buf + o2, "EPSON", 6))
275			n->version = epsonV1;
276		else
277			n->version = olympusV1;
278		if (buf[o2 + 6] == 1)
279			n->order = EXIF_BYTE_ORDER_INTEL;
280		else if (buf[o2 + 6 + 1] == 1)
281			n->order = EXIF_BYTE_ORDER_MOTOROLA;
282		o2 += 8;
283		if (o2 + 2 > buf_size) return;
284		c = exif_get_short (buf + o2, n->order);
285		if ((!(c & 0xFF)) && (c > 0x500)) {
286			if (n->order == EXIF_BYTE_ORDER_INTEL) {
287				n->order = EXIF_BYTE_ORDER_MOTOROLA;
288			} else {
289				n->order = EXIF_BYTE_ORDER_INTEL;
290			}
291		}
292
293	} else if (!memcmp (buf + o2, "OLYMPUS", 8)) {
294		/* Olympus S760, S770 */
295		datao = o2;
296		o2 += 8;
297		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
298			"Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
299			buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
300
301		if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
302			n->order = EXIF_BYTE_ORDER_INTEL;
303		else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
304			n->order = EXIF_BYTE_ORDER_MOTOROLA;
305
306		/* The number of entries is at position 8+4. */
307		n->version = olympusV2;
308		o2 += 4;
309
310	} else if (!memcmp (buf + o2, "Nikon", 6)) {
311		o2 += 6;
312		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
313			"Parsing Nikon maker note (0x%02x, %02x, %02x, "
314			"%02x, %02x, %02x, %02x, %02x)...",
315			buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
316			buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
317		/* The first byte is the version. */
318		if (o2 >= buf_size) return;
319		n->version = buf[o2];
320		o2 += 1;
321
322		/* Skip an unknown byte (00 or 0A). */
323		o2 += 1;
324
325		switch (n->version) {
326		case nikonV1:
327
328			base = MNOTE_NIKON1_TAG_BASE;
329			/* Fix endianness, if needed */
330			if (o2 + 2 > buf_size) return;
331			c = exif_get_short (buf + o2, n->order);
332			if ((!(c & 0xFF)) && (c > 0x500)) {
333				if (n->order == EXIF_BYTE_ORDER_INTEL) {
334					n->order = EXIF_BYTE_ORDER_MOTOROLA;
335				} else {
336					n->order = EXIF_BYTE_ORDER_INTEL;
337				}
338			}
339			break;
340
341		case nikonV2:
342
343			/* Skip 2 unknown bytes (00 00). */
344			o2 += 2;
345
346			/*
347			 * Byte order. From here the data offset
348			 * gets calculated.
349			 */
350			datao = o2;
351			if (o2 >= buf_size) return;
352			if (!strncmp ((char *)&buf[o2], "II", 2))
353				n->order = EXIF_BYTE_ORDER_INTEL;
354			else if (!strncmp ((char *)&buf[o2], "MM", 2))
355				n->order = EXIF_BYTE_ORDER_MOTOROLA;
356			else {
357				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
358					"ExifMnoteDatalympus", "Unknown "
359					"byte order '%c%c'", buf[o2],
360					buf[o2 + 1]);
361				return;
362			}
363			o2 += 2;
364
365			/* Skip 2 unknown bytes (00 2A). */
366			o2 += 2;
367
368			/* Go to where the number of entries is. */
369			if (o2 + 4 > buf_size) return;
370			o2 = datao + exif_get_long (buf + o2, n->order);
371			break;
372
373		default:
374			exif_log (en->log, EXIF_LOG_CODE_DEBUG,
375				"ExifMnoteDataOlympus", "Unknown version "
376				"number %i.", n->version);
377			return;
378		}
379	} else if (!memcmp (buf + o2, "\0\x1b", 2)) {
380		n->version = nikonV2;
381		/* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
382		n->order = EXIF_BYTE_ORDER_MOTOROLA;
383	} else {
384		return;
385	}
386
387	/* Sanity check the offset */
388	if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
389		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
390			  "ExifMnoteOlympus", "Short MakerNote");
391		return;
392	}
393
394	/* Read the number of tags */
395	c = exif_get_short (buf + o2, n->order);
396	o2 += 2;
397
398	/* Remove any old entries */
399	exif_mnote_data_olympus_clear (n);
400
401	/* Reserve enough space for all the possible MakerNote tags */
402	n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
403	if (!n->entries) {
404		EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
405		return;
406	}
407
408	/* Parse all c entries, storing ones that are successfully parsed */
409	tcount = 0;
410	for (i = c, o = o2; i; --i, o += 12) {
411		size_t s;
412		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
413			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
414				  "ExifMnoteOlympus", "Short MakerNote");
415			break;
416		}
417
418	    n->entries[tcount].tag        = exif_get_short (buf + o, n->order) + base;
419	    n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
420	    n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
421	    n->entries[tcount].order      = n->order;
422
423	    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
424		      "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
425		      mnote_olympus_tag_get_name (n->entries[tcount].tag));
426/*	    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
427			    "0x%x %d %ld*(%d)",
428		    n->entries[tcount].tag,
429		    n->entries[tcount].format,
430		    n->entries[tcount].components,
431		    (int)exif_format_get_size(n->entries[tcount].format)); */
432
433	    /*
434	     * Size? If bigger than 4 bytes, the actual data is not
435	     * in the entry but somewhere else (offset).
436	     */
437	    s = exif_format_get_size (n->entries[tcount].format) *
438		   			 n->entries[tcount].components;
439		n->entries[tcount].size = s;
440		if (s) {
441			size_t dataofs = o + 8;
442			if (s > 4) {
443				/* The data in this case is merely a pointer */
444				dataofs = exif_get_long (buf + dataofs, n->order) + datao;
445#ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
446				/* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
447				 * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
448				 * tag in its MakerNote. The offset is actually the absolute
449				 * position in the file instead of the position within the IFD.
450				 */
451			    if (dataofs + s > buf_size && n->version == sanyoV1) {
452					/* fix pointer */
453					dataofs -= datao + 6;
454					exif_log (en->log, EXIF_LOG_CODE_DEBUG,
455						  "ExifMnoteOlympus",
456						  "Inconsistent thumbnail tag offset; attempting to recover");
457			    }
458#endif
459			}
460			if ((dataofs + s < dataofs) || (dataofs + s < s) ||
461			    (dataofs + s > buf_size)) {
462				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
463					  "ExifMnoteOlympus",
464					  "Tag data past end of buffer (%u > %u)",
465					  dataofs + s, buf_size);
466				continue;
467			}
468
469			n->entries[tcount].data = exif_mem_alloc (en->mem, s);
470			if (!n->entries[tcount].data) {
471				EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
472				continue;
473			}
474			memcpy (n->entries[tcount].data, buf + dataofs, s);
475		}
476
477		/* Tag was successfully parsed */
478		++tcount;
479	}
480	/* Store the count of successfully parsed tags */
481	n->count = tcount;
482}
483
484static unsigned int
485exif_mnote_data_olympus_count (ExifMnoteData *n)
486{
487	return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
488}
489
490static unsigned int
491exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
492{
493	ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
494
495	if (!note) return 0;
496	if (note->count <= n) return 0;
497	return note->entries[n].tag;
498}
499
500static const char *
501exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
502{
503	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
504
505	if (!n) return NULL;
506	if (i >= n->count) return NULL;
507	return mnote_olympus_tag_get_name (n->entries[i].tag);
508}
509
510static const char *
511exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
512{
513	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
514
515	if (!n) return NULL;
516	if (i >= n->count) return NULL;
517        return mnote_olympus_tag_get_title (n->entries[i].tag);
518}
519
520static const char *
521exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
522{
523	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
524
525	if (!n) return NULL;
526	if (i >= n->count) return NULL;
527        return mnote_olympus_tag_get_description (n->entries[i].tag);
528}
529
530static void
531exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
532{
533	ExifByteOrder o_orig;
534	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
535	unsigned int i;
536
537	if (!n) return;
538
539	o_orig = n->order;
540	n->order = o;
541	for (i = 0; i < n->count; i++) {
542		n->entries[i].order = o;
543		exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
544				n->entries[i].components, o_orig, o);
545	}
546}
547
548static void
549exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
550{
551	if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
552}
553
554ExifMnoteData *
555exif_mnote_data_olympus_new (ExifMem *mem)
556{
557	ExifMnoteData *d;
558
559	if (!mem) return NULL;
560
561	d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
562	if (!d) return NULL;
563
564	exif_mnote_data_construct (d, mem);
565
566	/* Set up function pointers */
567	d->methods.free            = exif_mnote_data_olympus_free;
568	d->methods.set_byte_order  = exif_mnote_data_olympus_set_byte_order;
569	d->methods.set_offset      = exif_mnote_data_olympus_set_offset;
570	d->methods.load            = exif_mnote_data_olympus_load;
571	d->methods.save            = exif_mnote_data_olympus_save;
572	d->methods.count           = exif_mnote_data_olympus_count;
573	d->methods.get_id          = exif_mnote_data_olympus_get_id;
574	d->methods.get_name        = exif_mnote_data_olympus_get_name;
575	d->methods.get_title       = exif_mnote_data_olympus_get_title;
576	d->methods.get_description = exif_mnote_data_olympus_get_description;
577	d->methods.get_value       = exif_mnote_data_olympus_get_value;
578
579	return d;
580}
581