php源码中对post数据的处理过程_php post数据进行处理-程序员宅基地

技术标签: php  源码  

一、php_ap2_register_hook函数注册ap_hook_post_configphp_apache_server_startup函数

void php_ap2_register_hook(apr_pool_t *p)
{
	ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}


二、php_apache_server_startup函数中调用apache2_sapi_module结构体变量中的startup函数

static int php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
	void *data = NULL;
	const char *userdata_key = "apache2hook_post_config";

	/* Apache will load, unload and then reload a DSO module. This
	 * prevents us from starting PHP until the second load. */
	apr_pool_userdata_get(&data, userdata_key, s->process->pool);
	if (data == NULL) {
		/* We must use set() here and *not* setn(), otherwise the
		 * static string pointed to by userdata_key will be mapped
		 * to a different location when the DSO is reloaded and the
		 * pointers won't match, causing get() to return NULL when
		 * we expected it to return non-NULL. */
		apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, s->process->pool);
		return OK;
	}

	/* Set up our overridden path. */
	if (apache2_php_ini_path_override) {
		apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override;
	}
#ifdef ZTS
	tsrm_startup(1, 1, 0, NULL);
#endif
	sapi_startup(&apache2_sapi_module);
	apache2_sapi_module.startup(&apache2_sapi_module);
	apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null);
	php_apache_add_version(pconf);

	return OK;
}
apache2_sapi_module结构体的声明如下

static sapi_module_struct apache2_sapi_module = {
	"apache2handler",
	"Apache 2.0 Handler",

	php_apache2_startup,				/* startup */
	php_module_shutdown_wrapper,			/* shutdown */

	NULL,						/* activate */
	NULL,						/* deactivate */

	php_apache_sapi_ub_write,			/* unbuffered write */
	php_apache_sapi_flush,				/* flush */
	php_apache_sapi_get_stat,			/* get uid */
	php_apache_sapi_getenv,				/* getenv */

	php_error,					/* error handler */

	php_apache_sapi_header_handler,			/* header handler */
	php_apache_sapi_send_headers,			/* send headers handler */
	NULL,						/* send header handler */

	php_apache_sapi_read_post,			/* read POST data */
	php_apache_sapi_read_cookies,			/* read Cookies */

	php_apache_sapi_register_variables,
	php_apache_sapi_log_message,			/* Log message */
	php_apache_sapi_get_request_time,		/* Request Time */
	NULL,						/* Child Terminate */

	STANDARD_SAPI_MODULE_PROPERTIES
};

sapi_module_struct结构体

<pre name="code" class="cpp">struct _sapi_module_struct {
	char *name;
	char *pretty_name;

	int (*startup)(struct _sapi_module_struct *sapi_module);
	int (*shutdown)(struct _sapi_module_struct *sapi_module);

	int (*activate)(TSRMLS_D);
	int (*deactivate)(TSRMLS_D);

	int (*ub_write)(const char *str, unsigned int str_length TSRMLS_DC);
	void (*flush)(void *server_context);
	struct stat *(*get_stat)(TSRMLS_D);
	char *(*getenv)(char *name, size_t name_len TSRMLS_DC);

	void (*sapi_error)(int type, const char *error_msg, ...);

	int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC);
	int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC);
	void (*send_header)(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC);

	int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC);
	char *(*read_cookies)(TSRMLS_D);

	void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);
	void (*log_message)(char *message TSRMLS_DC);
	double (*get_request_time)(TSRMLS_D);
	void (*terminate_process)(TSRMLS_D);

	char *php_ini_path_override;

	void (*block_interruptions)(void);
	void (*unblock_interruptions)(void);

	void (*default_post_reader)(TSRMLS_D);
	void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC);
	char *executable_location;

	int php_ini_ignore;
	int php_ini_ignore_cwd; /* don't look for php.ini in the current directory */

	int (*get_fd)(int *fd TSRMLS_DC);

	int (*force_http_10)(TSRMLS_D);

	int (*get_target_uid)(uid_t * TSRMLS_DC);
	int (*get_target_gid)(gid_t * TSRMLS_DC);

	unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
	
	void (*ini_defaults)(HashTable *configuration_hash);
	int phpinfo_as_text;

	char *ini_entries;
	const zend_function_entry *additional_functions;
	unsigned int (*input_filter_init)(TSRMLS_D);
};

