From 760573695c00921198363f16b4ac414954e66478 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Tue, 30 Apr 2002 00:28:24 +0000 Subject: [PATCH] Implement user-space funtions to operate on stream contexts. --- ext/standard/basic_functions.c | 6 +- ext/standard/file.c | 125 ++++++++++++++++++++++++++++++--- ext/standard/file.h | 6 +- 3 files changed, 125 insertions(+), 12 deletions(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 85be8bcf6e..286ba2845a 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -595,8 +595,10 @@ function_entry basic_functions[] = { PHP_STATIC_FE("tmpfile", php_if_tmpfile, NULL) PHP_FE(file, NULL) PHP_FE(file_get_contents, NULL) - PHP_FE(file_context_create, NULL) - PHP_FE(file_context_set_params, NULL) + PHP_FE(stream_context_create, NULL) + PHP_FE(stream_context_set_params, NULL) + PHP_FE(stream_context_set_option, NULL) + PHP_FE(stream_context_get_options, NULL) PHP_FE(fgetcsv, NULL) PHP_FE(flock, NULL) PHP_FE(get_meta_tags, NULL) diff --git a/ext/standard/file.c b/ext/standard/file.c index f5f33e61c8..c8a14afb59 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -582,7 +582,7 @@ PHP_FUNCTION(file_get_wrapper_data) } /* }}} */ -/* {{{ file_context related functions */ +/* {{{ stream_context related functions */ static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity, char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC) { @@ -618,7 +618,39 @@ static void user_space_stream_notifier(php_stream_context *context, int notifyco zval_ptr_dtor(&retval); } -static int parse_context_options(php_stream_context *context, zval *params) +static int parse_context_options(php_stream_context *context, zval *options) +{ + HashPosition pos, opos; + zval **wval, **oval; + char *wkey, *okey; + int wkey_len, okey_len; + int ret = SUCCESS; + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(options), &pos); + while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(options), (void**)&wval, &pos)) { + if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &wkey, &wkey_len, NULL, 0, &pos) + && Z_TYPE_PP(wval) == IS_ARRAY) { + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(wval), &opos); + while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(wval), (void**)&oval, &opos)) { + + if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_PP(wval), &okey, &okey_len, NULL, 0, &opos)) { + ZVAL_ADDREF(*oval); + php_stream_context_set_option(context, wkey, okey, *oval); + } + zend_hash_move_forward_ex(Z_ARRVAL_PP(wval), &opos); + } + + } else { + zend_error(E_WARNING, "options should have the form [\"wrappername\"][\"optionname\"] = $value"); + } + zend_hash_move_forward_ex(Z_ARRVAL_P(options), &pos); + } + + return ret; +} + +static int parse_context_params(php_stream_context *context, zval *params) { int ret = SUCCESS; zval **tmp; @@ -635,14 +667,91 @@ static int parse_context_options(php_stream_context *context, zval *params) context->notifier->ptr = *tmp; ZVAL_ADDREF(*tmp); } + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), "options", sizeof("options"), (void**)&tmp)) { + parse_context_options(context, *tmp); + } return ret; } + +/* given a zval which is either a stream or a context, return the underlying + * stream_context. If it is a stream that does not have a context assigned, it + * will create and assign a context and return that. */ +static php_stream_context *decode_context_param(zval *contextresource) { + php_stream_context *context = NULL; void *what; int type; + + what = zend_fetch_resource(&contextresource TSRMLS_CC, -1, "Stream-Context", &type, 2, le_stream_context, le_stream); + + if (what && type == le_stream) { + php_stream *stream = (php_stream*)what; + context = stream->context; + if (context == NULL) + context = stream->context = php_stream_context_alloc(); + } else if (what && type == le_stream_context) { + context = (php_stream_context*)what; + } + return context; +} +/* }}} */ + +/* {{{ proto array stream_context_get_options(resource context|resource stream) + Retrieve options for a stream/wrapper/context */ +PHP_FUNCTION(stream_context_get_options) +{ + zval *zcontext; + php_stream_context *context; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zcontext) == FAILURE) { + RETURN_FALSE; + } + context = decode_context_param(zcontext); + ZEND_VERIFY_RESOURCE(context); + + array_init(return_value); + *return_value = *context->options; + zval_copy_ctor(return_value); +} +/* }}} */ + +/* {{{ proto bool stream_context_set_option(resource context|resource stream, string wrappername, string optionname, mixed value) + Set an option for a wrapper */ +PHP_FUNCTION(stream_context_set_option) +{ + zval *options = NULL, *zcontext = NULL, *zvalue = NULL; + php_stream_context *context; + char *wrappername, *optionname; + long wrapperlen, optionlen; + + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, + "rssz", &zcontext, &wrappername, &wrapperlen, + &optionname, &optionlen, &zvalue) == FAILURE) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, + "ra", &zcontext, &options) == FAILURE) { + zend_error(E_WARNING, "%s() called with wrong number or type of parameters; please RTM", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + } + + /* figure out where the context is coming from exactly */ + context = decode_context_param(zcontext); + ZEND_VERIFY_RESOURCE(context); + + if (options) { + /* handle the array syntax */ + RETVAL_BOOL(parse_context_options(context, options) == SUCCESS); + } else { + ZVAL_ADDREF(zvalue); + php_stream_context_set_option(context, wrappername, optionname, zvalue); + RETVAL_TRUE; + } + +} /* }}} */ -/* {{{ proto bool file_context_set_params(resource context, array options) +/* {{{ proto bool stream_context_set_params(resource context|resource stream, array options) Set parameters for a file context */ -PHP_FUNCTION(file_context_set_params) +PHP_FUNCTION(stream_context_set_params) { zval *params, *zcontext; php_stream_context *context; @@ -651,16 +760,16 @@ PHP_FUNCTION(file_context_set_params) RETURN_FALSE; } - context = (php_stream_context*)zend_fetch_resource(&zcontext TSRMLS_CC, -1, "Stream-Context", NULL, 1, le_stream_context); + context = decode_context_param(zcontext); ZEND_VERIFY_RESOURCE(context); - RETVAL_BOOL(parse_context_options(context, params) == SUCCESS); + RETVAL_BOOL(parse_context_params(context, params) == SUCCESS); } /* }}} */ -/* {{{ proto resource file_context_create([array options]) +/* {{{ proto resource stream_context_create([array options]) Create a file context and optionally set parameters */ -PHP_FUNCTION(file_context_create) +PHP_FUNCTION(stream_context_create) { zval *params = NULL; php_stream_context *context; diff --git a/ext/standard/file.h b/ext/standard/file.h index 3261aaba08..e861bd88e6 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -73,8 +73,10 @@ PHP_NAMED_FUNCTION(php_if_fstat); PHP_FUNCTION(file_get_wrapper_data); PHP_FUNCTION(file_register_wrapper); -PHP_FUNCTION(file_context_create); -PHP_FUNCTION(file_context_set_params); +PHP_FUNCTION(stream_context_create); +PHP_FUNCTION(stream_context_set_params); +PHP_FUNCTION(stream_context_set_option); +PHP_FUNCTION(stream_context_get_options); PHP_MINIT_FUNCTION(user_streams); PHPAPI int php_set_sock_blocking(int socketd, int block); -- 2.40.0