mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
239 lines
5.3 KiB
C
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 */
|