php_apache2_startup函数中调用php_module_startup函数

static int php_apache2_startup(sapi_module_struct *sapi_module)
{
	if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) {
		return FAILURE;
	}
	return SUCCESS;
}

main/main.c中php_module_startup函数调用php_startup_sapi_content_types

int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
{
	zend_utility_functions zuf;
	zend_utility_values zuv;
	int retval = SUCCESS, module_number=0;	/* for REGISTER_INI_ENTRIES() */
	char *php_os;
	zend_module_entry *module;
#ifdef ZTS
	zend_executor_globals *executor_globals;
	void ***tsrm_ls;
	php_core_globals *core_globals;
#endif

#if defined(PHP_WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
	WORD wVersionRequested = MAKEWORD(2, 0);
	WSADATA wsaData;
#endif
#ifdef PHP_WIN32
	php_os = "WINNT";
#if _MSC_VER >= 1400
	old_invalid_parameter_handler =
		_set_invalid_parameter_handler(dummy_invalid_parameter_handler);
	if (old_invalid_parameter_handler != NULL) {
		_set_invalid_parameter_handler(old_invalid_parameter_handler);
	}

	/* Disable the message box for assertions.*/
	_CrtSetReportMode(_CRT_ASSERT, 0);
#endif
#else
	php_os=PHP_OS;
#endif

#ifdef ZTS
	tsrm_ls = ts_resource(0);
#endif

#ifdef PHP_WIN32
	php_win32_init_rng_lock();
#endif

	module_shutdown = 0;
	module_startup = 1;
	sapi_initialize_empty_request(TSRMLS_C);
	sapi_activate(TSRMLS_C);

	if (module_initialized) {
		return SUCCESS;
	}

	sapi_module = *sf;

	php_output_startup();

	zuf.error_function = php_error_cb;
	zuf.printf_function = php_printf;
	zuf.write_function = php_output_wrapper;
	zuf.fopen_function = php_fopen_wrapper_for_zend;
	zuf.message_handler = php_message_handler_for_zend;
	zuf.block_interruptions = sapi_module.block_interruptions;
	zuf.unblock_interruptions = sapi_module.unblock_interruptions;
	zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
	zuf.ticks_function = php_run_ticks;
	zuf.on_timeout = php_on_timeout;
	zuf.stream_open_function = php_stream_open_for_zend;
	zuf.vspprintf_function = vspprintf;
	zuf.getenv_function = sapi_getenv;
	zuf.resolve_path_function = php_resolve_path_for_zend;
	zend_startup(&zuf, NULL TSRMLS_CC);

#ifdef ZTS
	executor_globals = ts_resource(executor_globals_id);
	ts_allocate_id(&core_globals_id, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
	core_globals = ts_resource(core_globals_id);
#ifdef PHP_WIN32
	ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, (ts_allocate_dtor) php_win32_core_globals_dtor);
#endif
#else
	php_startup_ticks(TSRMLS_C);
#endif
	gc_globals_ctor(TSRMLS_C);

#ifdef PHP_WIN32
	{
		OSVERSIONINFOEX *osvi = &EG(windows_version_info);

		ZeroMemory(osvi, sizeof(OSVERSIONINFOEX));
		osvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
		if( !GetVersionEx((OSVERSIONINFO *) osvi)) {
			php_printf("\nGetVersionEx unusable. %d\n", GetLastError());
			return FAILURE;
		}
	}
#endif
	EG(bailout) = NULL;
	EG(error_reporting) = E_ALL & ~E_NOTICE;
	EG(active_symbol_table) = NULL;
	PG(header_is_being_sent) = 0;
	SG(request_info).headers_only = 0;
	SG(request_info).argv0 = NULL;
	SG(request_info).argc=0;
	SG(request_info).argv=(char **)NULL;
	PG(connection_status) = PHP_CONNECTION_NORMAL;
	PG(during_request_startup) = 0;
	PG(last_error_message) = NULL;
	PG(last_error_file) = NULL;
	PG(last_error_lineno) = 0;
	EG(error_handling)  = EH_NORMAL;
	EG(exception_class) = NULL;
	PG(disable_functions) = NULL;
	PG(disable_classes) = NULL;
	EG(exception) = NULL;
	EG(objects_store).object_buckets = NULL;

#if HAVE_SETLOCALE
	setlocale(LC_CTYPE, "");
	zend_update_current_locale();
#endif

#if HAVE_TZSET
	tzset();
#endif

#if defined(PHP_WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
	/* start up winsock services */
	if (WSAStartup(wVersionRequested, &wsaData) != 0) {
		php_printf("\nwinsock.dll unusable. %d\n", WSAGetLastError());
		return FAILURE;
	}
#endif

	le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);

	/* Register constants */
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_RELEASE_VERSION", PHP_RELEASE_VERSION, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, sizeof(PHP_EXTRA_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT | CONST_CS);
#ifdef ZTS
	REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 1, CONST_PERSISTENT | CONST_CS);
