lbarnaud                Fri May  1 00:36:43 2009 UTC

  Modified files:              
    /php-src/main       rfc1867.c 
  Log:
  revert to allow Andrei to make his changes
  
  
http://cvs.php.net/viewvc.cgi/php-src/main/rfc1867.c?r1=1.209&r2=1.210&diff_format=u
Index: php-src/main/rfc1867.c
diff -u php-src/main/rfc1867.c:1.209 php-src/main/rfc1867.c:1.210
--- php-src/main/rfc1867.c:1.209        Fri May  1 00:18:09 2009
+++ php-src/main/rfc1867.c      Fri May  1 00:36:43 2009
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: rfc1867.c,v 1.209 2009/05/01 00:18:09 lbarnaud Exp $ */
+/* $Id: rfc1867.c,v 1.210 2009/05/01 00:36:43 lbarnaud Exp $ */
 
 /*
  *  This product includes software developed by the Apache Group
@@ -49,6 +49,63 @@
        if (mbuff) efree(mbuff); \
        return; }
 
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+#include "ext/mbstring/mbstring.h"
+
+static void safe_php_register_variable(char *var, char *strval, int val_len, 
zval *track_vars_array, zend_bool override_protection TSRMLS_DC);
+
+void php_mb_flush_gpc_variables(int num_vars, char **val_list, int *len_list, 
zval *array_ptr  TSRMLS_DC)
+{
+       int i;
+       if (php_mb_encoding_translation(TSRMLS_C)) {
+               if (num_vars > 0 &&
+                       php_mb_gpc_encoding_detector(val_list, len_list, 
num_vars, NULL TSRMLS_CC) == SUCCESS) {
+                       php_mb_gpc_encoding_converter(val_list, len_list, 
num_vars, NULL, NULL TSRMLS_CC);
+               }
+               for (i=0; i<num_vars; i+=2){
+                       safe_php_register_variable(val_list[i], val_list[i+1], 
len_list[i+1], array_ptr, 0 TSRMLS_CC);
+                       efree(val_list[i]);
+                       efree(val_list[i+1]);
+               } 
+               efree(val_list);
+               efree(len_list);
+       }
+}
+
+void php_mb_gpc_realloc_buffer(char ***pval_list, int **plen_list, int 
*num_vars_max, int inc  TSRMLS_DC)
+{
+       /* allow only even increments */
+       if (inc & 1) {
+               inc++;
+       }
+       (*num_vars_max) += inc;
+       *pval_list = (char **)erealloc(*pval_list, 
(*num_vars_max+2)*sizeof(char *));
+       *plen_list = (int *)erealloc(*plen_list, (*num_vars_max+2)*sizeof(int));
+}
+
+void php_mb_gpc_stack_variable(char *param, char *value, char ***pval_list, 
int **plen_list, int *num_vars, int *num_vars_max TSRMLS_DC)
+{
+       char **val_list=*pval_list;
+       int *len_list=*plen_list;
+
+       if (*num_vars>=*num_vars_max){  
+               php_mb_gpc_realloc_buffer(pval_list, plen_list, num_vars_max, 
+                                                                 16 TSRMLS_CC);
+               /* in case realloc relocated the buffer */
+               val_list = *pval_list;
+               len_list = *plen_list;
+       }
+
+       val_list[*num_vars] = (char *)estrdup(param);
+       len_list[*num_vars] = strlen(param);
+       (*num_vars)++;
+       val_list[*num_vars] = (char *)estrdup(value);
+       len_list[*num_vars] = strlen(value);
+       (*num_vars)++;
+}
+
+#endif
+
 /* The longest property name we use in an uploaded file array */
 #define MAX_SIZE_OF_INDEX sizeof("[tmp_name]")
 
@@ -77,6 +134,66 @@
        REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_EXTENSION",  UPLOAD_ERROR_X,  
CONST_CS | CONST_PERSISTENT);
 }
 
+static void normalize_protected_variable(char *varname TSRMLS_DC)
+{
+       char *s=varname, *index=NULL, *indexend=NULL, *p;
+       
+       /* overjump leading space */
+       while (*s == ' ') {
+               s++;
+       }
+       
+       /* and remove it */
+       if (s != varname) {
+               memmove(varname, s, strlen(s)+1);
+       }
+
+       for (p=varname; *p && *p != '['; p++) {
+               switch(*p) {
+                       case ' ':
+                       case '.':
+                               *p='_';
+                               break;
+               }
+       }
+
+       /* find index */
+       index = strchr(varname, '[');
+       if (index) {
+               index++;
+               s=index;
+       } else {
+               return;
+       }
+
+       /* done? */
+       while (index) {
+
+               while (*index == ' ' || *index == '\r' || *index == '\n' || 
*index=='\t') {
+                       index++;
+               }
+               indexend = strchr(index, ']');
+               indexend = indexend ? indexend + 1 : index + strlen(index);
+               
+               if (s != index) {
+                       memmove(s, index, strlen(index)+1);
+                       s += indexend-index;
+               } else {
+                       s = indexend;
+               }
+
+               if (*s == '[') {
+                       s++;
+                       index = s;
+               } else {
+                       index = NULL;
+               }       
+       }
+
+       *s = '\0';
+}
+
+
 static void normalize_u_protected_variable(UChar *varname TSRMLS_DC)
 {
        UChar *s=varname, *index=NULL, *indexend=NULL, *p;
@@ -138,6 +255,15 @@
        *s++ = 0;
 }
 
