CURLcode Curl_unencode_deflate_write(struct connectdata *conn, struct SingleRequest *k, ssize_t nread) { z_stream *z = &k->z; /* zlib state structure */ /* Initialize zlib? */ if(k->zlib_init == ZLIB_UNINIT) { z->zalloc = (alloc_func)Z_NULL; z->zfree = (free_func)Z_NULL; z->opaque = 0; z->next_in = NULL; z->avail_in = 0; if(inflateInit(z) != Z_OK) return process_zlib_error(conn, z); k->zlib_init = ZLIB_INIT; } /* Set the compressed input when this function is called */ z->next_in = (Bytef *)k->str; z->avail_in = (uInt)nread; /* Now uncompress the data */ return inflate_stream(conn, k); }
static CURLcode deflate_unencode_write(struct connectdata *conn, contenc_writer *writer, const char *buf, size_t nbytes) { zlib_params *zp = (zlib_params *) &writer->params; z_stream *z = &zp->z; /* zlib state structure */ /* Set the compressed input when this function is called */ z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; /* Now uncompress the data */ return inflate_stream(conn, writer, ZLIB_INFLATING); }
int main(int argc, char *argv[]) { enum program_mode { MODE_UNSPECIFIED, MODE_DEFLATE, MODE_INFLATE }; enum program_mode mode = MODE_UNSPECIFIED; FILE *source = stdin; FILE *sink = stdout; int optchar; /* * Get options */ while ((optchar = getopt(argc, argv, "dih")) != -1) { switch (optchar) { case 'd': mode = MODE_DEFLATE; break; case 'i': mode = MODE_INFLATE; break; case 'h': show_usage(stdout); exit(EXIT_SUCCESS); default: show_usage(stderr); exit(EX_USAGE); } } argc -= optind; argv += optind; switch (mode) { case MODE_UNSPECIFIED: (void) fputs("Operation mode is not specified.\n", stderr); show_usage(stderr); exit(EX_USAGE); case MODE_DEFLATE: deflate_stream(source, sink); break; case MODE_INFLATE: inflate_stream(source, sink); break; } return EXIT_SUCCESS; }
CURLcode Curl_unencode_gzip_write(struct connectdata *conn, struct SingleRequest *k, ssize_t nread) { z_stream *z = &k->z; /* zlib state structure */ /* Initialize zlib? */ if(k->zlib_init == ZLIB_UNINIT) { z->zalloc = (alloc_func)Z_NULL; z->zfree = (free_func)Z_NULL; z->opaque = 0; z->next_in = NULL; z->avail_in = 0; if(strcmp(ZLIB_VERSION, "1.2.0.4") >= 0) { /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ if(inflateInit2(z, MAX_WBITS+32) != Z_OK) { return process_zlib_error(conn, z); } k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ } else { /* we must parse the gzip header ourselves */ if(inflateInit2(z, -MAX_WBITS) != Z_OK) { return process_zlib_error(conn, z); } k->zlib_init = ZLIB_INIT; /* Initial call state */ } } if(k->zlib_init == ZLIB_INIT_GZIP) { /* Let zlib handle the gzip decompression entirely */ z->next_in = (Bytef *)k->str; z->avail_in = (uInt)nread; /* Now uncompress the data */ return inflate_stream(conn, k); } #ifndef OLD_ZLIB_SUPPORT /* Support for old zlib versions is compiled away and we are running with an old version, so return an error. */ return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND); #else /* This next mess is to get around the potential case where there isn't * enough data passed in to skip over the gzip header. If that happens, we * malloc a block and copy what we have then wait for the next call. If * there still isn't enough (this is definitely a worst-case scenario), we * make the block bigger, copy the next part in and keep waiting. * * This is only required with zlib versions < 1.2.0.4 as newer versions * can handle the gzip header themselves. */ switch (k->zlib_init) { /* Skip over gzip header? */ case ZLIB_INIT: { /* Initial call state */ ssize_t hlen; switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) { case GZIP_OK: z->next_in = (Bytef *)k->str + hlen; z->avail_in = (uInt)(nread - hlen); k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ break; case GZIP_UNDERFLOW: /* We need more data so we can find the end of the gzip header. It's * possible that the memory block we malloc here will never be freed if * the transfer abruptly aborts after this point. Since it's unlikely * that circumstances will be right for this code path to be followed in * the first place, and it's even more unlikely for a transfer to fail * immediately afterwards, it should seldom be a problem. */ z->avail_in = (uInt)nread; z->next_in = (curlNamespace::z_Bytef *) malloc(z->avail_in); if(z->next_in == NULL) { return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } memcpy(z->next_in, k->str, z->avail_in); k->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ /* We don't have any data to inflate yet */ return CURLE_OK; case GZIP_BAD: default: return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); } } break; case ZLIB_GZIP_HEADER: { /* Need more gzip header data state */ ssize_t hlen; unsigned char *oldblock = z->next_in; z->avail_in += nread; z->next_in = (curlNamespace::z_Bytef *) realloc(z->next_in, z->avail_in); if(z->next_in == NULL) { free(oldblock); return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ memcpy(z->next_in + z->avail_in - nread, k->str, nread); switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) { case GZIP_OK: /* This is the zlib stream data */ free(z->next_in); /* Don't point into the malloced block since we just freed it */ z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in; z->avail_in = (uInt)(z->avail_in - hlen); k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ break; case GZIP_UNDERFLOW: /* We still don't have any data to inflate! */ return CURLE_OK; case GZIP_BAD: default: free(z->next_in); return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); } } break; case ZLIB_GZIP_INFLATING: default: /* Inflating stream state */ z->next_in = (Bytef *)k->str; z->avail_in = (uInt)nread; break; } if(z->avail_in == 0) { /* We don't have any data to inflate; wait until next time */ return CURLE_OK; } /* We've parsed the header, now uncompress the data */ return inflate_stream(conn, k); #endif }
static CURLcode gzip_unencode_write(struct connectdata *conn, contenc_writer *writer, const char *buf, size_t nbytes) { zlib_params *zp = (zlib_params *) &writer->params; z_stream *z = &zp->z; /* zlib state structure */ if(zp->zlib_init == ZLIB_INIT_GZIP) { /* Let zlib handle the gzip decompression entirely */ z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; /* Now uncompress the data */ return inflate_stream(conn, writer, ZLIB_INIT_GZIP); } #ifndef OLD_ZLIB_SUPPORT /* Support for old zlib versions is compiled away and we are running with an old version, so return an error. */ return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); #else /* This next mess is to get around the potential case where there isn't * enough data passed in to skip over the gzip header. If that happens, we * malloc a block and copy what we have then wait for the next call. If * there still isn't enough (this is definitely a worst-case scenario), we * make the block bigger, copy the next part in and keep waiting. * * This is only required with zlib versions < 1.2.0.4 as newer versions * can handle the gzip header themselves. */ switch(zp->zlib_init) { /* Skip over gzip header? */ case ZLIB_INIT: { /* Initial call state */ ssize_t hlen; switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) { case GZIP_OK: z->next_in = (Bytef *) buf + hlen; z->avail_in = (uInt) (nbytes - hlen); zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ break; case GZIP_UNDERFLOW: /* We need more data so we can find the end of the gzip header. It's * possible that the memory block we malloc here will never be freed if * the transfer abruptly aborts after this point. Since it's unlikely * that circumstances will be right for this code path to be followed in * the first place, and it's even more unlikely for a transfer to fail * immediately afterwards, it should seldom be a problem. */ z->avail_in = (uInt) nbytes; z->next_in = malloc(z->avail_in); if(z->next_in == NULL) { return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } memcpy(z->next_in, buf, z->avail_in); zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ /* We don't have any data to inflate yet */ return CURLE_OK; case GZIP_BAD: default: return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); } } break; case ZLIB_GZIP_HEADER: { /* Need more gzip header data state */ ssize_t hlen; z->avail_in += (uInt) nbytes; z->next_in = Curl_saferealloc(z->next_in, z->avail_in); if(z->next_in == NULL) { return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes); switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) { case GZIP_OK: /* This is the zlib stream data */ free(z->next_in); /* Don't point into the malloced block since we just freed it */ z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in; z->avail_in = (uInt) (z->avail_in - hlen); zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ break; case GZIP_UNDERFLOW: /* We still don't have any data to inflate! */ return CURLE_OK; case GZIP_BAD: default: return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); } } break; case ZLIB_GZIP_TRAILER: z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; return process_trailer(conn, zp); case ZLIB_GZIP_INFLATING: default: /* Inflating stream state */ z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; break; } if(z->avail_in == 0) { /* We don't have any data to inflate; wait until next time */ return CURLE_OK; } /* We've parsed the header, now uncompress the data */ return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING); #endif }