#else
	REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 0, CONST_PERSISTENT | CONST_CS);
#endif
	REGISTER_MAIN_LONG_CONSTANT("PHP_DEBUG", PHP_DEBUG, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS", php_os, strlen(php_os), CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_SAPI", sapi_module.name, strlen(sapi_module.name), CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("DEFAULT_INCLUDE_PATH", PHP_INCLUDE_PATH, sizeof(PHP_INCLUDE_PATH)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PEAR_INSTALL_DIR", PEAR_INSTALLDIR, sizeof(PEAR_INSTALLDIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PEAR_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_PREFIX", PHP_PREFIX, sizeof(PHP_PREFIX)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINDIR", PHP_BINDIR, sizeof(PHP_BINDIR)-1, CONST_PERSISTENT | CONST_CS);
#ifndef PHP_WIN32
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_MANDIR", PHP_MANDIR, sizeof(PHP_MANDIR)-1, CONST_PERSISTENT | CONST_CS);
#endif
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_LIBDIR", PHP_LIBDIR, sizeof(PHP_LIBDIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_DATADIR", PHP_DATADIR, sizeof(PHP_DATADIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_SYSCONFDIR", PHP_SYSCONFDIR, sizeof(PHP_SYSCONFDIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_LOCALSTATEDIR", PHP_LOCALSTATEDIR, sizeof(PHP_LOCALSTATEDIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, strlen(PHP_CONFIG_FILE_PATH), CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);

#ifdef PHP_WIN32
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MAJOR",      EG(windows_version_info).dwMajorVersion, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MINOR",      EG(windows_version_info).dwMinorVersion, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_BUILD",      EG(windows_version_info).dwBuildNumber, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PLATFORM",   EG(windows_version_info).dwPlatformId, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MAJOR",   EG(windows_version_info).wServicePackMajor, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MINOR",   EG(windows_version_info).wServicePackMinor, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SUITEMASK",  EG(windows_version_info).wSuiteMask, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PRODUCTTYPE", EG(windows_version_info).wProductType, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_DOMAIN_CONTROLLER", VER_NT_DOMAIN_CONTROLLER, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_SERVER", VER_NT_SERVER, CONST_PERSISTENT | CONST_CS);
	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_WORKSTATION", VER_NT_WORKSTATION, CONST_PERSISTENT | CONST_CS);
#endif

	php_binary_init(TSRMLS_C);
	if (PG(php_binary)) {
		REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", PG(php_binary), strlen(PG(php_binary)), CONST_PERSISTENT | CONST_CS);
	} else {
		REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS);
	}

	php_output_register_constants(TSRMLS_C);
	php_rfc1867_register_constants(TSRMLS_C);

	/* this will read in php.ini, set up the configuration parameters,
	   load zend extensions and register php function extensions
	   to be loaded later */
	if (php_init_config(TSRMLS_C) == FAILURE) {
		return FAILURE;
	}

	/* Register PHP core ini entries */
	REGISTER_INI_ENTRIES();

	/* Register Zend ini entries */
	zend_register_standard_ini_entries(TSRMLS_C);

	/* Disable realpath cache if an open_basedir is set */
	if (PG(open_basedir) && *PG(open_basedir)) {
		CWDG(realpath_cache_size_limit) = 0;
	}

	/* initialize stream wrappers registry
	 * (this uses configuration parameters from php.ini)
	 */
	if (php_init_stream_wrappers(module_number TSRMLS_CC) == FAILURE)	{
		php_printf("PHP:  Unable to initialize stream url wrappers.\n");
		return FAILURE;
	}

	/* initialize registry for images to be used in phpinfo()
	   (this uses configuration parameters from php.ini)
	 */
	if (php_init_info_logos() == FAILURE) {
		php_printf("PHP:  Unable to initialize info phpinfo logos.\n");
		return FAILURE;
	}

	zuv.html_errors = 1;
	zuv.import_use_extension = ".php";
	php_startup_auto_globals(TSRMLS_C);
	zend_set_utility_values(&zuv);
	php_startup_sapi_content_types(TSRMLS_C);

	/* startup extensions staticly compiled in */
	if (php_register_internal_extensions_func(TSRMLS_C) == FAILURE) {
		php_printf("Unable to start builtin modules\n");
		return FAILURE;
	}

	/* start additional PHP extensions */
	php_register_extensions(&additional_modules, num_additional_modules TSRMLS_CC);

	/* load and startup extensions compiled as shared objects (aka DLLs)
	   as requested by php.ini entries
	   theese are loaded after initialization of internal extensions
	   as extensions *might* rely on things from ext/standard
	   which is always an internal extension and to be initialized
	   ahead of all other internals
	 */
	php_ini_register_extensions(TSRMLS_C);
	zend_startup_modules(TSRMLS_C);

	/* start Zend extensions */
	zend_startup_extensions();

	zend_collect_module_handlers(TSRMLS_C);

	/* register additional functions */
	if (sapi_module.additional_functions) {
		if (zend_hash_find(&module_registry, "standard", sizeof("standard"), (void**)&module)==SUCCESS) {
			EG(current_module) = module;
			zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
			EG(current_module) = NULL;
		}
	}

	/* disable certain classes and functions as requested by php.ini */
	php_disable_functions(TSRMLS_C);
	php_disable_classes(TSRMLS_C);

	/* make core report what it should */
	if (zend_hash_find(&module_registry, "core", sizeof("core"), (void**)&module)==SUCCESS) {
		module->version = PHP_VERSION;
		module->info_func = PHP_MINFO(php_core);
	}


#ifdef PHP_WIN32
	/* Disable incompatible functions for the running platform */
	if (php_win32_disable_functions(TSRMLS_C) == FAILURE) {
		php_printf("Unable to disable unsupported functions\n");
		return FAILURE;
	}
#endif

#ifdef ZTS
	zend_post_startup(TSRMLS_C);
#endif

	module_initialized = 1;

	/* Check for deprecated directives */
	/* NOTE: If you add anything here, remember to add it to Makefile.global! */
	{
		struct {
			const long error_level;
			const char *phrase;
			const char *directives[16]; /* Remember to change this if the number of directives change */
		} directives[2] = {
			{
				E_DEPRECATED,
				"Directive '%s' is deprecated in PHP 5.3 and greater",
				{
					NULL
				}
			},
			{
				E_CORE_ERROR,
				"Directive '%s' is no longer available in PHP",
				{
					"allow_call_time_pass_reference",
					"define_syslog_variables",
					"highlight.bg",
					"magic_quotes_gpc",
					"magic_quotes_runtime",
					"magic_quotes_sybase",
					"register_globals",
					"register_long_arrays",
					"safe_mode",
					"safe_mode_gid",
					"safe_mode_include_dir",
					"safe_mode_exec_dir",
					"safe_mode_allowed_env_vars",
					"safe_mode_protected_env_vars",
					"zend.ze1_compatibility_mode",
					NULL
				}
			}
		};

		unsigned int i;

		zend_try {
			/* 2 = Count of deprecation structs */
			for (i = 0; i < 2; i++) {
				const char **p = directives[i].directives;

				while(*p) {
					long value;

					if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
						zend_error(directives[i].error_level, directives[i].phrase, *p);
					}

					++p;
				}
			}
		} zend_catch {
			retval = FAILURE;
		} zend_end_try();
	}

	sapi_deactivate(TSRMLS_C);
	module_startup = 0;

	shutdown_memory_manager(1, 0 TSRMLS_CC);
	zend_interned_strings_snapshot(TSRMLS_C);

	/* we're done */
	return retval;
}

