Coverage Report

Created: 2026-06-10 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libexif/libexif/olympus/exif-mnote-data-olympus.c
Line
Count
Source
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
 * SPDX-License-Identifier: LGPL-2.0-or-later
21
 */
22
23
#include <config.h>
24
#include "exif-mnote-data-olympus.h"
25
26
#include <stdlib.h>
27
#include <string.h>
28
#include <stdio.h>
29
30
#include <libexif/exif-utils.h>
31
#include <libexif/exif-data.h>
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
40
148k
#define CHECKOVERFLOW(offset,datasize,structsize) (( (offset) >= (datasize)) || ((structsize) > (datasize)) || ((offset) > (datasize) - (structsize) ))
41
42
static enum OlympusVersion
43
exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
44
    unsigned int buf_size);
45
46
47
static void
48
exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
49
7.33k
{
50
7.33k
  ExifMnoteData *d = (ExifMnoteData *) n;
51
7.33k
  unsigned int i;
52
53
7.33k
  if (!n) return;
54
55
7.33k
  if (n->entries) {
56
95.4k
    for (i = 0; i < n->count; i++)
57
91.8k
      if (n->entries[i].data) {
58
35.4k
        exif_mem_free (d->mem, n->entries[i].data);
59
35.4k
        n->entries[i].data = NULL;
60
35.4k
      }
61
3.57k
    exif_mem_free (d->mem, n->entries);
62
3.57k
    n->entries = NULL;
63
3.57k
    n->count = 0;
64
3.57k
  }
65
7.33k
}
66
67
static void
68
exif_mnote_data_olympus_free (ExifMnoteData *n)
69
3.76k
{
70
3.76k
  if (!n) return;
71
72
3.76k
  exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
73
3.76k
}
74
75
static char *
76
exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
77
52.0k
{
78
52.0k
  ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
79
80
52.0k
  if (!d || !val) return NULL;
81
52.0k
  if (i >= n->count) return NULL;
82
/*
83
  exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
84
      "Querying value for tag '%s'...",
85
      mnote_olympus_tag_get_name (n->entries[i].tag));
86
*/
87
52.0k
  return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
88
52.0k
}
89
90
91
92
93
/** 
94
 * @brief save the MnoteData from ne to buf
95
 * 
96
 * @param ne extract the data from this structure 
97
 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
98
 * @param buf_size the size of the buffer
99
 */
100
static void
101
exif_mnote_data_olympus_save (ExifMnoteData *ne,
102
    unsigned char **buf, unsigned int *buf_size)
