21#include <brotli/decode.h>
38 int chunkRemaining = *((
int *)dc->
state);
45 while (inputRemaining > 0) {
46 if (chunkRemaining > 2) {
48 int copylen =
MIN(chunkRemaining - 2, inputRemaining);
50 chunkRemaining -= copylen;
51 inputRemaining -= copylen;
55 if ((chunkRemaining == 2) && (inputRemaining > 0)) {
61 if ((chunkRemaining == 1) && (inputRemaining > 0)) {
72 if (!(eol = (
char *)memchr(inputPtr,
'\n', inputRemaining))) {
76 if (!(chunkRemaining = strtol(inputPtr, NULL, 0x10))) {
80 inputRemaining -= (eol - inputPtr) + 1;
88 *(
int *)dc->
state = chunkRemaining;
106 (void)inflateEnd((z_stream *)dc->
state);
125 z_stream *zs = (z_stream *)dc->
state;
127 int inputConsumed = 0;
130 while ((rc == Z_OK) && (inputConsumed < inlen)) {
131 zs->next_in = (Bytef *)instr + inputConsumed;
132 zs->avail_in = inlen - inputConsumed;
134 zs->next_out = (Bytef *)dc->
buffer;
137 rc = inflate(zs, Z_SYNC_FLUSH);
141 if ((rc == Z_OK) || (rc == Z_STREAM_END)) {
144 inputConsumed += zs->total_in;
147 }
else if (rc == Z_DATA_ERROR) {
148 MSG_ERR(
"gzip decompression error\n");
161 z_stream *zs = (z_stream *)dc->
state;
163 int inputConsumed = 0;
166 while ((rc == Z_OK) && (inputConsumed < inlen)) {
167 zs->next_in = (Bytef *)instr + inputConsumed;
168 zs->avail_in = inlen - inputConsumed;
170 zs->next_out = (Bytef *)dc->
buffer;
173 rc = inflate(zs, Z_SYNC_FLUSH);
177 if ((rc == Z_OK) || (rc == Z_STREAM_END)) {
180 inputConsumed += zs->total_in;
183 }
else if (rc == Z_DATA_ERROR) {
184 MSG_ERR(
"raw deflate decompression also failed\n");
198 z_stream *zs = (z_stream *)dc->
state;
200 int inputConsumed = 0;
203 while ((rc == Z_OK) && (inputConsumed < inlen)) {
204 zs->next_in = (Bytef *)instr + inputConsumed;
205 zs->avail_in = inlen - inputConsumed;
207 zs->next_out = (Bytef *)dc->
buffer;
210 rc = inflate(zs, Z_SYNC_FLUSH);
214 if ((rc == Z_OK) || (rc == Z_STREAM_END)) {
217 inputConsumed += zs->total_in;
220 }
else if (rc == Z_DATA_ERROR) {
221 MSG_WARN(
"Deflate decompression error. Certain servers illegally fail"
222 " to send data in a zlib wrapper. Let's try raw deflate.\n");
224 (void)inflateEnd(zs);
234 inflateInit2(zs, -MAX_WBITS);
246static Dstr *Decode_brotli_process(
Decode *dc,
const char *instr,
int inlen)
249 BrotliDecoderState *st = (BrotliDecoderState *) dc->
state;
251 const uint8_t *next_in = (
const uint8_t *) instr;
252 size_t avail_in = inlen;
253 BrotliDecoderResult res;
255 _MSG(
"Decode_brotli_process inlen=%d\n", inlen);
263 uint8_t *next_out = (uint8_t *) dc->buffer;
266 _MSG(
"Decode_brotli_process decoding %zd bytes\n", avail_in);
268 res = BrotliDecoderDecompressStream(st,
269 &avail_in, &next_in, &avail_out, &next_out, NULL);
271 _MSG(
"Decode_brotli_process res=%d\n", res);
273 if (res == BROTLI_DECODER_RESULT_ERROR) {
274 MSG_ERR(
"brotli decompression error\n");
278 size_t delta =
bufsize - avail_out;
279 _MSG(
"Decode_brotli_process delta=%zd\n", delta);
282 }
while (res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT);
284 _MSG(
"Decode_brotli_process exitting with res=%d\n", res);
289static void Decode_brotli_free(
Decode *dc)
291 BrotliDecoderState *st = (BrotliDecoderState *) dc->
state;
292 BrotliDecoderDestroyInstance(st);
297static Decode *Decode_brotli_init(
void)
299 BrotliDecoderState *st = BrotliDecoderCreateInstance(NULL, NULL, NULL);
301 MSG_ERR(
"Cannot create brotli decoder instance\n");
310 dc->
decode = Decode_brotli_process;
311 dc->
free = Decode_brotli_free;
325 size_t inLeft, outRoom;
334 while ((rc != EINVAL) && (inLeft > 0)) {
339 rc = iconv((iconv_t)dc->
state, &inPtr, &inLeft, &outPtr, &outRoom);
365 (void)iconv_close((iconv_t)(dc->
state));
379 int *chunk_remaining =
dNew(
int, 1);
380 *chunk_remaining = 0;
383 dc->
state = chunk_remaining;
392 z_stream *zs =
dNew(z_stream, 1);
415 if (format && *format) {
418 _MSG(
"gzipped data!\n");
421 zs = (z_stream *)dc->
state;
423 inflateInit2(zs, MAX_WBITS+16);
427 _MSG(
"deflated data!\n");
430 zs = (z_stream *)dc->
state;
436 _MSG(
"brotli data!\n");
437 dc = Decode_brotli_init();
440 MSG(
"Content-Encoding '%s' not recognized.\n", format);
461 iconv_t ic = iconv_open(
"UTF-8", format);
462 if (ic != (iconv_t) -1) {
471 MSG_WARN(
"Unable to convert from character encoding: '%s'\n", format);
482 return dc->
decode(dc, instr, inlen);
Decode * a_Decode_charset_init(const char *format)
Initialize decoder to translate from any character set known to iconv() to UTF-8.
Dstr * a_Decode_transfer_process(DecodeTransfer *dc, const char *instr, int inlen)
Decode 'Transfer-Encoding: chunked' data.
static Dstr * Decode_charset(Decode *dc, const char *instr, int inlen)
Translate to desired character set (UTF-8)
void a_Decode_transfer_free(DecodeTransfer *dc)
Decode * a_Decode_content_init(const char *format)
Initialize content decoder.
static Dstr * Decode_raw_deflate(Decode *dc, const char *instr, int inlen)
Decode (raw) deflated data.
DecodeTransfer * a_Decode_transfer_init(const char *format)
Initialize transfer decoder.
Dstr * a_Decode_process(Decode *dc, const char *instr, int inlen)
Decode data.
static Decode * Decode_content_init_common(void)
static Dstr * Decode_deflate(Decode *dc, const char *instr, int inlen)
Decode deflated data, initially presuming that the required zlib wrapper is there.
void a_Decode_free(Decode *dc)
static void Decode_charset_free(Decode *dc)
static Dstr * Decode_gzip(Decode *dc, const char *instr, int inlen)
Decode gzipped data.
bool_t a_Decode_transfer_finished(DecodeTransfer *dc)
static void Decode_compression_free(Decode *dc)
int dStrAsciiCasecmp(const char *s1, const char *s2)
Dstr * dStr_sized_new(int sz)
Create a new string with a given size.
void dStr_erase(Dstr *ds, int pos_0, int len)
Erase a substring.
void dStr_free(Dstr *ds, int all)
Free a dillo string.
void dStr_append_l(Dstr *ds, const char *s, int l)
Append a C string to a Dstr (providing length).
Dstr * dStr_new(const char *s)
Create a new string.
#define dNew0(type, count)
#define dNew(type, count)
bool_t finished
has the terminating chunk been seen?
Dstr *(* decode)(struct Decode *dc, const char *instr, int inlen)
void(* free)(struct Decode *dc)
static const char utf8_replacement_char[]
Unicode replacement character U+FFFD.