00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "postgres.h"
00033
00034 #include "mbuf.h"
00035 #include "px.h"
00036 #include "pgp.h"
00037
00038
00039
00040
00041
00042
00043 #ifdef HAVE_LIBZ
00044
00045 #include <zlib.h>
00046
00047 #define ZIP_OUT_BUF 8192
00048 #define ZIP_IN_BLOCK 8192
00049
00050 struct ZipStat
00051 {
00052 uint8 type;
00053 int buf_len;
00054 int hdr_done;
00055 z_stream stream;
00056 uint8 buf[ZIP_OUT_BUF];
00057 };
00058
00059 static void *
00060 z_alloc(void *priv, unsigned n_items, unsigned item_len)
00061 {
00062 return px_alloc(n_items * item_len);
00063 }
00064
00065 static void
00066 z_free(void *priv, void *addr)
00067 {
00068 px_free(addr);
00069 }
00070
00071 static int
00072 compress_init(PushFilter *next, void *init_arg, void **priv_p)
00073 {
00074 int res;
00075 struct ZipStat *st;
00076 PGP_Context *ctx = init_arg;
00077 uint8 type = ctx->compress_algo;
00078
00079 if (type != PGP_COMPR_ZLIB && type != PGP_COMPR_ZIP)
00080 return PXE_PGP_UNSUPPORTED_COMPR;
00081
00082
00083
00084
00085 st = px_alloc(sizeof(*st));
00086 memset(st, 0, sizeof(*st));
00087 st->buf_len = ZIP_OUT_BUF;
00088 st->stream.zalloc = z_alloc;
00089 st->stream.zfree = z_free;
00090
00091 if (type == PGP_COMPR_ZIP)
00092 res = deflateInit2(&st->stream, ctx->compress_level,
00093 Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
00094 else
00095 res = deflateInit(&st->stream, ctx->compress_level);
00096 if (res != Z_OK)
00097 {
00098 px_free(st);
00099 return PXE_PGP_COMPRESSION_ERROR;
00100 }
00101 *priv_p = st;
00102
00103 return ZIP_IN_BLOCK;
00104 }
00105
00106
00107
00108
00109 static int
00110 compress_process(PushFilter *next, void *priv, const uint8 *data, int len)
00111 {
00112 int res,
00113 n_out;
00114 struct ZipStat *st = priv;
00115
00116
00117
00118
00119 while (len > 0)
00120 {
00121 st->stream.next_in = (void *) data;
00122 st->stream.avail_in = len;
00123 st->stream.next_out = st->buf;
00124 st->stream.avail_out = st->buf_len;
00125 res = deflate(&st->stream, 0);
00126 if (res != Z_OK)
00127 return PXE_PGP_COMPRESSION_ERROR;
00128
00129 n_out = st->buf_len - st->stream.avail_out;
00130 if (n_out > 0)
00131 {
00132 res = pushf_write(next, st->buf, n_out);
00133 if (res < 0)
00134 return res;
00135 }
00136 len = st->stream.avail_in;
00137 }
00138
00139 return 0;
00140 }
00141
00142 static int
00143 compress_flush(PushFilter *next, void *priv)
00144 {
00145 int res,
00146 zres,
00147 n_out;
00148 struct ZipStat *st = priv;
00149
00150 st->stream.next_in = NULL;
00151 st->stream.avail_in = 0;
00152 while (1)
00153 {
00154 st->stream.next_out = st->buf;
00155 st->stream.avail_out = st->buf_len;
00156 zres = deflate(&st->stream, Z_FINISH);
00157 if (zres != Z_STREAM_END && zres != Z_OK)
00158 return PXE_PGP_COMPRESSION_ERROR;
00159 n_out = st->buf_len - st->stream.avail_out;
00160 if (n_out > 0)
00161 {
00162 res = pushf_write(next, st->buf, n_out);
00163 if (res < 0)
00164 return res;
00165 }
00166 if (zres == Z_STREAM_END)
00167 break;
00168 }
00169 return 0;
00170 }
00171
00172 static void
00173 compress_free(void *priv)
00174 {
00175 struct ZipStat *st = priv;
00176
00177 deflateEnd(&st->stream);
00178 memset(st, 0, sizeof(*st));
00179 px_free(st);
00180 }
00181
00182 static const PushFilterOps
00183 compress_filter = {
00184 compress_init, compress_process, compress_flush, compress_free
00185 };
00186
00187 int
00188 pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
00189 {
00190 return pushf_create(res, &compress_filter, ctx, dst);
00191 }
00192
00193
00194
00195
00196 struct DecomprData
00197 {
00198 int buf_len;
00199 int buf_data;
00200 uint8 *pos;
00201 z_stream stream;
00202 int eof;
00203 uint8 buf[ZIP_OUT_BUF];
00204 };
00205
00206 static int
00207 decompress_init(void **priv_p, void *arg, PullFilter *src)
00208 {
00209 PGP_Context *ctx = arg;
00210 struct DecomprData *dec;
00211 int res;
00212
00213 if (ctx->compress_algo != PGP_COMPR_ZLIB
00214 && ctx->compress_algo != PGP_COMPR_ZIP)
00215 return PXE_PGP_UNSUPPORTED_COMPR;
00216
00217 dec = px_alloc(sizeof(*dec));
00218 memset(dec, 0, sizeof(*dec));
00219 dec->buf_len = ZIP_OUT_BUF;
00220 *priv_p = dec;
00221
00222 dec->stream.zalloc = z_alloc;
00223 dec->stream.zfree = z_free;
00224
00225 if (ctx->compress_algo == PGP_COMPR_ZIP)
00226 res = inflateInit2(&dec->stream, -15);
00227 else
00228 res = inflateInit(&dec->stream);
00229 if (res != Z_OK)
00230 {
00231 px_free(dec);
00232 px_debug("decompress_init: inflateInit error");
00233 return PXE_PGP_COMPRESSION_ERROR;
00234 }
00235
00236 return 0;
00237 }
00238
00239 static int
00240 decompress_read(void *priv, PullFilter *src, int len,
00241 uint8 **data_p, uint8 *buf, int buflen)
00242 {
00243 int res;
00244 int flush;
00245 struct DecomprData *dec = priv;
00246
00247 restart:
00248 if (dec->buf_data > 0)
00249 {
00250 if (len > dec->buf_data)
00251 len = dec->buf_data;
00252 *data_p = dec->pos;
00253 dec->pos += len;
00254 dec->buf_data -= len;
00255 return len;
00256 }
00257
00258 if (dec->eof)
00259 return 0;
00260
00261 if (dec->stream.avail_in == 0)
00262 {
00263 uint8 *tmp;
00264
00265 res = pullf_read(src, 8192, &tmp);
00266 if (res < 0)
00267 return res;
00268 dec->stream.next_in = tmp;
00269 dec->stream.avail_in = res;
00270 }
00271
00272 dec->stream.next_out = dec->buf;
00273 dec->stream.avail_out = dec->buf_len;
00274 dec->pos = dec->buf;
00275
00276
00277
00278
00279
00280
00281 flush = dec->stream.avail_in ? Z_SYNC_FLUSH : Z_FINISH;
00282 res = inflate(&dec->stream, flush);
00283 if (res != Z_OK && res != Z_STREAM_END)
00284 {
00285 px_debug("decompress_read: inflate error: %d", res);
00286 return PXE_PGP_CORRUPT_DATA;
00287 }
00288
00289 dec->buf_data = dec->buf_len - dec->stream.avail_out;
00290 if (res == Z_STREAM_END)
00291 dec->eof = 1;
00292 goto restart;
00293 }
00294
00295 static void
00296 decompress_free(void *priv)
00297 {
00298 struct DecomprData *dec = priv;
00299
00300 inflateEnd(&dec->stream);
00301 memset(dec, 0, sizeof(*dec));
00302 px_free(dec);
00303 }
00304
00305 static const PullFilterOps
00306 decompress_filter = {
00307 decompress_init, decompress_read, decompress_free
00308 };
00309
00310 int
00311 pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
00312 {
00313 return pullf_create(res, &decompress_filter, ctx, src);
00314 }
00315 #else
00316
00317 int
00318 pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
00319 {
00320 return PXE_PGP_UNSUPPORTED_COMPR;
00321 }
00322
00323 int
00324 pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
00325 {
00326 return PXE_PGP_UNSUPPORTED_COMPR;
00327 }
00328
00329 #endif