+static void add_protected_variable(char *varname TSRMLS_DC)
+{
+       int dummy=1;
+
+       normalize_protected_variable(varname TSRMLS_CC);
+       zend_hash_add(&PG(rfc1867_protected_variables), varname, 
strlen(varname)+1, &dummy, sizeof(int), NULL);
+}
+
+
 static void add_u_protected_variable(UChar *varname TSRMLS_DC)
 {
        int dummy=1;
@@ -147,6 +273,13 @@
 }
 
 
+static zend_bool is_protected_variable(char *varname TSRMLS_DC)
+{
+       normalize_protected_variable(varname TSRMLS_CC);
+       return zend_hash_exists(&PG(rfc1867_protected_variables), varname, 
strlen(varname)+1);
+}
+
+
 static zend_bool is_u_protected_variable(UChar *varname TSRMLS_DC)
 {
        normalize_u_protected_variable(varname TSRMLS_CC);
@@ -154,6 +287,22 @@
 }
 
 
+static void safe_php_register_variable(char *var, char *strval, int val_len, 
zval *track_vars_array, zend_bool override_protection TSRMLS_DC)
+{
+       if (override_protection || !is_protected_variable(var TSRMLS_CC)) {
+               php_register_variable_safe(var, strval, val_len, 
track_vars_array TSRMLS_CC);
+       }
+}
+
+
+static void safe_php_register_variable_ex(char *var, zval *val, zval 
*track_vars_array, zend_bool override_protection TSRMLS_DC)
+{
+       if (override_protection || !is_protected_variable(var TSRMLS_CC)) {
+               php_register_variable_ex(var, val, track_vars_array TSRMLS_CC);
+       }
+}
+
+
 static void safe_u_php_register_variable(UChar *var, UChar *str_val, int 
str_len, zval *track_vars_array, zend_bool override_protection TSRMLS_DC)
 {
        if (override_protection || !is_u_protected_variable(var TSRMLS_CC)) {
@@ -170,12 +319,24 @@
 }
 
 
+static void register_http_post_files_variable(char *strvar, char *val, zval 
*http_post_files, zend_bool override_protection TSRMLS_DC)
+{
+       safe_php_register_variable(strvar, val, strlen(val), http_post_files, 
override_protection TSRMLS_CC);
+}
+
+
 static void register_u_http_post_files_variable(UChar *strvar, UChar *val, int 
val_len, zval *http_post_files, zend_bool override_protection TSRMLS_DC)
 {
        safe_u_php_register_variable(strvar, val, val_len, http_post_files, 
override_protection TSRMLS_CC);
 }
 
 
+static void register_http_post_files_variable_ex(char *var, zval *val, zval 
*http_post_files, zend_bool override_protection TSRMLS_DC)
+{
+       safe_php_register_variable_ex(var, val, http_post_files, 
override_protection TSRMLS_CC);
+}
+
+
 static void register_u_http_post_files_variable_ex(UChar *var, zval *val, zval 
*http_post_files, zend_bool override_protection TSRMLS_DC)
 {
        safe_u_php_register_variable_ex(var, val, http_post_files, 
override_protection TSRMLS_CC);
@@ -202,10 +363,14 @@
        UErrorCode status = U_ZERO_ERROR;
        UChar *buf;
        int buf_len = 0;
-       UConverter *input_conv = ZEND_U_CONVERTER(UG(http_input_encoding_conv));
+       UConverter *input_conv = UG(http_input_encoding_conv);
 
-       zend_string_to_unicode_ex(input_conv, &buf, &buf_len, in, in_len, 
&status);
+       if (!input_conv) {
+               input_conv = ZEND_U_CONVERTER(UG(output_encoding_conv));
+       }
 
+       input_conv = ZEND_U_CONVERTER(UG(output_encoding_conv));
+       zend_string_to_unicode_ex(input_conv, &buf, &buf_len, in, in_len, 
&status);
        if (U_SUCCESS(status)) {
                if (out_len)
                        *out_len = buf_len;
@@ -536,6 +701,45 @@
 }
 
 
+static char *php_ap_getword(char **line, char stop)
+{
+       char *pos = *line, quote;
+       char *res;
+
+       while (*pos && *pos != stop) {
+               
+               if ((quote = *pos) == '"' || quote == '\'') {
+                       ++pos;
+                       while (*pos && *pos != quote) {
+                               if (*pos == '\\' && pos[1] && pos[1] == quote) {
+                                       pos += 2;
+                               } else {
+                                       ++pos;
+                               }
+                       }
+                       if (*pos) {
+                               ++pos;
+                       }
+               } else ++pos;
+               
+       }
+       if (*pos == '\0') {
+               res = estrdup(*line);
+               *line += strlen(*line);
+               return res;
+       }
+
+       res = estrndup(*line, pos - *line);
+
+       while (*pos == stop) {
+               ++pos;
+       }
+
+       *line = pos;
+       return res;
+}
+
+
 static UChar *substring_u_conf(UChar *start, int len, UChar quote TSRMLS_DC)
 {
        UChar *result = eumalloc(len + 2);
@@ -555,6 +759,37 @@
 }
 
 
+static char *substring_conf(char *start, int len, char quote TSRMLS_DC)
+{
+       char *result = emalloc(len + 2);
+       char *resp = result;
+       int i;
+
+       for (i = 0; i < len; ++i) {
+               if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && 
start[i + 1] == quote))) {
+                       *resp++ = start[++i];
+               } else {
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+                       if (php_mb_encoding_translation(TSRMLS_C)) {
+                               size_t j = php_mb_gpc_mbchar_bytes(start+i 
TSRMLS_CC);
+                               while (j-- > 0 && i < len) {
+                                       *resp++ = start[i++];
+                               }
+                               --i;
+                       } else {
+                               *resp++ = start[i];
+                       }
+#else
+                       *resp++ = start[i];
+#endif
+               }
+       }
+
+       *resp = '\0';
+       return result;
+}
+
+
 static UChar *php_u_ap_getword_conf(UChar **line TSRMLS_DC)
 {
        UChar *str = *line, *strend, *res, quote;
@@ -610,6 +845,68 @@
 }
 
 
