--- php5.2-200809191430\ext\bz2\bz2_filter.c 2008-01-13 00:35:00.000000000 +0100
+++ php5.2-200809181030\ext\bz2\bz2_filter.c 2008-09-19 18:41:52.000000000 +0200
@@ -27,6 +27,13 @@
/* {{{ data structure */
+enum strm_status {
+ Uninitialised,
+ Running,
+ Finished
+};
+
+
typedef struct _php_bz2_filter_data {
int persistent;
bz_stream strm;
@@ -34,6 +41,11 @@
size_t inbuf_len;
char *outbuf;
size_t outbuf_len;
+
+ /* Decompress options */
+ enum strm_status status;
+ unsigned int small_footprint : 1;
+ int expect_concatenated : 1;
} php_bz2_filter_data;
/* }}} */
@@ -65,7 +77,7 @@
php_bz2_filter_data *data;
php_stream_bucket *bucket;
size_t consumed = 0;
- int status;
+ int bzlib_status;
php_stream_filter_status_t exit_status = PSFS_FEED_ME;
bz_stream *streamp;
@@ -82,6 +94,16 @@
bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
while (bin < bucket->buflen) {
+ if (data->status == Uninitialised) {
+ bzlib_status = BZ2_bzDecompressInit(streamp, 0, data->small_footprint);
+
+ if (BZ_OK != bzlib_status)
+ return PSFS_ERR_FATAL;
+
+ data->status = Running;
+ }
+
+ if (data->status == Running) {
desired = bucket->buflen - bin;
if (desired > data->inbuf_len) {
desired = data->inbuf_len;
@@ -89,9 +111,19 @@
memcpy(data->strm.next_in, bucket->buf + bin, desired);
data->strm.avail_in = desired;
- status = BZ2_bzDecompress(&(data->strm));
- if (status != BZ_OK && status != BZ_STREAM_END) {
+ bzlib_status = BZ2_bzDecompress(&(data->strm));
+
+ if (bzlib_status == BZ_STREAM_END) {
+ BZ2_bzDecompressEnd(&(data->strm));
+ if (data->expect_concatenated)
+ data->status = Uninitialised;
+ else
+ data->status = Finished;
+ } else
+ if (bzlib_status != BZ_OK) {
/* Something bad happened */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bzip decompress error %d.", bzlib_status);
+
php_stream_bucket_delref(bucket TSRMLS_CC);
return PSFS_ERR_FATAL;
}
@@ -109,20 +141,25 @@
data->strm.avail_out = data->outbuf_len;
data->strm.next_out = data->outbuf;
exit_status = PSFS_PASS_ON;
- } else if (status == BZ_STREAM_END && data->strm.avail_out >= data->outbuf_len) {
+ } else if (bzlib_status == BZ_STREAM_END && data->strm.avail_out >= data->outbuf_len) {
/* no more data to decompress, and nothing was spat out */
php_stream_bucket_delref(bucket TSRMLS_CC);
return PSFS_PASS_ON;
}
+ } else {
+ consumed += bucket->buflen;
+ break;
}
+ }
+
php_stream_bucket_delref(bucket TSRMLS_CC);
}
- if (flags & PSFS_FLAG_FLUSH_CLOSE) {
+ if ((data->status == Running) && (flags & PSFS_FLAG_FLUSH_CLOSE)) {
/* Spit it out! */
- status = BZ_OK;
- while (status == BZ_OK) {
- status = BZ2_bzDecompress(&(data->strm));
+ bzlib_status = BZ_OK;
+ while (bzlib_status == BZ_OK) {
+ bzlib_status = BZ2_bzDecompress(&(data->strm));
if (data->strm.avail_out < data->outbuf_len) {
size_t bucketlen = data->outbuf_len - data->strm.avail_out;
@@ -131,7 +168,7 @@
data->strm.avail_out = data->outbuf_len;
data->strm.next_out = data->outbuf;
exit_status = PSFS_PASS_ON;
- } else if (status == BZ_OK) {
+ } else if (bzlib_status == BZ_OK) {
break;
}
}
@@ -148,7 +185,7 @@
{
if (thisfilter && thisfilter->abstract) {
php_bz2_filter_data *data = thisfilter->abstract;
- BZ2_bzDecompressEnd(&(data->strm));
+ if (data->status == Running) BZ2_bzDecompressEnd(&(data->strm));
pefree(data->inbuf, data->persistent);
pefree(data->outbuf, data->persistent);
pefree(data, data->persistent);
@@ -275,7 +312,7 @@
{
php_stream_filter_ops *fops = NULL;
php_bz2_filter_data *data;
- int status;
+ int status = BZ_OK;
/* Create this filter */
data = pecalloc(1, sizeof(php_bz2_filter_data), persistent);
@@ -307,12 +344,22 @@
}
if (strcasecmp(filtername, "bzip2.decompress") == 0) {
- int smallFootprint = 0;
+ data->small_footprint = 0;
+ data->expect_concatenated = 0;
if (filterparams) {
zval **tmpzval = NULL;
if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {
+
+ if (SUCCESS == zend_hash_find(HASH_OF(filterparams), "concatenated", sizeof("concatenated"), (void **) &tmpzval) ) {
+ SEPARATE_ZVAL(tmpzval);
+ convert_to_boolean_ex(tmpzval);
+ data->expect_concatenated = Z_LVAL_PP(tmpzval);
+ zval_ptr_dtor(tmpzval);
+ tmpzval = NULL;
+ }
+
zend_hash_find(HASH_OF(filterparams), "small", sizeof("small"), (void **) &tmpzval);
} else {
tmpzval = &filterparams;
@@ -321,12 +368,12 @@
if (tmpzval) {
SEPARATE_ZVAL(tmpzval);
convert_to_boolean_ex(tmpzval);
- smallFootprint = Z_LVAL_PP(tmpzval);
+ data->small_footprint = Z_LVAL_PP(tmpzval);
zval_ptr_dtor(tmpzval);
}
}
- status = BZ2_bzDecompressInit(&(data->strm), 0, smallFootprint);
+ data->status = Uninitialised;
fops = &php_bz2_decompress_ops;
} else if (strcasecmp(filtername, "bzip2.compress") == 0) {
int blockSize100k = PHP_BZ2_FILTER_DEFAULT_BLOCKSIZE;