Annotation of embedaddon/php/ext/standard/streamsfuncs.c, revision 1.1.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: Wez Furlong <wez@thebrainroom.com>                          |
                     16:   |          Sara Golemon <pollita@php.net>                              |
                     17:   +----------------------------------------------------------------------+
                     18: */
                     19: 
                     20: /* $Id: streamsfuncs.c 321634 2012-01-01 13:15:04Z felipe $ */
                     21: 
                     22: #include "php.h"
                     23: #include "php_globals.h"
                     24: #include "ext/standard/flock_compat.h"
                     25: #include "ext/standard/file.h"
                     26: #include "ext/standard/php_filestat.h"
                     27: #include "php_open_temporary_file.h"
                     28: #include "ext/standard/basic_functions.h"
                     29: #include "php_ini.h"
                     30: #include "streamsfuncs.h"
                     31: #include "php_network.h"
                     32: #include "php_string.h"
                     33: 
                     34: #ifndef PHP_WIN32
                     35: #define php_select(m, r, w, e, t)      select(m, r, w, e, t)
                     36: typedef unsigned long long php_timeout_ull;
                     37: #else
                     38: #include "win32/select.h"
                     39: #include "win32/sockets.h"
                     40: typedef unsigned __int64 php_timeout_ull;
                     41: #endif
                     42: 
                     43: static php_stream_context *decode_context_param(zval *contextresource TSRMLS_DC);
                     44: 
                     45: /* Streams based network functions */
                     46: 
                     47: #if HAVE_SOCKETPAIR
                     48: /* {{{ proto array stream_socket_pair(int domain, int type, int protocol)
                     49:    Creates a pair of connected, indistinguishable socket streams */
                     50: PHP_FUNCTION(stream_socket_pair)
                     51: {
                     52:        long domain, type, protocol;
                     53:        php_stream *s1, *s2;
                     54:        int pair[2];
                     55: 
                     56:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll",
                     57:                        &domain, &type, &protocol)) {
                     58:                RETURN_FALSE;
                     59:        }
                     60: 
                     61:        if (0 != socketpair(domain, type, protocol, pair)) {
                     62:                char errbuf[256];
                     63:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create sockets: [%d]: %s",
                     64:                        php_socket_errno(), php_socket_strerror(php_socket_errno(), errbuf, sizeof(errbuf)));
                     65:                RETURN_FALSE;
                     66:        }
                     67: 
                     68:        array_init(return_value);
                     69: 
                     70:        s1 = php_stream_sock_open_from_socket(pair[0], 0);
                     71:        s2 = php_stream_sock_open_from_socket(pair[1], 0);
                     72: 
                     73:        /* set the __exposed flag.
                     74:         * php_stream_to_zval() does, add_next_index_resource() does not */
                     75:        php_stream_auto_cleanup(s1);
                     76:        php_stream_auto_cleanup(s2);
                     77: 
                     78:        add_next_index_resource(return_value, php_stream_get_resource_id(s1));
                     79:        add_next_index_resource(return_value, php_stream_get_resource_id(s2));
                     80: }
                     81: /* }}} */
                     82: #endif
                     83: 
                     84: /* {{{ proto resource stream_socket_client(string remoteaddress [, long &errcode [, string &errstring [, double timeout [, long flags [, resource context]]]]])
                     85:    Open a client connection to a remote address */
                     86: PHP_FUNCTION(stream_socket_client)
                     87: {
                     88:        char *host;
                     89:        int host_len;
                     90:        zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL;
                     91:        double timeout = FG(default_socket_timeout);
                     92:        php_timeout_ull conv;
                     93:        struct timeval tv;
                     94:        char *hashkey = NULL;
                     95:        php_stream *stream = NULL;
                     96:        int err;
                     97:        long flags = PHP_STREAM_CLIENT_CONNECT;
                     98:        char *errstr = NULL;
                     99:        php_stream_context *context = NULL;
                    100: 
                    101:        RETVAL_FALSE;
                    102: 
                    103:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zzdlr", &host, &host_len, &zerrno, &zerrstr, &timeout, &flags, &zcontext) == FAILURE) {
                    104:                RETURN_FALSE;
                    105:        }
                    106: 
                    107:        context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
                    108: 
                    109:        if (context) {
                    110:                zend_list_addref(context->rsrc_id);
                    111:        }
                    112: 
                    113:        if (flags & PHP_STREAM_CLIENT_PERSISTENT) {
                    114:                spprintf(&hashkey, 0, "stream_socket_client__%s", host);
                    115:        }
                    116: 
                    117:        /* prepare the timeout value for use */
                    118:        conv = (php_timeout_ull) (timeout * 1000000.0);
                    119: #ifdef PHP_WIN32
                    120:        tv.tv_sec = (long)(conv / 1000000);
                    121:        tv.tv_usec =(long)(conv % 1000000);
                    122: #else
                    123:        tv.tv_sec = conv / 1000000;
                    124:        tv.tv_usec = conv % 1000000;
                    125: #endif
                    126:        if (zerrno)     {
                    127:                zval_dtor(zerrno);
                    128:                ZVAL_LONG(zerrno, 0);
                    129:        }
                    130:        if (zerrstr) {
                    131:                zval_dtor(zerrstr);
                    132:                ZVAL_STRING(zerrstr, "", 1);
                    133:        }
                    134: 
                    135:        stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE | REPORT_ERRORS,
                    136:                        STREAM_XPORT_CLIENT | (flags & PHP_STREAM_CLIENT_CONNECT ? STREAM_XPORT_CONNECT : 0) |
                    137:                        (flags & PHP_STREAM_CLIENT_ASYNC_CONNECT ? STREAM_XPORT_CONNECT_ASYNC : 0),
                    138:                        hashkey, &tv, context, &errstr, &err);
                    139: 
                    140: 
                    141:        if (stream == NULL) {
                    142:                /* host might contain binary characters */
                    143:                char *quoted_host = php_addslashes(host, host_len, NULL, 0 TSRMLS_CC);
                    144: 
                    145:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s (%s)", quoted_host, errstr == NULL ? "Unknown error" : errstr);
                    146:                efree(quoted_host);
                    147:        }
                    148: 
                    149:        if (hashkey) {
                    150:                efree(hashkey);
                    151:        }
                    152: 
                    153:        if (stream == NULL)     {
                    154:                if (zerrno) {
                    155:                        zval_dtor(zerrno);
                    156:                        ZVAL_LONG(zerrno, err);
                    157:                }
                    158:                if (zerrstr && errstr) {
                    159:                        /* no need to dup; we need to efree buf anyway */
                    160:                        zval_dtor(zerrstr);
                    161:                        ZVAL_STRING(zerrstr, errstr, 0);
                    162:                } else if (errstr) {
                    163:                        efree(errstr);
                    164:                }
                    165:                RETURN_FALSE;
                    166:        }
                    167: 
                    168:        if (errstr) {
                    169:                efree(errstr);
                    170:        }
                    171: 
                    172:        php_stream_to_zval(stream, return_value);
                    173: 
                    174: }
                    175: /* }}} */
                    176: 
                    177: /* {{{ proto resource stream_socket_server(string localaddress [, long &errcode [, string &errstring [, long flags [, resource context]]]])
                    178:    Create a server socket bound to localaddress */
                    179: PHP_FUNCTION(stream_socket_server)
                    180: {
                    181:        char *host;
                    182:        int host_len;
                    183:        zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL;
                    184:        php_stream *stream = NULL;
                    185:        int err = 0;
                    186:        long flags = STREAM_XPORT_BIND | STREAM_XPORT_LISTEN;
                    187:        char *errstr = NULL;
                    188:        php_stream_context *context = NULL;
                    189: 
                    190:        RETVAL_FALSE;
                    191: 
                    192:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zzlr", &host, &host_len, &zerrno, &zerrstr, &flags, &zcontext) == FAILURE) {
                    193:                RETURN_FALSE;
                    194:        }
                    195: 
                    196:        context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
                    197: 
                    198:        if (context) {
                    199:                zend_list_addref(context->rsrc_id);
                    200:        }
                    201: 
                    202:        if (zerrno)     {
                    203:                zval_dtor(zerrno);
                    204:                ZVAL_LONG(zerrno, 0);
                    205:        }
                    206:        if (zerrstr) {
                    207:                zval_dtor(zerrstr);
                    208:                ZVAL_STRING(zerrstr, "", 1);
                    209:        }
                    210: 
                    211:        stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE | REPORT_ERRORS,
                    212:                        STREAM_XPORT_SERVER | flags,
                    213:                        NULL, NULL, context, &errstr, &err);
                    214: 
                    215:        if (stream == NULL) {
                    216:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s (%s)", host, errstr == NULL ? "Unknown error" : errstr);
                    217:        }
                    218: 
                    219:        if (stream == NULL)     {
                    220:                if (zerrno) {
                    221:                        zval_dtor(zerrno);
                    222:                        ZVAL_LONG(zerrno, err);
                    223:                }
                    224:                if (zerrstr && errstr) {
                    225:                        /* no need to dup; we need to efree buf anyway */
                    226:                        zval_dtor(zerrstr);
                    227:                        ZVAL_STRING(zerrstr, errstr, 0);
                    228:                } else if (errstr) {
                    229:                        efree(errstr);
                    230:                }
                    231:                RETURN_FALSE;
                    232:        }
                    233: 
                    234:        if (errstr) {
                    235:                efree(errstr);
                    236:        }
                    237: 
                    238:        php_stream_to_zval(stream, return_value);
                    239: }
                    240: /* }}} */
                    241: 
                    242: /* {{{ proto resource stream_socket_accept(resource serverstream, [ double timeout [, string &peername ]])
                    243:    Accept a client connection from a server socket */
                    244: PHP_FUNCTION(stream_socket_accept)
                    245: {
                    246:        double timeout = FG(default_socket_timeout);
                    247:        zval *zpeername = NULL;
                    248:        char *peername = NULL;
                    249:        int peername_len;
                    250:        php_timeout_ull conv;
                    251:        struct timeval tv;
                    252:        php_stream *stream = NULL, *clistream = NULL;
                    253:        zval *zstream;
                    254: 
                    255:        char *errstr = NULL;
                    256: 
                    257:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|dz", &zstream, &timeout, &zpeername) == FAILURE) {
                    258:                RETURN_FALSE;
                    259:        }
                    260: 
                    261:        php_stream_from_zval(stream, &zstream);
                    262: 
                    263:        /* prepare the timeout value for use */
                    264:        conv = (php_timeout_ull) (timeout * 1000000.0);
                    265: #ifdef PHP_WIN32
                    266:        tv.tv_sec = (long)(conv / 1000000);
                    267:        tv.tv_usec = (long)(conv % 1000000);
                    268: #else
                    269:        tv.tv_sec = conv / 1000000;
                    270:        tv.tv_usec = conv % 1000000;
                    271: #endif
                    272:        if (zpeername) {
                    273:                zval_dtor(zpeername);
                    274:                ZVAL_NULL(zpeername);
                    275:        }
                    276: 
                    277:        if (0 == php_stream_xport_accept(stream, &clistream,
                    278:                                zpeername ? &peername : NULL,
                    279:                                zpeername ? &peername_len : NULL,
                    280:                                NULL, NULL,
                    281:                                &tv, &errstr
                    282:                                TSRMLS_CC) && clistream) {
                    283: 
                    284:                if (peername) {
                    285:                        ZVAL_STRINGL(zpeername, peername, peername_len, 0);
                    286:                }
                    287:                php_stream_to_zval(clistream, return_value);
                    288:        } else {
                    289:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "accept failed: %s", errstr ? errstr : "Unknown error");
                    290:                RETVAL_FALSE;
                    291:        }
                    292: 
                    293:        if (errstr) {
                    294:                efree(errstr);
                    295:        }
                    296: }
                    297: /* }}} */
                    298: 
                    299: /* {{{ proto string stream_socket_get_name(resource stream, bool want_peer)
                    300:    Returns either the locally bound or remote name for a socket stream */
                    301: PHP_FUNCTION(stream_socket_get_name)
                    302: {
                    303:        php_stream *stream;
                    304:        zval *zstream;
                    305:        zend_bool want_peer;
                    306:        char *name = NULL;
                    307:        int name_len;
                    308: 
                    309:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb", &zstream, &want_peer) == FAILURE) {
                    310:                RETURN_FALSE;
                    311:        }
                    312: 
                    313:        php_stream_from_zval(stream, &zstream);
                    314: 
                    315:        if (0 != php_stream_xport_get_name(stream, want_peer,
                    316:                                &name,
                    317:                                &name_len,
                    318:                                NULL, NULL
                    319:                                TSRMLS_CC)) {
                    320:                RETURN_FALSE;
                    321:        }
                    322: 
                    323:        RETURN_STRINGL(name, name_len, 0);
                    324: }
                    325: /* }}} */
                    326: 
                    327: /* {{{ proto long stream_socket_sendto(resouce stream, string data [, long flags [, string target_addr]])
                    328:    Send data to a socket stream.  If target_addr is specified it must be in dotted quad (or [ipv6]) format */
                    329: PHP_FUNCTION(stream_socket_sendto)
                    330: {
                    331:        php_stream *stream;
                    332:        zval *zstream;
                    333:        long flags = 0;
                    334:        char *data, *target_addr = NULL;
                    335:        int datalen, target_addr_len = 0;
                    336:        php_sockaddr_storage sa;
                    337:        socklen_t sl = 0;
                    338: 
                    339:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ls", &zstream, &data, &datalen, &flags, &target_addr, &target_addr_len) == FAILURE) {
                    340:                RETURN_FALSE;
                    341:        }
                    342:        php_stream_from_zval(stream, &zstream);
                    343: 
                    344:        if (target_addr_len) {
                    345:                /* parse the address */
                    346:                if (FAILURE == php_network_parse_network_address_with_port(target_addr, target_addr_len, (struct sockaddr*)&sa, &sl TSRMLS_CC)) {
                    347:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse `%s' into a valid network address", target_addr);
                    348:                        RETURN_FALSE;
                    349:                }
                    350:        }
                    351: 
                    352:        RETURN_LONG(php_stream_xport_sendto(stream, data, datalen, flags, target_addr ? &sa : NULL, sl TSRMLS_CC));
                    353: }
                    354: /* }}} */
                    355: 
                    356: /* {{{ proto string stream_socket_recvfrom(resource stream, long amount [, long flags [, string &remote_addr]])
                    357:    Receives data from a socket stream */
                    358: PHP_FUNCTION(stream_socket_recvfrom)
                    359: {
                    360:        php_stream *stream;
                    361:        zval *zstream, *zremote = NULL;
                    362:        char *remote_addr = NULL;
                    363:        int remote_addr_len;
                    364:        long to_read = 0;
                    365:        char *read_buf;
                    366:        long flags = 0;
                    367:        int recvd;
                    368: 
                    369:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|lz", &zstream, &to_read, &flags, &zremote) == FAILURE) {
                    370:                RETURN_FALSE;
                    371:        }
                    372: 
                    373:        php_stream_from_zval(stream, &zstream);
                    374: 
                    375:        if (zremote) {
                    376:                zval_dtor(zremote);
                    377:                ZVAL_NULL(zremote);
                    378:        }
                    379: 
                    380:        if (to_read <= 0) {
                    381:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
                    382:                RETURN_FALSE;
                    383:        }
                    384: 
                    385:        read_buf = safe_emalloc(1, to_read, 1);
                    386: 
                    387:        recvd = php_stream_xport_recvfrom(stream, read_buf, to_read, flags, NULL, NULL,
                    388:                        zremote ? &remote_addr : NULL,
                    389:                        zremote ? &remote_addr_len : NULL
                    390:                        TSRMLS_CC);
                    391: 
                    392:        if (recvd >= 0) {
                    393:                if (zremote) {
                    394:                        ZVAL_STRINGL(zremote, remote_addr, remote_addr_len, 0);
                    395:                }
                    396:                read_buf[recvd] = '\0';
                    397: 
                    398:                if (PG(magic_quotes_runtime)) {
                    399:                        Z_TYPE_P(return_value) = IS_STRING;
                    400:                        Z_STRVAL_P(return_value) = php_addslashes(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
                    401:                        return;
                    402:                } else {
                    403:                        RETURN_STRINGL(read_buf, recvd, 0);
                    404:                }
                    405:        }
                    406: 
                    407:        efree(read_buf);
                    408:        RETURN_FALSE;
                    409: }
                    410: /* }}} */
                    411: 
                    412: /* {{{ proto string stream_get_contents(resource source [, long maxlen [, long offset]])
                    413:    Reads all remaining bytes (or up to maxlen bytes) from a stream and returns them as a string. */
                    414: PHP_FUNCTION(stream_get_contents)
                    415: {
                    416:        php_stream      *stream;
                    417:        zval            *zsrc;
                    418:        long            maxlen          = PHP_STREAM_COPY_ALL,
                    419:                                desiredpos      = -1L;
                    420:        int                     len,
                    421:                                newlen;
                    422:        char            *contents       = NULL;
                    423: 
                    424:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ll", &zsrc, &maxlen, &desiredpos) == FAILURE) {
                    425:                RETURN_FALSE;
                    426:        }
                    427: 
                    428:        php_stream_from_zval(stream, &zsrc);
                    429: 
                    430:        if (desiredpos >= 0) {
                    431:                int             seek_res = 0;
                    432:                off_t   position;
                    433: 
                    434:                position = php_stream_tell(stream);
                    435:                if (position >= 0 && desiredpos > position) {
                    436:                        /* use SEEK_CUR to allow emulation in streams that don't support seeking */
                    437:                        seek_res = php_stream_seek(stream, desiredpos - position, SEEK_CUR);
                    438:                } else if (desiredpos < position)  {
                    439:                        /* desired position before position or error on tell */
                    440:                        seek_res = php_stream_seek(stream, desiredpos, SEEK_SET);
                    441:                }
                    442: 
                    443:                if (seek_res != 0) {
                    444:                        php_error_docref(NULL TSRMLS_CC, E_WARNING,
                    445:                                "Failed to seek to position %ld in the stream", desiredpos);
                    446:                        RETURN_FALSE;
                    447:                }
                    448:        }
                    449: 
                    450:        len = php_stream_copy_to_mem(stream, &contents, maxlen, 0);
                    451: 
                    452:        if (contents) {
                    453:                if (len && PG(magic_quotes_runtime)) {
                    454:                        contents = php_addslashes(contents, len, &newlen, 1 TSRMLS_CC); /* 1 = free source string */
                    455:                        len = newlen;
                    456:                }
                    457:                RETVAL_STRINGL(contents, len, 0);
                    458:        } else {
                    459:                RETVAL_EMPTY_STRING();
                    460:        }
                    461: }
                    462: /* }}} */
                    463: 
                    464: /* {{{ proto long stream_copy_to_stream(resource source, resource dest [, long maxlen [, long pos]])
                    465:    Reads up to maxlen bytes from source stream and writes them to dest stream. */
                    466: PHP_FUNCTION(stream_copy_to_stream)
                    467: {
                    468:        php_stream *src, *dest;
                    469:        zval *zsrc, *zdest;
                    470:        long maxlen = PHP_STREAM_COPY_ALL, pos = 0;
                    471:        size_t len;
                    472:        int ret;
                    473: 
                    474:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|ll", &zsrc, &zdest, &maxlen, &pos) == FAILURE) {
                    475:                RETURN_FALSE;
                    476:        }
                    477: 
                    478:        php_stream_from_zval(src, &zsrc);
                    479:        php_stream_from_zval(dest, &zdest);
                    480: 
                    481:        if (pos > 0 && php_stream_seek(src, pos, SEEK_SET) < 0) {
                    482:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek to position %ld in the stream", pos);
                    483:                RETURN_FALSE;
                    484:        }
                    485: 
                    486:        ret = php_stream_copy_to_stream_ex(src, dest, maxlen, &len);
                    487: 
                    488:        if (ret != SUCCESS) {
                    489:                RETURN_FALSE;
                    490:        }
                    491:        RETURN_LONG(len);
                    492: }
                    493: /* }}} */
                    494: 
                    495: /* {{{ proto array stream_get_meta_data(resource fp)
                    496:     Retrieves header/meta data from streams/file pointers */
                    497: PHP_FUNCTION(stream_get_meta_data)
                    498: {
                    499:        zval *arg1;
                    500:        php_stream *stream;
                    501:        zval *newval;
                    502: 
                    503:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
                    504:                return;
                    505:        }
                    506:        php_stream_from_zval(stream, &arg1);
                    507: 
                    508:        array_init(return_value);
                    509: 
                    510:        if (stream->wrapperdata) {
                    511:                MAKE_STD_ZVAL(newval);
                    512:                MAKE_COPY_ZVAL(&stream->wrapperdata, newval);
                    513: 
                    514:                add_assoc_zval(return_value, "wrapper_data", newval);
                    515:        }
                    516:        if (stream->wrapper) {
                    517:                add_assoc_string(return_value, "wrapper_type", (char *)stream->wrapper->wops->label, 1);
                    518:        }
                    519:        add_assoc_string(return_value, "stream_type", (char *)stream->ops->label, 1);
                    520: 
                    521:        add_assoc_string(return_value, "mode", stream->mode, 1);
                    522: 
                    523: #if 0  /* TODO: needs updating for new filter API */
                    524:        if (stream->filterhead) {
                    525:                php_stream_filter *filter;
                    526: 
                    527:                MAKE_STD_ZVAL(newval);
                    528:                array_init(newval);
                    529: 
                    530:                for (filter = stream->filterhead; filter != NULL; filter = filter->next) {
                    531:                        add_next_index_string(newval, (char *)filter->fops->label, 1);
                    532:                }
                    533: 
                    534:                add_assoc_zval(return_value, "filters", newval);
                    535:        }
                    536: #endif
                    537: 
                    538:        add_assoc_long(return_value, "unread_bytes", stream->writepos - stream->readpos);
                    539: 
                    540:        add_assoc_bool(return_value, "seekable", (stream->ops->seek) && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0);
                    541:        if (stream->orig_path) {
                    542:                add_assoc_string(return_value, "uri", stream->orig_path, 1);
                    543:        }
                    544: 
                    545:        if (!php_stream_populate_meta_data(stream, return_value)) {
                    546:                add_assoc_bool(return_value, "timed_out", 0);
                    547:                add_assoc_bool(return_value, "blocked", 1);
                    548:                add_assoc_bool(return_value, "eof", php_stream_eof(stream));
                    549:        }
                    550: 
                    551: }
                    552: /* }}} */
                    553: 
                    554: /* {{{ proto array stream_get_transports()
                    555:    Retrieves list of registered socket transports */
                    556: PHP_FUNCTION(stream_get_transports)
                    557: {
                    558:        HashTable *stream_xport_hash;
                    559:        char *stream_xport;
                    560:        int stream_xport_len;
                    561:        ulong num_key;
                    562: 
                    563:        if (zend_parse_parameters_none() == FAILURE) {
                    564:                return;
                    565:        }
                    566: 
                    567:        if ((stream_xport_hash = php_stream_xport_get_hash())) {
                    568:                HashPosition pos;
                    569:                array_init(return_value);
                    570:                zend_hash_internal_pointer_reset_ex(stream_xport_hash, &pos);
                    571:                while (zend_hash_get_current_key_ex(stream_xport_hash,
                    572:                                        &stream_xport, &stream_xport_len,
                    573:                                        &num_key, 0, &pos) == HASH_KEY_IS_STRING) {
                    574:                        add_next_index_stringl(return_value, stream_xport, stream_xport_len - 1, 1);
                    575:                        zend_hash_move_forward_ex(stream_xport_hash, &pos);
                    576:                }
                    577:        } else {
                    578:                RETURN_FALSE;
                    579:        }
                    580: }
                    581: /* }}} */
                    582: 
                    583: /* {{{ proto array stream_get_wrappers()
                    584:     Retrieves list of registered stream wrappers */
                    585: PHP_FUNCTION(stream_get_wrappers)
                    586: {
                    587:        HashTable *url_stream_wrappers_hash;
                    588:        char *stream_protocol;
                    589:        int key_flags, stream_protocol_len = 0;
                    590:        ulong num_key;
                    591: 
                    592:        if (zend_parse_parameters_none() == FAILURE) {
                    593:                return;
                    594:        }
                    595: 
                    596:        if ((url_stream_wrappers_hash = php_stream_get_url_stream_wrappers_hash())) {
                    597:                HashPosition pos;
                    598:                array_init(return_value);
                    599:                for (zend_hash_internal_pointer_reset_ex(url_stream_wrappers_hash, &pos);
                    600:                        (key_flags = zend_hash_get_current_key_ex(url_stream_wrappers_hash, &stream_protocol, &stream_protocol_len, &num_key, 0, &pos)) != HASH_KEY_NON_EXISTANT;
                    601:                        zend_hash_move_forward_ex(url_stream_wrappers_hash, &pos)) {
                    602:                                if (key_flags == HASH_KEY_IS_STRING) {
                    603:                                        add_next_index_stringl(return_value, stream_protocol, stream_protocol_len - 1, 1);
                    604:                                }
                    605:                }
                    606:        } else {
                    607:                RETURN_FALSE;
                    608:        }
                    609: 
                    610: }
                    611: /* }}} */
                    612: 
                    613: /* {{{ stream_select related functions */
                    614: static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t *max_fd TSRMLS_DC)
                    615: {
                    616:        zval **elem;
                    617:        php_stream *stream;
                    618:        php_socket_t this_fd;
                    619:        int cnt = 0;
                    620: 
                    621:        if (Z_TYPE_P(stream_array) != IS_ARRAY) {
                    622:                return 0;
                    623:        }
                    624:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
                    625:                 zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
                    626:                 zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
                    627: 
                    628:                php_stream_from_zval_no_verify(stream, elem);
                    629:                if (stream == NULL) {
                    630:                        continue;
                    631:                }
                    632:                /* get the fd.
                    633:                 * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
                    634:                 * when casting.  It is only used here so that the buffered data warning
                    635:                 * is not displayed.
                    636:                 * */
                    637:                if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd != -1) {
                    638: 
                    639:                        PHP_SAFE_FD_SET(this_fd, fds);
                    640: 
                    641:                        if (this_fd > *max_fd) {
                    642:                                *max_fd = this_fd;
                    643:                        }
                    644:                        cnt++;
                    645:                }
                    646:        }
                    647:        return cnt ? 1 : 0;
                    648: }
                    649: 
                    650: static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC)
                    651: {
                    652:        zval **elem, **dest_elem;
                    653:        php_stream *stream;
                    654:        HashTable *new_hash;
                    655:        php_socket_t this_fd;
                    656:        int ret = 0;
                    657: 
                    658:        if (Z_TYPE_P(stream_array) != IS_ARRAY) {
                    659:                return 0;
                    660:        }
                    661:        ALLOC_HASHTABLE(new_hash);
                    662:        zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(stream_array)), NULL, ZVAL_PTR_DTOR, 0);
                    663: 
                    664:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
                    665:                 zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
                    666:                 zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
                    667: 
                    668:                php_stream_from_zval_no_verify(stream, elem);
                    669:                if (stream == NULL) {
                    670:                        continue;
                    671:                }
                    672:                /* get the fd
                    673:                 * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
                    674:                 * when casting.  It is only used here so that the buffered data warning
                    675:                 * is not displayed.
                    676:                 */
                    677:                if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd != -1) {
                    678:                        if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
                    679:                                zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
                    680:                                if (dest_elem) {
                    681:                                        zval_add_ref(dest_elem);
                    682:                                }
                    683:                                ret++;
                    684:                                continue;
                    685:                        }
                    686:                }
                    687:        }
                    688: 
                    689:        /* destroy old array and add new one */
                    690:        zend_hash_destroy(Z_ARRVAL_P(stream_array));
                    691:        efree(Z_ARRVAL_P(stream_array));
                    692: 
                    693:        zend_hash_internal_pointer_reset(new_hash);
                    694:        Z_ARRVAL_P(stream_array) = new_hash;
                    695: 
                    696:        return ret;
                    697: }
                    698: 
                    699: static int stream_array_emulate_read_fd_set(zval *stream_array TSRMLS_DC)
                    700: {
                    701:        zval **elem, **dest_elem;
                    702:        php_stream *stream;
                    703:        HashTable *new_hash;
                    704:        int ret = 0;
                    705: 
                    706:        if (Z_TYPE_P(stream_array) != IS_ARRAY) {
                    707:                return 0;
                    708:        }
                    709:        ALLOC_HASHTABLE(new_hash);
                    710:        zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(stream_array)), NULL, ZVAL_PTR_DTOR, 0);
                    711: 
                    712:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
                    713:                 zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
                    714:                 zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
                    715: 
                    716:                php_stream_from_zval_no_verify(stream, elem);
                    717:                if (stream == NULL) {
                    718:                        continue;
                    719:                }
                    720:                if ((stream->writepos - stream->readpos) > 0) {
                    721:                        /* allow readable non-descriptor based streams to participate in stream_select.
                    722:                         * Non-descriptor streams will only "work" if they have previously buffered the
                    723:                         * data.  Not ideal, but better than nothing.
                    724:                         * This branch of code also allows blocking streams with buffered data to
                    725:                         * operate correctly in stream_select.
                    726:                         * */
                    727:                        zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
                    728:                        if (dest_elem) {
                    729:                                zval_add_ref(dest_elem);
                    730:                        }
                    731:                        ret++;
                    732:                        continue;
                    733:                }
                    734:        }
                    735: 
                    736:        if (ret > 0) {
                    737:                /* destroy old array and add new one */
                    738:                zend_hash_destroy(Z_ARRVAL_P(stream_array));
                    739:                efree(Z_ARRVAL_P(stream_array));
                    740: 
                    741:                zend_hash_internal_pointer_reset(new_hash);
                    742:                Z_ARRVAL_P(stream_array) = new_hash;
                    743:        } else {
                    744:                zend_hash_destroy(new_hash);
                    745:                FREE_HASHTABLE(new_hash);
                    746:        }
                    747: 
                    748:        return ret;
                    749: }
                    750: /* }}} */
                    751: 
                    752: /* {{{ proto int stream_select(array &read_streams, array &write_streams, array &except_streams, int tv_sec[, int tv_usec])
                    753:    Runs the select() system call on the sets of streams with a timeout specified by tv_sec and tv_usec */
                    754: PHP_FUNCTION(stream_select)
                    755: {
                    756:        zval                    *r_array, *w_array, *e_array, **sec = NULL;
                    757:        struct timeval  tv;
                    758:        struct timeval *tv_p = NULL;
                    759:        fd_set                  rfds, wfds, efds;
                    760:        php_socket_t    max_fd = 0;
                    761:        int                             retval, sets = 0;
                    762:        long                    usec = 0;
                    763:        int                             set_count, max_set_count = 0;
                    764: 
                    765:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!Z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE)
                    766:                return;
                    767: 
                    768:        FD_ZERO(&rfds);
                    769:        FD_ZERO(&wfds);
                    770:        FD_ZERO(&efds);
                    771: 
                    772:        if (r_array != NULL) {
                    773:                set_count = stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
                    774:                if (set_count > max_set_count)
                    775:                        max_set_count = set_count;
                    776:                sets += set_count;
                    777:        }
                    778: 
                    779:        if (w_array != NULL) {
                    780:                set_count = stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
                    781:                if (set_count > max_set_count)
                    782:                        max_set_count = set_count;
                    783:                sets += set_count;
                    784:        }
                    785: 
                    786:        if (e_array != NULL) {
                    787:                set_count = stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
                    788:                if (set_count > max_set_count)
                    789:                        max_set_count = set_count;
                    790:                sets += set_count;
                    791:        }
                    792: 
                    793:        if (!sets) {
                    794:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed");
                    795:                RETURN_FALSE;
                    796:        }
                    797: 
                    798:        PHP_SAFE_MAX_FD(max_fd, max_set_count);
                    799: 
                    800:        /* If seconds is not set to null, build the timeval, else we wait indefinitely */
                    801:        if (sec != NULL) {
                    802:                convert_to_long_ex(sec);
                    803: 
                    804:                if (Z_LVAL_PP(sec) < 0) {
                    805:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "The seconds parameter must be greater than 0");
                    806:                        RETURN_FALSE;
                    807:                } else if (usec < 0) {
                    808:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "The microseconds parameter must be greater than 0");
                    809:                        RETURN_FALSE;
                    810:                }
                    811: 
                    812:                /* Solaris + BSD do not like microsecond values which are >= 1 sec */
                    813:                if (usec > 999999) {
                    814:                        tv.tv_sec = Z_LVAL_PP(sec) + (usec / 1000000);
                    815:                        tv.tv_usec = usec % 1000000;
                    816:                } else {
                    817:                        tv.tv_sec = Z_LVAL_PP(sec);
                    818:                        tv.tv_usec = usec;
                    819:                }
                    820: 
                    821:                tv_p = &tv;
                    822:        }
                    823: 
                    824:        /* slight hack to support buffered data; if there is data sitting in the
                    825:         * read buffer of any of the streams in the read array, let's pretend
                    826:         * that we selected, but return only the readable sockets */
                    827:        if (r_array != NULL) {
                    828: 
                    829:                retval = stream_array_emulate_read_fd_set(r_array TSRMLS_CC);
                    830:                if (retval > 0) {
                    831:                        if (w_array != NULL) {
                    832:                                zend_hash_clean(Z_ARRVAL_P(w_array));
                    833:                        }
                    834:                        if (e_array != NULL) {
                    835:                                zend_hash_clean(Z_ARRVAL_P(e_array));
                    836:                        }
                    837:                        RETURN_LONG(retval);
                    838:                }
                    839:        }
                    840: 
                    841:        retval = php_select(max_fd+1, &rfds, &wfds, &efds, tv_p);
                    842: 
                    843:        if (retval == -1) {
                    844:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
                    845:                                errno, strerror(errno), max_fd);
                    846:                RETURN_FALSE;
                    847:        }
                    848: 
                    849:        if (r_array != NULL) stream_array_from_fd_set(r_array, &rfds TSRMLS_CC);
                    850:        if (w_array != NULL) stream_array_from_fd_set(w_array, &wfds TSRMLS_CC);
                    851:        if (e_array != NULL) stream_array_from_fd_set(e_array, &efds TSRMLS_CC);
                    852: 
                    853:        RETURN_LONG(retval);
                    854: }
                    855: /* }}} */
                    856: 
                    857: /* {{{ stream_context related functions */
                    858: static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity,
                    859:                char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC)
                    860: {
                    861:        zval *callback = (zval*)context->notifier->ptr;
                    862:        zval *retval = NULL;
                    863:        zval zvs[6];
                    864:        zval *ps[6];
                    865:        zval **ptps[6];
                    866:        int i;
                    867: 
                    868:        for (i = 0; i < 6; i++) {
                    869:                INIT_ZVAL(zvs[i]);
                    870:                ps[i] = &zvs[i];
                    871:                ptps[i] = &ps[i];
                    872:                MAKE_STD_ZVAL(ps[i]);
                    873:        }
                    874: 
                    875:        ZVAL_LONG(ps[0], notifycode);
                    876:        ZVAL_LONG(ps[1], severity);
                    877:        if (xmsg) {
                    878:                ZVAL_STRING(ps[2], xmsg, 1);
                    879:        } else {
                    880:                ZVAL_NULL(ps[2]);
                    881:        }
                    882:        ZVAL_LONG(ps[3], xcode);
                    883:        ZVAL_LONG(ps[4], bytes_sofar);
                    884:        ZVAL_LONG(ps[5], bytes_max);
                    885: 
                    886:        if (FAILURE == call_user_function_ex(EG(function_table), NULL, callback, &retval, 6, ptps, 0, NULL TSRMLS_CC)) {
                    887:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to call user notifier");
                    888:        }
                    889:        for (i = 0; i < 6; i++) {
                    890:                zval_ptr_dtor(&ps[i]);
                    891:        }
                    892:        if (retval) {
                    893:                zval_ptr_dtor(&retval);
                    894:        }
                    895: }
                    896: 
                    897: static void user_space_stream_notifier_dtor(php_stream_notifier *notifier)
                    898: {
                    899:        if (notifier && notifier->ptr) {
                    900:                zval_ptr_dtor((zval **)&(notifier->ptr));
                    901:                notifier->ptr = NULL;
                    902:        }
                    903: }
                    904: 
                    905: static int parse_context_options(php_stream_context *context, zval *options TSRMLS_DC)
                    906: {
                    907:        HashPosition pos, opos;
                    908:        zval **wval, **oval;
                    909:        char *wkey, *okey;
                    910:        int wkey_len, okey_len;
                    911:        int ret = SUCCESS;
                    912:        ulong num_key;
                    913: 
                    914:        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(options), &pos);
                    915:        while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(options), (void**)&wval, &pos)) {
                    916:                if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &wkey, &wkey_len, &num_key, 0, &pos)
                    917:                                && Z_TYPE_PP(wval) == IS_ARRAY) {
                    918: 
                    919:                        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(wval), &opos);
                    920:                        while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(wval), (void**)&oval, &opos)) {
                    921: 
                    922:                                if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_PP(wval), &okey, &okey_len, &num_key, 0, &opos)) {
                    923:                                        php_stream_context_set_option(context, wkey, okey, *oval);
                    924:                                }
                    925:                                zend_hash_move_forward_ex(Z_ARRVAL_PP(wval), &opos);
                    926:                        }
                    927: 
                    928:                } else {
                    929:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "options should have the form [\"wrappername\"][\"optionname\"] = $value");
                    930:                }
                    931:                zend_hash_move_forward_ex(Z_ARRVAL_P(options), &pos);
                    932:        }
                    933: 
                    934:        return ret;
                    935: }
                    936: 
                    937: static int parse_context_params(php_stream_context *context, zval *params TSRMLS_DC)
                    938: {
                    939:        int ret = SUCCESS;
                    940:        zval **tmp;
                    941: 
                    942:        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), "notification", sizeof("notification"), (void**)&tmp)) {
                    943: 
                    944:                if (context->notifier) {
                    945:                        php_stream_notification_free(context->notifier);
                    946:                        context->notifier = NULL;
                    947:                }
                    948: 
                    949:                context->notifier = php_stream_notification_alloc();
                    950:                context->notifier->func = user_space_stream_notifier;
                    951:                context->notifier->ptr = *tmp;
                    952:                Z_ADDREF_P(*tmp);
                    953:                context->notifier->dtor = user_space_stream_notifier_dtor;
                    954:        }
                    955:        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), "options", sizeof("options"), (void**)&tmp)) {
                    956:                if (Z_TYPE_PP(tmp) == IS_ARRAY) {
                    957:                        parse_context_options(context, *tmp TSRMLS_CC);
                    958:                } else {
                    959:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                    960:                }
                    961:        }
                    962: 
                    963:        return ret;
                    964: }
                    965: 
                    966: /* given a zval which is either a stream or a context, return the underlying
                    967:  * stream_context.  If it is a stream that does not have a context assigned, it
                    968:  * will create and assign a context and return that.  */
                    969: static php_stream_context *decode_context_param(zval *contextresource TSRMLS_DC)
                    970: {
                    971:        php_stream_context *context = NULL;
                    972: 
                    973:        context = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 1, php_le_stream_context());
                    974:        if (context == NULL) {
                    975:                php_stream *stream;
                    976: 
                    977:                stream = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream);
                    978: 
                    979:                if (stream) {
                    980:                        context = stream->context;
                    981:                        if (context == NULL) {
                    982:                                /* Only way this happens is if file is opened with NO_DEFAULT_CONTEXT
                    983:                                   param, but then something is called which requires a context.
                    984:                                   Don't give them the default one though since they already said they
                    985:                                   didn't want it. */
                    986:                                context = stream->context = php_stream_context_alloc();
                    987:                        }
                    988:                }
                    989:        }
                    990: 
                    991:        return context;
                    992: }
                    993: /* }}} */
                    994: 
                    995: /* {{{ proto array stream_context_get_options(resource context|resource stream)
                    996:    Retrieve options for a stream/wrapper/context */
                    997: PHP_FUNCTION(stream_context_get_options)
                    998: {
                    999:        zval *zcontext;
                   1000:        php_stream_context *context;
                   1001: 
                   1002:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zcontext) == FAILURE) {
                   1003:                RETURN_FALSE;
                   1004:        }
                   1005:        context = decode_context_param(zcontext TSRMLS_CC);
                   1006:        if (!context) {
                   1007:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1008:                RETURN_FALSE;
                   1009:        }
                   1010: 
                   1011:        RETURN_ZVAL(context->options, 1, 0);
                   1012: }
                   1013: /* }}} */
                   1014: 
                   1015: /* {{{ proto bool stream_context_set_option(resource context|resource stream, string wrappername, string optionname, mixed value)
                   1016:    Set an option for a wrapper */
                   1017: PHP_FUNCTION(stream_context_set_option)
                   1018: {
                   1019:        zval *options = NULL, *zcontext = NULL, *zvalue = NULL;
                   1020:        php_stream_context *context;
                   1021:        char *wrappername, *optionname;
                   1022:        int wrapperlen, optionlen;
                   1023: 
                   1024:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
                   1025:                                "rssz", &zcontext, &wrappername, &wrapperlen,
                   1026:                                &optionname, &optionlen, &zvalue) == FAILURE) {
                   1027:                if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
                   1028:                                        "ra", &zcontext, &options) == FAILURE) {
                   1029:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "called with wrong number or type of parameters; please RTM");
                   1030:                        RETURN_FALSE;
                   1031:                }
                   1032:        }
                   1033: 
                   1034:        /* figure out where the context is coming from exactly */
                   1035:        context = decode_context_param(zcontext TSRMLS_CC);
                   1036:        if (!context) {
                   1037:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1038:                RETURN_FALSE;
                   1039:        }
                   1040: 
                   1041:        if (options) {
                   1042:                /* handle the array syntax */
                   1043:                RETVAL_BOOL(parse_context_options(context, options TSRMLS_CC) == SUCCESS);
                   1044:        } else {
                   1045:                php_stream_context_set_option(context, wrappername, optionname, zvalue);
                   1046:                RETVAL_TRUE;
                   1047:        }
                   1048: }
                   1049: /* }}} */
                   1050: 
                   1051: /* {{{ proto bool stream_context_set_params(resource context|resource stream, array options)
                   1052:    Set parameters for a file context */
                   1053: PHP_FUNCTION(stream_context_set_params)
                   1054: {
                   1055:        zval *params, *zcontext;
                   1056:        php_stream_context *context;
                   1057: 
                   1058:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra", &zcontext, &params) == FAILURE) {
                   1059:                RETURN_FALSE;
                   1060:        }
                   1061: 
                   1062:        context = decode_context_param(zcontext TSRMLS_CC);
                   1063:        if (!context) {
                   1064:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1065:                RETURN_FALSE;
                   1066:        }
                   1067: 
                   1068:        RETVAL_BOOL(parse_context_params(context, params TSRMLS_CC) == SUCCESS);
                   1069: }
                   1070: /* }}} */
                   1071: 
                   1072: /* {{{ proto array stream_context_get_params(resource context|resource stream)
                   1073:    Get parameters of a file context */
                   1074: PHP_FUNCTION(stream_context_get_params)
                   1075: {
                   1076:        zval *zcontext, *options;
                   1077:        php_stream_context *context;
                   1078: 
                   1079:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zcontext) == FAILURE) {
                   1080:                RETURN_FALSE;
                   1081:        }
                   1082: 
                   1083:        context = decode_context_param(zcontext TSRMLS_CC);
                   1084:        if (!context) {
                   1085:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1086:                RETURN_FALSE;
                   1087:        }
                   1088: 
                   1089:        array_init(return_value);
                   1090:        if (context->notifier && context->notifier->ptr && context->notifier->func == user_space_stream_notifier) {
                   1091:                add_assoc_zval_ex(return_value, ZEND_STRS("notification"), context->notifier->ptr);
                   1092:                Z_ADDREF_P(context->notifier->ptr);
                   1093:        }
                   1094:        ALLOC_INIT_ZVAL(options);
                   1095:        ZVAL_ZVAL(options, context->options, 1, 0);
                   1096:        add_assoc_zval_ex(return_value, ZEND_STRS("options"), options);
                   1097: }
                   1098: /* }}} */
                   1099: 
                   1100: /* {{{ proto resource stream_context_get_default([array options])
                   1101:    Get a handle on the default file/stream context and optionally set parameters */
                   1102: PHP_FUNCTION(stream_context_get_default)
                   1103: {
                   1104:        zval *params = NULL;
                   1105:        php_stream_context *context;
                   1106: 
                   1107:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &params) == FAILURE) {
                   1108:                RETURN_FALSE;
                   1109:        }
                   1110: 
                   1111:        if (FG(default_context) == NULL) {
                   1112:                FG(default_context) = php_stream_context_alloc();
                   1113:        }
                   1114:        context = FG(default_context);
                   1115: 
                   1116:        if (params) {
                   1117:                parse_context_options(context, params TSRMLS_CC);
                   1118:        }
                   1119: 
                   1120:        php_stream_context_to_zval(context, return_value);
                   1121: }
                   1122: /* }}} */
                   1123: 
                   1124: /* {{{ proto resource stream_context_set_default(array options)
                   1125:    Set default file/stream context, returns the context as a resource */
                   1126: PHP_FUNCTION(stream_context_set_default)
                   1127: {
                   1128:        zval *options = NULL;
                   1129:        php_stream_context *context;
                   1130: 
                   1131:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &options) == FAILURE) {
                   1132:                return;
                   1133:        }
                   1134: 
                   1135:        if (FG(default_context) == NULL) {
                   1136:                FG(default_context) = php_stream_context_alloc();
                   1137:        }
                   1138:        context = FG(default_context);
                   1139: 
                   1140:        parse_context_options(context, options TSRMLS_CC);
                   1141: 
                   1142:        php_stream_context_to_zval(context, return_value);
                   1143: }
                   1144: /* }}} */
                   1145: 
                   1146: /* {{{ proto resource stream_context_create([array options[, array params]])
                   1147:    Create a file context and optionally set parameters */
                   1148: PHP_FUNCTION(stream_context_create)
                   1149: {
                   1150:        zval *options = NULL, *params = NULL;
                   1151:        php_stream_context *context;
                   1152: 
                   1153:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!a!", &options, &params) == FAILURE) {
                   1154:                RETURN_FALSE;
                   1155:        }
                   1156: 
                   1157:        context = php_stream_context_alloc();
                   1158: 
                   1159:        if (options) {
                   1160:                parse_context_options(context, options TSRMLS_CC);
                   1161:        }
                   1162: 
                   1163:        if (params) {
                   1164:                parse_context_params(context, params TSRMLS_CC);
                   1165:        }
                   1166: 
                   1167:        RETURN_RESOURCE(context->rsrc_id);
                   1168: }
                   1169: /* }}} */
                   1170: 
                   1171: /* {{{ streams filter functions */
                   1172: static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS)
                   1173: {
                   1174:        zval *zstream;
                   1175:        php_stream *stream;
                   1176:        char *filtername;
                   1177:        int filternamelen;
                   1178:        long read_write = 0;
                   1179:        zval *filterparams = NULL;
                   1180:        php_stream_filter *filter = NULL;
                   1181:        int ret;
                   1182: 
                   1183:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz", &zstream,
                   1184:                                &filtername, &filternamelen, &read_write, &filterparams) == FAILURE) {
                   1185:                RETURN_FALSE;
                   1186:        }
                   1187: 
                   1188:        php_stream_from_zval(stream, &zstream);
                   1189: 
                   1190:        if ((read_write & PHP_STREAM_FILTER_ALL) == 0) {
                   1191:                /* Chain not specified.
                   1192:                 * Examine stream->mode to determine which filters are needed
                   1193:                 * There's no harm in attaching a filter to an unused chain,
                   1194:                 * but why waste the memory and clock cycles?
                   1195:                 */
                   1196:                if (strchr(stream->mode, 'r') || strchr(stream->mode, '+')) {
                   1197:                        read_write |= PHP_STREAM_FILTER_READ;
                   1198:                }
                   1199:                if (strchr(stream->mode, 'w') || strchr(stream->mode, '+') || strchr(stream->mode, 'a')) {
                   1200:                        read_write |= PHP_STREAM_FILTER_WRITE;
                   1201:                }
                   1202:        }
                   1203: 
                   1204:        if (read_write & PHP_STREAM_FILTER_READ) {
                   1205:                filter = php_stream_filter_create(filtername, filterparams, php_stream_is_persistent(stream) TSRMLS_CC);
                   1206:                if (filter == NULL) {
                   1207:                        RETURN_FALSE;
                   1208:                }
                   1209: 
                   1210:                if (append) {
                   1211:                        ret = php_stream_filter_append_ex(&stream->readfilters, filter TSRMLS_CC);
                   1212:                } else {
                   1213:                        ret = php_stream_filter_prepend_ex(&stream->readfilters, filter TSRMLS_CC);
                   1214:                }
                   1215:                if (ret != SUCCESS) {
                   1216:                        php_stream_filter_remove(filter, 1 TSRMLS_CC);
                   1217:                        RETURN_FALSE;
                   1218:                }
                   1219:        }
                   1220: 
                   1221:        if (read_write & PHP_STREAM_FILTER_WRITE) {
                   1222:                filter = php_stream_filter_create(filtername, filterparams, php_stream_is_persistent(stream) TSRMLS_CC);
                   1223:                if (filter == NULL) {
                   1224:                        RETURN_FALSE;
                   1225:                }
                   1226: 
                   1227:                if (append) {
                   1228:                        ret = php_stream_filter_append_ex(&stream->writefilters, filter TSRMLS_CC);
                   1229:                } else {
                   1230:                        ret = php_stream_filter_prepend_ex(&stream->writefilters, filter TSRMLS_CC);
                   1231:                }
                   1232:                if (ret != SUCCESS) {
                   1233:                        php_stream_filter_remove(filter, 1 TSRMLS_CC);
                   1234:                        RETURN_FALSE;
                   1235:                }
                   1236:        }
                   1237: 
                   1238:        if (filter) {
                   1239:                RETURN_RESOURCE(filter->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, filter, php_file_le_stream_filter()));
                   1240:        } else {
                   1241:                RETURN_FALSE;
                   1242:        }
                   1243: }
                   1244: /* }}} */
                   1245: 
                   1246: /* {{{ proto resource stream_filter_prepend(resource stream, string filtername[, int read_write[, string filterparams]])
                   1247:    Prepend a filter to a stream */
                   1248: PHP_FUNCTION(stream_filter_prepend)
                   1249: {
                   1250:        apply_filter_to_stream(0, INTERNAL_FUNCTION_PARAM_PASSTHRU);
                   1251: }
                   1252: /* }}} */
                   1253: 
                   1254: /* {{{ proto resource stream_filter_append(resource stream, string filtername[, int read_write[, string filterparams]])
                   1255:    Append a filter to a stream */
                   1256: PHP_FUNCTION(stream_filter_append)
                   1257: {
                   1258:        apply_filter_to_stream(1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
                   1259: }
                   1260: /* }}} */
                   1261: 
                   1262: /* {{{ proto bool stream_filter_remove(resource stream_filter)
                   1263:        Flushes any data in the filter's internal buffer, removes it from the chain, and frees the resource */
                   1264: PHP_FUNCTION(stream_filter_remove)
                   1265: {
                   1266:        zval *zfilter;
                   1267:        php_stream_filter *filter;
                   1268: 
                   1269:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zfilter) == FAILURE) {
                   1270:                RETURN_FALSE;
                   1271:        }
                   1272: 
                   1273:        filter = zend_fetch_resource(&zfilter TSRMLS_CC, -1, NULL, NULL, 1, php_file_le_stream_filter());
                   1274:        if (!filter) {
                   1275:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid resource given, not a stream filter");
                   1276:                RETURN_FALSE;
                   1277:        }
                   1278: 
                   1279:        if (php_stream_filter_flush(filter, 1) == FAILURE) {
                   1280:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to flush filter, not removing");
                   1281:                RETURN_FALSE;
                   1282:        }
                   1283: 
                   1284:        if (zend_list_delete(Z_LVAL_P(zfilter)) == FAILURE) {
                   1285:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not invalidate filter, not removing");
                   1286:                RETURN_FALSE;
                   1287:        } else {
                   1288:                php_stream_filter_remove(filter, 1 TSRMLS_CC);
                   1289:                RETURN_TRUE;
                   1290:        }
                   1291: }
                   1292: /* }}} */
                   1293: 
                   1294: /* {{{ proto string stream_get_line(resource stream, int maxlen [, string ending])
                   1295:    Read up to maxlen bytes from a stream or until the ending string is found */
                   1296: PHP_FUNCTION(stream_get_line)
                   1297: {
                   1298:        char *str = NULL;
                   1299:        int str_len = 0;
                   1300:        long max_length;
                   1301:        zval *zstream;
                   1302:        char *buf;
                   1303:        size_t buf_size;
                   1304:        php_stream *stream;
                   1305: 
                   1306:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|s", &zstream, &max_length, &str, &str_len) == FAILURE) {
                   1307:                RETURN_FALSE;
                   1308:        }
                   1309: 
                   1310:        if (max_length < 0) {
                   1311:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The maximum allowed length must be greater than or equal to zero");
                   1312:                RETURN_FALSE;
                   1313:        }
                   1314:        if (!max_length) {
                   1315:                max_length = PHP_SOCK_CHUNK_SIZE;
                   1316:        }
                   1317: 
                   1318:        php_stream_from_zval(stream, &zstream);
                   1319: 
                   1320:        if ((buf = php_stream_get_record(stream, max_length, &buf_size, str, str_len TSRMLS_CC))) {
                   1321:                RETURN_STRINGL(buf, buf_size, 0);
                   1322:        } else {
                   1323:                RETURN_FALSE;
                   1324:        }
                   1325: }
                   1326: 
                   1327: /* }}} */
                   1328: 
                   1329: /* {{{ proto bool stream_set_blocking(resource socket, int mode)
                   1330:    Set blocking/non-blocking mode on a socket or stream */
                   1331: PHP_FUNCTION(stream_set_blocking)
                   1332: {
                   1333:        zval *arg1;
                   1334:        int block;
                   1335:        long arg2;
                   1336:        php_stream *stream;
                   1337: 
                   1338:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &arg1, &arg2) == FAILURE) {
                   1339:                return;
                   1340:        }
                   1341: 
                   1342:        php_stream_from_zval(stream, &arg1);
                   1343: 
                   1344:        block = arg2;
                   1345: 
                   1346:        if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, block == 0 ? 0 : 1, NULL) == -1) {
                   1347:                RETURN_FALSE;
                   1348:        }
                   1349: 
                   1350:        RETURN_TRUE;
                   1351: }
                   1352: 
                   1353: /* }}} */
                   1354: 
                   1355: /* {{{ proto bool stream_set_timeout(resource stream, int seconds [, int microseconds])
                   1356:    Set timeout on stream read to seconds + microseonds */
                   1357: #if HAVE_SYS_TIME_H || defined(PHP_WIN32)
                   1358: PHP_FUNCTION(stream_set_timeout)
                   1359: {
                   1360:        zval *socket;
                   1361:        long seconds, microseconds = 0;
                   1362:        struct timeval t;
                   1363:        php_stream *stream;
                   1364:        int argc = ZEND_NUM_ARGS();
                   1365: 
                   1366:        if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &socket, &seconds, &microseconds) == FAILURE) {
                   1367:                return;
                   1368:        }
                   1369: 
                   1370:        php_stream_from_zval(stream, &socket);
                   1371: 
                   1372:        t.tv_sec = seconds;
                   1373: 
                   1374:        if (argc == 3) {
                   1375:                t.tv_usec = microseconds % 1000000;
                   1376:                t.tv_sec += microseconds / 1000000;
                   1377:        } else {
                   1378:                t.tv_usec = 0;
                   1379:        }
                   1380: 
                   1381:        if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &t)) {
                   1382:                RETURN_TRUE;
                   1383:        }
                   1384: 
                   1385:        RETURN_FALSE;
                   1386: }
                   1387: #endif /* HAVE_SYS_TIME_H || defined(PHP_WIN32) */
                   1388: /* }}} */
                   1389: 
                   1390: /* {{{ proto int stream_set_write_buffer(resource fp, int buffer)
                   1391:    Set file write buffer */
                   1392: PHP_FUNCTION(stream_set_write_buffer)
                   1393: {
                   1394:        zval *arg1;
                   1395:        int ret;
                   1396:        long arg2;
                   1397:        size_t buff;
                   1398:        php_stream *stream;
                   1399: 
                   1400:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &arg1, &arg2) == FAILURE) {
                   1401:                RETURN_FALSE;
                   1402:        }
                   1403: 
                   1404:        php_stream_from_zval(stream, &arg1);
                   1405: 
                   1406:        buff = arg2;
                   1407: 
                   1408:        /* if buff is 0 then set to non-buffered */
                   1409:        if (buff == 0) {
                   1410:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
                   1411:        } else {
                   1412:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_FULL, &buff);
                   1413:        }
                   1414: 
                   1415:        RETURN_LONG(ret == 0 ? 0 : EOF);
                   1416: }
                   1417: /* }}} */
                   1418: 
                   1419: /* {{{ proto int stream_set_read_buffer(resource fp, int buffer)
                   1420:    Set file read buffer */
                   1421: PHP_FUNCTION(stream_set_read_buffer)
                   1422: {
                   1423:        zval *arg1;
                   1424:        int ret;
                   1425:        long arg2;
                   1426:        size_t buff;
                   1427:        php_stream *stream;
                   1428: 
                   1429:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &arg1, &arg2) == FAILURE) {
                   1430:                RETURN_FALSE;
                   1431:        }
                   1432: 
                   1433:        php_stream_from_zval(stream, &arg1);
                   1434: 
                   1435:        buff = arg2;
                   1436: 
                   1437:        /* if buff is 0 then set to non-buffered */
                   1438:        if (buff == 0) {
                   1439:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
                   1440:        } else {
                   1441:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_FULL, &buff);
                   1442:        }
                   1443: 
                   1444:        RETURN_LONG(ret == 0 ? 0 : EOF);
                   1445: }
                   1446: /* }}} */
                   1447: 
                   1448: /* {{{ proto int stream_socket_enable_crypto(resource stream, bool enable [, int cryptokind [, resource sessionstream]])
                   1449:    Enable or disable a specific kind of crypto on the stream */
                   1450: PHP_FUNCTION(stream_socket_enable_crypto)
                   1451: {
                   1452:        long cryptokind = 0;
                   1453:        zval *zstream, *zsessstream = NULL;
                   1454:        php_stream *stream, *sessstream = NULL;
                   1455:        zend_bool enable;
                   1456:        int ret;
                   1457: 
                   1458:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb|lr", &zstream, &enable, &cryptokind, &zsessstream) == FAILURE) {
                   1459:                RETURN_FALSE;
                   1460:        }
                   1461: 
                   1462:        php_stream_from_zval(stream, &zstream);
                   1463: 
                   1464:        if (ZEND_NUM_ARGS() >= 3) {
                   1465:                if (zsessstream) {
                   1466:                        php_stream_from_zval(sessstream, &zsessstream);
                   1467:                }
                   1468: 
                   1469:                if (php_stream_xport_crypto_setup(stream, cryptokind, sessstream TSRMLS_CC) < 0) {
                   1470:                        RETURN_FALSE;
                   1471:                }
                   1472:        } else if (enable) {
                   1473:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "When enabling encryption you must specify the crypto type");
                   1474:                RETURN_FALSE;
                   1475:        }
                   1476: 
                   1477:        ret = php_stream_xport_crypto_enable(stream, enable TSRMLS_CC);
                   1478:        switch (ret) {
                   1479:                case -1:
                   1480:                        RETURN_FALSE;
                   1481: 
                   1482:                case 0:
                   1483:                        RETURN_LONG(0);
                   1484: 
                   1485:                default:
                   1486:                        RETURN_TRUE;
                   1487:        }
                   1488: }
                   1489: /* }}} */
                   1490: 
                   1491: /* {{{ proto string stream_resolve_include_path(string filename)
                   1492: Determine what file will be opened by calls to fopen() with a relative path */
                   1493: PHP_FUNCTION(stream_resolve_include_path)
                   1494: {
                   1495:        char *filename, *resolved_path;
                   1496:        int filename_len;
                   1497: 
                   1498:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
                   1499:                return;
                   1500:        }
                   1501: 
                   1502:        resolved_path = zend_resolve_path(filename, filename_len TSRMLS_CC);
                   1503: 
                   1504:        if (resolved_path) {
                   1505:                RETURN_STRING(resolved_path, 0);
                   1506:        }
                   1507:        RETURN_FALSE;
                   1508: }
                   1509: /* }}} */
                   1510: 
                   1511: /* {{{ proto bool stream_is_local(resource stream|string url) U
                   1512: */
                   1513: PHP_FUNCTION(stream_is_local)
                   1514: {
                   1515:        zval **zstream;
                   1516:        php_stream *stream = NULL;
                   1517:        php_stream_wrapper *wrapper = NULL;
                   1518: 
                   1519:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &zstream) == FAILURE) {
                   1520:                RETURN_FALSE;
                   1521:        }
                   1522: 
                   1523:        if (Z_TYPE_PP(zstream) == IS_RESOURCE) {
                   1524:                php_stream_from_zval(stream, zstream);
                   1525:                if (stream == NULL) {
                   1526:                        RETURN_FALSE;
                   1527:                }
                   1528:                wrapper = stream->wrapper;
                   1529:        } else {
                   1530:                convert_to_string_ex(zstream);
                   1531: 
                   1532:                wrapper = php_stream_locate_url_wrapper(Z_STRVAL_PP(zstream), NULL, 0 TSRMLS_CC);
                   1533:        }
                   1534: 
                   1535:        if (!wrapper) {
                   1536:                RETURN_FALSE;
                   1537:        }
                   1538: 
                   1539:        RETURN_BOOL(wrapper->is_url==0);
                   1540: }
                   1541: /* }}} */
                   1542: 
                   1543: /* {{{ proto bool stream_supports_lock(resource stream)
                   1544:    Tells wether the stream supports locking through flock(). */
                   1545: PHP_FUNCTION(stream_supports_lock)
                   1546: {
                   1547:        php_stream *stream;
                   1548:        zval *zsrc;
                   1549: 
                   1550:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsrc) == FAILURE) {
                   1551:                RETURN_FALSE;
                   1552:        }
                   1553: 
                   1554:        php_stream_from_zval(stream, &zsrc);
                   1555: 
                   1556:        if (!php_stream_supports_lock(stream)) {
                   1557:                RETURN_FALSE;
                   1558:        }
                   1559: 
                   1560:        RETURN_TRUE;
                   1561: }
                   1562: 
                   1563: #ifdef HAVE_SHUTDOWN
                   1564: /* {{{ proto int stream_socket_shutdown(resource stream, int how)
                   1565:        causes all or part of a full-duplex connection on the socket associated
                   1566:        with stream to be shut down.  If how is SHUT_RD,  further receptions will
                   1567:        be disallowed. If how is SHUT_WR, further transmissions will be disallowed.
                   1568:        If how is SHUT_RDWR,  further  receptions and transmissions will be
                   1569:        disallowed. */
                   1570: PHP_FUNCTION(stream_socket_shutdown)
                   1571: {
                   1572:        long how;
                   1573:        zval *zstream;
                   1574:        php_stream *stream;
                   1575: 
                   1576:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zstream, &how) == FAILURE) {
                   1577:                RETURN_FALSE;
                   1578:        }
                   1579: 
                   1580:        if (how != STREAM_SHUT_RD &&
                   1581:            how != STREAM_SHUT_WR &&
                   1582:            how != STREAM_SHUT_RDWR) {
                   1583:                RETURN_FALSE;
                   1584:        }
                   1585: 
                   1586:        php_stream_from_zval(stream, &zstream);
                   1587: 
                   1588:        RETURN_BOOL(php_stream_xport_shutdown(stream, (stream_shutdown_t)how TSRMLS_CC) == 0);
                   1589: }
                   1590: /* }}} */
                   1591: #endif
                   1592: 
                   1593: /*
                   1594:  * Local variables:
                   1595:  * tab-width: 4
                   1596:  * c-basic-offset: 4
                   1597:  * End:
                   1598:  * vim600: noet sw=4 ts=4 fdm=marker
                   1599:  * vim<600: noet sw=4 ts=4
                   1600:  */
                   1601: 

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