103
0
{
104
0
  ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
105
0
  size_t i, o, s, doff, base = 0, o2 = 6 + 2;
106
0
  size_t datao = 0;
107
0
  unsigned char *t;
108
0
  size_t ts;
109
110
0
  if (!n || !buf || !buf_size) return;
111
112
  /*
113
   * Allocate enough memory for all entries and the number of entries.
114
   */
115
0
  *buf_size = 6 + 2 + 2 + n->count * 12;
116
0
  switch (n->version) {
117
0
  case olympusV1:
118
0
  case sanyoV1:
119
0
  case epsonV1:
120
0
    *buf = exif_mem_alloc (ne->mem, *buf_size);
121
0
    if (!*buf) {
122
0
      EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
123
0
      return;
124
0
    }
125
126
    /* Write the header and the number of entries. */
127
0
    strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
128
0
          (n->version==epsonV1?"EPSON":"OLYMP"));
129
0
    exif_set_short (*buf + 6, n->order, (ExifShort) 1);
130
0
    datao = n->offset;
131
0
    break;
132
133
0
  case olympusV2:
134
0
    *buf_size += 8-6 + 4;
135
0
    *buf = exif_mem_alloc (ne->mem, *buf_size);
136
0
    if (!*buf) {
137
0
      EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
138
0
      return;
139
0
    }
140
141
    /* Write the header and the number of entries. */
142
0
    strcpy ((char *)*buf, "OLYMPUS");
143
0
    exif_set_short (*buf + 8, n->order, (ExifShort) (
144
0
      (n->order == EXIF_BYTE_ORDER_INTEL) ?
145
0
      ('I' << 8) | 'I' :
146
0
      ('M' << 8) | 'M'));
147
0
    exif_set_short (*buf + 10, n->order, (ExifShort) 3);
148
0
    o2 += 4;
149
0
    break;
150
151
0
  case nikonV1: 
152
0
    base = MNOTE_NIKON1_TAG_BASE;
153
154
    /* v1 has offsets based to main IFD, not makernote IFD */
155
0
    datao += n->offset + 10;
156
    /* subtract the size here, so the increment in the next case will not harm us */
157
0
    *buf_size -= 8 + 2;
158
    /* fall through */
159
  /* Fall through to nikonV2 handler */
160
0
  case nikonV2: 
161
  /* Write out V0 files in V2 format */
162
0
  case nikonV0: 
163
0
    *buf_size += 8 + 2;
164
0
    *buf_size += 4; /* Next IFD pointer */
165
0
    *buf = exif_mem_alloc (ne->mem, *buf_size);
166
0
    if (!*buf) {
167
0
      EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
168
0
      return;
169
0
    }
170
171
    /* Write the header and the number of entries. */
172
0
    strcpy ((char *)*buf, "Nikon");
173
0
    (*buf)[6] = (unsigned char)n->version;
174
175
0
    if (n->version != nikonV1) {
176
0
      exif_set_short (*buf + 10, n->order, (ExifShort) (
177
0
        (n->order == EXIF_BYTE_ORDER_INTEL) ?
178
0
        ('I' << 8) | 'I' :
179
0
        ('M' << 8) | 'M'));
180
0
      exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
181
0
      exif_set_long (*buf + 14, n->order, (ExifShort) 8);
182
0
      o2 += 2 + 8;
183
0
    }
184
0
    datao -= 10;
185
    /* Reset next IFD pointer */
186
0
    exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
187
0
    break;
188
189
0
  default:
190
0
    return;
191
0
  }
192
193
0
  exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
194
0
  o2 += 2;
195
196
  /* Save each entry */
197
0
  for (i = 0; i < n->count; i++) {
198
0
    o = o2 + i * 12;
199
0
    exif_set_short (*buf + o + 0, n->order,
200
0
        (ExifShort) (n->entries[i].tag - base));
201
0
    exif_set_short (*buf + o + 2, n->order,
202
0
        (ExifShort) n->entries[i].format);
203
0
    exif_set_long  (*buf + o + 4, n->order,
204
0
        n->entries[i].components);
205
0
    o += 8;
206
0
    s = exif_format_get_size (n->entries[i].format) *
207
0
            n->entries[i].components;
208
0
    if (s > 65536) {
209
      /* Corrupt data: EXIF data size is limited to the
210
       * maximum size of a JPEG segment (64 kb).
211
       */
212
0
      continue;
213
0
    }
214
0
    if (s > 4) {
215
0
      doff = *buf_size;
216
0
      ts = *buf_size + s;
217
0
      t = exif_mem_realloc (ne->mem, *buf,
218
0
             sizeof (char) * ts);
219
0
      if (!t) {
220
0
        EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
221
0
        return;
222
0
      }
223
0
      *buf = t;
224
0
      *buf_size = ts;
225
0
      exif_set_long (*buf + o, n->order, datao + doff);
226
0
    } else
227
0
      doff = o;
228
229
    /* Write the data. */
230
0
    if (n->entries[i].data) {
231
0
      memcpy (*buf + doff, n->entries[i].data, s);
232
0
    } else {
233
      /* Most certainly damaged input file */
234
0
      memset (*buf + doff, 0, s);
235
0
    }
236
0
  }
237
0
}
238
239
static void
240
exif_mnote_data_olympus_load (ExifMnoteData *en,
241
            const unsigned char *buf, unsigned int buf_size)
242
3.76k
{
243
3.76k
  ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
244
3.76k
  ExifShort c;
245
3.76k
  size_t i, tcount, o, o2, datao = 6, base = 0;
246
247
3.76k
  if (!n) return;
248
249
3.76k
  if (!buf || !buf_size) {
250
0
    exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
251
0
        "ExifMnoteDataOlympus", "Short MakerNote");
252
0
    return;
253
0
  }