+static char *php_ap_getword_conf(char **line TSRMLS_DC)
+{
+       char *str = *line, *strend, *res, quote;
+
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+       if (php_mb_encoding_translation(TSRMLS_C)) {
+               int len=strlen(str);
+               php_mb_gpc_encoding_detector(&str, &len, 1, NULL TSRMLS_CC);
+       }
+#endif
+
+       while (*str && isspace(*str)) {
+               ++str;
+       }
+
+       if (!*str) {
+               *line = str;
+               return estrdup("");
+       }
+
+       if ((quote = *str) == '"' || quote == '\'') {
+               strend = str + 1;
+look_for_quote:
+               while (*strend && *strend != quote) {
+                       if (*strend == '\\' && strend[1] && strend[1] == quote) 
{
+                               strend += 2;
+                       } else {
+                               ++strend;
+                       }
+               }
+               if (*strend && *strend == quote) {
+                       char p = *(strend + 1);
+                       if (p != '\r' && p != '\n' && p != '\0') {
+                               strend++;
+                               goto look_for_quote;
+                       }
+               }
+
+               res = substring_conf(str + 1, strend - str - 1, quote 
TSRMLS_CC);
+
+               if (*strend == quote) {
+                       ++strend;
+               }
+
+       } else {
+
+               strend = str;
+               while (*strend && !isspace(*strend)) {
+                       ++strend;
+               }
+               res = substring_conf(str, strend - str, 0 TSRMLS_CC);
+       }
+
+       while (*strend && isspace(*strend)) {
+               ++strend;
+       }
+
+       *line = strend;
+       return res;
+}
+
+
 /*
   search for a string in a fixed-length byte string.
   if partial is true, partial matches are allowed at the end of the buffer.
@@ -704,12 +1001,7 @@
        return out;
 }
 
-/*
- * The combined READER/HANDLER
- *
- */
-
-SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler)
+static SAPI_POST_HANDLER_FUNC(rfc1867_post_handler_unicode)
 {
        char *boundary, *boundary_end = NULL;
        UChar *temp_filename=NULL, *array_index = NULL, *lbuf = NULL, *abuf = 
NULL;
@@ -1130,17 +1422,23 @@
                                        efree(array_index);
                                }
                                array_index = eustrndup(start_arr+1, 
array_len-2);   
-
-                               if (abuf) efree(abuf);
-                               abuf = eustrndup(param, 
u_strlen(param)-array_len);
                        }
 
+                       /* Add $foo_name */
                        if (lbuf) {
                                efree(lbuf);
                        }
                        llen = u_strlen(param) + MAX_SIZE_OF_INDEX + 1;
                        lbuf = eumalloc(llen);
 
+                       if (is_arr_upload) {
+                               if (abuf) efree(abuf);
+                               abuf = eustrndup(param, 
u_strlen(param)-array_len);
+                               u_snprintf(lbuf, llen, "%S_name[%S]", abuf, 
array_index);
+                       } else {
+                               u_snprintf(lbuf, llen, "%S_name", param);
+                       }
+
                        /* The \ check should technically be needed for win32 
systems only where
                         * it is a valid path separator. However, IE in all its 
wisdom always sends
                         * the full path of the file on the user's filesystem, 
which means that unless
@@ -1152,6 +1450,14 @@
                                s = tmp;
                        }
 
+                       if (!is_anonymous) {
+                               if (s && s > filename) {
+                                       safe_u_php_register_variable(lbuf, s+1, 
u_strlen(s+1), NULL, 0 TSRMLS_CC);
+                               } else {
+                                       safe_u_php_register_variable(lbuf, 
filename, u_strlen(filename), NULL, 0 TSRMLS_CC);
+                               }
+                       }
+
                        /* Add $foo[name] */
                        if (is_arr_upload) {
                                u_snprintf(lbuf, llen, "%S[name][%S]", abuf, 
array_index);
@@ -1183,6 +1489,16 @@
                                }
                        }
 
