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=®ister_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