LTP GCOV extension - code coverage report
Current view: directory - ext/standard - streamsfuncs.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 585
Code covered: 19.7 % Executed lines: 115
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5