254
3.76k
  o2 = 6 + n->offset; /* Start of interesting data */
255
3.76k
  if (CHECKOVERFLOW(o2,buf_size,10)) {
256
4
    exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
257
4
        "ExifMnoteDataOlympus", "Short MakerNote");
258
4
    return;
259
4
  }
260
261
  /*
262
   * Olympus headers start with "OLYMP" and need to have at least
263
   * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
264
   * number of entries, and 12 for one entry.
265
   *
266
   * Sanyo format is identical and uses identical tags except that
267
   * header starts with "SANYO".
268
   *
269
   * Epson format is identical and uses identical tags except that
270
   * header starts with "EPSON".
271
   *
272
   * Nikon headers start with "Nikon" (6 bytes including '\0'), 
273
   * version number (1 or 2).
274
   * 
275
   * Version 1 continues with 0, 1, 0, number_of_tags,
276
   * or just with number_of_tags (models D1H, D1X...).
277
   * 
278
   * Version 2 continues with an unknown byte (0 or 10),
279
   * two unknown bytes (0), "MM" or "II", another byte 0 and 
280
   * lastly 0x2A.
281
   */
282
3.75k
  n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2);
283
3.75k
  switch (n->version) {
284
1.20k
  case olympusV1:
285
2.44k
  case sanyoV1:
286
3.08k
  case epsonV1:
287
3.08k
    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
288
3.08k
      "Parsing Olympus/Sanyo/Epson maker note v1...");
289
290
    /* The number of entries is at position 8. */
291
3.08k
    if (buf[o2 + 6] == 1)
292
172
      n->order = EXIF_BYTE_ORDER_INTEL;
293
2.91k
    else if (buf[o2 + 6 + 1] == 1)
294
33
      n->order = EXIF_BYTE_ORDER_MOTOROLA;
295
3.08k
    o2 += 8;
296
3.08k
    c = exif_get_short (buf + o2, n->order);
297
3.08k
    if ((!(c & 0xFF)) && (c > 0x500)) {
298
663
      if (n->order == EXIF_BYTE_ORDER_INTEL) {
299
629
        n->order = EXIF_BYTE_ORDER_MOTOROLA;
300
629
      } else {
301
34
        n->order = EXIF_BYTE_ORDER_INTEL;
302
34
      }
303
663
    }
304
3.08k
    break;
305
306
451
  case olympusV2:
307
    /* Olympus S760, S770 */
308
451
    datao = o2;
309
451
    o2 += 8;
310
451
    if (CHECKOVERFLOW(o2,buf_size,4)) return;
311
449
    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
312
449
      "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
313
449
      buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
314
315
449
    if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
316
2
      n->order = EXIF_BYTE_ORDER_INTEL;
317
447
    else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
318
1
      n->order = EXIF_BYTE_ORDER_MOTOROLA;
319
320
    /* The number of entries is at position 8+4. */
321
449
    o2 += 4;
322
449
    break;
323
324
60
  case nikonV1:
325
60
    o2 += 6;
326
60
    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
327
60
      "Parsing Nikon maker note v1 (0x%02x, %02x, %02x, "
328
60
      "%02x)...",
329
60
      buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
330
331
    /* Skip version number */
332
60
    o2 += 1;
333
334
    /* Skip an unknown byte (00 or 0A). */
335
60
    o2 += 1;
336
337
60
    base = MNOTE_NIKON1_TAG_BASE;
338
    /* Fix endianness, if needed */
339
60
    c = exif_get_short (buf + o2, n->order);
340
60
    if ((!(c & 0xFF)) && (c > 0x500)) {
341
8
      if (n->order == EXIF_BYTE_ORDER_INTEL) {
342
4
        n->order = EXIF_BYTE_ORDER_MOTOROLA;
343
4
      } else {
344
4
        n->order = EXIF_BYTE_ORDER_INTEL;
345
4
      }
346
8
    }
347
60
    break;
348
349
114
  case nikonV2:
350
114
    o2 += 6;
351
114
    if (CHECKOVERFLOW(o2,buf_size,12)) return;
352
110
    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
