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: 0 601 0.0 %
Date: 2014-04-16 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 16 Apr 2014 12:48:03 +0000 (43 hours ago)

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