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-10-30 Functions: 29 30 96.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 30 Oct 2014 07:41:46 +0000 (42 hours ago)

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