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