Annotation of embedaddon/php/ext/standard/streamsfuncs.c, revision 1.1.1.2

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

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