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

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:   | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       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;
1.1.1.3   misho      54:        php_socket_t pair[2];
1.1       misho      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:        int cnt = 0;
                    605: 
                    606:        if (Z_TYPE_P(stream_array) != IS_ARRAY) {
                    607:                return 0;
                    608:        }
                    609:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
                    610:                 zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
                    611:                 zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
                    612: 
1.1.1.3   misho     613:                /* Temporary int fd is needed for the STREAM data type on windows, passing this_fd directly to php_stream_cast()
                    614:                        would eventually bring a wrong result on x64. php_stream_cast() casts to int internally, and this will leave
                    615:                        the higher bits of a SOCKET variable uninitialized on systems with little endian. */
                    616:                int tmp_fd;
                    617: 
1.1       misho     618:                php_stream_from_zval_no_verify(stream, elem);
                    619:                if (stream == NULL) {
                    620:                        continue;
                    621:                }
                    622:                /* get the fd.
                    623:                 * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
                    624:                 * when casting.  It is only used here so that the buffered data warning
                    625:                 * is not displayed.
                    626:                 * */
1.1.1.3   misho     627:                if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&tmp_fd, 1) && tmp_fd != -1) {
                    628: 
                    629:                        php_socket_t this_fd = (php_socket_t)tmp_fd;
1.1       misho     630: 
                    631:                        PHP_SAFE_FD_SET(this_fd, fds);
                    632: 
                    633:                        if (this_fd > *max_fd) {
                    634:                                *max_fd = this_fd;
                    635:                        }
                    636:                        cnt++;
                    637:                }
                    638:        }
                    639:        return cnt ? 1 : 0;
                    640: }
                    641: 
                    642: static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC)
                    643: {
                    644:        zval **elem, **dest_elem;
                    645:        php_stream *stream;
                    646:        HashTable *new_hash;
                    647:        int ret = 0;
                    648: 
                    649:        if (Z_TYPE_P(stream_array) != IS_ARRAY) {
                    650:                return 0;
                    651:        }
                    652:        ALLOC_HASHTABLE(new_hash);
                    653:        zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(stream_array)), NULL, ZVAL_PTR_DTOR, 0);
                    654: 
                    655:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
1.1.1.2   misho     656:                 zend_hash_has_more_elements(Z_ARRVAL_P(stream_array)) == SUCCESS;
1.1       misho     657:                 zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
                    658: 
1.1.1.2   misho     659:                int type;
                    660:                char *key;
                    661:                uint key_len;
                    662:                ulong num_ind;
1.1.1.3   misho     663:                /* Temporary int fd is needed for the STREAM data type on windows, passing this_fd directly to php_stream_cast()
                    664:                        would eventually bring a wrong result on x64. php_stream_cast() casts to int internally, and this will leave
                    665:                        the higher bits of a SOCKET variable uninitialized on systems with little endian. */
                    666:                int tmp_fd;
                    667: 
1.1.1.2   misho     668: 
                    669:                type = zend_hash_get_current_key_ex(Z_ARRVAL_P(stream_array),
                    670:                                &key, &key_len, &num_ind, 0, NULL);
                    671:                if (type == HASH_KEY_NON_EXISTANT ||
                    672:                        zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == FAILURE) {
                    673:                        continue; /* should not happen */
                    674:                }
                    675: 
1.1       misho     676:                php_stream_from_zval_no_verify(stream, elem);
                    677:                if (stream == NULL) {
                    678:                        continue;
                    679:                }
                    680:                /* get the fd
                    681:                 * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
                    682:                 * when casting.  It is only used here so that the buffered data warning
                    683:                 * is not displayed.
                    684:                 */