+                       /* Add $foo_type */
+                       if (is_arr_upload) {
+                               u_snprintf(lbuf, llen, "%S_type[%S]", abuf, 
array_index);
+                       } else {
+                               u_snprintf(lbuf, llen, "%S_type", param);
+                       }
+                       if (!is_anonymous) {
+                               safe_u_php_register_variable(lbuf, ucd, 
ucd_len, NULL, 0 TSRMLS_CC);
+                       }
+
                        /* Add $foo[type] */
                        if (is_arr_upload) {
                                u_snprintf(lbuf, llen, "%S[type][%S]", abuf, 
array_index);
@@ -1197,6 +1513,11 @@
                        /* Initialize variables */
                        add_u_protected_variable(param TSRMLS_CC);
 
+                       /* if param is of form xxx[.*] this will cut it to xxx 
*/
+                       if (!is_anonymous) {
+                               safe_u_php_register_variable(param, 
temp_filename, u_strlen(temp_filename), NULL, 1 TSRMLS_CC);
+                       }
+
                        /* Add $foo[tmp_name] */
                        if (is_arr_upload) {
                                u_snprintf(lbuf, llen, "%S[tmp_name][%S]", 
abuf, array_index);
@@ -1231,6 +1552,16 @@
                                }
                                register_u_http_post_files_variable_ex(lbuf, 
&error_type, http_post_files, 0 TSRMLS_CC);
 
+                               /* Add $foo_size */
+                               if (is_arr_upload) {
+                                       u_snprintf(lbuf, llen, "%S_size[%S]", 
abuf, array_index);
+                               } else {
+                                       u_snprintf(lbuf, llen, "%S_size", 
param);
+                               }
+                               if (!is_anonymous) {
+                                       safe_u_php_register_variable_ex(lbuf, 
&file_size, NULL, 0 TSRMLS_CC);
+                               }       
+
                                /* Add $foo[size] */
                                if (is_arr_upload) {
                                        u_snprintf(lbuf, llen, "%S[size][%S]", 
abuf, array_index);
@@ -1254,6 +1585,584 @@
        SAFE_RETURN;
 }
 
+static SAPI_POST_HANDLER_FUNC(rfc1867_post_handler_legacy)
+{
+       char *boundary, *s=NULL, *boundary_end = NULL, *start_arr=NULL, 
*array_index=NULL;
+       char *temp_filename=NULL, *lbuf=NULL, *abuf=NULL;
+       int boundary_len=0, total_bytes=0, cancel_upload=0, is_arr_upload=0, 
array_len=0;
+       int max_file_size=0, skip_upload=0, anonindex=0, is_anonymous;
+       zval *http_post_files=NULL; HashTable *uploaded_files=NULL;
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+       int str_len = 0, num_vars = 0, num_vars_max = 2*10, *len_list = NULL;
+       char **val_list = NULL;
+#endif
+       multipart_buffer *mbuff;
+       zval *array_ptr = (zval *) arg;
+       int fd=-1;
+       zend_llist header;
+       void *event_extra_data = NULL;
+       int llen = 0;
+
+       if (SG(request_info).content_length > SG(post_max_size)) {
+               sapi_module.sapi_error(E_WARNING, "POST Content-Length of %ld 
bytes exceeds the limit of %ld bytes", SG(request_info).content_length, 
SG(post_max_size));
+               return;
+       }
+
+       /* Get the boundary */
+       boundary = strstr(content_type_dup, "boundary");
+       if (!boundary || !(boundary=strchr(boundary, '='))) {
+               sapi_module.sapi_error(E_WARNING, "Missing boundary in 
multipart/form-data POST data");
+               return;
+       }
+
+       boundary++;
+       boundary_len = strlen(boundary);
+
+       if (boundary[0] == '"') {
+               boundary++;
+               boundary_end = strchr(boundary, '"');
+               if (!boundary_end) { 
+                       sapi_module.sapi_error(E_WARNING, "Invalid boundary in 
multipart/form-data POST data");
+                       return;
+               }
+       } else {
+               /* search for the end of the boundary */
+               boundary_end = strchr(boundary, ',');
+       }
+       if (boundary_end) {
+               boundary_end[0] = '\0';
+               boundary_len = boundary_end-boundary;
+       }
+
+       /* Initialize the buffer */
+       if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) {
+               sapi_module.sapi_error(E_WARNING, "Unable to initialize the 
input buffer");
+               return;
+       }
+
+       /* Initialize $_FILES[] */
+       zend_hash_init(&PG(rfc1867_protected_variables), 5, NULL, NULL, 0);
+
+       ALLOC_HASHTABLE(uploaded_files);
+       zend_hash_init(uploaded_files, 5, NULL, (dtor_func_t) free_estring, 0);
+       SG(rfc1867_uploaded_files) = uploaded_files;
+
+       ALLOC_ZVAL(http_post_files);
+       array_init(http_post_files);
+       INIT_PZVAL(http_post_files);
+       PG(http_globals)[TRACK_VARS_FILES] = http_post_files;
+
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+       if (php_mb_encoding_translation(TSRMLS_C)) {
+               val_list = (char **)ecalloc(num_vars_max+2, sizeof(char *));
+               len_list = (int *)ecalloc(num_vars_max+2, sizeof(int));
+       }
+#endif
+       zend_llist_init(&header, sizeof(mime_header_entry), (llist_dtor_func_t) 
php_free_hdr_entry, 0);
+
+       if (php_rfc1867_callback != NULL) {
+               multipart_event_start event_start;
+
+               event_start.content_length = SG(request_info).content_length;
+               if (php_rfc1867_callback(MULTIPART_EVENT_START, &event_start, 
&event_extra_data TSRMLS_CC) == FAILURE) {
+                       goto fileupload_done;
+               }
+       }
+
+
+       while (!multipart_buffer_eof(mbuff TSRMLS_CC))
+       {
+               char buff[FILLUNIT];
+               char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
+               size_t blen=0, wlen=0;
+               off_t offset;
+
+               zend_llist_clean(&header);
+
+               if (!multipart_buffer_headers(mbuff, &header TSRMLS_CC)) {
+                       goto fileupload_done;
+               }
+
+               if ((cd = php_mime_get_hdr_value(header, 
"Content-Disposition"))) {
+                       char *pair=NULL;
+                       int end=0;
+                       
+                       while (isspace(*cd)) {
+                               ++cd;
+                       }
+
+                       while (*cd && (pair = php_ap_getword(&cd, ';')))
+                       {
+                               char *key=NULL, *word = pair;
+
+                               while (isspace(*cd)) {
+                                       ++cd;
+                               }
+
+                               if (strchr(pair, '=')) {
+                                       key = php_ap_getword(&pair, '=');
+
+                                       if (!strcasecmp(key, "name")) {
+                                               if (param) {
+                                                       efree(param);
+                                               }
+                                               param = 
php_ap_getword_conf(&pair TSRMLS_CC);
+                                       } else if (!strcasecmp(key, 
"filename")) {
+                                               if (filename) {
+                                                       efree(filename);
+                                               }
+                                               filename = 
php_ap_getword_conf(&pair TSRMLS_CC);
+                                       }
+                               }
+                               if (key) {
+                                       efree(key);
+                               }
+                               efree(word);
+                       }
+
+                       /* Normal form variable, safe to read all data into 
memory */
+                       if (!filename && param) {
+                               unsigned int value_len; 
+                               char *value = multipart_buffer_read_body(mbuff, 
&value_len TSRMLS_CC);
+                               unsigned int new_val_len; /* Dummy variable */
+
+                               if (!value) {
+                                       value = estrdup("");
+                               }
+
+                               if (sapi_module.input_filter(PARSE_POST, param, 
&value, value_len, &new_val_len TSRMLS_CC)) {
+                                       if (php_rfc1867_callback != NULL) {
+                                               multipart_event_formdata 
event_formdata;
+                                               size_t newlength = 0;
+
+                                               
event_formdata.post_bytes_processed = SG(read_post_bytes);
+                                               event_formdata.name = 
ZSTR(param);
+                                               event_formdata.value = 
PZSTR(value);
+                                               event_formdata.length = 
new_val_len;
+                                               event_formdata.newlength = 
&newlength;
+                                               if 
(php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, 
&event_extra_data TSRMLS_CC) == FAILURE) {
+                                                       efree(param);
+                                                       efree(value);
+                                                       continue;
+                                               }
+                                               new_val_len = newlength;
+                                       }
+
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+                                       if 
(php_mb_encoding_translation(TSRMLS_C)) {
+                                               
php_mb_gpc_stack_variable(param, value, &val_list, &len_list, 
+                                                                               
                  &num_vars, &num_vars_max TSRMLS_CC);
+                                       } else {
+                                               
safe_php_register_variable(param, value, new_val_len, array_ptr, 0 TSRMLS_CC);
+                                       }
+#else
+                                       safe_php_register_variable(param, 
value, new_val_len, array_ptr, 0 TSRMLS_CC);
+#endif
+                               } else if (php_rfc1867_callback != NULL) {
+                                       multipart_event_formdata event_formdata;
+
+                                       event_formdata.post_bytes_processed = 
SG(read_post_bytes);
+                                       event_formdata.name = ZSTR(param);
+                                       event_formdata.value = PZSTR(value);
+                                       event_formdata.length = value_len;
+                                       event_formdata.newlength = NULL;
+                                       
php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, 
&event_extra_data TSRMLS_CC);
+                               }
+
+                               if (!strcasecmp(param, "MAX_FILE_SIZE")) {
+                                       max_file_size = atol(value);
+                               }
+
+                               efree(param);
+                               efree(value);
+                               continue;
+                       }
+
+                       /* If file_uploads=off, skip the file part */
+                       if (!PG(file_uploads)) {
+                               skip_upload = 1;
+                       }
+
+                       /* Return with an error if the posted data is garbled */
+                       if (!param && !filename) {
+                               sapi_module.sapi_error(E_WARNING, "File Upload 
Mime headers garbled");
+                               goto fileupload_done;
+                       }
+
+                       if (!param) {
+                               is_anonymous = 1;
+                               param = emalloc(MAX_SIZE_ANONNAME);
+                               snprintf(param, MAX_SIZE_ANONNAME, "%u", 
anonindex++);
+                       } else {
+                               is_anonymous = 0;
+                       }
+
+                       /* New Rule: never repair potential malicious user 
input */
+                       if (!skip_upload) {
+                               char *tmp = param;
+                               long c = 0;
+
+                               while (*tmp) {
+                                       if (*tmp == '[') {
+                                               c++;
+                                       } else if (*tmp == ']') {
+                                               c--;
+                                               if (tmp[1] && tmp[1] != '[') {
+                                                       skip_upload = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (c < 0) {
+                                               skip_upload = 1;
+                                               break;
+                                       }
+                                       tmp++;                          
+                               }
+                       }
+
+                       total_bytes = cancel_upload = 0;
+
+                       if (!skip_upload) {
+                               /* Handle file */
+                               fd = php_open_temporary_fd(PG(upload_tmp_dir), 
"php", &temp_filename TSRMLS_CC);
+                               if (fd==-1) {
+                                       sapi_module.sapi_error(E_WARNING, "File 
upload error - unable to create a temporary file");
+                                       cancel_upload = UPLOAD_ERROR_E;
+                               }
+                       }
+                       
+                       if (!skip_upload && php_rfc1867_callback != NULL) {
+                               multipart_event_file_start event_file_start;
+
+                               event_file_start.post_bytes_processed = 
SG(read_post_bytes);
+                               event_file_start.name = ZSTR(param);
+                               event_file_start.filename = PZSTR(filename);
+                               if 
(php_rfc1867_callback(MULTIPART_EVENT_FILE_START, &event_file_start, 
&event_extra_data TSRMLS_CC) == FAILURE) {
+                                       if (temp_filename) {
+                                               if (cancel_upload != 
UPLOAD_ERROR_E) { /* file creation failed */
+                                                       close(fd);
+                                                       unlink(temp_filename);
+                                               }
+                                               efree(temp_filename);
+                                       }
+                                       temp_filename="";
+                                       efree(param);
+                                       efree(filename);
+                                       continue;
+                               }
+                       }
+
+                       
+                       if (skip_upload) {
+                               efree(param);
+                               efree(filename);
+                               continue;
+                       }       
+
+                       if(strlen(filename) == 0) {
+#if DEBUG_FILE_UPLOAD
+                               sapi_module.sapi_error(E_NOTICE, "No file 
uploaded");
+#endif
+                               cancel_upload = UPLOAD_ERROR_D;
+                       }
+
+                       offset = 0;
+                       end = 0;
+                       while (!cancel_upload && (blen = 
multipart_buffer_read(mbuff, buff, sizeof(buff), &end TSRMLS_CC)))
+                       {
+                               if (php_rfc1867_callback != NULL) {
+                                       multipart_event_file_data 
event_file_data;
+
+                                       event_file_data.post_bytes_processed = 
SG(read_post_bytes);
+                                       event_file_data.offset = offset;
+                                       event_file_data.data = buff;
+                                       event_file_data.length = blen;
+                                       event_file_data.newlength = &blen;
+                                       if 
(php_rfc1867_callback(MULTIPART_EVENT_FILE_DATA, &event_file_data, 
&event_extra_data TSRMLS_CC) == FAILURE) {
+                                               cancel_upload = UPLOAD_ERROR_X;
+                                               continue;
+                                       }
+                               }
+                               
+                       
+                               if (PG(upload_max_filesize) > 0 && 
(total_bytes+blen) > PG(upload_max_filesize)) {
+#if DEBUG_FILE_UPLOAD
+                                       sapi_module.sapi_error(E_NOTICE, 
"upload_max_filesize of %ld bytes exceeded - file [%s=%s] not saved", 
PG(upload_max_filesize), param, filename);
+#endif
+                                       cancel_upload = UPLOAD_ERROR_A;
+                               } else if (max_file_size && ((total_bytes+blen) 
> max_file_size)) {
+#if DEBUG_FILE_UPLOAD
+                                       sapi_module.sapi_error(E_NOTICE, 
"MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, 
param, filename);
+#endif
+                                       cancel_upload = UPLOAD_ERROR_B;
+                               } else if (blen > 0) {
+                                       wlen = write(fd, buff, blen);
+                       
+                                       if (wlen == -1) {
+                                               /* write failed */
+#if DEBUG_FILE_UPLOAD
+                                               
sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno));
+#endif
+                                               cancel_upload = UPLOAD_ERROR_F;
+                                       } else if (wlen < blen) {
+#if DEBUG_FILE_UPLOAD
+                                               
sapi_module.sapi_error(E_NOTICE, "Only %d bytes were written, expected to write 
%d", wlen, blen);
+#endif
+                                               cancel_upload = UPLOAD_ERROR_F;
+                                       } else {
+                                               total_bytes += wlen;
+                                       }
+                                       
+                                       offset += wlen;
+                               } 
+                       }
+                       if (fd!=-1) { /* may not be initialized if file could 
not be created */
+                               close(fd);
+                       }
+                       if (!cancel_upload && !end) {
+#if DEBUG_FILE_UPLOAD
+                               sapi_module.sapi_error(E_NOTICE, "Missing mime 
boundary at the end of the data for file %s", strlen(filename) > 0 ? filename : 
"");
+#endif
+                               cancel_upload = UPLOAD_ERROR_C;
+                       }
+#if DEBUG_FILE_UPLOAD
+                       if(strlen(filename) > 0 && total_bytes == 0 && 
!cancel_upload) {
+                               sapi_module.sapi_error(E_WARNING, "Uploaded 
file size 0 - file [%s=%s] not saved", param, filename);
+                               cancel_upload = 5;
+                       }
+#endif         
+
+                       if (php_rfc1867_callback != NULL) {
+                               multipart_event_file_end event_file_end;
+
+                               event_file_end.post_bytes_processed = 
SG(read_post_bytes);
+                               event_file_end.temp_filename = 
ZSTR(temp_filename);
+                               event_file_end.cancel_upload = cancel_upload;
+                               if 
(php_rfc1867_callback(MULTIPART_EVENT_FILE_END, &event_file_end, 
&event_extra_data TSRMLS_CC) == FAILURE) {
+                                       cancel_upload = UPLOAD_ERROR_X;
+                               }
+                       }
+
+                       if (cancel_upload) {
+                               if (temp_filename) {
+                                       if (cancel_upload != UPLOAD_ERROR_E) { 
/* file creation failed */
+                                               unlink(temp_filename);
+                                       }
+                                       efree(temp_filename);
+                               }
+                               temp_filename="";
+                       } else {
+                               zend_hash_add(SG(rfc1867_uploaded_files), 
temp_filename, strlen(temp_filename) + 1, &temp_filename, sizeof(char *), NULL);
+                       }
+
+                       /* is_arr_upload is true when name of file upload field
+                        * ends in [.*]
+                        * start_arr is set to point to 1st [
+                        */
+                       is_arr_upload = (start_arr = strchr(param,'[')) && 
(param[strlen(param)-1] == ']');
+
+                       if (is_arr_upload) {
+                               array_len = strlen(start_arr);
+                               if (array_index) {
+                                       efree(array_index);
+                               }
+                               array_index = estrndup(start_arr+1, 
array_len-2);   
+                       }
+
+                       /* Add $foo_name */
+                       if (lbuf) {
+                               efree(lbuf);
+                       }
+                       llen = strlen(param) + MAX_SIZE_OF_INDEX + 1;
+                       lbuf = (char *) emalloc(llen);
+
+                       if (is_arr_upload) {
+                               if (abuf) efree(abuf);
+                               abuf = estrndup(param, strlen(param)-array_len);
+                               snprintf(lbuf, llen, "%s_name[%s]", abuf, 
array_index);
+                       } else {
+                               snprintf(lbuf, llen, "%s_name", param);
+                       }
+
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+                       if (php_mb_encoding_translation(TSRMLS_C)) {
+                               if (num_vars>=num_vars_max){    
+                                       php_mb_gpc_realloc_buffer(&val_list, 
&len_list, &num_vars_max, 
+                                                                               
          1 TSRMLS_CC);
+                               }
+                               val_list[num_vars] = filename;
+                               len_list[num_vars] = strlen(filename);
+                               num_vars++;
+                               if(php_mb_gpc_encoding_detector(val_list, 
len_list, num_vars, NULL TSRMLS_CC) == SUCCESS) {
+                                       str_len = strlen(filename);
+                                       
php_mb_gpc_encoding_converter(&filename, &str_len, 1, NULL, NULL TSRMLS_CC);
+                               }
+                               s = php_mb_strrchr(filename, '\\' TSRMLS_CC);
+                               if ((tmp = php_mb_strrchr(filename, '/' 
TSRMLS_CC)) > s) {
+                                       s = tmp;
+                               }
+                               num_vars--;
+                               goto filedone;
+                       }
+#endif                 
+                       /* The \ check should technically be needed for win32 
systems only where
+                        * it is a valid path separator. However, IE in all 
it's wisdom always sends
+                        * the full path of the file on the user's filesystem, 
which means that unless
+                        * the user does basename() they get a bogus file name. 
Until IE's user base drops 
+                        * to nill or problem is fixed this code must remain 
enabled for all systems.
+                        */
+                       s = strrchr(filename, '\\');
+                       if ((tmp = strrchr(filename, '/')) > s) {
+                               s = tmp;
+                       }
+
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+filedone:                      
+#endif
+
+                       if (!is_anonymous) {
+                               if (s && s > filename) {
+                                       safe_php_register_variable(lbuf, s+1, 
strlen(s+1), NULL, 0 TSRMLS_CC);
+                               } else {
+                                       safe_php_register_variable(lbuf, 
filename, strlen(filename), NULL, 0 TSRMLS_CC);
+                               }
+                       }
+
+                       /* Add $foo[name] */
+                       if (is_arr_upload) {
+                               snprintf(lbuf, llen, "%s[name][%s]", abuf, 
array_index);
+                       } else {
+                               snprintf(lbuf, llen, "%s[name]", param);
+                       }
+                       if (s && s > filename) {
+                               register_http_post_files_variable(lbuf, s+1, 
http_post_files, 0 TSRMLS_CC);
+                       } else {
+                               register_http_post_files_variable(lbuf, 
filename, http_post_files, 0 TSRMLS_CC);
+                       }
+                       efree(filename);
+                       s = NULL;
+
+                       /* Possible Content-Type: */
+                       if (cancel_upload || !(cd = 
php_mime_get_hdr_value(header, "Content-Type"))) {
+                               cd = "";
+                       } else { 
+                               /* fix for Opera 6.01 */
+                               s = strchr(cd, ';');
+                               if (s != NULL) {
+                                       *s = '\0';
+                               }
+                       }
+
+                       /* Add $foo_type */
+                       if (is_arr_upload) {
+                               snprintf(lbuf, llen, "%s_type[%s]", abuf, 
array_index);
+                       } else {
+                               snprintf(lbuf, llen, "%s_type", param);
+                       }
+                       if (!is_anonymous) {
+                               safe_php_register_variable(lbuf, cd, 
strlen(cd), NULL, 0 TSRMLS_CC);
+                       }
+
+                       /* Add $foo[type] */
+                       if (is_arr_upload) {
+                               snprintf(lbuf, llen, "%s[type][%s]", abuf, 
array_index);
+                       } else {
+                               snprintf(lbuf, llen, "%s[type]", param);
+                       }
+                       register_http_post_files_variable(lbuf, cd, 
http_post_files, 0 TSRMLS_CC);
+
+                       /* Restore Content-Type Header */
+                       if (s != NULL) {
+                               *s = ';';
+                       }
+                       s = "";
+
+                       /* Initialize variables */
+                       add_protected_variable(param TSRMLS_CC);
+
+                       /* if param is of form xxx[.*] this will cut it to xxx 
*/
+                       if (!is_anonymous) {
+                               safe_php_register_variable(param, 
temp_filename, strlen(temp_filename), NULL, 1 TSRMLS_CC);
+                       }
+
+                       /* Add $foo[tmp_name] */
+                       if (is_arr_upload) {
+                               snprintf(lbuf, llen, "%s[tmp_name][%s]", abuf, 
array_index);
+                       } else {
+                               snprintf(lbuf, llen, "%s[tmp_name]", param);
+                       }
+                       add_protected_variable(lbuf TSRMLS_CC);
+                       register_http_post_files_variable(lbuf, temp_filename, 
http_post_files, 1 TSRMLS_CC);
+
+                       {
+                               zval file_size, error_type;
+
+                               error_type.value.lval = cancel_upload;
+                               error_type.type = IS_LONG;
+
+                               /* Add $foo[error] */
+                               if (cancel_upload) {
+                                       file_size.value.lval = 0;
+                                       file_size.type = IS_LONG;
+                               } else {
+                                       file_size.value.lval = total_bytes;
+                                       file_size.type = IS_LONG;
+                               }       
+
+                               if (is_arr_upload) {
+                                       snprintf(lbuf, llen, "%s[error][%s]", 
abuf, array_index);
+                               } else {
+                                       snprintf(lbuf, llen, "%s[error]", 
param);
+                               }
+                               register_http_post_files_variable_ex(lbuf, 
&error_type, http_post_files, 0 TSRMLS_CC);
+
+                               /* Add $foo_size */
+                               if (is_arr_upload) {
+                                       snprintf(lbuf, llen, "%s_size[%s]", 
abuf, array_index);
+                               } else {
+                                       snprintf(lbuf, llen, "%s_size", param);
+                               }
+                               if (!is_anonymous) {
+                                       safe_php_register_variable_ex(lbuf, 
&file_size, NULL, 0 TSRMLS_CC);
+                               }       
+
+                               /* Add $foo[size] */
+                               if (is_arr_upload) {
+                                       snprintf(lbuf, llen, "%s[size][%s]", 
abuf, array_index);
+                               } else {
+                                       snprintf(lbuf, llen, "%s[size]", param);
+                               }
+                               register_http_post_files_variable_ex(lbuf, 
&file_size, http_post_files, 0 TSRMLS_CC);
+                       }
+                       efree(param);
+               }
+       }
+
+fileupload_done:
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+       php_mb_flush_gpc_variables(num_vars, val_list, len_list, array_ptr 
TSRMLS_CC);
+#endif
+
+       if (php_rfc1867_callback != NULL) {
+               multipart_event_end event_end;
+               
+               event_end.post_bytes_processed = SG(read_post_bytes);
+               php_rfc1867_callback(MULTIPART_EVENT_END, &event_end, 
&event_extra_data TSRMLS_CC);
+       }
+
+       SAFE_RETURN;
+}
+
+/*
+ * The combined READER/HANDLER
+ *
+ */
+
+SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler)
+{
+       rfc1867_post_handler_unicode(content_type_dup, arg TSRMLS_CC);
+}
+
 /*
  * Local variables:
  * tab-width: 4

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to