LTP GCOV extension - code coverage report
Current view: directory - main - rfc1867.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 544
Code covered: 1.8 % Executed lines: 10
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
      16                 :    |          Jani Taskinen <sniper@php.net>                              |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : 
      20                 : /* $Id: rfc1867.c,v 1.173.2.1.2.8 2007/02/24 14:53:50 helly Exp $ */
      21                 : 
      22                 : /*
      23                 :  *  This product includes software developed by the Apache Group
      24                 :  *  for use in the Apache HTTP server project (http://www.apache.org/).
      25                 :  *
      26                 :  */   
      27                 : 
      28                 : #include <stdio.h>
      29                 : #include "php.h"
      30                 : #include "php_open_temporary_file.h"
      31                 : #include "zend_globals.h"
      32                 : #include "php_globals.h"
      33                 : #include "php_variables.h"
      34                 : #include "rfc1867.h"
      35                 : 
      36                 : #define DEBUG_FILE_UPLOAD ZEND_DEBUG
      37                 : 
      38                 : PHPAPI int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC) = NULL;
      39                 : 
      40                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
      41                 : #include "ext/mbstring/mbstring.h"
      42                 : 
      43                 : static void safe_php_register_variable(char *var, char *strval, int val_len, zval *track_vars_array, zend_bool override_protection TSRMLS_DC);
      44                 : 
      45                 : #define SAFE_RETURN { \
      46                 :     php_mb_flush_gpc_variables(num_vars, val_list, len_list, array_ptr TSRMLS_CC); \
      47                 :         if (lbuf) efree(lbuf); \
      48                 :         if (abuf) efree(abuf); \
      49                 :         if (array_index) efree(array_index); \
      50                 :         zend_hash_destroy(&PG(rfc1867_protected_variables)); \
      51                 :         zend_llist_destroy(&header); \
      52                 :         if (mbuff->boundary_next) efree(mbuff->boundary_next); \
      53                 :         if (mbuff->boundary) efree(mbuff->boundary); \
      54                 :         if (mbuff->buffer) efree(mbuff->buffer); \
      55                 :         if (mbuff) efree(mbuff); \
      56                 :         return; }
      57                 : 
      58                 : void php_mb_flush_gpc_variables(int num_vars, char **val_list, int *len_list, zval *array_ptr  TSRMLS_DC)
      59                 : {
      60                 :         int i;
      61                 :         if (php_mb_encoding_translation(TSRMLS_C)) {
      62                 :                 if (num_vars > 0 &&
      63                 :                         php_mb_gpc_encoding_detector(val_list, len_list, num_vars, NULL TSRMLS_CC) == SUCCESS) {
      64                 :                         php_mb_gpc_encoding_converter(val_list, len_list, num_vars, NULL, NULL TSRMLS_CC);
      65                 :                 }
      66                 :                 for (i=0; i<num_vars; i+=2){
      67                 :                         safe_php_register_variable(val_list[i], val_list[i+1], len_list[i+1], array_ptr, 0 TSRMLS_CC);
      68                 :                         efree(val_list[i]);
      69                 :                         efree(val_list[i+1]);
      70                 :                 } 
      71                 :                 efree(val_list);
      72                 :                 efree(len_list);
      73                 :         }
      74                 : }
      75                 : 
      76                 : void php_mb_gpc_realloc_buffer(char ***pval_list, int **plen_list, int *num_vars_max, int inc  TSRMLS_DC)
      77                 : {
      78                 :         /* allow only even increments */
      79                 :         if (inc & 1) {
      80                 :                 inc++;
      81                 :         }
      82                 :         (*num_vars_max) += inc;
      83                 :         *pval_list = (char **)erealloc(*pval_list, (*num_vars_max+2)*sizeof(char *));
      84                 :         *plen_list = (int *)erealloc(*plen_list, (*num_vars_max+2)*sizeof(int));
      85                 : }
      86                 : 
      87                 : 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)
      88                 : {
      89                 :         char **val_list=*pval_list;
      90                 :         int *len_list=*plen_list;
      91                 : 
      92                 :         if (*num_vars>=*num_vars_max){       
      93                 :                 php_mb_gpc_realloc_buffer(pval_list, plen_list, num_vars_max, 
      94                 :                                                                   16 TSRMLS_CC);
      95                 :                 /* in case realloc relocated the buffer */
      96                 :                 val_list = *pval_list;
      97                 :                 len_list = *plen_list;
      98                 :         }
      99                 : 
     100                 :         val_list[*num_vars] = (char *)estrdup(param);
     101                 :         len_list[*num_vars] = strlen(param);
     102                 :         (*num_vars)++;
     103                 :         val_list[*num_vars] = (char *)estrdup(value);
     104                 :         len_list[*num_vars] = strlen(value);
     105                 :         (*num_vars)++;
     106                 : }
     107                 : 
     108                 : #else
     109                 : 
     110                 : #define SAFE_RETURN { \
     111                 :         if (lbuf) efree(lbuf); \
     112                 :         if (abuf) efree(abuf); \
     113                 :         if (array_index) efree(array_index); \
     114                 :         zend_hash_destroy(&PG(rfc1867_protected_variables)); \
     115                 :         zend_llist_destroy(&header); \
     116                 :         if (mbuff->boundary_next) efree(mbuff->boundary_next); \
     117                 :         if (mbuff->boundary) efree(mbuff->boundary); \
     118                 :         if (mbuff->buffer) efree(mbuff->buffer); \
     119                 :         if (mbuff) efree(mbuff); \
     120                 :         return; }
     121                 : #endif
     122                 : 
     123                 : /* The longest property name we use in an uploaded file array */
     124                 : #define MAX_SIZE_OF_INDEX sizeof("[tmp_name]")
     125                 : 
     126                 : /* The longest anonymous name */
     127                 : #define MAX_SIZE_ANONNAME 33
     128                 : 
     129                 : /* Errors */
     130                 : #define UPLOAD_ERROR_OK   0  /* File upload succesful */
     131                 : #define UPLOAD_ERROR_A    1  /* Uploaded file exceeded upload_max_filesize */
     132                 : #define UPLOAD_ERROR_B    2  /* Uploaded file exceeded MAX_FILE_SIZE */
     133                 : #define UPLOAD_ERROR_C    3  /* Partially uploaded */
     134                 : #define UPLOAD_ERROR_D    4  /* No file uploaded */
     135                 : #define UPLOAD_ERROR_E    6  /* Missing /tmp or similar directory */
     136                 : #define UPLOAD_ERROR_F    7  /* Failed to write file to disk */
     137                 : #define UPLOAD_ERROR_X    8  /* File upload stopped by extension */
     138                 : 
     139                 : void php_rfc1867_register_constants(TSRMLS_D)
     140             220 : {
     141             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_OK",         UPLOAD_ERROR_OK, CONST_CS | CONST_PERSISTENT);
     142             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_INI_SIZE",   UPLOAD_ERROR_A,  CONST_CS | CONST_PERSISTENT);
     143             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FORM_SIZE",  UPLOAD_ERROR_B,  CONST_CS | CONST_PERSISTENT);
     144             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL",    UPLOAD_ERROR_C,  CONST_CS | CONST_PERSISTENT);
     145             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE",    UPLOAD_ERROR_D,  CONST_CS | CONST_PERSISTENT);
     146             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E,  CONST_CS | CONST_PERSISTENT);
     147             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_CANT_WRITE", UPLOAD_ERROR_F,  CONST_CS | CONST_PERSISTENT);
     148             220 :         REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_EXTENSION",  UPLOAD_ERROR_X,  CONST_CS | CONST_PERSISTENT);
     149             220 : }
     150                 : 
     151                 : static void normalize_protected_variable(char *varname TSRMLS_DC)
     152               0 : {
     153               0 :         char *s=varname, *index=NULL, *indexend=NULL, *p;
     154                 :         
     155                 :         /* overjump leading space */
     156               0 :         while (*s == ' ') {
     157               0 :                 s++;
     158                 :         }
     159                 :         
     160                 :         /* and remove it */
     161               0 :         if (s != varname) {
     162               0 :                 memmove(varname, s, strlen(s)+1);
     163                 :         }
     164                 : 
     165               0 :         for (p=varname; *p && *p != '['; p++) {
     166               0 :                 switch(*p) {
     167                 :                         case ' ':
     168                 :                         case '.':
     169               0 :                                 *p='_';
     170                 :                                 break;
     171                 :                 }
     172                 :         }
     173                 : 
     174                 :         /* find index */
     175               0 :         index = strchr(varname, '[');
     176               0 :         if (index) {
     177               0 :                 index++;
     178               0 :                 s=index;
     179                 :         } else {
     180               0 :                 return;
     181                 :         }
     182                 : 
     183                 :         /* done? */
     184               0 :         while (index) {
     185                 : 
     186               0 :                 while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
     187               0 :                         index++;
     188                 :                 }
     189               0 :                 indexend = strchr(index, ']');
     190               0 :                 indexend = indexend ? indexend + 1 : index + strlen(index);
     191                 :                 
     192               0 :                 if (s != index) {
     193               0 :                         memmove(s, index, strlen(index)+1);
     194               0 :                         s += indexend-index;
     195                 :                 } else {
     196               0 :                         s = indexend;
     197                 :                 }
     198                 : 
     199               0 :                 if (*s == '[') {
     200               0 :                         s++;
     201               0 :                         index = s;
     202                 :                 } else {
     203               0 :                         index = NULL;
     204                 :                 }       
     205                 :         }
     206               0 :         *s++='\0';
     207                 : }
     208                 : 
     209                 : 
     210                 : static void add_protected_variable(char *varname TSRMLS_DC)
     211               0 : {
     212               0 :         int dummy=1;
     213                 : 
     214               0 :         normalize_protected_variable(varname TSRMLS_CC);
     215               0 :         zend_hash_add(&PG(rfc1867_protected_variables), varname, strlen(varname)+1, &dummy, sizeof(int), NULL);
     216               0 : }
     217                 : 
     218                 : 
     219                 : static zend_bool is_protected_variable(char *varname TSRMLS_DC)
     220               0 : {
     221               0 :         normalize_protected_variable(varname TSRMLS_CC);
     222               0 :         return zend_hash_exists(&PG(rfc1867_protected_variables), varname, strlen(varname)+1);
     223                 : }
     224                 : 
     225                 : 
     226                 : static void safe_php_register_variable(char *var, char *strval, int val_len, zval *track_vars_array, zend_bool override_protection TSRMLS_DC)
     227               0 : {
     228               0 :         if (override_protection || !is_protected_variable(var TSRMLS_CC)) {
     229               0 :                 php_register_variable_safe(var, strval, val_len, track_vars_array TSRMLS_CC);
     230                 :         }
     231               0 : }
     232                 : 
     233                 : 
     234                 : static void safe_php_register_variable_ex(char *var, zval *val, zval *track_vars_array, zend_bool override_protection TSRMLS_DC)
     235               0 : {
     236               0 :         if (override_protection || !is_protected_variable(var TSRMLS_CC)) {
     237               0 :                 php_register_variable_ex(var, val, track_vars_array TSRMLS_CC);
     238                 :         }
     239               0 : }
     240                 : 
     241                 : 
     242                 : static void register_http_post_files_variable(char *strvar, char *val, zval *http_post_files, zend_bool override_protection TSRMLS_DC)
     243               0 : {
     244               0 :         int register_globals = PG(register_globals);
     245                 : 
     246               0 :         PG(register_globals) = 0;
     247               0 :         safe_php_register_variable(strvar, val, strlen(val), http_post_files, override_protection TSRMLS_CC);
     248               0 :         PG(register_globals) = register_globals;
     249               0 : }
     250                 : 
     251                 : 
     252                 : static void register_http_post_files_variable_ex(char *var, zval *val, zval *http_post_files, zend_bool override_protection TSRMLS_DC)
     253               0 : {
     254               0 :         int register_globals = PG(register_globals);
     255                 : 
     256               0 :         PG(register_globals) = 0;
     257               0 :         safe_php_register_variable_ex(var, val, http_post_files, override_protection TSRMLS_CC);
     258               0 :         PG(register_globals) = register_globals;
     259               0 : }
     260                 : 
     261                 : 
     262                 : static int unlink_filename(char **filename TSRMLS_DC)
     263               0 : {
     264               0 :         VCWD_UNLINK(*filename);
     265               0 :         return 0;
     266                 : }
     267                 : 
     268                 : 
     269                 : void destroy_uploaded_files_hash(TSRMLS_D)
     270               0 : {
     271               0 :         zend_hash_apply(SG(rfc1867_uploaded_files), (apply_func_t) unlink_filename TSRMLS_CC);
     272               0 :         zend_hash_destroy(SG(rfc1867_uploaded_files));
     273               0 :         FREE_HASHTABLE(SG(rfc1867_uploaded_files));
     274               0 : }
     275                 : 
     276                 : 
     277                 : /*
     278                 :  *  Following code is based on apache_multipart_buffer.c from libapreq-0.33 package.
     279                 :  *
     280                 :  */
     281                 : 
     282                 : #define FILLUNIT (1024 * 5)
     283                 : 
     284                 : typedef struct {
     285                 : 
     286                 :         /* read buffer */
     287                 :         char *buffer;
     288                 :         char *buf_begin;
     289                 :         int  bufsize;
     290                 :         int  bytes_in_buffer;
     291                 : 
     292                 :         /* boundary info */
     293                 :         char *boundary;
     294                 :         char *boundary_next;
     295                 :         int  boundary_next_len;
     296                 : 
     297                 : } multipart_buffer;
     298                 : 
     299                 : 
     300                 : typedef struct {
     301                 :         char *key;
     302                 :         char *value;
     303                 : } mime_header_entry;
     304                 : 
     305                 : 
     306                 : /*
     307                 :   fill up the buffer with client data.
     308                 :   returns number of bytes added to buffer.
     309                 : */
     310                 : static int fill_buffer(multipart_buffer *self TSRMLS_DC)
     311               0 : {
     312               0 :         int bytes_to_read, total_read = 0, actual_read = 0;
     313                 : 
     314                 :         /* shift the existing data if necessary */
     315               0 :         if (self->bytes_in_buffer > 0 && self->buf_begin != self->buffer) {
     316               0 :                 memmove(self->buffer, self->buf_begin, self->bytes_in_buffer);
     317                 :         }
     318                 : 
     319               0 :         self->buf_begin = self->buffer;
     320                 : 
     321                 :         /* calculate the free space in the buffer */
     322               0 :         bytes_to_read = self->bufsize - self->bytes_in_buffer;
     323                 : 
     324                 :         /* read the required number of bytes */
     325               0 :         while (bytes_to_read > 0) {
     326                 : 
     327               0 :                 char *buf = self->buffer + self->bytes_in_buffer;
     328                 : 
     329               0 :                 actual_read = sapi_module.read_post(buf, bytes_to_read TSRMLS_CC);
     330                 : 
     331                 :                 /* update the buffer length */
     332               0 :                 if (actual_read > 0) {
     333               0 :                         self->bytes_in_buffer += actual_read;
     334               0 :                         SG(read_post_bytes) += actual_read;
     335               0 :                         total_read += actual_read;
     336               0 :                         bytes_to_read -= actual_read;
     337                 :                 } else {
     338               0 :                         break;
     339                 :                 }
     340                 :         }
     341                 : 
     342               0 :         return total_read;
     343                 : }
     344                 : 
     345                 : 
     346                 : /* eof if we are out of bytes, or if we hit the final boundary */
     347                 : static int multipart_buffer_eof(multipart_buffer *self TSRMLS_DC)
     348               0 : {
     349               0 :         if ( (self->bytes_in_buffer == 0 && fill_buffer(self TSRMLS_CC) < 1) ) {
     350               0 :                 return 1;
     351                 :         } else {
     352               0 :                 return 0;
     353                 :         }
     354                 : }
     355                 : 
     356                 : 
     357                 : /* create new multipart_buffer structure */
     358                 : static multipart_buffer *multipart_buffer_new(char *boundary, int boundary_len)
     359               0 : {
     360               0 :         multipart_buffer *self = (multipart_buffer *) ecalloc(1, sizeof(multipart_buffer));
     361                 : 
     362               0 :         int minsize = boundary_len + 6;
     363               0 :         if (minsize < FILLUNIT) minsize = FILLUNIT;
     364                 : 
     365               0 :         self->buffer = (char *) ecalloc(1, minsize + 1);
     366               0 :         self->bufsize = minsize;
     367                 : 
     368               0 :         spprintf(&self->boundary, 0, "--%s", boundary);
     369                 :         
     370               0 :         self->boundary_next_len = spprintf(&self->boundary_next, 0, "\n--%s", boundary);
     371                 : 
     372               0 :         self->buf_begin = self->buffer;
     373               0 :         self->bytes_in_buffer = 0;
     374                 : 
     375               0 :         return self;
     376                 : }
     377                 : 
     378                 : 
     379                 : /*
     380                 :   gets the next CRLF terminated line from the input buffer.
     381                 :   if it doesn't find a CRLF, and the buffer isn't completely full, returns
     382                 :   NULL; otherwise, returns the beginning of the null-terminated line,
     383                 :   minus the CRLF.
     384                 : 
     385                 :   note that we really just look for LF terminated lines. this works
     386                 :   around a bug in internet explorer for the macintosh which sends mime
     387                 :   boundaries that are only LF terminated when you use an image submit
     388                 :   button in a multipart/form-data form.
     389                 :  */
     390                 : static char *next_line(multipart_buffer *self)
     391               0 : {
     392                 :         /* look for LF in the data */
     393               0 :         char* line = self->buf_begin;
     394               0 :         char* ptr = memchr(self->buf_begin, '\n', self->bytes_in_buffer);
     395                 : 
     396               0 :         if (ptr) {      /* LF found */
     397                 : 
     398                 :                 /* terminate the string, remove CRLF */
     399               0 :                 if ((ptr - line) > 0 && *(ptr-1) == '\r') {
     400               0 :                         *(ptr-1) = 0;
     401                 :                 } else {
     402               0 :                         *ptr = 0;
     403                 :                 }
     404                 : 
     405                 :                 /* bump the pointer */
     406               0 :                 self->buf_begin = ptr + 1;
     407               0 :                 self->bytes_in_buffer -= (self->buf_begin - line);
     408                 :         
     409                 :         } else {        /* no LF found */
     410                 : 
     411                 :                 /* buffer isn't completely full, fail */
     412               0 :                 if (self->bytes_in_buffer < self->bufsize) {
     413               0 :                         return NULL;
     414                 :                 }
     415                 :                 /* return entire buffer as a partial line */
     416               0 :                 line[self->bufsize] = 0;
     417               0 :                 self->buf_begin = ptr;
     418               0 :                 self->bytes_in_buffer = 0;
     419                 :         }
     420                 : 
     421               0 :         return line;
     422                 : }
     423                 : 
     424                 : 
     425                 : /* returns the next CRLF terminated line from the client */
     426                 : static char *get_line(multipart_buffer *self TSRMLS_DC)
     427               0 : {
     428               0 :         char* ptr = next_line(self);
     429                 : 
     430               0 :         if (!ptr) {
     431               0 :                 fill_buffer(self TSRMLS_CC);
     432               0 :                 ptr = next_line(self);
     433                 :         }
     434                 : 
     435               0 :         return ptr;
     436                 : }
     437                 : 
     438                 : 
     439                 : /* Free header entry */
     440                 : static void php_free_hdr_entry(mime_header_entry *h)
     441               0 : {
     442               0 :         if (h->key) {
     443               0 :                 efree(h->key);
     444                 :         }
     445               0 :         if (h->value) {
     446               0 :                 efree(h->value);
     447                 :         }
     448               0 : }
     449                 : 
     450                 : 
     451                 : /* finds a boundary */
     452                 : static int find_boundary(multipart_buffer *self, char *boundary TSRMLS_DC)
     453               0 : {
     454                 :         char *line;
     455                 : 
     456                 :         /* loop thru lines */
     457               0 :         while( (line = get_line(self TSRMLS_CC)) )
     458                 :         {
     459                 :                 /* finished if we found the boundary */
     460               0 :                 if (!strcmp(line, boundary)) {
     461               0 :                         return 1;
     462                 :                 }
     463                 :         }
     464                 : 
     465                 :         /* didn't find the boundary */
     466               0 :         return 0;
     467                 : }
     468                 : 
     469                 : 
     470                 : /* parse headers */
     471                 : static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header TSRMLS_DC)
     472               0 : {
     473                 :         char *line;
     474                 :         mime_header_entry prev_entry, entry;
     475                 :         int prev_len, cur_len;
     476                 :         
     477                 :         /* didn't find boundary, abort */
     478               0 :         if (!find_boundary(self, self->boundary TSRMLS_CC)) {
     479               0 :                 return 0;
     480                 :         }
     481                 : 
     482                 :         /* get lines of text, or CRLF_CRLF */
     483                 : 
     484               0 :         while( (line = get_line(self TSRMLS_CC)) && strlen(line) > 0 )
     485                 :         {
     486                 :                 /* add header to table */
     487                 :                 
     488               0 :                 char *key = line;
     489               0 :                 char *value = NULL;
     490                 :                 
     491                 :                 /* space in the beginning means same header */
     492               0 :                 if (!isspace(line[0])) {
     493               0 :                         value = strchr(line, ':');
     494                 :                 }
     495                 : 
     496               0 :                 if (value) {
     497               0 :                         *value = 0;
     498               0 :                         do { value++; } while(isspace(*value));
     499                 : 
     500               0 :                         entry.value = estrdup(value);
     501               0 :                         entry.key = estrdup(key);
     502                 : 
     503               0 :                 } else if (zend_llist_count(header)) { /* If no ':' on the line, add to previous line */
     504                 : 
     505               0 :                         prev_len = strlen(prev_entry.value);
     506               0 :                         cur_len = strlen(line);
     507                 : 
     508               0 :                         entry.value = emalloc(prev_len + cur_len + 1);
     509               0 :                         memcpy(entry.value, prev_entry.value, prev_len);
     510               0 :                         memcpy(entry.value + prev_len, line, cur_len);
     511               0 :                         entry.value[cur_len + prev_len] = '\0';
     512                 : 
     513               0 :                         entry.key = estrdup(prev_entry.key);
     514                 :                         
     515               0 :                         zend_llist_remove_tail(header);
     516                 :                 } else {
     517               0 :                         continue;
     518                 :                 }
     519                 : 
     520               0 :                 zend_llist_add_element(header, &entry);
     521               0 :                 prev_entry = entry;
     522                 :         }
     523                 : 
     524               0 :         return 1;
     525                 : }
     526                 : 
     527                 : 
     528                 : static char *php_mime_get_hdr_value(zend_llist header, char *key)
     529               0 : {
     530                 :         mime_header_entry *entry;
     531                 : 
     532               0 :         if (key == NULL) {
     533               0 :                 return NULL;
     534                 :         }
     535                 :         
     536               0 :         entry = zend_llist_get_first(&header);
     537               0 :         while (entry) {
     538               0 :                 if (!strcasecmp(entry->key, key)) {
     539               0 :                         return entry->value;
     540                 :                 }
     541               0 :                 entry = zend_llist_get_next(&header);
     542                 :         }
     543                 :         
     544               0 :         return NULL;
     545                 : }
     546                 : 
     547                 : 
     548                 : static char *php_ap_getword(char **line, char stop)
     549               0 : {
     550               0 :         char *pos = *line, quote;
     551                 :         char *res;
     552                 : 
     553               0 :         while (*pos && *pos != stop) {
     554                 :                 
     555               0 :                 if ((quote = *pos) == '"' || quote == '\'') {
     556               0 :                         ++pos;
     557               0 :                         while (*pos && *pos != quote) {
     558               0 :                                 if (*pos == '\\' && pos[1] && pos[1] == quote) {
     559               0 :                                         pos += 2;
     560                 :                                 } else {
     561               0 :                                         ++pos;
     562                 :                                 }
     563                 :                         }
     564               0 :                         if (*pos) {
     565               0 :                                 ++pos;
     566                 :                         }
     567               0 :                 } else ++pos;
     568                 :                 
     569                 :         }
     570               0 :         if (*pos == '\0') {
     571               0 :                 res = estrdup(*line);
     572               0 :                 *line += strlen(*line);
     573               0 :                 return res;
     574                 :         }
     575                 : 
     576               0 :         res = estrndup(*line, pos - *line);
     577                 : 
     578               0 :         while (*pos == stop) {
     579               0 :                 ++pos;
     580                 :         }
     581                 : 
     582               0 :         *line = pos;
     583               0 :         return res;
     584                 : }
     585                 : 
     586                 : 
     587                 : static char *substring_conf(char *start, int len, char quote TSRMLS_DC)
     588               0 : {
     589               0 :         char *result = emalloc(len + 2);
     590               0 :         char *resp = result;
     591                 :         int i;
     592                 : 
     593               0 :         for (i = 0; i < len; ++i) {
     594               0 :                 if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
     595               0 :                         *resp++ = start[++i];
     596                 :                 } else {
     597                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
     598                 :                         if (php_mb_encoding_translation(TSRMLS_C)) {
     599                 :                                 size_t j = php_mb_gpc_mbchar_bytes(start+i TSRMLS_CC);
     600                 :                                 while (j-- > 0 && i < len) {
     601                 :                                         *resp++ = start[i++];
     602                 :                                 }
     603                 :                                 --i;
     604                 :                         } else {
     605                 :                                 *resp++ = start[i];
     606                 :                         }
     607                 : #else
     608               0 :                         *resp++ = start[i];
     609                 : #endif
     610                 :                 }
     611                 :         }
     612                 : 
     613               0 :         *resp++ = '\0';
     614               0 :         return result;
     615                 : }
     616                 : 
     617                 : 
     618                 : static char *php_ap_getword_conf(char **line TSRMLS_DC)
     619               0 : {
     620               0 :         char *str = *line, *strend, *res, quote;
     621                 : 
     622                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
     623                 :         if (php_mb_encoding_translation(TSRMLS_C)) {
     624                 :                 int len=strlen(str);
     625                 :                 php_mb_gpc_encoding_detector(&str, &len, 1, NULL TSRMLS_CC);
     626                 :         }
     627                 : #endif
     628                 : 
     629               0 :         while (*str && isspace(*str)) {
     630               0 :                 ++str;
     631                 :         }
     632                 : 
     633               0 :         if (!*str) {
     634               0 :                 *line = str;
     635               0 :                 return estrdup("");
     636                 :         }
     637                 : 
     638               0 :         if ((quote = *str) == '"' || quote == '\'') {
     639               0 :                 strend = str + 1;
     640               0 : look_for_quote:
     641               0 :                 while (*strend && *strend != quote) {
     642               0 :                         if (*strend == '\\' && strend[1] && strend[1] == quote) {
     643               0 :                                 strend += 2;
     644                 :                         } else {
     645               0 :                                 ++strend;
     646                 :                         }
     647                 :                 }
     648               0 :                 if (*strend && *strend == quote) {
     649               0 :                         char p = *(strend + 1);
     650               0 :                         if (p != '\r' && p != '\n' && p != '\0') {
     651               0 :                                 strend++;
     652               0 :                                 goto look_for_quote;
     653                 :                         }
     654                 :                 }
     655                 : 
     656               0 :                 res = substring_conf(str + 1, strend - str - 1, quote TSRMLS_CC);
     657                 : 
     658               0 :                 if (*strend == quote) {
     659               0 :                         ++strend;
     660                 :                 }
     661                 : 
     662                 :         } else {
     663                 : 
     664               0 :                 strend = str;
     665               0 :                 while (*strend && !isspace(*strend)) {
     666               0 :                         ++strend;
     667                 :                 }
     668               0 :                 res = substring_conf(str, strend - str, 0 TSRMLS_CC);
     669                 :         }
     670                 : 
     671               0 :         while (*strend && isspace(*strend)) {
     672               0 :                 ++strend;
     673                 :         }
     674                 : 
     675               0 :         *line = strend;
     676               0 :         return res;
     677                 : }
     678                 : 
     679                 : 
     680                 : /*
     681                 :   search for a string in a fixed-length byte string.
     682                 :   if partial is true, partial matches are allowed at the end of the buffer.
     683                 :   returns NULL if not found, or a pointer to the start of the first match.
     684                 : */
     685                 : static void *php_ap_memstr(char *haystack, int haystacklen, char *needle, int needlen, int partial)
     686               0 : {
     687               0 :         int len = haystacklen;
     688               0 :         char *ptr = haystack;
     689                 : 
     690                 :         /* iterate through first character matches */
     691               0 :         while( (ptr = memchr(ptr, needle[0], len)) ) {
     692                 : 
     693                 :                 /* calculate length after match */
     694               0 :                 len = haystacklen - (ptr - (char *)haystack);
     695                 : 
     696                 :                 /* done if matches up to capacity of buffer */
     697               0 :                 if (memcmp(needle, ptr, needlen < len ? needlen : len) == 0 && (partial || len >= needlen)) {
     698                 :                         break;
     699                 :                 }
     700                 : 
     701                 :                 /* next character */
     702               0 :                 ptr++; len--;
     703                 :         }
     704                 : 
     705               0 :         return ptr;
     706                 : }
     707                 : 
     708                 : 
     709                 : /* read until a boundary condition */
     710                 : static int multipart_buffer_read(multipart_buffer *self, char *buf, int bytes, int *end TSRMLS_DC)
     711               0 : {
     712                 :         int len, max;
     713                 :         char *bound;
     714                 : 
     715                 :         /* fill buffer if needed */
     716               0 :         if (bytes > self->bytes_in_buffer) {
     717               0 :                 fill_buffer(self TSRMLS_CC);
     718                 :         }
     719                 : 
     720                 :         /* look for a potential boundary match, only read data up to that point */
     721               0 :         if ((bound = php_ap_memstr(self->buf_begin, self->bytes_in_buffer, self->boundary_next, self->boundary_next_len, 1))) {
     722               0 :                 max = bound - self->buf_begin;
     723               0 :                 if (end && php_ap_memstr(self->buf_begin, self->bytes_in_buffer, self->boundary_next, self->boundary_next_len, 0)) {
     724               0 :                         *end = 1;
     725                 :                 }
     726                 :         } else {
     727               0 :                 max = self->bytes_in_buffer;
     728                 :         }
     729                 : 
     730                 :         /* maximum number of bytes we are reading */
     731               0 :         len = max < bytes-1 ? max : bytes-1;
     732                 : 
     733                 :         /* if we read any data... */
     734               0 :         if (len > 0) {
     735                 : 
     736                 :                 /* copy the data */
     737               0 :                 memcpy(buf, self->buf_begin, len);
     738               0 :                 buf[len] = 0;
     739                 : 
     740               0 :                 if (bound && len > 0 && buf[len-1] == '\r') {
     741               0 :                         buf[--len] = 0;
     742                 :                 }
     743                 : 
     744                 :                 /* update the buffer */
     745               0 :                 self->bytes_in_buffer -= len;
     746               0 :                 self->buf_begin += len;
     747                 :         }
     748                 : 
     749               0 :         return len;
     750                 : }
     751                 : 
     752                 : 
     753                 : /*
     754                 :   XXX: this is horrible memory-usage-wise, but we only expect
     755                 :   to do this on small pieces of form data.
     756                 : */
     757                 : static char *multipart_buffer_read_body(multipart_buffer *self, unsigned int *len TSRMLS_DC)
     758               0 : {
     759               0 :         char buf[FILLUNIT], *out=NULL;
     760               0 :         int total_bytes=0, read_bytes=0;
     761                 : 
     762               0 :         while((read_bytes = multipart_buffer_read(self, buf, sizeof(buf), NULL TSRMLS_CC))) {
     763               0 :                 out = erealloc(out, total_bytes + read_bytes + 1);
     764               0 :                 memcpy(out + total_bytes, buf, read_bytes);
     765               0 :                 total_bytes += read_bytes;
     766                 :         }
     767                 : 
     768               0 :         if (out) out[total_bytes] = '\0';
     769               0 :         *len = total_bytes;
     770                 : 
     771               0 :         return out;
     772                 : }
     773                 : 
     774                 : 
     775                 : /*
     776                 :  * The combined READER/HANDLER
     777                 :  *
     778                 :  */
     779                 : 
     780                 : SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler)
     781               0 : {
     782               0 :         char *boundary, *s=NULL, *boundary_end = NULL, *start_arr=NULL, *array_index=NULL;
     783               0 :         char *temp_filename=NULL, *lbuf=NULL, *abuf=NULL;
     784               0 :         int boundary_len=0, total_bytes=0, cancel_upload=0, is_arr_upload=0, array_len=0;
     785               0 :         int max_file_size=0, skip_upload=0, anonindex=0, is_anonymous;
     786               0 :         zval *http_post_files=NULL; HashTable *uploaded_files=NULL;
     787                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
     788                 :         int str_len = 0, num_vars = 0, num_vars_max = 2*10, *len_list = NULL;
     789                 :         char **val_list = NULL;
     790                 : #endif
     791                 :         zend_bool magic_quotes_gpc;
     792                 :         multipart_buffer *mbuff;
     793               0 :         zval *array_ptr = (zval *) arg;
     794               0 :         int fd=-1;
     795                 :         zend_llist header;
     796               0 :         void *event_extra_data = NULL;
     797               0 :         int llen = 0;
     798                 : 
     799               0 :         if (SG(request_info).content_length > SG(post_max_size)) {
     800               0 :                 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));
     801               0 :                 return;
     802                 :         }
     803                 : 
     804                 :         /* Get the boundary */
     805               0 :         boundary = strstr(content_type_dup, "boundary");
     806               0 :         if (!boundary || !(boundary=strchr(boundary, '='))) {
     807               0 :                 sapi_module.sapi_error(E_WARNING, "Missing boundary in multipart/form-data POST data");
     808               0 :                 return;
     809                 :         }
     810                 : 
     811               0 :         boundary++;
     812               0 :         boundary_len = strlen(boundary);
     813                 : 
     814               0 :         if (boundary[0] == '"') {
     815               0 :                 boundary++;
     816               0 :                 boundary_end = strchr(boundary, '"');
     817               0 :                 if (!boundary_end) { 
     818               0 :                         sapi_module.sapi_error(E_WARNING, "Invalid boundary in multipart/form-data POST data");
     819               0 :                         return;
     820                 :                 }
     821                 :         } else {
     822                 :                 /* search for the end of the boundary */
     823               0 :                 boundary_end = strchr(boundary, ',');
     824                 :         }
     825               0 :         if (boundary_end) {
     826               0 :                 boundary_end[0] = '\0';
     827               0 :                 boundary_len = boundary_end-boundary;
     828                 :         }
     829                 : 
     830                 :         /* Initialize the buffer */
     831               0 :         if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) {
     832               0 :                 sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer");
     833               0 :                 return;
     834                 :         }
     835                 : 
     836                 :         /* Initialize $_FILES[] */
     837               0 :         zend_hash_init(&PG(rfc1867_protected_variables), 5, NULL, NULL, 0);
     838                 : 
     839               0 :         ALLOC_HASHTABLE(uploaded_files);
     840               0 :         zend_hash_init(uploaded_files, 5, NULL, (dtor_func_t) free_estring, 0);
     841               0 :         SG(rfc1867_uploaded_files) = uploaded_files;
     842                 : 
     843               0 :         ALLOC_ZVAL(http_post_files);
     844               0 :         array_init(http_post_files);
     845               0 :         INIT_PZVAL(http_post_files);
     846               0 :         PG(http_globals)[TRACK_VARS_FILES] = http_post_files;
     847                 : 
     848                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
     849                 :         if (php_mb_encoding_translation(TSRMLS_C)) {
     850                 :                 val_list = (char **)ecalloc(num_vars_max+2, sizeof(char *));
     851                 :                 len_list = (int *)ecalloc(num_vars_max+2, sizeof(int));
     852                 :         }
     853                 : #endif
     854               0 :         zend_llist_init(&header, sizeof(mime_header_entry), (llist_dtor_func_t) php_free_hdr_entry, 0);
     855                 : 
     856               0 :         if (php_rfc1867_callback != NULL) {
     857                 :                 multipart_event_start event_start;
     858                 : 
     859               0 :                 event_start.content_length = SG(request_info).content_length;
     860               0 :                 if (php_rfc1867_callback(MULTIPART_EVENT_START, &event_start, &event_extra_data TSRMLS_CC) == FAILURE) {
     861               0 :                         goto fileupload_done;
     862                 :                 }
     863                 :         }
     864                 : 
     865               0 :         while (!multipart_buffer_eof(mbuff TSRMLS_CC))
     866                 :         {
     867                 :                 char buff[FILLUNIT];
     868               0 :                 char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
     869               0 :                 size_t blen=0, wlen=0;
     870                 :                 off_t offset;
     871                 : 
     872               0 :                 zend_llist_clean(&header);
     873                 : 
     874               0 :                 if (!multipart_buffer_headers(mbuff, &header TSRMLS_CC)) {
     875               0 :                         goto fileupload_done;
     876                 :                 }
     877                 : 
     878               0 :                 if ((cd = php_mime_get_hdr_value(header, "Content-Disposition"))) {
     879               0 :                         char *pair=NULL;
     880               0 :                         int end=0;
     881                 :                         
     882               0 :                         while (isspace(*cd)) {
     883               0 :                                 ++cd;
     884                 :                         }
     885                 : 
     886               0 :                         while (*cd && (pair = php_ap_getword(&cd, ';')))
     887                 :                         {
     888               0 :                                 char *key=NULL, *word = pair;
     889                 : 
     890               0 :                                 while (isspace(*cd)) {
     891               0 :                                         ++cd;
     892                 :                                 }
     893                 : 
     894               0 :                                 if (strchr(pair, '=')) {
     895               0 :                                         key = php_ap_getword(&pair, '=');
     896                 :                                         
     897               0 :                                         if (!strcasecmp(key, "name")) {
     898               0 :                                                 if (param) {
     899               0 :                                                         efree(param);
     900                 :                                                 }
     901               0 :                                                 param = php_ap_getword_conf(&pair TSRMLS_CC);
     902               0 :                                         } else if (!strcasecmp(key, "filename")) {
     903               0 :                                                 if (filename) {
     904               0 :                                                         efree(filename);
     905                 :                                                 }
     906               0 :                                                 filename = php_ap_getword_conf(&pair TSRMLS_CC);
     907                 :                                         }
     908                 :                                 }
     909               0 :                                 if (key) {
     910               0 :                                         efree(key);
     911                 :                                 }
     912               0 :                                 efree(word);
     913                 :                         }
     914                 : 
     915                 :                         /* Normal form variable, safe to read all data into memory */
     916               0 :                         if (!filename && param) {
     917                 :                                 unsigned int value_len;
     918               0 :                                 char *value = multipart_buffer_read_body(mbuff, &value_len TSRMLS_CC);
     919                 :                                 unsigned int new_val_len; /* Dummy variable */
     920                 : 
     921               0 :                                 if (!value) {
     922               0 :                                         value = estrdup("");
     923                 :                                 }
     924                 : 
     925               0 :                                 if (sapi_module.input_filter(PARSE_POST, param, &value, value_len, &new_val_len TSRMLS_CC)) {
     926               0 :                                         if (php_rfc1867_callback != NULL) {
     927                 :                                                 multipart_event_formdata event_formdata;
     928               0 :                                                 size_t newlength = 0;
     929                 : 
     930               0 :                                                 event_formdata.post_bytes_processed = SG(read_post_bytes);
     931               0 :                                                 event_formdata.name = param;
     932               0 :                                                 event_formdata.value = &value;
     933               0 :                                                 event_formdata.length = new_val_len;
     934               0 :                                                 event_formdata.newlength = &newlength;
     935               0 :                                                 if (php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data TSRMLS_CC) == FAILURE) {
     936               0 :                                                         efree(param);
     937               0 :                                                         efree(value);
     938               0 :                                                         continue;
     939                 :                                                 }
     940               0 :                                                 new_val_len = newlength;
     941                 :                                         }
     942                 : 
     943                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
     944                 :                                         if (php_mb_encoding_translation(TSRMLS_C)) {
     945                 :                                                 php_mb_gpc_stack_variable(param, value, &val_list, &len_list, 
     946                 :                                                                                                   &num_vars, &num_vars_max TSRMLS_CC);
     947                 :                                         } else {
     948                 :                                                 safe_php_register_variable(param, value, new_val_len, array_ptr, 0 TSRMLS_CC);
     949                 :                                         }
     950                 : #else
     951               0 :                                         safe_php_register_variable(param, value, new_val_len, array_ptr, 0 TSRMLS_CC);
     952                 : #endif
     953               0 :                                 } else if (php_rfc1867_callback != NULL) {
     954                 :                                         multipart_event_formdata event_formdata;
     955                 : 
     956               0 :                                         event_formdata.post_bytes_processed = SG(read_post_bytes);
     957               0 :                                         event_formdata.name = param;
     958               0 :                                         event_formdata.value = &value;
     959               0 :                                         event_formdata.length = value_len;
     960               0 :                                         event_formdata.newlength = NULL;
     961               0 :                                         php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data TSRMLS_CC);
     962                 :                                 }
     963                 : 
     964               0 :                                 if (!strcasecmp(param, "MAX_FILE_SIZE")) {
     965               0 :                                         max_file_size = atol(value);
     966                 :                                 }
     967                 : 
     968               0 :                                 efree(param);
     969               0 :                                 efree(value);
     970               0 :                                 continue;
     971                 :                         }
     972                 : 
     973                 :                         /* If file_uploads=off, skip the file part */
     974               0 :                         if (!PG(file_uploads)) {
     975               0 :                                 skip_upload = 1;
     976                 :                         }
     977                 : 
     978                 :                         /* Return with an error if the posted data is garbled */
     979               0 :                         if (!param && !filename) {
     980               0 :                                 sapi_module.sapi_error(E_WARNING, "File Upload Mime headers garbled");
     981               0 :                                 goto fileupload_done;
     982                 :                         }
     983                 :                         
     984               0 :                         if (!param) {
     985               0 :                                 is_anonymous = 1;
     986               0 :                                 param = emalloc(MAX_SIZE_ANONNAME);
     987               0 :                                 snprintf(param, MAX_SIZE_ANONNAME, "%u", anonindex++);
     988                 :                         } else {
     989               0 :                                 is_anonymous = 0;
     990                 :                         }
     991                 :                         
     992                 :                         /* New Rule: never repair potential malicious user input */
     993               0 :                         if (!skip_upload) {
     994               0 :                                 char *tmp = param;
     995               0 :                                 long c = 0;
     996                 :                                 
     997               0 :                                 while (*tmp) {
     998               0 :                                         if (*tmp == '[') {
     999               0 :                                                 c++;
    1000               0 :                                         } else if (*tmp == ']') {
    1001               0 :                                                 c--;
    1002               0 :                                                 if (tmp[1] && tmp[1] != '[') {
    1003               0 :                                                         skip_upload = 1;
    1004               0 :                                                         break;
    1005                 :                                                 }
    1006                 :                                         }
    1007               0 :                                         if (c < 0) {
    1008               0 :                                                 skip_upload = 1;
    1009               0 :                                                 break;
    1010                 :                                         }
    1011               0 :                                         tmp++;                          
    1012                 :                                 }
    1013                 :                         }
    1014                 : 
    1015               0 :                         total_bytes = cancel_upload = 0;
    1016                 : 
    1017               0 :                         if (!skip_upload) {
    1018                 :                                 /* Handle file */
    1019               0 :                                 fd = php_open_temporary_fd(PG(upload_tmp_dir), "php", &temp_filename TSRMLS_CC);
    1020               0 :                                 if (fd==-1) {
    1021               0 :                                         sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file");
    1022               0 :                                         cancel_upload = UPLOAD_ERROR_E;
    1023                 :                                 }
    1024                 :                         }
    1025                 :                         
    1026               0 :                         if (!skip_upload && php_rfc1867_callback != NULL) {
    1027                 :                                 multipart_event_file_start event_file_start;
    1028                 : 
    1029               0 :                                 event_file_start.post_bytes_processed = SG(read_post_bytes);
    1030               0 :                                 event_file_start.name = param;
    1031               0 :                                 event_file_start.filename = &filename;
    1032               0 :                                 if (php_rfc1867_callback(MULTIPART_EVENT_FILE_START, &event_file_start, &event_extra_data TSRMLS_CC) == FAILURE) {
    1033               0 :                                         if (temp_filename) {
    1034               0 :                                                 if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
    1035               0 :                                                         close(fd);
    1036               0 :                                                         unlink(temp_filename);
    1037                 :                                                 }
    1038               0 :                                                 efree(temp_filename);
    1039                 :                                         }
    1040               0 :                                         temp_filename="";
    1041               0 :                                         efree(param);
    1042               0 :                                         efree(filename);
    1043               0 :                                         continue;
    1044                 :                                 }
    1045                 :                         }
    1046                 : 
    1047                 :                         
    1048               0 :                         if (skip_upload) {
    1049               0 :                                 efree(param);
    1050               0 :                                 efree(filename);
    1051               0 :                                 continue;
    1052                 :                         }
    1053                 : 
    1054               0 :                         if(strlen(filename) == 0) {
    1055                 : #if DEBUG_FILE_UPLOAD
    1056                 :                                 sapi_module.sapi_error(E_NOTICE, "No file uploaded");
    1057                 : #endif
    1058               0 :                                 cancel_upload = UPLOAD_ERROR_D;
    1059                 :                         }
    1060                 : 
    1061               0 :                         offset = 0;
    1062               0 :                         end = 0;
    1063               0 :                         while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end TSRMLS_CC)))
    1064                 :                         {
    1065               0 :                                 if (php_rfc1867_callback != NULL) {
    1066                 :                                         multipart_event_file_data event_file_data;
    1067                 : 
    1068               0 :                                         event_file_data.post_bytes_processed = SG(read_post_bytes);
    1069               0 :                                         event_file_data.offset = offset;
    1070               0 :                                         event_file_data.data = buff;
    1071               0 :                                         event_file_data.length = blen;
    1072               0 :                                         event_file_data.newlength = &blen;
    1073               0 :                                         if (php_rfc1867_callback(MULTIPART_EVENT_FILE_DATA, &event_file_data, &event_extra_data TSRMLS_CC) == FAILURE) {
    1074               0 :                                                 cancel_upload = UPLOAD_ERROR_X;
    1075               0 :                                                 continue;
    1076                 :                                         }
    1077                 :                                 }
    1078                 :                                 
    1079                 :                         
    1080               0 :                                 if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) {
    1081                 : #if DEBUG_FILE_UPLOAD
    1082                 :                                         sapi_module.sapi_error(E_NOTICE, "upload_max_filesize of %ld bytes exceeded - file [%s=%s] not saved", PG(upload_max_filesize), param, filename);
    1083                 : #endif
    1084               0 :                                         cancel_upload = UPLOAD_ERROR_A;
    1085               0 :                                 } else if (max_file_size && (total_bytes > max_file_size)) {
    1086                 : #if DEBUG_FILE_UPLOAD
    1087                 :                                         sapi_module.sapi_error(E_NOTICE, "MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
    1088                 : #endif
    1089               0 :                                         cancel_upload = UPLOAD_ERROR_B;
    1090               0 :                                 } else if (blen > 0) {
    1091                 :                                 
    1092               0 :                                         wlen = write(fd, buff, blen);
    1093                 :                         
    1094               0 :                                         if (wlen < blen) {
    1095                 : #if DEBUG_FILE_UPLOAD
    1096                 :                                                 sapi_module.sapi_error(E_NOTICE, "Only %d bytes were written, expected to write %d", wlen, blen);
    1097                 : #endif
    1098               0 :                                                 cancel_upload = UPLOAD_ERROR_F;
    1099                 :                                         } else {
    1100               0 :                                                 total_bytes += wlen;
    1101                 :                                         }
    1102                 :                                         
    1103               0 :                                         offset += wlen;
    1104                 :                                 } 
    1105                 :                         }
    1106               0 :                         if (fd!=-1) { /* may not be initialized if file could not be created */
    1107               0 :                                 close(fd);
    1108                 :                         }
    1109               0 :                         if (!cancel_upload && !end) {
    1110                 : #if DEBUG_FILE_UPLOAD
    1111                 :                                 sapi_module.sapi_error(E_NOTICE, "Missing mime boundary at the end of the data for file %s", strlen(filename) > 0 ? filename : "");
    1112                 : #endif
    1113               0 :                                 cancel_upload = UPLOAD_ERROR_C;
    1114                 :                         }
    1115                 : #if DEBUG_FILE_UPLOAD
    1116                 :                         if(strlen(filename) > 0 && total_bytes == 0 && !cancel_upload) {
    1117                 :                                 sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename);
    1118                 :                                 cancel_upload = 5;
    1119                 :                         }
    1120                 : #endif          
    1121                 : 
    1122               0 :                         if (php_rfc1867_callback != NULL) {
    1123                 :                                 multipart_event_file_end event_file_end;
    1124                 : 
    1125               0 :                                 event_file_end.post_bytes_processed = SG(read_post_bytes);
    1126               0 :                                 event_file_end.temp_filename = temp_filename;
    1127               0 :                                 event_file_end.cancel_upload = cancel_upload;
    1128               0 :                                 if (php_rfc1867_callback(MULTIPART_EVENT_FILE_END, &event_file_end, &event_extra_data TSRMLS_CC) == FAILURE) {
    1129               0 :                                         cancel_upload = UPLOAD_ERROR_X;
    1130                 :                                 }
    1131                 :                         }
    1132                 : 
    1133               0 :                         if (cancel_upload) {
    1134               0 :                                 if (temp_filename) {
    1135               0 :                                         if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
    1136               0 :                                                 unlink(temp_filename);
    1137                 :                                         }
    1138               0 :                                         efree(temp_filename);
    1139                 :                                 }
    1140               0 :                                 temp_filename="";
    1141                 :                         } else {
    1142               0 :                                 zend_hash_add(SG(rfc1867_uploaded_files), temp_filename, strlen(temp_filename) + 1, &temp_filename, sizeof(char *), NULL);
    1143                 :                         }
    1144                 : 
    1145                 :                         /* is_arr_upload is true when name of file upload field
    1146                 :                          * ends in [.*]
    1147                 :                          * start_arr is set to point to 1st [
    1148                 :                          */
    1149               0 :                         is_arr_upload = (start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']');
    1150                 : 
    1151               0 :                         if (is_arr_upload) {
    1152               0 :                                 array_len = strlen(start_arr);
    1153               0 :                                 if (array_index) {
    1154               0 :                                         efree(array_index);
    1155                 :                                 }
    1156               0 :                                 array_index = estrndup(start_arr+1, array_len-2);   
    1157                 :                         }
    1158                 :                         
    1159                 :                         /* Add $foo_name */
    1160               0 :                         if (llen < strlen(param) + MAX_SIZE_OF_INDEX + 1) {
    1161               0 :                                 llen = strlen(param);
    1162               0 :                                 lbuf = (char *) safe_erealloc(lbuf, llen, 1, MAX_SIZE_OF_INDEX + 1);
    1163               0 :                                 llen += MAX_SIZE_OF_INDEX + 1;
    1164                 :                         }
    1165                 :                         
    1166               0 :                         if (is_arr_upload) {
    1167               0 :                                 if (abuf) efree(abuf);
    1168               0 :                                 abuf = estrndup(param, strlen(param)-array_len);
    1169               0 :                                 snprintf(lbuf, llen, "%s_name[%s]", abuf, array_index);
    1170                 :                         } else {
    1171               0 :                                 snprintf(lbuf, llen, "%s_name", param);
    1172                 :                         }
    1173                 : 
    1174                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
    1175                 :                         if (php_mb_encoding_translation(TSRMLS_C)) {
    1176                 :                                 if (num_vars>=num_vars_max){ 
    1177                 :                                         php_mb_gpc_realloc_buffer(&val_list, &len_list, &num_vars_max, 
    1178                 :                                                                                           1 TSRMLS_CC);
    1179                 :                                 }
    1180                 :                                 val_list[num_vars] = filename;
    1181                 :                                 len_list[num_vars] = strlen(filename);
    1182                 :                                 num_vars++;
    1183                 :                                 if(php_mb_gpc_encoding_detector(val_list, len_list, num_vars, NULL TSRMLS_CC) == SUCCESS) {
    1184                 :                                         str_len = strlen(filename);
    1185                 :                                         php_mb_gpc_encoding_converter(&filename, &str_len, 1, NULL, NULL TSRMLS_CC);
    1186                 :                                 }
    1187                 :                                 s = php_mb_strrchr(filename, '\\' TSRMLS_CC);
    1188                 :                                 if ((tmp = php_mb_strrchr(filename, '/' TSRMLS_CC)) > s) {
    1189                 :                                         s = tmp;
    1190                 :                                 }
    1191                 :                                 num_vars--;
    1192                 :                                 goto filedone;
    1193                 :                         }
    1194                 : #endif                  
    1195                 :                         /* The \ check should technically be needed for win32 systems only where
    1196                 :                          * it is a valid path separator. However, IE in all it's wisdom always sends
    1197                 :                          * the full path of the file on the user's filesystem, which means that unless
    1198                 :                          * the user does basename() they get a bogus file name. Until IE's user base drops 
    1199                 :                          * to nill or problem is fixed this code must remain enabled for all systems.
    1200                 :                          */
    1201               0 :                         s = strrchr(filename, '\\');
    1202               0 :                         if ((tmp = strrchr(filename, '/')) > s) {
    1203               0 :                                 s = tmp;
    1204                 :                         }
    1205                 : #ifdef PHP_WIN32
    1206                 :                         if (PG(magic_quotes_gpc)) {
    1207                 :                                 s = s ? s : filename;
    1208                 :                                 tmp = strrchr(s, '\'');
    1209                 :                                 s = tmp > s ? tmp : s;
    1210                 :                                 tmp = strrchr(s, '"');
    1211                 :                                 s = tmp > s ? tmp : s;
    1212                 :                         }
    1213                 : #endif
    1214                 : 
    1215                 : #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
    1216                 : filedone:                       
    1217                 : #endif
    1218                 :                         
    1219               0 :                         if (!is_anonymous) {
    1220               0 :                                 if (s && s > filename) {
    1221               0 :                                         safe_php_register_variable(lbuf, s+1, strlen(s+1), NULL, 0 TSRMLS_CC);
    1222                 :                                 } else {
    1223               0 :                                         safe_php_register_variable(lbuf, filename, strlen(filename), NULL, 0 TSRMLS_CC);
    1224                 :                                 }
    1225                 :                         }
    1226                 : 
    1227                 :                         /* Add $foo[name] */
    1228               0 :                         if (is_arr_upload) {
    1229               0 :                                 snprintf(lbuf, llen, "%s[name][%s]", abuf, array_index);
    1230                 :                         } else {
    1231               0 :                                 snprintf(lbuf, llen, "%s[name]", param);
    1232                 :                         }
    1233               0 :                         if (s && s > filename) {
    1234               0 :                                 register_http_post_files_variable(lbuf, s+1, http_post_files, 0 TSRMLS_CC);
    1235                 :                         } else {
    1236               0 :                                 register_http_post_files_variable(lbuf, filename, http_post_files, 0 TSRMLS_CC);
    1237                 :                         }
    1238               0 :                         efree(filename);
    1239               0 :                         s = NULL;
    1240                 :         
    1241                 :                         /* Possible Content-Type: */
    1242               0 :                         if (cancel_upload || !(cd = php_mime_get_hdr_value(header, "Content-Type"))) {
    1243               0 :                                 cd = "";
    1244                 :                         } else { 
    1245                 :                                 /* fix for Opera 6.01 */
    1246               0 :                                 s = strchr(cd, ';');
    1247               0 :                                 if (s != NULL) {
    1248               0 :                                         *s = '\0';
    1249                 :                                 }
    1250                 :                         }
    1251                 : 
    1252                 :                         /* Add $foo_type */
    1253               0 :                         if (is_arr_upload) {
    1254               0 :                                 snprintf(lbuf, llen, "%s_type[%s]", abuf, array_index);
    1255                 :                         } else {
    1256               0 :                                 snprintf(lbuf, llen, "%s_type", param);
    1257                 :                         }
    1258               0 :                         if (!is_anonymous) {
    1259               0 :                                 safe_php_register_variable(lbuf, cd, strlen(cd), NULL, 0 TSRMLS_CC);
    1260                 :                         }
    1261                 : 
    1262                 :                         /* Add $foo[type] */
    1263               0 :                         if (is_arr_upload) {
    1264               0 :                                 snprintf(lbuf, llen, "%s[type][%s]", abuf, array_index);
    1265                 :                         } else {
    1266               0 :                                 snprintf(lbuf, llen, "%s[type]", param);
    1267                 :                         }
    1268               0 :                         register_http_post_files_variable(lbuf, cd, http_post_files, 0 TSRMLS_CC);
    1269                 : 
    1270                 :                         /* Restore Content-Type Header */
    1271               0 :                         if (s != NULL) {
    1272               0 :                                 *s = ';';
    1273                 :                         }
    1274               0 :                         s = "";
    1275                 : 
    1276                 :                         /* Initialize variables */
    1277               0 :                         add_protected_variable(param TSRMLS_CC);
    1278                 : 
    1279               0 :                         magic_quotes_gpc = PG(magic_quotes_gpc);
    1280               0 :                         PG(magic_quotes_gpc) = 0;
    1281                 :                         /* if param is of form xxx[.*] this will cut it to xxx */
    1282               0 :                         if (!is_anonymous) {
    1283               0 :                                 safe_php_register_variable(param, temp_filename, strlen(temp_filename), NULL, 1 TSRMLS_CC);
    1284                 :                         }
    1285                 :         
    1286                 :                         /* Add $foo[tmp_name] */
    1287               0 :                         if (is_arr_upload) {
    1288               0 :                                 snprintf(lbuf, llen, "%s[tmp_name][%s]", abuf, array_index);
    1289                 :                         } else {
    1290               0 :                                 snprintf(lbuf, llen, "%s[tmp_name]", param);
    1291                 :                         }
    1292               0 :                         add_protected_variable(lbuf TSRMLS_CC);
    1293               0 :                         register_http_post_files_variable(lbuf, temp_filename, http_post_files, 1 TSRMLS_CC);
    1294                 : 
    1295               0 :                         PG(magic_quotes_gpc) = magic_quotes_gpc;
    1296                 : 
    1297                 :                         {
    1298                 :                                 zval file_size, error_type;
    1299                 : 
    1300               0 :                                 error_type.value.lval = cancel_upload;
    1301               0 :                                 error_type.type = IS_LONG;
    1302                 : 
    1303                 :                                 /* Add $foo[error] */
    1304               0 :                                 if (cancel_upload) {
    1305               0 :                                         file_size.value.lval = 0;
    1306               0 :                                         file_size.type = IS_LONG;
    1307                 :                                 } else {
    1308               0 :                                         file_size.value.lval = total_bytes;
    1309               0 :                                         file_size.type = IS_LONG;
    1310                 :                                 }       
    1311                 :         
    1312               0 :                                 if (is_arr_upload) {
    1313               0 :                                         snprintf(lbuf, llen, "%s[error][%s]", abuf, array_index);
    1314                 :                                 } else {
    1315               0 :                                         snprintf(lbuf, llen, "%s[error]", param);
    1316                 :                                 }
    1317               0 :                                 register_http_post_files_variable_ex(lbuf, &error_type, http_post_files, 0 TSRMLS_CC);
    1318                 : 
    1319                 :                                 /* Add $foo_size */
    1320               0 :                                 if (is_arr_upload) {
    1321               0 :                                         snprintf(lbuf, llen, "%s_size[%s]", abuf, array_index);
    1322                 :                                 } else {
    1323               0 :                                         snprintf(lbuf, llen, "%s_size", param);
    1324                 :                                 }
    1325               0 :                                 if (!is_anonymous) {
    1326               0 :                                         safe_php_register_variable_ex(lbuf, &file_size, NULL, 0 TSRMLS_CC);
    1327                 :                                 }       
    1328                 : 
    1329                 :                                 /* Add $foo[size] */
    1330               0 :                                 if (is_arr_upload) {
    1331               0 :                                         snprintf(lbuf, llen, "%s[size][%s]", abuf, array_index);
    1332                 :                                 } else {
    1333               0 :                                         snprintf(lbuf, llen, "%s[size]", param);
    1334                 :                                 }
    1335               0 :                                 register_http_post_files_variable_ex(lbuf, &file_size, http_post_files, 0 TSRMLS_CC);
    1336                 :                         }
    1337               0 :                         efree(param);
    1338                 :                 }
    1339                 :         }
    1340               0 : fileupload_done:
    1341               0 :         if (php_rfc1867_callback != NULL) {
    1342                 :                 multipart_event_end event_end;
    1343                 :                 
    1344               0 :                 event_end.post_bytes_processed = SG(read_post_bytes);
    1345               0 :                 php_rfc1867_callback(MULTIPART_EVENT_END, &event_end, &event_extra_data TSRMLS_CC);
    1346                 :         }
    1347                 :         
    1348               0 :         SAFE_RETURN;
    1349                 : }
    1350                 : 
    1351                 : /*
    1352                 :  * Local variables:
    1353                 :  * tab-width: 4
    1354                 :  * c-basic-offset: 4
    1355                 :  * End:
    1356                 :  * vim600: sw=4 ts=4 fdm=marker
    1357                 :  * vim<600: sw=4 ts=4
    1358                 :  */

Generated by: LTP GCOV extension version 1.5