+#ifdef HTTP_HAVE_ZLIB
+static HTTP_FILTER_FUNCTION(gzip)
+{
+ int out_avail = 0;
+ php_stream_bucket *ptr, *nxt;
+ HTTP_FILTER_BUFFER(gzip) *buffer = (HTTP_FILTER_BUFFER(gzip) *) this->abstract;
+
+ if (bytes_consumed) {
+ *bytes_consumed = 0;
+ }
+
+ /* first round */
+ if (!buffer->init) {
+ char *encoded = NULL;
+ size_t encoded_len = 0;
+
+ buffer->init = 1;
+ http_encoding_stream_init(&buffer->stream, buffer->flags, -1, &encoded, &encoded_len);
+
+ if (encoded) {
+ out_avail = 1;
+ NEW_BUCKET(encoded, encoded_len);
+ pefree(encoded, this->is_persistent);
+ }
+ }
+
+ /* new data available? */
+ if (buckets_in->head) {
+
+ /* fetch available bucket data */
+ for (ptr = buckets_in->head; ptr; ptr = nxt) {
+ char *encoded = NULL;
+ size_t encoded_len = 0;
+
+ nxt = ptr->next;
+ if (bytes_consumed) {
+ *bytes_consumed += ptr->buflen;
+ }
+
+ /* this is actually flushing implicitly */
+ http_encoding_stream_update(&buffer->stream, ptr->buf, ptr->buflen, &encoded, &encoded_len);
+ if (encoded) {
+ out_avail = 1;
+ NEW_BUCKET(encoded, encoded_len);
+ pefree(encoded, this->is_persistent);
+ }
+
+ php_stream_bucket_unlink(ptr TSRMLS_CC);
+ php_stream_bucket_delref(ptr TSRMLS_CC);
+ }
+ }
+
+ /* flush & close */
+ if (flags == PSFS_FLAG_FLUSH_CLOSE) {
+ char *encoded = NULL;
+ size_t encoded_len = 0;
+
+ http_encoding_stream_finish(&buffer->stream, &encoded, &encoded_len);
+ if (encoded) {
+ out_avail = 1;
+ NEW_BUCKET(encoded, encoded_len);
+ }
+ }
+
+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
+}
+
+static HTTP_FILTER_DESTRUCTOR(gzip)
+{
+ HTTP_FILTER_BUFFER(gzip) *buffer = (HTTP_FILTER_BUFFER(gzip) *) this->abstract;
+
+ pefree(buffer, this->is_persistent);
+}
+
+static HTTP_FILTER_OPS(gzencode) = {
+ HTTP_FILTER_FUNC(gzip),
+ HTTP_FILTER_DTOR(gzip),
+ "http.gzencode"
+};
+
+static HTTP_FILTER_OPS(deflate) = {
+ HTTP_FILTER_FUNC(gzip),
+ HTTP_FILTER_DTOR(gzip),
+ "http.deflate"
+};
+#endif /* HTTP_HAVE_ZLIB */
+