main/php_content_types.c中php_startup_sapi_content_types函数注册默认post数据处理函数php_default_post_reader和文件上传post处理函数php_default_treat_data

int php_startup_sapi_content_types(TSRMLS_D)
{
	sapi_register_default_post_reader(php_default_post_reader TSRMLS_CC);
	sapi_register_treat_data(php_default_treat_data TSRMLS_CC);
	sapi_register_input_filter(php_default_input_filter, NULL TSRMLS_CC);
	return SUCCESS;
}

在main/php_variables.c文件中有php_default_treat_data函数的代码,SAPI_TREAT_DATA_FUNC宏声明如下

#define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
php_default_treat_data函数中调用sapi_handle_post函数

SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
{
	char *res = NULL, *var, *val, *separator = NULL;
	const char *c_var;
	zval *array_ptr;
	int free_buffer = 0;
	char *strtok_buf = NULL;
	long count = 0;
	
	switch (arg) {
		case PARSE_POST:
		case PARSE_GET:
		case PARSE_COOKIE:
			ALLOC_ZVAL(array_ptr);
			array_init(array_ptr);
			INIT_PZVAL(array_ptr);
			switch (arg) {
				case PARSE_POST:
					if (PG(http_globals)[TRACK_VARS_POST]) {
						zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
					}
					PG(http_globals)[TRACK_VARS_POST] = array_ptr;
					break;
				case PARSE_GET:
					if (PG(http_globals)[TRACK_VARS_GET]) {
						zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]);
					}
					PG(http_globals)[TRACK_VARS_GET] = array_ptr;
					break;
				case PARSE_COOKIE:
					if (PG(http_globals)[TRACK_VARS_COOKIE]) {
						zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]);
					}
					PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr;
					break;
			}
			break;
		default:
			array_ptr = destArray;
			break;
	}

	if (arg == PARSE_POST) {
		sapi_handle_post(array_ptr TSRMLS_CC);
		return;
	}

	if (arg == PARSE_GET) {		/* GET data */
		c_var = SG(request_info).query_string;
		if (c_var && *c_var) {
			res = (char *) estrdup(c_var);
			free_buffer = 1;
		} else {
			free_buffer = 0;
		}
	} else if (arg == PARSE_COOKIE) {		/* Cookie data */
		c_var = SG(request_info).cookie_data;
		if (c_var && *c_var) {
			res = (char *) estrdup(c_var);
			free_buffer = 1;
		} else {
			free_buffer = 0;
		}
	} else if (arg == PARSE_STRING) {		/* String data */
		res = str;
		free_buffer = 1;
	}

	if (!res) {
		return;
	}

	switch (arg) {
		case PARSE_GET:
		case PARSE_STRING:
			separator = (char *) estrdup(PG(arg_separator).input);
			break;
		case PARSE_COOKIE:
			separator = ";\0";
			break;
	}
	
	var = php_strtok_r(res, separator, &strtok_buf);
	
	while (var) {
		val = strchr(var, '=');

		if (arg == PARSE_COOKIE) {
			/* Remove leading spaces from cookie names, needed for multi-cookie header where ; can be followed by a space */
			while (isspace(*var)) {
				var++;
			}
			if (var == val || *var == '\0') {
				goto next_cookie;
			}
		}

		if (++count > PG(max_input_vars)) {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
			break;
		}

		if (val) { /* have a value */
			int val_len;
			unsigned int new_val_len;

			*val++ = '\0';
			php_url_decode(var, strlen(var));
			val_len = php_url_decode(val, strlen(val));
			val = estrndup(val, val_len);
			if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
				php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
			}
			efree(val);
		} else {
			int val_len;
			unsigned int new_val_len;

			php_url_decode(var, strlen(var));
			val_len = 0;
			val = estrndup("", val_len);
			if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
				php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
			}
			efree(val);
		}
