Annotation of embedaddon/curl/lib/content_encoding.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>