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

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:21 +0000 (8 days ago)

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