PageRenderTime 59ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/main/SAPI.c

http://github.com/php/php-src
C | 1152 lines | 911 code | 155 blank | 86 comment | 239 complexity | 22dc93cf7e6a1094bd081d8932ffd5a1 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  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. | Original design: Shane Caraveo <shane@caraveo.com> |
  14. | Authors: Andi Gutmans <andi@php.net> |
  15. | Zeev Suraski <zeev@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include <ctype.h>
  19. #include <sys/stat.h>
  20. #include "php.h"
  21. #include "SAPI.h"
  22. #include "php_variables.h"
  23. #include "php_ini.h"
  24. #include "ext/standard/php_string.h"
  25. #include "ext/standard/pageinfo.h"
  26. #include "ext/pcre/php_pcre.h"
  27. #ifdef ZTS
  28. #include "TSRM.h"
  29. #endif
  30. #ifdef HAVE_SYS_TIME_H
  31. #include <sys/time.h>
  32. #elif defined(PHP_WIN32)
  33. #include "win32/time.h"
  34. #endif
  35. #include "rfc1867.h"
  36. #include "php_content_types.h"
  37. #ifdef ZTS
  38. SAPI_API int sapi_globals_id;
  39. SAPI_API size_t sapi_globals_offset;
  40. #else
  41. sapi_globals_struct sapi_globals;
  42. #endif
  43. static void _type_dtor(zval *zv)
  44. {
  45. free(Z_PTR_P(zv));
  46. }
  47. static void sapi_globals_ctor(sapi_globals_struct *sapi_globals)
  48. {
  49. memset(sapi_globals, 0, sizeof(*sapi_globals));
  50. zend_hash_init_ex(&sapi_globals->known_post_content_types, 8, NULL, _type_dtor, 1, 0);
  51. php_setup_sapi_content_types();
  52. }
  53. static void sapi_globals_dtor(sapi_globals_struct *sapi_globals)
  54. {
  55. zend_hash_destroy(&sapi_globals->known_post_content_types);
  56. }
  57. /* True globals (no need for thread safety) */
  58. SAPI_API sapi_module_struct sapi_module;
  59. SAPI_API void sapi_startup(sapi_module_struct *sf)
  60. {
  61. sf->ini_entries = NULL;
  62. sapi_module = *sf;
  63. #ifdef ZTS
  64. ts_allocate_fast_id(&sapi_globals_id, &sapi_globals_offset, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor);
  65. # ifdef PHP_WIN32
  66. _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
  67. # endif
  68. #else
  69. sapi_globals_ctor(&sapi_globals);
  70. #endif
  71. #ifdef PHP_WIN32
  72. tsrm_win32_startup();
  73. #endif
  74. reentrancy_startup();
  75. }
  76. SAPI_API void sapi_shutdown(void)
  77. {
  78. #ifdef ZTS
  79. ts_free_id(sapi_globals_id);
  80. #else
  81. sapi_globals_dtor(&sapi_globals);
  82. #endif
  83. reentrancy_shutdown();
  84. #ifdef PHP_WIN32
  85. tsrm_win32_shutdown();
  86. #endif
  87. }
  88. SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
  89. {
  90. efree(sapi_header->header);
  91. }
  92. /* {{{ proto bool header_register_callback(mixed callback)
  93. call a header function */
  94. PHP_FUNCTION(header_register_callback)
  95. {
  96. zval *callback_func;
  97. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &callback_func) == FAILURE) {
  98. RETURN_THROWS();
  99. }
  100. if (!zend_is_callable(callback_func, 0, NULL)) {
  101. RETURN_FALSE;
  102. }
  103. if (Z_TYPE(SG(callback_func)) != IS_UNDEF) {
  104. zval_ptr_dtor(&SG(callback_func));
  105. SG(fci_cache) = empty_fcall_info_cache;
  106. }
  107. ZVAL_COPY(&SG(callback_func), callback_func);
  108. RETURN_TRUE;
  109. }
  110. /* }}} */
  111. static void sapi_run_header_callback(zval *callback)
  112. {
  113. int error;
  114. zend_fcall_info fci;
  115. char *callback_error = NULL;
  116. zval retval;
  117. if (zend_fcall_info_init(callback, 0, &fci, &SG(fci_cache), NULL, &callback_error) == SUCCESS) {
  118. fci.retval = &retval;
  119. error = zend_call_function(&fci, &SG(fci_cache));
  120. if (error == FAILURE) {
  121. goto callback_failed;
  122. } else {
  123. zval_ptr_dtor(&retval);
  124. }
  125. } else {
  126. callback_failed:
  127. php_error_docref(NULL, E_WARNING, "Could not call the sapi_header_callback");
  128. }
  129. if (callback_error) {
  130. efree(callback_error);
  131. }
  132. }
  133. SAPI_API void sapi_handle_post(void *arg)
  134. {
  135. if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
  136. SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg);
  137. efree(SG(request_info).content_type_dup);
  138. SG(request_info).content_type_dup = NULL;
  139. }
  140. }
  141. static void sapi_read_post_data(void)
  142. {
  143. sapi_post_entry *post_entry;
  144. uint32_t content_type_length = (uint32_t)strlen(SG(request_info).content_type);
  145. char *content_type = estrndup(SG(request_info).content_type, content_type_length);
  146. char *p;
  147. char oldchar=0;
  148. void (*post_reader_func)(void) = NULL;
  149. /* dedicated implementation for increased performance:
  150. * - Make the content type lowercase
  151. * - Trim descriptive data, stay with the content-type only
  152. */
  153. for (p=content_type; p<content_type+content_type_length; p++) {
  154. switch (*p) {
  155. case ';':
  156. case ',':
  157. case ' ':
  158. content_type_length = p-content_type;
  159. oldchar = *p;
  160. *p = 0;
  161. break;
  162. default:
  163. *p = tolower(*p);
  164. break;
  165. }
  166. }
  167. /* now try to find an appropriate POST content handler */
  168. if ((post_entry = zend_hash_str_find_ptr(&SG(known_post_content_types), content_type,
  169. content_type_length)) != NULL) {
  170. /* found one, register it for use */
  171. SG(request_info).post_entry = post_entry;
  172. post_reader_func = post_entry->post_reader;
  173. } else {
  174. /* fallback */
  175. SG(request_info).post_entry = NULL;
  176. if (!sapi_module.default_post_reader) {
  177. /* no default reader ? */
  178. SG(request_info).content_type_dup = NULL;
  179. sapi_module.sapi_error(E_WARNING, "Unsupported content type: '%s'", content_type);
  180. return;
  181. }
  182. }
  183. if (oldchar) {
  184. *(p-1) = oldchar;
  185. }
  186. SG(request_info).content_type_dup = content_type;
  187. if(post_reader_func) {
  188. post_reader_func();
  189. }
  190. if(sapi_module.default_post_reader) {
  191. sapi_module.default_post_reader();
  192. }
  193. }
  194. SAPI_API size_t sapi_read_post_block(char *buffer, size_t buflen)
  195. {
  196. size_t read_bytes;
  197. if (!sapi_module.read_post) {
  198. return 0;
  199. }
  200. read_bytes = sapi_module.read_post(buffer, buflen);
  201. if (read_bytes > 0) {
  202. /* gogo */
  203. SG(read_post_bytes) += read_bytes;
  204. }
  205. if (read_bytes < buflen) {
  206. /* done */
  207. SG(post_read) = 1;
  208. }
  209. return read_bytes;
  210. }
  211. SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
  212. {
  213. if ((SG(post_max_size) > 0) && (SG(request_info).content_length > SG(post_max_size))) {
  214. php_error_docref(NULL, E_WARNING, "POST Content-Length of " ZEND_LONG_FMT " bytes exceeds the limit of " ZEND_LONG_FMT " bytes",
  215. SG(request_info).content_length, SG(post_max_size));
  216. return;
  217. }
  218. SG(request_info).request_body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir));
  219. if (sapi_module.read_post) {
  220. size_t read_bytes;
  221. for (;;) {
  222. char buffer[SAPI_POST_BLOCK_SIZE];
  223. read_bytes = sapi_read_post_block(buffer, SAPI_POST_BLOCK_SIZE);
  224. if (read_bytes > 0) {
  225. if (php_stream_write(SG(request_info).request_body, buffer, read_bytes) != read_bytes) {
  226. /* if parts of the stream can't be written, purge it completely */
  227. php_stream_truncate_set_size(SG(request_info).request_body, 0);
  228. php_error_docref(NULL, E_WARNING, "POST data can't be buffered; all data discarded");
  229. break;
  230. }
  231. }
  232. if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
  233. php_error_docref(NULL, E_WARNING, "Actual POST length does not match Content-Length, and exceeds " ZEND_LONG_FMT " bytes", SG(post_max_size));
  234. break;
  235. }
  236. if (read_bytes < SAPI_POST_BLOCK_SIZE) {
  237. /* done */
  238. break;
  239. }
  240. }
  241. php_stream_rewind(SG(request_info).request_body);
  242. }
  243. }
  244. static inline char *get_default_content_type(uint32_t prefix_len, uint32_t *len)
  245. {
  246. char *mimetype, *charset, *content_type;
  247. uint32_t mimetype_len, charset_len;
  248. if (SG(default_mimetype)) {
  249. mimetype = SG(default_mimetype);
  250. mimetype_len = (uint32_t)strlen(SG(default_mimetype));
  251. } else {
  252. mimetype = SAPI_DEFAULT_MIMETYPE;
  253. mimetype_len = sizeof(SAPI_DEFAULT_MIMETYPE) - 1;
  254. }
  255. if (SG(default_charset)) {
  256. charset = SG(default_charset);
  257. charset_len = (uint32_t)strlen(SG(default_charset));
  258. } else {
  259. charset = SAPI_DEFAULT_CHARSET;
  260. charset_len = sizeof(SAPI_DEFAULT_CHARSET) - 1;
  261. }
  262. if (*charset && strncasecmp(mimetype, "text/", 5) == 0) {
  263. char *p;
  264. *len = prefix_len + mimetype_len + sizeof("; charset=") - 1 + charset_len;
  265. content_type = (char*)emalloc(*len + 1);
  266. p = content_type + prefix_len;
  267. memcpy(p, mimetype, mimetype_len);
  268. p += mimetype_len;
  269. memcpy(p, "; charset=", sizeof("; charset=") - 1);
  270. p += sizeof("; charset=") - 1;
  271. memcpy(p, charset, charset_len + 1);
  272. } else {
  273. *len = prefix_len + mimetype_len;
  274. content_type = (char*)emalloc(*len + 1);
  275. memcpy(content_type + prefix_len, mimetype, mimetype_len + 1);
  276. }
  277. return content_type;
  278. }
  279. SAPI_API char *sapi_get_default_content_type(void)
  280. {
  281. uint32_t len;
  282. return get_default_content_type(0, &len);
  283. }
  284. SAPI_API void sapi_get_default_content_type_header(sapi_header_struct *default_header)
  285. {
  286. uint32_t len;
  287. default_header->header = get_default_content_type(sizeof("Content-type: ")-1, &len);
  288. default_header->header_len = len;
  289. memcpy(default_header->header, "Content-type: ", sizeof("Content-type: ") - 1);
  290. }
  291. /*
  292. * Add charset on content-type header if the MIME type starts with
  293. * "text/", the default_charset directive is not empty and
  294. * there is not already a charset option in there.
  295. *
  296. * If "mimetype" is non-NULL, it should point to a pointer allocated
  297. * with emalloc(). If a charset is added, the string will be
  298. * re-allocated and the new length is returned. If mimetype is
  299. * unchanged, 0 is returned.
  300. *
  301. */
  302. SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len)
  303. {
  304. char *charset, *newtype;
  305. size_t newlen;
  306. charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
  307. if (*mimetype != NULL) {
  308. if (*charset && strncmp(*mimetype, "text/", 5) == 0 && strstr(*mimetype, "charset=") == NULL) {
  309. newlen = len + (sizeof(";charset=")-1) + strlen(charset);
  310. newtype = emalloc(newlen + 1);
  311. PHP_STRLCPY(newtype, *mimetype, newlen + 1, len);
  312. strlcat(newtype, ";charset=", newlen + 1);
  313. strlcat(newtype, charset, newlen + 1);
  314. efree(*mimetype);
  315. *mimetype = newtype;
  316. return newlen;
  317. }
  318. }
  319. return 0;
  320. }
  321. SAPI_API void sapi_activate_headers_only(void)
  322. {
  323. if (SG(request_info).headers_read == 1)
  324. return;
  325. SG(request_info).headers_read = 1;
  326. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct),
  327. (void (*)(void *)) sapi_free_header, 0);
  328. SG(sapi_headers).send_default_content_type = 1;
  329. /* SG(sapi_headers).http_response_code = 200; */
  330. SG(sapi_headers).http_status_line = NULL;
  331. SG(sapi_headers).mimetype = NULL;
  332. SG(read_post_bytes) = 0;
  333. SG(request_info).request_body = NULL;
  334. SG(request_info).current_user = NULL;
  335. SG(request_info).current_user_length = 0;
  336. SG(request_info).no_headers = 0;
  337. SG(request_info).post_entry = NULL;
  338. SG(global_request_time) = 0;
  339. /*
  340. * It's possible to override this general case in the activate() callback,
  341. * if necessary.
  342. */
  343. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  344. SG(request_info).headers_only = 1;
  345. } else {
  346. SG(request_info).headers_only = 0;
  347. }
  348. if (SG(server_context)) {
  349. SG(request_info).cookie_data = sapi_module.read_cookies();
  350. if (sapi_module.activate) {
  351. sapi_module.activate();
  352. }
  353. }
  354. if (sapi_module.input_filter_init ) {
  355. sapi_module.input_filter_init();
  356. }
  357. }
  358. /*
  359. * Called from php_request_startup() for every request.
  360. */
  361. SAPI_API void sapi_activate(void)
  362. {
  363. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
  364. SG(sapi_headers).send_default_content_type = 1;
  365. /*
  366. SG(sapi_headers).http_response_code = 200;
  367. */
  368. SG(sapi_headers).http_status_line = NULL;
  369. SG(sapi_headers).mimetype = NULL;
  370. SG(headers_sent) = 0;
  371. ZVAL_UNDEF(&SG(callback_func));
  372. SG(read_post_bytes) = 0;
  373. SG(request_info).request_body = NULL;
  374. SG(request_info).current_user = NULL;
  375. SG(request_info).current_user_length = 0;
  376. SG(request_info).no_headers = 0;
  377. SG(request_info).post_entry = NULL;
  378. SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
  379. SG(global_request_time) = 0;
  380. SG(post_read) = 0;
  381. /* It's possible to override this general case in the activate() callback, if necessary. */
  382. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  383. SG(request_info).headers_only = 1;
  384. } else {
  385. SG(request_info).headers_only = 0;
  386. }
  387. SG(rfc1867_uploaded_files) = NULL;
  388. /* Handle request method */
  389. if (SG(server_context)) {
  390. if (PG(enable_post_data_reading)
  391. && SG(request_info).content_type
  392. && SG(request_info).request_method
  393. && !strcmp(SG(request_info).request_method, "POST")) {
  394. /* HTTP POST may contain form data to be processed into variables
  395. * depending on given content type */
  396. sapi_read_post_data();
  397. } else {
  398. SG(request_info).content_type_dup = NULL;
  399. }
  400. /* Cookies */
  401. SG(request_info).cookie_data = sapi_module.read_cookies();
  402. }
  403. if (sapi_module.activate) {
  404. sapi_module.activate();
  405. }
  406. if (sapi_module.input_filter_init) {
  407. sapi_module.input_filter_init();
  408. }
  409. }
  410. static void sapi_send_headers_free(void)
  411. {
  412. if (SG(sapi_headers).http_status_line) {
  413. efree(SG(sapi_headers).http_status_line);
  414. SG(sapi_headers).http_status_line = NULL;
  415. }
  416. }
  417. SAPI_API void sapi_deactivate(void)
  418. {
  419. zend_llist_destroy(&SG(sapi_headers).headers);
  420. if (SG(request_info).request_body) {
  421. SG(request_info).request_body = NULL;
  422. } else if (SG(server_context)) {
  423. if (!SG(post_read)) {
  424. /* make sure we've consumed all request input data */
  425. char dummy[SAPI_POST_BLOCK_SIZE];
  426. size_t read_bytes;
  427. do {
  428. read_bytes = sapi_read_post_block(dummy, SAPI_POST_BLOCK_SIZE);
  429. } while (SAPI_POST_BLOCK_SIZE == read_bytes);
  430. }
  431. }
  432. if (SG(request_info).auth_user) {
  433. efree(SG(request_info).auth_user);
  434. }
  435. if (SG(request_info).auth_password) {
  436. efree(SG(request_info).auth_password);
  437. }
  438. if (SG(request_info).auth_digest) {
  439. efree(SG(request_info).auth_digest);
  440. }
  441. if (SG(request_info).content_type_dup) {
  442. efree(SG(request_info).content_type_dup);
  443. }
  444. if (SG(request_info).current_user) {
  445. efree(SG(request_info).current_user);
  446. }
  447. if (sapi_module.deactivate) {
  448. sapi_module.deactivate();
  449. }
  450. if (SG(rfc1867_uploaded_files)) {
  451. destroy_uploaded_files_hash();
  452. }
  453. if (SG(sapi_headers).mimetype) {
  454. efree(SG(sapi_headers).mimetype);
  455. SG(sapi_headers).mimetype = NULL;
  456. }
  457. sapi_send_headers_free();
  458. SG(sapi_started) = 0;
  459. SG(headers_sent) = 0;
  460. SG(request_info).headers_read = 0;
  461. SG(global_request_time) = 0;
  462. }
  463. SAPI_API void sapi_initialize_empty_request(void)
  464. {
  465. SG(server_context) = NULL;
  466. SG(request_info).request_method = NULL;
  467. SG(request_info).auth_digest = SG(request_info).auth_user = SG(request_info).auth_password = NULL;
  468. SG(request_info).content_type_dup = NULL;
  469. }
  470. static int sapi_extract_response_code(const char *header_line)
  471. {
  472. int code = 200;
  473. const char *ptr;
  474. for (ptr = header_line; *ptr; ptr++) {
  475. if (*ptr == ' ' && *(ptr + 1) != ' ') {
  476. code = atoi(ptr + 1);
  477. break;
  478. }
  479. }
  480. return code;
  481. }
  482. static void sapi_update_response_code(int ncode)
  483. {
  484. /* if the status code did not change, we do not want
  485. to change the status line, and no need to change the code */
  486. if (SG(sapi_headers).http_response_code == ncode) {
  487. return;
  488. }
  489. if (SG(sapi_headers).http_status_line) {
  490. efree(SG(sapi_headers).http_status_line);
  491. SG(sapi_headers).http_status_line = NULL;
  492. }
  493. SG(sapi_headers).http_response_code = ncode;
  494. }
  495. /*
  496. * since zend_llist_del_element only remove one matched item once,
  497. * we should remove them by ourself
  498. */
  499. static void sapi_remove_header(zend_llist *l, char *name, size_t len) {
  500. sapi_header_struct *header;
  501. zend_llist_element *next;
  502. zend_llist_element *current=l->head;
  503. while (current) {
  504. header = (sapi_header_struct *)(current->data);
  505. next = current->next;
  506. if (header->header_len > len && header->header[len] == ':'
  507. && !strncasecmp(header->header, name, len)) {
  508. if (current->prev) {
  509. current->prev->next = next;
  510. } else {
  511. l->head = next;
  512. }
  513. if (next) {
  514. next->prev = current->prev;
  515. } else {
  516. l->tail = current->prev;
  517. }
  518. sapi_free_header(header);
  519. efree(current);
  520. --l->count;
  521. }
  522. current = next;
  523. }
  524. }
  525. SAPI_API int sapi_add_header_ex(char *header_line, size_t header_line_len, zend_bool duplicate, zend_bool replace)
  526. {
  527. sapi_header_line ctr = {0};
  528. int r;
  529. ctr.line = header_line;
  530. ctr.line_len = header_line_len;
  531. r = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD,
  532. &ctr);
  533. if (!duplicate)
  534. efree(header_line);
  535. return r;
  536. }
  537. static void sapi_header_add_op(sapi_header_op_enum op, sapi_header_struct *sapi_header)
  538. {
  539. if (!sapi_module.header_handler ||
  540. (SAPI_HEADER_ADD & sapi_module.header_handler(sapi_header, op, &SG(sapi_headers)))) {
  541. if (op == SAPI_HEADER_REPLACE) {
  542. char *colon_offset = strchr(sapi_header->header, ':');
  543. if (colon_offset) {
  544. char sav = *colon_offset;
  545. *colon_offset = 0;
  546. sapi_remove_header(&SG(sapi_headers).headers, sapi_header->header, strlen(sapi_header->header));
  547. *colon_offset = sav;
  548. }
  549. }
  550. zend_llist_add_element(&SG(sapi_headers).headers, (void *) sapi_header);
  551. } else {
  552. sapi_free_header(sapi_header);
  553. }
  554. }
  555. SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg)
  556. {
  557. sapi_header_struct sapi_header;
  558. char *colon_offset;
  559. char *header_line;
  560. size_t header_line_len;
  561. int http_response_code;
  562. if (SG(headers_sent) && !SG(request_info).no_headers) {
  563. const char *output_start_filename = php_output_get_start_filename();
  564. int output_start_lineno = php_output_get_start_lineno();
  565. if (output_start_filename) {
  566. sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)",
  567. output_start_filename, output_start_lineno);
  568. } else {
  569. sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent");
  570. }
  571. return FAILURE;
  572. }
  573. switch (op) {
  574. case SAPI_HEADER_SET_STATUS:
  575. sapi_update_response_code((int)(zend_intptr_t) arg);
  576. return SUCCESS;
  577. case SAPI_HEADER_ADD:
  578. case SAPI_HEADER_REPLACE:
  579. case SAPI_HEADER_DELETE: {
  580. sapi_header_line *p = arg;
  581. if (!p->line || !p->line_len) {
  582. return FAILURE;
  583. }
  584. header_line = p->line;
  585. header_line_len = p->line_len;
  586. http_response_code = p->response_code;
  587. break;
  588. }
  589. case SAPI_HEADER_DELETE_ALL:
  590. if (sapi_module.header_handler) {
  591. sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers));
  592. }
  593. zend_llist_clean(&SG(sapi_headers).headers);
  594. return SUCCESS;
  595. default:
  596. return FAILURE;
  597. }
  598. header_line = estrndup(header_line, header_line_len);
  599. /* cut off trailing spaces, linefeeds and carriage-returns */
  600. if (header_line_len && isspace(header_line[header_line_len-1])) {
  601. do {
  602. header_line_len--;
  603. } while(header_line_len && isspace(header_line[header_line_len-1]));
  604. header_line[header_line_len]='\0';
  605. }
  606. if (op == SAPI_HEADER_DELETE) {
  607. if (strchr(header_line, ':')) {
  608. efree(header_line);
  609. sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon.");
  610. return FAILURE;
  611. }
  612. if (sapi_module.header_handler) {
  613. sapi_header.header = header_line;
  614. sapi_header.header_len = header_line_len;
  615. sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers));
  616. }
  617. sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len);
  618. efree(header_line);
  619. return SUCCESS;
  620. } else {
  621. /* new line/NUL character safety check */
  622. uint32_t i;
  623. for (i = 0; i < header_line_len; i++) {
  624. /* RFC 7230 ch. 3.2.4 deprecates folding support */
  625. if (header_line[i] == '\n' || header_line[i] == '\r') {
  626. efree(header_line);
  627. sapi_module.sapi_error(E_WARNING, "Header may not contain "
  628. "more than a single header, new line detected");
  629. return FAILURE;
  630. }
  631. if (header_line[i] == '\0') {
  632. efree(header_line);
  633. sapi_module.sapi_error(E_WARNING, "Header may not contain NUL bytes");
  634. return FAILURE;
  635. }
  636. }
  637. }
  638. sapi_header.header = header_line;
  639. sapi_header.header_len = header_line_len;
  640. /* Check the header for a few cases that we have special support for in SAPI */
  641. if (header_line_len>=5
  642. && !strncasecmp(header_line, "HTTP/", 5)) {
  643. /* filter out the response code */
  644. sapi_update_response_code(sapi_extract_response_code(header_line));
  645. /* sapi_update_response_code doesn't free the status line if the code didn't change */
  646. if (SG(sapi_headers).http_status_line) {
  647. efree(SG(sapi_headers).http_status_line);
  648. }
  649. SG(sapi_headers).http_status_line = header_line;
  650. return SUCCESS;
  651. } else {
  652. colon_offset = strchr(header_line, ':');
  653. if (colon_offset) {
  654. *colon_offset = 0;
  655. if (!strcasecmp(header_line, "Content-Type")) {
  656. char *ptr = colon_offset+1, *mimetype = NULL, *newheader;
  657. size_t len = header_line_len - (ptr - header_line), newlen;
  658. while (*ptr == ' ') {
  659. ptr++;
  660. len--;
  661. }
  662. /* Disable possible output compression for images */
  663. if (!strncmp(ptr, "image/", sizeof("image/")-1)) {
  664. zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0);
  665. zend_alter_ini_entry_chars(key, "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
  666. zend_string_release_ex(key, 0);
  667. }
  668. mimetype = estrdup(ptr);
  669. newlen = sapi_apply_default_charset(&mimetype, len);
  670. if (!SG(sapi_headers).mimetype){
  671. SG(sapi_headers).mimetype = estrdup(mimetype);
  672. }
  673. if (newlen != 0) {
  674. newlen += sizeof("Content-type: ");
  675. newheader = emalloc(newlen);
  676. PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1);
  677. strlcat(newheader, mimetype, newlen);
  678. sapi_header.header = newheader;
  679. sapi_header.header_len = (uint32_t)(newlen - 1);
  680. efree(header_line);
  681. }
  682. efree(mimetype);
  683. SG(sapi_headers).send_default_content_type = 0;
  684. } else if (!strcasecmp(header_line, "Content-Length")) {
  685. /* Script is setting Content-length. The script cannot reasonably
  686. * know the size of the message body after compression, so it's best
  687. * do disable compression altogether. This contributes to making scripts
  688. * portable between setups that have and don't have zlib compression
  689. * enabled globally. See req #44164 */
  690. zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0);
  691. zend_alter_ini_entry_chars(key,
  692. "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
  693. zend_string_release_ex(key, 0);
  694. } else if (!strcasecmp(header_line, "Location")) {
  695. if ((SG(sapi_headers).http_response_code < 300 ||
  696. SG(sapi_headers).http_response_code > 399) &&
  697. SG(sapi_headers).http_response_code != 201) {
  698. /* Return a Found Redirect if one is not already specified */
  699. if (http_response_code) { /* user specified redirect code */
  700. sapi_update_response_code(http_response_code);
  701. } else if (SG(request_info).proto_num > 1000 &&
  702. SG(request_info).request_method &&
  703. strcmp(SG(request_info).request_method, "HEAD") &&
  704. strcmp(SG(request_info).request_method, "GET")) {
  705. sapi_update_response_code(303);
  706. } else {
  707. sapi_update_response_code(302);
  708. }
  709. }
  710. } else if (!strcasecmp(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
  711. sapi_update_response_code(401); /* authentication-required */
  712. }
  713. if (sapi_header.header==header_line) {
  714. *colon_offset = ':';
  715. }
  716. }
  717. }
  718. if (http_response_code) {
  719. sapi_update_response_code(http_response_code);
  720. }
  721. sapi_header_add_op(op, &sapi_header);
  722. return SUCCESS;
  723. }
  724. SAPI_API int sapi_send_headers(void)
  725. {
  726. int retval;
  727. int ret = FAILURE;
  728. if (SG(headers_sent) || SG(request_info).no_headers) {
  729. return SUCCESS;
  730. }
  731. /* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop
  732. * in case of an error situation.
  733. */
  734. if (SG(sapi_headers).send_default_content_type && sapi_module.send_headers) {
  735. uint32_t len = 0;
  736. char *default_mimetype = get_default_content_type(0, &len);
  737. if (default_mimetype && len) {
  738. sapi_header_struct default_header;
  739. SG(sapi_headers).mimetype = default_mimetype;
  740. default_header.header_len = sizeof("Content-type: ") - 1 + len;
  741. default_header.header = emalloc(default_header.header_len + 1);
  742. memcpy(default_header.header, "Content-type: ", sizeof("Content-type: ") - 1);
  743. memcpy(default_header.header + sizeof("Content-type: ") - 1, SG(sapi_headers).mimetype, len + 1);
  744. sapi_header_add_op(SAPI_HEADER_ADD, &default_header);
  745. } else {
  746. efree(default_mimetype);
  747. }
  748. SG(sapi_headers).send_default_content_type = 0;
  749. }
  750. if (Z_TYPE(SG(callback_func)) != IS_UNDEF) {
  751. zval cb;
  752. ZVAL_COPY_VALUE(&cb, &SG(callback_func));
  753. ZVAL_UNDEF(&SG(callback_func));
  754. sapi_run_header_callback(&cb);
  755. zval_ptr_dtor(&cb);
  756. }
  757. SG(headers_sent) = 1;
  758. if (sapi_module.send_headers) {
  759. retval = sapi_module.send_headers(&SG(sapi_headers));
  760. } else {
  761. retval = SAPI_HEADER_DO_SEND;
  762. }
  763. switch (retval) {
  764. case SAPI_HEADER_SENT_SUCCESSFULLY:
  765. ret = SUCCESS;
  766. break;
  767. case SAPI_HEADER_DO_SEND: {
  768. sapi_header_struct http_status_line;
  769. char buf[255];
  770. if (SG(sapi_headers).http_status_line) {
  771. http_status_line.header = SG(sapi_headers).http_status_line;
  772. http_status_line.header_len = (uint32_t)strlen(SG(sapi_headers).http_status_line);
  773. } else {
  774. http_status_line.header = buf;
  775. http_status_line.header_len = slprintf(buf, sizeof(buf), "HTTP/1.0 %d X", SG(sapi_headers).http_response_code);
  776. }
  777. sapi_module.send_header(&http_status_line, SG(server_context));
  778. }
  779. zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context));
  780. if(SG(sapi_headers).send_default_content_type) {
  781. sapi_header_struct default_header;
  782. sapi_get_default_content_type_header(&default_header);
  783. sapi_module.send_header(&default_header, SG(server_context));
  784. sapi_free_header(&default_header);
  785. }
  786. sapi_module.send_header(NULL, SG(server_context));
  787. ret = SUCCESS;
  788. break;
  789. case SAPI_HEADER_SEND_FAILED:
  790. SG(headers_sent) = 0;
  791. ret = FAILURE;
  792. break;
  793. }
  794. sapi_send_headers_free();
  795. return ret;
  796. }
  797. SAPI_API int sapi_register_post_entries(const sapi_post_entry *post_entries)
  798. {
  799. const sapi_post_entry *p=post_entries;
  800. while (p->content_type) {
  801. if (sapi_register_post_entry(p) == FAILURE) {
  802. return FAILURE;
  803. }
  804. p++;
  805. }
  806. return SUCCESS;
  807. }
  808. SAPI_API int sapi_register_post_entry(const sapi_post_entry *post_entry)
  809. {
  810. int ret;
  811. zend_string *key;
  812. if (SG(sapi_started) && EG(current_execute_data)) {
  813. return FAILURE;
  814. }
  815. key = zend_string_init(post_entry->content_type, post_entry->content_type_len, 1);
  816. GC_MAKE_PERSISTENT_LOCAL(key);
  817. ret = zend_hash_add_mem(&SG(known_post_content_types), key,
  818. (void *) post_entry, sizeof(sapi_post_entry)) ? SUCCESS : FAILURE;
  819. zend_string_release_ex(key, 1);
  820. return ret;
  821. }
  822. SAPI_API void sapi_unregister_post_entry(const sapi_post_entry *post_entry)
  823. {
  824. if (SG(sapi_started) && EG(current_execute_data)) {
  825. return;
  826. }
  827. zend_hash_str_del(&SG(known_post_content_types), post_entry->content_type,
  828. post_entry->content_type_len);
  829. }
  830. SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(void))
  831. {
  832. if (SG(sapi_started) && EG(current_execute_data)) {
  833. return FAILURE;
  834. }
  835. sapi_module.default_post_reader = default_post_reader;
  836. return SUCCESS;
  837. }
  838. SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray))
  839. {
  840. if (SG(sapi_started) && EG(current_execute_data)) {
  841. return FAILURE;
  842. }
  843. sapi_module.treat_data = treat_data;
  844. return SUCCESS;
  845. }
  846. SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, size_t val_len, size_t *new_val_len), unsigned int (*input_filter_init)(void))
  847. {
  848. if (SG(sapi_started) && EG(current_execute_data)) {
  849. return FAILURE;
  850. }
  851. sapi_module.input_filter = input_filter;
  852. sapi_module.input_filter_init = input_filter_init;
  853. return SUCCESS;
  854. }
  855. SAPI_API int sapi_flush(void)
  856. {
  857. if (sapi_module.flush) {
  858. sapi_module.flush(SG(server_context));
  859. return SUCCESS;
  860. } else {
  861. return FAILURE;
  862. }
  863. }
  864. SAPI_API zend_stat_t *sapi_get_stat(void)
  865. {
  866. if (sapi_module.get_stat) {
  867. return sapi_module.get_stat();
  868. } else {
  869. if (!SG(request_info).path_translated || (VCWD_STAT(SG(request_info).path_translated, &SG(global_stat)) == -1)) {
  870. return NULL;
  871. }
  872. return &SG(global_stat);
  873. }
  874. }
  875. SAPI_API char *sapi_getenv(char *name, size_t name_len)
  876. {
  877. if (!strncasecmp(name, "HTTP_PROXY", name_len)) {
  878. /* Ugly fix for HTTP_PROXY issue, see bug #72573 */
  879. return NULL;
  880. }
  881. if (sapi_module.getenv) {
  882. char *value, *tmp = sapi_module.getenv(name, name_len);
  883. if (tmp) {
  884. value = estrdup(tmp);
  885. #ifdef PHP_WIN32
  886. if (strlen(sapi_module.name) == sizeof("cgi-fcgi") - 1 && !strcmp(sapi_module.name, "cgi-fcgi")) {
  887. /* XXX more modules to go, if needed. */
  888. free(tmp);
  889. }
  890. #endif
  891. } else {
  892. return NULL;
  893. }
  894. if (sapi_module.input_filter) {
  895. sapi_module.input_filter(PARSE_STRING, name, &value, strlen(value), NULL);
  896. }
  897. return value;
  898. }
  899. return NULL;
  900. }
  901. SAPI_API int sapi_get_fd(int *fd)
  902. {
  903. if (sapi_module.get_fd) {
  904. return sapi_module.get_fd(fd);
  905. } else {
  906. return FAILURE;
  907. }
  908. }
  909. SAPI_API int sapi_force_http_10(void)
  910. {
  911. if (sapi_module.force_http_10) {
  912. return sapi_module.force_http_10();
  913. } else {
  914. return FAILURE;
  915. }
  916. }
  917. SAPI_API int sapi_get_target_uid(uid_t *obj)
  918. {
  919. if (sapi_module.get_target_uid) {
  920. return sapi_module.get_target_uid(obj);
  921. } else {
  922. return FAILURE;
  923. }
  924. }
  925. SAPI_API int sapi_get_target_gid(gid_t *obj)
  926. {
  927. if (sapi_module.get_target_gid) {
  928. return sapi_module.get_target_gid(obj);
  929. } else {
  930. return FAILURE;
  931. }
  932. }
  933. SAPI_API double sapi_get_request_time(void)
  934. {
  935. if(SG(global_request_time)) return SG(global_request_time);
  936. if (sapi_module.get_request_time && SG(server_context)) {
  937. SG(global_request_time) = sapi_module.get_request_time();
  938. } else {
  939. struct timeval tp = {0};
  940. if (!gettimeofday(&tp, NULL)) {
  941. SG(global_request_time) = (double)(tp.tv_sec + tp.tv_usec / 1000000.00);
  942. } else {
  943. SG(global_request_time) = (double)time(0);
  944. }
  945. }
  946. return SG(global_request_time);
  947. }
  948. SAPI_API void sapi_terminate_process(void) {
  949. if (sapi_module.terminate_process) {
  950. sapi_module.terminate_process();
  951. }
  952. }
  953. SAPI_API void sapi_add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) /* {{{ */
  954. {
  955. zval *return_value = (zval*)arg;
  956. char *str = NULL;
  957. ALLOCA_FLAG(use_heap)
  958. if (var_len > 5 &&
  959. var[0] == 'H' &&
  960. var[1] == 'T' &&
  961. var[2] == 'T' &&
  962. var[3] == 'P' &&
  963. var[4] == '_') {
  964. char *p;
  965. var_len -= 5;
  966. p = var + 5;
  967. var = str = do_alloca(var_len + 1, use_heap);
  968. *str++ = *p++;
  969. while (*p) {
  970. if (*p == '_') {
  971. *str++ = '-';
  972. p++;
  973. if (*p) {
  974. *str++ = *p++;
  975. }
  976. } else if (*p >= 'A' && *p <= 'Z') {
  977. *str++ = (*p++ - 'A' + 'a');
  978. } else {
  979. *str++ = *p++;
  980. }
  981. }
  982. *str = 0;
  983. } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
  984. memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
  985. var = "Content-Type";
  986. } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
  987. memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
  988. var = "Content-Length";
  989. } else {
  990. return;
  991. }
  992. add_assoc_stringl_ex(return_value, var, var_len, val, val_len);
  993. if (str) {
  994. free_alloca(var, use_heap);
  995. }
  996. }
  997. /* }}} */