+static DSO *zlib_dso = NULL;
+
+#define compress p_compress
+#define inflateEnd p_inflateEnd
+#define inflate p_inflate
+#define inflateInit_ p_inflateInit_
+#define deflateEnd p_deflateEnd
+#define deflate p_deflate
+#define deflateInit_ p_deflateInit_
+#define zError p_zError
+#endif /* ZLIB_SHARED */
+
+struct zlib_state
+ {
+ z_stream istream;
+ z_stream ostream;
+ };
+
+static int zlib_stateful_ex_idx = -1;
+
+static int zlib_stateful_init(COMP_CTX *ctx)
+ {
+ int err;
+ struct zlib_state *state =
+ (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state));
+
+ if (state == NULL)
+ goto err;
+
+ state->istream.zalloc = zlib_zalloc;
+ state->istream.zfree = zlib_zfree;
+ state->istream.opaque = Z_NULL;
+ state->istream.next_in = Z_NULL;
+ state->istream.next_out = Z_NULL;
+ state->istream.avail_in = 0;
+ state->istream.avail_out = 0;
+ err = inflateInit_(&state->istream,
+ ZLIB_VERSION, sizeof(z_stream));
+ if (err != Z_OK)
+ goto err;
+
+ state->ostream.zalloc = zlib_zalloc;
+ state->ostream.zfree = zlib_zfree;
+ state->ostream.opaque = Z_NULL;
+ state->ostream.next_in = Z_NULL;
+ state->ostream.next_out = Z_NULL;
+ state->ostream.avail_in = 0;
+ state->ostream.avail_out = 0;
+ err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION,
+ ZLIB_VERSION, sizeof(z_stream));
+ if (err != Z_OK)
+ goto err;
+
+ CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
+ CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state);
+ return 1;
+ err:
+ if (state) OPENSSL_free(state);
+ return 0;
+ }
+
+static void zlib_stateful_finish(COMP_CTX *ctx)
+ {
+ struct zlib_state *state =
+ (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
+ zlib_stateful_ex_idx);
+ inflateEnd(&state->istream);
+ deflateEnd(&state->ostream);
+ OPENSSL_free(state);
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
+ }
+
+static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
+ unsigned int olen, unsigned char *in, unsigned int ilen)
+ {
+ int err = Z_OK;
+ struct zlib_state *state =
+ (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
+ zlib_stateful_ex_idx);
+
+ if (state == NULL)
+ return -1;
+
+ state->ostream.next_in = in;
+ state->ostream.avail_in = ilen;
+ state->ostream.next_out = out;
+ state->ostream.avail_out = olen;
+ if (ilen > 0)
+ err = deflate(&state->ostream, Z_SYNC_FLUSH);
+ if (err != Z_OK)
+ return -1;
+#ifdef DEBUG_ZLIB
+ fprintf(stderr,"compress(%4d)->%4d %s\n",
+ ilen,olen - state->ostream.avail_out,
+ (ilen != olen - state->ostream.avail_out)?"zlib":"clear");
+#endif
+ return olen - state->ostream.avail_out;
+ }