From a6393de6f7211ec72c1cdffbc30078fe35ce87c3 Mon Sep 17 00:00:00 2001 From: Zeev Suraski Date: Thu, 17 Feb 2000 20:23:59 +0000 Subject: [PATCH] Make POST handling the way it should be. RFC1867, and any future POST handlers we might have in the future now obey to the variables_order directive, and there's a real way modular way to handle POST content. This is all untested, BEFORE_SAPI_POST_PATCH_17_FEB_2000 tagged before submission @- Made multipart/form-data content obey to the variables_order directive (Zeev) --- ext/fdf/fdf.c | 16 ++++++ main/SAPI.c | 60 +++++++++++++++-------- main/SAPI.h | 33 ++++++++----- main/main.c | 6 +-- main/php_content_types.c | 11 +++-- main/php_content_types.h | 5 +- main/php_variables.c | 102 +++++++++++++++++++-------------------- main/php_variables.h | 1 + main/rfc1867.c | 21 ++------ main/rfc1867.h | 1 + 10 files changed, 147 insertions(+), 109 deletions(-) diff --git a/ext/fdf/fdf.c b/ext/fdf/fdf.c index 34e3aaca0f..3e4b7dd9c4 100644 --- a/ext/fdf/fdf.c +++ b/ext/fdf/fdf.c @@ -27,6 +27,22 @@ #undef THREAD_SAFE #endif + +#if 0 + if((NULL != SG(request_info).content_type) && (0 == strcmp(SG(request_info).content_type, "application/vnd.fdf"))) { + pval *tmp; + + ALLOC_ZVAL(tmp); + tmp->value.str.len = SG(request_info).post_data_length; + tmp->value.str.val = estrndup(SG(request_info).post_data, SG(request_info).post_data_length); + tmp->type = IS_STRING; + INIT_PZVAL(tmp); + zend_hash_add(&EG(symbol_table), "HTTP_FDF_DATA", sizeof("HTTP_FDF_DATA"), &tmp, sizeof(pval *),NULL); + + } else { +#endif + + #include "php.h" #include "ext/standard/head.h" #include diff --git a/main/SAPI.c b/main/SAPI.c index f1eec0aa49..254c187948 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -38,10 +38,7 @@ SAPI_POST_READER_FUNC(sapi_read_standard_form_data); -#define DEFAULT_POST_CONTENT_TYPE "application/x-www-form-urlencoded" - -static sapi_post_content_type_reader supported_post_content_types[] = { - { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data }, +static sapi_post_entry supported_post_entries[] = { #if HAVE_FDFLIB { "application/vnd.fdf", sizeof("application/vnd.fdf")-1, sapi_read_standard_form_data }, #endif @@ -71,7 +68,7 @@ SAPI_API void sapi_startup(sapi_module_struct *sf) sapi_module = *sf; zend_hash_init(&known_post_content_types, 5, NULL, NULL, 1); - sapi_register_post_readers(supported_post_content_types); + sapi_register_post_entries(supported_post_entries); #ifdef ZTS sapi_globals_id = ts_allocate_id(sizeof(sapi_globals_struct), NULL, NULL); @@ -95,14 +92,24 @@ SAPI_API void sapi_free_header(sapi_header_struct *sapi_header) } +SAPI_API void sapi_handle_post(void *arg SLS_DC) +{ + if (SG(request_info).post_entry) { + SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg SLS_CC); + efree(SG(request_info).post_data); + efree(SG(request_info).content_type_dup); + SG(request_info).content_type_dup = NULL; + } +} + static void sapi_read_post_data(SLS_D) { - sapi_post_content_type_reader *post_content_type_reader; + 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)(char *content_type_dup SLS_DC); + void (*post_reader_func)(SLS_D); /* dedicated implementation for increased performance: @@ -124,20 +131,22 @@ static void sapi_read_post_data(SLS_D) } } - if (zend_hash_find(&known_post_content_types, content_type, content_type_length+1, (void **) &post_content_type_reader)==SUCCESS) { - post_reader_func = post_content_type_reader->post_reader; + if (zend_hash_find(&known_post_content_types, content_type, content_type_length+1, (void **) &post_entry)==SUCCESS) { + SG(request_info).post_entry = post_entry; + post_reader_func = post_entry->post_reader; } else { if (!sapi_module.default_post_reader) { sapi_module.sapi_error(E_COMPILE_ERROR, "Unsupported content type: '%s'", content_type); return; } + SG(request_info).post_entry = NULL; post_reader_func = sapi_module.default_post_reader; } if (oldchar) { *(p-1) = oldchar; } - post_reader_func(content_type SLS_CC); - efree(content_type); + post_reader_func(SLS_C); + SG(request_info).content_type_dup = content_type; } @@ -213,6 +222,9 @@ SAPI_API void sapi_deactivate(SLS_D) if (SG(request_info).auth_password) { efree(SG(request_info).auth_password); } + if (SG(request_info).content_type_dup) { + efree(SG(request_info).content_type_dup); + } if (SG(request_info).current_user) { efree(SG(request_info).current_user); } @@ -221,6 +233,16 @@ SAPI_API void sapi_deactivate(SLS_D) } } + +SAPI_API void sapi_initialize_empty_request(SLS_D) +{ + SG(server_context) = NULL; + SG(request_info).request_method = NULL; + SG(request_info).auth_user = SG(request_info).auth_password = NULL; + SG(request_info).content_type_dup = NULL; +} + + static int sapi_extract_response_code(const char *header_line) { int code = 200; @@ -351,12 +373,12 @@ SAPI_API int sapi_send_headers() } -SAPI_API int sapi_register_post_readers(sapi_post_content_type_reader *post_content_type_readers) +SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries) { - sapi_post_content_type_reader *p=post_content_type_readers; + sapi_post_entry *p=post_entries; while (p->content_type) { - if (sapi_register_post_reader(p)==FAILURE) { + if (sapi_register_post_entry(p)==FAILURE) { return FAILURE; } p++; @@ -365,19 +387,19 @@ SAPI_API int sapi_register_post_readers(sapi_post_content_type_reader *post_cont } -SAPI_API int sapi_register_post_reader(sapi_post_content_type_reader *post_content_type_reader) +SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry) { - return zend_hash_add(&known_post_content_types, post_content_type_reader->content_type, post_content_type_reader->content_type_len+1, (void *) post_content_type_reader, sizeof(sapi_post_content_type_reader), NULL); + return zend_hash_add(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1, (void *) post_entry, sizeof(sapi_post_entry), NULL); } -SAPI_API void sapi_unregister_post_reader(sapi_post_content_type_reader *post_content_type_reader) +SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry) { - zend_hash_del(&known_post_content_types, post_content_type_reader->content_type, post_content_type_reader->content_type_len+1); + zend_hash_del(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1); } -SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(char *content_type_dup SLS_DC)) +SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(SLS_D)) { sapi_module.default_post_reader = default_post_reader; return SUCCESS; diff --git a/main/SAPI.h b/main/SAPI.h index c5fdd13982..709e7f51a7 100644 --- a/main/SAPI.h +++ b/main/SAPI.h @@ -52,6 +52,7 @@ typedef struct { } sapi_headers_struct; +typedef struct _sapi_post_entry sapi_post_entry; typedef struct _sapi_module_struct sapi_module_struct; @@ -73,6 +74,10 @@ typedef struct { unsigned char headers_only; + sapi_post_entry *post_entry; + + char *content_type_dup; + /* for HTTP authentication */ char *auth_user; char *auth_password; @@ -114,26 +119,22 @@ SAPI_API extern int sapi_globals_id; extern SAPI_API sapi_globals_struct sapi_globals; #endif -typedef struct _sapi_post_content_type_reader { - char *content_type; - uint content_type_len; - void (*post_reader)(char *content_type_dup SLS_DC); -} sapi_post_content_type_reader; - SAPI_API void sapi_startup(sapi_module_struct *sf); SAPI_API void sapi_shutdown(void); SAPI_API void sapi_activate(SLS_D); SAPI_API void sapi_deactivate(SLS_D); +SAPI_API void sapi_initialize_empty_request(SLS_D); SAPI_API int sapi_add_header(char *header_line, uint header_line_len); SAPI_API int sapi_send_headers(void); SAPI_API void sapi_free_header(sapi_header_struct *sapi_header); +SAPI_API void sapi_handle_post(void *arg SLS_DC); -SAPI_API int sapi_register_post_readers(sapi_post_content_type_reader *post_content_type_readers); -SAPI_API int sapi_register_post_reader(sapi_post_content_type_reader *post_content_type_reader); -SAPI_API void sapi_unregister_post_reader(sapi_post_content_type_reader *post_content_type_reader); -SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(char *content_type_dup SLS_DC)); +SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entry); +SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry); +SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry); +SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(SLS_D)); SAPI_API int sapi_flush(); SAPI_API struct stat *sapi_get_stat(); @@ -168,10 +169,17 @@ struct _sapi_module_struct { void (*block_interruptions)(void); void (*unblock_interruptions)(void); - void (*default_post_reader)(char *content_type_dup SLS_DC); + void (*default_post_reader)(SLS_D); }; +struct _sapi_post_entry { + char *content_type; + uint content_type_len; + void (*post_reader)(SLS_D); + void (*post_handler)(char *content_type_dup, void *arg SLS_DC); +}; + /* header_handler() constants */ #define SAPI_HEADER_ADD (1<<0) #define SAPI_HEADER_DELETE_ALL (1<<1) @@ -185,7 +193,8 @@ struct _sapi_module_struct { #define SAPI_DEFAULT_CONTENT_TYPE "Content-Type: text/html" #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION -#define SAPI_POST_READER_FUNC(post_reader) void post_reader(char *content_type_dup SLS_DC) +#define SAPI_POST_READER_FUNC(post_reader) void post_reader(SLS_D) +#define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg SLS_DC) SAPI_POST_READER_FUNC(sapi_read_standard_form_data); diff --git a/main/main.c b/main/main.c index 1478ee7c0e..a2a622763c 100644 --- a/main/main.c +++ b/main/main.c @@ -793,9 +793,7 @@ int php_module_startup(sapi_module_struct *sf) #endif global_lock_init(); - SG(server_context) = NULL; - SG(request_info).request_method = NULL; - SG(request_info).auth_user = SG(request_info).auth_password = NULL; + sapi_initialize_empty_request(SLS_C); sapi_activate(SLS_C); if (module_initialized) { @@ -859,7 +857,7 @@ int php_module_startup(sapi_module_struct *sf) zuv.allow_call_time_pass_reference = PG(allow_call_time_pass_reference); zuv.import_use_extension = ".php"; zend_set_utility_values(&zuv); - php_startup_SAPI_content_types(); + php_startup_sapi_content_types(); REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS", php_os, strlen(php_os), CONST_PERSISTENT | CONST_CS); diff --git a/main/php_content_types.c b/main/php_content_types.c index e273723eb8..3c76c57e66 100644 --- a/main/php_content_types.c +++ b/main/php_content_types.c @@ -4,8 +4,9 @@ #include "php_content_types.h" -static sapi_post_content_type_reader php_post_content_types[] = { - { MULTIPART_CONTENT_TYPE, sizeof(MULTIPART_CONTENT_TYPE)-1, rfc1867_post_reader }, +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, sapi_read_standard_form_data, rfc1867_post_handler }, { NULL, 0, NULL } }; @@ -15,15 +16,15 @@ SAPI_POST_READER_FUNC(php_default_post_reader) char *data; ELS_FETCH(); - sapi_read_standard_form_data(content_type_dup SLS_CC); + sapi_read_standard_form_data(SLS_C); data = estrndup(SG(request_info).post_data,SG(request_info).post_data_length); SET_VAR_STRINGL("HTTP_RAW_POST_DATA", data, SG(request_info).post_data_length); } -int php_startup_SAPI_content_types(void) +int php_startup_sapi_content_types(void) { - sapi_register_post_readers(php_post_content_types); + sapi_register_post_entries(php_post_entries); sapi_register_default_post_reader(php_default_post_reader); return SUCCESS; } diff --git a/main/php_content_types.h b/main/php_content_types.h index 429d9a7502..af512ed3ab 100644 --- a/main/php_content_types.h +++ b/main/php_content_types.h @@ -1,7 +1,10 @@ #ifndef _PHP_CONTENT_TYPES_H #define _PHP_CONTENT_TYPES_H +#define DEFAULT_POST_CONTENT_TYPE "application/x-www-form-urlencoded" + SAPI_POST_READER_FUNC(php_default_post_reader); -int php_startup_SAPI_content_types(void); +SAPI_POST_HANDLER_FUNC(php_std_post_handler); +int php_startup_sapi_content_types(void); #endif /* _PHP_CONTENT_TYPES_H */ diff --git a/main/php_variables.c b/main/php_variables.c index 842b5d47eb..aa2fcfe70e 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -175,6 +175,30 @@ PHPAPI void php_register_variable(char *var, char *val, pval *track_vars_array E } +SAPI_POST_HANDLER_FUNC(php_std_post_handler) +{ + char *var, *val; + char *strtok_buf = NULL; + zval *array_ptr = (zval *) arg; + ELS_FETCH(); + PLS_FETCH(); + + var = strtok_r(SG(request_info).post_data, "&", &strtok_buf); + + while (var) { + val = strchr(var, '='); + if (val) { /* have a value */ + *val++ = '\0'; + /* FIXME: XXX: not binary safe, discards returned length */ + php_url_decode(var, strlen(var)); + php_url_decode(val, strlen(val)); + php_register_variable(var, val, array_ptr ELS_CC PLS_CC); + } + var = strtok_r(NULL, "&", &strtok_buf); + } +} + + void php_treat_data(int arg, char *str ELS_DC PLS_DC SLS_DC) { char *res = NULL, *var, *val; @@ -192,18 +216,7 @@ void php_treat_data(int arg, char *str ELS_DC PLS_DC SLS_DC) INIT_PZVAL(array_ptr); switch (arg) { case PARSE_POST: - if (zend_hash_add_ptr(&EG(symbol_table), "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), array_ptr, sizeof(pval *),NULL)==FAILURE) { - zval **p; - - /* This could happen if we're in RFC 1867 file upload */ - /* The parsing portion of the POST reader should actually move - * to this function - Zeev - */ - zval_dtor(array_ptr); - FREE_ZVAL(array_ptr); - zend_hash_find(&EG(symbol_table), "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), (void **) &p); - array_ptr = *p; - } + zend_hash_add_ptr(&EG(symbol_table), "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), array_ptr, sizeof(pval *),NULL); break; case PARSE_GET: zend_hash_add_ptr(&EG(symbol_table), "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"), array_ptr, sizeof(pval *),NULL); @@ -221,10 +234,12 @@ void php_treat_data(int arg, char *str ELS_DC PLS_DC SLS_DC) break; } - if (arg == PARSE_POST) { /* POST data */ - res = SG(request_info).post_data; - free_buffer = 0; - } else if (arg == PARSE_GET) { /* GET data */ + if (arg==PARSE_POST) { + sapi_handle_post(array_ptr SLS_CC); + return; + } + + if (arg == PARSE_GET) { /* GET data */ var = SG(request_info).query_string; if (var && *var) { res = (char *) estrdup(var); @@ -244,51 +259,34 @@ void php_treat_data(int arg, char *str ELS_DC PLS_DC SLS_DC) res = str; free_buffer = 1; } + if (!res) { return; } -#if HAVE_FDFLIB - if((NULL != SG(request_info).content_type) && (0 == strcmp(SG(request_info).content_type, "application/vnd.fdf"))) { - pval *tmp; - - ALLOC_ZVAL(tmp); - tmp->value.str.len = SG(request_info).post_data_length; - tmp->value.str.val = estrndup(SG(request_info).post_data, SG(request_info).post_data_length); - tmp->type = IS_STRING; - INIT_PZVAL(tmp); - zend_hash_add(&EG(symbol_table), "HTTP_FDF_DATA", sizeof("HTTP_FDF_DATA"), &tmp, sizeof(pval *),NULL); - + if (arg == PARSE_COOKIE) { + var = strtok_r(res, ";", &strtok_buf); + } else if (arg == PARSE_POST) { + var = strtok_r(res, "&", &strtok_buf); } else { -#endif + var = strtok_r(res, PG(arg_separator), &strtok_buf); + } + + while (var) { + val = strchr(var, '='); + if (val) { /* have a value */ + *val++ = '\0'; + /* FIXME: XXX: not binary safe, discards returned length */ + php_url_decode(var, strlen(var)); + php_url_decode(val, strlen(val)); + php_register_variable(var, val, array_ptr ELS_CC PLS_CC); + } if (arg == PARSE_COOKIE) { - var = strtok_r(res, ";", &strtok_buf); - } else if (arg == PARSE_POST) { - var = strtok_r(res, "&", &strtok_buf); + var = strtok_r(NULL, ";", &strtok_buf); } else { - var = strtok_r(res, PG(arg_separator), &strtok_buf); - } - - while (var) { - val = strchr(var, '='); - if (val) { /* have a value */ - *val++ = '\0'; - /* FIXME: XXX: not binary safe, discards returned length */ - php_url_decode(var, strlen(var)); - php_url_decode(val, strlen(val)); - php_register_variable(var, val, array_ptr ELS_CC PLS_CC); - } - if (arg == PARSE_COOKIE) { - var = strtok_r(NULL, ";", &strtok_buf); - } else if (arg == PARSE_POST) { - var = strtok_r(NULL, "&", &strtok_buf); - } else { - var = strtok_r(NULL, PG(arg_separator), &strtok_buf); - } + var = strtok_r(NULL, PG(arg_separator), &strtok_buf); } -#if HAVE_FDFLIB } -#endif if (free_buffer) { efree(res); } diff --git a/main/php_variables.h b/main/php_variables.h index 932b86bcc2..33797f8333 100644 --- a/main/php_variables.h +++ b/main/php_variables.h @@ -44,4 +44,5 @@ void php_treat_data(int arg, char *str ELS_DC PLS_DC SLS_DC); void php_import_environment_variables(ELS_D PLS_DC); PHPAPI void php_register_variable(char *var, char *val, pval *track_vars_array ELS_DC PLS_DC); + #endif /* _PHP_VARIABLES_H */ diff --git a/main/rfc1867.c b/main/rfc1867.c index ef01e1e3f8..a4d041f457 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -33,7 +33,7 @@ /* * Split raw mime stream up into appropriate components */ -static void php_mime_split(char *buf, int cnt, char *boundary) +static void php_mime_split(char *buf, int cnt, char *boundary, zval *array_ptr) { char *ptr, *loc, *loc2, *s, *name, *filename, *u, *fn; int len, state = 0, Done = 0, rem, urem; @@ -42,18 +42,9 @@ static void php_mime_split(char *buf, int cnt, char *boundary) char *namebuf=NULL, *filenamebuf=NULL, *lbuf=NULL; FILE *fp; int itype; - zval *http_post_vars=NULL; ELS_FETCH(); PLS_FETCH(); - if (PG(track_vars)) { - ALLOC_ZVAL(http_post_vars); - array_init(http_post_vars); - INIT_PZVAL(http_post_vars); - - zend_hash_add(&EG(symbol_table), "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), &http_post_vars, sizeof(pval *), NULL); - } - ptr = buf; rem = cnt; len = strlen(boundary); @@ -164,7 +155,7 @@ static void php_mime_split(char *buf, int cnt, char *boundary) *(loc - 4) = '\0'; /* Magic function that figures everything out */ - php_register_variable(namebuf, ptr, http_post_vars ELS_CC PLS_CC); + php_register_variable(namebuf, ptr, array_ptr ELS_CC PLS_CC); /* And a little kludge to pick out special MAX_FILE_SIZE */ itype = php_check_ident_type(namebuf); @@ -243,10 +234,11 @@ static void php_mime_split(char *buf, int cnt, char *boundary) } -SAPI_POST_READER_FUNC(rfc1867_post_reader) +SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) { char *boundary; uint boundary_len; + zval *array_ptr = (zval *) arg; boundary = strstr(content_type_dup, "boundary"); if (!boundary || !(boundary=strchr(boundary, '='))) { @@ -256,11 +248,8 @@ SAPI_POST_READER_FUNC(rfc1867_post_reader) boundary++; boundary_len = strlen(boundary); - sapi_read_standard_form_data(content_type_dup SLS_CC); if (SG(request_info).post_data) { - php_mime_split(SG(request_info).post_data, SG(request_info).post_data_length, boundary); - efree(SG(request_info).post_data); - SG(request_info).post_data = NULL; + php_mime_split(SG(request_info).post_data, SG(request_info).post_data_length, boundary, array_ptr); } } diff --git a/main/rfc1867.h b/main/rfc1867.h index 97c1475e80..b50cf46549 100644 --- a/main/rfc1867.h +++ b/main/rfc1867.h @@ -6,6 +6,7 @@ #define MULTIPART_CONTENT_TYPE "multipart/form-data" SAPI_POST_READER_FUNC(rfc1867_post_reader); +SAPI_POST_HANDLER_FUNC(rfc1867_post_handler); #define FILE_UPLOAD_INPUT_BUFFER_SIZE 8192 -- 2.50.1