+ HTTP_DEFLATE_LEVEL_SET(flags, level);
+ HTTP_DEFLATE_WBITS_SET(flags, wbits);
+ HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
+
+ memset(&Z, 0, sizeof(z_stream));
+ *encoded = NULL;
+ *encoded_len = 0;
+
+ status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy);
+ if (Z_OK == status) {
+ *encoded_len = HTTP_ENCODING_BUFLEN(data_len);
+ *encoded = emalloc_rel(*encoded_len);
+
+ Z.next_in = (Bytef *) data;
+ Z.next_out = (Bytef *) *encoded;
+ Z.avail_in = data_len;
+ Z.avail_out = *encoded_len;
+
+ status = deflate(&Z, Z_FINISH);
+ deflateEnd(&Z);
+
+ if (Z_STREAM_END == status) {
+ /* size buffer down to actual length */
+ *encoded = erealloc_rel(*encoded, Z.total_out + 1);
+ (*encoded)[*encoded_len = Z.total_out] = '\0';
+ return SUCCESS;
+ } else {
+ STR_SET(*encoded, NULL);
+ *encoded_len = 0;
+ }
+ }
+
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not deflate data: %s (%s)", zError(status));
+ return FAILURE;
+}
+
+PHP_HTTP_API STATUS _http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
+{
+ int status, max = 0, wbits = HTTP_WINDOW_BITS_ANY;
+ z_stream Z;
+ phpstr buffer;
+
+ memset(&Z, 0, sizeof(z_stream));
+ *decoded = NULL;
+ *decoded_len = 0;
+
+ phpstr_init_ex(&buffer, data_len << 2, PHPSTR_INIT_PREALLOC);
+ buffer.size = data_len;
+
+retry_inflate:
+ status = inflateInit2(&Z, wbits);
+ if (Z_OK == status) {
+ Z.next_in = (Bytef *) data;
+ Z.avail_in = data_len;
+
+ do {
+ phpstr_resize(&buffer, data_len << 2);
+
+ do {
+ Z.avail_out = (buffer.free -= Z.total_out - buffer.used);
+ Z.next_out = (Bytef *) buffer.data + (buffer.used = Z.total_out);
+ status = inflate(&Z, Z_NO_FLUSH);
+ } while (Z_OK == status);
+ } while (Z_BUF_ERROR == status && ++max < HTTP_ENCODING_MAXTRY);
+
+ if (Z_DATA_ERROR == status && HTTP_WINDOW_BITS_ANY == wbits) {
+ /* raw deflated data? */
+ inflateEnd(&Z);
+ wbits = HTTP_WINDOW_BITS_RAW;
+ goto retry_inflate;
+ }
+
+ inflateEnd(&Z);
+
+ if (Z_STREAM_END == status) {
+ *decoded_len = Z.total_out;
+ *decoded = erealloc_rel(buffer.data, *decoded_len + 1);
+ (*decoded)[*decoded_len] = '\0';
+ return SUCCESS;
+ } else {
+ phpstr_dtor(&buffer);
+ }
+ }
+
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s", zError(status));
+ return FAILURE;
+}
+
+
+PHP_HTTP_API http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
+{
+ int status, level, wbits, strategy, free_stream;
+
+ if ((free_stream = !s)) {
+ s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));