PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - main - rfc1867.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 477 624 76.4 %
Date: 2014-07-13 Functions: 27 29 93.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 13 Jul 2014 23:58:03 +0000 (9 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.