next_cookie:
		var = php_strtok_r(NULL, separator, &strtok_buf);
	}

	if (arg != PARSE_COOKIE) {
		efree(separator);
	}

	if (free_buffer) {
		efree(res);
	}
}

main/SAPI.c文件中调用结构体变量post_entry中储存的post_handler函数入口
SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
{
	if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
		SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
		if (SG(request_info).post_data) {
			efree(SG(request_info).post_data);
			SG(request_info).post_data = NULL;
		}
		efree(SG(request_info).content_type_dup);
		SG(request_info).content_type_dup = NULL;
	}
}

static void sapi_read_post_data(TSRMLS_D)
{
	sapi_post_entry *post_entry;
	uint content_type_length = strlen(SG(request_info).content_type);
	char *content_type = estrndup(SG(request_info).content_type, content_type_length);
	char *p;
	char oldchar=0;
	void (*post_reader_func)(TSRMLS_D) = NULL;


	/* dedicated implementation for increased performance:
	 * - Make the content type lowercase
	 * - Trim descriptive data, stay with the content-type only
	 */
	for (p=content_type; p<content_type+content_type_length; p++) {
		switch (*p) {
			case ';':
			case ',':
			case ' ':
				content_type_length = p-content_type;
				oldchar = *p;
				*p = 0;
				break;
			default:
				*p = tolower(*p);
				break;
		}
	}

	/* now try to find an appropriate POST content handler */
	if (zend_hash_find(&SG(known_post_content_types), content_type,
			content_type_length+1, (void **) &post_entry) == SUCCESS) {
		/* found one, register it for use */
		SG(request_info).post_entry = post_entry;
		post_reader_func = post_entry->post_reader;
	} else {
		/* fallback */
		SG(request_info).post_entry = NULL;
		if (!sapi_module.default_post_reader) {
			/* no default reader ? */
			SG(request_info).content_type_dup = NULL;
			sapi_module.sapi_error(E_WARNING, "Unsupported content type:  '%s'", content_type);
			return;
		}
	}
	if (oldchar) {
		*(p-1) = oldchar;
	}

	SG(request_info).content_type_dup = content_type;

	if(post_reader_func) {
		post_reader_func(TSRMLS_C);
	}

	if(sapi_module.default_post_reader) {
		sapi_module.default_post_reader(TSRMLS_C);
	}
}

