/main/rfc1867.c

http://github.com/php/php-src · C · 1332 lines · 998 code · 191 blank · 143 comment · 291 complexity · 7aae7973e48189a6037ba53f71c83baf MD5 · raw file

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