00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include "exif-mnote-data-canon.h"
00024
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028
00029 #include <libexif/exif-byte-order.h>
00030 #include <libexif/exif-utils.h>
00031 #include <libexif/exif-data.h>
00032
00033 #define DEBUG
00034
00035 static void
00036 exif_mnote_data_canon_clear (ExifMnoteDataCanon *n)
00037 {
00038 ExifMnoteData *d = (ExifMnoteData *) n;
00039 unsigned int i;
00040
00041 if (!n) return;
00042
00043 if (n->entries) {
00044 for (i = 0; i < n->count; i++)
00045 if (n->entries[i].data) {
00046 exif_mem_free (d->mem, n->entries[i].data);
00047 n->entries[i].data = NULL;
00048 }
00049 exif_mem_free (d->mem, n->entries);
00050 n->entries = NULL;
00051 n->count = 0;
00052 }
00053 }
00054
00055 static void
00056 exif_mnote_data_canon_free (ExifMnoteData *n)
00057 {
00058 if (!n) return;
00059
00060 exif_mnote_data_canon_clear ((ExifMnoteDataCanon *) n);
00061 }
00062
00063 static void
00064 exif_mnote_data_canon_get_tags (ExifMnoteDataCanon *dc, unsigned int n,
00065 unsigned int *m, unsigned int *s)
00066 {
00067 unsigned int from = 0, to;
00068
00069 if (!dc || !m) return;
00070 for (*m = 0; *m < dc->count; (*m)++) {
00071 to = from + mnote_canon_entry_count_values (&dc->entries[*m]);
00072 if (to > n) {
00073 if (s) *s = n - from;
00074 break;
00075 }
00076 from = to;
00077 }
00078 }
00079
00080 static char *
00081 exif_mnote_data_canon_get_value (ExifMnoteData *note, unsigned int n, char *val, unsigned int maxlen)
00082 {
00083 ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
00084 unsigned int m, s;
00085
00086 if (!dc) return NULL;
00087 exif_mnote_data_canon_get_tags (dc, n, &m, &s);
00088 if (m >= dc->count) return NULL;
00089 return mnote_canon_entry_get_value (&dc->entries[m], s, val, maxlen);
00090 }
00091
00092 static void
00093 exif_mnote_data_canon_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
00094 {
00095 ExifByteOrder o_orig;
00096 ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) d;
00097 unsigned int i;
00098
00099 if (!n) return;
00100
00101 o_orig = n->order;
00102 n->order = o;
00103 for (i = 0; i < n->count; i++) {
00104 n->entries[i].order = o;
00105 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
00106 n->entries[i].components, o_orig, o);
00107 }
00108 }
00109
00110 static void
00111 exif_mnote_data_canon_set_offset (ExifMnoteData *n, unsigned int o)
00112 {
00113 if (n) ((ExifMnoteDataCanon *) n)->offset = o;
00114 }
00115
00116 static void
00117 exif_mnote_data_canon_save (ExifMnoteData *ne,
00118 unsigned char **buf, unsigned int *buf_size)
00119 {
00120 ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
00121 size_t i, o, s, doff;
00122 unsigned char *t;
00123 size_t ts;
00124
00125 if (!n || !buf || !buf_size) return;
00126
00127
00128
00129
00130
00131 *buf_size = 2 + n->count * 12 + 4;
00132 *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
00133 if (!*buf) {
00134 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size);
00135 return;
00136 }
00137
00138
00139 exif_set_short (*buf, n->order, (ExifShort) n->count);
00140
00141
00142 for (i = 0; i < n->count; i++) {
00143 o = 2 + i * 12;
00144 exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
00145 exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
00146 exif_set_long (*buf + o + 4, n->order,
00147 n->entries[i].components);
00148 o += 8;
00149 s = exif_format_get_size (n->entries[i].format) *
00150 n->entries[i].components;
00151 if (s > 65536) {
00152
00153
00154
00155 continue;
00156 }
00157 if (s > 4) {
00158 ts = *buf_size + s;
00159
00160
00161 if (s & 1) ts += 1;
00162 t = exif_mem_realloc (ne->mem, *buf,
00163 sizeof (char) * ts);
00164 if (!t) {
00165 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts);
00166 return;
00167 }
00168 *buf = t;
00169 *buf_size = ts;
00170 doff = *buf_size - s;
00171 if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
00172 exif_set_long (*buf + o, n->order, n->offset + doff);
00173 } else
00174 doff = o;
00175
00176
00177
00178
00179
00180 if (!n->entries[i].data) memset (*buf + doff, 0, s);
00181 else memcpy (*buf + doff, n->entries[i].data, s);
00182 if (s < 4) memset (*buf + doff + s, 0, (4 - s));
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 static void
00199 exif_mnote_data_canon_load (ExifMnoteData *ne,
00200 const unsigned char *buf, unsigned int buf_size)
00201 {
00202 ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
00203 ExifShort c;
00204 size_t i, tcount, o, datao;
00205
00206 if (!n || !buf || !buf_size) {
00207 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
00208 "ExifMnoteCanon", "Short MakerNote");
00209 return;
00210 }
00211 datao = 6 + n->offset;
00212 if ((datao + 2 < datao) || (datao + 2 < 2) || (datao + 2 > buf_size)) {
00213 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
00214 "ExifMnoteCanon", "Short MakerNote");
00215 return;
00216 }
00217
00218
00219 c = exif_get_short (buf + datao, n->order);
00220 datao += 2;
00221
00222
00223 exif_mnote_data_canon_clear (n);
00224
00225
00226 n->entries = exif_mem_alloc (ne->mem, sizeof (MnoteCanonEntry) * c);
00227 if (!n->entries) {
00228 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", sizeof (MnoteCanonEntry) * c);
00229 return;
00230 }
00231
00232
00233 tcount = 0;
00234 for (i = c, o = datao; i; --i, o += 12) {
00235 size_t s;
00236 if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
00237 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
00238 "ExifMnoteCanon", "Short MakerNote");
00239 break;
00240 }
00241
00242 n->entries[tcount].tag = exif_get_short (buf + o, n->order);
00243 n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
00244 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
00245 n->entries[tcount].order = n->order;
00246
00247 exif_log (ne->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteCanon",
00248 "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
00249 mnote_canon_tag_get_name (n->entries[tcount].tag));
00250
00251
00252
00253
00254
00255 s = exif_format_get_size (n->entries[tcount].format) *
00256 n->entries[tcount].components;
00257 n->entries[tcount].size = s;
00258 if (!s) {
00259 exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
00260 "ExifMnoteCanon",
00261 "Invalid zero-length tag size");
00262 continue;
00263
00264 } else {
00265 size_t dataofs = o + 8;
00266 if (s > 4) dataofs = exif_get_long (buf + dataofs, n->order) + 6;
00267 if ((dataofs + s < s) || (dataofs + s < dataofs) || (dataofs + s > buf_size)) {
00268 exif_log (ne->log, EXIF_LOG_CODE_DEBUG,
00269 "ExifMnoteCanon",
00270 "Tag data past end of buffer (%u > %u)",
00271 dataofs + s, buf_size);
00272 continue;
00273 }
00274
00275 n->entries[tcount].data = exif_mem_alloc (ne->mem, s);
00276 if (!n->entries[tcount].data) {
00277 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", s);
00278 continue;
00279 }
00280 memcpy (n->entries[tcount].data, buf + dataofs, s);
00281 }
00282
00283
00284 ++tcount;
00285 }
00286
00287 n->count = tcount;
00288 }
00289
00290 static unsigned int
00291 exif_mnote_data_canon_count (ExifMnoteData *n)
00292 {
00293 ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) n;
00294 unsigned int i, c;
00295
00296 for (i = c = 0; dc && (i < dc->count); i++)
00297 c += mnote_canon_entry_count_values (&dc->entries[i]);
00298 return c;
00299 }
00300
00301 static unsigned int
00302 exif_mnote_data_canon_get_id (ExifMnoteData *d, unsigned int i)
00303 {
00304 ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) d;
00305 unsigned int m;
00306
00307 if (!dc) return 0;
00308 exif_mnote_data_canon_get_tags (dc, i, &m, NULL);
00309 if (m >= dc->count) return 0;
00310 return dc->entries[m].tag;
00311 }
00312
00313 static const char *
00314 exif_mnote_data_canon_get_name (ExifMnoteData *note, unsigned int i)
00315 {
00316 ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
00317 unsigned int m, s;
00318
00319 if (!dc) return NULL;
00320 exif_mnote_data_canon_get_tags (dc, i, &m, &s);
00321 if (m >= dc->count) return NULL;
00322 return mnote_canon_tag_get_name_sub (dc->entries[m].tag, s, dc->options);
00323 }
00324
00325 static const char *
00326 exif_mnote_data_canon_get_title (ExifMnoteData *note, unsigned int i)
00327 {
00328 ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
00329 unsigned int m, s;
00330
00331 if (!dc) return NULL;
00332 exif_mnote_data_canon_get_tags (dc, i, &m, &s);
00333 if (m >= dc->count) return NULL;
00334 return mnote_canon_tag_get_title_sub (dc->entries[m].tag, s, dc->options);
00335 }
00336
00337 static const char *
00338 exif_mnote_data_canon_get_description (ExifMnoteData *note, unsigned int i)
00339 {
00340 ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
00341 unsigned int m;
00342
00343 if (!dc) return NULL;
00344 exif_mnote_data_canon_get_tags (dc, i, &m, NULL);
00345 if (m >= dc->count) return NULL;
00346 return mnote_canon_tag_get_description (dc->entries[m].tag);
00347 }
00348
00349 int
00350 exif_mnote_data_canon_identify (const ExifData *ed, const ExifEntry *e)
00351 {
00352 char value[8];
00353 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
00354 if (!em)
00355 return 0;
00356 return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon");
00357 }
00358
00359 ExifMnoteData *
00360 exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o)
00361 {
00362 ExifMnoteData *d;
00363 ExifMnoteDataCanon *dc;
00364
00365 if (!mem) return NULL;
00366
00367 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataCanon));
00368 if (!d)
00369 return NULL;
00370
00371 exif_mnote_data_construct (d, mem);
00372
00373
00374 d->methods.free = exif_mnote_data_canon_free;
00375 d->methods.set_byte_order = exif_mnote_data_canon_set_byte_order;
00376 d->methods.set_offset = exif_mnote_data_canon_set_offset;
00377 d->methods.load = exif_mnote_data_canon_load;
00378 d->methods.save = exif_mnote_data_canon_save;
00379 d->methods.count = exif_mnote_data_canon_count;
00380 d->methods.get_id = exif_mnote_data_canon_get_id;
00381 d->methods.get_name = exif_mnote_data_canon_get_name;
00382 d->methods.get_title = exif_mnote_data_canon_get_title;
00383 d->methods.get_description = exif_mnote_data_canon_get_description;
00384 d->methods.get_value = exif_mnote_data_canon_get_value;
00385
00386 dc = (ExifMnoteDataCanon*)d;
00387 dc->options = o;
00388 return d;
00389 }