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: 581 691 84.1 %
Date: 2016-08-24 Functions: 42 43 97.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 24 Aug 2016 12:20:31 +0000 (3 days ago)

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