1.1.1.3   misho     685:                if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&tmp_fd, 1) && tmp_fd != -1) {
                    686: 
                    687:                        php_socket_t this_fd = (php_socket_t)tmp_fd;
                    688: 
1.1       misho     689:                        if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
1.1.1.2   misho     690:                                if (type == HASH_KEY_IS_LONG) {
                    691:                                        zend_hash_index_update(new_hash, num_ind, (void *)elem, sizeof(zval *), (void **)&dest_elem);
                    692:                                } else { /* HASH_KEY_IS_STRING */
                    693:                                        zend_hash_update(new_hash, key, key_len, (void *)elem, sizeof(zval *), (void **)&dest_elem);
                    694:                                }
                    695:                                
1.1       misho     696:                                if (dest_elem) {
                    697:                                        zval_add_ref(dest_elem);
                    698:                                }
                    699:                                ret++;
                    700:                                continue;
                    701:                        }
                    702:                }
                    703:        }
                    704: 
                    705:        /* destroy old array and add new one */
                    706:        zend_hash_destroy(Z_ARRVAL_P(stream_array));
                    707:        efree(Z_ARRVAL_P(stream_array));
                    708: 
                    709:        zend_hash_internal_pointer_reset(new_hash);
                    710:        Z_ARRVAL_P(stream_array) = new_hash;
                    711: 
                    712:        return ret;
                    713: }
                    714: 
                    715: static int stream_array_emulate_read_fd_set(zval *stream_array TSRMLS_DC)
                    716: {
                    717:        zval **elem, **dest_elem;
                    718:        php_stream *stream;
                    719:        HashTable *new_hash;
                    720:        int ret = 0;
                    721: 
                    722:        if (Z_TYPE_P(stream_array) != IS_ARRAY) {
                    723:                return 0;
                    724:        }
                    725:        ALLOC_HASHTABLE(new_hash);
                    726:        zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(stream_array)), NULL, ZVAL_PTR_DTOR, 0);
                    727: 
                    728:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
                    729:                 zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
                    730:                 zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
                    731: 
                    732:                php_stream_from_zval_no_verify(stream, elem);
                    733:                if (stream == NULL) {
                    734:                        continue;
                    735:                }
                    736:                if ((stream->writepos - stream->readpos) > 0) {
                    737:                        /* allow readable non-descriptor based streams to participate in stream_select.
                    738:                         * Non-descriptor streams will only "work" if they have previously buffered the
                    739:                         * data.  Not ideal, but better than nothing.
                    740:                         * This branch of code also allows blocking streams with buffered data to
                    741:                         * operate correctly in stream_select.
                    742:                         * */
                    743:                        zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
                    744:                        if (dest_elem) {
                    745:                                zval_add_ref(dest_elem);
                    746:                        }
                    747:                        ret++;
                    748:                        continue;
                    749:                }
                    750:        }
                    751: 
                    752:        if (ret > 0) {
                    753:                /* destroy old array and add new one */
                    754:                zend_hash_destroy(Z_ARRVAL_P(stream_array));
                    755:                efree(Z_ARRVAL_P(stream_array));
                    756: 
                    757:                zend_hash_internal_pointer_reset(new_hash);
                    758:                Z_ARRVAL_P(stream_array) = new_hash;
                    759:        } else {
                    760:                zend_hash_destroy(new_hash);
                    761:                FREE_HASHTABLE(new_hash);
                    762:        }
                    763: 
                    764:        return ret;
                    765: }
                    766: /* }}} */
                    767: 
                    768: /* {{{ proto int stream_select(array &read_streams, array &write_streams, array &except_streams, int tv_sec[, int tv_usec])
                    769:    Runs the select() system call on the sets of streams with a timeout specified by tv_sec and tv_usec */
                    770: PHP_FUNCTION(stream_select)
                    771: {
                    772:        zval                    *r_array, *w_array, *e_array, **sec = NULL;
                    773:        struct timeval  tv;
                    774:        struct timeval *tv_p = NULL;
                    775:        fd_set                  rfds, wfds, efds;
                    776:        php_socket_t    max_fd = 0;
                    777:        int                             retval, sets = 0;
                    778:        long                    usec = 0;
                    779:        int                             set_count, max_set_count = 0;
                    780: 
                    781:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!Z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE)
                    782:                return;
                    783: 
                    784:        FD_ZERO(&rfds);
                    785:        FD_ZERO(&wfds);
                    786:        FD_ZERO(&efds);
                    787: 
                    788:        if (r_array != NULL) {
                    789:                set_count = stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
                    790:                if (set_count > max_set_count)
                    791:                        max_set_count = set_count;
                    792:                sets += set_count;
                    793:        }
                    794: 
                    795:        if (w_array != NULL) {
                    796:                set_count = stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
                    797:                if (set_count > max_set_count)
                    798:                        max_set_count = set_count;
                    799:                sets += set_count;
                    800:        }
                    801: 
                    802:        if (e_array != NULL) {
                    803:                set_count = stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
                    804:                if (set_count > max_set_count)
                    805:                        max_set_count = set_count;
                    806:                sets += set_count;
                    807:        }
                    808: 
                    809:        if (!sets) {
                    810:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed");
                    811:                RETURN_FALSE;
                    812:        }
                    813: 
                    814:        PHP_SAFE_MAX_FD(max_fd, max_set_count);
                    815: 
                    816:        /* If seconds is not set to null, build the timeval, else we wait indefinitely */
                    817:        if (sec != NULL) {
                    818:                convert_to_long_ex(sec);
                    819: 
                    820:                if (Z_LVAL_PP(sec) < 0) {
                    821:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "The seconds parameter must be greater than 0");
                    822:                        RETURN_FALSE;
                    823:                } else if (usec < 0) {
                    824:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "The microseconds parameter must be greater than 0");
                    825:                        RETURN_FALSE;
                    826:                }
                    827: 
                    828:                /* Solaris + BSD do not like microsecond values which are >= 1 sec */
                    829:                if (usec > 999999) {
                    830:                        tv.tv_sec = Z_LVAL_PP(sec) + (usec / 1000000);
                    831:                        tv.tv_usec = usec % 1000000;
                    832:                } else {
                    833:                        tv.tv_sec = Z_LVAL_PP(sec);
                    834:                        tv.tv_usec = usec;
                    835:                }
                    836: 
                    837:                tv_p = &tv;
                    838:        }
                    839: 
                    840:        /* slight hack to support buffered data; if there is data sitting in the
                    841:         * read buffer of any of the streams in the read array, let's pretend
                    842:         * that we selected, but return only the readable sockets */
                    843:        if (r_array != NULL) {
                    844: 
                    845:                retval = stream_array_emulate_read_fd_set(r_array TSRMLS_CC);
                    846:                if (retval > 0) {
                    847:                        if (w_array != NULL) {
                    848:                                zend_hash_clean(Z_ARRVAL_P(w_array));
                    849:                        }
                    850:                        if (e_array != NULL) {
                    851:                                zend_hash_clean(Z_ARRVAL_P(e_array));
                    852:                        }
                    853:                        RETURN_LONG(retval);
                    854:                }
                    855:        }
                    856: 
                    857:        retval = php_select(max_fd+1, &rfds, &wfds, &efds, tv_p);
                    858: 
                    859:        if (retval == -1) {
                    860:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
                    861:                                errno, strerror(errno), max_fd);
                    862:                RETURN_FALSE;
                    863:        }
                    864: 
                    865:        if (r_array != NULL) stream_array_from_fd_set(r_array, &rfds TSRMLS_CC);
                    866:        if (w_array != NULL) stream_array_from_fd_set(w_array, &wfds TSRMLS_CC);
                    867:        if (e_array != NULL) stream_array_from_fd_set(e_array, &efds TSRMLS_CC);
                    868: 
                    869:        RETURN_LONG(retval);
                    870: }
                    871: /* }}} */
                    872: 
                    873: /* {{{ stream_context related functions */
                    874: static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity,
                    875:                char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC)
                    876: {
                    877:        zval *callback = (zval*)context->notifier->ptr;
                    878:        zval *retval = NULL;
                    879:        zval zvs[6];
                    880:        zval *ps[6];
                    881:        zval **ptps[6];
                    882:        int i;
                    883: 
                    884:        for (i = 0; i < 6; i++) {
                    885:                INIT_ZVAL(zvs[i]);
                    886:                ps[i] = &zvs[i];
                    887:                ptps[i] = &ps[i];
                    888:                MAKE_STD_ZVAL(ps[i]);
                    889:        }
                    890: 
                    891:        ZVAL_LONG(ps[0], notifycode);
                    892:        ZVAL_LONG(ps[1], severity);
                    893:        if (xmsg) {
                    894:                ZVAL_STRING(ps[2], xmsg, 1);
                    895:        } else {
                    896:                ZVAL_NULL(ps[2]);
                    897:        }
                    898:        ZVAL_LONG(ps[3], xcode);
                    899:        ZVAL_LONG(ps[4], bytes_sofar);
                    900:        ZVAL_LONG(ps[5], bytes_max);
                    901: 
                    902:        if (FAILURE == call_user_function_ex(EG(function_table), NULL, callback, &retval, 6, ptps, 0, NULL TSRMLS_CC)) {
                    903:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to call user notifier");
                    904:        }
                    905:        for (i = 0; i < 6; i++) {
                    906:                zval_ptr_dtor(&ps[i]);
                    907:        }
                    908:        if (retval) {
                    909:                zval_ptr_dtor(&retval);
                    910:        }
                    911: }
                    912: 
                    913: static void user_space_stream_notifier_dtor(php_stream_notifier *notifier)
                    914: {
                    915:        if (notifier && notifier->ptr) {
                    916:                zval_ptr_dtor((zval **)&(notifier->ptr));
                    917:                notifier->ptr = NULL;
                    918:        }
                    919: }
                    920: 
                    921: static int parse_context_options(php_stream_context *context, zval *options TSRMLS_DC)
                    922: {
                    923:        HashPosition pos, opos;
                    924:        zval **wval, **oval;
                    925:        char *wkey, *okey;
1.1.1.2   misho     926:        uint wkey_len, okey_len;
1.1       misho     927:        int ret = SUCCESS;
                    928:        ulong num_key;
                    929: 
                    930:        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(options), &pos);
                    931:        while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(options), (void**)&wval, &pos)) {
                    932:                if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &wkey, &wkey_len, &num_key, 0, &pos)
                    933:                                && Z_TYPE_PP(wval) == IS_ARRAY) {
                    934: 
                    935:                        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(wval), &opos);
                    936:                        while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(wval), (void**)&oval, &opos)) {
                    937: 
                    938:                                if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_PP(wval), &okey, &okey_len, &num_key, 0, &opos)) {
                    939:                                        php_stream_context_set_option(context, wkey, okey, *oval);
                    940:                                }
                    941:                                zend_hash_move_forward_ex(Z_ARRVAL_PP(wval), &opos);
                    942:                        }
                    943: 
                    944:                } else {
                    945:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "options should have the form [\"wrappername\"][\"optionname\"] = $value");
                    946:                }
                    947:                zend_hash_move_forward_ex(Z_ARRVAL_P(options), &pos);
                    948:        }
                    949: 
                    950:        return ret;
                    951: }
                    952: 
                    953: static int parse_context_params(php_stream_context *context, zval *params TSRMLS_DC)
                    954: {
                    955:        int ret = SUCCESS;
                    956:        zval **tmp;
                    957: 
                    958:        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), "notification", sizeof("notification"), (void**)&tmp)) {
                    959: 
                    960:                if (context->notifier) {
                    961:                        php_stream_notification_free(context->notifier);
                    962:                        context->notifier = NULL;
                    963:                }
                    964: 
                    965:                context->notifier = php_stream_notification_alloc();
                    966:                context->notifier->func = user_space_stream_notifier;
                    967:                context->notifier->ptr = *tmp;
                    968:                Z_ADDREF_P(*tmp);
                    969:                context->notifier->dtor = user_space_stream_notifier_dtor;
                    970:        }
                    971:        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), "options", sizeof("options"), (void**)&tmp)) {
                    972:                if (Z_TYPE_PP(tmp) == IS_ARRAY) {
                    973:                        parse_context_options(context, *tmp TSRMLS_CC);
                    974:                } else {
                    975:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                    976:                }
                    977:        }
                    978: 
                    979:        return ret;
                    980: }
                    981: 
                    982: /* given a zval which is either a stream or a context, return the underlying
                    983:  * stream_context.  If it is a stream that does not have a context assigned, it
                    984:  * will create and assign a context and return that.  */
                    985: static php_stream_context *decode_context_param(zval *contextresource TSRMLS_DC)
                    986: {
                    987:        php_stream_context *context = NULL;
                    988: 
1.1.1.2   misho     989:        context = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 1, php_le_stream_context(TSRMLS_C));
1.1       misho     990:        if (context == NULL) {
                    991:                php_stream *stream;
                    992: 
                    993:                stream = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream);
                    994: 
                    995:                if (stream) {
                    996:                        context = stream->context;
                    997:                        if (context == NULL) {
                    998:                                /* Only way this happens is if file is opened with NO_DEFAULT_CONTEXT
                    999:                                   param, but then something is called which requires a context.
                   1000:                                   Don't give them the default one though since they already said they
                   1001:                                   didn't want it. */
1.1.1.2   misho    1002:                                context = stream->context = php_stream_context_alloc(TSRMLS_C);
1.1       misho    1003:                        }
                   1004:                }
                   1005:        }
                   1006: 
                   1007:        return context;
                   1008: }
                   1009: /* }}} */
                   1010: 
                   1011: /* {{{ proto array stream_context_get_options(resource context|resource stream)
                   1012:    Retrieve options for a stream/wrapper/context */
                   1013: PHP_FUNCTION(stream_context_get_options)
                   1014: {
                   1015:        zval *zcontext;
                   1016:        php_stream_context *context;
                   1017: 
                   1018:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zcontext) == FAILURE) {
                   1019:                RETURN_FALSE;
                   1020:        }
                   1021:        context = decode_context_param(zcontext TSRMLS_CC);
                   1022:        if (!context) {
                   1023:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1024:                RETURN_FALSE;
                   1025:        }
                   1026: 
                   1027:        RETURN_ZVAL(context->options, 1, 0);
                   1028: }
                   1029: /* }}} */
                   1030: 
                   1031: /* {{{ proto bool stream_context_set_option(resource context|resource stream, string wrappername, string optionname, mixed value)
                   1032:    Set an option for a wrapper */
                   1033: PHP_FUNCTION(stream_context_set_option)
                   1034: {
                   1035:        zval *options = NULL, *zcontext = NULL, *zvalue = NULL;
                   1036:        php_stream_context *context;
                   1037:        char *wrappername, *optionname;
                   1038:        int wrapperlen, optionlen;
                   1039: 
                   1040:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
                   1041:                                "rssz", &zcontext, &wrappername, &wrapperlen,
                   1042:                                &optionname, &optionlen, &zvalue) == FAILURE) {
                   1043:                if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
                   1044:                                        "ra", &zcontext, &options) == FAILURE) {
                   1045:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "called with wrong number or type of parameters; please RTM");
                   1046:                        RETURN_FALSE;
                   1047:                }
                   1048:        }
                   1049: 
                   1050:        /* figure out where the context is coming from exactly */
                   1051:        context = decode_context_param(zcontext TSRMLS_CC);
                   1052:        if (!context) {
                   1053:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1054:                RETURN_FALSE;
                   1055:        }
                   1056: 
                   1057:        if (options) {
                   1058:                /* handle the array syntax */
                   1059:                RETVAL_BOOL(parse_context_options(context, options TSRMLS_CC) == SUCCESS);
                   1060:        } else {
                   1061:                php_stream_context_set_option(context, wrappername, optionname, zvalue);
                   1062:                RETVAL_TRUE;
                   1063:        }
                   1064: }
                   1065: /* }}} */
                   1066: 
                   1067: /* {{{ proto bool stream_context_set_params(resource context|resource stream, array options)
                   1068:    Set parameters for a file context */
                   1069: PHP_FUNCTION(stream_context_set_params)
                   1070: {
                   1071:        zval *params, *zcontext;
                   1072:        php_stream_context *context;
                   1073: 
                   1074:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra", &zcontext, &params) == FAILURE) {
                   1075:                RETURN_FALSE;
                   1076:        }
                   1077: 
                   1078:        context = decode_context_param(zcontext TSRMLS_CC);
                   1079:        if (!context) {
                   1080:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1081:                RETURN_FALSE;
                   1082:        }
                   1083: 
                   1084:        RETVAL_BOOL(parse_context_params(context, params TSRMLS_CC) == SUCCESS);
                   1085: }
                   1086: /* }}} */
                   1087: 
                   1088: /* {{{ proto array stream_context_get_params(resource context|resource stream)
                   1089:    Get parameters of a file context */
                   1090: PHP_FUNCTION(stream_context_get_params)
                   1091: {
                   1092:        zval *zcontext, *options;
                   1093:        php_stream_context *context;
                   1094: 
                   1095:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zcontext) == FAILURE) {
                   1096:                RETURN_FALSE;
                   1097:        }
                   1098: 
                   1099:        context = decode_context_param(zcontext TSRMLS_CC);
                   1100:        if (!context) {
                   1101:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream/context parameter");
                   1102:                RETURN_FALSE;
                   1103:        }
                   1104: 
                   1105:        array_init(return_value);
                   1106:        if (context->notifier && context->notifier->ptr && context->notifier->func == user_space_stream_notifier) {
                   1107:                add_assoc_zval_ex(return_value, ZEND_STRS("notification"), context->notifier->ptr);
                   1108:                Z_ADDREF_P(context->notifier->ptr);
                   1109:        }
                   1110:        ALLOC_INIT_ZVAL(options);
                   1111:        ZVAL_ZVAL(options, context->options, 1, 0);
                   1112:        add_assoc_zval_ex(return_value, ZEND_STRS("options"), options);
                   1113: }
                   1114: /* }}} */
                   1115: 
                   1116: /* {{{ proto resource stream_context_get_default([array options])
                   1117:    Get a handle on the default file/stream context and optionally set parameters */
                   1118: PHP_FUNCTION(stream_context_get_default)
                   1119: {
                   1120:        zval *params = NULL;
                   1121:        php_stream_context *context;
                   1122: 
                   1123:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &params) == FAILURE) {
                   1124:                RETURN_FALSE;
                   1125:        }
                   1126: 
                   1127:        if (FG(default_context) == NULL) {
1.1.1.2   misho    1128:                FG(default_context) = php_stream_context_alloc(TSRMLS_C);
1.1       misho    1129:        }
                   1130:        context = FG(default_context);
                   1131: 
                   1132:        if (params) {
                   1133:                parse_context_options(context, params TSRMLS_CC);
                   1134:        }
                   1135: 
                   1136:        php_stream_context_to_zval(context, return_value);
                   1137: }
                   1138: /* }}} */
                   1139: 
                   1140: /* {{{ proto resource stream_context_set_default(array options)
                   1141:    Set default file/stream context, returns the context as a resource */
                   1142: PHP_FUNCTION(stream_context_set_default)
                   1143: {
                   1144:        zval *options = NULL;
                   1145:        php_stream_context *context;
                   1146: 
                   1147:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &options) == FAILURE) {
                   1148:                return;
                   1149:        }
                   1150: 
                   1151:        if (FG(default_context) == NULL) {
1.1.1.2   misho    1152:                FG(default_context) = php_stream_context_alloc(TSRMLS_C);
1.1       misho    1153:        }
                   1154:        context = FG(default_context);
                   1155: 
                   1156:        parse_context_options(context, options TSRMLS_CC);
                   1157: 
                   1158:        php_stream_context_to_zval(context, return_value);
                   1159: }
                   1160: /* }}} */
                   1161: 
                   1162: /* {{{ proto resource stream_context_create([array options[, array params]])
                   1163:    Create a file context and optionally set parameters */
                   1164: PHP_FUNCTION(stream_context_create)
                   1165: {
                   1166:        zval *options = NULL, *params = NULL;
                   1167:        php_stream_context *context;
                   1168: 
                   1169:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!a!", &options, &params) == FAILURE) {
                   1170:                RETURN_FALSE;
                   1171:        }
                   1172: 
