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