Exemple #1
0
			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");
			}
Exemple #2
0
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;
  }
}
Exemple #3
0
/*
    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;
    }
}
Exemple #5
0
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));
}
Exemple #8
0
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);
}
Exemple #9
0
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;
}
Exemple #10
0
/* 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;
}