#ifdef HTTP_HAVE_CURL
# include "php_http_request_api.h"
#endif
+#ifdef HTTP_HAVE_ZLIB
+# include "php_http_encoding_api.h"
+#endif
#ifdef ZEND_ENGINE_2
# include "php_http_filter_api.h"
#endif
PHP_FE(ob_etaghandler, NULL)
#ifdef HTTP_HAVE_ZLIB
- PHP_FE(http_gzencode, NULL)
- PHP_FE(http_gzdecode, NULL)
PHP_FE(http_deflate, NULL)
PHP_FE(http_inflate, NULL)
#endif
#ifdef HTTP_HAVE_CURL
(SUCCESS != PHP_MINIT_CALL(http_request)) ||
#endif /* HTTP_HAVE_CURL */
+#ifdef HTTP_HAVE_ZLIB
+ (SUCCESS != PHP_MINIT_CALL(http_encoding)) ||
+#endif
(SUCCESS != PHP_MINIT_CALL(http_request_method))) {
return FAILURE;
}
#ifdef HTTP_HAVE_MAGIC
support |= HTTP_SUPPORT_MAGICMIME;
#endif
-#if defined(HTTP_HAVE_ZLIB) || defined(HAVE_ZLIB)
+#ifdef HTTP_HAVE_ZLIB
support |= HTTP_SUPPORT_ENCODINGS;
#endif
ZEND_EXTERN_MODULE_GLOBALS(http);
+#ifdef HTTP_HAVE_ZLIB
+PHP_MINIT_FUNCTION(http_encoding)
+{
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_DEF", HTTP_DEFLATE_LEVEL_DEF);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MIN", HTTP_DEFLATE_LEVEL_MIN);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MAX", HTTP_DEFLATE_LEVEL_MAX);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_ZLIB", HTTP_DEFLATE_TYPE_ZLIB);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_GZIP", HTTP_DEFLATE_TYPE_GZIP);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_RAW", HTTP_DEFLATE_TYPE_RAW);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_DEF", HTTP_DEFLATE_STRATEGY_DEF);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FILT", HTTP_DEFLATE_STRATEGY_FILT);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_HUFF", HTTP_DEFLATE_STRATEGY_HUFF);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_RLE", HTTP_DEFLATE_STRATEGY_RLE);
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FIXED", HTTP_DEFLATE_STRATEGY_FIXED);
+ return SUCCESS;
+}
+#endif
+
static inline int eol_match(char **line, int *eol_len)
{
char *ptr = *line;
#ifdef HTTP_HAVE_ZLIB
-static const char http_encoding_gzip_header[] = {
- (const char) 0x1f, // fixed value
- (const char) 0x8b, // fixed value
- (const char) Z_DEFLATED, // compression algorithm
- (const char) 0, // none of the possible flags defined by the GZIP "RFC"
- (const char) 0, // MTIME
- (const char) 0, // =*=
- (const char) 0, // =*=
- (const char) 0, // =*=
- (const char) 0, // two possible flag values for 9 compression levels? o_O
-#ifdef PHP_WIN32
- (const char) 0x0b // OS_CODE
-#else
- (const char) 0x03 // OS_CODE
-#endif
-};
+#define HTTP_DEFLATE_LEVEL_SET(flags, level) \
+ switch (flags & 0xf) \
+ { \
+ default: \
+ if ((flags & 0xf) < 10) { \
+ level = flags & 0xf; \
+ break; \
+ } \
+ case HTTP_DEFLATE_LEVEL_DEF: \
+ level = Z_DEFAULT_COMPRESSION; \
+ break; \
+ }
+
+#define HTTP_DEFLATE_WBITS_SET(flags, wbits) \
+ switch (flags & 0xf0) \
+ { \
+ case HTTP_DEFLATE_TYPE_GZIP: \
+ wbits = HTTP_WINDOW_BITS_GZIP; \
+ break; \
+ case HTTP_DEFLATE_TYPE_RAW: \
+ wbits = HTTP_WINDOW_BITS_RAW; \
+ break; \
+ default: \
+ wbits = HTTP_WINDOW_BITS_ZLIB; \
+ break; \
+ }
+
+#define HTTP_INFLATE_WBITS_SET(flags, wbits) \
+ if (flags & HTTP_INFLATE_TYPE_RAW) { \
+ wbits = HTTP_WINDOW_BITS_RAW; \
+ } else { \
+ wbits = HTTP_WINDOW_BITS_ANY; \
+ }
-PHP_HTTP_API STATUS _http_encoding_gzencode(int level, int mtime, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC)
+#define HTTP_DEFLATE_STRATEGY_SET(flags, strategy) \
+ switch (flags & 0xf00) \
+ { \
+ case HTTP_DEFLATE_STRATEGY_FILT: \
+ strategy = Z_FILTERED; \
+ break; \
+ case HTTP_DEFLATE_STRATEGY_HUFF: \
+ strategy = Z_HUFFMAN_ONLY; \
+ break; \
+ case HTTP_DEFLATE_STRATEGY_RLE: \
+ strategy = Z_RLE; \
+ break; \
+ case HTTP_DEFLATE_STRATEGY_FIXED: \
+ strategy = Z_FIXED; \
+ break; \
+ default: \
+ strategy = Z_DEFAULT_STRATEGY; \
+ break; \
+ }
+
+#define HTTP_WINDOW_BITS_ZLIB 0x0000000f
+#define HTTP_WINDOW_BITS_GZIP 0x0000001f
+#define HTTP_WINDOW_BITS_ANY 0x0000002f
+#define HTTP_WINDOW_BITS_RAW -0x000000f
+
+STATUS _http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC)
{
+ int status, level, wbits, strategy;
z_stream Z;
- STATUS status = Z_OK;
- if (!(data && data_len)) {
- return FAILURE;
- }
+ 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;
- memset(&Z, 0, sizeof(z_stream));
- Z.next_in = (Bytef *) data;
- Z.avail_in = data_len;
- Z.avail_out = HTTP_ENCODING_BUFLEN(data_len) + HTTP_ENCODING_SAFPAD - 1;
+ status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy);
+ if (Z_OK == status) {
+ *encoded_len = HTTP_ENCODING_BUFLEN(data_len);
+ *encoded = emalloc(*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);
+ if (Z_STREAM_END == status) {
+ /* size buffer down to actual length */
+ *encoded = erealloc(*encoded, Z.total_out + 1);
+ (*encoded)[*encoded_len = Z.total_out] = '\0';
+ deflateEnd(&Z);
+ return SUCCESS;
+ } else {
+ STR_SET(*encoded, NULL);
+ *encoded_len = 0;
+ }
+ }
- *encoded = emalloc(HTTP_ENCODING_BUFLEN(data_len) + sizeof(http_encoding_gzip_header) + HTTP_ENCODING_SAFPAD);
- memcpy(*encoded, http_encoding_gzip_header, sizeof(http_encoding_gzip_header));
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not deflate data: %s (%s)", zError(status), Z.msg);
+ deflateEnd(&Z);
+ return FAILURE;
+}
+
+STATUS _http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len TSRMLS_DC)
+{
+ int status, max = 0, wbits = HTTP_WINDOW_BITS_ANY;
+ z_stream Z;
+ phpstr buffer;
- if (mtime) {
- (*encoded)[4] = (char) (mtime & 0xFF);
- (*encoded)[5] = (char) ((mtime >> 8) & 0xFF);
- (*encoded)[6] = (char) ((mtime >> 16) & 0xFF);
- (*encoded)[7] = (char) ((mtime >> 24) & 0xFF);
- }
+ memset(&Z, 0, sizeof(z_stream));
+ *decoded = NULL;
+ *decoded_len = 0;
- Z.next_out = (Bytef *) *encoded + sizeof(http_encoding_gzip_header);
+ phpstr_init_ex(&buffer, data_len << 2, PHPSTR_INIT_PREALLOC);
+ buffer.size = data_len;
- if (Z_OK == (status = deflateInit2(&Z, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
- status = deflate(&Z, Z_FINISH);
- deflateEnd(&Z);
+retry_inflate:
+ status = inflateInit2(&Z, wbits);
+ if (Z_OK == status) {
+ Z.next_in = (Bytef *) data;
+ Z.avail_in = data_len;
- if (Z_STREAM_END == status) {
- ulong crc;
- char *trailer;
-
- crc = crc32(0L, Z_NULL, 0);
- crc = crc32(crc, (const Bytef *) data, data_len);
-
- trailer = *encoded + sizeof(http_encoding_gzip_header) + Z.total_out;
-
- /* LSB */
- trailer[0] = (char) (crc & 0xFF);
- trailer[1] = (char) ((crc >> 8) & 0xFF);
- trailer[2] = (char) ((crc >> 16) & 0xFF);
- trailer[3] = (char) ((crc >> 24) & 0xFF);
- trailer[4] = (char) ((Z.total_in) & 0xFF);
- trailer[5] = (char) ((Z.total_in >> 8) & 0xFF);
- trailer[6] = (char) ((Z.total_in >> 16) & 0xFF);
- trailer[7] = (char) ((Z.total_in >> 24) & 0xFF);
+ do {
+ phpstr_resize(&buffer, data_len);
+
+ do {
+ Z.next_out = buffer.data + (buffer.used += Z.total_out);
+ Z.avail_out = (buffer.free -= Z.total_out);
+ status = inflate(&Z, Z_NO_FLUSH);
+ } while (Z_OK == status);
- *encoded_len = Z.total_out + sizeof(http_encoding_gzip_header) + 8;
- (*encoded)[*encoded_len] = '\0';
+ } 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;
+ }
+
+ if (Z_STREAM_END == status) {
+ *decoded = erealloc(buffer.data, (buffer.used += Z.total_out) + 1);
+ (*decoded)[*decoded_len = buffer.used] = '\0';
+ inflateEnd(&Z);
return SUCCESS;
+ } else {
+ phpstr_dtor(&buffer);
}
}
- STR_SET(*encoded, NULL);
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not gzencode data: %s", zError(status));
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s (%s)", zError(status), Z.msg);
+ inflateEnd(&Z);
return FAILURE;
}
-PHP_HTTP_API STATUS _http_encoding_gzdecode(const char *data, size_t data_len, char **decoded, size_t *decoded_len TSRMLS_DC)
+
+http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *s, int flags TSRMLS_DC)
{
- const char *encoded;
- size_t encoded_len;
+ int status, level, wbits, strategy, free_stream;
- if ( (data && data_len) &&
- (SUCCESS == http_encoding_gzencode_verify(data, data_len, &encoded, &encoded_len)) &&
- (SUCCESS == http_encoding_inflate(encoded, encoded_len, decoded, decoded_len))) {
- http_encoding_gzdecode_verify(data, data_len, *decoded, *decoded_len);
- return SUCCESS;
+ if ((free_stream = !s)) {
+ s = pemalloc(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));
}
+ memset(s, 0, sizeof(http_encoding_stream));
+ s->flags = flags;
- return FAILURE;
+ HTTP_DEFLATE_LEVEL_SET(flags, level);
+ HTTP_DEFLATE_WBITS_SET(flags, wbits);
+ HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
+
+ if (Z_OK == (status = deflateInit2(&s->stream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy))) {
+ int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
+
+ if ((s->stream.opaque = phpstr_init_ex(NULL, 0x8000, p))) {
+ return s;
+ }
+ deflateEnd(&s->stream);
+ status = Z_MEM_ERROR;
+ }
+
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize deflate encoding stream: %s", zError(status));
+ if (free_stream) {
+ efree(s);
+ }
+ return NULL;
}
-PHP_HTTP_API STATUS _http_encoding_deflate(int level, int zhdr, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC)
+http_encoding_stream *_http_encoding_inflate_stream_init(http_encoding_stream *s, int flags TSRMLS_DC)
{
- z_stream Z;
- STATUS status = Z_OK;
+ int status, wbits, free_stream;
- *encoded = NULL;
- *encoded_len = 0;
- memset(&Z, 0, sizeof(z_stream));
-
- Z.data_type = Z_UNKNOWN;
- Z.next_in = (Bytef *) data;
- Z.avail_in = data_len;
- Z.avail_out = HTTP_ENCODING_BUFLEN(data_len) - 1;
- Z.next_out = emalloc(HTTP_ENCODING_BUFLEN(data_len));
+ if ((free_stream = !s)) {
+ s = emalloc(sizeof(http_encoding_stream));
+ }
+ memset(s, 0, sizeof(http_encoding_stream));
+ s->flags = flags;
- *encoded = (char *) Z.next_out;
+ HTTP_INFLATE_WBITS_SET(flags, wbits);
- if (Z_OK == (status = deflateInit2(&Z, level, Z_DEFLATED, zhdr ? MAX_WBITS : -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
- status = deflate(&Z, Z_FINISH);
- deflateEnd(&Z);
+ if (Z_OK == (status = inflateInit2(&s->stream, wbits))) {
+ int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
- if (Z_STREAM_END == status) {
- (*encoded)[*encoded_len = Z.total_out] = '\0';
- return SUCCESS;
+ if ((s->stream.opaque = phpstr_init_ex(NULL, 0x8000, p))) {
+ return s;
}
+ inflateEnd(&s->stream);
+ status = Z_MEM_ERROR;
+ }
+
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize inflate stream: %s", zError(status));
+ if (free_stream) {
+ efree(s);
+ }
+ return NULL;
+}
+
+STATUS _http_encoding_deflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC)
+{
+ int status;
+
+ /* append input to our buffer */
+ phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
+
+ s->stream.next_in = PHPSTR_VAL(s->stream.opaque);
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
+
+ /* deflate */
+ s->stream.avail_out = *encoded_len = HTTP_ENCODING_BUFLEN(data_len);
+ s->stream.next_out = *encoded = emalloc(*encoded_len);
+
+ switch (status = deflate(&s->stream, Z_NO_FLUSH))
+ {
+ case Z_OK:
+ case Z_STREAM_END:
+ /* cut processed chunk off the buffer */
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, data_len - s->stream.avail_in);
+
+ /* size buffer down to actual size */
+ *encoded_len -= s->stream.avail_out;
+ *encoded = erealloc(*encoded, *encoded_len + 1);
+ (*encoded)[*encoded_len] = '\0';
+ return SUCCESS;
+ break;
}
STR_SET(*encoded, NULL);
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not deflate data: %s", zError(status));
+ *encoded_len = 0;
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update deflate stream: %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 TSRMLS_DC)
+STATUS _http_encoding_inflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len TSRMLS_DC)
{
- int max = 0, wbits = -MAX_WBITS;
- STATUS status;
- z_stream Z;
+ int status, max = 0;
+
+ /* append input to buffer */
+ phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
+ /* for realloc() */
*decoded = NULL;
- *decoded_len = 0;
- memset(&Z, 0, sizeof(z_stream));
+ *decoded_len = data_len << 1;
+ /* inflate */
do {
- if (!max) {
- *decoded_len = data_len * 2;
- *decoded = emalloc(*decoded_len + 1);
- } else {
- size_t new_len = *decoded_len << 2;
- char *new_ptr = erealloc_recoverable(*decoded, new_len + 1);
-
- if (new_ptr) {
- *decoded = new_ptr;
- *decoded_len = new_len;
- } else {
- max = INT_MAX-1; /* avoid integer overflow on increment op */
- }
- }
+ *decoded_len <<= 1;
+ *decoded = erealloc(*decoded, *decoded_len);
-retry_inflate:
- Z.next_in = (Bytef *) data;
- Z.avail_in = data_len;
- Z.next_out = (Bytef *) *decoded;
- Z.avail_out = *decoded_len;
+retry_raw_inflate:
+ s->stream.next_in = PHPSTR_VAL(s->stream.opaque);
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
+
+ s->stream.next_out = *decoded;
+ s->stream.avail_out = *decoded_len;
- if (Z_OK == (status = inflateInit2(&Z, wbits))) {
- status = inflate(&Z, Z_FINISH);
- inflateEnd(&Z);
-
- /* retry if it looks like we've got a zlib header */
- if (wbits == -MAX_WBITS && status == Z_DATA_ERROR) {
- wbits = MAX_WBITS;
- goto retry_inflate;
- }
-
- if (Z_STREAM_END == status) {
- (*decoded)[*decoded_len = Z.total_out] = '\0';
+ switch (status = inflate(&s->stream, Z_NO_FLUSH))
+ {
+ case Z_OK:
+ case Z_STREAM_END:
+ /* cut off */
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, data_len - s->stream.avail_in);
+
+ /* size down */
+ *decoded_len -= s->stream.avail_out;
+ *decoded = erealloc(*decoded, *decoded_len + 1);
+ (*decoded)[*decoded_len] = '\0';
return SUCCESS;
- }
+ break;
+
+ case Z_DATA_ERROR:
+ /* raw deflated data ? */
+ if (!(s->flags & HTTP_INFLATE_TYPE_RAW) && !s->stream.total_out) {
+ inflateEnd(&s->stream);
+ s->flags |= HTTP_INFLATE_TYPE_RAW;
+ inflateInit2(&s->stream, HTTP_WINDOW_BITS_RAW);
+ goto retry_raw_inflate;
+ }
+ break;
}
- } while (status == Z_BUF_ERROR && ++max < HTTP_ENCODING_MAXTRY);
+ if (Z_BUF_ERROR == status) DebugBreak();
+ } while (Z_BUF_ERROR == status && ++max < HTTP_ENCODING_MAXTRY);
+
+ STR_SET(*decoded, NULL);
+ *decoded_len = 0;
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not update inflate stream: %s", zError(status));
+ return FAILURE;
+}
+
+STATUS _http_encoding_deflate_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len TSRMLS_DC)
+{
+ int status;
+
+ /* deflate remaining input */
+ s->stream.next_in = PHPSTR_VAL(s->stream.opaque);
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
+
+ s->stream.avail_out = *encoded_len = 0x800;
+ s->stream.next_out = *encoded = emalloc(*encoded_len);
+
+ do {
+ status = deflate(&s->stream, Z_FINISH);
+ } while (Z_OK == status);
+
+ if (Z_STREAM_END == status) {
+ /* cut processed intp off */
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
+
+ /* size down */
+ *encoded_len -= s->stream.avail_out;
+ *encoded = erealloc(*encoded, *encoded_len + 1);
+ (*encoded)[*encoded_len] = '\0';
+ return SUCCESS;
+ }
+
+ STR_SET(*encoded, NULL);
+ *encoded_len = 0;
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish deflate stream: %s", zError(status));
+ return FAILURE;
+}
+
+STATUS _http_encoding_inflate_stream_finish(http_encoding_stream *s, char **decoded, size_t *decoded_len TSRMLS_DC)
+{
+ int status;
+
+ /* inflate remaining input */
+ s->stream.next_in = PHPSTR_VAL(s->stream.opaque);
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
+
+ s->stream.avail_out = *decoded_len = s->stream.avail_in << 2;
+ s->stream.next_out = *decoded = emalloc(*decoded_len);
+
+ if (Z_STREAM_END == (status = inflate(&s->stream, Z_FINISH))) {
+ /* cut processed input off */
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
+
+ /* size down */
+ *decoded_len -= s->stream.avail_out;
+ *decoded = erealloc(*decoded, *decoded_len + 1);
+ (*decoded)[*decoded_len] = '\0';
+ return SUCCESS;
+ }
STR_SET(*decoded, NULL);
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s", zError(status));
+ *decoded_len = 0;
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish inflate stream: %s", zError(status));
return FAILURE;
}
+void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
+{
+ if (s) {
+ if (s->stream.opaque) {
+ phpstr_free((phpstr **) &s->stream.opaque);
+ }
+ deflateEnd(&s->stream);
+ }
+}
+
+void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
+{
+ if (s) {
+ if (s->stream.opaque) {
+ phpstr_free((phpstr **) &s->stream.opaque);
+ }
+ inflateEnd(&s->stream);
+ }
+}
+
+void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC)
+{
+ if (s) {
+ http_encoding_deflate_stream_dtor(*s);
+ if (*s) {
+ pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
+ }
+ *s = NULL;
+ }
+}
+
+void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC)
+{
+ if (s) {
+ http_encoding_inflate_stream_dtor(*s);
+ if (*s) {
+ pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
+ }
+ *s = NULL;
+ }
+}
+
+static const char http_encoding_gzip_header[] = {
+ (const char) 0x1f, // fixed value
+ (const char) 0x8b, // fixed value
+ (const char) Z_DEFLATED, // compression algorithm
+ (const char) 0, // none of the possible flags defined by the GZIP "RFC"
+ (const char) 0, // MTIME
+ (const char) 0, // =*=
+ (const char) 0, // =*=
+ (const char) 0, // =*=
+ (const char) 0, // two possible flag values for 9 compression levels? o_O
+#ifdef PHP_WIN32
+ (const char) 0x0b // OS_CODE
+#else
+ (const char) 0x03 // OS_CODE
+#endif
+};
+
PHP_HTTP_API STATUS _http_encoding_gzencode_verify(const char *data, size_t data_len, const char **encoded, size_t *encoded_len, int error_level TSRMLS_DC)
{
size_t offset = sizeof(http_encoding_gzip_header);
return status;
}
-#define HTTP_ENCODING_STREAM_ERROR(status, tofree) \
- { \
- if (tofree) efree(tofree); \
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "GZIP stream error: %s", zError(status)); \
- return FAILURE; \
- }
-
-PHP_HTTP_API STATUS _http_encoding_stream_init(http_encoding_stream *s, int flags, int level, char **encoded, size_t *encoded_len TSRMLS_DC)
-{
- STATUS status;
- int wbits = (flags & HTTP_ENCODING_STREAM_ZLIB_HEADER) ? MAX_WBITS : -MAX_WBITS;
-
- memset(s, 0, sizeof(http_encoding_stream));
- if (Z_OK != (status = deflateInit2(&s->Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
- HTTP_ENCODING_STREAM_ERROR(status, NULL);
- }
-
- s->persistent = (flags & HTTP_ENCODING_STREAM_PERSISTENT);
- if ((s->gzip = (flags & HTTP_ENCODING_STREAM_GZIP_HEADER))) {
- s->crc = crc32(0L, Z_NULL, 0);
- *encoded_len = sizeof(http_encoding_gzip_header);
- *encoded = pemalloc(*encoded_len, s->persistent);
- memcpy(*encoded, http_encoding_gzip_header, *encoded_len);
- } else {
- *encoded_len = 0;
- *encoded = NULL;
- }
-
- return SUCCESS;
-}
-
-PHP_HTTP_API STATUS _http_encoding_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC)
-{
- STATUS status;
-
- *encoded_len = HTTP_ENCODING_BUFLEN(data_len);
- *encoded = pemalloc(*encoded_len, s->persistent);
-
- s->Z.next_in = (Bytef *) data;
- s->Z.avail_in = data_len;
- s->Z.next_out = (Bytef *) *encoded;
- s->Z.avail_out = *encoded_len;
-
- status = deflate(&s->Z, Z_SYNC_FLUSH);
-
- if (Z_OK != status && Z_STREAM_END != status) {
- HTTP_ENCODING_STREAM_ERROR(status, *encoded);
- }
- *encoded_len -= s->Z.avail_out;
-
- if (s->gzip) {
- s->crc = crc32(s->crc, (const Bytef *) data, data_len);
- }
-
- return SUCCESS;
-}
-
-PHP_HTTP_API STATUS _http_encoding_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len TSRMLS_DC)
-{
- STATUS status;
-
- *encoded_len = 1024;
- *encoded = pemalloc(*encoded_len, s->persistent);
-
- s->Z.next_out = (Bytef *) *encoded;
- s->Z.avail_out = *encoded_len;
-
- if (Z_STREAM_END != (status = deflate(&s->Z, Z_FINISH)) || Z_OK != (status = deflateEnd(&s->Z))) {
- HTTP_ENCODING_STREAM_ERROR(status, *encoded);
- }
-
- *encoded_len -= s->Z.avail_out;
- if (s->gzip) {
- if (s->Z.avail_out < 8) {
- *encoded = perealloc(*encoded, *encoded_len + 8, s->persistent);
- }
- (*encoded)[(*encoded_len)++] = (char) (s->crc & 0xFF);
- (*encoded)[(*encoded_len)++] = (char) ((s->crc >> 8) & 0xFF);
- (*encoded)[(*encoded_len)++] = (char) ((s->crc >> 16) & 0xFF);
- (*encoded)[(*encoded_len)++] = (char) ((s->crc >> 24) & 0xFF);
- (*encoded)[(*encoded_len)++] = (char) ((s->Z.total_in) & 0xFF);
- (*encoded)[(*encoded_len)++] = (char) ((s->Z.total_in >> 8) & 0xFF);
- (*encoded)[(*encoded_len)++] = (char) ((s->Z.total_in >> 16) & 0xFF);
- (*encoded)[(*encoded_len)++] = (char) ((s->Z.total_in >> 24) & 0xFF);
- }
-
- return SUCCESS;
-}
-
#endif /* HTTP_HAVE_ZLIB */
PHP_HTTP_API zend_bool _http_encoding_response_start(size_t content_length TSRMLS_DC)
} HTTP_FILTER_BUFFER(chunked_decode);
#ifdef HTTP_HAVE_ZLIB
-typedef struct {
- int init;
- int flags;
- http_encoding_stream stream;
-} HTTP_FILTER_BUFFER(gzip);
+typedef http_encoding_stream HTTP_FILTER_BUFFER(deflate);
+typedef http_encoding_stream HTTP_FILTER_BUFFER(inflate);
#endif /* HTTP_HAVE_ZLIB */
};
#ifdef HTTP_HAVE_ZLIB
-static HTTP_FILTER_FUNCTION(gzip)
+
+static HTTP_FILTER_FUNCTION(deflate)
{
int out_avail = 0;
php_stream_bucket *ptr, *nxt;
- HTTP_FILTER_BUFFER(gzip) *buffer = (HTTP_FILTER_BUFFER(gzip) *) this->abstract;
+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
if (bytes_consumed) {
*bytes_consumed = 0;
}
- /* first round */
- if (!buffer->init) {
+ /* 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;
+ }
+
+ if (ptr->buflen) {
+ http_encoding_deflate_stream_update(buffer, ptr->buf, ptr->buflen, &encoded, &encoded_len);
+ if (encoded) {
+ out_avail = 1;
+ NEW_BUCKET(encoded, encoded_len);
+ efree(encoded);
+ }
+ }
+
+ 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;
- buffer->init = 1;
- http_encoding_stream_init(&buffer->stream, buffer->flags, -1, &encoded, &encoded_len);
-
+ http_encoding_deflate_stream_finish(buffer, &encoded, &encoded_len);
if (encoded) {
out_avail = 1;
NEW_BUCKET(encoded, encoded_len);
- pefree(encoded, this->is_persistent);
+ efree(encoded);
}
}
+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
+}
+
+static HTTP_FILTER_FUNCTION(inflate)
+{
+ int out_avail = 0;
+ php_stream_bucket *ptr, *nxt;
+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
+
+ if (bytes_consumed) {
+ *bytes_consumed = 0;
+ }
+
/* 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;
+ char *decoded = NULL;
+ size_t decoded_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);
+ if (ptr->buflen) {
+ http_encoding_inflate_stream_update(buffer, ptr->buf, ptr->buflen, &decoded, &decoded_len);
+ if (decoded) {
+ out_avail = 1;
+ NEW_BUCKET(decoded, decoded_len);
+ efree(decoded);
+ }
}
php_stream_bucket_unlink(ptr TSRMLS_CC);
/* flush & close */
if (flags == PSFS_FLAG_FLUSH_CLOSE) {
- char *encoded = NULL;
- size_t encoded_len = 0;
+ char *decoded = NULL;
+ size_t decoded_len = 0;
- http_encoding_stream_finish(&buffer->stream, &encoded, &encoded_len);
- if (encoded) {
+ http_encoding_inflate_stream_finish(buffer, &decoded, &decoded_len);
+ if (decoded) {
out_avail = 1;
- NEW_BUCKET(encoded, encoded_len);
+ NEW_BUCKET(decoded, decoded_len);
+ efree(decoded);
}
}
return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
}
-static HTTP_FILTER_DESTRUCTOR(gzip)
+static HTTP_FILTER_DESTRUCTOR(deflate)
{
- HTTP_FILTER_BUFFER(gzip) *buffer = (HTTP_FILTER_BUFFER(gzip) *) this->abstract;
-
- pefree(buffer, this->is_persistent);
+ HTTP_FILTER_BUFFER(deflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
+ http_encoding_deflate_stream_free(&buffer);
}
-static HTTP_FILTER_OPS(gzencode) = {
- HTTP_FILTER_FUNC(gzip),
- HTTP_FILTER_DTOR(gzip),
- "http.gzencode"
-};
+static HTTP_FILTER_DESTRUCTOR(inflate)
+{
+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
+ http_encoding_inflate_stream_free(&buffer);
+}
static HTTP_FILTER_OPS(deflate) = {
- HTTP_FILTER_FUNC(gzip),
- HTTP_FILTER_DTOR(gzip),
+ HTTP_FILTER_FUNC(deflate),
+ HTTP_FILTER_DTOR(deflate),
"http.deflate"
};
+
+static HTTP_FILTER_OPS(inflate) = {
+ HTTP_FILTER_FUNC(inflate),
+ HTTP_FILTER_DTOR(inflate),
+ "http.inflate"
+};
+
#endif /* HTTP_HAVE_ZLIB */
static php_stream_filter *http_filter_create(const char *name, zval *params, int p TSRMLS_DC)
#ifdef HTTP_HAVE_ZLIB
} else
- if (!strcasecmp(name, "http.gzencode")) {
- HTTP_FILTER_BUFFER(gzip) *b = NULL;
+ if (!strcasecmp(name, "http.inflate")) {
+ int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
+ HTTP_FILTER_BUFFER(inflate) *b = NULL;
- if ((b = pecalloc(1, sizeof(HTTP_FILTER_BUFFER(gzip)), p))) {
- b->flags = HTTP_ENCODING_STREAM_GZIP_HEADER;
- if (p) {
- b->flags |= HTTP_ENCODING_STREAM_PERSISTENT;
- }
- if (params) {
- switch (Z_TYPE_P(params))
- {
- case IS_ARRAY:
- case IS_OBJECT:
- if (SUCCESS != zend_hash_find(HASH_OF(params), "zlib", sizeof("zlib"), (void **) &tmp)) {
- break;
- }
- default:
- if (zval_is_true(*tmp)) {
- b->flags |= HTTP_ENCODING_STREAM_ZLIB_HEADER;
- }
- }
- }
- if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(gzencode), b, p))) {
- pefree(b, p);
+ if ((b = http_encoding_inflate_stream_init(NULL, flags))) {
+ if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(inflate), b, p))) {
+ http_encoding_inflate_stream_free(&b);
}
}
} else
if (!strcasecmp(name, "http.deflate")) {
- HTTP_FILTER_BUFFER(gzip) *b = NULL;
+ int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
+ HTTP_FILTER_BUFFER(deflate) *b = NULL;
- if ((b = pecalloc(1, sizeof(HTTP_FILTER_BUFFER(gzip)), p))) {
- if (p) {
- b->flags |= HTTP_ENCODING_STREAM_PERSISTENT;
- }
- if (params) {
- switch (Z_TYPE_P(params))
+ if (params) {
+ switch (Z_TYPE_P(params))
+ {
+ case IS_ARRAY:
+ case IS_OBJECT:
+ if (SUCCESS != zend_hash_find(HASH_OF(params), "flags", sizeof("flags"), (void **) &tmp)) {
+ break;
+ }
+ default:
{
- case IS_ARRAY:
- case IS_OBJECT:
- if (SUCCESS != zend_hash_find(HASH_OF(params), "zlib", sizeof("zlib"), (void **) &tmp)) {
- break;
- }
- default:
- if (zval_is_true(*tmp)) {
- b->flags |= HTTP_ENCODING_STREAM_ZLIB_HEADER;
- }
+ zval *orig = *tmp;
+
+ convert_to_long_ex(tmp);
+ flags |= (Z_LVAL_PP(tmp) & 0x0fffffff);
+ if (orig != *tmp) zval_ptr_dtor(tmp);
}
}
+ }
+ if ((b = http_encoding_deflate_stream_init(NULL, flags))) {
if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(deflate), b, p))) {
- pefree(b, p);
+ http_encoding_deflate_stream_free(&b);
}
}
#endif /* HTTP_HAVE_ZLIB */
/* {{{ */
#ifdef HTTP_HAVE_ZLIB
-/* {{{ proto string http_gzencode(string data[, int level = -1[, int mtime = 0]])
+/* {{{ proto string http_deflate(string data[, int flags = 0])
*
- * Compress data with the HTTP compatible GZIP encoding.
- *
- * Expects the first parameter to be a string which contains the data that
- * should be encoded. Additionally accepts an optional in paramter specifying
- * the compression level, where -1 is default, 0 is no compression and 9 is
- * best compression ratio.
- *
- * Returns the encoded string on success, or NULL on failure.
- */
-PHP_FUNCTION(http_gzencode)
-{
- char *data;
- int data_len;
- long level = -1, mtime = 0;
-
- RETVAL_NULL();
-
- if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &level, &mtime)) {
- HTTP_CHECK_GZIP_LEVEL(level, return);
- {
- char *encoded;
- size_t encoded_len;
-
- if (SUCCESS == http_encoding_gzencode(level, mtime, data, data_len, &encoded, &encoded_len)) {
- RETURN_STRINGL(encoded, (int) encoded_len, 0);
- }
- }
- }
-}
-/* }}} */
-
-/* {{{ proto string http_gzdecode(string data)
- *
- * Uncompress data compressed with the HTTP compatible GZIP encoding.
- *
- * Expects a string as parameter containing the compressed data.
- *
- * Returns the decoded string on success, or NULL on failure.
- */
-PHP_FUNCTION(http_gzdecode)
-{
- char *data;
- int data_len;
-
- RETVAL_NULL();
-
- if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
- char *decoded;
- size_t decoded_len;
-
- if (SUCCESS == http_encoding_gzdecode(data, data_len, &decoded, &decoded_len)) {
- RETURN_STRINGL(decoded, (int) decoded_len, 0);
- }
- }
-}
-/* }}} */
-
-/* {{{ proto string http_deflate(string data[, int level = -1[, bool zlib_header = false]])
- *
- * Compress data with the HTTP compatible DEFLATE encoding.
+ * Compress data with gzip, zlib AKA deflate or raw deflate encoding.
*
* Expects the first parameter to be a string containing the data that should
- * be encoded. Additionally accepts an optional int parameter specifying the
- * compression level, where -1 is default, 0 is no compression and 9 is best
- * compression ratio.
+ * be encoded.
*
* Returns the encoded string on success, or NULL on failure.
*/
{
char *data;
int data_len;
- long level = -1;
- zend_bool zhdr = 0;
+ long flags = 0;
RETVAL_NULL();
- if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &data, &data_len, &level, &zhdr)) {
- HTTP_CHECK_GZIP_LEVEL(level, return);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags)) {
{
char *encoded;
size_t encoded_len;
- if (SUCCESS == http_encoding_deflate(level, zhdr, data, data_len, &encoded, &encoded_len)) {
+ if (SUCCESS == http_encoding_deflate(flags, data, data_len, &encoded, &encoded_len)) {
RETURN_STRINGL(encoded, (int) encoded_len, 0);
}
}
/* {{{ proto string http_inflate(string data)
*
- * Uncompress data compressed with the HTTP compatible DEFLATE encoding.
+ * Uncompress data compressed with either gzip, deflate AKA zlib or raw
+ * deflate encoding.
*
* Expects a string as parameter containing the compressed data.
*
# ifndef HTTP_HAVE_ZLIB
DECODE_WITH_EXT_ZLIB("gzinflate", PHPSTR_VAL(msg) + 10, PHPSTR_LEN(msg) - 18);
# else
- http_encoding_gzdecode(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len);
+ http_encoding_inflate(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len);
} else if (!strcasecmp(Z_STRVAL_P(c), "deflate") || !strcasecmp(Z_STRVAL_P(c), "compress") || !strcasecmp(Z_STRVAL_P(c), "x-compress")) {
http_encoding_inflate(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len);
# endif /* HTTP_HAVE_ZLIB */
}
}
+#if LIBCURL_VERSIONNUM >= 0x070f01
/* reset cookies */
if ((zoption = http_request_option(request, options, "resetcookies", IS_BOOL)) && Z_LVAL_P(zoption)) {
HTTP_CURL_OPT(COOKIELIST, "ALL");
}
-
+#endif
+
/* session cookies */
if ((zoption = http_request_option(request, options, "cookiesession", IS_BOOL))) {
if (Z_LVAL_P(zoption)) {
#define http_send_response_start(b, cl) _http_send_response_start((b), (cl) TSRMLS_CC)
static inline void _http_send_response_start(void **buffer, size_t content_length TSRMLS_DC)
{
- if (http_encoding_response_start(content_length)) {
+ int encoding;
+
+ if ((encoding = http_encoding_response_start(content_length))) {
+ //DebugBreak();
#ifdef HTTP_HAVE_ZLIB
- char *encoded;
- size_t encoded_len;
- int gzip = (HTTP_G(send).gzip_encoding == HTTP_ENCODING_GZIP);
- http_encoding_stream *s = emalloc(sizeof(http_encoding_stream));
-
- http_encoding_stream_init(s, gzip?HTTP_ENCODING_STREAM_GZIP_HEADER:0, -1, &encoded, &encoded_len);
- phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, HTTP_G(send).buffer_size, _http_flush TSRMLS_CC);
- STR_FREE(encoded);
- *buffer = s;
+ *buffer = http_encoding_deflate_stream_init(NULL,
+ (encoding == HTTP_ENCODING_GZIP) ?
+ HTTP_DEFLATE_TYPE_GZIP : HTTP_DEFLATE_TYPE_ZLIB);
#endif
}
}
size_t encoded_len;
http_encoding_stream *s = *((http_encoding_stream **) buffer);
- http_encoding_stream_update(s, data, data_len, &encoded, &encoded_len);
+ http_encoding_deflate_stream_update(s, data, data_len, &encoded, &encoded_len);
phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, HTTP_G(send).buffer_size, _http_flush TSRMLS_CC);
efree(encoded);
#else
size_t encoded_len = 0;
http_encoding_stream *s = *((http_encoding_stream **) buffer);
- http_encoding_stream_finish(s, &encoded, &encoded_len);
+ http_encoding_deflate_stream_finish(s, &encoded, &encoded_len);
phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, 0, _http_flush TSRMLS_CC);
+ http_encoding_deflate_stream_free(&s);
STR_FREE(encoded);
- efree(s);
#else
http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug");
#endif
HTTP_UTIL_ALIAS(parseCookie, http_parse_cookie)
HTTP_UTIL_ALIAS(chunkedDecode, http_chunked_decode)
#ifdef HTTP_HAVE_ZLIB
- HTTP_UTIL_ALIAS(gzEncode, http_gzencode)
- HTTP_UTIL_ALIAS(gzDecode, http_gzdecode)
HTTP_UTIL_ALIAS(deflate, http_deflate)
HTTP_UTIL_ALIAS(inflate, http_inflate)
#endif /* HTTP_HAVE_ZLIB */
#endif /* ZEND_ENGINE_2 */
PHP_FUNCTION(ob_etaghandler);
#ifdef HTTP_HAVE_ZLIB
-PHP_FUNCTION(http_gzencode);
-PHP_FUNCTION(http_gzdecode);
PHP_FUNCTION(http_deflate);
PHP_FUNCTION(http_inflate);
#endif
#ifdef HTTP_HAVE_ZLIB
+extern PHP_MINIT_FUNCTION(http_encoding);
+
/* max count of uncompress trials, alloc_size <<= 2 for each try */
#define HTTP_ENCODING_MAXTRY 10
/* safe padding */
-#define HTTP_ENCODING_SAFPAD 10
+#define HTTP_ENCODING_SAFPAD 28
/* add 1% extra space in case we need to encode widely differing (binary) data */
#define HTTP_ENCODING_BUFLEN(l) (l + (l / 100) + HTTP_ENCODING_SAFPAD)
typedef enum {
- HTTP_ENCODING_NONE = 0,
+ HTTP_ENCODING_NONE,
HTTP_ENCODING_GZIP,
HTTP_ENCODING_DEFLATE,
} http_encoding_type;
-#define HTTP_ENCODING_STREAM_GZIP_HEADER 0x1
-#define HTTP_ENCODING_STREAM_ZLIB_HEADER 0x2
-#define HTTP_ENCODING_STREAM_PERSISTENT 0x4
+#define HTTP_DEFLATE_LEVEL_DEF 0x00000000
+#define HTTP_DEFLATE_LEVEL_MIN 0x00000001
+#define HTTP_DEFLATE_LEVEL_MAX 0x00000002
+#define HTTP_DEFLATE_TYPE_ZLIB 0x00000000
+#define HTTP_DEFLATE_TYPE_GZIP 0x00000010
+#define HTTP_DEFLATE_TYPE_RAW 0x00000020
+#define HTTP_DEFLATE_STRATEGY_DEF 0x00000000
+#define HTTP_DEFLATE_STRATEGY_FILT 0x00000100
+#define HTTP_DEFLATE_STRATEGY_HUFF 0x00000200
+#define HTTP_DEFLATE_STRATEGY_RLE 0x00000300
+#define HTTP_DEFLATE_STRATEGY_FIXED 0x00000400
+
+#define HTTP_INFLATE_TYPE_ZLIB 0x00000000
+#define HTTP_INFLATE_TYPE_GZIP 0x00000000
+#define HTTP_INFLATE_TYPE_RAW 0x00000001
+
+#define HTTP_ENCODING_STREAM_PERSISTENT 0x01000000
typedef struct {
- z_stream Z;
- int gzip;
- int persistent;
- ulong crc;
+ z_stream stream;
+ int flags;
void *storage;
} http_encoding_stream;
-#define http_encoding_stream_init(s, g, l, e, el) _http_encoding_stream_init((s), (g), (l), (e), (el) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_encoding_stream_init(http_encoding_stream *s, int flags, int level, char **encoded, size_t *encoded_len TSRMLS_DC);
-#define http_encoding_stream_update(s, d, dl, e, el) _http_encoding_stream_update((s), (d), (dl), (e), (el) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_encoding_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC);
-#define http_encoding_stream_finish(s, e, el) _http_encoding_stream_finish((s), (e), (el) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_encoding_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len TSRMLS_DC);
-
-#define http_encoding_gzencode_verify(d, dl, e, el) _http_encoding_gzencode_verify((d), (dl), (e), (el), HE_NOTICE)
-PHP_HTTP_API STATUS _http_encoding_gzencode_verify(const char *data, size_t data_len, const char **encoded, size_t *encoded_len, int error_level TSRMLS_DC);
-#define http_encoding_gzdecode_verify(e, el, d, dl) _http_encoding_gzdecode_verify((e), (el), (d), (dl), HE_NOTICE)
-PHP_HTTP_API STATUS _http_encoding_gzdecode_verify(const char *data, size_t data_len, const char *decoded, size_t decoded_len, int error_level TSRMLS_DC);
-
-#define http_encoding_gzencode(l, m, d, dl, r, rl) _http_encoding_gzencode((l), (m), (d), (dl), (r), (rl) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_encoding_gzencode(int level, int mtime, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC);
-#define http_encoding_gzdecode(d, dl, r, rl) _http_encoding_gzdecode((d), (dl), (r), (rl) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_encoding_gzdecode(const char *data, size_t data_len, char **decoded, size_t *decoded_len TSRMLS_DC);
-#define http_encoding_deflate(l, h, d, dl, r, rl) _http_encoding_deflate((l), (h), (d), (dl), (r), (rl) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_encoding_deflate(int level, int zhdr, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC);
+#define http_encoding_deflate(f, d, dl, r, rl) _http_encoding_deflate((f), (d), (dl), (r), (rl) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC);
#define http_encoding_inflate(d, dl, r, rl) _http_encoding_inflate((d), (dl), (r), (rl) TSRMLS_CC)
PHP_HTTP_API STATUS _http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len TSRMLS_DC);
+#define http_encoding_deflate_stream_init(s, f) _http_encoding_deflate_stream_init((s), (f) TSRMLS_CC)
+PHP_HTTP_API http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *s, int flags TSRMLS_DC);
+#define http_encoding_deflate_stream_update(s, d, dl, e, el) _http_encoding_deflate_stream_update((s), (d), (dl), (e), (el) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len TSRMLS_DC);
+#define http_encoding_deflate_stream_finish(s, e, el) _http_encoding_deflate_stream_finish((s), (e), (el) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len TSRMLS_DC);
+#define http_encoding_deflate_stream_dtor(s) _http_encoding_deflate_stream_dtor((s) TSRMLS_CC)
+PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
+#define http_encoding_deflate_stream_free(s) _http_encoding_deflate_stream_free((s) TSRMLS_CC)
+PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC);
+
+#define http_encoding_inflate_stream_init(s, f) _http_encoding_inflate_stream_init((s), (f) TSRMLS_CC)
+PHP_HTTP_API http_encoding_stream *_http_encoding_inflate_stream_init(http_encoding_stream *s, int flags TSRMLS_DC);
+#define http_encoding_inflate_stream_update(s, d, dl, e, el) _http_encoding_inflate_stream_update((s), (d), (dl), (e), (el) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len TSRMLS_DC);
+#define http_encoding_inflate_stream_finish(s, e, el) _http_encoding_inflate_stream_finish((s), (e), (el) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_finish(http_encoding_stream *s, char **decoded, size_t *decoded_len TSRMLS_DC);
+#define http_encoding_inflate_stream_dtor(s) _http_encoding_inflate_stream_dtor((s) TSRMLS_CC)
+PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
+#define http_encoding_inflate_stream_free(s) _http_encoding_inflate_stream_free((s) TSRMLS_CC)
+PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC);
+
#endif /* HTTP_HAVE_ZLIB */
#endif
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
-
PHP_METHOD(HttpUtil, parseMessage);
PHP_METHOD(HttpUtil, parseCookie);
PHP_METHOD(HttpUtil, chunkedDecode);
-PHP_METHOD(HttpUtil, gzEncode);
-PHP_METHOD(HttpUtil, gzDecode);
PHP_METHOD(HttpUtil, deflate);
PHP_METHOD(HttpUtil, inflate);
PHP_METHOD(HttpUtil, support);
#define RETURN_PHPSTR_DUP(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
#define RETVAL_PHPSTR_PTR(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_PTR, 0)
#define RETVAL_PHPSTR_VAL(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 0)
-#define RETVAL_PHPSTR_DUP(STR) RETVAÖ_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
+#define RETVAL_PHPSTR_DUP(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
/* RETURN_PHPSTR(buf, PHPSTR_FREE_PTR, 0) */
#define RETURN_PHPSTR(STR, free, dup) \
RETVAL_PHPSTR((STR), (free), (dup)); \
%sTEST
https://www.example.com:9999/replaced?q=1#n
https://www.example.com:9999/replaced?q=1#n
-Array
+Array
(
[scheme] => https
[host] => www.example.com
$n = tempnam(dirname(__FILE__), 'hsf');
$f = fopen($n, 'wb');
-stream_filter_append($f, 'http.gzencode', STREAM_FILTER_WRITE);
+stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_GZIP);
fwrite($f, $d);
-fflush($f);
fclose($f);
-$gzencoded = file_get_contents($n);
+var_dump($d == http_inflate(file_get_contents($n)));
$f = fopen($n, 'wb');
stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE);
fwrite($f, $d);
-fflush($f);
fclose($f);
-$deflated = file_get_contents($n);
+var_dump($d == http_inflate(file_get_contents($n)));
-var_dump($d == http_gzdecode($gzencoded));
-var_dump($d == http_inflate($deflated));
+$f = fopen($n, 'wb');
+stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_RAW);
+fwrite($f, $d);
+fclose($f);
+var_dump($d == http_inflate(file_get_contents($n)));
unlink($n);
%sTEST
bool(true)
bool(true)
+bool(true)
Done