1.1.1.2   misho    1173:        context = php_stream_context_alloc(TSRMLS_C);
1.1       misho    1174: 
                   1175:        if (options) {
                   1176:                parse_context_options(context, options TSRMLS_CC);
                   1177:        }
                   1178: 
                   1179:        if (params) {
                   1180:                parse_context_params(context, params TSRMLS_CC);
                   1181:        }
                   1182: 
                   1183:        RETURN_RESOURCE(context->rsrc_id);
                   1184: }
                   1185: /* }}} */
                   1186: 
                   1187: /* {{{ streams filter functions */
                   1188: static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS)
                   1189: {
                   1190:        zval *zstream;
                   1191:        php_stream *stream;
                   1192:        char *filtername;
                   1193:        int filternamelen;
                   1194:        long read_write = 0;
                   1195:        zval *filterparams = NULL;
                   1196:        php_stream_filter *filter = NULL;
                   1197:        int ret;
                   1198: 
                   1199:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz", &zstream,
                   1200:                                &filtername, &filternamelen, &read_write, &filterparams) == FAILURE) {
                   1201:                RETURN_FALSE;
                   1202:        }
                   1203: 
                   1204:        php_stream_from_zval(stream, &zstream);
                   1205: 
                   1206:        if ((read_write & PHP_STREAM_FILTER_ALL) == 0) {
                   1207:                /* Chain not specified.
                   1208:                 * Examine stream->mode to determine which filters are needed
                   1209:                 * There's no harm in attaching a filter to an unused chain,
                   1210:                 * but why waste the memory and clock cycles?
                   1211:                 */
                   1212:                if (strchr(stream->mode, 'r') || strchr(stream->mode, '+')) {
                   1213:                        read_write |= PHP_STREAM_FILTER_READ;
                   1214:                }
                   1215:                if (strchr(stream->mode, 'w') || strchr(stream->mode, '+') || strchr(stream->mode, 'a')) {
                   1216:                        read_write |= PHP_STREAM_FILTER_WRITE;
                   1217:                }
                   1218:        }
                   1219: 
                   1220:        if (read_write & PHP_STREAM_FILTER_READ) {
                   1221:                filter = php_stream_filter_create(filtername, filterparams, php_stream_is_persistent(stream) TSRMLS_CC);
                   1222:                if (filter == NULL) {
                   1223:                        RETURN_FALSE;
                   1224:                }
                   1225: 
                   1226:                if (append) {
                   1227:                        ret = php_stream_filter_append_ex(&stream->readfilters, filter TSRMLS_CC);
                   1228:                } else {
                   1229:                        ret = php_stream_filter_prepend_ex(&stream->readfilters, filter TSRMLS_CC);
                   1230:                }
                   1231:                if (ret != SUCCESS) {
                   1232:                        php_stream_filter_remove(filter, 1 TSRMLS_CC);
                   1233:                        RETURN_FALSE;
                   1234:                }
                   1235:        }
                   1236: 
                   1237:        if (read_write & PHP_STREAM_FILTER_WRITE) {
                   1238:                filter = php_stream_filter_create(filtername, filterparams, php_stream_is_persistent(stream) TSRMLS_CC);
                   1239:                if (filter == NULL) {
                   1240:                        RETURN_FALSE;
                   1241:                }
                   1242: 
                   1243:                if (append) {
                   1244:                        ret = php_stream_filter_append_ex(&stream->writefilters, filter TSRMLS_CC);
                   1245:                } else {
                   1246:                        ret = php_stream_filter_prepend_ex(&stream->writefilters, filter TSRMLS_CC);
                   1247:                }
                   1248:                if (ret != SUCCESS) {
                   1249:                        php_stream_filter_remove(filter, 1 TSRMLS_CC);
                   1250:                        RETURN_FALSE;
                   1251:                }
                   1252:        }
                   1253: 
                   1254:        if (filter) {
                   1255:                RETURN_RESOURCE(filter->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, filter, php_file_le_stream_filter()));
                   1256:        } else {
                   1257:                RETURN_FALSE;
                   1258:        }
                   1259: }
                   1260: /* }}} */
                   1261: 
                   1262: /* {{{ proto resource stream_filter_prepend(resource stream, string filtername[, int read_write[, string filterparams]])
                   1263:    Prepend a filter to a stream */
                   1264: PHP_FUNCTION(stream_filter_prepend)
                   1265: {
                   1266:        apply_filter_to_stream(0, INTERNAL_FUNCTION_PARAM_PASSTHRU);
                   1267: }
                   1268: /* }}} */
                   1269: 
                   1270: /* {{{ proto resource stream_filter_append(resource stream, string filtername[, int read_write[, string filterparams]])
                   1271:    Append a filter to a stream */
                   1272: PHP_FUNCTION(stream_filter_append)
                   1273: {
                   1274:        apply_filter_to_stream(1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
                   1275: }
                   1276: /* }}} */
                   1277: 
                   1278: /* {{{ proto bool stream_filter_remove(resource stream_filter)
                   1279:        Flushes any data in the filter's internal buffer, removes it from the chain, and frees the resource */
                   1280: PHP_FUNCTION(stream_filter_remove)
                   1281: {
                   1282:        zval *zfilter;
                   1283:        php_stream_filter *filter;
                   1284: 
                   1285:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zfilter) == FAILURE) {
                   1286:                RETURN_FALSE;
                   1287:        }
                   1288: 
                   1289:        filter = zend_fetch_resource(&zfilter TSRMLS_CC, -1, NULL, NULL, 1, php_file_le_stream_filter());
                   1290:        if (!filter) {
                   1291:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid resource given, not a stream filter");
                   1292:                RETURN_FALSE;
                   1293:        }
                   1294: 
                   1295:        if (php_stream_filter_flush(filter, 1) == FAILURE) {
                   1296:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to flush filter, not removing");
                   1297:                RETURN_FALSE;
                   1298:        }
                   1299: 
                   1300:        if (zend_list_delete(Z_LVAL_P(zfilter)) == FAILURE) {
                   1301:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not invalidate filter, not removing");
                   1302:                RETURN_FALSE;
                   1303:        } else {
                   1304:                php_stream_filter_remove(filter, 1 TSRMLS_CC);
                   1305:                RETURN_TRUE;
                   1306:        }
                   1307: }
                   1308: /* }}} */
                   1309: 
                   1310: /* {{{ proto string stream_get_line(resource stream, int maxlen [, string ending])
                   1311:    Read up to maxlen bytes from a stream or until the ending string is found */
                   1312: PHP_FUNCTION(stream_get_line)
                   1313: {
                   1314:        char *str = NULL;
                   1315:        int str_len = 0;
                   1316:        long max_length;
                   1317:        zval *zstream;
                   1318:        char *buf;
                   1319:        size_t buf_size;
                   1320:        php_stream *stream;
                   1321: 
                   1322:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|s", &zstream, &max_length, &str, &str_len) == FAILURE) {
                   1323:                RETURN_FALSE;
                   1324:        }
                   1325: 
                   1326:        if (max_length < 0) {
                   1327:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The maximum allowed length must be greater than or equal to zero");
                   1328:                RETURN_FALSE;
                   1329:        }
                   1330:        if (!max_length) {
                   1331:                max_length = PHP_SOCK_CHUNK_SIZE;
                   1332:        }
                   1333: 
                   1334:        php_stream_from_zval(stream, &zstream);
                   1335: 
                   1336:        if ((buf = php_stream_get_record(stream, max_length, &buf_size, str, str_len TSRMLS_CC))) {
                   1337:                RETURN_STRINGL(buf, buf_size, 0);
                   1338:        } else {
                   1339:                RETURN_FALSE;
                   1340:        }
                   1341: }
                   1342: 
                   1343: /* }}} */
                   1344: 
                   1345: /* {{{ proto bool stream_set_blocking(resource socket, int mode)
                   1346:    Set blocking/non-blocking mode on a socket or stream */
                   1347: PHP_FUNCTION(stream_set_blocking)
                   1348: {
                   1349:        zval *arg1;
                   1350:        int block;
                   1351:        long arg2;
                   1352:        php_stream *stream;
                   1353: 
                   1354:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &arg1, &arg2) == FAILURE) {
                   1355:                return;
                   1356:        }
                   1357: 
                   1358:        php_stream_from_zval(stream, &arg1);
                   1359: 
                   1360:        block = arg2;
                   1361: 
                   1362:        if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, block == 0 ? 0 : 1, NULL) == -1) {
                   1363:                RETURN_FALSE;
                   1364:        }
                   1365: 
                   1366:        RETURN_TRUE;
                   1367: }
                   1368: 
                   1369: /* }}} */
                   1370: 
                   1371: /* {{{ proto bool stream_set_timeout(resource stream, int seconds [, int microseconds])
                   1372:    Set timeout on stream read to seconds + microseonds */
                   1373: #if HAVE_SYS_TIME_H || defined(PHP_WIN32)
                   1374: PHP_FUNCTION(stream_set_timeout)
                   1375: {
                   1376:        zval *socket;
                   1377:        long seconds, microseconds = 0;
                   1378:        struct timeval t;
                   1379:        php_stream *stream;
                   1380:        int argc = ZEND_NUM_ARGS();
                   1381: 
                   1382:        if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &socket, &seconds, &microseconds) == FAILURE) {
                   1383:                return;
                   1384:        }
                   1385: 
                   1386:        php_stream_from_zval(stream, &socket);
                   1387: 
                   1388:        t.tv_sec = seconds;
                   1389: 
                   1390:        if (argc == 3) {
                   1391:                t.tv_usec = microseconds % 1000000;
                   1392:                t.tv_sec += microseconds / 1000000;
                   1393:        } else {
                   1394:                t.tv_usec = 0;
                   1395:        }
                   1396: 
                   1397:        if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &t)) {
                   1398:                RETURN_TRUE;
                   1399:        }
                   1400: 
                   1401:        RETURN_FALSE;
                   1402: }
                   1403: #endif /* HAVE_SYS_TIME_H || defined(PHP_WIN32) */
                   1404: /* }}} */
                   1405: 
                   1406: /* {{{ proto int stream_set_write_buffer(resource fp, int buffer)
                   1407:    Set file write buffer */
                   1408: PHP_FUNCTION(stream_set_write_buffer)
                   1409: {
                   1410:        zval *arg1;
                   1411:        int ret;
                   1412:        long arg2;
                   1413:        size_t buff;
                   1414:        php_stream *stream;
                   1415: 
                   1416:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &arg1, &arg2) == FAILURE) {
                   1417:                RETURN_FALSE;
                   1418:        }
                   1419: 
                   1420:        php_stream_from_zval(stream, &arg1);
                   1421: 
                   1422:        buff = arg2;
                   1423: 
                   1424:        /* if buff is 0 then set to non-buffered */
                   1425:        if (buff == 0) {
                   1426:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
                   1427:        } else {
                   1428:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_FULL, &buff);
                   1429:        }
                   1430: 
                   1431:        RETURN_LONG(ret == 0 ? 0 : EOF);
                   1432: }
                   1433: /* }}} */
                   1434: 
