content_encoding.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, 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. #include "curl_setup.h"
  25. #include "urldata.h"
  26. #include <curl/curl.h>
  27. #include <stddef.h>
  28. #ifdef HAVE_LIBZ
  29. #include <cm3p/zlib.h>
  30. #endif
  31. #ifdef HAVE_BROTLI
  32. #if defined(__GNUC__) || defined(__clang__)
  33. /* Ignore -Wvla warnings in brotli headers */
  34. #pragma GCC diagnostic push
  35. #pragma GCC diagnostic ignored "-Wvla"
  36. #endif
  37. #include <brotli/decode.h>
  38. #if defined(__GNUC__) || defined(__clang__)
  39. #pragma GCC diagnostic pop
  40. #endif
  41. #endif
  42. #ifdef HAVE_ZSTD
  43. #include <zstd.h>
  44. #endif
  45. #include "sendf.h"
  46. #include "http.h"
  47. #include "content_encoding.h"
  48. #include "strdup.h"
  49. #include "strcase.h"
  50. /* The last 3 #include files should be in this order */
  51. #include "curl_printf.h"
  52. #include "curl_memory.h"
  53. #include "memdebug.h"
  54. #define CONTENT_ENCODING_DEFAULT "identity"
  55. #ifndef CURL_DISABLE_HTTP
  56. /* allow no more than 5 "chained" compression steps */
  57. #define MAX_ENCODE_STACK 5
  58. #define DECOMPRESS_BUFFER_SIZE 16384 /* buffer size for decompressed data */
  59. #ifdef HAVE_LIBZ
  60. #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
  61. #error "requires zlib 1.2.0.4 or newer"
  62. #endif
  63. typedef enum {
  64. ZLIB_UNINIT, /* uninitialized */
  65. ZLIB_INIT, /* initialized */
  66. ZLIB_INFLATING, /* inflating started. */
  67. ZLIB_EXTERNAL_TRAILER, /* reading external trailer */
  68. ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
  69. } zlibInitState;
  70. /* Deflate and gzip writer. */
  71. struct zlib_writer {
  72. struct Curl_cwriter super;
  73. zlibInitState zlib_init; /* zlib init state */
  74. char buffer[DECOMPRESS_BUFFER_SIZE]; /* Put the decompressed data here. */
  75. uInt trailerlen; /* Remaining trailer byte count. */
  76. z_stream z; /* State structure for zlib. */
  77. };
  78. static voidpf
  79. zalloc_cb(voidpf opaque, unsigned int items, unsigned int size)
  80. {
  81. (void) opaque;
  82. /* not a typo, keep it calloc() */
  83. return (voidpf) calloc(items, size);
  84. }
  85. static void
  86. zfree_cb(voidpf opaque, voidpf ptr)
  87. {
  88. (void) opaque;
  89. free(ptr);
  90. }
  91. static CURLcode
  92. process_zlib_error(struct Curl_easy *data, z_stream *z)
  93. {
  94. if(z->msg)
  95. failf(data, "Error while processing content unencoding: %s",
  96. z->msg);
  97. else
  98. failf(data, "Error while processing content unencoding: "
  99. "Unknown failure within decompression software.");
  100. return CURLE_BAD_CONTENT_ENCODING;
  101. }
  102. static CURLcode
  103. exit_zlib(struct Curl_easy *data,
  104. z_stream *z, zlibInitState *zlib_init, CURLcode result)
  105. {
  106. if(*zlib_init != ZLIB_UNINIT) {
  107. if(inflateEnd(z) != Z_OK && result == CURLE_OK)
  108. result = process_zlib_error(data, z);
  109. *zlib_init = ZLIB_UNINIT;
  110. }
  111. return result;
  112. }
  113. static CURLcode process_trailer(struct Curl_easy *data,
  114. struct zlib_writer *zp)
  115. {
  116. z_stream *z = &zp->z;
  117. CURLcode result = CURLE_OK;
  118. uInt len = z->avail_in < zp->trailerlen ? z->avail_in : zp->trailerlen;
  119. /* Consume expected trailer bytes. Terminate stream if exhausted.
  120. Issue an error if unexpected bytes follow. */
  121. zp->trailerlen -= len;
  122. z->avail_in -= len;
  123. z->next_in += len;
  124. if(z->avail_in)
  125. result = CURLE_WRITE_ERROR;
  126. if(result || !zp->trailerlen)
  127. result = exit_zlib(data, z, &zp->zlib_init, result);
  128. else {
  129. /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
  130. zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
  131. }
  132. return result;
  133. }
  134. static CURLcode inflate_stream(struct Curl_easy *data,
  135. struct Curl_cwriter *writer, int type,
  136. zlibInitState started)
  137. {
  138. struct zlib_writer *zp = (struct zlib_writer *) writer;
  139. z_stream *z = &zp->z; /* zlib state structure */
  140. uInt nread = z->avail_in;
  141. Bytef *orig_in = z->next_in;
  142. bool done = FALSE;
  143. CURLcode result = CURLE_OK; /* Curl_client_write status */
  144. /* Check state. */
  145. if(zp->zlib_init != ZLIB_INIT &&
  146. zp->zlib_init != ZLIB_INFLATING &&
  147. zp->zlib_init != ZLIB_INIT_GZIP)
  148. return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
  149. /* because the buffer size is fixed, iteratively decompress and transfer to
  150. the client via next_write function. */
  151. while(!done) {
  152. int status; /* zlib status */
  153. done = TRUE;
  154. /* (re)set buffer for decompressed output for every iteration */
  155. z->next_out = (Bytef *) zp->buffer;
  156. z->avail_out = DECOMPRESS_BUFFER_SIZE;
  157. #ifdef Z_BLOCK
  158. /* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */
  159. status = inflate(z, Z_BLOCK);
  160. #else
  161. /* fallback for zlib ver. < 1.2.0.5 */
  162. status = inflate(z, Z_SYNC_FLUSH);
  163. #endif
  164. /* Flush output data if some. */
  165. if(z->avail_out != DECOMPRESS_BUFFER_SIZE) {
  166. if(status == Z_OK || status == Z_STREAM_END) {
  167. zp->zlib_init = started; /* Data started. */
  168. result = Curl_cwriter_write(data, writer->next, type, zp->buffer,
  169. DECOMPRESS_BUFFER_SIZE - z->avail_out);
  170. if(result) {
  171. exit_zlib(data, z, &zp->zlib_init, result);
  172. break;
  173. }
  174. }
  175. }
  176. /* Dispatch by inflate() status. */
  177. switch(status) {
  178. case Z_OK:
  179. /* Always loop: there may be unflushed latched data in zlib state. */
  180. done = FALSE;
  181. break;
  182. case Z_BUF_ERROR:
  183. /* No more data to flush: just exit loop. */
  184. break;
  185. case Z_STREAM_END:
  186. result = process_trailer(data, zp);
  187. break;
  188. case Z_DATA_ERROR:
  189. /* some servers seem to not generate zlib headers, so this is an attempt
  190. to fix and continue anyway */
  191. if(zp->zlib_init == ZLIB_INIT) {
  192. /* Do not use inflateReset2(): only available since zlib 1.2.3.4. */
  193. (void) inflateEnd(z); /* do not care about the return code */
  194. if(inflateInit2(z, -MAX_WBITS) == Z_OK) {
  195. z->next_in = orig_in;
  196. z->avail_in = nread;
  197. zp->zlib_init = ZLIB_INFLATING;
  198. zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
  199. done = FALSE;
  200. break;
  201. }
  202. zp->zlib_init = ZLIB_UNINIT; /* inflateEnd() already called. */
  203. }
  204. result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
  205. break;
  206. default:
  207. result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
  208. break;
  209. }
  210. }
  211. /* We are about to leave this call so the `nread' data bytes will not be seen
  212. again. If we are in a state that would wrongly allow restart in raw mode
  213. at the next call, assume output has already started. */
  214. if(nread && zp->zlib_init == ZLIB_INIT)
  215. zp->zlib_init = started; /* Cannot restart anymore. */
  216. return result;
  217. }
  218. /* Deflate handler. */
  219. static CURLcode deflate_do_init(struct Curl_easy *data,
  220. struct Curl_cwriter *writer)
  221. {
  222. struct zlib_writer *zp = (struct zlib_writer *) writer;
  223. z_stream *z = &zp->z; /* zlib state structure */
  224. /* Initialize zlib */
  225. z->zalloc = (alloc_func) zalloc_cb;
  226. z->zfree = (free_func) zfree_cb;
  227. if(inflateInit(z) != Z_OK)
  228. return process_zlib_error(data, z);
  229. zp->zlib_init = ZLIB_INIT;
  230. return CURLE_OK;
  231. }
  232. static CURLcode deflate_do_write(struct Curl_easy *data,
  233. struct Curl_cwriter *writer, int type,
  234. const char *buf, size_t nbytes)
  235. {
  236. struct zlib_writer *zp = (struct zlib_writer *) writer;
  237. z_stream *z = &zp->z; /* zlib state structure */
  238. if(!(type & CLIENTWRITE_BODY) || !nbytes)
  239. return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
  240. /* Set the compressed input when this function is called */
  241. z->next_in = (Bytef *) buf;
  242. z->avail_in = (uInt) nbytes;
  243. if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
  244. return process_trailer(data, zp);
  245. /* Now uncompress the data */
  246. return inflate_stream(data, writer, type, ZLIB_INFLATING);
  247. }
  248. static void deflate_do_close(struct Curl_easy *data,
  249. struct Curl_cwriter *writer)
  250. {
  251. struct zlib_writer *zp = (struct zlib_writer *) writer;
  252. z_stream *z = &zp->z; /* zlib state structure */
  253. exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
  254. }
  255. static const struct Curl_cwtype deflate_encoding = {
  256. "deflate",
  257. NULL,
  258. deflate_do_init,
  259. deflate_do_write,
  260. deflate_do_close,
  261. sizeof(struct zlib_writer)
  262. };
  263. /* Gzip handler. */
  264. static CURLcode gzip_do_init(struct Curl_easy *data,
  265. struct Curl_cwriter *writer)
  266. {
  267. struct zlib_writer *zp = (struct zlib_writer *) writer;
  268. z_stream *z = &zp->z; /* zlib state structure */
  269. /* Initialize zlib */
  270. z->zalloc = (alloc_func) zalloc_cb;
  271. z->zfree = (free_func) zfree_cb;
  272. if(inflateInit2(z, MAX_WBITS + 32) != Z_OK)
  273. return process_zlib_error(data, z);
  274. zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
  275. return CURLE_OK;
  276. }
  277. static CURLcode gzip_do_write(struct Curl_easy *data,
  278. struct Curl_cwriter *writer, int type,
  279. const char *buf, size_t nbytes)
  280. {
  281. struct zlib_writer *zp = (struct zlib_writer *) writer;
  282. z_stream *z = &zp->z; /* zlib state structure */
  283. if(!(type & CLIENTWRITE_BODY) || !nbytes)
  284. return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
  285. if(zp->zlib_init == ZLIB_INIT_GZIP) {
  286. /* Let zlib handle the gzip decompression entirely */
  287. z->next_in = (Bytef *) buf;
  288. z->avail_in = (uInt) nbytes;
  289. /* Now uncompress the data */
  290. return inflate_stream(data, writer, type, ZLIB_INIT_GZIP);
  291. }
  292. /* We are running with an old version: return error. */
  293. return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
  294. }
  295. static void gzip_do_close(struct Curl_easy *data,
  296. struct Curl_cwriter *writer)
  297. {
  298. struct zlib_writer *zp = (struct zlib_writer *) writer;
  299. z_stream *z = &zp->z; /* zlib state structure */
  300. exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
  301. }
  302. static const struct Curl_cwtype gzip_encoding = {
  303. "gzip",
  304. "x-gzip",
  305. gzip_do_init,
  306. gzip_do_write,
  307. gzip_do_close,
  308. sizeof(struct zlib_writer)
  309. };
  310. #endif /* HAVE_LIBZ */
  311. #ifdef HAVE_BROTLI
  312. /* Brotli writer. */
  313. struct brotli_writer {
  314. struct Curl_cwriter super;
  315. char buffer[DECOMPRESS_BUFFER_SIZE];
  316. BrotliDecoderState *br; /* State structure for brotli. */
  317. };
  318. static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
  319. {
  320. switch(be) {
  321. case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:
  322. case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:
  323. case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:
  324. case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:
  325. case BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:
  326. case BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:
  327. case BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:
  328. case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:
  329. case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:
  330. case BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:
  331. case BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:
  332. case BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:
  333. case BROTLI_DECODER_ERROR_FORMAT_PADDING_1:
  334. case BROTLI_DECODER_ERROR_FORMAT_PADDING_2:
  335. #ifdef BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY
  336. case BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY:
  337. #endif
  338. #ifdef BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET
  339. case BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:
  340. #endif
  341. case BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:
  342. return CURLE_BAD_CONTENT_ENCODING;
  343. case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:
  344. case BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:
  345. case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:
  346. case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:
  347. case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:
  348. case BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:
  349. return CURLE_OUT_OF_MEMORY;
  350. default:
  351. break;
  352. }
  353. return CURLE_WRITE_ERROR;
  354. }
  355. static CURLcode brotli_do_init(struct Curl_easy *data,
  356. struct Curl_cwriter *writer)
  357. {
  358. struct brotli_writer *bp = (struct brotli_writer *) writer;
  359. (void) data;
  360. bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
  361. return bp->br ? CURLE_OK : CURLE_OUT_OF_MEMORY;
  362. }
  363. static CURLcode brotli_do_write(struct Curl_easy *data,
  364. struct Curl_cwriter *writer, int type,
  365. const char *buf, size_t nbytes)
  366. {
  367. struct brotli_writer *bp = (struct brotli_writer *) writer;
  368. const uint8_t *src = (const uint8_t *) buf;
  369. uint8_t *dst;
  370. size_t dstleft;
  371. CURLcode result = CURLE_OK;
  372. BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
  373. if(!(type & CLIENTWRITE_BODY) || !nbytes)
  374. return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
  375. if(!bp->br)
  376. return CURLE_WRITE_ERROR; /* Stream already ended. */
  377. while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) &&
  378. result == CURLE_OK) {
  379. dst = (uint8_t *) bp->buffer;
  380. dstleft = DECOMPRESS_BUFFER_SIZE;
  381. r = BrotliDecoderDecompressStream(bp->br,
  382. &nbytes, &src, &dstleft, &dst, NULL);
  383. result = Curl_cwriter_write(data, writer->next, type,
  384. bp->buffer, DECOMPRESS_BUFFER_SIZE - dstleft);
  385. if(result)
  386. break;
  387. switch(r) {
  388. case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
  389. case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
  390. break;
  391. case BROTLI_DECODER_RESULT_SUCCESS:
  392. BrotliDecoderDestroyInstance(bp->br);
  393. bp->br = NULL;
  394. if(nbytes)
  395. result = CURLE_WRITE_ERROR;
  396. break;
  397. default:
  398. result = brotli_map_error(BrotliDecoderGetErrorCode(bp->br));
  399. break;
  400. }
  401. }
  402. return result;
  403. }
  404. static void brotli_do_close(struct Curl_easy *data,
  405. struct Curl_cwriter *writer)
  406. {
  407. struct brotli_writer *bp = (struct brotli_writer *) writer;
  408. (void) data;
  409. if(bp->br) {
  410. BrotliDecoderDestroyInstance(bp->br);
  411. bp->br = NULL;
  412. }
  413. }
  414. static const struct Curl_cwtype brotli_encoding = {
  415. "br",
  416. NULL,
  417. brotli_do_init,
  418. brotli_do_write,
  419. brotli_do_close,
  420. sizeof(struct brotli_writer)
  421. };
  422. #endif
  423. #ifdef HAVE_ZSTD
  424. /* Zstd writer. */
  425. struct zstd_writer {
  426. struct Curl_cwriter super;
  427. ZSTD_DStream *zds; /* State structure for zstd. */
  428. char buffer[DECOMPRESS_BUFFER_SIZE];
  429. };
  430. #ifdef ZSTD_STATIC_LINKING_ONLY
  431. static void *Curl_zstd_alloc(void *opaque, size_t size)
  432. {
  433. (void)opaque;
  434. return Curl_cmalloc(size);
  435. }
  436. static void Curl_zstd_free(void *opaque, void *address)
  437. {
  438. (void)opaque;
  439. Curl_cfree(address);
  440. }
  441. #endif
  442. static CURLcode zstd_do_init(struct Curl_easy *data,
  443. struct Curl_cwriter *writer)
  444. {
  445. struct zstd_writer *zp = (struct zstd_writer *) writer;
  446. (void)data;
  447. #ifdef ZSTD_STATIC_LINKING_ONLY
  448. zp->zds = ZSTD_createDStream_advanced((ZSTD_customMem) {
  449. .customAlloc = Curl_zstd_alloc,
  450. .customFree = Curl_zstd_free,
  451. .opaque = NULL
  452. });
  453. #else
  454. zp->zds = ZSTD_createDStream();
  455. #endif
  456. return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
  457. }
  458. static CURLcode zstd_do_write(struct Curl_easy *data,
  459. struct Curl_cwriter *writer, int type,
  460. const char *buf, size_t nbytes)
  461. {
  462. CURLcode result = CURLE_OK;
  463. struct zstd_writer *zp = (struct zstd_writer *) writer;
  464. ZSTD_inBuffer in;
  465. ZSTD_outBuffer out;
  466. size_t errorCode;
  467. if(!(type & CLIENTWRITE_BODY) || !nbytes)
  468. return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
  469. in.pos = 0;
  470. in.src = buf;
  471. in.size = nbytes;
  472. for(;;) {
  473. out.pos = 0;
  474. out.dst = zp->buffer;
  475. out.size = DECOMPRESS_BUFFER_SIZE;
  476. errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
  477. if(ZSTD_isError(errorCode)) {
  478. return CURLE_BAD_CONTENT_ENCODING;
  479. }
  480. if(out.pos > 0) {
  481. result = Curl_cwriter_write(data, writer->next, type,
  482. zp->buffer, out.pos);
  483. if(result)
  484. break;
  485. }
  486. if((in.pos == nbytes) && (out.pos < out.size))
  487. break;
  488. }
  489. return result;
  490. }
  491. static void zstd_do_close(struct Curl_easy *data,
  492. struct Curl_cwriter *writer)
  493. {
  494. struct zstd_writer *zp = (struct zstd_writer *) writer;
  495. (void)data;
  496. if(zp->zds) {
  497. ZSTD_freeDStream(zp->zds);
  498. zp->zds = NULL;
  499. }
  500. }
  501. static const struct Curl_cwtype zstd_encoding = {
  502. "zstd",
  503. NULL,
  504. zstd_do_init,
  505. zstd_do_write,
  506. zstd_do_close,
  507. sizeof(struct zstd_writer)
  508. };
  509. #endif
  510. /* Identity handler. */
  511. static const struct Curl_cwtype identity_encoding = {
  512. "identity",
  513. "none",
  514. Curl_cwriter_def_init,
  515. Curl_cwriter_def_write,
  516. Curl_cwriter_def_close,
  517. sizeof(struct Curl_cwriter)
  518. };
  519. /* supported general content decoders. */
  520. static const struct Curl_cwtype * const general_unencoders[] = {
  521. &identity_encoding,
  522. #ifdef HAVE_LIBZ
  523. &deflate_encoding,
  524. &gzip_encoding,
  525. #endif
  526. #ifdef HAVE_BROTLI
  527. &brotli_encoding,
  528. #endif
  529. #ifdef HAVE_ZSTD
  530. &zstd_encoding,
  531. #endif
  532. NULL
  533. };
  534. /* supported content decoders only for transfer encodings */
  535. static const struct Curl_cwtype * const transfer_unencoders[] = {
  536. #ifndef CURL_DISABLE_HTTP
  537. &Curl_httpchunk_unencoder,
  538. #endif
  539. NULL
  540. };
  541. /* Provide a list of comma-separated names of supported encodings.
  542. */
  543. void Curl_all_content_encodings(char *buf, size_t blen)
  544. {
  545. size_t len = 0;
  546. const struct Curl_cwtype * const *cep;
  547. const struct Curl_cwtype *ce;
  548. DEBUGASSERT(buf);
  549. DEBUGASSERT(blen);
  550. buf[0] = 0;
  551. for(cep = general_unencoders; *cep; cep++) {
  552. ce = *cep;
  553. if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT))
  554. len += strlen(ce->name) + 2;
  555. }
  556. if(!len) {
  557. if(blen >= sizeof(CONTENT_ENCODING_DEFAULT))
  558. strcpy(buf, CONTENT_ENCODING_DEFAULT);
  559. }
  560. else if(blen > len) {
  561. char *p = buf;
  562. for(cep = general_unencoders; *cep; cep++) {
  563. ce = *cep;
  564. if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
  565. strcpy(p, ce->name);
  566. p += strlen(p);
  567. *p++ = ',';
  568. *p++ = ' ';
  569. }
  570. }
  571. p[-2] = '\0';
  572. }
  573. }
  574. /* Deferred error dummy writer. */
  575. static CURLcode error_do_init(struct Curl_easy *data,
  576. struct Curl_cwriter *writer)
  577. {
  578. (void)data;
  579. (void)writer;
  580. return CURLE_OK;
  581. }
  582. static CURLcode error_do_write(struct Curl_easy *data,
  583. struct Curl_cwriter *writer, int type,
  584. const char *buf, size_t nbytes)
  585. {
  586. (void) writer;
  587. (void) buf;
  588. (void) nbytes;
  589. if(!(type & CLIENTWRITE_BODY) || !nbytes)
  590. return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
  591. else {
  592. char all[256];
  593. (void)Curl_all_content_encodings(all, sizeof(all));
  594. failf(data, "Unrecognized content encoding type. "
  595. "libcurl understands %s content encodings.", all);
  596. }
  597. return CURLE_BAD_CONTENT_ENCODING;
  598. }
  599. static void error_do_close(struct Curl_easy *data,
  600. struct Curl_cwriter *writer)
  601. {
  602. (void) data;
  603. (void) writer;
  604. }
  605. static const struct Curl_cwtype error_writer = {
  606. "ce-error",
  607. NULL,
  608. error_do_init,
  609. error_do_write,
  610. error_do_close,
  611. sizeof(struct Curl_cwriter)
  612. };
  613. /* Find the content encoding by name. */
  614. static const struct Curl_cwtype *find_unencode_writer(const char *name,
  615. size_t len,
  616. Curl_cwriter_phase phase)
  617. {
  618. const struct Curl_cwtype * const *cep;
  619. if(phase == CURL_CW_TRANSFER_DECODE) {
  620. for(cep = transfer_unencoders; *cep; cep++) {
  621. const struct Curl_cwtype *ce = *cep;
  622. if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
  623. (ce->alias && strncasecompare(name, ce->alias, len)
  624. && !ce->alias[len]))
  625. return ce;
  626. }
  627. }
  628. /* look among the general decoders */
  629. for(cep = general_unencoders; *cep; cep++) {
  630. const struct Curl_cwtype *ce = *cep;
  631. if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
  632. (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
  633. return ce;
  634. }
  635. return NULL;
  636. }
  637. /* Setup the unencoding stack from the Content-Encoding header value.
  638. * See RFC 7231 section 3.1.2.2. */
  639. CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
  640. const char *enclist, int is_transfer)
  641. {
  642. Curl_cwriter_phase phase = is_transfer ?
  643. CURL_CW_TRANSFER_DECODE : CURL_CW_CONTENT_DECODE;
  644. CURLcode result;
  645. do {
  646. const char *name;
  647. size_t namelen;
  648. bool is_chunked = FALSE;
  649. /* Parse a single encoding name. */
  650. while(ISBLANK(*enclist) || *enclist == ',')
  651. enclist++;
  652. name = enclist;
  653. for(namelen = 0; *enclist && *enclist != ','; enclist++)
  654. if(!ISSPACE(*enclist))
  655. namelen = enclist - name + 1;
  656. if(namelen) {
  657. const struct Curl_cwtype *cwt;
  658. struct Curl_cwriter *writer;
  659. CURL_TRC_WRITE(data, "looking for %s decoder: %.*s",
  660. is_transfer ? "transfer" : "content", (int)namelen, name);
  661. is_chunked = (is_transfer && (namelen == 7) &&
  662. strncasecompare(name, "chunked", 7));
  663. /* if we skip the decoding in this phase, do not look further.
  664. * Exception is "chunked" transfer-encoding which always must happen */
  665. if((is_transfer && !data->set.http_transfer_encoding && !is_chunked) ||
  666. (!is_transfer && data->set.http_ce_skip)) {
  667. /* not requested, ignore */
  668. CURL_TRC_WRITE(data, "decoder not requested, ignored: %.*s",
  669. (int)namelen, name);
  670. return CURLE_OK;
  671. }
  672. if(Curl_cwriter_count(data, phase) + 1 >= MAX_ENCODE_STACK) {
  673. failf(data, "Reject response due to more than %u content encodings",
  674. MAX_ENCODE_STACK);
  675. return CURLE_BAD_CONTENT_ENCODING;
  676. }
  677. cwt = find_unencode_writer(name, namelen, phase);
  678. if(cwt && is_chunked && Curl_cwriter_get_by_type(data, cwt)) {
  679. /* A 'chunked' transfer encoding has already been added.
  680. * Ignore duplicates. See #13451.
  681. * Also RFC 9112, ch. 6.1:
  682. * "A sender MUST NOT apply the chunked transfer coding more than
  683. * once to a message body."
  684. */
  685. CURL_TRC_WRITE(data, "ignoring duplicate 'chunked' decoder");
  686. return CURLE_OK;
  687. }
  688. if(is_transfer && !is_chunked &&
  689. Curl_cwriter_get_by_name(data, "chunked")) {
  690. /* RFC 9112, ch. 6.1:
  691. * "If any transfer coding other than chunked is applied to a
  692. * response's content, the sender MUST either apply chunked as the
  693. * final transfer coding or terminate the message by closing the
  694. * connection."
  695. * "chunked" must be the last added to be the first in its phase,
  696. * reject this.
  697. */
  698. failf(data, "Reject response due to 'chunked' not being the last "
  699. "Transfer-Encoding");
  700. return CURLE_BAD_CONTENT_ENCODING;
  701. }
  702. if(!cwt)
  703. cwt = &error_writer; /* Defer error at use. */
  704. result = Curl_cwriter_create(&writer, data, cwt, phase);
  705. CURL_TRC_WRITE(data, "added %s decoder %s -> %d",
  706. is_transfer ? "transfer" : "content", cwt->name, result);
  707. if(result)
  708. return result;
  709. result = Curl_cwriter_add(data, writer);
  710. if(result) {
  711. Curl_cwriter_free(data, writer);
  712. return result;
  713. }
  714. }
  715. } while(*enclist);
  716. return CURLE_OK;
  717. }
  718. #else
  719. /* Stubs for builds without HTTP. */
  720. CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
  721. const char *enclist, int is_transfer)
  722. {
  723. (void) data;
  724. (void) enclist;
  725. (void) is_transfer;
  726. return CURLE_NOT_BUILT_IN;
  727. }
  728. void Curl_all_content_encodings(char *buf, size_t blen)
  729. {
  730. DEBUGASSERT(buf);
  731. DEBUGASSERT(blen);
  732. if(blen < sizeof(CONTENT_ENCODING_DEFAULT))
  733. buf[0] = 0;
  734. else
  735. strcpy(buf, CONTENT_ENCODING_DEFAULT);
  736. }
  737. #endif /* CURL_DISABLE_HTTP */