00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022 #include "exif-mnote-data-olympus.h"
00023
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <stdio.h>
00027
00028 #include <libexif/exif-utils.h>
00029 #include <libexif/exif-data.h>
00030
00031 #define DEBUG
00032
00033
00034
00035
00036
00037
00038
00039
00040 static enum OlympusVersion
00041 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
00042 unsigned int buf_size);
00043
00044
00045 static void
00046 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
00047 {
00048 ExifMnoteData *d = (ExifMnoteData *) n;
00049 unsigned int i;
00050
00051 if (!n) return;
00052
00053 if (n->entries) {
00054 for (i = 0; i < n->count; i++)
00055 if (n->entries[i].data) {
00056 exif_mem_free (d->mem, n->entries[i].data);
00057 n->entries[i].data = NULL;
00058 }
00059 exif_mem_free (d->mem, n->entries);
00060 n->entries = NULL;
00061 n->count = 0;
00062 }
00063 }
00064
00065 static void
00066 exif_mnote_data_olympus_free (ExifMnoteData *n)
00067 {
00068 if (!n) return;
00069
00070 exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
00071 }
00072
00073 static char *
00074 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
00075 {
00076 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00077
00078 if (!d || !val) return NULL;
00079 if (i > n->count -1) return NULL;
00080
00081
00082
00083
00084
00085 return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
00086 }
00087
00088
00089
00090
00098 static void
00099 exif_mnote_data_olympus_save (ExifMnoteData *ne,
00100 unsigned char **buf, unsigned int *buf_size)
00101 {
00102 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
00103 size_t i, o, s, doff, base = 0, o2 = 6 + 2;
00104 size_t datao = 0;
00105 unsigned char *t;
00106 size_t ts;
00107
00108 if (!n || !buf || !buf_size) return;
00109
00110
00111
00112
00113 *buf_size = 6 + 2 + 2 + n->count * 12;
00114 switch (n->version) {
00115 case olympusV1:
00116 case sanyoV1:
00117 case epsonV1:
00118 *buf = exif_mem_alloc (ne->mem, *buf_size);
00119 if (!*buf) {
00120 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
00121 return;
00122 }
00123
00124
00125 strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
00126 (n->version==epsonV1?"EPSON":"OLYMP"));
00127 exif_set_short (*buf + 6, n->order, (ExifShort) 1);
00128 datao = n->offset;
00129 break;
00130
00131 case olympusV2:
00132 *buf_size += 8-6 + 4;
00133 *buf = exif_mem_alloc (ne->mem, *buf_size);
00134 if (!*buf) {
00135 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
00136 return;
00137 }
00138
00139
00140 strcpy ((char *)*buf, "OLYMPUS");
00141 exif_set_short (*buf + 8, n->order, (ExifShort) (
00142 (n->order == EXIF_BYTE_ORDER_INTEL) ?
00143 ('I' << 8) | 'I' :
00144 ('M' << 8) | 'M'));
00145 exif_set_short (*buf + 10, n->order, (ExifShort) 3);
00146 o2 += 4;
00147 break;
00148
00149 case nikonV1:
00150 base = MNOTE_NIKON1_TAG_BASE;
00151
00152
00153 datao += n->offset + 10;
00154
00155 *buf_size -= 8 + 2;
00156
00157 case nikonV2:
00158
00159 case nikonV0:
00160 *buf_size += 8 + 2;
00161 *buf_size += 4;
00162 *buf = exif_mem_alloc (ne->mem, *buf_size);
00163 if (!*buf) {
00164 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
00165 return;
00166 }
00167
00168
00169 strcpy ((char *)*buf, "Nikon");
00170 (*buf)[6] = n->version;
00171
00172 if (n->version != nikonV1) {
00173 exif_set_short (*buf + 10, n->order, (ExifShort) (
00174 (n->order == EXIF_BYTE_ORDER_INTEL) ?
00175 ('I' << 8) | 'I' :
00176 ('M' << 8) | 'M'));
00177 exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
00178 exif_set_long (*buf + 14, n->order, (ExifShort) 8);
00179 o2 += 2 + 8;
00180 }
00181 datao -= 10;
00182
00183 exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
00184 break;
00185
00186 default:
00187 return;
00188 }
00189
00190 exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
00191 o2 += 2;
00192
00193
00194 for (i = 0; i < n->count; i++) {
00195 o = o2 + i * 12;
00196 exif_set_short (*buf + o + 0, n->order,
00197 (ExifShort) (n->entries[i].tag - base));
00198 exif_set_short (*buf + o + 2, n->order,
00199 (ExifShort) n->entries[i].format);
00200 exif_set_long (*buf + o + 4, n->order,
00201 n->entries[i].components);
00202 o += 8;
00203 s = exif_format_get_size (n->entries[i].format) *
00204 n->entries[i].components;
00205 if (s > 65536) {
00206
00207
00208
00209 continue;
00210 }
00211 if (s > 4) {
00212 doff = *buf_size;
00213 ts = *buf_size + s;
00214 t = exif_mem_realloc (ne->mem, *buf,
00215 sizeof (char) * ts);
00216 if (!t) {
00217 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
00218 return;
00219 }
00220 *buf = t;
00221 *buf_size = ts;
00222 exif_set_long (*buf + o, n->order, datao + doff);
00223 } else
00224 doff = o;
00225
00226
00227 if (n->entries[i].data) {
00228 memcpy (*buf + doff, n->entries[i].data, s);
00229 } else {
00230
00231 memset (*buf + doff, 0, s);
00232 }
00233 }
00234 }
00235
00236 static void
00237 exif_mnote_data_olympus_load (ExifMnoteData *en,
00238 const unsigned char *buf, unsigned int buf_size)
00239 {
00240 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
00241 ExifShort c;
00242 size_t i, tcount, o, o2, datao = 6, base = 0;
00243
00244 if (!n || !buf || !buf_size) {
00245 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00246 "ExifMnoteDataOlympus", "Short MakerNote");
00247 return;
00248 }
00249 o2 = 6 + n->offset;
00250 if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
00251 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00252 "ExifMnoteDataOlympus", "Short MakerNote");
00253 return;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2);
00278 switch (n->version) {
00279 case olympusV1:
00280 case sanyoV1:
00281 case epsonV1:
00282 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00283 "Parsing Olympus/Sanyo/Epson maker note v1...");
00284
00285
00286 if (buf[o2 + 6] == 1)
00287 n->order = EXIF_BYTE_ORDER_INTEL;
00288 else if (buf[o2 + 6 + 1] == 1)
00289 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00290 o2 += 8;
00291 if (o2 + 2 > buf_size) return;
00292 c = exif_get_short (buf + o2, n->order);
00293 if ((!(c & 0xFF)) && (c > 0x500)) {
00294 if (n->order == EXIF_BYTE_ORDER_INTEL) {
00295 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00296 } else {
00297 n->order = EXIF_BYTE_ORDER_INTEL;
00298 }
00299 }
00300 break;
00301
00302 case olympusV2:
00303
00304 datao = o2;
00305 o2 += 8;
00306 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00307 "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
00308 buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
00309
00310 if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
00311 n->order = EXIF_BYTE_ORDER_INTEL;
00312 else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
00313 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00314
00315
00316 o2 += 4;
00317 break;
00318
00319 case nikonV1:
00320 o2 += 6;
00321 if (o2 >= buf_size) return;
00322 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00323 "Parsing Nikon maker note v1 (0x%02x, %02x, %02x, "
00324 "%02x, %02x, %02x, %02x, %02x)...",
00325 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
00326 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
00327
00328
00329 o2 += 1;
00330
00331
00332 o2 += 1;
00333
00334 base = MNOTE_NIKON1_TAG_BASE;
00335
00336 if (o2 + 2 > buf_size) return;
00337 c = exif_get_short (buf + o2, n->order);
00338 if ((!(c & 0xFF)) && (c > 0x500)) {
00339 if (n->order == EXIF_BYTE_ORDER_INTEL) {
00340 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00341 } else {
00342 n->order = EXIF_BYTE_ORDER_INTEL;
00343 }
00344 }
00345 break;
00346
00347 case nikonV2:
00348 o2 += 6;
00349 if (o2 >= buf_size) return;
00350 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00351 "Parsing Nikon maker note v2 (0x%02x, %02x, %02x, "
00352 "%02x, %02x, %02x, %02x, %02x)...",
00353 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
00354 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
00355
00356
00357 o2 += 1;
00358
00359
00360 o2 += 1;
00361
00362
00363 o2 += 2;
00364
00365
00366
00367
00368
00369 datao = o2;
00370 if (o2 >= buf_size) return;
00371 if (!strncmp ((char *)&buf[o2], "II", 2))
00372 n->order = EXIF_BYTE_ORDER_INTEL;
00373 else if (!strncmp ((char *)&buf[o2], "MM", 2))
00374 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00375 else {
00376 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00377 "ExifMnoteDataOlympus", "Unknown "
00378 "byte order '%c%c'", buf[o2],
00379 buf[o2 + 1]);
00380 return;
00381 }
00382 o2 += 2;
00383
00384
00385 o2 += 2;
00386
00387
00388 if (o2 + 4 > buf_size) return;
00389 o2 = datao + exif_get_long (buf + o2, n->order);
00390 break;
00391
00392 case nikonV0:
00393 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00394 "Parsing Nikon maker note v0 (0x%02x, %02x, %02x, "
00395 "%02x, %02x, %02x, %02x, %02x)...",
00396 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
00397 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
00398
00399 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00400 break;
00401
00402 default:
00403 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00404 "Unknown Olympus variant %i.", n->version);
00405 return;
00406 }
00407
00408
00409 if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
00410 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00411 "ExifMnoteOlympus", "Short MakerNote");
00412 return;
00413 }
00414
00415
00416 c = exif_get_short (buf + o2, n->order);
00417 o2 += 2;
00418
00419
00420 exif_mnote_data_olympus_clear (n);
00421
00422
00423 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
00424 if (!n->entries) {
00425 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
00426 return;
00427 }
00428
00429
00430 tcount = 0;
00431 for (i = c, o = o2; i; --i, o += 12) {
00432 size_t s;
00433 if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
00434 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00435 "ExifMnoteOlympus", "Short MakerNote");
00436 break;
00437 }
00438
00439 n->entries[tcount].tag = exif_get_short (buf + o, n->order) + base;
00440 n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
00441 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
00442 n->entries[tcount].order = n->order;
00443
00444 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
00445 "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
00446 mnote_olympus_tag_get_name (n->entries[tcount].tag));
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 s = exif_format_get_size (n->entries[tcount].format) *
00459 n->entries[tcount].components;
00460 n->entries[tcount].size = s;
00461 if (s) {
00462 size_t dataofs = o + 8;
00463 if (s > 4) {
00464
00465 dataofs = exif_get_long (buf + dataofs, n->order) + datao;
00466 #ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
00467
00468
00469
00470
00471
00472 if (dataofs + s > buf_size && n->version == sanyoV1) {
00473
00474 dataofs -= datao + 6;
00475 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00476 "ExifMnoteOlympus",
00477 "Inconsistent thumbnail tag offset; attempting to recover");
00478 }
00479 #endif
00480 }
00481 if ((dataofs + s < dataofs) || (dataofs + s < s) ||
00482 (dataofs + s > buf_size)) {
00483 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00484 "ExifMnoteOlympus",
00485 "Tag data past end of buffer (%u > %u)",
00486 dataofs + s, buf_size);
00487 continue;
00488 }
00489
00490 n->entries[tcount].data = exif_mem_alloc (en->mem, s);
00491 if (!n->entries[tcount].data) {
00492 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
00493 continue;
00494 }
00495 memcpy (n->entries[tcount].data, buf + dataofs, s);
00496 }
00497
00498
00499 ++tcount;
00500 }
00501
00502 n->count = tcount;
00503 }
00504
00505 static unsigned int
00506 exif_mnote_data_olympus_count (ExifMnoteData *n)
00507 {
00508 return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
00509 }
00510
00511 static unsigned int
00512 exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
00513 {
00514 ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
00515
00516 if (!note) return 0;
00517 if (note->count <= n) return 0;
00518 return note->entries[n].tag;
00519 }
00520
00521 static const char *
00522 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
00523 {
00524 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00525
00526 if (!n) return NULL;
00527 if (i >= n->count) return NULL;
00528 return mnote_olympus_tag_get_name (n->entries[i].tag);
00529 }
00530
00531 static const char *
00532 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
00533 {
00534 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00535
00536 if (!n) return NULL;
00537 if (i >= n->count) return NULL;
00538 return mnote_olympus_tag_get_title (n->entries[i].tag);
00539 }
00540
00541 static const char *
00542 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
00543 {
00544 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00545
00546 if (!n) return NULL;
00547 if (i >= n->count) return NULL;
00548 return mnote_olympus_tag_get_description (n->entries[i].tag);
00549 }
00550
00551 static void
00552 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
00553 {
00554 ExifByteOrder o_orig;
00555 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00556 unsigned int i;
00557
00558 if (!n) return;
00559
00560 o_orig = n->order;
00561 n->order = o;
00562 for (i = 0; i < n->count; i++) {
00563 n->entries[i].order = o;
00564 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
00565 n->entries[i].components, o_orig, o);
00566 }
00567 }
00568
00569 static void
00570 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
00571 {
00572 if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
00573 }
00574
00575 static enum OlympusVersion
00576 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
00577 unsigned int buf_size)
00578 {
00579
00580 if (buf_size >= 8) {
00581
00582 if (!memcmp (buf, "OLYMPUS", 8))
00583 return olympusV2;
00584 else if (!memcmp (buf, "OLYMP", 6))
00585 return olympusV1;
00586 else if (!memcmp (buf, "SANYO", 6))
00587 return sanyoV1;
00588 else if (!memcmp (buf, "EPSON", 6))
00589 return epsonV1;
00590 else if (!memcmp (buf, "Nikon", 6)) {
00591 switch (buf[6]) {
00592 case 1: return nikonV1;
00593 case 2: return nikonV2;
00594 default: return 0;
00595 }
00596 }
00597 }
00598
00599
00600 if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) {
00601 return nikonV0;
00602 }
00603
00604 return unrecognized;
00605 }
00606
00607 int
00608 exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e)
00609 {
00610 int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size);
00611
00612 if (variant == nikonV0) {
00613
00614 char value[5];
00615 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
00616 variant = unrecognized;
00617
00618 if (em) {
00619 const char *v = exif_entry_get_value (em, value, sizeof(value));
00620 if (v && (!strncmp (v, "Nikon", sizeof(value)) ||
00621 !strncmp (v, "NIKON", sizeof(value)) ))
00622
00623
00624
00625 variant = nikonV0;
00626 }
00627 }
00628
00629 return variant;
00630 }
00631
00632
00633 ExifMnoteData *
00634 exif_mnote_data_olympus_new (ExifMem *mem)
00635 {
00636 ExifMnoteData *d;
00637
00638 if (!mem) return NULL;
00639
00640 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
00641 if (!d) return NULL;
00642
00643 exif_mnote_data_construct (d, mem);
00644
00645
00646 d->methods.free = exif_mnote_data_olympus_free;
00647 d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order;
00648 d->methods.set_offset = exif_mnote_data_olympus_set_offset;
00649 d->methods.load = exif_mnote_data_olympus_load;
00650 d->methods.save = exif_mnote_data_olympus_save;
00651 d->methods.count = exif_mnote_data_olympus_count;
00652 d->methods.get_id = exif_mnote_data_olympus_get_id;
00653 d->methods.get_name = exif_mnote_data_olympus_get_name;
00654 d->methods.get_title = exif_mnote_data_olympus_get_title;
00655 d->methods.get_description = exif_mnote_data_olympus_get_description;
00656 d->methods.get_value = exif_mnote_data_olympus_get_value;
00657
00658 return d;
00659 }