void init_(zip_format format, int level_, dict_type dict_, heap* h, int strategy_){ if (h){ zstream.zalloc = zip_malloc; zstream.zfree = zip_free; zstream.opaque = h; } if(deflateInit2(&zstream, level_, Z_DEFLATED, get_winbits(format, MAX_WBITS), MAX_MEM_LEVEL, strategy_) != Z_OK) AIO_THROW(deflate_exception)("deflateInit2 failed"); if (!dict_.empty() && (deflateSetDictionary(&zstream, (const Bytef*)dict_.begin(), uInt(dict_.size())) != Z_OK)) AIO_THROW(deflate_exception)("deflateSetDictionary failed"); }
const GzipHeaderCodec::ZlibContext* GzipHeaderCodec::getZlibContext( SPDYVersionSettings versionSettings, int compressionLevel) { static folly::ThreadLocal<ZlibContextMap> zlibContexts_; ZlibConfig zlibConfig(versionSettings.version, compressionLevel); auto match = zlibContexts_->find(zlibConfig); if (match != zlibContexts_->end()) { return match->second.get(); } else { // This is the first request for the specified SPDY version and compression // level in this thread, so we need to construct the initial compressor and // decompressor contexts. auto newContext = folly::make_unique<ZlibContext>(); newContext->deflater.zalloc = Z_NULL; newContext->deflater.zfree = Z_NULL; newContext->deflater.opaque = Z_NULL; newContext->deflater.avail_in = 0; newContext->deflater.next_in = Z_NULL; int windowBits = (compressionLevel == Z_NO_COMPRESSION) ? 8 : 11; int r = deflateInit2( &(newContext->deflater), compressionLevel, Z_DEFLATED, // compression method windowBits, // log2 of the compression window size, negative value // means raw deflate output format w/o libz header 1, // memory size for internal compression state, 1-9 Z_DEFAULT_STRATEGY); CHECK(r == Z_OK); if (compressionLevel != Z_NO_COMPRESSION) { r = deflateSetDictionary(&(newContext->deflater), versionSettings.dict, versionSettings.dictSize); CHECK(r == Z_OK); } newContext->inflater.zalloc = Z_NULL; newContext->inflater.zfree = Z_NULL; newContext->inflater.opaque = Z_NULL; newContext->inflater.avail_in = 0; newContext->inflater.next_in = Z_NULL; r = inflateInit(&(newContext->inflater)); CHECK(r == Z_OK); auto result = newContext.get(); zlibContexts_->emplace(zlibConfig, std::move(newContext)); return result; } }
/* zlib.deflate( sink: function | { write: function [, close: function, flush: function] }, compression level, [Z_DEFAILT_COMPRESSION] method, [Z_DEFLATED] windowBits, [15] memLevel, [8] strategy, [Z_DEFAULT_STRATEGY] dictionary: [""] ) */ static int lzlib_deflate(lua_State *L) { int level, method, windowBits, memLevel, strategy; lz_stream *s; const char *dictionary; size_t dictionary_len; if (lua_istable(L, 1) || lua_isuserdata(L, 1)) { /* is there a :write function? */ lua_getfield(L, 1, "write"); if (!lua_isfunction(L, -1)) { luaL_argerror(L, 1, "output parameter does not provide :write function"); } lua_pop(L, 1); } else if (!lua_isfunction(L, 1)) { luaL_argerror(L, 1, "output parameter must be a function, table or userdata value"); } level = luaL_optint(L, 2, Z_DEFAULT_COMPRESSION); method = luaL_optint(L, 3, Z_DEFLATED); windowBits = luaL_optint(L, 4, 15); memLevel = luaL_optint(L, 5, 8); strategy = luaL_optint(L, 6, Z_DEFAULT_STRATEGY); dictionary = luaL_optlstring(L, 7, NULL, &dictionary_len); s = lzstream_new(L, 1); if (deflateInit2(&s->zstream, level, method, windowBits, memLevel, strategy) != Z_OK) { lua_pushliteral(L, "call to deflateInit2 failed"); lua_error(L); } if (dictionary) { if (deflateSetDictionary(&s->zstream, (const Bytef *) dictionary, dictionary_len) != Z_OK) { lua_pushliteral(L, "call to deflateSetDictionnary failed"); lua_error(L); } } s->state = LZ_DEFLATE; return 1; }
JNIEXPORT void JNICALL Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong strm, jarray b, jint off, jint len) { Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); int res; if (buf == 0) {/* out of memory */ return; } res = deflateSetDictionary((z_stream *)jlong_to_ptr(strm), buf + off, len); (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0); switch (res) { case Z_OK: break; case Z_STREAM_ERROR: JNU_ThrowIllegalArgumentException(env, 0); break; default: JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(strm))->msg); break; } }
int SzipCompress::do_compress(Buffer &origBuf, Buffer &outBuf, const unsigned char *aDict, size_t aDictSize, SeekableZStream::FilterId aFilter) { size_t origSize = origBuf.GetLength(); MOZ_ASSERT(origSize != 0); /* Expected total number of chunks */ size_t nChunks = ((origSize + chunkSize - 1) / chunkSize); /* The first chunk is going to be stored after the header, the dictionary * and the offset table */ size_t offset = sizeof(SeekableZStreamHeader) + aDictSize + nChunks * sizeof(uint32_t); if (offset >= origSize) return 1; /* Allocate a buffer the size of the uncompressed data: we don't want * a compressed file larger than that anyways. */ if (!outBuf.Resize(origSize)) { log("Couldn't allocate output buffer: %s", strerror(errno)); return 1; } SeekableZStreamHeader *header = new (outBuf) SeekableZStreamHeader; unsigned char *dictionary = static_cast<unsigned char *>( outBuf + sizeof(SeekableZStreamHeader)); le_uint32 *entry = reinterpret_cast<le_uint32 *>(dictionary + aDictSize); /* Initialize header */ header->chunkSize = chunkSize; header->dictSize = aDictSize; header->totalSize = offset; header->windowBits = -SzipCompress::winSizeLog; // Raw stream, // window size of 32k. header->filter = aFilter; if (aDictSize) memcpy(dictionary, aDict, aDictSize); /* Initialize zlib structure */ z_stream zStream; memset(&zStream, 0, sizeof(zStream)); zStream.avail_out = origSize - offset; zStream.next_out = static_cast<Bytef*>(outBuf) + offset; size_t avail = 0; size_t size = origSize; unsigned char *data = reinterpret_cast<unsigned char *>( static_cast<void *>(origBuf)); while (size) { avail = std::min(size, chunkSize); /* Compress chunk */ int ret = deflateInit2(&zStream, 9, Z_DEFLATED, header->windowBits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (aDictSize) deflateSetDictionary(&zStream, dictionary, aDictSize); MOZ_ASSERT(ret == Z_OK); zStream.avail_in = avail; zStream.next_in = data; ret = deflate(&zStream, Z_FINISH); MOZ_ASSERT(ret == Z_STREAM_END); ret = deflateEnd(&zStream); MOZ_ASSERT(ret == Z_OK); if (zStream.avail_out <= 0) return 1; size_t len = origSize - offset - zStream.avail_out; /* Adjust headers */ header->totalSize += len; *entry++ = offset; header->nChunks++; /* Prepare for next iteration */ size -= avail; data += avail; offset += len; } header->lastChunkSize = avail; MOZ_ASSERT(header->totalSize == offset); if (!outBuf.Resize(offset)) { log("Error truncating output: %s", strerror(errno)); return 1; } MOZ_ASSERT(header->nChunks == nChunks); return 0; }
int streaming_commons_deflate_set_dictionary(z_stream *stream, const char* dictionary, unsigned int dictLength) { return deflateSetDictionary(stream, dictionary, dictLength); }
int Sg_DeflateSetDictionary(SgZStream *strm, SgByteVector *dict) { return deflateSetDictionary(strm->strm, SG_BVECTOR_ELEMENTS(dict), SG_BVECTOR_SIZE(dict)); }
static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { ZLibData* d = (ZLibData*)drv_data; int res; switch(command) { case DEFLATE_INIT: if (len != 4) goto badarg; if (d->state != ST_NONE) goto badarg; res = deflateInit(&d->s, i32(buf)); if (res == Z_OK) { d->state = ST_DEFLATE; d->want_crc = 0; d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); case DEFLATE_INIT2: { int wbits; if (len != 20) goto badarg; if (d->state != ST_NONE) goto badarg; wbits = i32(buf+8); res = deflateInit2(&d->s, i32(buf), i32(buf+4), wbits, i32(buf+12), i32(buf+16)); if (res == Z_OK) { d->state = ST_DEFLATE; d->want_crc = (wbits < 0); d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); } case DEFLATE_SETDICT: if (d->state != ST_DEFLATE) goto badarg; res = deflateSetDictionary(&d->s, (unsigned char*)buf, len); if (res == Z_OK) { return zlib_value(d->s.adler, rbuf, rlen); } else { return zlib_return(res, rbuf, rlen); } case DEFLATE_RESET: if (len != 0) goto badarg; if (d->state != ST_DEFLATE) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = deflateReset(&d->s); return zlib_return(res, rbuf, rlen); case DEFLATE_END: if (len != 0) goto badarg; if (d->state != ST_DEFLATE) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = deflateEnd(&d->s); d->state = ST_NONE; return zlib_return(res, rbuf, rlen); case DEFLATE_PARAMS: if (len != 8) goto badarg; if (d->state != ST_DEFLATE) goto badarg; res = deflateParams(&d->s, i32(buf), i32(buf+4)); return zlib_return(res, rbuf, rlen); case DEFLATE: if (d->state != ST_DEFLATE) goto badarg; if (len != 4) goto badarg; res = zlib_deflate(d, i32(buf)); return zlib_return(res, rbuf, rlen); case INFLATE_INIT: if (len != 0) goto badarg; if (d->state != ST_NONE) goto badarg; res = inflateInit(&d->s); if (res == Z_OK) { d->state = ST_INFLATE; d->inflate_eos_seen = 0; d->want_crc = 0; d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); case INFLATE_INIT2: { int wbits; if (len != 4) goto badarg; if (d->state != ST_NONE) goto badarg; wbits = i32(buf); res = inflateInit2(&d->s, wbits); if (res == Z_OK) { d->state = ST_INFLATE; d->inflate_eos_seen = 0; d->want_crc = (wbits < 0); d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); } case INFLATE_SETDICT: if (d->state != ST_INFLATE) goto badarg; res = inflateSetDictionary(&d->s, (unsigned char*)buf, len); return zlib_return(res, rbuf, rlen); case INFLATE_SYNC: if (d->state != ST_INFLATE) goto badarg; if (len != 0) goto badarg; if (driver_sizeq(d->port) == 0) { res = Z_BUF_ERROR; } else { int vlen; SysIOVec* iov = driver_peekq(d->port, &vlen); d->s.next_in = iov[0].iov_base; d->s.avail_in = iov[0].iov_len; res = inflateSync(&d->s); } return zlib_return(res, rbuf, rlen); case INFLATE_RESET: if (d->state != ST_INFLATE) goto badarg; if (len != 0) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = inflateReset(&d->s); d->inflate_eos_seen = 0; return zlib_return(res, rbuf, rlen); case INFLATE_END: if (d->state != ST_INFLATE) goto badarg; if (len != 0) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = inflateEnd(&d->s); if (res == Z_OK && d->inflate_eos_seen == 0) { res = Z_DATA_ERROR; } d->state = ST_NONE; return zlib_return(res, rbuf, rlen); case INFLATE: if (d->state != ST_INFLATE) goto badarg; if (len != 4) goto badarg; res = zlib_inflate(d, i32(buf)); if (res == Z_NEED_DICT) { return zlib_value2(3, d->s.adler, rbuf, rlen); } else { return zlib_return(res, rbuf, rlen); } case GET_QSIZE: return zlib_value(driver_sizeq(d->port), rbuf, rlen); case GET_BUFSZ: return zlib_value(d->binsz_need, rbuf, rlen); case SET_BUFSZ: { int need; if (len != 4) goto badarg; need = i32(buf); if ((need < 16) || (need > 0x00ffffff)) goto badarg; if (d->binsz_need != need) { d->binsz_need = need; if (d->bin != NULL) { if (d->s.avail_out == d->binsz) { driver_free_binary(d->bin); d->bin = NULL; d->binsz = 0; } else zlib_output(d); } } return zlib_return(Z_OK, rbuf, rlen); } case CRC32_0: return zlib_value(d->crc, rbuf, rlen); case CRC32_1: { uLong crc = crc32(0L, Z_NULL, 0); crc = crc32(crc, (unsigned char*) buf, len); return zlib_value(crc, rbuf, rlen); } case CRC32_2: { uLong crc; if (len < 4) goto badarg; crc = (unsigned int) i32(buf); crc = crc32(crc, (unsigned char*) buf+4, len-4); return zlib_value(crc, rbuf, rlen); } case ADLER32_1: { uLong adler = adler32(0L, Z_NULL, 0); adler = adler32(adler, (unsigned char*) buf, len); return zlib_value(adler, rbuf, rlen); } case ADLER32_2: { uLong adler; if (len < 4) goto badarg; adler = (unsigned int) i32(buf); adler = adler32(adler, (unsigned char*) buf+4, len-4); return zlib_value(adler, rbuf, rlen); } case CRC32_COMBINE: { uLong crc, crc1, crc2, len2; if (len != 12) goto badarg; crc1 = (unsigned int) i32(buf); crc2 = (unsigned int) i32(buf+4); len2 = (unsigned int) i32(buf+8); crc = crc32_combine(crc1, crc2, len2); return zlib_value(crc, rbuf, rlen); } case ADLER32_COMBINE: { uLong adler, adler1, adler2, len2; if (len != 12) goto badarg; adler1 = (unsigned int) i32(buf); adler2 = (unsigned int) i32(buf+4); len2 = (unsigned int) i32(buf+8); adler = adler32_combine(adler1, adler2, len2); return zlib_value(adler, rbuf, rlen); } } badarg: errno = EINVAL; return zlib_return(Z_ERRNO, rbuf, rlen); }
int ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) { ZIPSTATE* context = (ZIPSTATE*) state->context; int err; int compress_level, compress_type; UINT8* ptr; int i, bpp, s, sum; ImagingSectionCookie cookie; if (!state->state) { /* Initialization */ /* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */ /* overflow check for malloc */ if (state->bytes > INT_MAX - 1) { state->errcode = IMAGING_CODEC_MEMORY; return -1; } /* Expand standard buffer to make room for the filter selector, and allocate filter buffers */ free(state->buffer); /* malloc check ok, overflow checked above */ state->buffer = (UINT8*) malloc(state->bytes+1); context->previous = (UINT8*) malloc(state->bytes+1); context->prior = (UINT8*) malloc(state->bytes+1); context->up = (UINT8*) malloc(state->bytes+1); context->average = (UINT8*) malloc(state->bytes+1); context->paeth = (UINT8*) malloc(state->bytes+1); if (!state->buffer || !context->previous || !context->prior || !context->up || !context->average || !context->paeth) { free(context->paeth); free(context->average); free(context->up); free(context->prior); free(context->previous); state->errcode = IMAGING_CODEC_MEMORY; return -1; } /* Initialise filter buffers */ state->buffer[0] = 0; context->prior[0] = 1; context->up[0] = 2; context->average[0] = 3; context->paeth[0] = 4; /* Initialise previous buffer to black */ memset(context->previous, 0, state->bytes+1); /* Setup compression context */ context->z_stream.zalloc = (alloc_func)0; context->z_stream.zfree = (free_func)0; context->z_stream.opaque = (voidpf)0; context->z_stream.next_in = 0; context->z_stream.avail_in = 0; compress_level = (context->optimize) ? Z_BEST_COMPRESSION : context->compress_level; if (context->compress_type == -1) { compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED : Z_DEFAULT_STRATEGY; } else { compress_type = context->compress_type; } err = deflateInit2(&context->z_stream, /* compression level */ compress_level, /* compression method */ Z_DEFLATED, /* compression memory resources */ 15, 9, /* compression strategy (image data are filtered)*/ compress_type); if (err < 0) { state->errcode = IMAGING_CODEC_CONFIG; return -1; } if (context->dictionary && context->dictionary_size > 0) { err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary, context->dictionary_size); if (err < 0) { state->errcode = IMAGING_CODEC_CONFIG; return -1; } } /* Ready to decode */ state->state = 1; } /* Setup the destination buffer */ context->z_stream.next_out = buf; context->z_stream.avail_out = bytes; if (context->z_stream.next_in && context->z_stream.avail_in > 0) { /* We have some data from previous round, deflate it first */ err = deflate(&context->z_stream, Z_NO_FLUSH); if (err < 0) { /* Something went wrong inside the compression library */ if (err == Z_DATA_ERROR) state->errcode = IMAGING_CODEC_BROKEN; else if (err == Z_MEM_ERROR) state->errcode = IMAGING_CODEC_MEMORY; else state->errcode = IMAGING_CODEC_CONFIG; free(context->paeth); free(context->average); free(context->up); free(context->prior); free(context->previous); deflateEnd(&context->z_stream); return -1; } } ImagingSectionEnter(&cookie); for (;;) { switch (state->state) { case 1: /* Compress image data */ while (context->z_stream.avail_out > 0) { if (state->y >= state->ysize) { /* End of image; now flush compressor buffers */ state->state = 2; break; } /* Stuff image data into the compressor */ state->shuffle(state->buffer+1, (UINT8*) im->image[state->y + state->yoff] + state->xoff * im->pixelsize, state->xsize); state->y++; context->output = state->buffer; if (context->mode == ZIP_PNG) { /* Filter the image data. For each line, select the filter that gives the least total distance from zero for the filtered data (taken from LIBPNG) */ bpp = (state->bits + 7) / 8; /* 0. No filter */ for (i = 1, sum = 0; i <= state->bytes; i++) { UINT8 v = state->buffer[i]; sum += (v < 128) ? v : 256 - v; } /* 2. Up. We'll test this first to save time when an image line is identical to the one above. */ if (sum > 0) { for (i = 1, s = 0; i <= state->bytes; i++) { UINT8 v = state->buffer[i] - context->previous[i]; context->up[i] = v; s += (v < 128) ? v : 256 - v; } if (s < sum) { context->output = context->up; sum = s; /* 0 if line was duplicated */ } } /* 1. Prior */ if (sum > 0) { for (i = 1, s = 0; i <= bpp; i++) { UINT8 v = state->buffer[i]; context->prior[i] = v; s += (v < 128) ? v : 256 - v; } for (; i <= state->bytes; i++) { UINT8 v = state->buffer[i] - state->buffer[i-bpp]; context->prior[i] = v; s += (v < 128) ? v : 256 - v; } if (s < sum) { context->output = context->prior; sum = s; /* 0 if line is solid */ } } /* 3. Average (not very common in real-life images, so its only used with the optimize option) */ if (context->optimize && sum > 0) { for (i = 1, s = 0; i <= bpp; i++) { UINT8 v = state->buffer[i] - context->previous[i]/2; context->average[i] = v; s += (v < 128) ? v : 256 - v; } for (; i <= state->bytes; i++) { UINT8 v = state->buffer[i] - (state->buffer[i-bpp] + context->previous[i])/2; context->average[i] = v; s += (v < 128) ? v : 256 - v; } if (s < sum) { context->output = context->average; sum = s; } } /* 4. Paeth */ if (sum > 0) { for (i = 1, s = 0; i <= bpp; i++) { UINT8 v = state->buffer[i] - context->previous[i]; context->paeth[i] = v; s += (v < 128) ? v : 256 - v; } for (; i <= state->bytes; i++) { UINT8 v; int a, b, c; int pa, pb, pc; /* fetch pixels */ a = state->buffer[i-bpp]; b = context->previous[i]; c = context->previous[i-bpp]; /* distances to surrounding pixels */ pa = abs(b - c); pb = abs(a - c); pc = abs(a + b - 2*c); /* pick predictor with the shortest distance */ v = state->buffer[i] - ((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c); context->paeth[i] = v; s += (v < 128) ? v : 256 - v; } if (s < sum) { context->output = context->paeth; sum = s; } } } /* Compress this line */ context->z_stream.next_in = context->output; context->z_stream.avail_in = state->bytes+1; err = deflate(&context->z_stream, Z_NO_FLUSH); if (err < 0) { /* Something went wrong inside the compression library */ if (err == Z_DATA_ERROR) state->errcode = IMAGING_CODEC_BROKEN; else if (err == Z_MEM_ERROR) state->errcode = IMAGING_CODEC_MEMORY; else state->errcode = IMAGING_CODEC_CONFIG; free(context->paeth); free(context->average); free(context->up); free(context->prior); free(context->previous); deflateEnd(&context->z_stream); ImagingSectionLeave(&cookie); return -1; } /* Swap buffer pointers */ ptr = state->buffer; state->buffer = context->previous; context->previous = ptr; } if (context->z_stream.avail_out == 0) break; /* Buffer full */ case 2: /* End of image data; flush compressor buffers */ while (context->z_stream.avail_out > 0) { err = deflate(&context->z_stream, Z_FINISH); if (err == Z_STREAM_END) { free(context->paeth); free(context->average); free(context->up); free(context->prior); free(context->previous); deflateEnd(&context->z_stream); state->errcode = IMAGING_CODEC_END; break; } if (context->z_stream.avail_out == 0) break; /* Buffer full */ } } ImagingSectionLeave(&cookie); return bytes - context->z_stream.avail_out; } /* Should never ever arrive here... */ state->errcode = IMAGING_CODEC_CONFIG; ImagingSectionLeave(&cookie); return -1; }
/* TODO: cleanup ctx */ static apr_status_t zlibdict_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) { apr_bucket *b; zlibdict_ctx_t *ctx = f->ctx; request_rec *r = f->r; const char *client_accepts; apr_status_t status = APR_SUCCESS; apr_pool_t *subpool; int zerr; ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "triggered zlibdict_output_filter"); /* Do nothing if asked to filter nothing. */ if (APR_BRIGADE_EMPTY(bb)) { return APR_SUCCESS; } /* First time we are called for this response? */ if (!ctx) { client_accepts = apr_table_get(r->headers_in, "Accept-Encoding"); if (client_accepts == NULL || zlibdict__header_contains(r->pool, client_accepts)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Not compressing (no Accept-Encoding: zlibdict)"); ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx)); ctx->bb = apr_brigade_create(r->pool, f->c->bucket_alloc); ctx->buf = apr_palloc(r->pool, DEFAULT_BUFFERSIZE); /* zstream must be NULL'd out. */ memset(&ctx->zstr, 0, sizeof(z_stream)); zerr = deflateInit2(&ctx->zstr, DEFAULT_COMPRESSION, Z_DEFLATED, DEFAULT_WINDOWSIZE, DEFAULT_MEMLEVEL, Z_DEFAULT_STRATEGY); deflateSetDictionary(&ctx->zstr, (Bytef *)propfind_dictionary, strlen(propfind_dictionary)); /* Set Content-Encoding header so our client knows how to handle this data. */ apr_table_mergen(r->headers_out, "Content-Encoding", "zlibdict"); } /* Read the data from the handler and compress it with a dictionary. */ for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) { const char *data; void *write_buf; size_t len; size_t buf_size, write_len; if (APR_BUCKET_IS_EOS(b)) { deflateEnd(&ctx->zstr); /* Remove EOS from the old list, and insert into the new. */ APR_BUCKET_REMOVE(b); APR_BRIGADE_INSERT_TAIL(ctx->bb, b); return ap_pass_brigade(f->next, ctx->bb); } if (APR_BUCKET_IS_METADATA(b)) continue; status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ); if (status != APR_SUCCESS) break; /* The largest buffer we should need is 0.1% larger than the compressed data, + 12 bytes. This info comes from zlib.h. */ buf_size = len + (len / 1000) + 13; apr_pool_create(&subpool, r->pool); write_buf = apr_palloc(subpool, buf_size); ctx->zstr.next_in = (Bytef *)data; /* Casting away const! */ ctx->zstr.avail_in = (uInt) len; zerr = Z_OK; while (ctx->zstr.avail_in > 0 && zerr != Z_STREAM_END) { ctx->zstr.next_out = write_buf; ctx->zstr.avail_out = (uInt) buf_size; zerr = deflate(&ctx->zstr, Z_FINISH); if (zerr < 0) return -1; /* TODO: fix error */ write_len = buf_size - ctx->zstr.avail_out; if (write_len > 0) { apr_bucket *b_out; b_out = apr_bucket_heap_create(write_buf, len, NULL, f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->bb, b_out); /* Send what we have right now to the next filter. */ status = ap_pass_brigade(f->next, ctx->bb); if (status != APR_SUCCESS) { apr_pool_destroy(subpool); return status; } } apr_pool_destroy(subpool); } } return status; }