2 * http_contentdecoder.c
4 * Copyright (c) 2012 project bchan
6 * This software is provided 'as-is', without any express or implied
7 * warranty. In no event will the authors be held liable for any damages
8 * arising from the use of this software.
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source
27 #include "http_contentdecoder.h"
31 #include <util/zlib.h>
33 #include "http_typedef.h"
35 #ifdef BCHAN_CONFIG_DEBUG
36 # define DP(arg) printf arg
37 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
40 # define DP_ER(msg, err) /**/
44 # define DP_STATE(state) printf("%s\n", state)
46 # define DP_STATE(state) /**/
49 LOCAL W http_contentdecoderidentity_inputentitybody(http_contentdecoderidentity_t *decoder, UB *data, W data_len)
51 decoder->state = HTTP_CONTENTDECODERIDENTITY_STATE_DATA;
53 decoder->data_len = data_len;
57 LOCAL W http_contentdecoderidentity_inputendofdata(http_contentdecoderidentity_t *decoder)
59 decoder->state = HTTP_CONTENTDECODERIDENTITY_STATE_END;
63 LOCAL W http_contentdecoderidentity_outputdata(http_contentdecoderidentity_t *decoder, http_contentdecoder_result **result, W *result_len)
65 switch (decoder->state) {
66 case HTTP_CONTENTDECODERIDENTITY_STATE_DATA:
67 decoder->result[0].type = HTTP_CONTENTDECODER_RESULTTYPE_DATA;
68 decoder->result[0].data = decoder->data;
69 decoder->result[0].len = decoder->data_len;
70 decoder->result[1].type = HTTP_CONTENTDECODER_RESULTTYPE_NEED_INPUT;
71 decoder->result[1].data = NULL;
72 decoder->result[1].len = 0;
73 *result = decoder->result;
76 case HTTP_CONTENTDECODERIDENTITY_STATE_END:
77 decoder->result[0].type = HTTP_CONTENTDECODER_RESULTTYPE_END;
78 decoder->result[0].data = NULL;
79 decoder->result[0].len = 0;
80 *result = decoder->result;
88 LOCAL W http_contentdecoderidentity_initialize(http_contentdecoderidentity_t *decoder)
90 decoder->state = HTTP_CONTENTDECODERIDENTITY_STATE_DATA;
92 decoder->data_len = 0;
96 LOCAL VOID http_contentdecoderidentity_finalize(http_contentdecoderidentity_t *decoder)
102 LOCAL W gzip_headerskip_inputchar(gzip_headerskip_t *gzip, UB ch, Bool *is_end)
106 switch (gzip->state) {
107 case GZIP_HEADERSKIP_STATE_MAGIC_NUMBER_FIRST:
109 return -1; /* TODO: format error */
111 gzip->state = GZIP_HEADERSKIP_STATE_MAGIC_NUMBER_SECOND;
113 case GZIP_HEADERSKIP_STATE_MAGIC_NUMBER_SECOND:
115 return -1; /* TODO: format error */
117 gzip->state = GZIP_HEADERSKIP_STATE_METHOD;
119 case GZIP_HEADERSKIP_STATE_METHOD:
120 if (ch != Z_DEFLATED) {
121 return -1; /* TODO: format error */
123 gzip->state = GZIP_HEADERSKIP_STATE_FLAGS;
125 case GZIP_HEADERSKIP_STATE_FLAGS:
127 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_UNUSED_FIELD;
129 case GZIP_HEADERSKIP_STATE_SKIP_UNUSED_FIELD:
131 if (gzip->unused != 0) {
134 if (gzip->flags & 0x04) {
135 gzip->state = GZIP_HEADERSKIP_STATE_EXTRA_FIELD_LEN_FIRST;
136 } else if (gzip->flags & 0x08) {
137 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_FILE_NAME;
138 } else if (gzip->flags & 0x10) {
139 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_FILE_COMMENT;
140 } else if (gzip->flags & 0x02) {
141 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_HEADER_CRC_FIRST;
146 case GZIP_HEADERSKIP_STATE_EXTRA_FIELD_LEN_FIRST:
147 gzip->extra_len = (W)ch;
148 gzip->state = GZIP_HEADERSKIP_STATE_EXTRA_FIELD_LEN_SECOND;
150 case GZIP_HEADERSKIP_STATE_EXTRA_FIELD_LEN_SECOND:
151 gzip->extra_len += (W)ch << 8;
152 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_EXTRA_FIELD;
154 case GZIP_HEADERSKIP_STATE_SKIP_EXTRA_FIELD:
156 if (gzip->extra_len != 0) {
159 if (gzip->flags & 0x08) {
160 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_FILE_NAME;
161 } else if (gzip->flags & 0x10) {
162 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_FILE_COMMENT;
163 } else if (gzip->flags & 0x02) {
164 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_HEADER_CRC_FIRST;
169 case GZIP_HEADERSKIP_STATE_SKIP_FILE_NAME:
173 if (gzip->flags & 0x10) {
174 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_FILE_COMMENT;
175 } else if (gzip->flags & 0x02) {
176 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_HEADER_CRC_FIRST;
181 case GZIP_HEADERSKIP_STATE_SKIP_FILE_COMMENT:
185 if (gzip->flags & 0x02) {
186 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_HEADER_CRC_FIRST;
191 case GZIP_HEADERSKIP_STATE_SKIP_HEADER_CRC_FIRST:
192 gzip->state = GZIP_HEADERSKIP_STATE_SKIP_HEADER_CRC_SECOND;
194 case GZIP_HEADERSKIP_STATE_SKIP_HEADER_CRC_SECOND:
201 LOCAL VOID gzip_headerskip_initialize(gzip_headerskip_t *gzip)
203 gzip->state = GZIP_HEADERSKIP_STATE_MAGIC_NUMBER_FIRST;
209 LOCAL VOID gzip_headerskip_finalize(gzip_headerskip_t *gzip)
215 LOCAL W http_contentdecodergzip_inputentitybody(http_contentdecodergzip_t *decoder, UB *data, W data_len)
220 switch (decoder->state) {
221 case HTTP_CONTENTDECODERGZIP_STATE_SKIP_HEADER:
222 DP_STATE("HTTP_CONTENTDECODERGZIP_STATE_SKIP_HEADER");
223 for (i = 0; i < data_len; i++) {
224 err = gzip_headerskip_inputchar(&decoder->gzipheader, data[i], &is_end);
228 if (is_end != False) {
229 decoder->state = HTTP_CONTENTDECODERGZIP_STATE_DECODE;
230 decoder->z.next_in = data + i + 1;
231 decoder->z.avail_in = data_len - (i + 1);
236 case HTTP_CONTENTDECODERGZIP_STATE_DECODE:
237 DP_STATE("HTTP_CONTENTDECODERGZIP_STATE_DECODE");
238 decoder->z.next_in = data;
239 decoder->z.avail_in = data_len;
241 case HTTP_CONTENTDECODERGZIP_STATE_END_OF_DATA:
242 DP_STATE("HTTP_CONTENTDECODERGZIP_STATE_END_OF_DATA");
243 return -1; /* TODO */
249 LOCAL W http_contentdecodergzip_inputendofdata(http_contentdecodergzip_t *decoder)
251 decoder->state = HTTP_CONTENTDECODERGZIP_STATE_END_OF_DATA;
255 LOCAL W http_contentdecodergzip_outputdata(http_contentdecodergzip_t *decoder, http_contentdecoder_result **result, W *result_len)
259 switch (decoder->state) {
260 case HTTP_CONTENTDECODERGZIP_STATE_SKIP_HEADER:
261 decoder->result[0].type = HTTP_CONTENTDECODER_RESULTTYPE_NEED_INPUT;
262 decoder->result[0].data = NULL;
263 decoder->result[0].len = 0;
264 *result = decoder->result;
267 case HTTP_CONTENTDECODERGZIP_STATE_DECODE:
268 if (decoder->z.avail_in == 0) {
269 decoder->result[0].type = HTTP_CONTENTDECODER_RESULTTYPE_NEED_INPUT;
270 decoder->result[0].data = NULL;
271 decoder->result[0].len = 0;
272 *result = decoder->result;
277 *result = decoder->result;
279 err = inflate(&(decoder->z), Z_NO_FLUSH);
280 if (err == Z_STREAM_END) {
281 decoder->result[0].type = HTTP_CONTENTDECODER_RESULTTYPE_DATA;
282 decoder->result[0].data = decoder->buffer;
283 decoder->result[0].len = HTTP_CONTENTDECODERGZIP_BUFLEN - decoder->z.avail_out;
285 decoder->state = HTTP_CONTENTDECODERGZIP_STATE_END_OF_DATA;
289 DP_ER("inflate error:", err);
292 if (decoder->z.avail_out == 0) {
293 decoder->result[0].type = HTTP_CONTENTDECODER_RESULTTYPE_DATA;
294 decoder->result[0].data = decoder->buffer;
295 decoder->result[0].len = HTTP_CONTENTDECODERGZIP_BUFLEN;
297 decoder->z.next_out = decoder->buffer;
298 decoder->z.avail_out = HTTP_CONTENTDECODERGZIP_BUFLEN;
305 case HTTP_CONTENTDECODERGZIP_STATE_END_OF_DATA:
306 decoder->result[0].type = HTTP_CONTENTDECODER_RESULTTYPE_END;
307 decoder->result[0].data = NULL;
308 decoder->result[0].len = 0;
316 LOCAL W http_contentdecodergzip_initialize(http_contentdecodergzip_t *decoder)
320 decoder->z.zalloc = Z_NULL;
321 decoder->z.zfree = Z_NULL;
322 decoder->z.opaque = Z_NULL;
323 decoder->z.next_in = Z_NULL;
324 decoder->z.avail_in = 0;
325 err = inflateInit2(&(decoder->z), -MAX_WBITS);
327 DP_ER("inflateInit2 error:", err);
330 decoder->z.next_out = decoder->buffer;
331 decoder->z.avail_out = HTTP_CONTENTDECODERGZIP_BUFLEN;
333 gzip_headerskip_initialize(&decoder->gzipheader);
334 decoder->state = HTTP_CONTENTDECODERGZIP_STATE_SKIP_HEADER;
339 LOCAL VOID http_contentdecodergzip_finalize(http_contentdecodergzip_t *decoder)
341 gzip_headerskip_finalize(&decoder->gzipheader);
342 inflateEnd(&(decoder->z));
347 EXPORT W http_contentdecoder_inputentitybody(http_contentdecoder_t *decoder, UB *data, W data_len)
349 switch (decoder->type) {
350 case HTTP_CONTENTCODING_VALUE_IDENTITY:
351 return http_contentdecoderidentity_inputentitybody(&decoder->d.identity, data, data_len);
352 case HTTP_CONTENTCODING_VALUE_GZIP:
353 return http_contentdecodergzip_inputentitybody(&decoder->d.gzip, data, data_len);
354 case HTTP_CONTENTCODING_VALUE_COMPRESS: /* unsupported yet */
355 case HTTP_CONTENTCODING_VALUE_DEFLATE: /* unsupported yet */
360 EXPORT W http_contentdecoder_inputendofdata(http_contentdecoder_t *decoder)
362 switch (decoder->type) {
363 case HTTP_CONTENTCODING_VALUE_IDENTITY:
364 return http_contentdecoderidentity_inputendofdata(&decoder->d.identity);
365 case HTTP_CONTENTCODING_VALUE_GZIP:
366 return http_contentdecodergzip_inputendofdata(&decoder->d.gzip);
367 case HTTP_CONTENTCODING_VALUE_COMPRESS: /* unsupported yet */
368 case HTTP_CONTENTCODING_VALUE_DEFLATE: /* unsupported yet */
373 EXPORT W http_contentdecoder_outputdata(http_contentdecoder_t *decoder, http_contentdecoder_result **result, W *result_len)
375 switch (decoder->type) {
376 case HTTP_CONTENTCODING_VALUE_IDENTITY:
377 return http_contentdecoderidentity_outputdata(&decoder->d.identity, result, result_len);
378 case HTTP_CONTENTCODING_VALUE_GZIP:
379 return http_contentdecodergzip_outputdata(&decoder->d.gzip, result, result_len);
380 case HTTP_CONTENTCODING_VALUE_COMPRESS: /* unsupported yet */
381 case HTTP_CONTENTCODING_VALUE_DEFLATE: /* unsupported yet */
386 EXPORT W http_contentdecoder_initialize(http_contentdecoder_t *decoder, HTTP_CONTENTCODING_VALUE type)
388 decoder->type = type;
390 case HTTP_CONTENTCODING_VALUE_IDENTITY:
391 return http_contentdecoderidentity_initialize(&decoder->d.identity);
392 case HTTP_CONTENTCODING_VALUE_GZIP:
393 return http_contentdecodergzip_initialize(&decoder->d.gzip);
394 case HTTP_CONTENTCODING_VALUE_COMPRESS: /* unsupported yet */
395 case HTTP_CONTENTCODING_VALUE_DEFLATE: /* unsupported yet */
400 EXPORT VOID http_contentdecoder_finalize(http_contentdecoder_t *decoder)
402 switch (decoder->type) {
403 case HTTP_CONTENTCODING_VALUE_IDENTITY:
404 http_contentdecoderidentity_finalize(&decoder->d.identity);
406 case HTTP_CONTENTCODING_VALUE_GZIP:
407 http_contentdecodergzip_finalize(&decoder->d.gzip);
409 case HTTP_CONTENTCODING_VALUE_COMPRESS: /* unsupported yet */
410 case HTTP_CONTENTCODING_VALUE_DEFLATE: /* unsupported yet */