resetting manifest requested domain to floor
[platform/upstream/libexif.git] / libexif / samsung / exif-mnote-data-samsung.c
1 /*
2  * libexif
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Sangchul Lee <sc11.lee@samsung.com>
7  *
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)
11  * any later version.
12  *
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.
17  *
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
21  *
22  */
23
24
25 #include "config.h"
26 #include "exif-mnote-data-samsung.h"
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31
32 #include <libexif/exif-byte-order.h>
33 #include <libexif/exif-utils.h>
34
35 #define DEBUG
36
37 static void exif_mnote_data_samsung_clear (ExifMnoteDataSamsung *mds)
38 {
39         ExifMnoteData *md = (ExifMnoteData *) mds;
40         unsigned int i;
41
42         if (!mds) return;
43
44         if (mds->entries) {
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;
49                         }
50                 exif_mem_free (md->mem, mds->entries);
51                 mds->entries = NULL;
52                 mds->count = 0;
53         }
54 }
55
56 static void exif_mnote_data_samsung_free (ExifMnoteData *md)
57 {
58         if (!md) return;
59
60         exif_mnote_data_samsung_clear ((ExifMnoteDataSamsung *) md);
61 }
62
63 static char *exif_mnote_data_samsung_get_value (ExifMnoteData *md, unsigned int i, char *val, unsigned int maxlen)
64 {
65         ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
66
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);
73 }
74
75
76 /**
77  * @brief save the MnoteData from md to buf
78  *
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
82  */
83 static void exif_mnote_data_samsung_save (ExifMnoteData *md,
84                 unsigned char **buf, unsigned int *buf_size)
85 {
86         ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
87         size_t i, off, val_size, doff;
88         unsigned char *new_buf;
89         size_t new_buf_size;
90
91         if (!mds || !buf || !buf_size) return;
92
93         /*
94          * Allocate enough memory for all entries and the number of entries.
95          */
96         *buf_size = 2 + mds->count * 12 + 4;
97         *buf = exif_mem_alloc (md->mem, *buf_size);
98         if (!*buf) {
99                 EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteDataSamsung", *buf_size);
100                 return;
101         }
102
103         /* Save the number of entries */
104         exif_set_short(*buf, mds->order, (ExifShort) mds->count);
105
106         /* Save entries */
107         for (i = 0; i < mds->count; i++) {
108                 off = 2 + i * 12;
109
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);
113                 off += 8;
114                 val_size = exif_format_get_size (mds->entries[i].format) * mds->entries[i].components;
115
116                 if (val_size > 65536) {
117                         /* Corrupt data: EXIF data size is limited to the
118                          * maximum size of a JPEG segment (64 kb).
119                          */
120                         continue;
121                 }
122                 if (val_size > 4) {
123                         new_buf_size = *buf_size + val_size;
124                         if(val_size & 1)
125                                 new_buf_size += 1;
126
127                         new_buf = exif_mem_realloc (md->mem, *buf, sizeof (char) * new_buf_size);
128                         if (!new_buf) {
129                                 EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteDataSamsung", new_buf_size);
130                                 return;
131                         }
132                         doff = *buf_size;
133                         *buf = new_buf;
134                         *buf_size = new_buf_size;
135
136                         if(val_size & 1)
137                                 *(*buf + *buf_size - 1) = '\0';
138
139                         //exif_set_long (*buf + off, mds->order, mds->offset + doff);
140                         exif_set_long (*buf + off, mds->order, doff);
141                 } else
142                         doff = off;
143
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 );
151                 } else {
152                         /* Most certainly damaged input file */
153                         memset (*buf + doff, 0, val_size);
154                 }
155         }
156 }
157
158 static void exif_mnote_data_samsung_load (ExifMnoteData *md,
159                               const unsigned char *buf, unsigned int buf_size)
160 {
161         ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
162         ExifShort entry_count;
163         size_t i, tcount, off, datao;
164         size_t val_size;
165
166         if (!mds || !buf || !buf_size) {
167                 exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
168                           "ExifMnoteDataSamsung", "Short MakerNote");
169                 return;
170         }
171         datao = mds->offset; /* Start of interesting data */
172         datao += 6;
173
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");
177                 return;
178         }
179
180         /* Read the number of Makernote Entries */
181         entry_count = exif_get_short (buf + datao, mds->order);
182
183         datao += 2;
184
185         /* Remove any old entries */
186         exif_mnote_data_samsung_clear (mds);
187
188         /* Reserve enough space for all the possible MakerNote tags */
189         mds->entries = exif_mem_alloc (md->mem, sizeof (MnoteSamsungEntry) * entry_count);
190         if (!mds->entries) {
191                 EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteSamsung", sizeof (MnoteSamsungEntry) * entry_count);
192                 return;
193         }
194
195         /* Parse all entries */
196         tcount = 0;
197
198         for (i = entry_count, off = datao; i; --i, off += 12) {
199
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");
203                         break;
204                 }
205
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;
210
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));
212
213                 val_size = exif_format_get_size (mds->entries[tcount].format) * mds->entries[tcount].components;
214                 mds->entries[tcount].size = val_size;
215
216
217                 if (val_size) {
218                         size_t dataofs = off + 8;
219                         if (val_size > 4)
220                                 dataofs = exif_get_long (buf + dataofs, mds->order) + datao - 2; // 2bytes for No. of IFD Entry field size
221
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);
224                                 continue;
225                         }
226
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);
230                                 continue;
231                         }
232                         memcpy (mds->entries[tcount].data, buf + dataofs, val_size);
233
234                 }else{
235                         exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteSamsung", "Invalid zero-length tag size");
236                         continue;
237                 }
238
239                 /* Tag was successfully parsed */
240                 ++tcount;
241         }
242         /* Store the count of successfully parsed tags */
243         mds->count = tcount;
244 }
245
246 static unsigned int exif_mnote_data_samsung_count (ExifMnoteData *md)
247 {
248         return md ? ((ExifMnoteDataSamsung *) md)->count : 0;
249 }
250
251 static unsigned int exif_mnote_data_samsung_get_id (ExifMnoteData *md, unsigned int n)
252 {
253         ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
254
255         if (!mds) return 0;
256         if (mds->count <= n) return 0;
257         return mds->entries[n].tag;
258 }
259
260 static const char *exif_mnote_data_samsung_get_name (ExifMnoteData *md, unsigned int i)
261 {
262         ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
263
264         if (!mds) return NULL;
265         if (i >= mds->count) return NULL;
266         return mnote_samsung_tag_get_name (mds->entries[i].tag);
267 }
268
269 static const char *
270 exif_mnote_data_samsung_get_title (ExifMnoteData *note, unsigned int i)
271 {
272         ExifMnoteDataSamsung *dc = (ExifMnoteDataSamsung *) note;
273         unsigned int m, s;
274
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);
279 }
280
281 static const char *
282 exif_mnote_data_samsung_get_description (ExifMnoteData *note, unsigned int i)
283 {
284         ExifMnoteDataSamsung *dc = (ExifMnoteDataSamsung *) note;
285         unsigned int m;
286
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);
291 }
292
293 int
294 exif_mnote_data_samsung_identify (const ExifData *ed, const ExifEntry *e)
295 {
296         char value[8];
297         ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
298         if (!em) 
299                 return 0;
300         return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "samsung");
301 }
302
303 static void exif_mnote_data_samsung_set_byte_order (ExifMnoteData *md, ExifByteOrder o)
304 {
305         ExifByteOrder o_orig;
306         ExifMnoteDataSamsung *mds = (ExifMnoteDataSamsung *) md;
307         unsigned int i;
308
309         if (!mds) return;
310
311         o_orig = mds->order;
312         mds->order = o;
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);
316         }
317 }
318
319 static void exif_mnote_data_samsung_set_offset (ExifMnoteData *md, unsigned int o)
320 {
321         if (md) ((ExifMnoteDataSamsung *) md)->offset = o;
322 }
323
324 ExifMnoteData *exif_mnote_data_samsung_new (ExifMem *mem)
325 {
326         ExifMnoteData *md;
327
328         if (!mem) return NULL;
329
330         md = exif_mem_alloc (mem, sizeof (ExifMnoteDataSamsung));
331         if (!md) return NULL;
332
333         exif_mnote_data_construct (md, mem);
334
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;
345
346         return md;
347 }