+
+/*
+ * \brief uses the same calling syntax as compress2(), but it
+ * creates a stream compatible with HTTP "Content-encoding: gzip"
+ */
+#ifdef HAVE_ZLIB
+#define DEF_MEM_LEVEL 8 /*< memlevel??? */
+#define OS_CODE 0x03 /*< unix */
+int ZEXPORT compress_gzip(Bytef * dest, /*< compressed buffer*/
+ size_t * destLen, /*< length of the compresed data */
+ const Bytef * source, /*< source to encode */
+ uLong sourceLen, /*< length of source to encode */
+ int level) /*< compression level */
+{
+ const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
+
+ /* write gzip header */
+ snprintf((char *) dest, *destLen,
+ "%c%c%c%c%c%c%c%c%c%c",
+ gz_magic[0], gz_magic[1], Z_DEFLATED,
+ 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /* xflags */ ,
+ OS_CODE);
+
+ /* normal deflate */
+ z_stream stream;
+ int err;
+ stream.next_in = (Bytef *) source;
+ stream.avail_in = (uInt) sourceLen;
+ stream.next_out = dest + 10L; // after header
+ stream.avail_out = (uInt) * destLen;
+ if ((uLong) stream.avail_out != *destLen)
+ return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func) 0;
+ stream.zfree = (free_func) 0;
+ stream.opaque = (voidpf) 0;
+
+ err = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS,
+ DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+ if (err != Z_OK)
+ return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out + 10L;
+
+ /* write CRC and Length */
+ uLong crc = crc32(0L, source, sourceLen);
+ int n;
+ for (n = 0; n < 4; ++n, ++*destLen) {
+ dest[*destLen] = (int) (crc & 0xff);
+ crc >>= 8;
+ }
+ uLong len = stream.total_in;
+ for (n = 0; n < 4; ++n, ++*destLen) {
+ dest[*destLen] = (int) (len & 0xff);
+ len >>= 8;
+ }
+ err = deflateEnd(&stream);
+ return err;
+}
+#endif
+
+
+/**
+ * Attention! If you feed this a Const String, you must maintain the uncompressed buffer yourself!
+ */
+int CompressBuffer(StrBuf *Buf)
+{
+#ifdef HAVE_ZLIB
+ char *compressed_data = NULL;
+ size_t compressed_len, bufsize;
+
+ bufsize = compressed_len = ((Buf->BufUsed * 101) / 100) + 100;
+ compressed_data = malloc(compressed_len);
+
+ if (compress_gzip((Bytef *) compressed_data,
+ &compressed_len,
+ (Bytef *) Buf->buf,
+ (uLongf) Buf->BufUsed, Z_BEST_SPEED) == Z_OK) {
+ if (!ConstBuf)
+ free(Buf->buf);
+ Buf->buf = compressed_data;
+ Buf->BufUsed = compressed_len;
+ Buf->BufSize = bufsize;
+ return 1;
+ } else {
+ free(compressed_data);
+ }
+#endif /* HAVE_ZLIB */
+ return 0;
+}