LTP GCOV extension - code coverage report
Current view: directory - main/streams - userspace.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 561
Code covered: 2.1 % Executed lines: 12
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: userspace.c,v 1.31.2.3.2.4 2007/02/13 19:50:59 tony2001 Exp $ */
      21                 : 
      22                 : #include "php.h"
      23                 : #include "php_globals.h"
      24                 : #include "ext/standard/file.h"
      25                 : 
      26                 : static int le_protocols;
      27                 : 
      28                 : struct php_user_stream_wrapper {
      29                 :         char * protoname;
      30                 :         char * classname;
      31                 :         zend_class_entry *ce;
      32                 :         php_stream_wrapper wrapper;
      33                 : };
      34                 : 
      35                 : static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
      36                 : static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);
      37                 : static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
      38                 : static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
      39                 : static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC);
      40                 : static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
      41                 : static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filename, char *mode,
      42                 :                 int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
      43                 : 
      44                 : static php_stream_wrapper_ops user_stream_wops = {
      45                 :         user_wrapper_opener,
      46                 :         NULL, /* close - the streams themselves know how */
      47                 :         NULL, /* stat - the streams themselves know how */
      48                 :         user_wrapper_stat_url,
      49                 :         user_wrapper_opendir,
      50                 :         "user-space",
      51                 :         user_wrapper_unlink,
      52                 :         user_wrapper_rename,
      53                 :         user_wrapper_mkdir,
      54                 :         user_wrapper_rmdir
      55                 : };
      56                 : 
      57                 : 
      58                 : static void stream_wrapper_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
      59               0 : {
      60               0 :         struct php_user_stream_wrapper * uwrap = (struct php_user_stream_wrapper*)rsrc->ptr;
      61                 : 
      62               0 :         efree(uwrap->protoname);
      63               0 :         efree(uwrap->classname);
      64               0 :         efree(uwrap);
      65               0 : }
      66                 : 
      67                 : 
      68                 : PHP_MINIT_FUNCTION(user_streams)
      69             220 : {
      70             220 :         le_protocols = zend_register_list_destructors_ex(stream_wrapper_dtor, NULL, "stream factory", 0);
      71             220 :         if (le_protocols == FAILURE)
      72               0 :                 return FAILURE;
      73                 : 
      74             220 :         REGISTER_LONG_CONSTANT("STREAM_USE_PATH",                     USE_PATH, CONST_CS|CONST_PERSISTENT);
      75             220 :         REGISTER_LONG_CONSTANT("STREAM_IGNORE_URL",           IGNORE_URL, CONST_CS|CONST_PERSISTENT);
      76             220 :         REGISTER_LONG_CONSTANT("STREAM_ENFORCE_SAFE_MODE",    ENFORCE_SAFE_MODE, CONST_CS|CONST_PERSISTENT);
      77             220 :         REGISTER_LONG_CONSTANT("STREAM_REPORT_ERRORS",                REPORT_ERRORS, CONST_CS|CONST_PERSISTENT);
      78             220 :         REGISTER_LONG_CONSTANT("STREAM_MUST_SEEK",                    STREAM_MUST_SEEK, CONST_CS|CONST_PERSISTENT);
      79                 : 
      80             220 :         REGISTER_LONG_CONSTANT("STREAM_URL_STAT_LINK",                PHP_STREAM_URL_STAT_LINK,               CONST_CS|CONST_PERSISTENT);
      81             220 :         REGISTER_LONG_CONSTANT("STREAM_URL_STAT_QUIET",       PHP_STREAM_URL_STAT_QUIET,              CONST_CS|CONST_PERSISTENT);
      82             220 :         REGISTER_LONG_CONSTANT("STREAM_MKDIR_RECURSIVE",      PHP_STREAM_MKDIR_RECURSIVE,             CONST_CS|CONST_PERSISTENT);
      83                 : 
      84             220 :         return SUCCESS;
      85                 : }
      86                 : 
      87                 : struct _php_userstream_data {
      88                 :         struct php_user_stream_wrapper * wrapper;
      89                 :         zval * object;
      90                 : };
      91                 : typedef struct _php_userstream_data php_userstream_data_t;
      92                 : 
      93                 : /* names of methods */
      94                 : #define USERSTREAM_OPEN         "stream_open"
      95                 : #define USERSTREAM_CLOSE        "stream_close"
      96                 : #define USERSTREAM_READ         "stream_read"
      97                 : #define USERSTREAM_WRITE        "stream_write"
      98                 : #define USERSTREAM_FLUSH        "stream_flush"
      99                 : #define USERSTREAM_SEEK         "stream_seek"
     100                 : #define USERSTREAM_TELL         "stream_tell"
     101                 : #define USERSTREAM_EOF          "stream_eof"
     102                 : #define USERSTREAM_STAT         "stream_stat"
     103                 : #define USERSTREAM_STATURL      "url_stat"
     104                 : #define USERSTREAM_UNLINK       "unlink"
     105                 : #define USERSTREAM_RENAME       "rename"
     106                 : #define USERSTREAM_MKDIR        "mkdir"
     107                 : #define USERSTREAM_RMDIR        "rmdir"
     108                 : #define USERSTREAM_DIR_OPEN             "dir_opendir"
     109                 : #define USERSTREAM_DIR_READ             "dir_readdir"
     110                 : #define USERSTREAM_DIR_REWIND   "dir_rewinddir"
     111                 : #define USERSTREAM_DIR_CLOSE    "dir_closedir"
     112                 : #define USERSTREAM_LOCK     "stream_lock"
     113                 : 
     114                 : /* {{{ class should have methods like these:
     115                 :  
     116                 :         function stream_open($path, $mode, $options, &$opened_path)
     117                 :         {
     118                 :                 return true/false;
     119                 :         }
     120                 :         
     121                 :         function stream_read($count)
     122                 :         {
     123                 :                 return false on error;
     124                 :                 else return string;
     125                 :         }
     126                 :         
     127                 :         function stream_write($data)
     128                 :         {
     129                 :                 return false on error;
     130                 :                 else return count written;
     131                 :         }
     132                 :         
     133                 :         function stream_close()
     134                 :         {
     135                 :         }
     136                 :         
     137                 :         function stream_flush()
     138                 :         {
     139                 :                 return true/false;
     140                 :         }
     141                 :         
     142                 :         function stream_seek($offset, $whence)
     143                 :         {
     144                 :                 return true/false;
     145                 :         }
     146                 : 
     147                 :         function stream_tell()
     148                 :         {
     149                 :                 return (int)$position;
     150                 :         }
     151                 : 
     152                 :         function stream_eof()
     153                 :         {
     154                 :                 return true/false;
     155                 :         }
     156                 : 
     157                 :         function stream_stat()
     158                 :         {
     159                 :                 return array( just like that returned by fstat() );
     160                 :         }
     161                 : 
     162                 :         function url_stat(string $url, int $flags)
     163                 :         {
     164                 :                 return array( just like that returned by stat() );
     165                 :         }
     166                 : 
     167                 :         function unlink(string $url)
     168                 :         {
     169                 :                 return true / false;
     170                 :         }
     171                 : 
     172                 :         function rename(string $from, string $to)
     173                 :         {
     174                 :                 return true / false;
     175                 :         }
     176                 : 
     177                 :         function mkdir($dir, $mode, $options)
     178                 :         {
     179                 :                 return true / false;
     180                 :         }
     181                 : 
     182                 :         function rmdir($dir, $options)
     183                 :         {
     184                 :                 return true / false;
     185                 :         }
     186                 : 
     187                 :         function dir_opendir(string $url, int $options)
     188                 :         {
     189                 :                 return true / false;
     190                 :         }
     191                 : 
     192                 :         function dir_readdir()
     193                 :         {
     194                 :                 return string next filename in dir ;
     195                 :         }
     196                 : 
     197                 :         function dir_closedir()
     198                 :         {
     199                 :                 release dir related resources;
     200                 :         }
     201                 : 
     202                 :         function dir_rewinddir()
     203                 :         {
     204                 :                 reset to start of dir list;
     205                 :         }
     206                 :   
     207                 :         }}} **/
     208                 : 
     209                 : static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
     210               0 : {
     211               0 :         struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
     212                 :         php_userstream_data_t *us;
     213               0 :         zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
     214                 :         zval **args[4]; 
     215                 :         int call_result;
     216               0 :         php_stream *stream = NULL;
     217               0 :         zval *zcontext = NULL;
     218                 : 
     219                 :         /* Try to catch bad usage without preventing flexibility */
     220               0 :         if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
     221               0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
     222               0 :                 return NULL;
     223                 :         }
     224               0 :         FG(user_stream_current_filename) = filename;
     225                 :         
     226               0 :         us = emalloc(sizeof(*us));
     227               0 :         us->wrapper = uwrap; 
     228                 : 
     229                 :         /* create an instance of our class */
     230               0 :         ALLOC_ZVAL(us->object);
     231               0 :         object_init_ex(us->object, uwrap->ce);
     232               0 :         ZVAL_REFCOUNT(us->object) = 1;
     233               0 :         PZVAL_IS_REF(us->object) = 1;
     234                 :         
     235               0 :         if (uwrap->ce->constructor) {
     236                 :                 zend_fcall_info fci;
     237                 :                 zend_fcall_info_cache fcc;
     238                 :                 zval *retval_ptr;
     239                 :                 
     240               0 :                 fci.size = sizeof(fci);
     241               0 :                 fci.function_table = &uwrap->ce->function_table;
     242               0 :                 fci.function_name = NULL;
     243               0 :                 fci.symbol_table = NULL;
     244               0 :                 fci.object_pp = &us->object;
     245               0 :                 fci.retval_ptr_ptr = &retval_ptr;
     246               0 :                 fci.param_count = 0;
     247               0 :                 fci.params = NULL;
     248               0 :                 fci.no_separation = 1;
     249                 :                 
     250               0 :                 fcc.initialized = 1;
     251               0 :                 fcc.function_handler = uwrap->ce->constructor;
     252               0 :                 fcc.calling_scope = EG(scope);
     253               0 :                 fcc.object_pp = &us->object;
     254                 : 
     255               0 :                 if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
     256               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute %s::%s()", uwrap->ce->name, uwrap->ce->constructor->common.function_name);
     257               0 :                         zval_dtor(us->object);
     258               0 :                         FREE_ZVAL(us->object);
     259               0 :                         efree(us);
     260               0 :                         FG(user_stream_current_filename) = NULL;
     261               0 :                         return NULL;
     262                 :                 } else {
     263               0 :                         if (retval_ptr) {
     264               0 :                                 zval_ptr_dtor(&retval_ptr);
     265                 :                         }
     266                 :                 }
     267                 :         }
     268                 : 
     269               0 :         if (context) {
     270               0 :                 MAKE_STD_ZVAL(zcontext);
     271               0 :                 php_stream_context_to_zval(context, zcontext);
     272               0 :                 add_property_zval(us->object, "context", zcontext);
     273                 :                 /* The object property should be the only reference,
     274                 :                    'get rid' of our local reference. */
     275               0 :                 zval_ptr_dtor(&zcontext);
     276                 :         } else {
     277               0 :                 add_property_null(us->object, "context");
     278                 :         }
     279                 :         
     280                 :         /* call it's stream_open method - set up params first */
     281               0 :         MAKE_STD_ZVAL(zfilename);
     282               0 :         ZVAL_STRING(zfilename, filename, 1);
     283               0 :         args[0] = &zfilename;
     284                 : 
     285               0 :         MAKE_STD_ZVAL(zmode);
     286               0 :         ZVAL_STRING(zmode, mode, 1);
     287               0 :         args[1] = &zmode;
     288                 : 
     289               0 :         MAKE_STD_ZVAL(zoptions);
     290               0 :         ZVAL_LONG(zoptions, options);
     291               0 :         args[2] = &zoptions;
     292                 : 
     293               0 :         MAKE_STD_ZVAL(zopened);
     294               0 :         ZVAL_REFCOUNT(zopened) = 1;
     295               0 :         PZVAL_IS_REF(zopened) = 1;
     296               0 :         ZVAL_NULL(zopened);
     297               0 :         args[3] = &zopened;
     298                 : 
     299               0 :         MAKE_STD_ZVAL(zfuncname);
     300               0 :         ZVAL_STRING(zfuncname, USERSTREAM_OPEN, 1);
     301                 :         
     302               0 :         call_result = call_user_function_ex(NULL,
     303                 :                         &us->object,
     304                 :                         zfuncname,
     305                 :                         &zretval,
     306                 :                         4, args,
     307                 :                         0, NULL TSRMLS_CC);
     308                 :         
     309               0 :         if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) {
     310                 :                 /* the stream is now open! */
     311               0 :                 stream = php_stream_alloc_rel(&php_stream_userspace_ops, us, 0, mode);
     312                 : 
     313                 :                 /* if the opened path is set, copy it out */
     314               0 :                 if (Z_TYPE_P(zopened) == IS_STRING && opened_path) {
     315               0 :                         *opened_path = estrndup(Z_STRVAL_P(zopened), Z_STRLEN_P(zopened));
     316                 :                 }
     317                 : 
     318                 :                 /* set wrapper data to be a reference to our object */
     319               0 :                 stream->wrapperdata = us->object;
     320               0 :                 zval_add_ref(&stream->wrapperdata);
     321                 :         } else {
     322               0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "\"%s::" USERSTREAM_OPEN "\" call failed",
     323                 :                         us->wrapper->classname);
     324                 :         }
     325                 :         
     326                 :         /* destroy everything else */
     327               0 :         if (stream == NULL) {
     328               0 :                 zval_ptr_dtor(&us->object);
     329               0 :                 efree(us);
     330                 :         }
     331               0 :         if (zretval)
     332               0 :                 zval_ptr_dtor(&zretval);
     333                 :         
     334               0 :         zval_ptr_dtor(&zfuncname);
     335               0 :         zval_ptr_dtor(&zopened);
     336               0 :         zval_ptr_dtor(&zoptions);
     337               0 :         zval_ptr_dtor(&zmode);
     338               0 :         zval_ptr_dtor(&zfilename);
     339                 : 
     340               0 :         FG(user_stream_current_filename) = NULL;
     341                 :                 
     342               0 :         return stream;
     343                 : }
     344                 : 
     345                 : static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filename, char *mode,
     346                 :                 int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
     347               0 : {
     348               0 :         struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
     349                 :         php_userstream_data_t *us;
     350               0 :         zval *zfilename, *zoptions, *zretval = NULL, *zfuncname, *zcontext;
     351                 :         zval **args[2]; 
     352                 :         int call_result;
     353               0 :         php_stream *stream = NULL;
     354                 : 
     355                 :         /* Try to catch bad usage without preventing flexibility */
     356               0 :         if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
     357               0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
     358               0 :                 return NULL;
     359                 :         }
     360               0 :         FG(user_stream_current_filename) = filename;
     361                 :         
     362               0 :         us = emalloc(sizeof(*us));
     363               0 :         us->wrapper = uwrap; 
     364                 : 
     365                 :         /* create an instance of our class */
     366               0 :         ALLOC_ZVAL(us->object);
     367               0 :         object_init_ex(us->object, uwrap->ce);
     368               0 :         ZVAL_REFCOUNT(us->object) = 1;
     369               0 :         PZVAL_IS_REF(us->object) = 1;
     370                 : 
     371               0 :         if (context) {
     372               0 :                 MAKE_STD_ZVAL(zcontext);
     373               0 :                 php_stream_context_to_zval(context, zcontext);
     374               0 :                 add_property_zval(us->object, "context", zcontext);
     375                 :                 /* The object property should be the only reference,
     376                 :                    'get rid' of our local reference. */
     377               0 :                 zval_ptr_dtor(&zcontext);
     378                 :         } else {
     379               0 :                 add_property_null(us->object, "context");
     380                 :         }
     381                 :         
     382                 :         /* call it's dir_open method - set up params first */
     383               0 :         MAKE_STD_ZVAL(zfilename);
     384               0 :         ZVAL_STRING(zfilename, filename, 1);
     385               0 :         args[0] = &zfilename;
     386                 : 
     387               0 :         MAKE_STD_ZVAL(zoptions);
     388               0 :         ZVAL_LONG(zoptions, options);
     389               0 :         args[1] = &zoptions;
     390                 : 
     391               0 :         MAKE_STD_ZVAL(zfuncname);
     392               0 :         ZVAL_STRING(zfuncname, USERSTREAM_DIR_OPEN, 1);
     393                 :         
     394               0 :         call_result = call_user_function_ex(NULL,
     395                 :                         &us->object,
     396                 :                         zfuncname,
     397                 :                         &zretval,
     398                 :                         2, args,
     399                 :                         0, NULL TSRMLS_CC);
     400                 :         
     401               0 :         if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) {
     402                 :                 /* the stream is now open! */
     403               0 :                 stream = php_stream_alloc_rel(&php_stream_userspace_dir_ops, us, 0, mode);
     404                 : 
     405                 :                 /* set wrapper data to be a reference to our object */
     406               0 :                 stream->wrapperdata = us->object;
     407               0 :                 zval_add_ref(&stream->wrapperdata);
     408                 :         } else {
     409               0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed",
     410                 :                         us->wrapper->classname);
     411                 :         }
     412                 :         
     413                 :         /* destroy everything else */
     414               0 :         if (stream == NULL) {
     415               0 :                 zval_ptr_dtor(&us->object);
     416               0 :                 efree(us);
     417                 :         }
     418               0 :         if (zretval)
     419               0 :                 zval_ptr_dtor(&zretval);
     420                 :         
     421               0 :         zval_ptr_dtor(&zfuncname);
     422               0 :         zval_ptr_dtor(&zoptions);
     423               0 :         zval_ptr_dtor(&zfilename);
     424                 : 
     425               0 :         FG(user_stream_current_filename) = NULL;
     426                 :                 
     427               0 :         return stream;
     428                 : }
     429                 : 
     430                 : 
     431                 : /* {{{ proto bool stream_wrapper_register(string protocol, string classname)
     432                 :    Registers a custom URL protocol handler class */
     433                 : PHP_FUNCTION(stream_wrapper_register)
     434               0 : {
     435                 :         char *protocol, *classname;
     436                 :         int protocol_len, classname_len;
     437                 :         struct php_user_stream_wrapper * uwrap;
     438                 :         int rsrc_id;
     439                 :         
     440               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &protocol, &protocol_len, &classname, &classname_len) == FAILURE) {
     441               0 :                 RETURN_FALSE;
     442                 :         }
     443                 :         
     444               0 :         uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
     445               0 :         uwrap->protoname = estrndup(protocol, protocol_len);
     446               0 :         uwrap->classname = estrndup(classname, classname_len);
     447               0 :         uwrap->wrapper.wops = &user_stream_wops;
     448               0 :         uwrap->wrapper.abstract = uwrap;
     449                 : 
     450               0 :         rsrc_id = ZEND_REGISTER_RESOURCE(NULL, uwrap, le_protocols);
     451                 : 
     452               0 :         if (zend_lookup_class(uwrap->classname, classname_len, (zend_class_entry***)&uwrap->ce TSRMLS_CC) == SUCCESS) {
     453               0 :                 uwrap->ce = *(zend_class_entry**)uwrap->ce;
     454               0 :                 if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper TSRMLS_CC) == SUCCESS) {
     455               0 :                         RETURN_TRUE;
     456                 :                 } else {
     457                 :                         /* We failed.  But why? */
     458               0 :                         if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol, protocol_len + 1)) {
     459               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol %s:// is already defined.", protocol);
     460                 :                         } else {
     461                 :                                 /* Should never happen */
     462               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to register wrapper class %s to %s://", classname, protocol);
     463                 :                         }
     464                 :                 }
     465                 :         } else {
     466               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "class '%s' is undefined", classname);
     467                 :         }
     468                 : 
     469               0 :         zend_list_delete(rsrc_id);
     470               0 :         RETURN_FALSE;
     471                 : }
     472                 : /* }}} */
     473                 : 
     474                 : /* {{{ proto bool stream_wrapper_unregister(string protocol)
     475                 :         Unregister a wrapper for the life of the current request. */
     476                 : PHP_FUNCTION(stream_wrapper_unregister)
     477               0 : {
     478                 :         char *protocol;
     479                 :         int protocol_len;
     480                 : 
     481               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &protocol, &protocol_len) == FAILURE) {
     482               0 :                 RETURN_FALSE;
     483                 :         }
     484                 : 
     485               0 :         if (php_unregister_url_stream_wrapper_volatile(protocol TSRMLS_CC) == FAILURE) {
     486                 :                 /* We failed */
     487               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to unregister protocol %s://", protocol);
     488               0 :                 RETURN_FALSE;
     489                 :         }
     490                 : 
     491               0 :         RETURN_TRUE;
     492                 : }
     493                 : /* }}} */
     494                 : 
     495                 : /* {{{ proto bool stream_wrapper_restore(string protocol)
     496                 :         Restore the original protocol handler, overriding if necessary */
     497                 : PHP_FUNCTION(stream_wrapper_restore)
     498               0 : {
     499                 :         char *protocol;
     500                 :         int protocol_len;
     501               0 :         php_stream_wrapper **wrapperpp = NULL, *wrapper;
     502                 :         HashTable *global_wrapper_hash;
     503                 : 
     504               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &protocol, &protocol_len) == FAILURE) {
     505               0 :                 RETURN_FALSE;
     506                 :         }
     507                 : 
     508               0 :         global_wrapper_hash = php_stream_get_url_stream_wrappers_hash_global();
     509               0 :         if (php_stream_get_url_stream_wrappers_hash() == global_wrapper_hash) {
     510               0 :                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s:// was never changed, nothing to restore", protocol);
     511               0 :                 RETURN_TRUE;
     512                 :         }
     513                 : 
     514               0 :         if ((zend_hash_find(global_wrapper_hash, protocol, protocol_len + 1, (void**)&wrapperpp) == FAILURE) || !wrapperpp) {
     515               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s:// never existed, nothing to restore", protocol);
     516               0 :                 RETURN_FALSE;
     517                 :         }
     518                 : 
     519                 :         /* next line might delete the pointer that wrapperpp points at, so deref it now */
     520               0 :         wrapper = *wrapperpp;
     521                 : 
     522                 :         /* A failure here could be okay given that the protocol might have been merely unregistered */
     523               0 :         php_unregister_url_stream_wrapper_volatile(protocol TSRMLS_CC);
     524                 : 
     525               0 :         if (php_register_url_stream_wrapper_volatile(protocol, wrapper TSRMLS_CC) == FAILURE) {
     526               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to restore original %s:// wrapper", protocol);
     527               0 :                 RETURN_FALSE;
     528                 :         }       
     529                 : 
     530               0 :         RETURN_TRUE;
     531                 : }
     532                 : /* }}} */
     533                 : 
     534                 : static size_t php_userstreamop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
     535               0 : {
     536                 :         zval func_name;
     537               0 :         zval *retval = NULL;
     538                 :         int call_result;
     539               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
     540                 :         zval **args[1];
     541                 :         zval *zbufptr;
     542               0 :         size_t didwrite = 0;
     543                 : 
     544                 :         assert(us != NULL);
     545                 : 
     546               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_WRITE, sizeof(USERSTREAM_WRITE)-1, 0);
     547                 : 
     548               0 :         MAKE_STD_ZVAL(zbufptr);
     549               0 :         ZVAL_STRINGL(zbufptr, (char*)buf, count, 1);;
     550               0 :         args[0] = &zbufptr;
     551                 : 
     552               0 :         call_result = call_user_function_ex(NULL,
     553                 :                         &us->object,
     554                 :                         &func_name,
     555                 :                         &retval,
     556                 :                         1, args,
     557                 :                         0, NULL TSRMLS_CC);
     558               0 :         zval_ptr_dtor(&zbufptr);
     559                 : 
     560               0 :         didwrite = 0;
     561               0 :         if (call_result == SUCCESS && retval != NULL) {
     562               0 :                 convert_to_long(retval);
     563               0 :                 didwrite = Z_LVAL_P(retval);
     564               0 :         } else if (call_result == FAILURE) {
     565               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!",
     566                 :                                 us->wrapper->classname);
     567                 :         }
     568                 : 
     569                 :         /* don't allow strange buffer overruns due to bogus return */
     570               0 :         if (didwrite > count) {
     571               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_WRITE " wrote %ld bytes more data than requested (%ld written, %ld max)",
     572                 :                                 us->wrapper->classname,
     573                 :                                 (long)(didwrite - count), (long)didwrite, (long)count);
     574               0 :                 didwrite = count;
     575                 :         }
     576                 :         
     577               0 :         if (retval)
     578               0 :                 zval_ptr_dtor(&retval);
     579                 :         
     580               0 :         return didwrite;
     581                 : }
     582                 : 
     583                 : static size_t php_userstreamop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     584               0 : {
     585                 :         zval func_name;
     586               0 :         zval *retval = NULL;
     587                 :         zval **args[1];
     588                 :         int call_result;
     589               0 :         size_t didread = 0;
     590               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
     591                 :         zval *zcount;
     592                 : 
     593                 :         assert(us != NULL);
     594                 : 
     595               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_READ, sizeof(USERSTREAM_READ)-1, 0);
     596                 : 
     597               0 :         MAKE_STD_ZVAL(zcount);
     598               0 :         ZVAL_LONG(zcount, count);
     599               0 :         args[0] = &zcount;
     600                 : 
     601               0 :         call_result = call_user_function_ex(NULL,
     602                 :                         &us->object,
     603                 :                         &func_name,
     604                 :                         &retval,
     605                 :                         1, args,
     606                 :                         0, NULL TSRMLS_CC);
     607                 : 
     608               0 :         if (call_result == SUCCESS && retval != NULL) {
     609               0 :                 convert_to_string(retval);
     610               0 :                 didread = Z_STRLEN_P(retval);
     611               0 :                 if (didread > count) {
     612               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_READ " - read %ld bytes more data than requested (%ld read, %ld max) - excess data will be lost",
     613                 :                                         us->wrapper->classname, (long)(didread - count), (long)didread, (long)count);
     614               0 :                         didread = count;
     615                 :                 }
     616               0 :                 if (didread > 0)
     617               0 :                         memcpy(buf, Z_STRVAL_P(retval), didread);
     618               0 :         } else if (call_result == FAILURE) {
     619               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_READ " is not implemented!",
     620                 :                                 us->wrapper->classname);
     621                 :         }
     622               0 :         zval_ptr_dtor(&zcount);
     623                 : 
     624               0 :         if (retval) {
     625               0 :                 zval_ptr_dtor(&retval);
     626               0 :                 retval = NULL;
     627                 :         }
     628                 : 
     629                 :         /* since the user stream has no way of setting the eof flag directly, we need to ask it if we hit eof */
     630                 : 
     631               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_EOF, sizeof(USERSTREAM_EOF)-1, 0);
     632                 : 
     633               0 :         call_result = call_user_function_ex(NULL,
     634                 :                         &us->object,
     635                 :                         &func_name,
     636                 :                         &retval,
     637                 :                         0, NULL, 0, NULL TSRMLS_CC);
     638                 : 
     639               0 :         if (call_result == SUCCESS && retval != NULL && zval_is_true(retval)) {
     640               0 :                 stream->eof = 1;
     641               0 :         } else if (call_result == FAILURE) {
     642               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING,
     643                 :                                 "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
     644                 :                                 us->wrapper->classname);
     645                 : 
     646               0 :                 stream->eof = 1;
     647                 :         }
     648                 : 
     649               0 :         if (retval) {
     650               0 :                 zval_ptr_dtor(&retval);
     651               0 :                 retval = NULL;
     652                 :         }
     653                 : 
     654               0 :         return didread;
     655                 : }
     656                 : 
     657                 : static int php_userstreamop_close(php_stream *stream, int close_handle TSRMLS_DC)
     658               0 : {
     659                 :         zval func_name;
     660               0 :         zval *retval = NULL;
     661               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
     662                 : 
     663                 :         assert(us != NULL);
     664                 :         
     665               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_CLOSE, sizeof(USERSTREAM_CLOSE)-1, 0);
     666                 :         
     667               0 :         call_user_function_ex(NULL,
     668                 :                         &us->object,
     669                 :                         &func_name,
     670                 :                         &retval,
     671                 :                         0, NULL, 0, NULL TSRMLS_CC);
     672                 : 
     673               0 :         if (retval)
     674               0 :                 zval_ptr_dtor(&retval);
     675                 :         
     676               0 :         zval_ptr_dtor(&us->object);
     677                 : 
     678               0 :         efree(us);
     679                 :         
     680               0 :         return 0;
     681                 : }
     682                 : 
     683                 : static int php_userstreamop_flush(php_stream *stream TSRMLS_DC)
     684               0 : {
     685                 :         zval func_name;
     686               0 :         zval *retval = NULL;
     687                 :         int call_result;
     688               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
     689                 : 
     690                 :         assert(us != NULL);
     691                 : 
     692               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_FLUSH, sizeof(USERSTREAM_FLUSH)-1, 0);
     693                 :         
     694               0 :         call_result = call_user_function_ex(NULL,
     695                 :                         &us->object,
     696                 :                         &func_name,
     697                 :                         &retval,
     698                 :                         0, NULL, 0, NULL TSRMLS_CC);
     699                 : 
     700               0 :         if (call_result == SUCCESS && retval != NULL && zval_is_true(retval))
     701               0 :                 call_result = 0;
     702                 :         else
     703               0 :                 call_result = -1;
     704                 :         
     705               0 :         if (retval)
     706               0 :                 zval_ptr_dtor(&retval);
     707                 :         
     708               0 :         return call_result;
     709                 : }
     710                 : 
     711                 : static int php_userstreamop_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
     712               0 : {
     713                 :         zval func_name;
     714               0 :         zval *retval = NULL;
     715                 :         int call_result, ret;
     716               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
     717                 :         zval **args[2];
     718                 :         zval *zoffs, *zwhence;
     719                 : 
     720                 :         assert(us != NULL);
     721                 : 
     722               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_SEEK, sizeof(USERSTREAM_SEEK)-1, 0);
     723                 : 
     724               0 :         MAKE_STD_ZVAL(zoffs);
     725               0 :         ZVAL_LONG(zoffs, offset);
     726               0 :         args[0] = &zoffs;
     727                 : 
     728               0 :         MAKE_STD_ZVAL(zwhence);
     729               0 :         ZVAL_LONG(zwhence, whence);
     730               0 :         args[1] = &zwhence;
     731                 : 
     732               0 :         call_result = call_user_function_ex(NULL,
     733                 :                         &us->object,
     734                 :                         &func_name,
     735                 :                         &retval,
     736                 :                         2, args,
     737                 :                         0, NULL TSRMLS_CC);
     738                 : 
     739               0 :         zval_ptr_dtor(&zoffs);
     740               0 :         zval_ptr_dtor(&zwhence);
     741                 : 
     742               0 :         if (call_result == FAILURE) {
     743                 :                 /* stream_seek is not implemented, so disable seeks for this stream */
     744               0 :                 stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
     745                 :                 /* there should be no retval to clean up */
     746                 :                 
     747               0 :                 if (retval) 
     748               0 :                         zval_ptr_dtor(&retval);
     749                 :                 
     750               0 :                 return -1;
     751               0 :         } else if (call_result == SUCCESS && retval != NULL && zval_is_true(retval)) {
     752               0 :                 ret = 0;
     753                 :         } else {
     754               0 :                 ret = -1;
     755                 :         }
     756                 : 
     757               0 :         if (retval) {
     758               0 :                 zval_ptr_dtor(&retval);
     759               0 :                 retval = NULL;
     760                 :         }
     761                 : 
     762               0 :         if (ret) {
     763               0 :                 return ret;
     764                 :         }
     765                 : 
     766                 :         /* now determine where we are */
     767               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_TELL, sizeof(USERSTREAM_TELL)-1, 0);
     768                 : 
     769               0 :         call_result = call_user_function_ex(NULL,
     770                 :                 &us->object,
     771                 :                 &func_name,
     772                 :                 &retval,
     773                 :                 0, NULL, 0, NULL TSRMLS_CC);
     774                 : 
     775               0 :         if (call_result == SUCCESS && retval != NULL && Z_TYPE_P(retval) == IS_LONG) {
     776               0 :                 *newoffs = Z_LVAL_P(retval);
     777               0 :                 ret = 0;
     778               0 :         } else if (call_result == FAILURE) {
     779               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", us->wrapper->classname);
     780               0 :                 ret = -1;
     781                 :         } else {
     782               0 :                 ret = -1;
     783                 :         }
     784                 : 
     785               0 :         if (retval) {
     786               0 :                 zval_ptr_dtor(&retval);
     787                 :         }
     788               0 :         return ret;
     789                 : }
     790                 : 
     791                 : /* parse the return value from one of the stat functions and store the
     792                 :  * relevant fields into the statbuf provided */
     793                 : static int statbuf_from_array(zval *array, php_stream_statbuf *ssb TSRMLS_DC)
     794               0 : {
     795                 :         zval **elem;
     796                 : 
     797                 : #define STAT_PROP_ENTRY_EX(name, name2)                        \
     798                 :         if (SUCCESS == zend_hash_find(Z_ARRVAL_P(array), #name, sizeof(#name), (void**)&elem)) {     \
     799                 :                 convert_to_long(*elem);                                                                   \
     800                 :                 ssb->sb.st_##name2 = Z_LVAL_PP(elem);                                                      \
     801                 :         }
     802                 : 
     803                 : #define STAT_PROP_ENTRY(name) STAT_PROP_ENTRY_EX(name,name)
     804                 : 
     805               0 :         STAT_PROP_ENTRY(dev);
     806               0 :         STAT_PROP_ENTRY(ino);
     807               0 :         STAT_PROP_ENTRY(mode);
     808               0 :         STAT_PROP_ENTRY(nlink);
     809               0 :         STAT_PROP_ENTRY(uid);
     810               0 :         STAT_PROP_ENTRY(gid);
     811                 : #if HAVE_ST_RDEV
     812               0 :         STAT_PROP_ENTRY(rdev);
     813                 : #endif
     814               0 :         STAT_PROP_ENTRY(size);
     815                 : #ifdef NETWARE
     816                 :         STAT_PROP_ENTRY_EX(atime, atime.tv_sec);
     817                 :         STAT_PROP_ENTRY_EX(mtime, mtime.tv_sec);
     818                 :         STAT_PROP_ENTRY_EX(ctime, ctime.tv_sec);
     819                 : #else
     820               0 :         STAT_PROP_ENTRY(atime);
     821               0 :         STAT_PROP_ENTRY(mtime);
     822               0 :         STAT_PROP_ENTRY(ctime);
     823                 : #endif
     824                 : #ifdef HAVE_ST_BLKSIZE
     825               0 :         STAT_PROP_ENTRY(blksize);
     826                 : #endif
     827                 : #ifdef HAVE_ST_BLOCKS
     828               0 :         STAT_PROP_ENTRY(blocks);
     829                 : #endif
     830                 : 
     831                 : #undef STAT_PROP_ENTRY  
     832                 : #undef STAT_PROP_ENTRY_EX       
     833               0 :         return SUCCESS;
     834                 : }
     835                 : 
     836                 : static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
     837               0 : {
     838                 :         zval func_name;
     839               0 :         zval *retval = NULL;
     840                 :         int call_result;
     841               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
     842               0 :         int ret = -1;
     843                 : 
     844               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_STAT, sizeof(USERSTREAM_STAT)-1, 0);
     845                 : 
     846               0 :         call_result = call_user_function_ex(NULL,
     847                 :                         &us->object,
     848                 :                         &func_name,
     849                 :                         &retval,
     850                 :                         0, NULL, 0, NULL TSRMLS_CC);
     851                 : 
     852               0 :         if (call_result == SUCCESS && retval != NULL && Z_TYPE_P(retval) == IS_ARRAY) {
     853               0 :                 if (SUCCESS == statbuf_from_array(retval, ssb TSRMLS_CC))
     854               0 :                         ret = 0;
     855                 :         } else {
     856               0 :                 if (call_result == FAILURE) {
     857               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!",
     858                 :                                         us->wrapper->classname);
     859                 :                 }
     860                 :         }
     861                 : 
     862               0 :         if (retval) 
     863               0 :                 zval_ptr_dtor(&retval);
     864                 :         
     865               0 :         return ret;
     866                 : }
     867                 : 
     868                 : 
     869               0 : static int php_userstreamop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) {
     870                 :         zval func_name;
     871               0 :         zval *retval = NULL;
     872                 :         int call_result;
     873               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
     874               0 :         int ret = -1;
     875               0 :         zval *zvalue = NULL;
     876                 :         zval **args[1];
     877                 : 
     878               0 :         switch (option) {
     879                 :         case PHP_STREAM_OPTION_CHECK_LIVENESS:
     880               0 :                 ZVAL_STRINGL(&func_name, USERSTREAM_EOF, sizeof(USERSTREAM_EOF)-1, 0);
     881               0 :                 call_result = call_user_function_ex(NULL, &us->object, &func_name, &retval, 0, NULL, 0, NULL TSRMLS_CC);
     882               0 :                 if (call_result == SUCCESS && retval != NULL && Z_TYPE_P(retval) == IS_BOOL) {
     883               0 :                         ret = zval_is_true(retval) ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
     884                 :                 } else {
     885               0 :                         ret = PHP_STREAM_OPTION_RETURN_ERR;
     886               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
     887                 :                                         "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
     888                 :                                         us->wrapper->classname);
     889                 :                 }
     890               0 :                 break;
     891                 : 
     892                 :         case PHP_STREAM_OPTION_LOCKING:
     893               0 :                 MAKE_STD_ZVAL(zvalue);
     894               0 :                 ZVAL_LONG(zvalue, value);
     895               0 :                 args[0] = &zvalue;
     896                 :                 
     897                 :                 /* TODO wouldblock */
     898               0 :                 ZVAL_STRINGL(&func_name, USERSTREAM_LOCK, sizeof(USERSTREAM_LOCK)-1, 0);
     899                 :                 
     900               0 :                 call_result = call_user_function_ex(NULL,
     901                 :                                                                                         &us->object,
     902                 :                                                                                         &func_name,
     903                 :                                                                                         &retval,
     904                 :                                                                                         1, args, 0, NULL TSRMLS_CC);
     905                 :                 
     906               0 :                 if (call_result == SUCCESS && retval != NULL && Z_TYPE_P(retval) == IS_BOOL) {
     907               0 :                         ret = !Z_LVAL_P(retval);
     908               0 :                 } else if (call_result == FAILURE) {
     909               0 :                         if (value == 0) { 
     910                 :                                 /* lock support test (TODO: more check) */
     911               0 :                                 ret = 0;
     912                 :                         } else {
     913               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!", 
     914                 :                                                                  us->wrapper->classname);
     915                 :                         }
     916                 :                 }
     917                 : 
     918                 :                 break;
     919                 :         }
     920                 : 
     921                 :         /* clean up */
     922               0 :         if (retval) {
     923               0 :                 zval_ptr_dtor(&retval);
     924                 :         }
     925                 :   
     926                 : 
     927               0 :         if (zvalue) {
     928               0 :                 zval_ptr_dtor(&zvalue);
     929                 :         }
     930                 : 
     931               0 :         return ret;
     932                 : }
     933                 : 
     934                 : 
     935                 : static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
     936               0 : {
     937               0 :         struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
     938                 :         zval *zfilename, *zfuncname, *zretval, *zcontext;
     939                 :         zval **args[1];
     940                 :         int call_result;
     941                 :         zval *object;
     942               0 :         int ret = 0;
     943                 : 
     944                 :         /* create an instance of our class */
     945               0 :         ALLOC_ZVAL(object);
     946               0 :         object_init_ex(object, uwrap->ce);
     947               0 :         ZVAL_REFCOUNT(object) = 1;
     948               0 :         PZVAL_IS_REF(object) = 1;
     949                 : 
     950               0 :         if (context) {
     951               0 :                 MAKE_STD_ZVAL(zcontext);
     952               0 :                 php_stream_context_to_zval(context, zcontext);
     953               0 :                 add_property_zval(object, "context", zcontext);
     954                 :                 /* The object property should be the only reference,
     955                 :                    'get rid' of our local reference. */
     956               0 :                 zval_ptr_dtor(&zcontext);
     957                 :         } else {
     958               0 :                 add_property_null(object, "context");
     959                 :         }
     960                 : 
     961                 :         /* call the unlink method */
     962               0 :         MAKE_STD_ZVAL(zfilename);
     963               0 :         ZVAL_STRING(zfilename, url, 1);
     964               0 :         args[0] = &zfilename;
     965                 : 
     966               0 :         MAKE_STD_ZVAL(zfuncname);
     967               0 :         ZVAL_STRING(zfuncname, USERSTREAM_UNLINK, 1);
     968                 :         
     969               0 :         call_result = call_user_function_ex(NULL,
     970                 :                         &object,
     971                 :                         zfuncname,
     972                 :                         &zretval,
     973                 :                         1, args,
     974                 :                         0, NULL TSRMLS_CC);
     975                 : 
     976               0 :         if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) {
     977               0 :                 ret = Z_LVAL_P(zretval);
     978               0 :         } else if (call_result == FAILURE) {
     979               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", uwrap->classname);
     980                 :         }
     981                 : 
     982                 :         /* clean up */
     983               0 :         zval_ptr_dtor(&object);
     984               0 :         if (zretval)
     985               0 :                 zval_ptr_dtor(&zretval);
     986                 :         
     987               0 :         zval_ptr_dtor(&zfuncname);
     988               0 :         zval_ptr_dtor(&zfilename);
     989                 : 
     990               0 :         return ret;
     991                 : }
     992                 : 
     993                 : static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC)
     994               0 : {
     995               0 :         struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
     996                 :         zval *zold_name, *znew_name, *zfuncname, *zretval, *zcontext;
     997                 :         zval **args[2];
     998                 :         int call_result;
     999                 :         zval *object;
    1000               0 :         int ret = 0;
    1001                 : 
    1002                 :         /* create an instance of our class */
    1003               0 :         ALLOC_ZVAL(object);
    1004               0 :         object_init_ex(object, uwrap->ce);
    1005               0 :         ZVAL_REFCOUNT(object) = 1;
    1006               0 :         PZVAL_IS_REF(object) = 1;
    1007                 : 
    1008               0 :         if (context) {
    1009               0 :                 MAKE_STD_ZVAL(zcontext);
    1010               0 :                 php_stream_context_to_zval(context, zcontext);
    1011               0 :                 add_property_zval(object, "context", zcontext);
    1012                 :                 /* The object property should be the only reference,
    1013                 :                    'get rid' of our local reference. */
    1014               0 :                 zval_ptr_dtor(&zcontext);
    1015                 :         } else {
    1016               0 :                 add_property_null(object, "context");
    1017                 :         }
    1018                 : 
    1019                 :         /* call the rename method */
    1020               0 :         MAKE_STD_ZVAL(zold_name);
    1021               0 :         ZVAL_STRING(zold_name, url_from, 1);
    1022               0 :         args[0] = &zold_name;
    1023                 : 
    1024               0 :         MAKE_STD_ZVAL(znew_name);
    1025               0 :         ZVAL_STRING(znew_name, url_to, 1);
    1026               0 :         args[1] = &znew_name;
    1027                 : 
    1028               0 :         MAKE_STD_ZVAL(zfuncname);
    1029               0 :         ZVAL_STRING(zfuncname, USERSTREAM_RENAME, 1);
    1030                 :         
    1031               0 :         call_result = call_user_function_ex(NULL,
    1032                 :                         &object,
    1033                 :                         zfuncname,
    1034                 :                         &zretval,
    1035                 :                         2, args,
    1036                 :                         0, NULL TSRMLS_CC);
    1037                 : 
    1038               0 :         if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) {
    1039               0 :                 ret = Z_LVAL_P(zretval);
    1040               0 :         } else if (call_result == FAILURE) {
    1041               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", uwrap->classname);
    1042                 :         }
    1043                 : 
    1044                 :         /* clean up */
    1045               0 :         zval_ptr_dtor(&object);
    1046               0 :         if (zretval)
    1047               0 :                 zval_ptr_dtor(&zretval);
    1048                 :         
    1049               0 :         zval_ptr_dtor(&zfuncname);
    1050               0 :         zval_ptr_dtor(&zold_name);
    1051               0 :         zval_ptr_dtor(&znew_name);
    1052                 : 
    1053               0 :         return ret;
    1054                 : }
    1055                 : 
    1056                 : static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC)
    1057               0 : {
    1058               0 :         struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
    1059                 :         zval *zfilename, *zmode, *zoptions, *zfuncname, *zretval, *zcontext;
    1060                 :         zval **args[3];
    1061                 :         int call_result;
    1062                 :         zval *object;
    1063               0 :         int ret = 0;
    1064                 : 
    1065                 :         /* create an instance of our class */
    1066               0 :         ALLOC_ZVAL(object);
    1067               0 :         object_init_ex(object, uwrap->ce);
    1068               0 :         ZVAL_REFCOUNT(object) = 1;
    1069               0 :         PZVAL_IS_REF(object) = 1;
    1070                 : 
    1071               0 :         if (context) {
    1072               0 :                 MAKE_STD_ZVAL(zcontext);
    1073               0 :                 php_stream_context_to_zval(context, zcontext);
    1074               0 :                 add_property_zval(object, "context", zcontext);
    1075                 :                 /* The object property should be the only reference,
    1076                 :                    'get rid' of our local reference. */
    1077               0 :                 zval_ptr_dtor(&zcontext);
    1078                 :         } else {
    1079               0 :                 add_property_null(object, "context");
    1080                 :         }
    1081                 : 
    1082                 :         /* call the unlink method */
    1083               0 :         MAKE_STD_ZVAL(zfilename);
    1084               0 :         ZVAL_STRING(zfilename, url, 1);
    1085               0 :         args[0] = &zfilename;
    1086                 : 
    1087               0 :         MAKE_STD_ZVAL(zmode);
    1088               0 :         ZVAL_LONG(zmode, mode);
    1089               0 :         args[1] = &zmode;
    1090                 : 
    1091               0 :         MAKE_STD_ZVAL(zoptions);
    1092               0 :         ZVAL_LONG(zoptions, options);
    1093               0 :         args[2] = &zoptions;
    1094                 : 
    1095               0 :         MAKE_STD_ZVAL(zfuncname);
    1096               0 :         ZVAL_STRING(zfuncname, USERSTREAM_MKDIR, 1);
    1097                 :         
    1098               0 :         call_result = call_user_function_ex(NULL,
    1099                 :                         &object,
    1100                 :                         zfuncname,
    1101                 :                         &zretval,
    1102                 :                         3, args,
    1103                 :                         0, NULL TSRMLS_CC);
    1104                 : 
    1105               0 :         if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) {
    1106               0 :                 ret = Z_LVAL_P(zretval);
    1107               0 :         } else if (call_result == FAILURE) {
    1108               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", uwrap->classname);
    1109                 :         }
    1110                 : 
    1111                 :         /* clean up */
    1112               0 :         zval_ptr_dtor(&object);
    1113               0 :         if (zretval) {
    1114               0 :                 zval_ptr_dtor(&zretval);
    1115                 :         }
    1116                 :         
    1117               0 :         zval_ptr_dtor(&zfuncname);
    1118               0 :         zval_ptr_dtor(&zfilename);
    1119               0 :         zval_ptr_dtor(&zmode);
    1120               0 :         zval_ptr_dtor(&zoptions);
    1121                 : 
    1122               0 :         return ret;
    1123                 : }
    1124                 : 
    1125                 : static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
    1126               0 : {
    1127               0 :         struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
    1128                 :         zval *zfilename, *zoptions, *zfuncname, *zretval, *zcontext;
    1129                 :         zval **args[3];
    1130                 :         int call_result;
    1131                 :         zval *object;
    1132               0 :         int ret = 0;
    1133                 : 
    1134                 :         /* create an instance of our class */
    1135               0 :         ALLOC_ZVAL(object);
    1136               0 :         object_init_ex(object, uwrap->ce);
    1137               0 :         ZVAL_REFCOUNT(object) = 1;
    1138               0 :         PZVAL_IS_REF(object) = 1;
    1139                 : 
    1140               0 :         if (context) {
    1141               0 :                 MAKE_STD_ZVAL(zcontext);
    1142               0 :                 php_stream_context_to_zval(context, zcontext);
    1143               0 :                 add_property_zval(object, "context", zcontext);
    1144                 :                 /* The object property should be the only reference,
    1145                 :                    'get rid' of our local reference. */
    1146               0 :                 zval_ptr_dtor(&zcontext);
    1147                 :         } else {
    1148               0 :                 add_property_null(object, "context");
    1149                 :         }
    1150                 : 
    1151                 :         /* call the unlink method */
    1152               0 :         MAKE_STD_ZVAL(zfilename);
    1153               0 :         ZVAL_STRING(zfilename, url, 1);
    1154               0 :         args[0] = &zfilename;
    1155                 : 
    1156               0 :         MAKE_STD_ZVAL(zoptions);
    1157               0 :         ZVAL_LONG(zoptions, options);
    1158               0 :         args[1] = &zoptions;
    1159                 : 
    1160               0 :         MAKE_STD_ZVAL(zfuncname);
    1161               0 :         ZVAL_STRING(zfuncname, USERSTREAM_RMDIR, 1);
    1162                 :         
    1163               0 :         call_result = call_user_function_ex(NULL,
    1164                 :                         &object,
    1165                 :                         zfuncname,
    1166                 :                         &zretval,
    1167                 :                         2, args,
    1168                 :                         0, NULL TSRMLS_CC);
    1169                 : 
    1170               0 :         if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) {
    1171               0 :                 ret = Z_LVAL_P(zretval);
    1172               0 :         } else if (call_result == FAILURE) {
    1173               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", uwrap->classname);
    1174                 :         }
    1175                 : 
    1176                 :         /* clean up */
    1177               0 :         zval_ptr_dtor(&object);
    1178               0 :         if (zretval) {
    1179               0 :                 zval_ptr_dtor(&zretval);
    1180                 :         }
    1181                 :         
    1182               0 :         zval_ptr_dtor(&zfuncname);
    1183               0 :         zval_ptr_dtor(&zfilename);
    1184               0 :         zval_ptr_dtor(&zoptions);
    1185                 : 
    1186               0 :         return ret;
    1187                 : }
    1188                 : 
    1189                 : static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
    1190               0 : {
    1191               0 :         struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
    1192                 :         zval *zfilename, *zfuncname, *zretval, *zflags, *zcontext;
    1193                 :         zval **args[2]; 
    1194                 :         int call_result;
    1195                 :         zval *object;
    1196               0 :         int ret = -1;
    1197                 : 
    1198                 :         /* create an instance of our class */
    1199               0 :         ALLOC_ZVAL(object);
    1200               0 :         object_init_ex(object, uwrap->ce);
    1201               0 :         ZVAL_REFCOUNT(object) = 1;
    1202               0 :         PZVAL_IS_REF(object) = 1;
    1203                 : 
    1204               0 :         if (context) {
    1205               0 :                 MAKE_STD_ZVAL(zcontext);
    1206               0 :                 php_stream_context_to_zval(context, zcontext);
    1207               0 :                 add_property_zval(object, "context", zcontext);
    1208                 :                 /* The object property should be the only reference,
    1209                 :                    'get rid' of our local reference. */
    1210               0 :                 zval_ptr_dtor(&zcontext);
    1211                 :         } else {
    1212               0 :                 add_property_null(object, "context");
    1213                 :         }
    1214                 : 
    1215                 :         /* call the stat_url method */
    1216                 :         
    1217                 :         /* call it's stream_open method - set up params first */
    1218               0 :         MAKE_STD_ZVAL(zfilename);
    1219               0 :         ZVAL_STRING(zfilename, url, 1);
    1220               0 :         args[0] = &zfilename;
    1221                 : 
    1222               0 :         MAKE_STD_ZVAL(zflags);
    1223               0 :         ZVAL_LONG(zflags, flags);
    1224               0 :         args[1] = &zflags;
    1225                 : 
    1226               0 :         MAKE_STD_ZVAL(zfuncname);
    1227               0 :         ZVAL_STRING(zfuncname, USERSTREAM_STATURL, 1);
    1228                 :         
    1229               0 :         call_result = call_user_function_ex(NULL,
    1230                 :                         &object,
    1231                 :                         zfuncname,
    1232                 :                         &zretval,
    1233                 :                         2, args,
    1234                 :                         0, NULL TSRMLS_CC);
    1235                 :         
    1236               0 :         if (call_result == SUCCESS && zretval != NULL && Z_TYPE_P(zretval) == IS_ARRAY) {
    1237                 :                 /* We got the info we needed */
    1238               0 :                 if (SUCCESS == statbuf_from_array(zretval, ssb TSRMLS_CC))
    1239               0 :                         ret = 0;
    1240                 :         } else {
    1241               0 :                 if (call_result == FAILURE) {
    1242               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!",
    1243                 :                                         uwrap->classname);
    1244                 :                 }
    1245                 :         }
    1246                 :         
    1247                 :         /* clean up */
    1248               0 :         zval_ptr_dtor(&object);
    1249               0 :         if (zretval)
    1250               0 :                 zval_ptr_dtor(&zretval);
    1251                 :         
    1252               0 :         zval_ptr_dtor(&zfuncname);
    1253               0 :         zval_ptr_dtor(&zfilename);
    1254               0 :         zval_ptr_dtor(&zflags);
    1255                 :                 
    1256               0 :         return ret;
    1257                 : 
    1258                 : }
    1259                 : 
    1260                 : static size_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t count TSRMLS_DC)
    1261               0 : {
    1262                 :         zval func_name;
    1263               0 :         zval *retval = NULL;
    1264                 :         int call_result;
    1265               0 :         size_t didread = 0;
    1266               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
    1267               0 :         php_stream_dirent *ent = (php_stream_dirent*)buf;
    1268                 : 
    1269                 :         /* avoid problems if someone mis-uses the stream */
    1270               0 :         if (count != sizeof(php_stream_dirent))
    1271               0 :                 return 0;
    1272                 : 
    1273               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_DIR_READ, sizeof(USERSTREAM_DIR_READ)-1, 0);
    1274                 : 
    1275               0 :         call_result = call_user_function_ex(NULL,
    1276                 :                         &us->object,
    1277                 :                         &func_name,
    1278                 :                         &retval,
    1279                 :                         0, NULL,
    1280                 :                         0, NULL TSRMLS_CC);
    1281                 : 
    1282               0 :         if (call_result == SUCCESS && retval != NULL && Z_TYPE_P(retval) != IS_BOOL) {
    1283               0 :                 convert_to_string(retval);
    1284               0 :                 PHP_STRLCPY(ent->d_name, Z_STRVAL_P(retval), sizeof(ent->d_name), Z_STRLEN_P(retval));
    1285                 : 
    1286               0 :                 didread = sizeof(php_stream_dirent);
    1287               0 :         } else if (call_result == FAILURE) {
    1288               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!",
    1289                 :                                 us->wrapper->classname);
    1290                 :         }
    1291                 : 
    1292               0 :         if (retval)
    1293               0 :                 zval_ptr_dtor(&retval);
    1294                 : 
    1295               0 :         return didread;
    1296                 : }
    1297                 : 
    1298                 : static int php_userstreamop_closedir(php_stream *stream, int close_handle TSRMLS_DC)
    1299               0 : {
    1300                 :         zval func_name;
    1301               0 :         zval *retval = NULL;
    1302               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
    1303                 : 
    1304                 :         assert(us != NULL);
    1305                 :         
    1306               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_DIR_CLOSE, sizeof(USERSTREAM_DIR_CLOSE)-1, 0);
    1307                 :         
    1308               0 :         call_user_function_ex(NULL,
    1309                 :                         &us->object,
    1310                 :                         &func_name,
    1311                 :                         &retval,
    1312                 :                         0, NULL, 0, NULL TSRMLS_CC);
    1313                 : 
    1314               0 :         if (retval)
    1315               0 :                 zval_ptr_dtor(&retval);
    1316                 :         
    1317               0 :         zval_ptr_dtor(&us->object);
    1318                 : 
    1319               0 :         efree(us);
    1320                 :         
    1321               0 :         return 0;
    1322                 : }
    1323                 : 
    1324                 : static int php_userstreamop_rewinddir(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
    1325               0 : {
    1326                 :         zval func_name;
    1327               0 :         zval *retval = NULL;
    1328               0 :         php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
    1329                 : 
    1330               0 :         ZVAL_STRINGL(&func_name, USERSTREAM_DIR_REWIND, sizeof(USERSTREAM_DIR_REWIND)-1, 0);
    1331                 :         
    1332               0 :         call_user_function_ex(NULL,
    1333                 :                         &us->object,
    1334                 :                         &func_name,
    1335                 :                         &retval,
    1336                 :                         0, NULL, 0, NULL TSRMLS_CC);
    1337                 : 
    1338               0 :         if (retval)
    1339               0 :                 zval_ptr_dtor(&retval);
    1340                 :         
    1341               0 :         return 0;
    1342                 : 
    1343                 : }
    1344                 : 
    1345                 : php_stream_ops php_stream_userspace_ops = {
    1346                 :         php_userstreamop_write, php_userstreamop_read,
    1347                 :         php_userstreamop_close, php_userstreamop_flush,
    1348                 :         "user-space",
    1349                 :         php_userstreamop_seek,
    1350                 :         NULL, /* cast */
    1351                 :         php_userstreamop_stat, 
    1352                 :         php_userstreamop_set_option,
    1353                 : };
    1354                 : 
    1355                 : php_stream_ops php_stream_userspace_dir_ops = {
    1356                 :         NULL, /* write */
    1357                 :         php_userstreamop_readdir,
    1358                 :         php_userstreamop_closedir,
    1359                 :         NULL, /* flush */
    1360                 :         "user-space-dir",
    1361                 :         php_userstreamop_rewinddir,
    1362                 :         NULL, /* cast */
    1363                 :         NULL, /* stat */
    1364                 :         NULL  /* set_option */
    1365                 : };
    1366                 : 
    1367                 : 

Generated by: LTP GCOV extension version 1.5