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

Generated by: LCOV version 1.10

Generated at Mon, 04 Aug 2014 15:49:19 +0000 (18 days ago)

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