Skip to content

Refactor user streams #5876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ext/standard/tests/file/userstreams.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,11 @@ class mystream

}

if (@stream_wrapper_register("bogus", "class_not_exist")) {
try {
stream_wrapper_register("bogus", "class_not_exist");
die("Registered a non-existent class!!!???");
} catch (\TypeError $e) {
echo $e->getMessage() . \PHP_EOL;
}
echo "Not Registered\n";

Expand Down Expand Up @@ -315,6 +318,7 @@ echo $data . "\n";

?>
--EXPECT--
stream_wrapper_register(): Argument #2 ($classname) must be a valid class name, class_not_exist given
Not Registered
Registered
Registered
Expand Down
81 changes: 38 additions & 43 deletions main/streams/userspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ static int le_protocols;

struct php_user_stream_wrapper {
char * protoname;
char * classname;
zend_class_entry *ce;
php_stream_wrapper wrapper;
};
Expand Down Expand Up @@ -71,7 +70,6 @@ static void stream_wrapper_dtor(zend_resource *rsrc)
struct php_user_stream_wrapper * uwrap = (struct php_user_stream_wrapper*)rsrc->ptr;

efree(uwrap->protoname);
efree(uwrap->classname);
efree(uwrap);
}

Expand Down Expand Up @@ -375,7 +373,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *
ZVAL_COPY(&stream->wrapperdata, &us->object);
} else {
php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_OPEN "\" call failed",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
}

/* destroy everything else */
Expand Down Expand Up @@ -444,7 +442,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char
ZVAL_COPY(&stream->wrapperdata, &us->object);
} else {
php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
}

/* destroy everything else */
Expand All @@ -468,38 +466,35 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char
/* {{{ Registers a custom URL protocol handler class */
PHP_FUNCTION(stream_wrapper_register)
{
zend_string *protocol, *classname;
struct php_user_stream_wrapper * uwrap;
zend_string *protocol;
struct php_user_stream_wrapper *uwrap;
zend_class_entry *ce = NULL;
zend_resource *rsrc;
zend_long flags = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &protocol, &classname, &flags) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "SC|l", &protocol, &ce, &flags) == FAILURE) {
RETURN_THROWS();
}

uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
uwrap->ce = ce;
uwrap->protoname = estrndup(ZSTR_VAL(protocol), ZSTR_LEN(protocol));
uwrap->classname = estrndup(ZSTR_VAL(classname), ZSTR_LEN(classname));
uwrap->wrapper.wops = &user_stream_wops;
uwrap->wrapper.abstract = uwrap;
uwrap->wrapper.is_url = ((flags & PHP_STREAM_IS_URL) != 0);

rsrc = zend_register_resource(uwrap, le_protocols);

if ((uwrap->ce = zend_lookup_class(classname)) != NULL) {
if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper) == SUCCESS) {
RETURN_TRUE;
} else {
/* We failed. But why? */
if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol)) {
php_error_docref(NULL, E_WARNING, "Protocol %s:// is already defined.", ZSTR_VAL(protocol));
} else {
/* Hash doesn't exist so it must have been an invalid protocol scheme */
php_error_docref(NULL, E_WARNING, "Invalid protocol scheme specified. Unable to register wrapper class %s to %s://", ZSTR_VAL(classname), ZSTR_VAL(protocol));
}
}
if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper) == SUCCESS) {
RETURN_TRUE;
}

/* We failed. But why? */
if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol)) {
php_error_docref(NULL, E_WARNING, "Protocol %s:// is already defined.", ZSTR_VAL(protocol));
} else {
php_error_docref(NULL, E_WARNING, "Class '%s' is undefined", ZSTR_VAL(classname));
/* Hash doesn't exist so it must have been an invalid protocol scheme */
php_error_docref(NULL, E_WARNING, "Invalid protocol scheme specified. Unable to register wrapper class %s to %s://", ZSTR_VAL(uwrap->ce->name), ZSTR_VAL(protocol));
}

zend_list_delete(rsrc);
Expand Down Expand Up @@ -596,14 +591,14 @@ static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_
}
} else {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
didwrite = -1;
}

/* don't allow strange buffer overruns due to bogus return */
if (didwrite > 0 && didwrite > count) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " wrote " ZEND_LONG_FMT " bytes more data than requested (" ZEND_LONG_FMT " written, " ZEND_LONG_FMT " max)",
us->wrapper->classname,
ZSTR_VAL(us->wrapper->ce->name),
(zend_long)(didwrite - count), (zend_long)didwrite, (zend_long)count);
didwrite = count;
}
Expand Down Expand Up @@ -643,7 +638,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count

