1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2012
6 * All rights reserved
7 *
8 * This file is part of GPAC / common tools sub-project
9 *
10 * GPAC is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * GPAC is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 #include <gpac/base_coding.h>
27 #include <gpac/constants.h>
28
29 #ifndef GPAC_DISABLE_CORE_TOOLS
30
31 static const char base_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32
33 GF_EXPORT
gf_base64_encode(const char * _in,u32 inSize,char * _out,u32 outSize)34 u32 gf_base64_encode(const char *_in, u32 inSize, char *_out, u32 outSize)
35 {
36 s32 padding;
37 u32 i = 0, j = 0;
38 unsigned char *in = (unsigned char *)_in;
39 unsigned char *out = (unsigned char *)_out;
40
41 if (outSize < (inSize * 4 / 3)) return 0;
42
43 while (i < inSize) {
44 padding = 3 - (inSize - i);
45 if (padding == 2) {
46 out[j] = base_64[in[i] >> 2];
47 out[j + 1] = base_64[(in[i] & 0x03) << 4];
48 out[j + 2] = '=';
49 out[j + 3] = '=';
50 }
51 else if (padding == 1) {
52 out[j] = base_64[in[i] >> 2];
53 out[j + 1] = base_64[((in[i] & 0x03) << 4) | ((in[i + 1] & 0xf0) >> 4)];
54 out[j + 2] = base_64[(in[i + 1] & 0x0f) << 2];
55 out[j + 3] = '=';
56 }
57 else {
58 out[j] = base_64[in[i] >> 2];
59 out[j + 1] = base_64[((in[i] & 0x03) << 4) | ((in[i + 1] & 0xf0) >> 4)];
60 out[j + 2] = base_64[((in[i + 1] & 0x0f) << 2) | ((in[i + 2] & 0xc0) >> 6)];
61 out[j + 3] = base_64[in[i + 2] & 0x3f];
62 }
63 i += 3;
64 j += 4;
65 }
66 return j;
67 }
68
69 static const unsigned char index_64[128] = {
70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
73 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
74 0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
75 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
76 0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
77 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff
78 };
79
80 #define char64(c) ((c > 127) ? (char) 0xff : index_64[(c)])
81
82 /*denoise input*/
load_block(char * in,u32 size,u32 pos,char * out)83 u32 load_block(char *in, u32 size, u32 pos, char *out)
84 {
85 u32 i, len;
86 u8 c;
87 len = i = 0;
88 while ((len<4) && ((pos + i)<size)) {
89 c = in[pos + i];
90 if (((c >= 'A') && (c <= 'Z'))
91 || ((c >= 'a') && (c <= 'z'))
92 || ((c >= '0') && (c <= '9'))
93 || (c == '=') || (c == '+') || (c == '/')
94 ) {
95 out[len] = c;
96 len++;
97 }
98 i++;
99 }
100 while (len<4) {
101 out[len] = (char)0xFF;
102 len++;
103 }
104 return pos + i;
105 }
106
107 GF_EXPORT
gf_base64_decode(char * in_buf,u32 inSize,char * out,u32 outSize)108 u32 gf_base64_decode(char *in_buf, u32 inSize, char *out, u32 outSize)
109 {
110 u32 i = 0, j = 0, padding;
111 unsigned char c[4], in[4];
112
113 if (outSize < (inSize * 3 / 4)) return 0;
114
115 while ((i + 3) < inSize) {
116 padding = 0;
117 i = load_block(in_buf, inSize, i, (char*)in);
118 c[0] = char64(in[0]);
119 padding += (c[0] == 0xff);
120 c[1] = char64(in[1]);
121 padding += (c[1] == 0xff);
122 c[2] = char64(in[2]);
123 padding += (c[2] == 0xff);
124 c[3] = char64(in[3]);
125 padding += (c[3] == 0xff);
126 if (padding == 2) {
127 out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
128 out[j] = (c[1] & 0x0f) << 4;
129 }
130 else if (padding == 1) {
131 out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
132 out[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
133 out[j] = (c[2] & 0x03) << 6;
134 }
135 else {
136 out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
137 out[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
138 out[j++] = ((c[2] & 0x03) << 6) | (c[3] & 0x3f);
139 }
140 //i += 4;
141 }
142 return j;
143 }
144
145 static const char base_16[] = "0123456789abcdef";
146
147 GF_EXPORT
gf_base16_encode(char * _in,u32 inSize,char * _out,u32 outSize)148 u32 gf_base16_encode(char *_in, u32 inSize, char *_out, u32 outSize)
149 {
150 u32 i = 0;
151 unsigned char *in = (unsigned char *)_in;
152 unsigned char *out = (unsigned char *)_out;
153
154 if (outSize < (inSize * 2) + 1) return 0;
155
156 for (i = 0; i<inSize; i++) {
157 out[2 * i] = base_16[((in[i] & 0xf0) >> 4)];
158 out[2 * i + 1] = base_16[(in[i] & 0x0f)];
159 }
160 out[(inSize * 2)] = 0;
161
162 return i;
163 }
164
165 #define char16(nb) (((nb) < 97) ? ((nb)-48) : ((nb)-87))
166
167 GF_EXPORT
gf_base16_decode(char * in,u32 inSize,char * out,u32 outSize)168 u32 gf_base16_decode(char *in, u32 inSize, char *out, u32 outSize)
169 {
170 u32 j = 0;
171 u32 c[2] = { 0,0 };
172
173 if (outSize < (inSize / 2)) return 0;
174 if ((inSize % 2) != 0) return 0;
175
176 for (j = 0; j<inSize / 2; j++) {
177 c[0] = char16(in[2 * j]);
178 c[1] = char16(in[2 * j + 1]);
179 out[j] = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
180 }
181 out[inSize / 2] = 0;
182
183 return j;
184 }
185
186
187 #ifndef GPAC_DISABLE_ZLIB
188
189 #include <zlib.h>
190
191 #define ZLIB_COMPRESS_SAFE 4
192
193 GF_EXPORT
gf_gz_compress_payload(char ** data,u32 data_len,u32 * max_size)194 GF_Err gf_gz_compress_payload(char **data, u32 data_len, u32 *max_size)
195 {
196 z_stream stream;
197 int err;
198 char *dest = (char *)gf_malloc(sizeof(char)*data_len*ZLIB_COMPRESS_SAFE);
199 stream.next_in = (Bytef*)(*data);
200 stream.avail_in = (uInt)data_len;
201 stream.next_out = (Bytef*)dest;
202 stream.avail_out = (uInt)data_len*ZLIB_COMPRESS_SAFE;
203 stream.zalloc = (alloc_func)NULL;
204 stream.zfree = (free_func)NULL;
205 stream.opaque = (voidpf)NULL;
206
207 err = deflateInit(&stream, 9);
208 if (err != Z_OK) {
209 gf_free(dest);
210 return GF_IO_ERR;
211 }
212
213 err = deflate(&stream, Z_FINISH);
214 if (err != Z_STREAM_END) {
215 deflateEnd(&stream);
216 gf_free(dest);
217 return GF_IO_ERR;
218 }
219 if (data_len <stream.total_out) {
220 GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[GZ] compressed data (%d) larger than input (%d)\n", (u32)stream.total_out, (u32)data_len));
221 }
222
223 if (*max_size < stream.total_out) {
224 *max_size = data_len*ZLIB_COMPRESS_SAFE;
225 *data = (char*)gf_realloc(*data, *max_size * sizeof(char));
226 }
227
228 memcpy((*data), dest, sizeof(char)*stream.total_out);
229 *max_size = (u32)stream.total_out;
230 gf_free(dest);
231
232 deflateEnd(&stream);
233 return GF_OK;
234 }
235
236 GF_EXPORT
gf_gz_decompress_payload(char * data,u32 data_len,char ** uncompressed_data,u32 * out_size)237 GF_Err gf_gz_decompress_payload(char *data, u32 data_len, char **uncompressed_data, u32 *out_size)
238 {
239 z_stream d_stream;
240 GF_Err e = GF_OK;
241 int err;
242 u32 size = 4096;
243
244 *uncompressed_data = (char*)gf_malloc(sizeof(char) * 4096);
245 if (!*uncompressed_data) return GF_OUT_OF_MEM;
246
247 d_stream.zalloc = (alloc_func)0;
248 d_stream.zfree = (free_func)0;
249 d_stream.opaque = (voidpf)0;
250 d_stream.next_in = (Bytef*)data;
251 d_stream.avail_in = data_len;
252 d_stream.next_out = (Bytef*)*uncompressed_data;
253 d_stream.avail_out = 4096;
254
255 err = inflateInit(&d_stream);
256 if (err == Z_OK) {
257 while (d_stream.total_in < data_len) {
258 err = inflate(&d_stream, Z_NO_FLUSH);
259 if (err < Z_OK) {
260 e = GF_NON_COMPLIANT_BITSTREAM;
261 break;
262 }
263 if (err == Z_STREAM_END) break;
264
265 size *= 2;
266 *uncompressed_data = (char*)gf_realloc(*uncompressed_data, sizeof(char)*size);
267 if (!*uncompressed_data) return GF_OUT_OF_MEM;
268 d_stream.avail_out = (u32)(size - d_stream.total_out);
269 d_stream.next_out = (Bytef*)(*uncompressed_data + d_stream.total_out);
270 }
271 *out_size = (u32)d_stream.total_out;
272 inflateEnd(&d_stream);
273 return e;
274 }
275 if (e != GF_OK) {
276 gf_free(*uncompressed_data);
277 *uncompressed_data = NULL;
278 }
279 return e;
280 }
281
282 #endif /*GPAC_DISABLE_ZLIB*/
283
284 #endif /* GPAC_DISABLE_CORE_TOOLS*/
285