summaryrefslogtreecommitdiff
path: root/ext/zlib/zlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/zlib/zlib.c')
-rw-r--r--ext/zlib/zlib.c106
1 files changed, 87 insertions, 19 deletions
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index dd0a1c23ef..3478fe536b 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -761,24 +761,6 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict,
switch (Z_TYPE_P(option_buffer)) {
case IS_STRING: {
zend_string *str = Z_STR_P(option_buffer);
- size_t i;
- zend_bool last_null = 1;
-
- for (i = 0; i < ZSTR_LEN(str); i++) {
- if (ZSTR_VAL(str)[i]) {
- last_null = 0;
- } else {
- if (last_null) {
- php_error_docref(NULL, E_WARNING, "dictionary string must not contain empty entries (two consecutive NULL-bytes or one at the very beginning)");
- return 0;
- }
- last_null = 1;
- }
- }
- if (!last_null) {
- php_error_docref(NULL, E_WARNING, "dictionary string must be NULL-byte terminated (each dictionary entry has to be NULL-terminated)");
- }
-
*dict = emalloc(ZSTR_LEN(str));
memcpy(*dict, ZSTR_VAL(str), ZSTR_LEN(str));
*dictlen = ZSTR_LEN(str);
@@ -886,6 +868,7 @@ PHP_FUNCTION(inflate_init)
ctx->zfree = php_zlib_free;
((php_zlib_context *) ctx)->inflateDict = dict;
((php_zlib_context *) ctx)->inflateDictlen = dictlen;
+ ((php_zlib_context *) ctx)->status = Z_OK;
if (encoding < 0) {
encoding += 15 - window;
@@ -894,6 +877,21 @@ PHP_FUNCTION(inflate_init)
}
if (Z_OK == inflateInit2(ctx, encoding)) {
+ if (encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) {
+ php_zlib_context *php_ctx = (php_zlib_context *) ctx;
+ switch (inflateSetDictionary(ctx, (Bytef *) php_ctx->inflateDict, php_ctx->inflateDictlen)) {
+ case Z_OK:
+ efree(php_ctx->inflateDict);
+ php_ctx->inflateDict = NULL;
+ break;
+ case Z_DATA_ERROR:
+ php_error_docref(NULL, E_WARNING, "dictionary does not match expected dictionary (incorrect adler32 hash)");
+ efree(php_ctx->inflateDict);
+ php_ctx->inflateDict = NULL;
+ RETURN_FALSE;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
RETURN_RES(zend_register_resource(ctx, le_inflate));
} else {
efree(ctx);
@@ -938,6 +936,13 @@ PHP_FUNCTION(inflate_add)
"flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH");
RETURN_FALSE;
}
+
+ /* Lazy-resetting the zlib stream so ctx->total_in remains available until the next inflate_add() call. */
+ if (((php_zlib_context *) ctx)->status == Z_STREAM_END)
+ {
+ ((php_zlib_context *) ctx)->status = Z_OK;
+ inflateReset(ctx);
+ }
if (in_len <= 0 && flush_type != Z_FINISH) {
RETURN_EMPTY_STRING();
@@ -953,6 +958,8 @@ PHP_FUNCTION(inflate_add)
status = inflate(ctx, flush_type);
buffer_used = ZSTR_LEN(out) - ctx->avail_out;
+ ((php_zlib_context *) ctx)->status = status; /* Save status for exposing to userspace */
+
switch (status) {
case Z_OK:
if (ctx->avail_out == 0) {
@@ -965,7 +972,6 @@ PHP_FUNCTION(inflate_add)
goto complete;
}
case Z_STREAM_END:
- inflateReset(ctx);
goto complete;
case Z_BUF_ERROR:
if (flush_type == Z_FINISH && ctx->avail_out == 0) {
@@ -1014,6 +1020,48 @@ PHP_FUNCTION(inflate_add)
}
/* }}} */
+/* {{{ proto bool inflate_get_status(resource context)
+ Get decompression status, usually returns either ZLIB_OK or ZLIB_STREAM_END. */
+PHP_FUNCTION(inflate_get_status)
+{
+ zval *res;
+ z_stream *ctx;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res))
+ {
+ RETURN_NULL();
+ }
+
+ if (!(ctx = zend_fetch_resource_ex(res, NULL, le_inflate))) {
+ php_error_docref(NULL, E_WARNING, "Invalid zlib.inflate resource");
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(((php_zlib_context *) ctx)->status);
+}
+/* }}} */
+
+/* {{{ proto bool inflate_get_read_len(resource context)
+ Get number of bytes read so far. */
+PHP_FUNCTION(inflate_get_read_len)
+{
+ zval *res;
+ z_stream *ctx;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res))
+ {
+ RETURN_NULL();
+ }
+
+ if (!(ctx = zend_fetch_resource_ex(res, NULL, le_inflate))) {
+ php_error_docref(NULL, E_WARNING, "Invalid zlib.inflate resource");
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(ctx->total_in);
+}
+/* }}} */
+
/* {{{ proto resource deflate_init(int encoding[, array options])
Initialize an incremental deflate context using the specified encoding */
PHP_FUNCTION(deflate_init)
@@ -1325,6 +1373,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_inflate_add, 0, 0, 2)
ZEND_ARG_INFO(0, flush_behavior)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_inflate_get_status, 0, 0, 1)
+ ZEND_ARG_INFO(0, resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_inflate_get_read_len, 0, 0, 1)
+ ZEND_ARG_INFO(0, resource)
+ZEND_END_ARG_INFO()
+
/* }}} */
/* {{{ php_zlib_functions[] */
@@ -1357,6 +1413,8 @@ static const zend_function_entry php_zlib_functions[] = {
PHP_FE(deflate_add, arginfo_deflate_add)
PHP_FE(inflate_init, arginfo_inflate_init)
PHP_FE(inflate_add, arginfo_inflate_add)
+ PHP_FE(inflate_get_status, arginfo_inflate_get_status)
+ PHP_FE(inflate_get_read_len, arginfo_inflate_get_read_len)
PHP_FE(ob_gzhandler, arginfo_ob_gzhandler)
PHP_FE_END
};
@@ -1472,6 +1530,16 @@ static PHP_MINIT_FUNCTION(zlib)
REGISTER_STRING_CONSTANT("ZLIB_VERSION", ZLIB_VERSION, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("ZLIB_VERNUM", ZLIB_VERNUM, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_OK", Z_OK, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_STREAM_END", Z_STREAM_END, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_NEED_DICT", Z_NEED_DICT, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_ERRNO", Z_ERRNO, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_STREAM_ERROR", Z_STREAM_ERROR, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_DATA_ERROR", Z_DATA_ERROR, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_MEM_ERROR", Z_MEM_ERROR, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_BUF_ERROR", Z_BUF_ERROR, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_VERSION_ERROR", Z_VERSION_ERROR, CONST_CS|CONST_PERSISTENT);
+
REGISTER_INI_ENTRIES();
return SUCCESS;
}