1 /*
2 
3     File: file_bpg.c
4 
5     Copyright (C) 1998-2007 Christophe GRENIER <grenier@cgsecurity.org>
6     Copyright (C) 2016 Dmitry Brant <me@dmitrybrant.com>
7 
8     BPG specification can be found at:
9     http://bellard.org/bpg/bpg_spec.txt
10 
11     This software is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15 
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20 
21     You should have received a copy of the GNU General Public License along
22     with this program; if not, write the Free Software Foundation, Inc., 51
23     Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #include <stdio.h>
34 #include "types.h"
35 #include "filegen.h"
36 
37 #define MAX_BPG_SIZE 0x800000
38 
39 static void register_header_check_bpg(file_stat_t *file_stat);
40 
41 const file_hint_t file_hint_bpg= {
42   .extension="bpg",
43   .description="Better Portable Graphics image",
44   .max_filesize=MAX_BPG_SIZE,
45   .recover=1,
46   .enable_by_default=1,
47   .register_header_check=&register_header_check_bpg
48 };
49 
getue32(const unsigned char * buffer,const unsigned int buffer_size,unsigned int * buf_ptr)50 static unsigned int getue32(const unsigned char *buffer, const unsigned int buffer_size, unsigned int *buf_ptr)
51 {
52   unsigned int value = 0;
53   int bitsRead = 0;
54   while (*buf_ptr < buffer_size)
55   {
56     const unsigned int b = buffer[*buf_ptr];
57     *buf_ptr = *buf_ptr + 1;
58     value <<= 7;
59     value |= (b & 0x7F);
60     if ((b & 0x80) == 0)
61       break;
62     bitsRead += 7;
63     if (bitsRead >= 32)
64       break;
65   }
66   return value;
67 }
68 
header_check_bpg(const unsigned char * buffer,const unsigned int buffer_size,const unsigned int safe_header_only,const file_recovery_t * file_recovery,file_recovery_t * file_recovery_new)69 static int header_check_bpg(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
70 {
71   unsigned int buf_ptr = 6;
72   // get image width
73   const unsigned int picture_width = getue32(buffer, buffer_size, &buf_ptr);
74   // get image height
75   const unsigned int picture_height = getue32(buffer, buffer_size, &buf_ptr);
76   unsigned int size = getue32(buffer, buffer_size, &buf_ptr);
77   if(picture_width==0 || picture_height==0)
78     return 0;
79   if (size == 0) {
80     size = MAX_BPG_SIZE;
81   } else {
82     size += buf_ptr;
83   }
84   reset_file_recovery(file_recovery_new);
85   file_recovery_new->calculated_file_size=size;
86   file_recovery_new->data_check=&data_check_size;
87   file_recovery_new->file_check=&file_check_size;
88   file_recovery_new->extension=file_hint_bpg.extension;
89   return 1;
90 }
91 
register_header_check_bpg(file_stat_t * file_stat)92 static void register_header_check_bpg(file_stat_t *file_stat)
93 {
94   static const unsigned char bpg_header[4]= {'B','P','G',0xFB};
95   register_header_check(0, bpg_header,sizeof(bpg_header), &header_check_bpg, file_stat);
96 }
97