Annotation of embedaddon/php/ext/bz2/bz2.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:   | 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:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>