353
110
      "Parsing Nikon maker note v2 (0x%02x, %02x, %02x, "
354
110
      "%02x, %02x, %02x, %02x, %02x)...",
355
110
      buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
356
110
      buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
357
358
    /* Skip version number */
359
110
    o2 += 1;
360
361
    /* Skip an unknown byte (00 or 0A). */
362
110
    o2 += 1;
363
364
    /* Skip 2 unknown bytes (00 00). */
365
110
    o2 += 2;
366
367
    /*
368
     * Byte order. From here the data offset
369
     * gets calculated.
370
     */
371
110
    datao = o2;
372
110
    if (!strncmp ((char *)&buf[o2], "II", 2))
373
59
      n->order = EXIF_BYTE_ORDER_INTEL;
374
51
    else if (!strncmp ((char *)&buf[o2], "MM", 2))
375
19
      n->order = EXIF_BYTE_ORDER_MOTOROLA;
376
32
    else {
377
32
      exif_log (en->log, EXIF_LOG_CODE_DEBUG,
378
32
        "ExifMnoteDataOlympus", "Unknown "
379
32
        "byte order '%c%c'", buf[o2],
380
32
        buf[o2 + 1]);
381
32
      return;
382
32
    }
383
78
    o2 += 2;
384
385
    /* Skip 2 unknown bytes (00 2A). */
386
78
    o2 += 2;
387
388
    /* Go to where the number of entries is. */
389
78
    if (CHECKOVERFLOW(o2,buf_size,exif_get_long (buf + o2, n->order))) return;
390
18
    o2 = datao + exif_get_long (buf + o2, n->order);
391
18
    break;
392
393
16
  case nikonV0:
394
16
    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
395
16
      "Parsing Nikon maker note v0 (0x%02x, %02x, %02x, "
396
16
      "%02x, %02x, %02x, %02x, %02x)...",
397
16
      buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3], 
398
16
      buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
399
    /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
400
16
    n->order = EXIF_BYTE_ORDER_MOTOROLA;
401
16
    break;
402
403
30
  default:
404
30
    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
405
30
      "Unknown Olympus variant %i.", n->version);
406
30
    return;
407
3.75k
  }
408
409
  /* Sanity check the offset */
410
3.63k
  if (CHECKOVERFLOW(o2,buf_size,2)) {
411
33
    exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
412
33
        "ExifMnoteOlympus", "Short MakerNote");
413
33
    return;
414
33
  }
415
416
  /* Read the number of tags */
417
3.59k
  c = exif_get_short (buf + o2, n->order);
418
3.59k
  o2 += 2;
419
420
  /* Just use an arbitrary max tag limit here to avoid needing to much memory or time. There are 150 named tags currently.
421
   * The format allows specifying the same range of memory as often as it can, so this multiplies quickly. */
422
3.59k
  if (c > 300) {
423
26
    exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Too much tags (%d) in Olympus MakerNote", c);
424
26
    return;
425
26
  }
426
427
  /* Remove any old entries */
428
3.57k
  exif_mnote_data_olympus_clear (n);
429
430
  /* Reserve enough space for all the possible MakerNote tags */
431
3.57k
  n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
432
3.57k
  if (!n->entries) {
433
0
    EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
434
0
    return;
435
0
  }
436
437
  /* Parse all c entries, storing ones that are successfully parsed */
438
3.57k
  tcount = 0;
439
102k
  for (i = c, o = o2; i; --i, o += 12) {
440
102k
    size_t s;
441
102k
    memset(&n->entries[tcount], 0, sizeof(MnoteOlympusEntry));
442
102k
    if (CHECKOVERFLOW(o, buf_size, 12)) {
443
2.97k
      exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
444
2.97k
          "ExifMnoteOlympus", "Short MakerNote");
445
2.97k
      break;
446
2.97k
    }
447
448
99.3k
      n->entries[tcount].tag        = exif_get_short (buf + o, n->order) + base;
449
99.3k
      n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
450
99.3k
      n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
451
99.3k
      n->entries[tcount].order      = n->order;
452
453
99.3k
      exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
454
99.3k
          "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
455
99.3k
          mnote_olympus_tag_get_name (n->entries[tcount].tag));
