Files
libmicrohttpd/src/daemon/https/opencdk/compress.c
T

239 lines
5.3 KiB
C

/* compress.c - Compression filters
* Copyright (C) 2002, 2003 Timo Schulz
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation
*
* This file is part of OpenCDK.
*
* OpenCDK is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* OpenCDK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <time.h>
#ifdef HAVE_LIBZ
# include <zlib.h>
#endif
#include "opencdk.h"
#include "main.h"
#include "filters.h"
#ifdef HAVE_LIBZ
static int
compress_data (z_stream * zs, int flush, byte * inbuf, size_t insize,
FILE * out)
{
int nbytes, zrc;
byte buf[4096];
zs->next_in = inbuf;
zs->avail_in = insize;
do
{
zs->next_out = buf;
zs->avail_out = DIM (buf);
zrc = deflate (zs, flush);
if (zrc == Z_STREAM_END && flush == Z_FINISH)
;
else if (zrc != Z_OK)
break;
nbytes = DIM (buf) - zs->avail_out;
fwrite (buf, 1, nbytes, out);
}
while (zs->avail_out == 0 || (flush == Z_FINISH && zrc != Z_STREAM_END));
return zrc;
}
static int
decompress_data (compress_filter_t * zfx, z_stream * zs,
FILE * in, size_t * ret_len)
{
int nread, nold;
int rc, zrc;
rc = 0;
nread = 0;
while (zs->avail_out != 0)
{
if (!zs->avail_in)
{
nread = fread (zfx->inbuf, 1, zfx->inbufsize, in);
zs->next_in = zfx->inbuf;
zs->avail_in = nread;
}
nold = zs->avail_out;
zrc = inflate (zs, Z_SYNC_FLUSH);
if (zrc != Z_OK && zrc != Z_STREAM_END)
{
rc = CDK_Zlib_Error;
break;
}
*ret_len = zfx->outbufsize - zs->avail_out;
if (nold == zs->avail_out)
break;
if (zrc == Z_STREAM_END)
{
rc = EOF; /* eof */
break;
}
}
if (!nread && feof (in))
rc = -1;
return rc;
}
static cdk_error_t
compress_decode (void *opaque, FILE * in, FILE * out)
{
compress_filter_t *zfx = opaque;
z_stream *zs;
size_t nbytes;
int zrc;
cdk_error_t rc = 0;
_cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo);
if (!zfx || !in || !out)
return CDK_Inv_Value;
zs = cdk_calloc (1, sizeof *zs);
if (!zs)
return CDK_Out_Of_Core;
if (zfx->algo == CDK_COMPRESS_ZIP)
zrc = inflateInit2 (zs, -13);
else
zrc = inflateInit (zs);
if (zrc != Z_OK)
return CDK_Zlib_Error;
zfx->outbufsize = 8192;
zfx->inbufsize = 2048;
memset (zfx->inbuf, 0, sizeof zfx->inbuf);
zs->avail_in = 0;
nbytes = 0;
while (rc != -1)
{
zs->next_out = zfx->outbuf;
zs->avail_out = 8192;
rc = decompress_data (zfx, zs, in, &nbytes);
fwrite (zfx->outbuf, 1, nbytes, out);
}
inflateEnd (zs);
cdk_free (zs);
if (rc == CDK_EOF)
rc = 0;
return rc;
}
static cdk_error_t
compress_encode (void *opaque, FILE * in, FILE * out)
{
compress_filter_t *zfx = opaque;
z_stream *zs;
struct cdk_pkt_compressed_s cd;
struct cdk_packet_s pkt;
int zrc, nread;
cdk_error_t rc;
_cdk_log_debug ("compress filter: encode\n");
if (!zfx || !in || !out)
return CDK_Inv_Value;
if (!zfx->algo)
zfx->algo = CDK_COMPRESS_ZIP;
memset (&cd, 0, sizeof (cd));
cd.len = 0;
cd.algorithm = zfx->algo;
pkt.pkttype = CDK_PKT_COMPRESSED;
pkt.pkt.compressed = &cd;
rc = _cdk_pkt_write_fp (out, &pkt);
if (rc)
return rc;
zs = cdk_calloc (1, sizeof *zs);
if (!zs)
return CDK_Out_Of_Core;
if (zfx->algo == CDK_COMPRESS_ZIP)
rc = deflateInit2 (zs, zfx->level, Z_DEFLATED, -13, 8,
Z_DEFAULT_STRATEGY);
else
rc = deflateInit (zs, zfx->level);
if (rc != Z_OK)
{
cdk_free (zs);
return CDK_Zlib_Error;
}
zfx->outbufsize = 8192;
memset (zfx->outbuf, 0, sizeof zfx->outbuf);
while (!feof (in))
{
nread = fread (zfx->outbuf, 1, zfx->outbufsize, in);
if (!nread)
break;
zrc = compress_data (zs, Z_NO_FLUSH, zfx->outbuf, nread, out);
if (zrc)
{
rc = CDK_Zlib_Error;
break;
}
}
if (!rc)
{
nread = 0;
zrc = compress_data (zs, Z_FINISH, zfx->outbuf, nread, out);
if (zrc != Z_STREAM_END)
rc = CDK_Zlib_Error;
}
deflateEnd (zs);
cdk_free (zs);
return rc;
}
cdk_error_t
_cdk_filter_compress (void *opaque, int ctl, FILE * in, FILE * out)
{
if (ctl == STREAMCTL_READ)
return compress_decode (opaque, in, out);
else if (ctl == STREAMCTL_WRITE)
return compress_encode (opaque, in, out);
else if (ctl == STREAMCTL_FREE)
{
compress_filter_t *zfx = opaque;
if (zfx)
{
_cdk_log_debug ("free compress filter\n");
zfx->level = 0;
zfx->algo = 0;
return 0;
}
}
return CDK_Inv_Mode;
}
#else
cdk_error_t
_cdk_filter_compress (void *opaque, int ctl, FILE * in, FILE * out)
{
return CDK_Not_Implemented;
}
#endif /* HAVE_LIBZ */