static sapi_post_entry php_post_entries[] = {
	{ DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data,	php_std_post_handler },
	{ MULTIPART_CONTENT_TYPE,    sizeof(MULTIPART_CONTENT_TYPE)-1,    NULL,                         rfc1867_post_handler },
	{ NULL, 0, NULL, NULL }
};



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010024302/article/details/34116773

智能推荐

c钩子库Minhook的使用_minihook使用 vs-程序员宅基地

文章浏览阅读5.4k次。简述最近在学习钩子库,逛了一下gay hub,发现了一个项目minhook,纯钩子库,甚合我意,就研究了一下,写了2个例子。后续打算研究一下这个钩子库的源代码,了解一下具体怎么实现的。例子例子就不贴到这上面了,给出github地址:minhook钩子库的使用示例例子vs2008编译通过,使用的dll,lib文件都是从minhook项目编译而来。minhook项目github地址..._minihook使用 vs

python 发布包_如何将自己的Python包发布到PyPI-程序员宅基地

文章浏览阅读150次。以前写过一篇类似的文章: 如何打包自己的项目并且发布到pypi上,不过由于PyPI进行了一些更新,因此旧方法不大适用了。趁端午有时间,想把haipproxy的客户端发布到PyPI,以改进用户体验,因此这次又尝试了如何将Python包发布到新版本的PyPI上。编写setup.py以haipproxy为例,它的setup.py如下from os import path as os_pathfrom s..._如何将python包推送到pipy

ITK-SNAP安装指南_itk snap安装-程序员宅基地

文章浏览阅读1.7k次。通过按照以上步骤安装和使用ITK-SNAP,您可以进行医学图像的分割和可视化。希望本文提供的安装指南和示例代码能帮助您顺利使用ITK-SNAP进行图像处理和分割。完成图像分割后,您可以使用"File"菜单中的"Save Image"选项将分割结果保存为您选择的格式。一旦ITK-SNAP启动,您可以通过单击"File"菜单并选择"Open Image"来加载您要分割和可视化的图像。ITK-SNAP提供了多种分割工具和算法,可用于分割加载的图像。本文将为您提供ITK-SNAP的安装指南和相应的源代码。_itk snap安装

