1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25#include "curl_setup.h"
26
27#include "urldata.h"
28#include <curl/curl.h>
29#include <stddef.h>
30
31#ifdef HAVE_LIBZ
32#include <zlib.h>
33#endif
34
35#ifdef HAVE_BROTLI
36#if defined(__GNUC__)
37/* Ignore -Wvla warnings in brotli headers */
38#pragma GCC diagnostic push
39#pragma GCC diagnostic ignored "-Wvla"
40#endif
41#include <brotli/decode.h>
42#if defined(__GNUC__)
43#pragma GCC diagnostic pop
44#endif
45#endif
46
47#ifdef HAVE_ZSTD
48#include <zstd.h>
49#endif
50
51#include "sendf.h"
52#include "http.h"
53#include "content_encoding.h"
54#include "strdup.h"
55#include "strcase.h"
56
57/* The last 3 #include files should be in this order */
58#include "curl_printf.h"
59#include "curl_memory.h"
60#include "memdebug.h"
61
62#define CONTENT_ENCODING_DEFAULT "identity"
63
64#ifndef CURL_DISABLE_HTTP
65
66#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
67
68
69#ifdef HAVE_LIBZ
70
71/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
72 (doing so will reduce code size slightly). */
73#define OLD_ZLIB_SUPPORT 1
74
75#define GZIP_MAGIC_0 0x1f
76#define GZIP_MAGIC_1 0x8b
77
78/* gzip flag byte */
79#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
80#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
81#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
82#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
83#define COMMENT 0x10 /* bit 4 set: file comment present */
84#define RESERVED 0xE0 /* bits 5..7: reserved */
85
86typedef enum {
87 ZLIB_UNINIT, /* uninitialized */
88 ZLIB_INIT, /* initialized */
89 ZLIB_INFLATING, /* inflating started. */
90 ZLIB_EXTERNAL_TRAILER, /* reading external trailer */
91 ZLIB_GZIP_HEADER, /* reading gzip header */
92 ZLIB_GZIP_INFLATING, /* inflating gzip stream */
93 ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
94} zlibInitState;
95
96/* Deflate and gzip writer. */
97struct zlib_writer {
98 struct contenc_writer super;
99 zlibInitState zlib_init; /* zlib init state */
100 uInt trailerlen; /* Remaining trailer byte count. */
101 z_stream z; /* State structure for zlib. */
102};
103
104
105static voidpf
106zalloc_cb(voidpf opaque, unsigned int items, unsigned int size)
107{
108 (void) opaque;
109 /* not a typo, keep it calloc() */
110 return (voidpf) calloc(items, size);
111}
112
113static void
114zfree_cb(voidpf opaque, voidpf ptr)
115{
116 (void) opaque;
117 free(ptr);
118}
119
120static CURLcode
121process_zlib_error(struct Curl_easy *data, z_stream *z)
122{
123 if(z->msg)
124 failf(data, fmt: "Error while processing content unencoding: %s",
125 z->msg);
126 else
127 failf(data, fmt: "Error while processing content unencoding: "
128 "Unknown failure within decompression software.");
129
130 return CURLE_BAD_CONTENT_ENCODING;
131}
132
133static CURLcode
134exit_zlib(struct Curl_easy *data,
135 z_stream *z, zlibInitState *zlib_init, CURLcode result)
136{
137 if(*zlib_init == ZLIB_GZIP_HEADER)
138 Curl_safefree(z->next_in);
139
140 if(*zlib_init != ZLIB_UNINIT) {
141 if(inflateEnd(strm: z) != Z_OK && result == CURLE_OK)
142 result = process_zlib_error(data, z);
143 *zlib_init = ZLIB_UNINIT;
144 }
145
146 return result;
147}
148
149static CURLcode process_trailer(struct Curl_easy *data,
150 struct zlib_writer *zp)
151{
152 z_stream *z = &zp->z;
153 CURLcode result = CURLE_OK;
154 uInt len = z->avail_in < zp->trailerlen? z->avail_in: zp->trailerlen;
155
156 /* Consume expected trailer bytes. Terminate stream if exhausted.
157 Issue an error if unexpected bytes follow. */
158
159 zp->trailerlen -= len;
160 z->avail_in -= len;
161 z->next_in += len;
162 if(z->avail_in)
163 result = CURLE_WRITE_ERROR;
164 if(result || !zp->trailerlen)
165 result = exit_zlib(data, z, zlib_init: &zp->zlib_init, result);
166 else {
167 /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
168 zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
169 }
170 return result;
171}
172
173static CURLcode inflate_stream(struct Curl_easy *data,
174 struct contenc_writer *writer,
175 zlibInitState started)
176{
177 struct zlib_writer *zp = (struct zlib_writer *) writer;
178 z_stream *z = &zp->z; /* zlib state structure */
179 uInt nread = z->avail_in;
180 Bytef *orig_in = z->next_in;
181 bool done = FALSE;
182 CURLcode result = CURLE_OK; /* Curl_client_write status */
183 char *decomp; /* Put the decompressed data here. */
184
185 /* Check state. */
186 if(zp->zlib_init != ZLIB_INIT &&
187 zp->zlib_init != ZLIB_INFLATING &&
188 zp->zlib_init != ZLIB_INIT_GZIP &&
189 zp->zlib_init != ZLIB_GZIP_INFLATING)
190 return exit_zlib(data, z, zlib_init: &zp->zlib_init, result: CURLE_WRITE_ERROR);
191
192 /* Dynamically allocate a buffer for decompression because it's uncommonly
193 large to hold on the stack */
194 decomp = malloc(DSIZ);
195 if(!decomp)
196 return exit_zlib(data, z, zlib_init: &zp->zlib_init, result: CURLE_OUT_OF_MEMORY);
197
198 /* because the buffer size is fixed, iteratively decompress and transfer to
199 the client via downstream_write function. */
200 while(!done) {
201 int status; /* zlib status */
202 done = TRUE;
203
204 /* (re)set buffer for decompressed output for every iteration */
205 z->next_out = (Bytef *) decomp;
206 z->avail_out = DSIZ;
207
208#ifdef Z_BLOCK
209 /* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */
210 status = inflate(strm: z, Z_BLOCK);
211#else
212 /* fallback for zlib ver. < 1.2.0.5 */
213 status = inflate(z, Z_SYNC_FLUSH);
214#endif
215
216 /* Flush output data if some. */
217 if(z->avail_out != DSIZ) {
218 if(status == Z_OK || status == Z_STREAM_END) {
219 zp->zlib_init = started; /* Data started. */
220 result = Curl_unencode_write(data, writer: writer->downstream, buf: decomp,
221 DSIZ - z->avail_out);
222 if(result) {
223 exit_zlib(data, z, zlib_init: &zp->zlib_init, result);
224 break;
225 }
226 }
227 }
228
229 /* Dispatch by inflate() status. */
230 switch(status) {
231 case Z_OK:
232 /* Always loop: there may be unflushed latched data in zlib state. */
233 done = FALSE;
234 break;
235 case Z_BUF_ERROR:
236 /* No more data to flush: just exit loop. */
237 break;
238 case Z_STREAM_END:
239 result = process_trailer(data, zp);
240 break;
241 case Z_DATA_ERROR:
242 /* some servers seem to not generate zlib headers, so this is an attempt
243 to fix and continue anyway */
244 if(zp->zlib_init == ZLIB_INIT) {
245 /* Do not use inflateReset2(): only available since zlib 1.2.3.4. */
246 (void) inflateEnd(strm: z); /* don't care about the return code */
247 if(inflateInit2(z, -MAX_WBITS) == Z_OK) {
248 z->next_in = orig_in;
249 z->avail_in = nread;
250 zp->zlib_init = ZLIB_INFLATING;
251 zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
252 done = FALSE;
253 break;
254 }
255 zp->zlib_init = ZLIB_UNINIT; /* inflateEnd() already called. */
256 }
257 result = exit_zlib(data, z, zlib_init: &zp->zlib_init, result: process_zlib_error(data, z));
258 break;
259 default:
260 result = exit_zlib(data, z, zlib_init: &zp->zlib_init, result: process_zlib_error(data, z));
261 break;
262 }
263 }
264 free(decomp);
265
266 /* We're about to leave this call so the `nread' data bytes won't be seen
267 again. If we are in a state that would wrongly allow restart in raw mode
268 at the next call, assume output has already started. */
269 if(nread && zp->zlib_init == ZLIB_INIT)
270 zp->zlib_init = started; /* Cannot restart anymore. */
271
272 return result;
273}
274
275
276/* Deflate handler. */
277static CURLcode deflate_init_writer(struct Curl_easy *data,
278 struct contenc_writer *writer)
279{
280 struct zlib_writer *zp = (struct zlib_writer *) writer;
281 z_stream *z = &zp->z; /* zlib state structure */
282
283 /* Initialize zlib */
284 z->zalloc = (alloc_func) zalloc_cb;
285 z->zfree = (free_func) zfree_cb;
286
287 if(inflateInit(z) != Z_OK)
288 return process_zlib_error(data, z);
289 zp->zlib_init = ZLIB_INIT;
290 return CURLE_OK;
291}
292
293static CURLcode deflate_unencode_write(struct Curl_easy *data,
294 struct contenc_writer *writer,
295 const char *buf, size_t nbytes)
296{
297 struct zlib_writer *zp = (struct zlib_writer *) writer;
298 z_stream *z = &zp->z; /* zlib state structure */
299
300 /* Set the compressed input when this function is called */
301 z->next_in = (Bytef *) buf;
302 z->avail_in = (uInt) nbytes;
303
304 if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
305 return process_trailer(data, zp);
306
307 /* Now uncompress the data */
308 return inflate_stream(data, writer, started: ZLIB_INFLATING);
309}
310
311static void deflate_close_writer(struct Curl_easy *data,
312 struct contenc_writer *writer)
313{
314 struct zlib_writer *zp = (struct zlib_writer *) writer;
315 z_stream *z = &zp->z; /* zlib state structure */
316
317 exit_zlib(data, z, zlib_init: &zp->zlib_init, result: CURLE_OK);
318}
319
320static const struct content_encoding deflate_encoding = {
321 "deflate",
322 NULL,
323 deflate_init_writer,
324 deflate_unencode_write,
325 deflate_close_writer,
326 sizeof(struct zlib_writer)
327};
328
329
330/* Gzip handler. */
331static CURLcode gzip_init_writer(struct Curl_easy *data,
332 struct contenc_writer *writer)
333{
334 struct zlib_writer *zp = (struct zlib_writer *) writer;
335 z_stream *z = &zp->z; /* zlib state structure */
336
337 /* Initialize zlib */
338 z->zalloc = (alloc_func) zalloc_cb;
339 z->zfree = (free_func) zfree_cb;
340
341 if(strcmp(s1: zlibVersion(), s2: "1.2.0.4") >= 0) {
342 /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
343 if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
344 return process_zlib_error(data, z);
345 }
346 zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
347 }
348 else {
349 /* we must parse the gzip header and trailer ourselves */
350 if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
351 return process_zlib_error(data, z);
352 }
353 zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
354 zp->zlib_init = ZLIB_INIT; /* Initial call state */
355 }
356
357 return CURLE_OK;
358}
359
360#ifdef OLD_ZLIB_SUPPORT
361/* Skip over the gzip header */
362static enum {
363 GZIP_OK,
364 GZIP_BAD,
365 GZIP_UNDERFLOW
366} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
367{
368 int method, flags;
369 const ssize_t totallen = len;
370
371 /* The shortest header is 10 bytes */
372 if(len < 10)
373 return GZIP_UNDERFLOW;
374
375 if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
376 return GZIP_BAD;
377
378 method = data[2];
379 flags = data[3];
380
381 if(method != Z_DEFLATED || (flags & RESERVED) != 0) {
382 /* Can't handle this compression method or unknown flag */
383 return GZIP_BAD;
384 }
385
386 /* Skip over time, xflags, OS code and all previous bytes */
387 len -= 10;
388 data += 10;
389
390 if(flags & EXTRA_FIELD) {
391 ssize_t extra_len;
392
393 if(len < 2)
394 return GZIP_UNDERFLOW;
395
396 extra_len = (data[1] << 8) | data[0];
397
398 if(len < (extra_len + 2))
399 return GZIP_UNDERFLOW;
400
401 len -= (extra_len + 2);
402 data += (extra_len + 2);
403 }
404
405 if(flags & ORIG_NAME) {
406 /* Skip over NUL-terminated file name */
407 while(len && *data) {
408 --len;
409 ++data;
410 }
411 if(!len || *data)
412 return GZIP_UNDERFLOW;
413
414 /* Skip over the NUL */
415 --len;
416 ++data;
417 }
418
419 if(flags & COMMENT) {
420 /* Skip over NUL-terminated comment */
421 while(len && *data) {
422 --len;
423 ++data;
424 }
425 if(!len || *data)
426 return GZIP_UNDERFLOW;
427
428 /* Skip over the NUL */
429 --len;
430 }
431
432 if(flags & HEAD_CRC) {
433 if(len < 2)
434 return GZIP_UNDERFLOW;
435
436 len -= 2;
437 }
438
439 *headerlen = totallen - len;
440 return GZIP_OK;
441}
442#endif
443
444static CURLcode gzip_unencode_write(struct Curl_easy *data,
445 struct contenc_writer *writer,
446 const char *buf, size_t nbytes)
447{
448 struct zlib_writer *zp = (struct zlib_writer *) writer;
449 z_stream *z = &zp->z; /* zlib state structure */
450
451 if(zp->zlib_init == ZLIB_INIT_GZIP) {
452 /* Let zlib handle the gzip decompression entirely */
453 z->next_in = (Bytef *) buf;
454 z->avail_in = (uInt) nbytes;
455 /* Now uncompress the data */
456 return inflate_stream(data, writer, started: ZLIB_INIT_GZIP);
457 }
458
459#ifndef OLD_ZLIB_SUPPORT
460 /* Support for old zlib versions is compiled away and we are running with
461 an old version, so return an error. */
462 return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
463
464#else
465 /* This next mess is to get around the potential case where there isn't
466 * enough data passed in to skip over the gzip header. If that happens, we
467 * malloc a block and copy what we have then wait for the next call. If
468 * there still isn't enough (this is definitely a worst-case scenario), we
469 * make the block bigger, copy the next part in and keep waiting.
470 *
471 * This is only required with zlib versions < 1.2.0.4 as newer versions
472 * can handle the gzip header themselves.
473 */
474
475 switch(zp->zlib_init) {
476 /* Skip over gzip header? */
477 case ZLIB_INIT:
478 {
479 /* Initial call state */
480 ssize_t hlen;
481
482 switch(check_gzip_header(data: (unsigned char *) buf, len: nbytes, headerlen: &hlen)) {
483 case GZIP_OK:
484 z->next_in = (Bytef *) buf + hlen;
485 z->avail_in = (uInt) (nbytes - hlen);
486 zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
487 break;
488
489 case GZIP_UNDERFLOW:
490 /* We need more data so we can find the end of the gzip header. It's
491 * possible that the memory block we malloc here will never be freed if
492 * the transfer abruptly aborts after this point. Since it's unlikely
493 * that circumstances will be right for this code path to be followed in
494 * the first place, and it's even more unlikely for a transfer to fail
495 * immediately afterwards, it should seldom be a problem.
496 */
497 z->avail_in = (uInt) nbytes;
498 z->next_in = malloc(z->avail_in);
499 if(!z->next_in) {
500 return exit_zlib(data, z, zlib_init: &zp->zlib_init, result: CURLE_OUT_OF_MEMORY);
501 }
502 memcpy(dest: z->next_in, src: buf, n: z->avail_in);
503 zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
504 /* We don't have any data to inflate yet */
505 return CURLE_OK;
506
507 case GZIP_BAD:
508 default:
509 return exit_zlib(data, z, zlib_init: &zp->zlib_init, result: process_zlib_error(data, z));
510 }
511
512 }
513 break;
514
515 case ZLIB_GZIP_HEADER:
516 {
517 /* Need more gzip header data state */
518 ssize_t hlen;
519 z->avail_in += (uInt) nbytes;
520 z->next_in = Curl_saferealloc(ptr: z->next_in, size: z->avail_in);
521 if(!z->next_in) {
522 return exit_zlib(data, z, zlib_init: &zp->zlib_init, result: CURLE_OUT_OF_MEMORY);
523 }
524 /* Append the new block of data to the previous one */
525 memcpy(dest: z->next_in + z->avail_in - nbytes, src: buf, n: nbytes);
526
527 switch(check_gzip_header(data: z->next_in, len: z->avail_in, headerlen: &hlen)) {
528 case GZIP_OK:
529 /* This is the zlib stream data */
530 free(z->next_in);
531 /* Don't point into the malloced block since we just freed it */
532 z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in;
533 z->avail_in = (uInt) (z->avail_in - hlen);
534 zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
535 break;
536
537 case GZIP_UNDERFLOW:
538 /* We still don't have any data to inflate! */
539 return CURLE_OK;
540
541 case GZIP_BAD:
542 default:
543 return exit_zlib(data, z, zlib_init: &zp->zlib_init, result: process_zlib_error(data, z));
544 }
545
546 }
547 break;
548
549 case ZLIB_EXTERNAL_TRAILER:
550 z->next_in = (Bytef *) buf;
551 z->avail_in = (uInt) nbytes;
552 return process_trailer(data, zp);
553
554 case ZLIB_GZIP_INFLATING:
555 default:
556 /* Inflating stream state */
557 z->next_in = (Bytef *) buf;
558 z->avail_in = (uInt) nbytes;
559 break;
560 }
561
562 if(z->avail_in == 0) {
563 /* We don't have any data to inflate; wait until next time */
564 return CURLE_OK;
565 }
566
567 /* We've parsed the header, now uncompress the data */
568 return inflate_stream(data, writer, started: ZLIB_GZIP_INFLATING);
569#endif
570}
571
572static void gzip_close_writer(struct Curl_easy *data,
573 struct contenc_writer *writer)
574{
575 struct zlib_writer *zp = (struct zlib_writer *) writer;
576 z_stream *z = &zp->z; /* zlib state structure */
577
578 exit_zlib(data, z, zlib_init: &zp->zlib_init, result: CURLE_OK);
579}
580
581static const struct content_encoding gzip_encoding = {
582 "gzip",
583 "x-gzip",
584 gzip_init_writer,
585 gzip_unencode_write,
586 gzip_close_writer,
587 sizeof(struct zlib_writer)
588};
589
590#endif /* HAVE_LIBZ */
591
592
593#ifdef HAVE_BROTLI
594/* Brotli writer. */
595struct brotli_writer {
596 struct contenc_writer super;
597 BrotliDecoderState *br; /* State structure for brotli. */
598};
599
600static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
601{
602 switch(be) {
603 case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:
604 case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:
605 case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:
606 case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:
607 case BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:
608 case BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:
609 case BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:
610 case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:
611 case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:
612 case BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:
613 case BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:
614 case BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:
615 case BROTLI_DECODER_ERROR_FORMAT_PADDING_1:
616 case BROTLI_DECODER_ERROR_FORMAT_PADDING_2:
617#ifdef BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY
618 case BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY:
619#endif
620#ifdef BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET
621 case BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:
622#endif
623 case BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:
624 return CURLE_BAD_CONTENT_ENCODING;
625 case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:
626 case BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:
627 case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:
628 case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:
629 case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:
630 case BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:
631 return CURLE_OUT_OF_MEMORY;
632 default:
633 break;
634 }
635 return CURLE_WRITE_ERROR;
636}
637
638static CURLcode brotli_init_writer(struct Curl_easy *data,
639 struct contenc_writer *writer)
640{
641 struct brotli_writer *bp = (struct brotli_writer *) writer;
642 (void) data;
643
644 bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
645 return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
646}
647
648static CURLcode brotli_unencode_write(struct Curl_easy *data,
649 struct contenc_writer *writer,
650 const char *buf, size_t nbytes)
651{
652 struct brotli_writer *bp = (struct brotli_writer *) writer;
653 const uint8_t *src = (const uint8_t *) buf;
654 char *decomp;
655 uint8_t *dst;
656 size_t dstleft;
657 CURLcode result = CURLE_OK;
658 BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
659
660 if(!bp->br)
661 return CURLE_WRITE_ERROR; /* Stream already ended. */
662
663 decomp = malloc(DSIZ);
664 if(!decomp)
665 return CURLE_OUT_OF_MEMORY;
666
667 while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) &&
668 result == CURLE_OK) {
669 dst = (uint8_t *) decomp;
670 dstleft = DSIZ;
671 r = BrotliDecoderDecompressStream(bp->br,
672 &nbytes, &src, &dstleft, &dst, NULL);
673 result = Curl_unencode_write(data, writer->downstream,
674 decomp, DSIZ - dstleft);
675 if(result)
676 break;
677 switch(r) {
678 case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
679 case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
680 break;
681 case BROTLI_DECODER_RESULT_SUCCESS:
682 BrotliDecoderDestroyInstance(bp->br);
683 bp->br = NULL;
684 if(nbytes)
685 result = CURLE_WRITE_ERROR;
686 break;
687 default:
688 result = brotli_map_error(BrotliDecoderGetErrorCode(bp->br));
689 break;
690 }
691 }
692 free(decomp);
693 return result;
694}
695
696static void brotli_close_writer(struct Curl_easy *data,
697 struct contenc_writer *writer)
698{
699 struct brotli_writer *bp = (struct brotli_writer *) writer;
700
701 (void) data;
702
703 if(bp->br) {
704 BrotliDecoderDestroyInstance(bp->br);
705 bp->br = NULL;
706 }
707}
708
709static const struct content_encoding brotli_encoding = {
710 "br",
711 NULL,
712 brotli_init_writer,
713 brotli_unencode_write,
714 brotli_close_writer,
715 sizeof(struct brotli_writer)
716};
717#endif
718
719
720#ifdef HAVE_ZSTD
721/* Zstd writer. */
722struct zstd_writer {
723 struct contenc_writer super;
724 ZSTD_DStream *zds; /* State structure for zstd. */
725 void *decomp;
726};
727
728static CURLcode zstd_init_writer(struct Curl_easy *data,
729 struct contenc_writer *writer)
730{
731 struct zstd_writer *zp = (struct zstd_writer *) writer;
732
733 (void)data;
734
735 zp->zds = ZSTD_createDStream();
736 zp->decomp = NULL;
737 return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
738}
739
740static CURLcode zstd_unencode_write(struct Curl_easy *data,
741 struct contenc_writer *writer,
742 const char *buf, size_t nbytes)
743{
744 CURLcode result = CURLE_OK;
745 struct zstd_writer *zp = (struct zstd_writer *) writer;
746 ZSTD_inBuffer in;
747 ZSTD_outBuffer out;
748 size_t errorCode;
749
750 if(!zp->decomp) {
751 zp->decomp = malloc(DSIZ);
752 if(!zp->decomp)
753 return CURLE_OUT_OF_MEMORY;
754 }
755 in.pos = 0;
756 in.src = buf;
757 in.size = nbytes;
758
759 for(;;) {
760 out.pos = 0;
761 out.dst = zp->decomp;
762 out.size = DSIZ;
763
764 errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
765 if(ZSTD_isError(errorCode)) {
766 return CURLE_BAD_CONTENT_ENCODING;
767 }
768 if(out.pos > 0) {
769 result = Curl_unencode_write(data, writer->downstream,
770 zp->decomp, out.pos);
771 if(result)
772 break;
773 }
774 if((in.pos == nbytes) && (out.pos < out.size))
775 break;
776 }
777
778 return result;
779}
780
781static void zstd_close_writer(struct Curl_easy *data,
782 struct contenc_writer *writer)
783{
784 struct zstd_writer *zp = (struct zstd_writer *) writer;
785
786 (void)data;
787
788 if(zp->decomp) {
789 free(zp->decomp);
790 zp->decomp = NULL;
791 }
792 if(zp->zds) {
793 ZSTD_freeDStream(zp->zds);
794 zp->zds = NULL;
795 }
796}
797
798static const struct content_encoding zstd_encoding = {
799 "zstd",
800 NULL,
801 zstd_init_writer,
802 zstd_unencode_write,
803 zstd_close_writer,
804 sizeof(struct zstd_writer)
805};
806#endif
807
808
809/* Identity handler. */
810static CURLcode identity_init_writer(struct Curl_easy *data,
811 struct contenc_writer *writer)
812{
813 (void)data;
814 (void)writer;
815 return CURLE_OK;
816}
817
818static CURLcode identity_unencode_write(struct Curl_easy *data,
819 struct contenc_writer *writer,
820 const char *buf, size_t nbytes)
821{
822 return Curl_unencode_write(data, writer: writer->downstream, buf, nbytes);
823}
824
825static void identity_close_writer(struct Curl_easy *data,
826 struct contenc_writer *writer)
827{
828 (void) data;
829 (void) writer;
830}
831
832static const struct content_encoding identity_encoding = {
833 "identity",
834 "none",
835 identity_init_writer,
836 identity_unencode_write,
837 identity_close_writer,
838 sizeof(struct contenc_writer)
839};
840
841
842/* supported content encodings table. */
843static const struct content_encoding * const encodings[] = {
844 &identity_encoding,
845#ifdef HAVE_LIBZ
846 &deflate_encoding,
847 &gzip_encoding,
848#endif
849#ifdef HAVE_BROTLI
850 &brotli_encoding,
851#endif
852#ifdef HAVE_ZSTD
853 &zstd_encoding,
854#endif
855 NULL
856};
857
858
859/* Return a list of comma-separated names of supported encodings. */
860char *Curl_all_content_encodings(void)
861{
862 size_t len = 0;
863 const struct content_encoding * const *cep;
864 const struct content_encoding *ce;
865 char *ace;
866
867 for(cep = encodings; *cep; cep++) {
868 ce = *cep;
869 if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT))
870 len += strlen(s: ce->name) + 2;
871 }
872
873 if(!len)
874 return strdup(CONTENT_ENCODING_DEFAULT);
875
876 ace = malloc(len);
877 if(ace) {
878 char *p = ace;
879 for(cep = encodings; *cep; cep++) {
880 ce = *cep;
881 if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
882 strcpy(dest: p, src: ce->name);
883 p += strlen(s: p);
884 *p++ = ',';
885 *p++ = ' ';
886 }
887 }
888 p[-2] = '\0';
889 }
890
891 return ace;
892}
893
894
895/* Deferred error dummy writer. */
896static CURLcode error_init_writer(struct Curl_easy *data,
897 struct contenc_writer *writer)
898{
899 (void)data;
900 (void)writer;
901 return CURLE_OK;
902}
903
904static CURLcode error_unencode_write(struct Curl_easy *data,
905 struct contenc_writer *writer,
906 const char *buf, size_t nbytes)
907{
908 char *all = Curl_all_content_encodings();
909
910 (void) writer;
911 (void) buf;
912 (void) nbytes;
913
914 if(!all)
915 return CURLE_OUT_OF_MEMORY;
916 failf(data, fmt: "Unrecognized content encoding type. "
917 "libcurl understands %s content encodings.", all);
918 free(all);
919 return CURLE_BAD_CONTENT_ENCODING;
920}
921
922static void error_close_writer(struct Curl_easy *data,
923 struct contenc_writer *writer)
924{
925 (void) data;
926 (void) writer;
927}
928
929static const struct content_encoding error_encoding = {
930 NULL,
931 NULL,
932 error_init_writer,
933 error_unencode_write,
934 error_close_writer,
935 sizeof(struct contenc_writer)
936};
937
938/* Write data using an unencoding writer stack. "nbytes" is not
939 allowed to be 0. */
940CURLcode Curl_unencode_write(struct Curl_easy *data,
941 struct contenc_writer *writer,
942 const char *buf, size_t nbytes)
943{
944 if(!nbytes)
945 return CURLE_OK;
946 if(!writer)
947 return CURLE_WRITE_ERROR;
948 return writer->handler->unencode_write(data, writer, buf, nbytes);
949}
950
951/* Find the content encoding by name. */
952static const struct content_encoding *find_encoding(const char *name,
953 size_t len)
954{
955 const struct content_encoding * const *cep;
956
957 for(cep = encodings; *cep; cep++) {
958 const struct content_encoding *ce = *cep;
959 if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
960 (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
961 return ce;
962 }
963 return NULL;
964}
965
966/* Set-up the unencoding stack from the Content-Encoding header value.
967 * See RFC 7231 section 3.1.2.2. */
968CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
969 const char *enclist, int is_transfer)
970{
971 struct SingleRequest *k = &data->req;
972 unsigned int order = is_transfer? 2: 1;
973 CURLcode result;
974
975 do {
976 const char *name;
977 size_t namelen;
978
979 /* Parse a single encoding name. */
980 while(ISBLANK(*enclist) || *enclist == ',')
981 enclist++;
982
983 name = enclist;
984
985 for(namelen = 0; *enclist && *enclist != ','; enclist++)
986 if(!ISSPACE(*enclist))
987 namelen = enclist - name + 1;
988
989 /* Special case: chunked encoding is handled at the reader level. */
990 if(is_transfer && namelen == 7 && strncasecompare(name, "chunked", 7)) {
991 k->chunk = TRUE; /* chunks coming our way. */
992 Curl_httpchunk_init(data); /* init our chunky engine. */
993 }
994 else if(namelen) {
995 const struct content_encoding *encoding;
996 struct contenc_writer *writer;
997 if(is_transfer && !data->set.http_transfer_encoding)
998 /* not requested, ignore */
999 return CURLE_OK;
1000
1001 encoding = find_encoding(name, len: namelen);
1002 if(!encoding)
1003 encoding = &error_encoding; /* Defer error at stack use. */
1004
1005 result = Curl_client_create_writer(pwriter: &writer, data, ce_handler: encoding, order);
1006 if(result)
1007 return result;
1008
1009 result = Curl_client_add_writer(data, writer);
1010 if(result) {
1011 Curl_client_free_writer(data, writer);
1012 return result;
1013 }
1014 }
1015 } while(*enclist);
1016
1017 return CURLE_OK;
1018}
1019
1020#else
1021/* Stubs for builds without HTTP. */
1022CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
1023 const char *enclist, int is_transfer)
1024{
1025 (void) data;
1026 (void) enclist;
1027 (void) is_transfer;
1028 return CURLE_NOT_BUILT_IN;
1029}
1030
1031CURLcode Curl_unencode_write(struct Curl_easy *data,
1032 struct contenc_writer *writer,
1033 const char *buf, size_t nbytes)
1034{
1035 (void) data;
1036 (void) writer;
1037 (void) buf;
1038 (void) nbytes;
1039 return CURLE_NOT_BUILT_IN;
1040}
1041
1042char *Curl_all_content_encodings(void)
1043{
1044 return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */
1045}
1046
1047#endif /* CURL_DISABLE_HTTP */
1048