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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_2/main/streams - userspace.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 577
Code covered: 84.7 % Executed lines: 489
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:29 +0000 (5 days ago)

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