Browse Source

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)
PHP-4.0.5
Zeev Suraski 27 years ago
parent
commit
a6393de6f7
  1. 16
      ext/fdf/fdf.c
  2. 60
      main/SAPI.c
  3. 33
      main/SAPI.h
  4. 6
      main/main.c
  5. 11
      main/php_content_types.c
  6. 5
      main/php_content_types.h
  7. 102
      main/php_variables.c
  8. 1
      main/php_variables.h
  9. 21
      main/rfc1867.c
  10. 1
      main/rfc1867.h

16
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 <math.h>

60
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;

33
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);

6
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);

11
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;
}

5
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 */

102
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);
}

1
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 */

21
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);
}
}

1
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

Loading…
Cancel
Save