if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
return -1;
}

Expand All @@ -659,7 +654,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
if (didread > 0) {
if (didread > count) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " - read " ZEND_LONG_FMT " bytes more data than requested (" ZEND_LONG_FMT " read, " ZEND_LONG_FMT " max) - excess data will be lost",
us->wrapper->classname, (zend_long)(didread - count), (zend_long)didread, (zend_long)count);
ZSTR_VAL(us->wrapper->ce->name), (zend_long)(didread - count), (zend_long)didread, (zend_long)count);
didread = count;
}
memcpy(buf, Z_STRVAL(retval), didread);
Expand Down Expand Up @@ -688,7 +683,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING,
"%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));

stream->eof = 1;
}
Expand Down Expand Up @@ -812,7 +807,7 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when
*newoffs = Z_LVAL(retval);
ret = 0;
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", us->wrapper->classname);
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", ZSTR_VAL(us->wrapper->ce->name));
ret = -1;
} else {
ret = -1;
Expand Down Expand Up @@ -884,7 +879,7 @@ static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb)
} else {
if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
}
}

Expand Down Expand Up @@ -913,7 +908,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
ret = PHP_STREAM_OPTION_RETURN_ERR;
php_error_docref(NULL, E_WARNING,
"%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
}
zval_ptr_dtor(&retval);
zval_ptr_dtor(&func_name);
Expand Down Expand Up @@ -954,7 +949,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
ret = PHP_STREAM_OPTION_RETURN_OK;
} else {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
ret = PHP_STREAM_OPTION_RETURN_ERR;
}
}
Expand Down Expand Up @@ -993,12 +988,12 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
} else {
php_error_docref(NULL, E_WARNING,
"%s::" USERSTREAM_TRUNCATE " did not return a boolean!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
}
} else {
php_error_docref(NULL, E_WARNING,
"%s::" USERSTREAM_TRUNCATE " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
}
zval_ptr_dtor(&retval);
zval_ptr_dtor(&args[0]);
Expand Down Expand Up @@ -1053,7 +1048,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value

if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
ret = PHP_STREAM_OPTION_RETURN_ERR;
} else if (zend_is_true(&retval)) {
ret = PHP_STREAM_OPTION_RETURN_OK;
Expand Down Expand Up @@ -1104,7 +1099,7 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
ret = (Z_TYPE(zretval) == IS_TRUE);
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", uwrap->classname);
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", ZSTR_VAL(uwrap->ce->name));
}

/* clean up */
Expand Down Expand Up @@ -1148,7 +1143,7 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
ret = (Z_TYPE(zretval) == IS_TRUE);
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", uwrap->classname);
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", ZSTR_VAL(uwrap->ce->name));
}

/* clean up */
Expand Down Expand Up @@ -1194,7 +1189,7 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
ret = (Z_TYPE(zretval) == IS_TRUE);
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", uwrap->classname);
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
}

/* clean up */
Expand Down Expand Up @@ -1240,7 +1235,7 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url,
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
ret = (Z_TYPE(zretval) == IS_TRUE);
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", uwrap->classname);
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
}

/* clean up */
Expand Down Expand Up @@ -1310,7 +1305,7 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
ret = Z_TYPE(zretval) == IS_TRUE;
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", uwrap->classname);
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", ZSTR_VAL(uwrap->ce->name));
}

/* clean up */
Expand Down Expand Up @@ -1361,7 +1356,7 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, i
} else {
if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!",
uwrap->classname);
ZSTR_VAL(uwrap->ce->name));
}
}

Expand Down Expand Up @@ -1405,7 +1400,7 @@ static ssize_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t co
didread = sizeof(php_stream_dirent);
} else if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
}

zval_ptr_dtor(&retval);
Expand Down Expand Up @@ -1491,7 +1486,7 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
do {
if (call_result == FAILURE) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
break;
}
if (!zend_is_true(&retval)) {
Expand All @@ -1500,12 +1495,12 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
php_stream_from_zval_no_verify(intstream, &retval);
if (!intstream) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must return a stream resource",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
break;
}
if (intstream == stream) {
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must not return itself",
us->wrapper->classname);
ZSTR_VAL(us->wrapper->ce->name));
intstream = NULL;
break;
}
Expand Down