From 3f47fc4cd2911b718b155de4e37752db9fa4f8c8 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 10 Oct 2005 16:40:15 +0000 Subject: [PATCH 1/1] - add compression functions to userspace --- http_functions.c | 182 ++++++++++++++++++++++++++++++++++++++++ http_util_object.c | 43 ++++++++-- package2.xml | 3 + php_http.h | 8 ++ php_http_api.h | 6 +- php_http_util_object.h | 8 +- tests/request_gzip.phpt | 4 +- 7 files changed, 246 insertions(+), 8 deletions(-) diff --git a/http_functions.c b/http_functions.c index 364e81f..d205ea2 100644 --- a/http_functions.c +++ b/http_functions.c @@ -1408,6 +1408,188 @@ PHP_FUNCTION(http_build_query) #endif /* !ZEND_ENGINE_2 */ /* }}} */ +/* {{{ */ +#ifdef HTTP_HAVE_ZLIB + +/* {{{ proto string http_gzencode(string data[, int level = -1]) + * + * 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; + + RETVAL_NULL(); + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level)) { + HTTP_CHECK_GZIP_LEVEL(level, return); + { + char *encoded; + size_t encoded_len; + + if (SUCCESS == http_encoding_gzencode(level, 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]) + * + * Compress data with the HTTP compatible 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. + * + * Returns the encoded string on success, or NULL on failure. + */ +PHP_FUNCTION(http_deflate) +{ + char *data; + int data_len; + long level = -1; + + RETVAL_NULL(); + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level)) { + HTTP_CHECK_GZIP_LEVEL(level, return); + { + char *encoded; + size_t encoded_len; + + if (SUCCESS == http_encoding_deflate(level, 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. + * + * Expects a string as parameter containing the compressed data. + * + * Returns the decoded string on success, or NULL on failure. + */ +PHP_FUNCTION(http_inflate) +{ + 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_inflate(data, data_len, &decoded, &decoded_len)) { + RETURN_STRINGL(decoded, (int) decoded_len, 0); + } + } +} +/* }}} */ + +/* {{{ proto string http_compress(string data[, int level = -1]) + * + * Compress data with the HTTP compatible COMPRESS encoding. + * + * Expects the first parameter to be a string containing the data which 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. + * + * Returns the encoded string on success, or NULL on failure. + */ +PHP_FUNCTION(http_compress) +{ + char *data; + int data_len; + long level; + + RETVAL_NULL(); + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level)) { + HTTP_CHECK_GZIP_LEVEL(level, return); + { + char *encoded; + size_t encoded_len; + + if (SUCCESS == http_encoding_compress(level, data, data_len, &encoded, &encoded_len)) { + RETURN_STRINGL(encoded, (int) encoded_len, 0); + } + } + } +} +/* }}} */ + +/* {{{ proto string http_uncompress(string data) + * + * Uncompress data compressed with the HTTP compatible COMPRESS encoding. + * + * Expects a string as parameter containing the compressed data. + * + * Returns the decoded string on success, or NULL on failure. + */ +PHP_FUNCTION(http_uncompress) +{ + 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_uncompress(data, data_len, &decoded, &decoded_len)) { + RETURN_STRINGL(decoded, decoded_len, 0); + } + } +} +/* }}} */ +#endif /* HTTP_HAVE_ZLIB */ +/* }}} */ + PHP_FUNCTION(http_test) { } diff --git a/http_util_object.c b/http_util_object.c index ac87820..8fab46b 100644 --- a/http_util_object.c +++ b/http_util_object.c @@ -69,10 +69,6 @@ HTTP_BEGIN_ARGS(matchRequestHeader, 2) HTTP_ARG_VAL(case_sensitive, 0) HTTP_END_ARGS; -HTTP_BEGIN_ARGS(chunkedDecode, 1) - HTTP_ARG_VAL(encoded_string, 0) -HTTP_END_ARGS; - HTTP_BEGIN_ARGS(parseMessage, 1) HTTP_ARG_VAL(message_string, 0) HTTP_END_ARGS; @@ -81,6 +77,37 @@ HTTP_BEGIN_ARGS(parseHeaders, 1) HTTP_ARG_VAL(headers_string, 0) HTTP_END_ARGS; +HTTP_BEGIN_ARGS(chunkedDecode, 1) + HTTP_ARG_VAL(encoded_string, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(gzEncode, 1) + HTTP_ARG_VAL(plain, 0) + HTTP_ARG_VAL(level, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(gzDecode, 1) + HTTP_ARG_VAL(encoded, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(deflate, 1) + HTTP_ARG_VAL(plain, 0) + HTTP_ARG_VAL(level, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(inflate, 1) + HTTP_ARG_VAL(encoded, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(compress, 1) + HTTP_ARG_VAL(plain, 0) + HTTP_ARG_VAL(level, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(uncompress, 1) + HTTP_ARG_VAL(encoded, 0) +HTTP_END_ARGS; + zend_class_entry *http_util_object_ce; zend_function_entry http_util_object_fe[] = { HTTP_UTIL_ALIAS(date, http_date) @@ -90,9 +117,15 @@ zend_function_entry http_util_object_fe[] = { HTTP_UTIL_ALIAS(matchModified, http_match_modified) HTTP_UTIL_ALIAS(matchEtag, http_match_etag) HTTP_UTIL_ALIAS(matchRequestHeader, http_match_request_header) - HTTP_UTIL_ALIAS(chunkedDecode, http_chunked_decode) HTTP_UTIL_ALIAS(parseMessage, http_parse_message) HTTP_UTIL_ALIAS(parseHeaders, http_parse_headers) + HTTP_UTIL_ALIAS(chunkedDecode, http_chunked_decode) + HTTP_UTIL_ALIAS(gzEncode, http_gzencode) + HTTP_UTIL_ALIAS(gzDecode, http_gzdecode) + HTTP_UTIL_ALIAS(deflate, http_deflate) + HTTP_UTIL_ALIAS(inflate, http_inflate) + HTTP_UTIL_ALIAS(compress, http_compress) + HTTP_UTIL_ALIAS(uncompress, http_uncompress) EMPTY_FUNCTION_ENTRY }; diff --git a/package2.xml b/package2.xml index efeadf3..8de160f 100644 --- a/package2.xml +++ b/package2.xml @@ -41,6 +41,7 @@ + @@ -105,6 +107,7 @@ + diff --git a/php_http.h b/php_http.h index 8600f12..223a4f6 100644 --- a/php_http.h +++ b/php_http.h @@ -132,6 +132,14 @@ PHP_FUNCTION(http_request_method_name); PHP_FUNCTION(http_build_query); #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); +PHP_FUNCTION(http_compress); +PHP_FUNCTION(http_uncompress); +#endif PHP_MINIT_FUNCTION(http); PHP_MSHUTDOWN_FUNCTION(http); diff --git a/php_http_api.h b/php_http_api.h index a6f19eb..c84331a 100644 --- a/php_http_api.h +++ b/php_http_api.h @@ -57,7 +57,11 @@ extern void _http_error_ex(long type TSRMLS_DC, long code, const char *format, . http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST"); \ action; \ } - +#define HTTP_CHECK_GZIP_LEVEL(level, action) \ + if (level < -1 || level > 9) { \ + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid compression level (-1 to 9): %d", level); \ + action; \ + } #define http_log(f, i, m) _http_log_ex((f), (i), (m) TSRMLS_CC) extern void http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC); diff --git a/php_http_util_object.h b/php_http_util_object.h index d50850e..ba711b8 100644 --- a/php_http_util_object.h +++ b/php_http_util_object.h @@ -31,9 +31,15 @@ PHP_METHOD(HttpUtil, negotiateLanguage); PHP_METHOD(HttpUtil, negotiateCharset); PHP_METHOD(HttpUtil, matchModified); PHP_METHOD(HttpUtil, matchEtag); -PHP_METHOD(HttpUtil, chunkedDecode); PHP_METHOD(HttpUtil, parseHeaders); PHP_METHOD(HttpUtil, parseMessage); +PHP_METHOD(HttpUtil, chunkedDecode); +PHP_METHOD(HttpUtil, gzEncode); +PHP_METHOD(HttpUtil, gzDecode); +PHP_METHOD(HttpUtil, deflate); +PHP_METHOD(HttpUtil, inflate); +PHP_METHOD(HttpUtil, compress); +PHP_METHOD(HttpUtil, uncompress); #endif #endif diff --git a/tests/request_gzip.phpt b/tests/request_gzip.phpt index 7a9f027..ea2cb5f 100644 --- a/tests/request_gzip.phpt +++ b/tests/request_gzip.phpt @@ -42,4 +42,6 @@ object(stdClass)#%d (%d) { " ["parentMessage"]=> NULL -}Done +} +Done + -- 2.30.2