Return to bz2.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / bz2 |
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: | Author: Sterling Hughes <sterling@php.net> | ! 16: +----------------------------------------------------------------------+ ! 17: */ ! 18: ! 19: /* $Id: bz2.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: #if HAVE_BZ2 ! 29: ! 30: /* PHP Includes */ ! 31: #include "ext/standard/file.h" ! 32: #include "ext/standard/info.h" ! 33: #include "ext/standard/php_string.h" ! 34: ! 35: /* for fileno() */ ! 36: #include <stdio.h> ! 37: ! 38: /* Internal error constants */ ! 39: #define PHP_BZ_ERRNO 0 ! 40: #define PHP_BZ_ERRSTR 1 ! 41: #define PHP_BZ_ERRBOTH 2 ! 42: ! 43: static PHP_MINIT_FUNCTION(bz2); ! 44: static PHP_MSHUTDOWN_FUNCTION(bz2); ! 45: static PHP_MINFO_FUNCTION(bz2); ! 46: static PHP_FUNCTION(bzopen); ! 47: static PHP_FUNCTION(bzread); ! 48: static PHP_FUNCTION(bzerrno); ! 49: static PHP_FUNCTION(bzerrstr); ! 50: static PHP_FUNCTION(bzerror); ! 51: static PHP_FUNCTION(bzcompress); ! 52: static PHP_FUNCTION(bzdecompress); ! 53: ! 54: /* {{{ arginfo */ ! 55: ZEND_BEGIN_ARG_INFO_EX(arginfo_bzread, 0, 0, 1) ! 56: ZEND_ARG_INFO(0, bz) ! 57: ZEND_ARG_INFO(0, length) ! 58: ZEND_END_ARG_INFO() ! 59: ! 60: ZEND_BEGIN_ARG_INFO(arginfo_bzopen, 0) ! 61: ZEND_ARG_INFO(0, file) ! 62: ZEND_ARG_INFO(0, mode) ! 63: ZEND_END_ARG_INFO() ! 64: ! 65: ZEND_BEGIN_ARG_INFO(arginfo_bzerrno, 0) ! 66: ZEND_ARG_INFO(0, bz) ! 67: ZEND_END_ARG_INFO() ! 68: ! 69: ZEND_BEGIN_ARG_INFO(arginfo_bzerrstr, 0) ! 70: ZEND_ARG_INFO(0, bz) ! 71: ZEND_END_ARG_INFO() ! 72: ! 73: ZEND_BEGIN_ARG_INFO(arginfo_bzerror, 0) ! 74: ZEND_ARG_INFO(0, bz) ! 75: ZEND_END_ARG_INFO() ! 76: ! 77: ZEND_BEGIN_ARG_INFO_EX(arginfo_bzcompress, 0, 0, 2) ! 78: ZEND_ARG_INFO(0, source) ! 79: ZEND_ARG_INFO(0, blocksize) ! 80: ZEND_ARG_INFO(0, workfactor) ! 81: ZEND_END_ARG_INFO() ! 82: ! 83: ZEND_BEGIN_ARG_INFO_EX(arginfo_bzdecompress, 0, 0, 1) ! 84: ZEND_ARG_INFO(0, source) ! 85: ZEND_ARG_INFO(0, small) ! 86: ZEND_END_ARG_INFO() ! 87: ! 88: ZEND_BEGIN_ARG_INFO_EX(arginfo_bzwrite, 0, 0, 2) ! 89: ZEND_ARG_INFO(0, fp) ! 90: ZEND_ARG_INFO(0, str) ! 91: ZEND_ARG_INFO(0, length) ! 92: ZEND_END_ARG_INFO() ! 93: ! 94: ZEND_BEGIN_ARG_INFO(arginfo_bzflush, 0) ! 95: ZEND_ARG_INFO(0, fp) ! 96: ZEND_END_ARG_INFO() ! 97: /* }}} */ ! 98: ! 99: static const zend_function_entry bz2_functions[] = { ! 100: PHP_FE(bzopen, arginfo_bzopen) ! 101: PHP_FE(bzread, arginfo_bzread) ! 102: PHP_FALIAS(bzwrite, fwrite, arginfo_bzwrite) ! 103: PHP_FALIAS(bzflush, fflush, arginfo_bzflush) ! 104: PHP_FALIAS(bzclose, fclose, arginfo_bzflush) ! 105: PHP_FE(bzerrno, arginfo_bzerrno) ! 106: PHP_FE(bzerrstr, arginfo_bzerrstr) ! 107: PHP_FE(bzerror, arginfo_bzerror) ! 108: PHP_FE(bzcompress, arginfo_bzcompress) ! 109: PHP_FE(bzdecompress, arginfo_bzdecompress) ! 110: PHP_FE_END ! 111: }; ! 112: ! 113: zend_module_entry bz2_module_entry = { ! 114: STANDARD_MODULE_HEADER, ! 115: "bz2", ! 116: bz2_functions, ! 117: PHP_MINIT(bz2), ! 118: PHP_MSHUTDOWN(bz2), ! 119: NULL, ! 120: NULL, ! 121: PHP_MINFO(bz2), ! 122: NO_VERSION_YET, ! 123: STANDARD_MODULE_PROPERTIES ! 124: }; ! 125: ! 126: #ifdef COMPILE_DL_BZ2 ! 127: ZEND_GET_MODULE(bz2) ! 128: #endif ! 129: ! 130: struct php_bz2_stream_data_t { ! 131: BZFILE *bz_file; ! 132: php_stream *stream; ! 133: }; ! 134: ! 135: /* {{{ BZip2 stream implementation */ ! 136: ! 137: static size_t php_bz2iop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) ! 138: { ! 139: struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract; ! 140: size_t ret; ! 141: ! 142: ret = BZ2_bzread(self->bz_file, buf, count); ! 143: ! 144: if (ret == 0) { ! 145: stream->eof = 1; ! 146: } ! 147: ! 148: return ret; ! 149: } ! 150: ! 151: static size_t php_bz2iop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) ! 152: { ! 153: struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract; ! 154: ! 155: return BZ2_bzwrite(self->bz_file, (char*)buf, count); ! 156: } ! 157: ! 158: static int php_bz2iop_close(php_stream *stream, int close_handle TSRMLS_DC) ! 159: { ! 160: struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract; ! 161: int ret = EOF; ! 162: ! 163: if (close_handle) { ! 164: BZ2_bzclose(self->bz_file); ! 165: } ! 166: ! 167: if (self->stream) { ! 168: php_stream_free(self->stream, PHP_STREAM_FREE_CLOSE | (close_handle == 0 ? PHP_STREAM_FREE_PRESERVE_HANDLE : 0)); ! 169: } ! 170: ! 171: efree(self); ! 172: ! 173: return ret; ! 174: } ! 175: ! 176: static int php_bz2iop_flush(php_stream *stream TSRMLS_DC) ! 177: { ! 178: struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract; ! 179: return BZ2_bzflush(self->bz_file); ! 180: } ! 181: /* }}} */ ! 182: ! 183: php_stream_ops php_stream_bz2io_ops = { ! 184: php_bz2iop_write, php_bz2iop_read, ! 185: php_bz2iop_close, php_bz2iop_flush, ! 186: "BZip2", ! 187: NULL, /* seek */ ! 188: NULL, /* cast */ ! 189: NULL, /* stat */ ! 190: NULL /* set_option */ ! 191: }; ! 192: ! 193: /* {{{ Bzip2 stream openers */ ! 194: PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, ! 195: char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC) ! 196: { ! 197: struct php_bz2_stream_data_t *self; ! 198: ! 199: self = emalloc(sizeof(*self)); ! 200: ! 201: self->stream = innerstream; ! 202: self->bz_file = bz; ! 203: ! 204: return php_stream_alloc_rel(&php_stream_bz2io_ops, self, 0, mode); ! 205: } ! 206: ! 207: PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, ! 208: char *path, ! 209: char *mode, ! 210: int options, ! 211: char **opened_path, ! 212: php_stream_context *context STREAMS_DC TSRMLS_DC) ! 213: { ! 214: php_stream *retstream = NULL, *stream = NULL; ! 215: char *path_copy = NULL; ! 216: BZFILE *bz_file = NULL; ! 217: ! 218: if (strncasecmp("compress.bzip2://", path, 17) == 0) { ! 219: path += 17; ! 220: } ! 221: if (mode[0] == '\0' || (mode[0] != 'w' && mode[0] != 'r' && mode[1] != '\0')) { ! 222: return NULL; ! 223: } ! 224: ! 225: #ifdef VIRTUAL_DIR ! 226: virtual_filepath_ex(path, &path_copy, NULL TSRMLS_CC); ! 227: #else ! 228: path_copy = path; ! 229: #endif ! 230: ! 231: if ((PG(safe_mode) && (!php_checkuid(path_copy, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(path_copy TSRMLS_CC)) { ! 232: return NULL; ! 233: } ! 234: ! 235: /* try and open it directly first */ ! 236: bz_file = BZ2_bzopen(path_copy, mode); ! 237: ! 238: if (opened_path && bz_file) { ! 239: *opened_path = estrdup(path_copy); ! 240: } ! 241: path_copy = NULL; ! 242: ! 243: if (bz_file == NULL) { ! 244: /* that didn't work, so try and get something from the network/wrapper */ ! 245: stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST | ENFORCE_SAFE_MODE, opened_path); ! 246: ! 247: if (stream) { ! 248: int fd; ! 249: if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) { ! 250: bz_file = BZ2_bzdopen(fd, mode); ! 251: } ! 252: } ! 253: ! 254: /* remove the file created by php_stream_open_wrapper(), it is not needed since BZ2 functions ! 255: * failed. ! 256: */ ! 257: if (opened_path && !bz_file && mode[0] == 'w') { ! 258: VCWD_UNLINK(*opened_path); ! 259: } ! 260: } ! 261: ! 262: if (bz_file) { ! 263: retstream = _php_stream_bz2open_from_BZFILE(bz_file, mode, stream STREAMS_REL_CC TSRMLS_CC); ! 264: if (retstream) { ! 265: return retstream; ! 266: } ! 267: ! 268: BZ2_bzclose(bz_file); ! 269: } ! 270: ! 271: if (stream) { ! 272: php_stream_close(stream); ! 273: } ! 274: ! 275: return NULL; ! 276: } ! 277: ! 278: /* }}} */ ! 279: ! 280: static php_stream_wrapper_ops bzip2_stream_wops = { ! 281: _php_stream_bz2open, ! 282: NULL, /* close */ ! 283: NULL, /* fstat */ ! 284: NULL, /* stat */ ! 285: NULL, /* opendir */ ! 286: "BZip2", ! 287: NULL, /* unlink */ ! 288: NULL, /* rename */ ! 289: NULL, /* mkdir */ ! 290: NULL /* rmdir */ ! 291: }; ! 292: ! 293: static php_stream_wrapper php_stream_bzip2_wrapper = { ! 294: &bzip2_stream_wops, ! 295: NULL, ! 296: 0 /* is_url */ ! 297: }; ! 298: ! 299: static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int); ! 300: ! 301: static PHP_MINIT_FUNCTION(bz2) ! 302: { ! 303: php_register_url_stream_wrapper("compress.bzip2", &php_stream_bzip2_wrapper TSRMLS_CC); ! 304: php_stream_filter_register_factory("bzip2.*", &php_bz2_filter_factory TSRMLS_CC); ! 305: return SUCCESS; ! 306: } ! 307: ! 308: static PHP_MSHUTDOWN_FUNCTION(bz2) ! 309: { ! 310: php_unregister_url_stream_wrapper("compress.bzip2" TSRMLS_CC); ! 311: php_stream_filter_unregister_factory("bzip2.*" TSRMLS_CC); ! 312: ! 313: return SUCCESS; ! 314: } ! 315: ! 316: static PHP_MINFO_FUNCTION(bz2) ! 317: { ! 318: php_info_print_table_start(); ! 319: php_info_print_table_row(2, "BZip2 Support", "Enabled"); ! 320: php_info_print_table_row(2, "Stream Wrapper support", "compress.bzip2://"); ! 321: php_info_print_table_row(2, "Stream Filter support", "bzip2.decompress, bzip2.compress"); ! 322: php_info_print_table_row(2, "BZip2 Version", (char *) BZ2_bzlibVersion()); ! 323: php_info_print_table_end(); ! 324: } ! 325: ! 326: /* {{{ proto string bzread(resource bz[, int length]) ! 327: Reads up to length bytes from a BZip2 stream, or 1024 bytes if length is not specified */ ! 328: static PHP_FUNCTION(bzread) ! 329: { ! 330: zval *bz; ! 331: long len = 1024; ! 332: php_stream *stream; ! 333: ! 334: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &bz, &len)) { ! 335: RETURN_FALSE; ! 336: } ! 337: ! 338: php_stream_from_zval(stream, &bz); ! 339: ! 340: if ((len + 1) < 1) { ! 341: php_error_docref(NULL TSRMLS_CC, E_WARNING, "length may not be negative"); ! 342: RETURN_FALSE; ! 343: } ! 344: ! 345: Z_STRVAL_P(return_value) = emalloc(len + 1); ! 346: Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len); ! 347: ! 348: if (Z_STRLEN_P(return_value) < 0) { ! 349: efree(Z_STRVAL_P(return_value)); ! 350: php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read valid bz2 data from stream"); ! 351: RETURN_FALSE; ! 352: } ! 353: ! 354: Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0; ! 355: ! 356: if (PG(magic_quotes_runtime)) { ! 357: Z_STRVAL_P(return_value) = php_addslashes( Z_STRVAL_P(return_value), ! 358: Z_STRLEN_P(return_value), ! 359: &Z_STRLEN_P(return_value), 1 TSRMLS_CC); ! 360: } ! 361: ! 362: Z_TYPE_P(return_value) = IS_STRING; ! 363: } ! 364: /* }}} */ ! 365: ! 366: /* {{{ proto resource bzopen(string|int file|fp, string mode) ! 367: Opens a new BZip2 stream */ ! 368: static PHP_FUNCTION(bzopen) ! 369: { ! 370: zval **file; /* The file to open */ ! 371: char *mode; /* The mode to open the stream with */ ! 372: int mode_len; ! 373: ! 374: BZFILE *bz; /* The compressed file stream */ ! 375: php_stream *stream = NULL; ! 376: ! 377: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &file, &mode, &mode_len) == FAILURE) { ! 378: return; ! 379: } ! 380: ! 381: if (mode_len != 1 || (mode[0] != 'r' && mode[0] != 'w')) { ! 382: php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid mode for bzopen(). Only 'w' and 'r' are supported.", mode); ! 383: RETURN_FALSE; ! 384: } ! 385: ! 386: /* If it's not a resource its a string containing the filename to open */ ! 387: if (Z_TYPE_PP(file) == IS_STRING) { ! 388: convert_to_string_ex(file); ! 389: ! 390: if (strlen(Z_STRVAL_PP(file)) != Z_STRLEN_PP(file)) { ! 391: RETURN_FALSE; ! 392: } ! 393: if (Z_STRLEN_PP(file) == 0) { ! 394: php_error_docref(NULL TSRMLS_CC, E_WARNING, "filename cannot be empty"); ! 395: RETURN_FALSE; ! 396: } ! 397: ! 398: stream = php_stream_bz2open(NULL, ! 399: Z_STRVAL_PP(file), ! 400: mode, ! 401: ENFORCE_SAFE_MODE | REPORT_ERRORS, ! 402: NULL); ! 403: } else if (Z_TYPE_PP(file) == IS_RESOURCE) { ! 404: /* If it is a resource, than its a stream resource */ ! 405: int fd; ! 406: int stream_mode_len; ! 407: ! 408: php_stream_from_zval(stream, file); ! 409: stream_mode_len = strlen(stream->mode); ! 410: ! 411: if (stream_mode_len != 1 && !(stream_mode_len == 2 && memchr(stream->mode, 'b', 2))) { ! 412: php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode); ! 413: RETURN_FALSE; ! 414: } else if (stream_mode_len == 1 && stream->mode[0] != 'r' && stream->mode[0] != 'w' && stream->mode[0] != 'a' && stream->mode[0] != 'x') { ! 415: php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode); ! 416: RETURN_FALSE; ! 417: } ! 418: ! 419: switch(mode[0]) { ! 420: case 'r': ! 421: /* only "r" and "rb" are supported */ ! 422: if (stream->mode[0] != mode[0] && !(stream_mode_len == 2 && stream->mode[1] != mode[0])) { ! 423: php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot read from a stream opened in write only mode"); ! 424: RETURN_FALSE; ! 425: } ! 426: break; ! 427: case 'w': ! 428: /* support only "w"(b), "a"(b), "x"(b) */ ! 429: if (stream->mode[0] != mode[0] && !(stream_mode_len == 2 && stream->mode[1] != mode[0]) ! 430: && stream->mode[0] != 'a' && !(stream_mode_len == 2 && stream->mode[1] != 'a') ! 431: && stream->mode[0] != 'x' && !(stream_mode_len == 2 && stream->mode[1] != 'x')) { ! 432: php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write to a stream opened in read only mode"); ! 433: RETURN_FALSE; ! 434: } ! 435: break; ! 436: default: ! 437: /* not reachable */ ! 438: break; ! 439: } ! 440: ! 441: if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void *) &fd, REPORT_ERRORS)) { ! 442: RETURN_FALSE; ! 443: } ! 444: ! 445: bz = BZ2_bzdopen(fd, mode); ! 446: ! 447: stream = php_stream_bz2open_from_BZFILE(bz, mode, stream); ! 448: } else { ! 449: php_error_docref(NULL TSRMLS_CC, E_WARNING, "first parameter has to be string or file-resource"); ! 450: RETURN_FALSE; ! 451: } ! 452: ! 453: if (stream) { ! 454: php_stream_to_zval(stream, return_value); ! 455: } else { ! 456: RETURN_FALSE; ! 457: } ! 458: } ! 459: /* }}} */ ! 460: ! 461: /* {{{ proto int bzerrno(resource bz) ! 462: Returns the error number */ ! 463: static PHP_FUNCTION(bzerrno) ! 464: { ! 465: php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRNO); ! 466: } ! 467: /* }}} */ ! 468: ! 469: /* {{{ proto string bzerrstr(resource bz) ! 470: Returns the error string */ ! 471: static PHP_FUNCTION(bzerrstr) ! 472: { ! 473: php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRSTR); ! 474: } ! 475: /* }}} */ ! 476: ! 477: /* {{{ proto array bzerror(resource bz) ! 478: Returns the error number and error string in an associative array */ ! 479: static PHP_FUNCTION(bzerror) ! 480: { ! 481: php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRBOTH); ! 482: } ! 483: /* }}} */ ! 484: ! 485: /* {{{ proto string bzcompress(string source [, int blocksize100k [, int workfactor]]) ! 486: Compresses a string into BZip2 encoded data */ ! 487: static PHP_FUNCTION(bzcompress) ! 488: { ! 489: char *source; /* Source data to compress */ ! 490: long zblock_size = 0; /* Optional block size to use */ ! 491: long zwork_factor = 0;/* Optional work factor to use */ ! 492: char *dest = NULL; /* Destination to place the compressed data into */ ! 493: int error, /* Error Container */ ! 494: block_size = 4, /* Block size for compression algorithm */ ! 495: work_factor = 0, /* Work factor for compression algorithm */ ! 496: argc; /* Argument count */ ! 497: int source_len; /* Length of the source data */ ! 498: unsigned int dest_len; /* Length of the destination buffer */ ! 499: ! 500: argc = ZEND_NUM_ARGS(); ! 501: ! 502: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &source, &source_len, &zblock_size, &zwork_factor) == FAILURE) { ! 503: return; ! 504: } ! 505: ! 506: /* Assign them to easy to use variables, dest_len is initially the length of the data ! 507: + .01 x length of data + 600 which is the largest size the results of the compression ! 508: could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net ! 509: for pointing this out). */ ! 510: dest_len = (unsigned int) (source_len + (0.01 * source_len) + 600); ! 511: ! 512: /* Allocate the destination buffer */ ! 513: dest = emalloc(dest_len + 1); ! 514: ! 515: /* Handle the optional arguments */ ! 516: if (argc > 1) { ! 517: block_size = zblock_size; ! 518: } ! 519: ! 520: if (argc > 2) { ! 521: work_factor = zwork_factor; ! 522: } ! 523: ! 524: error = BZ2_bzBuffToBuffCompress(dest, &dest_len, source, source_len, block_size, 0, work_factor); ! 525: if (error != BZ_OK) { ! 526: efree(dest); ! 527: RETURN_LONG(error); ! 528: } else { ! 529: /* Copy the buffer, we have perhaps allocate alot more than we need, ! 530: so we erealloc() the buffer to the proper size */ ! 531: dest = erealloc(dest, dest_len + 1); ! 532: dest[dest_len] = 0; ! 533: RETURN_STRINGL(dest, dest_len, 0); ! 534: } ! 535: } ! 536: /* }}} */ ! 537: ! 538: /* {{{ proto string bzdecompress(string source [, int small]) ! 539: Decompresses BZip2 compressed data */ ! 540: static PHP_FUNCTION(bzdecompress) ! 541: { ! 542: char *source, *dest; ! 543: int source_len, error; ! 544: long small = 0; ! 545: #if defined(PHP_WIN32) ! 546: unsigned __int64 size = 0; ! 547: #else ! 548: unsigned long long size = 0; ! 549: #endif ! 550: bz_stream bzs; ! 551: ! 552: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &small)) { ! 553: RETURN_FALSE; ! 554: } ! 555: ! 556: bzs.bzalloc = NULL; ! 557: bzs.bzfree = NULL; ! 558: ! 559: if (BZ2_bzDecompressInit(&bzs, 0, small) != BZ_OK) { ! 560: RETURN_FALSE; ! 561: } ! 562: ! 563: bzs.next_in = source; ! 564: bzs.avail_in = source_len; ! 565: ! 566: /* in most cases bz2 offers at least 2:1 compression, so we use that as our base */ ! 567: bzs.avail_out = source_len * 2; ! 568: bzs.next_out = dest = emalloc(bzs.avail_out + 1); ! 569: ! 570: while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) { ! 571: /* compression is better then 2:1, need to allocate more memory */ ! 572: bzs.avail_out = source_len; ! 573: size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; ! 574: dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size ); ! 575: bzs.next_out = dest + size; ! 576: } ! 577: ! 578: if (error == BZ_STREAM_END || error == BZ_OK) { ! 579: size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; ! 580: dest = safe_erealloc(dest, 1, (size_t) size, 1); ! 581: dest[size] = '\0'; ! 582: RETVAL_STRINGL(dest, (int) size, 0); ! 583: } else { /* real error */ ! 584: efree(dest); ! 585: RETVAL_LONG(error); ! 586: } ! 587: ! 588: BZ2_bzDecompressEnd(&bzs); ! 589: } ! 590: /* }}} */ ! 591: ! 592: /* {{{ php_bz2_error() ! 593: The central error handling interface, does the work for bzerrno, bzerrstr and bzerror */ ! 594: static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt) ! 595: { ! 596: zval *bzp; /* BZip2 Resource Pointer */ ! 597: php_stream *stream; ! 598: const char *errstr; /* Error string */ ! 599: int errnum; /* Error number */ ! 600: struct php_bz2_stream_data_t *self; ! 601: ! 602: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &bzp) == FAILURE) { ! 603: return; ! 604: } ! 605: ! 606: php_stream_from_zval(stream, &bzp); ! 607: ! 608: if (!php_stream_is(stream, PHP_STREAM_IS_BZIP2)) { ! 609: RETURN_FALSE; ! 610: } ! 611: ! 612: self = (struct php_bz2_stream_data_t *) stream->abstract; ! 613: ! 614: /* Fetch the error information */ ! 615: errstr = BZ2_bzerror(self->bz_file, &errnum); ! 616: ! 617: /* Determine what to return */ ! 618: switch (opt) { ! 619: case PHP_BZ_ERRNO: ! 620: RETURN_LONG(errnum); ! 621: break; ! 622: case PHP_BZ_ERRSTR: ! 623: RETURN_STRING((char*)errstr, 1); ! 624: break; ! 625: case PHP_BZ_ERRBOTH: ! 626: array_init(return_value); ! 627: ! 628: add_assoc_long (return_value, "errno", errnum); ! 629: add_assoc_string(return_value, "errstr", (char*)errstr, 1); ! 630: break; ! 631: } ! 632: } ! 633: /* }}} */ ! 634: ! 635: #endif ! 636: ! 637: /* ! 638: * Local variables: ! 639: * tab-width: 4 ! 640: * c-basic-offset: 4 ! 641: * End: ! 642: * vim600: fdm=marker ! 643: * vim: noet sw=4 ts=4 ! 644: */