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: 529 698 75.8 %
Date: 2014-09-13 Functions: 39 43 90.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 13 Sep 2014 16:24:35 +0000 (6 days ago)

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