1.1.1.2   misho    1435: /* {{{ proto int stream_set_chunk_size(resource fp, int chunk_size)
                   1436:    Set the stream chunk size */
                   1437: PHP_FUNCTION(stream_set_chunk_size)
                   1438: {
                   1439:        int                     ret;
                   1440:        long            csize;
                   1441:        zval            *zstream;
                   1442:        php_stream      *stream;
                   1443: 
                   1444:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zstream, &csize) == FAILURE) {
                   1445:                RETURN_FALSE;
                   1446:        }
                   1447: 
                   1448:        if (csize <= 0) {
                   1449:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The chunk size must be a positive integer, given %ld", csize);
                   1450:                RETURN_FALSE;
                   1451:        }
                   1452:        /* stream.chunk_size is actually a size_t, but php_stream_set_option 
                   1453:         * can only use an int to accept the new value and return the old one.
                   1454:         * In any case, values larger than INT_MAX for a chunk size make no sense.
                   1455:         */
                   1456:        if (csize > INT_MAX) {
                   1457:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The chunk size cannot be larger than %d", INT_MAX);
                   1458:                RETURN_FALSE;
                   1459:        }
                   1460:        
                   1461:        php_stream_from_zval(stream, &zstream);
                   1462: 
                   1463:        ret = php_stream_set_option(stream, PHP_STREAM_OPTION_SET_CHUNK_SIZE, (int)csize, NULL);
                   1464:        
                   1465:        RETURN_LONG(ret > 0 ? (long)ret : (long)EOF);
                   1466: }
                   1467: /* }}} */
                   1468: 
