Merge pull request #1244 from rouault/fix_pi_warnings
[openjpeg.git] / src / lib / openjpip / box_manager.c
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2014, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include <assert.h>
36 #include "box_manager.h"
37 #include "opj_inttypes.h"
38
39 #ifdef SERVER
40 #include "fcgi_stdio.h"
41 #define logstream FCGI_stdout
42 #else
43 #define FCGI_stdout stdout
44 #define FCGI_stderr stderr
45 #define logstream stderr
46 #endif /*SERVER*/
47
48 boxlist_param_t * gene_boxlist(void)
49 {
50     boxlist_param_t *boxlist;
51
52     boxlist = (boxlist_param_t *)malloc(sizeof(boxlist_param_t));
53
54     boxlist->first = NULL;
55     boxlist->last  = NULL;
56
57     return boxlist;
58 }
59
60 boxlist_param_t * get_boxstructure(int fd, OPJ_OFF_T offset, OPJ_SIZE_T length)
61 {
62     boxlist_param_t *boxlist;
63     box_param_t *box;
64     OPJ_OFF_T pos;
65
66     boxlist = NULL;
67     pos = offset;
68     assert((OPJ_OFF_T)length >= 0);
69     do {
70         if (!(box = gene_boxbyOffset(fd, pos))) {
71             break;
72         }
73
74         assert((OPJ_OFF_T)box->length >= 0);
75         pos += (OPJ_OFF_T)box->length;
76
77         if (!boxlist) {
78             boxlist = gene_boxlist();
79         }
80         insert_box_into_list(box, boxlist);
81     } while (pos < offset + (OPJ_OFF_T)length);
82
83     return boxlist;
84 }
85
86 box_param_t * gene_boxbyOffset(int fd, OPJ_OFF_T offset)
87 {
88     Byte_t *data;
89     Byte8_t boxlen;
90     Byte_t headlen;
91     char *boxtype;
92     box_param_t *box;
93
94     /* read LBox and TBox*/
95     if (!(data = fetch_bytes(fd, offset, 8))) {
96         fprintf(FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %" PRId64 ")\n", fd,
97                 offset);
98         return NULL;
99     }
100
101     headlen = 8;
102     boxlen = (Byte8_t)big4(data);
103     boxtype = (char *)(data + 4);
104
105     /* box type constraint*/
106     if (!isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
107             (!isalnum(boxtype[2]) && !isspace(boxtype[2])) ||
108             (!isalpha(boxtype[3]) && !isspace(boxtype[3]))) {
109         free(data);
110         return NULL;
111     }
112
113     if (boxlen == 1) {
114         Byte_t *data2;
115         headlen = 16;
116         /* read XLBox*/
117         if ((data2 = fetch_bytes(fd, offset + 8, 8))) {
118             boxlen = big8(data2);
119             free(data2);
120         } else {
121             fprintf(FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %" PRId64 ")\n", fd,
122                     offset);
123             free(data);
124             return NULL;
125         }
126     }
127     box = (box_param_t *)malloc(sizeof(box_param_t));
128     box->fd = fd;
129     box->offset = offset;
130     box->headlen = headlen;
131     box->length = boxlen;
132     strncpy(box->type, boxtype, 4);
133     box->next = NULL;
134     free(data);
135     return box;
136 }
137
138 box_param_t * gene_boxbyOffinStream(Byte_t *stream, OPJ_OFF_T offset)
139 {
140     Byte8_t boxlen;
141     Byte_t headlen;
142     char *boxtype;
143     box_param_t *box;
144
145     /* read LBox and TBox*/
146     headlen = 8;
147     boxlen = (Byte8_t)big4(stream);
148     boxtype = (char *)(stream + 4);
149
150     /* box type constraint*/
151     if (!isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
152             (!isalnum(boxtype[2]) && !isspace(boxtype[2])) ||
153             (!isalpha(boxtype[3]) && !isspace(boxtype[3]))) {
154         return NULL;
155     }
156
157     if (boxlen == 1) {
158         headlen = 16;
159         boxlen = big8(stream + 8); /* read XLBox*/
160     }
161     box = (box_param_t *)malloc(sizeof(box_param_t));
162     box->fd = -1;
163     box->offset = offset;
164     box->headlen = headlen;
165     box->length = boxlen;
166     strncpy(box->type, boxtype, 4);
167     box->next = NULL;
168
169     return box;
170 }
171
172
173 box_param_t * gene_boxbyType(int fd, OPJ_OFF_T offset, OPJ_SIZE_T length,
174                              const char TBox[])
175 {
176     OPJ_OFF_T pos;
177     Byte_t *data;
178     Byte8_t boxlen;
179     Byte_t headlen;
180     char *boxtype;
181     box_param_t *foundbox;
182
183
184     if (length == 0) { /* set the max length*/
185         if (get_filesize(fd) <= offset) {
186             return NULL;
187         }
188         assert(get_filesize(fd) > offset);
189         assert(offset >= 0);
190         length = (OPJ_SIZE_T)(get_filesize(fd) - offset);
191     }
192
193     pos = offset;
194     assert(pos >= 0);
195     assert((OPJ_OFF_T)length >= 0);
196     while (pos < offset + (OPJ_OFF_T)length - 7) { /* LBox+TBox-1=7*/
197
198         /* read LBox and TBox*/
199         if ((data = fetch_bytes(fd, pos, 8))) {
200             headlen = 8;
201             boxlen = (Byte8_t)big4(data);
202             boxtype = (char *)(data + 4);
203
204             if (boxlen == 1) {
205                 Byte_t *data2;
206                 headlen = 16;
207                 /* read XLBox*/
208                 if ((data2 = fetch_bytes(fd, pos + 8, 8))) {
209                     boxlen = big8(data2);
210                     free(data2);
211                 } else {
212                     fprintf(FCGI_stderr, "Error: error in gene_boxbyType( %d, %" PRId64 ", %" PRId64
213                             ", %s)\n", fd, offset, length, TBox);
214                     free(data);
215                     return NULL;
216                 }
217             }
218             if (strncmp(boxtype, TBox, 4) == 0) {
219                 foundbox = (box_param_t *)malloc(sizeof(box_param_t));
220                 foundbox->fd = fd;
221                 foundbox->offset = pos;
222                 foundbox->headlen = headlen;
223                 foundbox->length = boxlen;
224                 strncpy(foundbox->type, TBox, 4);
225                 foundbox->next = NULL;
226                 free(data);
227                 return foundbox;
228             }
229             free(data);
230         } else {
231             fprintf(FCGI_stderr, "Error: error in gene_boxbyType( %d, %" PRId64 ", %" PRId64
232                     ", %s)\n", fd, offset, length, TBox);
233             return NULL;
234         }
235         assert(((Byte8_t)pos + boxlen) >= (Byte8_t)pos);
236         pos += (OPJ_OFF_T)boxlen;
237     }
238     fprintf(FCGI_stderr, "Error: Box %s not found\n", TBox);
239
240     return NULL;
241 }
242
243 box_param_t * gene_boxbyTypeinStream(Byte_t *stream, OPJ_OFF_T offset,
244                                      OPJ_SIZE_T length, const char TBox[])
245 {
246     OPJ_OFF_T pos;
247     Byte_t *data;
248     Byte8_t boxlen;
249     Byte_t headlen;
250     char *boxtype;
251     box_param_t *foundbox;
252
253     pos = offset;
254     assert(pos >= 0);
255     assert((OPJ_OFF_T)length >= 0);
256     while (pos < offset + (OPJ_OFF_T)(length) - 7) { /* LBox+TBox-1=7*/
257
258         /* read LBox and TBox*/
259         data = stream + pos;
260         headlen = 8;
261         boxlen = (Byte8_t)big4(data);
262         boxtype = (char *)(data + 4);
263
264         if (boxlen == 1) {
265             /* read XLBox*/
266             headlen = 16;
267             boxlen = big8(data + 8);
268         }
269
270         if (strncmp(boxtype, TBox, 4) == 0) {
271             foundbox = (box_param_t *)malloc(sizeof(box_param_t));
272             foundbox->fd = -1;
273             foundbox->offset = pos;
274             foundbox->headlen = headlen;
275             foundbox->length = boxlen;
276             strncpy(foundbox->type, TBox, 4);
277             foundbox->next = NULL;
278             return foundbox;
279         }
280         assert(((Byte8_t)pos + boxlen) >= (Byte8_t)pos);
281         pos += (OPJ_OFF_T)boxlen;
282     }
283     fprintf(FCGI_stderr, "Error: Box %s not found\n", TBox);
284
285     return NULL;
286 }
287
288 box_param_t * gene_childboxbyOffset(box_param_t *superbox, OPJ_OFF_T offset)
289 {
290     return gene_boxbyOffset(superbox->fd, get_DBoxoff(superbox) + offset);
291 }
292
293 box_param_t * gene_childboxbyType(box_param_t *superbox, OPJ_OFF_T offset,
294                                   const char TBox[])
295 {
296     OPJ_SIZE_T DBOXlen = get_DBoxlen(superbox);
297     assert(offset >= 0);
298     if (DBOXlen < (OPJ_SIZE_T)offset) {
299         fprintf(FCGI_stderr, "Error: Impossible happen %lu < %ld\n", DBOXlen, offset);
300         return NULL;
301     }
302     return gene_boxbyType(superbox->fd, get_DBoxoff(superbox) + offset,
303                           DBOXlen - (OPJ_SIZE_T)offset, TBox);
304 }
305
306 OPJ_OFF_T get_DBoxoff(box_param_t *box)
307 {
308     return box->offset + box->headlen;
309 }
310
311 OPJ_SIZE_T get_DBoxlen(box_param_t *box)
312 {
313     return box->length - box->headlen;
314 }
315
316 Byte_t * fetch_headbytes(box_param_t *box)
317 {
318     return fetch_bytes(box->fd, box->offset, box->headlen);
319 }
320
321 Byte_t * fetch_DBoxbytes(box_param_t *box, OPJ_OFF_T offset, OPJ_SIZE_T size)
322 {
323     return fetch_bytes(box->fd, get_DBoxoff(box) + offset, size);
324 }
325
326 Byte_t fetch_DBox1byte(box_param_t *box, OPJ_OFF_T offset)
327 {
328     return fetch_1byte(box->fd, get_DBoxoff(box) + offset);
329 }
330
331 Byte2_t fetch_DBox2bytebigendian(box_param_t *box, OPJ_OFF_T offset)
332 {
333     return fetch_2bytebigendian(box->fd, get_DBoxoff(box) + offset);
334 }
335
336 Byte4_t fetch_DBox4bytebigendian(box_param_t *box, OPJ_OFF_T offset)
337 {
338     return fetch_4bytebigendian(box->fd, get_DBoxoff(box) + offset);
339 }
340
341 Byte8_t fetch_DBox8bytebigendian(box_param_t *box, OPJ_OFF_T offset)
342 {
343     return fetch_8bytebigendian(box->fd, get_DBoxoff(box) + offset);
344 }
345
346 box_param_t * search_box(const char type[], boxlist_param_t *boxlist)
347 {
348     box_param_t *foundbox;
349
350     foundbox = boxlist->first;
351
352     while (foundbox != NULL) {
353
354         if (strncmp(type, foundbox->type, 4) == 0) {
355             return foundbox;
356         }
357
358         foundbox = foundbox->next;
359     }
360     fprintf(FCGI_stderr, "Error: Box %s not found\n", type);
361
362     return NULL;
363 }
364
365 void print_box(box_param_t *box)
366 {
367     fprintf(logstream, "box info:\n"
368             "\t type: %.4s\n"
369             "\t offset: %" PRId64 " %#" PRIx64 "\n"
370             "\t header length: %d\n"
371             "\t length: %" PRId64 " %#" PRIx64 "\n", box->type, box->offset,
372             box->offset, box->headlen, box->length, box->length);
373 }
374
375 void print_allbox(boxlist_param_t *boxlist)
376 {
377     box_param_t *ptr;
378
379     if (!boxlist) {
380         return;
381     }
382
383     ptr = boxlist->first;
384     if (!ptr) {
385         fprintf(logstream, "no box\n");
386     }
387
388     fprintf(logstream, "all box info: \n");
389     while (ptr != NULL) {
390         print_box(ptr);
391         ptr = ptr->next;
392     }
393 }
394
395 void delete_box_in_list(box_param_t **box, boxlist_param_t *boxlist)
396 {
397     box_param_t *ptr;
398
399     if (*box == boxlist->first) {
400         boxlist->first = (*box)->next;
401     } else {
402         ptr = boxlist->first;
403         while (ptr->next != *box) {
404             ptr = ptr->next;
405         }
406         ptr->next = (*box)->next;
407
408         if (*box == boxlist->last) {
409             boxlist->last = ptr;
410         }
411     }
412     free(*box);
413 }
414
415 void delete_box_in_list_by_type(const char type[], boxlist_param_t *boxlist)
416 {
417     box_param_t *box;
418
419     box = search_box(type, boxlist);
420     delete_box_in_list(&box, boxlist);
421 }
422
423 void delete_boxlist(boxlist_param_t **boxlist)
424 {
425     box_param_t *boxPtr, *boxNext;
426
427     if (!(*boxlist)) {
428         return;
429     }
430
431     boxPtr = (*boxlist)->first;
432     while (boxPtr != NULL) {
433         boxNext = boxPtr->next;
434         free(boxPtr);
435         boxPtr = boxNext;
436     }
437     free(*boxlist);
438 }
439
440 void insert_box_into_list(box_param_t *box, boxlist_param_t *boxlist)
441 {
442     if (boxlist->first) {
443         boxlist->last->next = box;
444     } else {
445         boxlist->first = box;
446     }
447     boxlist->last = box;
448 }