456
/*      exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
457
          "0x%x %d %ld*(%d)",
458
        n->entries[tcount].tag,
459
        n->entries[tcount].format,
460
        n->entries[tcount].components,
461
        (int)exif_format_get_size(n->entries[tcount].format)); */
462
463
      /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
464
       * we will check the buffer sizes closer later. */
465
99.3k
      if (exif_format_get_size (n->entries[tcount].format) &&
466
50.7k
    buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
467
99.3k
      ) {
468
5.16k
    exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
469
5.16k
    continue;
470
5.16k
      }
471
      /*
472
       * Size? If bigger than 4 bytes, the actual data is not
473
       * in the entry but somewhere else (offset).
474
       */
475
94.2k
      s = exif_format_get_size (n->entries[tcount].format) *
476
94.2k
             n->entries[tcount].components;
477
94.2k
    n->entries[tcount].size = s;
478
94.2k
    if (s) {
479
37.8k
      size_t dataofs = o + 8;
480
37.8k
      if (s > 4) {
481
        /* The data in this case is merely a pointer */
482
19.4k
        dataofs = exif_get_long (buf + dataofs, n->order) + datao;
483
#ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
484
        /* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
485
         * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
486
         * tag in its MakerNote. The offset is actually the absolute
487
         * position in the file instead of the position within the IFD.
488
         */
489
          if (dataofs > (buf_size - s) && n->version == sanyoV1) {
490
          /* fix pointer */
491
          dataofs -= datao + 6;
492
          exif_log (en->log, EXIF_LOG_CODE_DEBUG,
493
              "ExifMnoteOlympus",
494
              "Inconsistent thumbnail tag offset; attempting to recover");
495
          }
496
#endif
497
19.4k
      }
498
37.8k
      if (CHECKOVERFLOW(dataofs, buf_size, s)) {
499
2.36k
        exif_log (en->log, EXIF_LOG_CODE_DEBUG,
500
2.36k
            "ExifMnoteOlympus",
501
2.36k
            "Tag data past end of buffer (%u > %u)",
502
2.36k
            (unsigned)(dataofs + s), buf_size);
503
2.36k
        continue;
504
2.36k
      }
505
506
35.4k
      n->entries[tcount].data = exif_mem_alloc (en->mem, s);
507
35.4k
      if (!n->entries[tcount].data) {
508
0
        EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
509
0
        continue;
510
0
      }
511
35.4k
      memcpy (n->entries[tcount].data, buf + dataofs, s);
512
35.4k
    }
513
514
    /* Tag was successfully parsed */
515
91.8k
    ++tcount;
516
91.8k
  }
517
  /* Store the count of successfully parsed tags */
518
3.57k
  n->count = tcount;
519
3.57k
}
520
521
static unsigned int
522
exif_mnote_data_olympus_count (ExifMnoteData *n)
523
3.76k
{
524
3.76k
  return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
525
3.76k
}
526
527
static unsigned int
528
exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
529
0
{
530
0
  ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
531
532
0
  if (!note) return 0;
533
0
  if (note->count <= n) return 0;
534
0
  return note->entries[n].tag;
535
0
}
536
537
static const char *
538
exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
539
53.0k
{
540
53.0k
  ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
541
542
53.0k
  if (!n) return NULL;
543
53.0k
  if (i >= n->count) return NULL;
544
53.0k
  return mnote_olympus_tag_get_name (n->entries[i].tag);
545
53.0k
}
546
547
static const char *
548
exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
549
52.0k
{
550
52.0k
  ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
551
  
552
52.0k
  if (!n) return NULL;
553
52.0k
  if (i >= n->count) return NULL;
554
52.0k
        return mnote_olympus_tag_get_title (n->entries[i].tag);
555
52.0k
}
556
557
static const char *
558
exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
559
52.0k
{
560
52.0k
  ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
561
  
562
52.0k
  if (!n) return NULL;
563
52.0k
  if (i >= n->count) return NULL;
564
52.0k
        return mnote_olympus_tag_get_description (n->entries[i].tag);
565
52.0k
}
566
567
static void
568
exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
569
3.76k
{
570
3.76k
  ExifByteOrder o_orig;
571
3.76k
  ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
572
3.76k
  unsigned int i;
573
574
3.76k
  if (!n) return;
575
576
3.76k
  o_orig = n->order;
577
3.76k
  n->order = o;
578
3.76k
  for (i = 0; i < n->count; i++) {
579
0
    if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
580
0
      continue;
581
0
    n->entries[i].order = o;
582
0
    exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
583
0
        n->entries[i].components, o_orig, o);
584
0
  }
