Annotation of embedaddon/php/ext/bz2/bz2_filter.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Sara Golemon (pollita@php.net) |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: bz2_filter.c 321634 2012-01-01 13:15:04Z felipe $ */
! 20:
! 21: #ifdef HAVE_CONFIG_H
! 22: #include "config.h"
! 23: #endif
! 24:
! 25: #include "php.h"
! 26: #include "php_bz2.h"
! 27:
! 28: /* {{{ data structure */
! 29:
! 30: enum strm_status {
! 31: PHP_BZ2_UNITIALIZED,
! 32: PHP_BZ2_RUNNING,
! 33: PHP_BZ2_FINISHED
! 34: };
! 35:
! 36: typedef struct _php_bz2_filter_data {
! 37: int persistent;
! 38: bz_stream strm;
! 39: char *inbuf;
! 40: size_t inbuf_len;
! 41: char *outbuf;
! 42: size_t outbuf_len;
! 43:
! 44: /* Decompress options */
! 45: enum strm_status status;
! 46: unsigned int small_footprint : 1;
! 47: unsigned int expect_concatenated : 1;
! 48: } php_bz2_filter_data;
! 49:
! 50: /* }}} */
! 51:
! 52: /* {{{ Memory management wrappers */
! 53:
! 54: static void *php_bz2_alloc(void *opaque, int items, int size)
! 55: {
! 56: return (void *)safe_pemalloc(items, size, 0, ((php_bz2_filter_data*)opaque)->persistent);
! 57: }
! 58:
! 59: static void php_bz2_free(void *opaque, void *address)
! 60: {
! 61: pefree((void *)address, ((php_bz2_filter_data*)opaque)->persistent);
! 62: }
! 63: /* }}} */
! 64:
! 65: /* {{{ bzip2.decompress filter implementation */
! 66:
! 67: static php_stream_filter_status_t php_bz2_decompress_filter(
! 68: php_stream *stream,
! 69: php_stream_filter *thisfilter,
! 70: php_stream_bucket_brigade *buckets_in,
! 71: php_stream_bucket_brigade *buckets_out,
! 72: size_t *bytes_consumed,
! 73: int flags
! 74: TSRMLS_DC)
! 75: {
! 76: php_bz2_filter_data *data;
! 77: php_stream_bucket *bucket;
! 78: size_t consumed = 0;
! 79: int status;
! 80: php_stream_filter_status_t exit_status = PSFS_FEED_ME;
! 81: bz_stream *streamp;
! 82:
! 83: if (!thisfilter || !thisfilter->abstract) {
! 84: /* Should never happen */
! 85: return PSFS_ERR_FATAL;
! 86: }
! 87:
! 88: data = (php_bz2_filter_data *)(thisfilter->abstract);
! 89: streamp = &(data->strm);
! 90:
! 91: while (buckets_in->head) {
! 92: size_t bin = 0, desired;
! 93:
! 94: bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
! 95: while (bin < bucket->buflen) {
! 96: if (data->status == PHP_BZ2_UNITIALIZED) {
! 97: status = BZ2_bzDecompressInit(streamp, 0, data->small_footprint);
! 98:
! 99: if (BZ_OK != status) {
! 100: return PSFS_ERR_FATAL;
! 101: }
! 102:
! 103: data->status = PHP_BZ2_RUNNING;
! 104: }
! 105:
! 106: if (data->status != PHP_BZ2_RUNNING) {
! 107: consumed += bucket->buflen;
! 108: break;
! 109: }
! 110:
! 111: desired = bucket->buflen - bin;
! 112: if (desired > data->inbuf_len) {
! 113: desired = data->inbuf_len;
! 114: }
! 115: memcpy(data->strm.next_in, bucket->buf + bin, desired);
! 116: data->strm.avail_in = desired;
! 117:
! 118: status = BZ2_bzDecompress(&(data->strm));
! 119:
! 120: if (status == BZ_STREAM_END) {
! 121: BZ2_bzDecompressEnd(&(data->strm));
! 122: if (data->expect_concatenated) {
! 123: data->status = PHP_BZ2_UNITIALIZED;
! 124: } else {
! 125: data->status = PHP_BZ2_FINISHED;
! 126: }
! 127: } else if (status != BZ_OK) {
! 128: /* Something bad happened */
! 129: php_stream_bucket_delref(bucket TSRMLS_CC);
! 130: return PSFS_ERR_FATAL;
! 131: }
! 132: desired -= data->strm.avail_in; /* desired becomes what we consumed this round through */
! 133: data->strm.next_in = data->inbuf;
! 134: data->strm.avail_in = 0;
! 135: consumed += desired;
! 136: bin += desired;
! 137:
! 138: if (data->strm.avail_out < data->outbuf_len) {
! 139: php_stream_bucket *out_bucket;
! 140: size_t bucketlen = data->outbuf_len - data->strm.avail_out;
! 141: out_bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
! 142: php_stream_bucket_append(buckets_out, out_bucket TSRMLS_CC);
! 143: data->strm.avail_out = data->outbuf_len;
! 144: data->strm.next_out = data->outbuf;
! 145: exit_status = PSFS_PASS_ON;
! 146: } else if (status == BZ_STREAM_END && data->strm.avail_out >= data->outbuf_len) {
! 147: /* no more data to decompress, and nothing was spat out */
! 148: php_stream_bucket_delref(bucket TSRMLS_CC);
! 149: return PSFS_PASS_ON;
! 150: }
! 151: }
! 152:
! 153: php_stream_bucket_delref(bucket TSRMLS_CC);
! 154: }
! 155:
! 156: if ((data->status == PHP_BZ2_RUNNING) && (flags & PSFS_FLAG_FLUSH_CLOSE)) {
! 157: /* Spit it out! */
! 158: status = BZ_OK;
! 159: while (status == BZ_OK) {
! 160: status = BZ2_bzDecompress(&(data->strm));
! 161: if (data->strm.avail_out < data->outbuf_len) {
! 162: size_t bucketlen = data->outbuf_len - data->strm.avail_out;
! 163:
! 164: bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
! 165: php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
! 166: data->strm.avail_out = data->outbuf_len;
! 167: data->strm.next_out = data->outbuf;
! 168: exit_status = PSFS_PASS_ON;
! 169: } else if (status == BZ_OK) {
! 170: break;
! 171: }
! 172: }
! 173: }
! 174:
! 175: if (bytes_consumed) {
! 176: *bytes_consumed = consumed;
! 177: }
! 178:
! 179: return exit_status;
! 180: }
! 181:
! 182: static void php_bz2_decompress_dtor(php_stream_filter *thisfilter TSRMLS_DC)
! 183: {
! 184: if (thisfilter && thisfilter->abstract) {
! 185: php_bz2_filter_data *data = thisfilter->abstract;
! 186: if (data->status == PHP_BZ2_RUNNING) {
! 187: BZ2_bzDecompressEnd(&(data->strm));
! 188: }
! 189: pefree(data->inbuf, data->persistent);
! 190: pefree(data->outbuf, data->persistent);
! 191: pefree(data, data->persistent);
! 192: }
! 193: }
! 194:
! 195: static php_stream_filter_ops php_bz2_decompress_ops = {
! 196: php_bz2_decompress_filter,
! 197: php_bz2_decompress_dtor,
! 198: "bzip2.decompress"
! 199: };
! 200: /* }}} */
! 201:
! 202: /* {{{ bzip2.compress filter implementation */
! 203:
! 204: static php_stream_filter_status_t php_bz2_compress_filter(
! 205: php_stream *stream,
! 206: php_stream_filter *thisfilter,
! 207: php_stream_bucket_brigade *buckets_in,
! 208: php_stream_bucket_brigade *buckets_out,
! 209: size_t *bytes_consumed,
! 210: int flags
! 211: TSRMLS_DC)
! 212: {
! 213: php_bz2_filter_data *data;
! 214: php_stream_bucket *bucket;
! 215: size_t consumed = 0;
! 216: int status;
! 217: php_stream_filter_status_t exit_status = PSFS_FEED_ME;
! 218: bz_stream *streamp;
! 219:
! 220: if (!thisfilter || !thisfilter->abstract) {
! 221: /* Should never happen */
! 222: return PSFS_ERR_FATAL;
! 223: }
! 224:
! 225: data = (php_bz2_filter_data *)(thisfilter->abstract);
! 226: streamp = &(data->strm);
! 227:
! 228: while (buckets_in->head) {
! 229: size_t bin = 0, desired;
! 230:
! 231: bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
! 232:
! 233: while (bin < bucket->buflen) {
! 234: desired = bucket->buflen - bin;
! 235: if (desired > data->inbuf_len) {
! 236: desired = data->inbuf_len;
! 237: }
! 238: memcpy(data->strm.next_in, bucket->buf + bin, desired);
! 239: data->strm.avail_in = desired;
! 240:
! 241: status = BZ2_bzCompress(&(data->strm), flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : (flags & PSFS_FLAG_FLUSH_INC ? BZ_FLUSH : BZ_RUN));
! 242: if (status != BZ_RUN_OK && status != BZ_FLUSH_OK && status != BZ_FINISH_OK) {
! 243: /* Something bad happened */
! 244: php_stream_bucket_delref(bucket TSRMLS_CC);
! 245: return PSFS_ERR_FATAL;
! 246: }
! 247: desired -= data->strm.avail_in; /* desired becomes what we consumed this round through */
! 248: data->strm.next_in = data->inbuf;
! 249: data->strm.avail_in = 0;
! 250: consumed += desired;
! 251: bin += desired;
! 252:
! 253: if (data->strm.avail_out < data->outbuf_len) {
! 254: php_stream_bucket *out_bucket;
! 255: size_t bucketlen = data->outbuf_len - data->strm.avail_out;
! 256:
! 257: out_bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
! 258: php_stream_bucket_append(buckets_out, out_bucket TSRMLS_CC);
! 259: data->strm.avail_out = data->outbuf_len;
! 260: data->strm.next_out = data->outbuf;
! 261: exit_status = PSFS_PASS_ON;
! 262: }
! 263: }
! 264: php_stream_bucket_delref(bucket TSRMLS_CC);
! 265: }
! 266:
! 267: if (flags & PSFS_FLAG_FLUSH_CLOSE) {
! 268: /* Spit it out! */
! 269: status = BZ_FINISH_OK;
! 270: while (status == BZ_FINISH_OK) {
! 271: status = BZ2_bzCompress(&(data->strm), BZ_FINISH);
! 272: if (data->strm.avail_out < data->outbuf_len) {
! 273: size_t bucketlen = data->outbuf_len - data->strm.avail_out;
! 274:
! 275: bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
! 276: php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
! 277: data->strm.avail_out = data->outbuf_len;
! 278: data->strm.next_out = data->outbuf;
! 279: exit_status = PSFS_PASS_ON;
! 280: }
! 281: }
! 282: }
! 283:
! 284: if (bytes_consumed) {
! 285: *bytes_consumed = consumed;
! 286: }
! 287: return exit_status;
! 288: }
! 289:
! 290: static void php_bz2_compress_dtor(php_stream_filter *thisfilter TSRMLS_DC)
! 291: {
! 292: if (thisfilter && thisfilter->abstract) {
! 293: php_bz2_filter_data *data = thisfilter->abstract;
! 294: BZ2_bzCompressEnd(&(data->strm));
! 295: pefree(data->inbuf, data->persistent);
! 296: pefree(data->outbuf, data->persistent);
! 297: pefree(data, data->persistent);
! 298: }
! 299: }
! 300:
! 301: static php_stream_filter_ops php_bz2_compress_ops = {
! 302: php_bz2_compress_filter,
! 303: php_bz2_compress_dtor,
! 304: "bzip2.compress"
! 305: };
! 306:
! 307: /* }}} */
! 308:
! 309: /* {{{ bzip2.* common factory */
! 310:
! 311: static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
! 312: {
! 313: php_stream_filter_ops *fops = NULL;
! 314: php_bz2_filter_data *data;
! 315: int status = BZ_OK;
! 316:
! 317: /* Create this filter */
! 318: data = pecalloc(1, sizeof(php_bz2_filter_data), persistent);
! 319: if (!data) {
! 320: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zu bytes", sizeof(php_bz2_filter_data));
! 321: return NULL;
! 322: }
! 323:
! 324: /* Circular reference */
! 325: data->strm.opaque = (void *) data;
! 326:
! 327: data->strm.bzalloc = php_bz2_alloc;
! 328: data->strm.bzfree = php_bz2_free;
! 329: data->persistent = persistent;
! 330: data->strm.avail_out = data->outbuf_len = data->inbuf_len = 2048;
! 331: data->strm.next_in = data->inbuf = (char *) pemalloc(data->inbuf_len, persistent);
! 332: if (!data->inbuf) {
! 333: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zu bytes", data->inbuf_len);
! 334: pefree(data, persistent);
! 335: return NULL;
! 336: }
! 337: data->strm.avail_in = 0;
! 338: data->strm.next_out = data->outbuf = (char *) pemalloc(data->outbuf_len, persistent);
! 339: if (!data->outbuf) {
! 340: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zu bytes", data->outbuf_len);
! 341: pefree(data->inbuf, persistent);
! 342: pefree(data, persistent);
! 343: return NULL;
! 344: }
! 345:
! 346: if (strcasecmp(filtername, "bzip2.decompress") == 0) {
! 347: data->small_footprint = 0;
! 348: data->expect_concatenated = 0;
! 349:
! 350: if (filterparams) {
! 351: zval **tmpzval = NULL;
! 352:
! 353: if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {
! 354:
! 355: if (SUCCESS == zend_hash_find(HASH_OF(filterparams), "concatenated", sizeof("concatenated"), (void **) &tmpzval) ) {
! 356: zval tmp, *tmp2;
! 357:
! 358: tmp = **tmpzval;
! 359: zval_copy_ctor(&tmp);
! 360: tmp2 = &tmp;
! 361: convert_to_boolean_ex(&tmp2);
! 362: data->expect_concatenated = Z_LVAL(tmp);
! 363: tmpzval = NULL;
! 364: }
! 365:
! 366: zend_hash_find(HASH_OF(filterparams), "small", sizeof("small"), (void **) &tmpzval);
! 367: } else {
! 368: tmpzval = &filterparams;
! 369: }
! 370:
! 371: if (tmpzval) {
! 372: zval tmp, *tmp2;
! 373:
! 374: tmp = **tmpzval;
! 375: zval_copy_ctor(&tmp);
! 376: tmp2 = &tmp;
! 377: convert_to_boolean_ex(&tmp2);
! 378: data->small_footprint = Z_LVAL(tmp);
! 379: }
! 380: }
! 381:
! 382: data->status = PHP_BZ2_UNITIALIZED;
! 383: fops = &php_bz2_decompress_ops;
! 384: } else if (strcasecmp(filtername, "bzip2.compress") == 0) {
! 385: int blockSize100k = PHP_BZ2_FILTER_DEFAULT_BLOCKSIZE;
! 386: int workFactor = PHP_BZ2_FILTER_DEFAULT_WORKFACTOR;
! 387:
! 388: if (filterparams) {
! 389: zval **tmpzval;
! 390:
! 391: if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {
! 392: if (zend_hash_find(HASH_OF(filterparams), "blocks", sizeof("blocks"), (void**) &tmpzval) == SUCCESS) {
! 393: /* How much memory to allocate (1 - 9) x 100kb */
! 394: zval tmp;
! 395:
! 396: tmp = **tmpzval;
! 397: zval_copy_ctor(&tmp);
! 398: convert_to_long(&tmp);
! 399: if (Z_LVAL(tmp) < 1 || Z_LVAL(tmp) > 9) {
! 400: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter given for number of blocks to allocate. (%ld)", Z_LVAL_PP(tmpzval));
! 401: } else {
! 402: blockSize100k = Z_LVAL(tmp);
! 403: }
! 404: }
! 405:
! 406: if (zend_hash_find(HASH_OF(filterparams), "work", sizeof("work"), (void**) &tmpzval) == SUCCESS) {
! 407: /* Work Factor (0 - 250) */
! 408: zval tmp;
! 409:
! 410: tmp = **tmpzval;
! 411: zval_copy_ctor(&tmp);
! 412: convert_to_long(&tmp);
! 413:
! 414: if (Z_LVAL(tmp) < 0 || Z_LVAL(tmp) > 250) {
! 415: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter given for work factor. (%ld)", Z_LVAL(tmp));
! 416: } else {
! 417: workFactor = Z_LVAL(tmp);
! 418: }
! 419: }
! 420: }
! 421: }
! 422:
! 423: status = BZ2_bzCompressInit(&(data->strm), blockSize100k, 0, workFactor);
! 424: fops = &php_bz2_compress_ops;
! 425: } else {
! 426: status = BZ_DATA_ERROR;
! 427: }
! 428:
! 429: if (status != BZ_OK) {
! 430: /* Unspecified (probably strm) error, let stream-filter error do its own whining */
! 431: pefree(data->strm.next_in, persistent);
! 432: pefree(data->strm.next_out, persistent);
! 433: pefree(data, persistent);
! 434: return NULL;
! 435: }
! 436:
! 437: return php_stream_filter_alloc(fops, data, persistent);
! 438: }
! 439:
! 440: php_stream_filter_factory php_bz2_filter_factory = {
! 441: php_bz2_filter_create
! 442: };
! 443: /* }}} */
! 444:
! 445: /*
! 446: * Local variables:
! 447: * tab-width: 4
! 448: * c-basic-offset: 4
! 449: * End:
! 450: * vim600: sw=4 ts=4 fdm=marker
! 451: * vim<600: sw=4 ts=4
! 452: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>