1.1       misho    1469: /* {{{ proto int stream_set_read_buffer(resource fp, int buffer)
                   1470:    Set file read buffer */
                   1471: PHP_FUNCTION(stream_set_read_buffer)
                   1472: {
                   1473:        zval *arg1;
                   1474:        int ret;
                   1475:        long arg2;
                   1476:        size_t buff;
                   1477:        php_stream *stream;
                   1478: 
                   1479:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &arg1, &arg2) == FAILURE) {
                   1480:                RETURN_FALSE;
                   1481:        }
                   1482: 
                   1483:        php_stream_from_zval(stream, &arg1);
                   1484: 
                   1485:        buff = arg2;
                   1486: 
                   1487:        /* if buff is 0 then set to non-buffered */
                   1488:        if (buff == 0) {
                   1489:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
                   1490:        } else {
                   1491:                ret = php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_FULL, &buff);
                   1492:        }
                   1493: 
                   1494:        RETURN_LONG(ret == 0 ? 0 : EOF);
                   1495: }
                   1496: /* }}} */
                   1497: 
                   1498: /* {{{ proto int stream_socket_enable_crypto(resource stream, bool enable [, int cryptokind [, resource sessionstream]])
                   1499:    Enable or disable a specific kind of crypto on the stream */
                   1500: PHP_FUNCTION(stream_socket_enable_crypto)
                   1501: {
                   1502:        long cryptokind = 0;
                   1503:        zval *zstream, *zsessstream = NULL;
                   1504:        php_stream *stream, *sessstream = NULL;
                   1505:        zend_bool enable;
                   1506:        int ret;
                   1507: 
                   1508:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb|lr", &zstream, &enable, &cryptokind, &zsessstream) == FAILURE) {
                   1509:                RETURN_FALSE;
                   1510:        }
                   1511: 
                   1512:        php_stream_from_zval(stream, &zstream);
                   1513: 
                   1514:        if (ZEND_NUM_ARGS() >= 3) {
                   1515:                if (zsessstream) {
                   1516:                        php_stream_from_zval(sessstream, &zsessstream);
                   1517:                }
                   1518: 
                   1519:                if (php_stream_xport_crypto_setup(stream, cryptokind, sessstream TSRMLS_CC) < 0) {
                   1520:                        RETURN_FALSE;
                   1521:                }
                   1522:        } else if (enable) {
                   1523:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "When enabling encryption you must specify the crypto type");
                   1524:                RETURN_FALSE;
                   1525:        }
                   1526: 
                   1527:        ret = php_stream_xport_crypto_enable(stream, enable TSRMLS_CC);
                   1528:        switch (ret) {
                   1529:                case -1:
                   1530:                        RETURN_FALSE;
                   1531: 
                   1532:                case 0:
                   1533:                        RETURN_LONG(0);
                   1534: 
                   1535:                default:
                   1536:                        RETURN_TRUE;
                   1537:        }
                   1538: }
                   1539: /* }}} */
                   1540: 
                   1541: /* {{{ proto string stream_resolve_include_path(string filename)
                   1542: Determine what file will be opened by calls to fopen() with a relative path */
                   1543: PHP_FUNCTION(stream_resolve_include_path)
                   1544: {
                   1545:        char *filename, *resolved_path;
                   1546:        int filename_len;
                   1547: 
                   1548:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
                   1549:                return;
                   1550:        }
                   1551: 
                   1552:        resolved_path = zend_resolve_path(filename, filename_len TSRMLS_CC);
                   1553: 
                   1554:        if (resolved_path) {
                   1555:                RETURN_STRING(resolved_path, 0);
                   1556:        }
                   1557:        RETURN_FALSE;
                   1558: }
                   1559: /* }}} */
                   1560: 
                   1561: /* {{{ proto bool stream_is_local(resource stream|string url) U
                   1562: */
                   1563: PHP_FUNCTION(stream_is_local)
                   1564: {
                   1565:        zval **zstream;
                   1566:        php_stream *stream = NULL;
                   1567:        php_stream_wrapper *wrapper = NULL;
                   1568: 
                   1569:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &zstream) == FAILURE) {
                   1570:                RETURN_FALSE;
                   1571:        }
                   1572: 
                   1573:        if (Z_TYPE_PP(zstream) == IS_RESOURCE) {
                   1574:                php_stream_from_zval(stream, zstream);
                   1575:                if (stream == NULL) {
                   1576:                        RETURN_FALSE;
                   1577:                }
                   1578:                wrapper = stream->wrapper;
                   1579:        } else {
                   1580:                convert_to_string_ex(zstream);
                   1581: 
                   1582:                wrapper = php_stream_locate_url_wrapper(Z_STRVAL_PP(zstream), NULL, 0 TSRMLS_CC);
                   1583:        }
                   1584: 
                   1585:        if (!wrapper) {
                   1586:                RETURN_FALSE;
                   1587:        }
                   1588: 
                   1589:        RETURN_BOOL(wrapper->is_url==0);
                   1590: }
                   1591: /* }}} */
                   1592: 
                   1593: /* {{{ proto bool stream_supports_lock(resource stream)
1.1.1.3   misho    1594:    Tells whether the stream supports locking through flock(). */
1.1       misho    1595: PHP_FUNCTION(stream_supports_lock)
                   1596: {
                   1597:        php_stream *stream;
                   1598:        zval *zsrc;
                   1599: 
                   1600:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsrc) == FAILURE) {
                   1601:                RETURN_FALSE;
                   1602:        }
                   1603: 
                   1604:        php_stream_from_zval(stream, &zsrc);
                   1605: 
                   1606:        if (!php_stream_supports_lock(stream)) {
                   1607:                RETURN_FALSE;
                   1608:        }
                   1609: 
                   1610:        RETURN_TRUE;
                   1611: }
                   1612: 
                   1613: #ifdef HAVE_SHUTDOWN
                   1614: /* {{{ proto int stream_socket_shutdown(resource stream, int how)
                   1615:        causes all or part of a full-duplex connection on the socket associated
                   1616:        with stream to be shut down.  If how is SHUT_RD,  further receptions will
                   1617:        be disallowed. If how is SHUT_WR, further transmissions will be disallowed.
                   1618:        If how is SHUT_RDWR,  further  receptions and transmissions will be
                   1619:        disallowed. */
                   1620: PHP_FUNCTION(stream_socket_shutdown)
                   1621: {
                   1622:        long how;
                   1623:        zval *zstream;
                   1624:        php_stream *stream;
                   1625: 
                   1626:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zstream, &how) == FAILURE) {
                   1627:                RETURN_FALSE;
                   1628:        }
                   1629: 
                   1630:        if (how != STREAM_SHUT_RD &&
                   1631:            how != STREAM_SHUT_WR &&
                   1632:            how != STREAM_SHUT_RDWR) {
                   1633:                RETURN_FALSE;
                   1634:        }
                   1635: 
                   1636:        php_stream_from_zval(stream, &zstream);
                   1637: 
                   1638:        RETURN_BOOL(php_stream_xport_shutdown(stream, (stream_shutdown_t)how TSRMLS_CC) == 0);
                   1639: }
                   1640: /* }}} */
                   1641: #endif
                   1642: 
                   1643: /*
                   1644:  * Local variables:
                   1645:  * tab-width: 4
                   1646:  * c-basic-offset: 4
                   1647:  * End:
                   1648:  * vim600: noet sw=4 ts=4 fdm=marker
                   1649:  * vim<600: noet sw=4 ts=4
                   1650:  */
                   1651: 

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