diff options
Diffstat (limited to 'main')
| -rwxr-xr-x | main/php_streams.h | 3 | ||||
| -rw-r--r-- | main/streams/plain_wrapper.c | 46 | ||||
| -rw-r--r-- | main/streams/userspace.c | 73 |
3 files changed, 120 insertions, 2 deletions
diff --git a/main/php_streams.h b/main/php_streams.h index 5451b8382f..f3d2ceedcb 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -148,6 +148,9 @@ typedef struct _php_stream_wrapper_ops { /* delete a file */ int (*unlink)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); + + /* rename a file */ + int (*rename)(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC); } php_stream_wrapper_ops; struct _php_stream_wrapper { diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 008e283367..3e2f67b57f 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -956,6 +956,49 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, char *url, int op return 1; } +static int php_plain_files_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) +{ + char *p; + int ret; + + if (!url_from || !url_to) { + return 0; + } + + if ((p = strstr(url_from, "://")) != NULL) { + url_from = p + 3; + } + + if ((p = strstr(url_to, "://")) != NULL) { + url_to = p + 3; + } + + if (PG(safe_mode) &&(!php_checkuid(url_from, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { + return 0; + } + + if (php_check_open_basedir(url_from TSRMLS_CC)) { + return 0; + } + + ret = VCWD_RENAME(url_from, url_to); + + if (ret == -1) { +#ifdef EXDEV + if (errno == EXDEV) { + if (php_copy_file(url_from, url_to TSRMLS_CC) == SUCCESS) { + VCWD_UNLINK(url_from); + return 1; + } + } +#endif + php_error_docref2(NULL TSRMLS_CC, url_from, url_to, 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, @@ -963,7 +1006,8 @@ static php_stream_wrapper_ops php_plain_files_wrapper_ops = { php_plain_files_url_stater, php_plain_files_dir_opener, "plainfile", - php_plain_files_unlink + php_plain_files_unlink, + php_plain_files_rename }; php_stream_wrapper php_plain_files_wrapper = { diff --git a/main/streams/userspace.c b/main/streams/userspace.c index ecacfb73b6..2176229248 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -34,6 +34,7 @@ struct php_user_stream_wrapper { 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); 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 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); @@ -44,7 +45,8 @@ static php_stream_wrapper_ops user_stream_wops = { user_wrapper_stat_url, user_wrapper_opendir, "user-space", - user_wrapper_unlink + user_wrapper_unlink, + user_wrapper_rename }; @@ -95,6 +97,7 @@ typedef struct _php_userstream_data php_userstream_data_t; #define USERSTREAM_STAT "stream_stat" #define USERSTREAM_STATURL "url_stat" #define USERSTREAM_UNLINK "unlink" +#define USERSTREAM_RENAME "rename" #define USERSTREAM_DIR_OPEN "dir_opendir" #define USERSTREAM_DIR_READ "dir_readdir" #define USERSTREAM_DIR_REWIND "dir_rewinddir" @@ -158,6 +161,11 @@ typedef struct _php_userstream_data php_userstream_data_t; return true / false; } + function rename(string $from, string $to) + { + return true / false; + } + function dir_opendir(string $url, int $options) { return true / false; @@ -791,6 +799,69 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio return ret; } +static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) +{ + struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; + zval *zold_name, *znew_name, *zfuncname, *zretval, *zcontext; + zval **args[2]; + 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 rename method */ + MAKE_STD_ZVAL(zold_name); + ZVAL_STRING(zold_name, url_from, 1); + args[0] = &zold_name; + + MAKE_STD_ZVAL(znew_name); + ZVAL_STRING(znew_name, url_to, 1); + args[1] = &znew_name; + + MAKE_STD_ZVAL(zfuncname); + ZVAL_STRING(zfuncname, USERSTREAM_RENAME, 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_RENAME " is not implemented!", uwrap->classname); + } + + /* clean up */ + zval_ptr_dtor(&object); + if (zretval) + zval_ptr_dtor(&zretval); + + zval_ptr_dtor(&zfuncname); + zval_ptr_dtor(&zold_name); + zval_ptr_dtor(&znew_name); + + 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; |
