• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* exif-mnote-data-apple.c
2  *
3  * Copyright (c) 2018 zhanwang-sky <zhanwang_sky@163.com>
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 
21 #include <config.h>
22 #include "exif-mnote-data-apple.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include <libexif/exif-data.h>
29 #include <libexif/exif-utils.h>
30 
31 static void
exif_mnote_data_apple_free(ExifMnoteData * md)32 exif_mnote_data_apple_free(ExifMnoteData *md) {
33     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
34     unsigned int i;
35 
36     /*printf("%s\n", __FUNCTION__);*/
37 
38     if (!d) {
39         return;
40     }
41 
42     if (d->entries) {
43         for (i = 0; i < d->count; i++) {
44             if (d->entries[i].data) {
45                 exif_mem_free(md->mem, d->entries[i].data);
46             }
47         }
48         exif_mem_free(md->mem, d->entries);
49         d->entries = NULL;
50         d->count = 0;
51     }
52 
53     return;
54 }
55 
56 static void
exif_mnote_data_apple_load(ExifMnoteData * md,const unsigned char * buf,unsigned int buf_size)57 exif_mnote_data_apple_load(ExifMnoteData *md, const unsigned char *buf, unsigned int buf_size) {
58     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
59     unsigned int tcount, i;
60     unsigned int dsize;
61     unsigned int ofs, dofs;
62 
63     /*printf("%s\n", __FUNCTION__);*/
64 
65     if (!d || !buf || (buf_size < 6 + 16)) {
66         exif_log(md->log, EXIF_LOG_CODE_CORRUPT_DATA,
67                  "ExifMnoteDataApple", "Short MakerNote");
68         return;
69     }
70 
71     /* Start of interesting data */
72     ofs = d->offset + 6;
73     if (ofs > buf_size - 16) {
74         exif_log(md->log, EXIF_LOG_CODE_CORRUPT_DATA,
75                  "ExifMnoteDataApple", "Short MakerNote");
76         return;
77     }
78 
79     if ((buf[ofs + 12] == 'M') && (buf[ofs + 13] == 'M')) {
80         d->order = EXIF_BYTE_ORDER_MOTOROLA;
81     } else if ((buf[ofs + 12] == 'I') && (buf[ofs + 13] == 'I')) {
82         d->order = EXIF_BYTE_ORDER_INTEL;
83     } else {
84         exif_log(md->log, EXIF_LOG_CODE_CORRUPT_DATA,
85                 "ExifMnoteDataApple", "Unrecognized byte order");
86         /*printf("%s(%d)\n", __FUNCTION__, __LINE__);*/
87         return;
88     }
89 
90     tcount = (unsigned int) exif_get_short(buf + ofs + 14, d->order);
91 
92     /* Sanity check the offset */
93     if (buf_size < d->offset + 6 + 16 + tcount * 12 + 4) {
94         exif_log(md->log, EXIF_LOG_CODE_CORRUPT_DATA,
95                  "ExifMnoteDataApple", "Short MakerNote");
96         /*printf("%s(%d)\n", __FUNCTION__, __LINE__);*/
97         return;
98     }
99 
100     /* printf("%s(%d): total %d tags\n", __FUNCTION__, __LINE__, tcount); */
101 
102     ofs += 16;
103 
104     exif_mnote_data_apple_free(md);
105 
106     /* Reserve enough space for all the possible MakerNote tags */
107     d->entries = exif_mem_alloc(md->mem, sizeof(MnoteAppleEntry) * tcount);
108     if (!d->entries) {
109         EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteApple", sizeof(MnoteAppleEntry) * tcount);
110         /*printf("%s(%d)\n", __FUNCTION__, __LINE__);*/
111         return;
112     }
113     memset(d->entries, 0, sizeof(MnoteAppleEntry) * tcount);
114 
115     for (i = 0; i < tcount; i++) {
116 	if (ofs + 12 > buf_size) {
117 		exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
118                                   "ExifMnoteApplet", "Tag size overflow detected (%u vs size %u)", ofs + 12, buf_size);
119 		break;
120 	}
121         d->entries[i].tag = exif_get_short(buf + ofs, d->order);
122         d->entries[i].format = exif_get_short(buf + ofs + 2, d->order);
123         d->entries[i].components = exif_get_long(buf + ofs + 4, d->order);
124         d->entries[i].order = d->order;
125 	if ((d->entries[i].components) && (buf_size / d->entries[i].components < exif_format_get_size(d->entries[i].format))) {
126 		exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
127                                   "ExifMnoteApplet", "Tag size overflow detected (components %lu vs size %u)", d->entries[i].components, buf_size);
128 		break;
129 	}
130         dsize = exif_format_get_size(d->entries[i].format) * d->entries[i].components;
131 	if ((dsize > 65536) || (dsize > buf_size)) {
132 		/* Corrupt data: EXIF data size is limited to the
133 		 * maximum size of a JPEG segment (64 kb).
134 		 */
135 		break;
136 	}
137         if (dsize > 4) {
138             dofs = d->offset + exif_get_long(buf + ofs + 8, d->order);
139         } else {
140             dofs = ofs + 8;
141         }
142 	if (dofs > buf_size) {
143 		exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
144                                   "ExifMnoteApplet", "Tag size overflow detected (%u vs size %u)", dofs, buf_size);
145 		continue;
146 	}
147         ofs += 12;
148         d->entries[i].data = exif_mem_alloc(md->mem, dsize);
149         if (!d->entries[i].data) {
150             EXIF_LOG_NO_MEMORY(md->log, "ExifMnoteApple", dsize);
151             continue;
152         }
153 	if (dofs + dsize > buf_size) {
154 		exif_log (md->log, EXIF_LOG_CODE_CORRUPT_DATA,
155                                   "ExifMnoteApplet", "Tag size overflow detected (%u vs size %u)", dofs + dsize, buf_size);
156 		continue;
157 	}
158         memcpy(d->entries[i].data, buf + dofs, dsize);
159         d->entries[i].size = dsize;
160     }
161     d->count = tcount;
162 
163     return;
164 }
165 
166 static void
exif_mnote_data_apple_set_offset(ExifMnoteData * md,unsigned int o)167 exif_mnote_data_apple_set_offset(ExifMnoteData *md, unsigned int o) {
168     /*printf("%s\n", __FUNCTION__);*/
169 
170     if (md) {
171         ((ExifMnoteDataApple *) md)->offset = o;
172     }
173 
174     return;
175 }
176 
177 static void
exif_mnote_data_apple_set_byte_order(ExifMnoteData * md,ExifByteOrder o)178 exif_mnote_data_apple_set_byte_order(ExifMnoteData *md , ExifByteOrder o) {
179     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
180     unsigned int i;
181 
182     /*printf("%s\n", __FUNCTION__);*/
183 
184     if (!d || d->order == o) {
185         return;
186     }
187 
188     for (i = 0; i < d->count; i++) {
189 	if (d->entries[i].components && (d->entries[i].size/d->entries[i].components < exif_format_get_size (d->entries[i].format)))
190 		continue;
191         exif_array_set_byte_order(d->entries[i].format, d->entries[i].data,
192                                   d->entries[i].components, d->entries[i].order, o);
193         d->entries[i].order = o;
194     }
195     d->order = o;
196 
197     return;
198 }
199 
200 static unsigned int
exif_mnote_data_apple_count(ExifMnoteData * md)201 exif_mnote_data_apple_count(ExifMnoteData *md){
202     /*printf("%s\n", __FUNCTION__);*/
203 
204     return md ? ((ExifMnoteDataApple *) md)->count : 0;
205 }
206 
207 static unsigned int
exif_mnote_data_apple_get_id(ExifMnoteData * md,unsigned int i)208 exif_mnote_data_apple_get_id(ExifMnoteData *md, unsigned int i) {
209     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
210 
211     if (!d || (d->count <= i)) {
212         return 0;
213     }
214 
215     return d->entries[i].tag;
216 }
217 
218 static const char *
exif_mnote_data_apple_get_name(ExifMnoteData * md,unsigned int i)219 exif_mnote_data_apple_get_name(ExifMnoteData *md, unsigned int i) {
220     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
221 
222     if (!d || (d->count <= i)) {
223         return NULL;
224     }
225 
226     return mnote_apple_tag_get_name(d->entries[i].tag);
227 }
228 
229 static const char *
exif_mnote_data_apple_get_title(ExifMnoteData * md,unsigned int i)230 exif_mnote_data_apple_get_title(ExifMnoteData *md, unsigned int i) {
231     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
232 
233     if (!d || (d->count <= i)) {
234         return NULL;
235     }
236 
237     return mnote_apple_tag_get_title(d->entries[i].tag);
238 }
239 
240 static const char *
exif_mnote_data_apple_get_description(ExifMnoteData * md,unsigned int i)241 exif_mnote_data_apple_get_description(ExifMnoteData *md, unsigned int i) {
242     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
243 
244     if (!d || (d->count <= i)) {
245         return NULL;
246     }
247 
248     return mnote_apple_tag_get_description(d->entries[i].tag);
249 }
250 
251 static char *
exif_mnote_data_apple_get_value(ExifMnoteData * md,unsigned int i,char * val,unsigned int maxlen)252 exif_mnote_data_apple_get_value(ExifMnoteData *md, unsigned int i, char *val, unsigned int maxlen) {
253     ExifMnoteDataApple *d = (ExifMnoteDataApple *) md;
254 
255     if (!val || !d || (d->count <= i)) {
256         return NULL;
257     }
258 
259     return mnote_apple_entry_get_value(&d->entries[i], val, maxlen);
260 }
261 
262 int
exif_mnote_data_apple_identify(const ExifData * ed,const ExifEntry * e)263 exif_mnote_data_apple_identify(const ExifData *ed, const ExifEntry *e) {
264     (void) ed;
265 
266     if (e->size < strlen("Apple iOS")+1)
267 	return 0;
268 
269     return !memcmp((const char *) e->data, "Apple iOS", strlen("Apple iOS"));
270 }
271 
272 ExifMnoteData *
exif_mnote_data_apple_new(ExifMem * mem)273 exif_mnote_data_apple_new(ExifMem *mem) {
274     ExifMnoteData *md;
275 
276     /*printf("%s\n", __FUNCTION__);*/
277 
278     if (!mem) {
279         return NULL;
280     }
281 
282     md = exif_mem_alloc(mem, sizeof(ExifMnoteDataApple));
283     if (!md) {
284         return NULL;
285     }
286 
287     exif_mnote_data_construct(md, mem);
288 
289     md->methods.free = exif_mnote_data_apple_free;
290     md->methods.load = exif_mnote_data_apple_load;
291     md->methods.set_offset = exif_mnote_data_apple_set_offset;
292     md->methods.set_byte_order = exif_mnote_data_apple_set_byte_order;
293     md->methods.count = exif_mnote_data_apple_count;
294     md->methods.get_id = exif_mnote_data_apple_get_id;
295     md->methods.get_name = exif_mnote_data_apple_get_name;
296     md->methods.get_title = exif_mnote_data_apple_get_title;
297     md->methods.get_description = exif_mnote_data_apple_get_description;
298     md->methods.get_value = exif_mnote_data_apple_get_value;
299 
300     return md;
301 }
302