PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/standard - streamsfuncs.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 509 669 76.1 %
Date: 2014-10-14 Functions: 39 43 90.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 14 Oct 2014 07:25:50 +0000 (6 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.