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