4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Sangchul Lee <sc11.lee@samsung.com>
8 * This library is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by the
10 * Free Software Foundation; either version 2.1 of the License, or (at your option)
13 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 * License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software Foundation, Inc., 51
20 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "exif-mnote-data-samsung.h"
32 #include <libexif/exif-byte-order.h>
33 #include <libexif/exif-utils.h>
37 static void exif_mnote_data_samsung_clear (ExifMnoteDataSamsung *mds)
39 ExifMnoteData *md = (ExifMnoteData *) mds;
45 for (i = 0; i < mds->count; i++)
46 if (mds->entries[i].data) {
47 exif_mem_free (md->mem, mds->entries[i].data);
48 mds->entries[i].data = NULL;
50 exif_mem_free (md->mem, mds->entries);
56 static void exif_mnote_data_samsung_free (ExifMnoteData *md)
60 exif_mnote_data_samsung_clear ((ExifMnoteDataSamsung *) md);
63 static char *exif_mnote_data_samsung_get_value (ExifMnoteData *md, unsigned int i, char *val, unsigned int maxlen)
65 ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
67 if (!md || !val) return NULL;
68 if (i > mds->count -1) return NULL;
69 exif_log (md->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataSamsung",
70 "Querying value for tag '%s'...",
71 mnote_samsung_tag_get_name (mds->entries[i].tag));
72 return mnote_samsung_entry_get_value (&mds->entries[i], val, maxlen);
77 * @brief save the MnoteData from md to buf
79 * @param md extract the data from this structure
80 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
81 * @param buf_size the size of the buffer
83 static void exif_mnote_data_samsung_save (ExifMnoteData *md,
84 unsigned char **buf, unsigned int *buf_size)
86 ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
87 size_t i, off, val_size, doff;
88 unsigned char *new_buf;
91 if (!mds || !buf || !buf_size) return;
94 * Allocate enough memory for all entries and the number of entries.
96 *buf_size = 2 + mds->count * 12 + 4;
97 *buf = exif_mem_alloc (md->mem, *buf_size);
99 EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteDataSamsung", *buf_size);
103 /* Save the number of entries */
104 exif_set_short(*buf, mds->order, (ExifShort) mds->count);
107 for (i = 0; i < mds->count; i++) {
110 exif_set_short (*buf + off + 0, mds->order, (ExifShort) mds->entries[i].tag);
111 exif_set_short (*buf + off + 2, mds->order, (ExifShort) mds->entries[i].format);
112 exif_set_long (*buf + off + 4, mds->order, mds->entries[i].components);
114 val_size = exif_format_get_size (mds->entries[i].format) * mds->entries[i].components;
116 if (val_size > 65536) {
117 /* Corrupt data: EXIF data size is limited to the
118 * maximum size of a JPEG segment (64 kb).
123 new_buf_size = *buf_size + val_size;
127 new_buf = exif_mem_realloc (md->mem, *buf, sizeof (char) * new_buf_size);
129 EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteDataSamsung", new_buf_size);
134 *buf_size = new_buf_size;
137 *(*buf + *buf_size - 1) = '\0';
139 //exif_set_long (*buf + off, mds->order, mds->offset + doff);
140 exif_set_long (*buf + off, mds->order, doff);
144 /* Write the data. */
145 if (mds->entries[i].data) {
146 memcpy (*buf + doff, mds->entries[i].data, val_size);
147 //fprintf(stdout, "in exif_mnote_data_samsung_save (write the data to buffer)\n");
148 //fprintf(stdout, " mds->entries[%d].data size : %d \n",i, val_size );
149 //fprintf(stdout, " mds->entries[%d].data : %s \n",i, mds->entries[i].data );
150 //fprintf(stdout, " buff + %d : %s \n",doff, buf+doff );
152 /* Most certainly damaged input file */
153 memset (*buf + doff, 0, val_size);
158 static void exif_mnote_data_samsung_load (ExifMnoteData *md,
159 const unsigned char *buf, unsigned int buf_size)
161 ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
162 ExifShort entry_count;
163 size_t i, tcount, off, datao;
166 if (!mds || !buf || !buf_size) {
167 exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
168 "ExifMnoteDataSamsung", "Short MakerNote");
171 datao = mds->offset; /* Start of interesting data */
174 if ((datao + 2 < datao) || (datao + 2 < 2) || (datao + 2 > buf_size)) {
175 exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
176 "ExifMnoteDataSamsung", "Short MakerNote");
180 /* Read the number of Makernote Entries */
181 entry_count = exif_get_short (buf + datao, mds->order);
185 /* Remove any old entries */
186 exif_mnote_data_samsung_clear (mds);
188 /* Reserve enough space for all the possible MakerNote tags */
189 mds->entries = exif_mem_alloc (md->mem, sizeof (MnoteSamsungEntry) * entry_count);
191 EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteSamsung", sizeof (MnoteSamsungEntry) * entry_count);
195 /* Parse all entries */
198 for (i = entry_count, off = datao; i; --i, off += 12) {
200 if ((off + 12 < off) || (off + 12 < 12) || (off + 12 > buf_size)) {
201 exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
202 "ExifMnoteSamsung", "Short MakerNote");
206 mds->entries[tcount].tag = exif_get_short (buf + off, mds->order);
207 mds->entries[tcount].format = exif_get_short (buf + off + 2, mds->order);
208 mds->entries[tcount].components = exif_get_long (buf + off + 4, mds->order);
209 mds->entries[tcount].order = mds->order;
211 exif_log (md->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteSamsung","Loading entry 0x%x ('%s')...", mds->entries[tcount].tag, mnote_samsung_tag_get_name (mds->entries[tcount].tag));
213 val_size = exif_format_get_size (mds->entries[tcount].format) * mds->entries[tcount].components;
214 mds->entries[tcount].size = val_size;
218 size_t dataofs = off + 8;
220 dataofs = exif_get_long (buf + dataofs, mds->order) + datao - 2; // 2bytes for No. of IFD Entry field size
222 if ((dataofs + val_size < dataofs) || (dataofs + val_size < val_size) || (dataofs + val_size > buf_size)) {
223 exif_log (md->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteSamsung", "Tag data past end of buffer (%u > %u)", dataofs + val_size, buf_size);
227 mds->entries[tcount].data = exif_mem_alloc (md->mem, val_size);
228 if (!mds->entries[tcount].data) {
229 EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteSamsung", val_size);
232 memcpy (mds->entries[tcount].data, buf + dataofs, val_size);
235 exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteSamsung", "Invalid zero-length tag size");
239 /* Tag was successfully parsed */
242 /* Store the count of successfully parsed tags */
246 static unsigned int exif_mnote_data_samsung_count (ExifMnoteData *md)
248 return md ? ((ExifMnoteDataSamsung *) md)->count : 0;
251 static unsigned int exif_mnote_data_samsung_get_id (ExifMnoteData *md, unsigned int n)
253 ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
256 if (mds->count <= n) return 0;
257 return mds->entries[n].tag;
260 static const char *exif_mnote_data_samsung_get_name (ExifMnoteData *md, unsigned int i)
262 ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
264 if (!mds) return NULL;
265 if (i >= mds->count) return NULL;
266 return mnote_samsung_tag_get_name (mds->entries[i].tag);
270 exif_mnote_data_samsung_get_title (ExifMnoteData *note, unsigned int i)
272 ExifMnoteDataSamsung *dc = (ExifMnoteDataSamsung *) note;
275 if (!dc) return NULL;
276 exif_mnote_data_canon_get_tags (dc, i, &m, &s);
277 if (m >= dc->count) return NULL;
278 return mnote_samsung_tag_get_title_sub (dc->entries[m].tag, s, dc->options);
282 exif_mnote_data_samsung_get_description (ExifMnoteData *note, unsigned int i)
284 ExifMnoteDataSamsung *dc = (ExifMnoteDataSamsung *) note;
287 if (!dc) return NULL;
288 exif_mnote_data_canon_get_tags (dc, i, &m, NULL);
289 if (m >= dc->count) return NULL;
290 return mnote_samsung_tag_get_description (dc->entries[m].tag);
294 exif_mnote_data_samsung_identify (const ExifData *ed, const ExifEntry *e)
297 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
300 return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "samsung");
303 static void exif_mnote_data_samsung_set_byte_order (ExifMnoteData *md, ExifByteOrder o)
305 ExifByteOrder o_orig;
306 ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
313 for (i = 0; i < mds->count; i++) {
314 mds->entries[i].order = o;
315 exif_array_set_byte_order (mds->entries[i].format, mds->entries[i].data, mds->entries[i].components, o_orig, o);
319 static void exif_mnote_data_samsung_set_offset (ExifMnoteData *md, unsigned int o)
321 if (md) ((ExifMnoteDataSamsung *) md)->offset = o;
324 ExifMnoteData *exif_mnote_data_samsung_new (ExifMem *mem)
328 if (!mem) return NULL;
330 md = exif_mem_alloc (mem, sizeof (ExifMnoteDataSamsung));
331 if (!md) return NULL;
333 exif_mnote_data_construct (md, mem);
335 /* Set up function pointers */
336 md->methods.free = exif_mnote_data_samsung_free;
337 md->methods.set_byte_order = exif_mnote_data_samsung_set_byte_order;
338 md->methods.set_offset = exif_mnote_data_samsung_set_offset;
339 md->methods.load = exif_mnote_data_samsung_load;
340 md->methods.save = exif_mnote_data_samsung_save;
341 md->methods.count = exif_mnote_data_samsung_count;
342 md->methods.get_id = exif_mnote_data_samsung_get_id;
343 md->methods.get_name = exif_mnote_data_samsung_get_name;
344 md->methods.get_value = exif_mnote_data_samsung_get_value;