canvas动态设置宽高_canvas设置宽高-程序员宅基地

文章浏览阅读855次,点赞7次,收藏5次。的默认宽高为 宽 3高如果在里修改宽高 相当于对做放大 而为了不影响效果 我们正常显示需要怎么办呢?_canvas设置宽高

详解Ubuntu配置VSCode+CMake的C++开发环境_ubuntu vscode配置c++环境-程序员宅基地

文章浏览阅读1.5k次,点赞2次,收藏26次。接下来需要在项目文件夹中创建一个CMakeLists.txt文件来配置CMake。安装完VSCode之后,需要安装C/C++插件,该插件提供了C++开发所需的工具和功能。在VSCode内安装CMake插件,该插件提供CMake语法高亮、调试和构建支持。这告诉CMake创建一个名为“hello_world”的可执行文件,并将“main.cpp”文件添加到该可执行文件中。以下是一个简单的示例,演示了如何在Ubuntu 18.04下使用VSCode+CMake开发和调试C++程序。_ubuntu vscode配置c++环境

王甲佳_移动互联条件下O2O已经迭代到哪里了?-程序员宅基地

文章浏览阅读342次。王甲佳_移动互联条件下O2O已经迭代到哪里了?“互联网的红利我们看到了,移动互联网的红利我们也看到了,马化腾说“微信是人的电子器官”,已经装备到我们的口袋里。包括我们用支付宝半夜想起来还个信用卡也可以,交水电费也不外排队,也不需要电脑操作,这个商业价值怎么应用,企业需经营是 终端会员&消费者会员”。详细解读 和小伙伴们一起来吐槽

随便推点

网安理论题-程序员宅基地

文章浏览阅读926次,点赞15次,收藏25次。网安理论题

应该如何进行POC测试?—【DBA从入门到实践】第三期-程序员宅基地

文章浏览阅读812次,点赞28次,收藏29次。性能测试数据库性能测试是业务选型和PoC测试中的重点关注指标,涉及多种评估标准和测试工具。OceanBase作为一款实时HTAP数据库,同时支持在线实时交易及实时分析两种场景,那应该如何进行测试呢。

springcloud gateway网关请求参数过长出现的问题_参数过大gateway接收不到-程序员宅基地

文章浏览阅读4.8k次。问题:本地用gateway网关转发,请求用postman,参数比较短能够正常运行,如果参数过长,会直接在网关拦截器之前被拦截短参数的情况:能够正常转发和获取请求体里面的参数长参数的情况:没有进拦截器,直接返回bad-request原因:postman的post请求,经过网关时,也会被读成get请求。处理:用表单提交模拟post请求,能够正常获取数据..._参数过大gateway接收不到

chatgpt赋能python:Python安装chardet详解_chardet安装-程序员宅基地

文章浏览阅读1.9k次。chardet是一个Python库,用于识别字符编码。它可以根据字符集多样性对文本进行自动探测。它可以识别所有热门的字符集,包括UTF-8、UTF-16和GB2312等。使用chardet,我们可以轻松地将文件从一种编码转换为另一种编码。本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。对于颠覆工作方式的ChatGPT,应该选择拥抱而不是抗拒,未来属于“会用”AI的人。_chardet安装

自动诊断档案库(ADR)学习-程序员宅基地

文章浏览阅读147次。(1)ADR概述 Oracle 11g的FDI(Fault Diagnosability Infrastructure)是自动化诊断方面的一个增强,其核心组件为自动诊断库(Automatic Diagnostic Repository--ADR)。 在Oracle 11g之前,Oracle的各类跟踪文件、日志文件等诊断信息的存储位置并不统一。Oracle 11g中,在基于FDI的基础架构..._adr基目录

wkt 中 Polygon 与 mutiPolygon 格式-程序员宅基地

文章浏览阅读4.8k次。// wktString="MULTIPOLYGON (((114.13699625057654 22.5752911563618, 114.13566415227888 22.575724387670391, 114.134542568185 22.573231496636311, 114.13716786730333 22.571756121048224, 114.1380137237544 22.573494236270051, 114.13699625057654 22.57529115...