585
3.76k
}
586
587
static void
588
exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
589
3.76k
{
590
3.76k
  if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
591
3.76k
}
592
593
static enum OlympusVersion
594
exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
595
    unsigned int buf_size)
596
10.5k
{
597
  /* Olympus, Nikon, Sanyo, Epson */
598
10.5k
  if (buf_size >= 8) {
599
    /* Match the terminating NUL character, too */
600
10.3k
    if (!memcmp (buf, "OLYMPUS", 8))
601
908
         return olympusV2;
602
9.44k
    else if (!memcmp (buf, "OLYMP", 6))
603
2.44k
         return olympusV1;
604
6.99k
    else if (!memcmp (buf, "SANYO", 6))
605
2.48k
         return sanyoV1;
606
4.51k
    else if (!memcmp (buf, "EPSON", 6))
607
1.29k
         return epsonV1;
608
3.21k
    else if (!memcmp (buf, "Nikon", 6)) {
609
345
      switch (buf[6]) {
610
123
        case 1:  return nikonV1;
611
214
        case 2:  return nikonV2;
612
8
        default: return 0; /* Unrecognized Nikon variant */
613
345
      }
614
345
    }
615
10.3k
  }
616
617
  /* Another variant of Nikon */
618
3.08k
  if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) {
619
456
    return nikonV0;
620
456
  }
621
622
2.62k
  return unrecognized;
623
3.08k
}
624
625
int
626
exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e)
627
6.80k
{
628
6.80k
  int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size);
629
630
6.80k
  if (variant == nikonV0) {
631
    /* This variant needs some extra checking with the Make */
632
440
    char value[5];
633
440
    ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
634
440
    variant = unrecognized;
635
636
440
    if (em) {
637
58
      const char *v = exif_entry_get_value (em, value, sizeof(value));
638
58
      if (v && (!strncmp (v, "Nikon", sizeof(value)) || 
639
58
            !strncmp (v, "NIKON", sizeof(value)) ))
640
        /* When saved, this variant will be written out like the
641
         * alternative nikonV2 form above instead
642
         */
643
0
        variant = nikonV0;
644
58
    }
645
440
  }
646
647
6.80k
  return variant;
648
6.80k
}
649
650
651
ExifMnoteData *
652
exif_mnote_data_olympus_new (ExifMem *mem)
653
3.76k
{
654
3.76k
  ExifMnoteData *d;
655
656
3.76k
  if (!mem) return NULL;
657
  
658
3.76k
  d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
659
3.76k
  if (!d) return NULL;
660
661
3.76k
  exif_mnote_data_construct (d, mem);
662
663
  /* Set up function pointers */
664
3.76k
  d->methods.free            = exif_mnote_data_olympus_free;
665
3.76k
  d->methods.set_byte_order  = exif_mnote_data_olympus_set_byte_order;
666
3.76k
  d->methods.set_offset      = exif_mnote_data_olympus_set_offset;
667
3.76k
  d->methods.load            = exif_mnote_data_olympus_load;
668
3.76k
  d->methods.save            = exif_mnote_data_olympus_save;
669
3.76k
  d->methods.count           = exif_mnote_data_olympus_count;
670
3.76k
  d->methods.get_id          = exif_mnote_data_olympus_get_id;
671
3.76k
  d->methods.get_name        = exif_mnote_data_olympus_get_name;
672
3.76k
  d->methods.get_title       = exif_mnote_data_olympus_get_title;
673
3.76k
  d->methods.get_description = exif_mnote_data_olympus_get_description;
674
3.76k
  d->methods.get_value       = exif_mnote_data_olympus_get_value;
675
676
3.76k
  return d;
677
3.76k
}