. stream_socket_sendto() and stream_socket_recvfrom(). (Wez)
. iconv_mime_decode_headers(). (Moriyoshi)
. get_declared_interfaces(). (Andrey, Marcus)
-- Added rename() support to userstreams. (Sara)
-- Added rename() support to ftp:// wrapper. (Sara)
-- Changed rename() to be routed via streams API. (Sara)
+- Added rename(), rmdir(), and mkdir() support to userstreams. (Sara)
+- Added rename(), rmdir(), and mkdir() support to ftp:// wrapper. (Sara)
+- Changed rename(), rmdir(), and mkdir() to be routed via streams API. (Sara)
- Changed stat() and family to be routed via streams API. (Sara)
- Fixed include_once() / require_once() on Windows to honor case-insensitivity
of files. (Andi)
NULL, /* opendir */
"BZip2",
NULL, /* unlink */
- NULL /* rename */
+ NULL, /* rename */
+ NULL, /* mkdir */
+ NULL /* rmdir */
};
php_stream_wrapper php_stream_bzip2_wrapper = {
NULL, /* opendir */
NULL, /* label */
NULL, /* unlink */
- NULL /* rename */
+ NULL, /* rename */
+ NULL, /* mkdir */
+ NULL /* rmdir */
};
php_stream_wrapper php_curl_wrapper = {
}
/* }}} */
-/* {{{ proto bool mkdir(string pathname [, int mode [, bool recursive])
+/* {{{ proto bool mkdir(string pathname [, int mode [, bool recursive [, resource context]]])
Create a directory */
PHP_FUNCTION(mkdir)
{
- int dir_len, ret;
- long mode = 0777;
- char *dir;
+ zval *zcontext = NULL;
+ long dir_len, mode = 0777;
zend_bool recursive = 0;
+ char *dir;
+ php_stream_context *context;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &dir, &dir_len, &mode, &recursive) == FAILURE) {
- return;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbr", &dir, &dir_len, &mode, &recursive, &zcontext) == FAILURE) {
+ RETURN_FALSE;
}
- if (!recursive) {
- ret = php_mkdir(dir, mode TSRMLS_CC);
- } else {
- /* we look for directory separator from the end of string, thus hopefuly reducing our work load */
- char *p, *e, *buf;
- struct stat sb;
-
- buf = estrndup(dir, dir_len);
- e = buf + dir_len;
-
- /* find a top level directory we need to create */
- while ((p = strrchr(buf, DEFAULT_SLASH))) {
- *p = '\0';
- if (VCWD_STAT(buf, &sb) == 0) {
- *p = DEFAULT_SLASH;
- break;
- }
- }
- if (p == buf) {
- ret = php_mkdir(dir, mode TSRMLS_CC);
- } else if (!(ret = php_mkdir(buf, mode TSRMLS_CC))) {
- if (!p) {
- p = buf;
- }
- /* create any needed directories if the creation of the 1st directory worked */
- while (++p != e) {
- if (*p == '\0' && *(p + 1) != '\0') {
- *p = DEFAULT_SLASH;
- if ((ret = VCWD_MKDIR(buf, (mode_t)mode)) < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
- break;
- }
- }
- }
- }
- efree(buf);
- }
+ context = php_stream_context_from_zval(zcontext, 0);
- if (ret < 0) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(php_stream_mkdir(dir, mode, (recursive ? PHP_STREAM_MKDIR_RECURSIVE : 0) | REPORT_ERRORS, context));
}
/* }}} */
-/* {{{ proto bool rmdir(string dirname)
+/* {{{ proto bool rmdir(string dirname[, resource context])
Remove a directory */
PHP_FUNCTION(rmdir)
{
- zval **arg1;
- int ret;
-
- if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
- WRONG_PARAM_COUNT;
- }
-
- convert_to_string_ex(arg1);
+ char *dir;
+ long dir_len;
+ zval *zcontext = NULL;
+ php_stream_context *context;
- if (PG(safe_mode) &&(!php_checkuid(Z_STRVAL_PP(arg1), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &dir, &dir_len, &zcontext) == FAILURE) {
RETURN_FALSE;
}
- if (php_check_open_basedir(Z_STRVAL_PP(arg1) TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- ret = VCWD_RMDIR(Z_STRVAL_PP(arg1));
- if (ret < 0) {
- php_error_docref1(NULL TSRMLS_CC, Z_STRVAL_PP(arg1), E_WARNING, "%s", strerror(errno));
- RETURN_FALSE;
- }
+ context = php_stream_context_from_zval(zcontext, 0);
- RETURN_TRUE;
+ RETURN_BOOL(php_stream_rmdir(dir, REPORT_ERRORS, context));
}
/* }}} */
}
/* }}} */
+/* {{{ php_stream_ftp_mkdir
+ */
+static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC)
+{
+ php_stream *stream = NULL;
+ php_url *resource = NULL;
+ int result, recursive = options & PHP_STREAM_MKDIR_RECURSIVE;
+ char tmp_line[512];
+
+ stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, NULL, NULL, &resource, NULL, NULL TSRMLS_CC);
+ if (!stream) {
+ if (options & REPORT_ERRORS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", url);
+ }
+ goto mkdir_errexit;
+ }
+
+ if (resource->path == NULL) {
+ if (options & REPORT_ERRORS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path provided in %s", url);
+ }
+ goto mkdir_errexit;
+ }
+
+ if (!recursive) {
+ php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", resource->path);
+ result = GET_FTP_RESULT(stream);
+ } else {
+ /* we look for directory separator from the end of string, thus hopefuly reducing our work load */
+ char *p, *e, *buf;
+
+ buf = estrdup(resource->path);
+ e = buf + strlen(buf);
+
+ /* find a top level directory we need to create */
+ while ((p = strrchr(buf, '/'))) {
+ *p = '\0';
+ php_stream_printf(stream TSRMLS_CC, "CWD %s\r\n", buf);
+ result = GET_FTP_RESULT(stream);
+ if (result >= 200 && result <= 299) {
+ *p = '/';
+ break;
+ }
+ }
+ if (p == buf) {
+ php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", resource->path);
+ result = GET_FTP_RESULT(stream);
+ } else {
+ php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", buf);
+ result = GET_FTP_RESULT(stream);
+ if (result >= 200 && result <= 299) {
+ if (!p) {
+ p = buf;
+ }
+ /* create any needed directories if the creation of the 1st directory worked */
+ while (++p != e) {
+ if (*p == '\0' && *(p + 1) != '\0') {
+ *p = '/';
+ php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", buf);
+ result = GET_FTP_RESULT(stream);
+ if (result < 200 || result > 299) {
+ if (options & REPORT_ERRORS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tmp_line);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ efree(buf);
+ }
+
+ php_url_free(resource);
+ php_stream_close(stream);
+
+ if (result < 200 || result > 299) {
+ /* Failure */
+ return 0;
+ }
+
+ return 1;
+
+ mkdir_errexit:
+ if (resource) {
+ php_url_free(resource);
+ }
+ if (stream) {
+ php_stream_close(stream);
+ }
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_stream_ftp_rmdir
+ */
+static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
+{
+ php_stream *stream = NULL;
+ php_url *resource = NULL;
+ int result;
+ char tmp_line[512];
+
+ stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, NULL, NULL, &resource, NULL, NULL TSRMLS_CC);
+ if (!stream) {
+ if (options & REPORT_ERRORS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", url);
+ }
+ goto rmdir_errexit;
+ }
+
+ if (resource->path == NULL) {
+ if (options & REPORT_ERRORS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path provided in %s", url);
+ }
+ goto rmdir_errexit;
+ }
+
+ php_stream_printf(stream TSRMLS_CC, "RMD %s\r\n", resource->path);
+ result = GET_FTP_RESULT(stream);
+
+ if (result < 200 || result > 299) {
+ if (options & REPORT_ERRORS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tmp_line);
+ }
+ goto rmdir_errexit;
+ }
+
+ php_url_free(resource);
+ php_stream_close(stream);
+
+ return 1;
+
+ rmdir_errexit:
+ if (resource) {
+ php_url_free(resource);
+ }
+ if (stream) {
+ php_stream_close(stream);
+ }
+ return 0;
+}
+/* }}} */
+
static php_stream_wrapper_ops ftp_stream_wops = {
php_stream_url_wrap_ftp,
php_stream_ftp_stream_close, /* stream_close */
php_stream_ftp_opendir, /* opendir */
"FTP",
php_stream_ftp_unlink, /* unlink */
- php_stream_ftp_rename /* rename */
+ php_stream_ftp_rename, /* rename */
+ php_stream_ftp_mkdir, /* mkdir */
+ php_stream_ftp_rmdir /* rmdir */
};
PHPAPI php_stream_wrapper php_stream_ftp_wrapper = {
"HTTP",
NULL, /* unlink */
NULL, /* rename */
+ NULL, /* mkdir */
+ NULL /* rmdir */
};
PHPAPI php_stream_wrapper php_stream_http_wrapper = {
NULL, /* opendir */
"PHP",
NULL, /* unlink */
- NULL /* rename */
+ NULL, /* rename */
+ NULL, /* mkdir */
+ NULL /* rmdir */
};
php_stream_wrapper php_stream_php_wrapper = {
NULL, /* opendir */
"ZLIB",
NULL, /* unlink */
- NULL /* rename */
+ NULL, /* rename */
+ NULL, /* mkdir */
+ NULL /* rmdir */
};
php_stream_wrapper php_stream_gzip_wrapper = {
/* rename a file */
int (*rename)(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
+
+ /* Create/Remove directory */
+ int (*mkdir)(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC);
+ int (*rmdir)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
} php_stream_wrapper_ops;
struct _php_stream_wrapper {
#define php_stream_stat_path(path, ssb) _php_stream_stat_path((path), 0, (ssb), NULL TSRMLS_CC)
#define php_stream_stat_path_ex(path, flags, ssb, context) _php_stream_stat_path((path), (flags), (ssb), (context) TSRMLS_CC)
+PHPAPI int _php_stream_mkdir(char *path, int mode, int options, php_stream_context *context TSRMLS_DC);
+#define php_stream_mkdir(path, mode, options, context) _php_stream_mkdir(path, mode, options, context TSRMLS_CC)
+
+PHPAPI int _php_stream_rmdir(char *path, int options, php_stream_context *context TSRMLS_DC);
+#define php_stream_rmdir(path, options, context) _php_stream_rmdir(path, options, context TSRMLS_CC)
+
PHPAPI php_stream *_php_stream_opendir(char *path, int options, php_stream_context *context STREAMS_DC TSRMLS_DC);
#define php_stream_opendir(path, options, context) _php_stream_opendir((path), (options), (context) STREAMS_CC TSRMLS_CC)
PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_dirent *ent TSRMLS_DC);
#define php_stream_set_chunk_size(stream, size) _php_stream_set_option((stream), PHP_STREAM_OPTION_SET_CHUNK_SIZE, (size), NULL TSRMLS_CC)
+/* Flags for mkdir method in wrapper ops */
+#define PHP_STREAM_MKDIR_RECURSIVE 1
+/* define REPORT ERRORS 8 (below) */
+
+/* Flags for rmdir method in wrapper ops */
+/* define REPORT_ERRORS 8 (below) */
+
/* Flags for url_stat method in wrapper ops */
#define PHP_STREAM_URL_STAT_LINK 1
#define PHP_STREAM_URL_STAT_QUIET 2
return 1;
}
+static int php_plain_files_mkdir(php_stream_wrapper *wrapper, char *dir, int mode, int options, php_stream_context *context TSRMLS_DC)
+{
+ int ret, recursive = options & PHP_STREAM_MKDIR_RECURSIVE;
+ char *p;
+
+ if ((p = strstr(dir, "://")) != NULL) {
+ dir = p + 3;
+ }
+
+ if (!recursive) {
+ ret = php_mkdir(dir, mode TSRMLS_CC);
+ } else {
+ /* we look for directory separator from the end of string, thus hopefuly reducing our work load */
+ char *e, *buf;
+ struct stat sb;
+ int dir_len = strlen(dir);
+
+ buf = estrndup(dir, dir_len);
+ e = buf + dir_len;
+
+ /* find a top level directory we need to create */
+ while ((p = strrchr(buf, DEFAULT_SLASH))) {
+ *p = '\0';
+ if (VCWD_STAT(buf, &sb) == 0) {
+ *p = DEFAULT_SLASH;
+ break;
+ }
+ }
+ if (p == buf) {
+ ret = php_mkdir(dir, mode TSRMLS_CC);
+ } else if (!(ret = php_mkdir(buf, mode TSRMLS_CC))) {
+ if (!p) {
+ p = buf;
+ }
+ /* create any needed directories if the creation of the 1st directory worked */
+ while (++p != e) {
+ if (*p == '\0' && *(p + 1) != '\0') {
+ *p = DEFAULT_SLASH;
+ if ((ret = VCWD_MKDIR(buf, (mode_t)mode)) < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
+ break;
+ }
+ }
+ }
+ }
+ efree(buf);
+ }
+ if (ret < 0) {
+ /* Failure */
+ return 0;
+ } else {
+ /* Success */
+ return 1;
+ }
+}
+
+static int php_plain_files_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
+{
+ if (PG(safe_mode) &&(!php_checkuid(url, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
+ return 0;
+ }
+
+ if (php_check_open_basedir(url TSRMLS_CC)) {
+ return 0;
+ }
+
+ if (VCWD_RMDIR(url) < 0) {
+ php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "%s", strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
php_plain_files_stream_opener,
NULL,
php_plain_files_dir_opener,
"plainfile",
php_plain_files_unlink,
- php_plain_files_rename
+ php_plain_files_rename,
+ php_plain_files_mkdir,
+ php_plain_files_rmdir
};
php_stream_wrapper php_plain_files_wrapper = {
}
/* }}} */
+/* {{{ _php_stream_mkdir
+ */
+PHPAPI int _php_stream_mkdir(char *path, int mode, int options, php_stream_context *context TSRMLS_DC)
+{
+ php_stream_wrapper *wrapper = NULL;
+
+ wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC);
+ if (!wrapper || !wrapper->wops || !wrapper->wops->mkdir) {
+ return 0;
+ }
+
+ return wrapper->wops->mkdir(wrapper, path, mode, options, context TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ _php_stream_rmdir
+ */
+PHPAPI int _php_stream_rmdir(char *path, int options, php_stream_context *context TSRMLS_DC)
+{
+ php_stream_wrapper *wrapper = NULL;
+
+ wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC);
+ if (!wrapper || !wrapper->wops || !wrapper->wops->rmdir) {
+ return 0;
+ }
+
+ return wrapper->wops->rmdir(wrapper, path, options, context TSRMLS_CC);
+}
+/* }}} */
+
/* {{{ _php_stream_stat_path */
PHPAPI int _php_stream_stat_path(char *path, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
{
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Wez Furlong <wez@thebrainroom.com> |
+ | Sara Golemon <pollita@php.net> |
+----------------------------------------------------------------------+
*/
static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);
static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
+static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC);
+static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filename, char *mode,
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
user_wrapper_opendir,
"user-space",
user_wrapper_unlink,
- user_wrapper_rename
+ user_wrapper_rename,
+ user_wrapper_mkdir,
+ user_wrapper_rmdir
};
#define USERSTREAM_STATURL "url_stat"
#define USERSTREAM_UNLINK "unlink"
#define USERSTREAM_RENAME "rename"
+#define USERSTREAM_MKDIR "mkdir"
+#define USERSTREAM_RMDIR "rmdir"
#define USERSTREAM_DIR_OPEN "dir_opendir"
#define USERSTREAM_DIR_READ "dir_readdir"
#define USERSTREAM_DIR_REWIND "dir_rewinddir"
return true / false;
}
+ function mkdir($dir, $mode, $options)
+ {
+ return true / false;
+ }
+
+ function rmdir($dir, $options)
+ {
+ return true / false;
+ }
+
function dir_opendir(string $url, int $options)
{
return true / false;
return ret;
}
+static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC)
+{
+ struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
+ zval *zfilename, *zmode, *zoptions, *zfuncname, *zretval, *zcontext;
+ zval **args[3];
+ int call_result;
+ zval *object;
+ int ret = 0;
+
+ /* create an instance of our class */
+ ALLOC_ZVAL(object);
+ object_init_ex(object, uwrap->ce);
+ ZVAL_REFCOUNT(object) = 1;
+ PZVAL_IS_REF(object) = 1;
+
+ if (context) {
+ MAKE_STD_ZVAL(zcontext);
+ php_stream_context_to_zval(context, zcontext);
+ add_property_zval(object, "context", zcontext);
+ /* The object property should be the only reference,
+ 'get rid' of our local reference. */
+ zval_ptr_dtor(&zcontext);
+ } else {
+ add_property_null(object, "context");
+ }
+
+ /* call the unlink method */
+ MAKE_STD_ZVAL(zfilename);
+ ZVAL_STRING(zfilename, url, 1);
+ args[0] = &zfilename;
+
+ MAKE_STD_ZVAL(zmode);
+ ZVAL_LONG(zmode, mode);
+ args[1] = &zmode;
+
+ MAKE_STD_ZVAL(zoptions);
+ ZVAL_LONG(zoptions, options);
+ args[2] = &zoptions;
+
+ MAKE_STD_ZVAL(zfuncname);
+ ZVAL_STRING(zfuncname, USERSTREAM_MKDIR, 1);
+
+ call_result = call_user_function_ex(NULL,
+ &object,
+ zfuncname,
+ &zretval,
+ 3, args,
+ 0, NULL TSRMLS_CC);
+
+ if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) {
+ ret = Z_LVAL_P(zretval);
+ } else if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", uwrap->classname);
+ }
+
+ /* clean up */
+ zval_ptr_dtor(&object);
+ if (zretval) {
+ zval_ptr_dtor(&zretval);
+ }
+
+ zval_ptr_dtor(&zfuncname);
+ zval_ptr_dtor(&zfilename);
+ zval_ptr_dtor(&zmode);
+ zval_ptr_dtor(&zoptions);
+
+ return ret;
+}
+
+static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
+{
+ struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
+ zval *zfilename, *zmode, *zoptions, *zfuncname, *zretval, *zcontext;
+ zval **args[3];
+ int call_result;
+ zval *object;
+ int ret = 0;
+
+ /* create an instance of our class */
+ ALLOC_ZVAL(object);
+ object_init_ex(object, uwrap->ce);
+ ZVAL_REFCOUNT(object) = 1;
+ PZVAL_IS_REF(object) = 1;
+
+ if (context) {
+ MAKE_STD_ZVAL(zcontext);
+ php_stream_context_to_zval(context, zcontext);
+ add_property_zval(object, "context", zcontext);
+ /* The object property should be the only reference,
+ 'get rid' of our local reference. */
+ zval_ptr_dtor(&zcontext);
+ } else {
+ add_property_null(object, "context");
+ }
+
+ /* call the unlink method */
+ MAKE_STD_ZVAL(zfilename);
+ ZVAL_STRING(zfilename, url, 1);
+ args[0] = &zfilename;
+
+ MAKE_STD_ZVAL(zoptions);
+ ZVAL_LONG(zoptions, options);
+ args[1] = &zoptions;
+
+ MAKE_STD_ZVAL(zfuncname);
+ ZVAL_STRING(zfuncname, USERSTREAM_RMDIR, 1);
+
+ call_result = call_user_function_ex(NULL,
+ &object,
+ zfuncname,
+ &zretval,
+ 2, args,
+ 0, NULL TSRMLS_CC);
+
+ if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) {
+ ret = Z_LVAL_P(zretval);
+ } else if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", uwrap->classname);
+ }
+
+ /* clean up */
+ zval_ptr_dtor(&object);
+ if (zretval) {
+ zval_ptr_dtor(&zretval);
+ }
+
+ zval_ptr_dtor(&zfuncname);
+ zval_ptr_dtor(&zfilename);
+ zval_ptr_dtor(&zoptions);
+
+ return ret;
+}
+
static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
{
struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;