You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1044 lines
30 KiB

27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
21 years ago
23 years ago
23 years ago
22 years ago
23 years ago
23 years ago
23 years ago
17 years ago
27 years ago
26 years ago
17 years ago
27 years ago
26 years ago
26 years ago
23 years ago
24 years ago
25 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
20 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
17 years ago
19 years ago
19 years ago
17 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
19 years ago
19 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2009 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. | Original design: Shane Caraveo <shane@caraveo.com> |
  16. | Authors: Andi Gutmans <andi@zend.com> |
  17. | Zeev Suraski <zeev@zend.com> |
  18. +----------------------------------------------------------------------+
  19. */
  20. /* $Id$ */
  21. #include <ctype.h>
  22. #include <sys/stat.h>
  23. #include "php.h"
  24. #include "SAPI.h"
  25. #include "php_variables.h"
  26. #include "php_ini.h"
  27. #include "ext/standard/php_string.h"
  28. #include "ext/standard/pageinfo.h"
  29. #if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
  30. #include "ext/pcre/php_pcre.h"
  31. #endif
  32. #if HAVE_ZLIB
  33. #include "ext/zlib/php_zlib.h"
  34. #endif
  35. #ifdef ZTS
  36. #include "TSRM.h"
  37. #endif
  38. #ifdef HAVE_SYS_TIME_H
  39. #include <sys/time.h>
  40. #endif
  41. #include "rfc1867.h"
  42. #ifdef PHP_WIN32
  43. #define STRCASECMP stricmp
  44. #else
  45. #define STRCASECMP strcasecmp
  46. #endif
  47. #include "php_content_types.h"
  48. #ifdef ZTS
  49. SAPI_API int sapi_globals_id;
  50. #else
  51. sapi_globals_struct sapi_globals;
  52. #endif
  53. static void sapi_globals_ctor(sapi_globals_struct *sapi_globals TSRMLS_DC)
  54. {
  55. memset(sapi_globals, 0, sizeof(*sapi_globals));
  56. zend_hash_init_ex(&sapi_globals->known_post_content_types, 5, NULL, NULL, 1, 0);
  57. php_setup_sapi_content_types(TSRMLS_C);
  58. }
  59. static void sapi_globals_dtor(sapi_globals_struct *sapi_globals TSRMLS_DC)
  60. {
  61. zend_hash_destroy(&sapi_globals->known_post_content_types);
  62. }
  63. /* True globals (no need for thread safety) */
  64. SAPI_API sapi_module_struct sapi_module;
  65. SAPI_API void sapi_startup(sapi_module_struct *sf)
  66. {
  67. sf->ini_entries = NULL;
  68. sapi_module = *sf;
  69. #ifdef ZTS
  70. ts_allocate_id(&sapi_globals_id, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor);
  71. #else
  72. sapi_globals_ctor(&sapi_globals);
  73. #endif
  74. virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
  75. #ifdef PHP_WIN32
  76. tsrm_win32_startup();
  77. #endif
  78. reentrancy_startup();
  79. }
  80. SAPI_API void sapi_shutdown(void)
  81. {
  82. #ifdef ZTS
  83. ts_free_id(sapi_globals_id);
  84. #else
  85. sapi_globals_dtor(&sapi_globals);
  86. #endif
  87. reentrancy_shutdown();
  88. virtual_cwd_shutdown();
  89. #ifdef PHP_WIN32
  90. tsrm_win32_shutdown();
  91. #endif
  92. }
  93. SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
  94. {
  95. efree(sapi_header->header);
  96. }
  97. SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
  98. {
  99. if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
  100. SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
  101. if (SG(request_info).post_data) {
  102. efree(SG(request_info).post_data);
  103. SG(request_info).post_data = NULL;
  104. }
  105. efree(SG(request_info).content_type_dup);
  106. SG(request_info).content_type_dup = NULL;
  107. }
  108. }
  109. static void sapi_read_post_data(TSRMLS_D)
  110. {
  111. sapi_post_entry *post_entry;
  112. uint content_type_length = strlen(SG(request_info).content_type);
  113. char *content_type = estrndup(SG(request_info).content_type, content_type_length);
  114. char *p;
  115. char oldchar=0;
  116. void (*post_reader_func)(TSRMLS_D) = NULL;
  117. /* dedicated implementation for increased performance:
  118. * - Make the content type lowercase
  119. * - Trim descriptive data, stay with the content-type only
  120. */
  121. for (p=content_type; p<content_type+content_type_length; p++) {
  122. switch (*p) {
  123. case ';':
  124. case ',':
  125. case ' ':
  126. content_type_length = p-content_type;
  127. oldchar = *p;
  128. *p = 0;
  129. break;
  130. default:
  131. *p = tolower(*p);
  132. break;
  133. }
  134. }
  135. /* now try to find an appropriate POST content handler */
  136. if (zend_hash_find(&SG(known_post_content_types), content_type,
  137. content_type_length+1, (void **) &post_entry) == SUCCESS) {
  138. /* found one, register it for use */
  139. SG(request_info).post_entry = post_entry;
  140. post_reader_func = post_entry->post_reader;
  141. } else {
  142. /* fallback */
  143. SG(request_info).post_entry = NULL;
  144. if (!sapi_module.default_post_reader) {
  145. /* no default reader ? */
  146. SG(request_info).content_type_dup = NULL;
  147. sapi_module.sapi_error(E_WARNING, "Unsupported content type: '%s'", content_type);
  148. return;
  149. }
  150. }
  151. if (oldchar) {
  152. *(p-1) = oldchar;
  153. }
  154. SG(request_info).content_type_dup = content_type;
  155. if(post_reader_func) {
  156. post_reader_func(TSRMLS_C);
  157. }
  158. if(sapi_module.default_post_reader) {
  159. sapi_module.default_post_reader(TSRMLS_C);
  160. }
  161. }
  162. SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
  163. {
  164. int read_bytes;
  165. int allocated_bytes=SAPI_POST_BLOCK_SIZE+1;
  166. if (SG(request_info).content_length > SG(post_max_size)) {
  167. php_error_docref(NULL TSRMLS_CC, E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes",
  168. SG(request_info).content_length, SG(post_max_size));
  169. return;
  170. }
  171. SG(request_info).post_data = emalloc(allocated_bytes);
  172. for (;;) {
  173. read_bytes = sapi_module.read_post(SG(request_info).post_data+SG(read_post_bytes), SAPI_POST_BLOCK_SIZE TSRMLS_CC);
  174. if (read_bytes<=0) {
  175. break;
  176. }
  177. SG(read_post_bytes) += read_bytes;
  178. if (SG(read_post_bytes) > SG(post_max_size)) {
  179. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
  180. break;
  181. }
  182. if (read_bytes < SAPI_POST_BLOCK_SIZE) {
  183. break;
  184. }
  185. if (SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE >= allocated_bytes) {
  186. allocated_bytes = SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE+1;
  187. SG(request_info).post_data = erealloc(SG(request_info).post_data, allocated_bytes);
  188. }
  189. }
  190. SG(request_info).post_data[SG(read_post_bytes)] = 0; /* terminating NULL */
  191. SG(request_info).post_data_length = SG(read_post_bytes);
  192. }
  193. SAPI_API char *sapi_get_default_content_type(TSRMLS_D)
  194. {
  195. char *mimetype, *charset, *content_type;
  196. mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
  197. charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
  198. if (strncasecmp(mimetype, "text/", 5) == 0 && *charset) {
  199. int len = strlen(mimetype) + sizeof("; charset=") + strlen(charset); /* sizeof() includes \0 */
  200. content_type = emalloc(len);
  201. snprintf(content_type, len, "%s; charset=%s", mimetype, charset);
  202. } else {
  203. content_type = estrdup(mimetype);
  204. }
  205. return content_type;
  206. }
  207. SAPI_API void sapi_get_default_content_type_header(sapi_header_struct *default_header TSRMLS_DC)
  208. {
  209. char *default_content_type = sapi_get_default_content_type(TSRMLS_C);
  210. int default_content_type_len = strlen(default_content_type);
  211. default_header->header_len = (sizeof("Content-type: ")-1) + default_content_type_len;
  212. default_header->header = emalloc(default_header->header_len+1);
  213. memcpy(default_header->header, "Content-type: ", sizeof("Content-type: "));
  214. memcpy(default_header->header+sizeof("Content-type: ")-1, default_content_type, default_content_type_len);
  215. default_header->header[default_header->header_len] = 0;
  216. efree(default_content_type);
  217. }
  218. /*
  219. * Add charset on content-type header if the MIME type starts with
  220. * "text/", the default_charset directive is not empty and
  221. * there is not already a charset option in there.
  222. *
  223. * If "mimetype" is non-NULL, it should point to a pointer allocated
  224. * with emalloc(). If a charset is added, the string will be
  225. * re-allocated and the new length is returned. If mimetype is
  226. * unchanged, 0 is returned.
  227. *
  228. */
  229. SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len TSRMLS_DC)
  230. {
  231. char *charset, *newtype;
  232. size_t newlen;
  233. charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
  234. if (*mimetype != NULL) {
  235. if (*charset && strncmp(*mimetype, "text/", 5) == 0 && strstr(*mimetype, "charset=") == NULL) {
  236. newlen = len + (sizeof(";charset=")-1) + strlen(charset);
  237. newtype = emalloc(newlen + 1);
  238. PHP_STRLCPY(newtype, *mimetype, newlen + 1, len);
  239. strlcat(newtype, ";charset=", newlen + 1);
  240. strlcat(newtype, charset, newlen + 1);
  241. efree(*mimetype);
  242. *mimetype = newtype;
  243. return newlen;
  244. }
  245. }
  246. return 0;
  247. }
  248. SAPI_API void sapi_activate_headers_only(TSRMLS_D)
  249. {
  250. if (SG(request_info).headers_read == 1)
  251. return;
  252. SG(request_info).headers_read = 1;
  253. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct),
  254. (void (*)(void *)) sapi_free_header, 0);
  255. SG(sapi_headers).send_default_content_type = 1;
  256. /* SG(sapi_headers).http_response_code = 200; */
  257. SG(sapi_headers).http_status_line = NULL;
  258. SG(sapi_headers).mimetype = NULL;
  259. SG(read_post_bytes) = 0;
  260. SG(request_info).post_data = NULL;
  261. SG(request_info).raw_post_data = NULL;
  262. SG(request_info).current_user = NULL;
  263. SG(request_info).current_user_length = 0;
  264. SG(request_info).no_headers = 0;
  265. SG(request_info).post_entry = NULL;
  266. SG(global_request_time) = 0;
  267. /*
  268. * It's possible to override this general case in the activate() callback,
  269. * if necessary.
  270. */
  271. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  272. SG(request_info).headers_only = 1;
  273. } else {
  274. SG(request_info).headers_only = 0;
  275. }
  276. if (SG(server_context)) {
  277. SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
  278. if (sapi_module.activate) {
  279. sapi_module.activate(TSRMLS_C);
  280. }
  281. }
  282. if (sapi_module.input_filter_init ) {
  283. sapi_module.input_filter_init(TSRMLS_C);
  284. }
  285. }
  286. /*
  287. * Called from php_request_startup() for every request.
  288. */
  289. SAPI_API void sapi_activate(TSRMLS_D)
  290. {
  291. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
  292. SG(sapi_headers).send_default_content_type = 1;
  293. /*
  294. SG(sapi_headers).http_response_code = 200;
  295. */
  296. SG(sapi_headers).http_status_line = NULL;
  297. SG(sapi_headers).mimetype = NULL;
  298. SG(headers_sent) = 0;
  299. SG(read_post_bytes) = 0;
  300. SG(request_info).post_data = NULL;
  301. SG(request_info).raw_post_data = NULL;
  302. SG(request_info).current_user = NULL;
  303. SG(request_info).current_user_length = 0;
  304. SG(request_info).no_headers = 0;
  305. SG(request_info).post_entry = NULL;
  306. SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
  307. SG(global_request_time) = 0;
  308. /* It's possible to override this general case in the activate() callback, if
  309. * necessary.
  310. */
  311. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  312. SG(request_info).headers_only = 1;
  313. } else {
  314. SG(request_info).headers_only = 0;
  315. }
  316. SG(rfc1867_uploaded_files) = NULL;
  317. /* handle request mehtod */
  318. if (SG(server_context)) {
  319. if ( SG(request_info).request_method) {
  320. if(!strcmp(SG(request_info).request_method, "POST")
  321. && (SG(request_info).content_type)) {
  322. /* HTTP POST -> may contain form data to be read into variables
  323. depending on content type given
  324. */
  325. sapi_read_post_data(TSRMLS_C);
  326. } else {
  327. /* any other method with content payload will fill
  328. $HTTP_RAW_POST_DATA if enabled by always_populate_raw_post_data
  329. it is up to the webserver to decide whether to allow a method or not
  330. */
  331. SG(request_info).content_type_dup = NULL;
  332. if(sapi_module.default_post_reader) {
  333. sapi_module.default_post_reader(TSRMLS_C);
  334. }
  335. }
  336. } else {
  337. SG(request_info).content_type_dup = NULL;
  338. }
  339. /* Cookies */
  340. SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
  341. if (sapi_module.activate) {
  342. sapi_module.activate(TSRMLS_C);
  343. }
  344. }
  345. if (sapi_module.input_filter_init ) {
  346. sapi_module.input_filter_init(TSRMLS_C);
  347. }
  348. }
  349. static void sapi_send_headers_free(TSRMLS_D)
  350. {
  351. if (SG(sapi_headers).http_status_line) {
  352. efree(SG(sapi_headers).http_status_line);
  353. SG(sapi_headers).http_status_line = NULL;
  354. }
  355. }
  356. SAPI_API void sapi_deactivate(TSRMLS_D)
  357. {
  358. zend_llist_destroy(&SG(sapi_headers).headers);
  359. if (SG(request_info).post_data) {
  360. efree(SG(request_info).post_data);
  361. } else if (SG(server_context)) {
  362. if(sapi_module.read_post) {
  363. /* make sure we've consumed all request input data */
  364. char dummy[SAPI_POST_BLOCK_SIZE];
  365. int read_bytes;
  366. while((read_bytes = sapi_module.read_post(dummy, sizeof(dummy)-1 TSRMLS_CC)) > 0) {
  367. SG(read_post_bytes) += read_bytes;
  368. }
  369. }
  370. }
  371. if (SG(request_info).raw_post_data) {
  372. efree(SG(request_info).raw_post_data);
  373. }
  374. if (SG(request_info).auth_user) {
  375. efree(SG(request_info).auth_user);
  376. }
  377. if (SG(request_info).auth_password) {
  378. efree(SG(request_info).auth_password);
  379. }
  380. if (SG(request_info).auth_digest) {
  381. efree(SG(request_info).auth_digest);
  382. }
  383. if (SG(request_info).content_type_dup) {
  384. efree(SG(request_info).content_type_dup);
  385. }
  386. if (SG(request_info).current_user) {
  387. efree(SG(request_info).current_user);
  388. }
  389. if (sapi_module.deactivate) {
  390. sapi_module.deactivate(TSRMLS_C);
  391. }
  392. if (SG(rfc1867_uploaded_files)) {
  393. destroy_uploaded_files_hash(TSRMLS_C);
  394. }
  395. if (SG(sapi_headers).mimetype) {
  396. efree(SG(sapi_headers).mimetype);
  397. SG(sapi_headers).mimetype = NULL;
  398. }
  399. sapi_send_headers_free(TSRMLS_C);
  400. SG(sapi_started) = 0;
  401. SG(headers_sent) = 0;
  402. SG(request_info).headers_read = 0;
  403. SG(global_request_time) = 0;
  404. }
  405. SAPI_API void sapi_initialize_empty_request(TSRMLS_D)
  406. {
  407. SG(server_context) = NULL;
  408. SG(request_info).request_method = NULL;
  409. SG(request_info).auth_digest = SG(request_info).auth_user = SG(request_info).auth_password = NULL;
  410. SG(request_info).content_type_dup = NULL;
  411. }
  412. static int sapi_extract_response_code(const char *header_line)
  413. {
  414. int code = 200;
  415. const char *ptr;
  416. for (ptr = header_line; *ptr; ptr++) {
  417. if (*ptr == ' ' && *(ptr + 1) != ' ') {
  418. code = atoi(ptr + 1);
  419. break;
  420. }
  421. }
  422. return code;
  423. }
  424. static void sapi_update_response_code(int ncode TSRMLS_DC)
  425. {
  426. /* if the status code did not change, we do not want
  427. to change the status line, and no need to change the code */
  428. if (SG(sapi_headers).http_response_code == ncode) {
  429. return;
  430. }
  431. if (SG(sapi_headers).http_status_line) {
  432. efree(SG(sapi_headers).http_status_line);
  433. SG(sapi_headers).http_status_line = NULL;
  434. }
  435. SG(sapi_headers).http_response_code = ncode;
  436. }
  437. static int sapi_find_matching_header(void *element1, void *element2)
  438. {
  439. int len = strlen((char*)element2);
  440. return strncasecmp(((sapi_header_struct*)element1)->header, (char*)element2, len) == 0 && ((sapi_header_struct*)element1)->header[len] == ':';
  441. }
  442. SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool duplicate, zend_bool replace TSRMLS_DC)
  443. {
  444. sapi_header_line ctr = {0};
  445. int r;
  446. ctr.line = header_line;
  447. ctr.line_len = header_line_len;
  448. r = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD,
  449. &ctr TSRMLS_CC);
  450. if (!duplicate)
  451. efree(header_line);
  452. return r;
  453. }
  454. SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
  455. {
  456. int retval;
  457. sapi_header_struct sapi_header;
  458. char *colon_offset;
  459. long myuid = 0L;
  460. char *header_line;
  461. uint header_line_len;
  462. int http_response_code;
  463. if (SG(headers_sent) && !SG(request_info).no_headers) {
  464. char *output_start_filename = php_get_output_start_filename(TSRMLS_C);
  465. int output_start_lineno = php_get_output_start_lineno(TSRMLS_C);
  466. if (output_start_filename) {
  467. sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)",
  468. output_start_filename, output_start_lineno);
  469. } else {
  470. sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent");
  471. }
  472. return FAILURE;
  473. }
  474. switch (op) {
  475. case SAPI_HEADER_SET_STATUS:
  476. sapi_update_response_code((int)(zend_intptr_t) arg TSRMLS_CC);
  477. return SUCCESS;
  478. case SAPI_HEADER_ADD:
  479. case SAPI_HEADER_REPLACE:
  480. case SAPI_HEADER_DELETE: {
  481. sapi_header_line *p = arg;
  482. if (!p->line || !p->line_len) {
  483. return FAILURE;
  484. }
  485. header_line = p->line;
  486. header_line_len = p->line_len;
  487. http_response_code = p->response_code;
  488. break;
  489. }
  490. case SAPI_HEADER_DELETE_ALL:
  491. if (sapi_module.header_handler) {
  492. sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
  493. }
  494. zend_llist_clean(&SG(sapi_headers).headers);
  495. return SUCCESS;
  496. default:
  497. return FAILURE;
  498. }
  499. header_line = estrndup(header_line, header_line_len);
  500. /* cut of trailing spaces, linefeeds and carriage-returns */
  501. while(header_line_len && isspace(header_line[header_line_len-1]))
  502. header_line[--header_line_len]='\0';
  503. if (op == SAPI_HEADER_DELETE) {
  504. if (strchr(header_line, ':')) {
  505. efree(header_line);
  506. sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon.");
  507. return FAILURE;
  508. }
  509. } else {
  510. /* new line safety check */
  511. char *s = header_line, *e = header_line + header_line_len, *p;
  512. while (s < e && (p = memchr(s, '\n', (e - s)))) {
  513. if (*(p + 1) == ' ' || *(p + 1) == '\t') {
  514. s = p + 1;
  515. continue;
  516. }
  517. efree(header_line);
  518. sapi_module.sapi_error(E_WARNING, "Header may not contain more than a single header, new line detected.");
  519. return FAILURE;
  520. }
  521. }
  522. sapi_header.header = header_line;
  523. sapi_header.header_len = header_line_len;
  524. if (op == SAPI_HEADER_DELETE) {
  525. if (sapi_module.header_handler) {
  526. sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
  527. }
  528. zend_llist_del_element(&SG(sapi_headers).headers, sapi_header.header, (int(*)(void*, void*))sapi_find_matching_header);
  529. sapi_free_header(&sapi_header);
  530. return SUCCESS;
  531. }
  532. /* Check the header for a few cases that we have special support for in SAPI */
  533. if (header_line_len>=5
  534. && !strncasecmp(header_line, "HTTP/", 5)) {
  535. /* filter out the response code */
  536. sapi_update_response_code(sapi_extract_response_code(header_line) TSRMLS_CC);
  537. /* sapi_update_response_code doesn't free the status line if the code didn't change */
  538. if (SG(sapi_headers).http_status_line) {
  539. efree(SG(sapi_headers).http_status_line);
  540. }
  541. SG(sapi_headers).http_status_line = header_line;
  542. return SUCCESS;
  543. } else {
  544. colon_offset = strchr(header_line, ':');
  545. if (colon_offset) {
  546. *colon_offset = 0;
  547. if (!STRCASECMP(header_line, "Content-Type")) {
  548. char *ptr = colon_offset+1, *mimetype = NULL, *newheader;
  549. size_t len = header_line_len - (ptr - header_line), newlen;
  550. while (*ptr == ' ') {
  551. ptr++;
  552. len--;
  553. }
  554. #if HAVE_ZLIB
  555. if(!strncmp(ptr, "image/", sizeof("image/")-1)) {
  556. zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
  557. }
  558. #endif
  559. mimetype = estrdup(ptr);
  560. newlen = sapi_apply_default_charset(&mimetype, len TSRMLS_CC);
  561. if (!SG(sapi_headers).mimetype){
  562. SG(sapi_headers).mimetype = estrdup(mimetype);
  563. }
  564. if (newlen != 0) {
  565. newlen += sizeof("Content-type: ");
  566. newheader = emalloc(newlen);
  567. PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1);
  568. strlcat(newheader, mimetype, newlen);
  569. sapi_header.header = newheader;
  570. sapi_header.header_len = newlen - 1;
  571. efree(header_line);
  572. }
  573. efree(mimetype);
  574. SG(sapi_headers).send_default_content_type = 0;
  575. } else if (!STRCASECMP(header_line, "Location")) {
  576. if ((SG(sapi_headers).http_response_code < 300 ||
  577. SG(sapi_headers).http_response_code > 307) &&
  578. SG(sapi_headers).http_response_code != 201) {
  579. /* Return a Found Redirect if one is not already specified */
  580. if (http_response_code) { /* user specified redirect code */
  581. sapi_update_response_code(http_response_code TSRMLS_CC);
  582. } else if (SG(request_info).proto_num > 1000 &&
  583. SG(request_info).request_method &&
  584. strcmp(SG(request_info).request_method, "HEAD") &&
  585. strcmp(SG(request_info).request_method, "GET")) {
  586. sapi_update_response_code(303 TSRMLS_CC);
  587. } else {
  588. sapi_update_response_code(302 TSRMLS_CC);
  589. }
  590. }
  591. } else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
  592. sapi_update_response_code(401 TSRMLS_CC); /* authentication-required */
  593. if(PG(safe_mode))
  594. #if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
  595. {
  596. zval *repl_temp;
  597. char *ptr = colon_offset+1, *result, *newheader;
  598. int ptr_len=0, result_len = 0, newlen = 0;
  599. /* skip white space */
  600. while (isspace(*ptr)) {
  601. ptr++;
  602. }
  603. myuid = php_getuid();
  604. ptr_len = strlen(ptr);
  605. MAKE_STD_ZVAL(repl_temp);
  606. Z_TYPE_P(repl_temp) = IS_STRING;
  607. Z_STRLEN_P(repl_temp) = spprintf(&Z_STRVAL_P(repl_temp), 0, "realm=\"\\1-%ld\"", myuid);
  608. /* Modify quoted realm value */
  609. result = php_pcre_replace("/realm=\"(.*?)\"/i", 16,
  610. ptr, ptr_len,
  611. repl_temp,
  612. 0, &result_len, -1, NULL TSRMLS_CC);
  613. if(result_len==ptr_len) {
  614. efree(result);
  615. efree(Z_STRVAL_P(repl_temp));
  616. Z_STRLEN_P(repl_temp) = spprintf(&Z_STRVAL_P(repl_temp), 0, "realm=\\1-%ld\\2", myuid);
  617. /* modify unquoted realm value */
  618. result = php_pcre_replace("/realm=([^\\s]+)(.*)/i", 21,
  619. ptr, ptr_len,
  620. repl_temp,
  621. 0, &result_len, -1, NULL TSRMLS_CC);
  622. if(result_len==ptr_len) {
  623. char *lower_temp = estrdup(ptr);
  624. char conv_temp[32];
  625. int conv_len;
  626. php_strtolower(lower_temp,strlen(lower_temp));
  627. /* If there is no realm string at all, append one */
  628. if(!strstr(lower_temp,"realm")) {
  629. efree(result);
  630. conv_len = slprintf(conv_temp, sizeof(conv_temp), " realm=\"%ld\"",myuid);
  631. result = emalloc(ptr_len+conv_len+1);
  632. result_len = ptr_len+conv_len;
  633. memcpy(result, ptr, ptr_len);
  634. memcpy(result+ptr_len, conv_temp, conv_len);
  635. *(result+ptr_len+conv_len) = '\0';
  636. }
  637. efree(lower_temp);
  638. }
  639. }
  640. newlen = spprintf(&newheader, 0, "WWW-Authenticate: %s", result);
  641. efree(header_line);
  642. sapi_header.header = newheader;
  643. sapi_header.header_len = newlen;
  644. efree(result);
  645. efree(Z_STRVAL_P(repl_temp));
  646. efree(repl_temp);
  647. }
  648. #else
  649. {
  650. myuid = php_getuid();
  651. efree(header_line);
  652. sapi_header.header_len = spprintf(&sapi_header.header, 0, "WWW-Authenticate: Basic realm=\"%ld\"", myuid);
  653. }
  654. #endif
  655. }
  656. if (sapi_header.header==header_line) {
  657. *colon_offset = ':';
  658. }
  659. }
  660. }
  661. if (http_response_code) {
  662. sapi_update_response_code(http_response_code TSRMLS_CC);
  663. }
  664. if (sapi_module.header_handler) {
  665. retval = sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
  666. } else {
  667. retval = SAPI_HEADER_ADD;
  668. }
  669. if (retval & SAPI_HEADER_ADD) {
  670. /* in replace mode first remove the header if it already exists in the headers llist */
  671. if (op == SAPI_HEADER_REPLACE) {
  672. colon_offset = strchr(sapi_header.header, ':');
  673. if (colon_offset) {
  674. char sav;
  675. sav = *colon_offset;
  676. *colon_offset = 0;
  677. zend_llist_del_element(&SG(sapi_headers).headers, sapi_header.header, (int(*)(void*, void*))sapi_find_matching_header);
  678. *colon_offset = sav;
  679. }
  680. }
  681. zend_llist_add_element(&SG(sapi_headers).headers, (void *) &sapi_header);
  682. } else {
  683. sapi_free_header(&sapi_header);
  684. }
  685. return SUCCESS;
  686. }
  687. SAPI_API int sapi_send_headers(TSRMLS_D)
  688. {
  689. int retval;
  690. int ret = FAILURE;
  691. if (SG(headers_sent) || SG(request_info).no_headers) {
  692. return SUCCESS;
  693. }
  694. #if HAVE_ZLIB
  695. /* Add output compression headers at this late stage in order to make
  696. it possible to switch it off inside the script. */
  697. if (ZLIBG(output_compression)) {
  698. zval nm_zlib_get_coding_type;
  699. zval *uf_result = NULL;
  700. ZVAL_STRINGL(&nm_zlib_get_coding_type, "zlib_get_coding_type", sizeof("zlib_get_coding_type") - 1, 0);
  701. if (call_user_function_ex(CG(function_table), NULL, &nm_zlib_get_coding_type, &uf_result, 0, NULL, 1, NULL TSRMLS_CC) != FAILURE && uf_result != NULL && Z_TYPE_P(uf_result) == IS_STRING) {
  702. char buf[128];
  703. int len;
  704. assert(Z_STRVAL_P(uf_result) != NULL);
  705. len = slprintf(buf, sizeof(buf), "Content-Encoding: %s", Z_STRVAL_P(uf_result));
  706. if (len <= 0 || sapi_add_header(buf, len, 1) == FAILURE) {
  707. return FAILURE;
  708. }
  709. if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC) == FAILURE) {
  710. return FAILURE;
  711. }
  712. }
  713. if (uf_result != NULL) {
  714. zval_ptr_dtor(&uf_result);
  715. }
  716. }
  717. #endif
  718. /* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop
  719. * in case of an error situation.
  720. */
  721. if (SG(sapi_headers).send_default_content_type && sapi_module.send_headers) {
  722. sapi_header_struct default_header;
  723. sapi_get_default_content_type_header(&default_header TSRMLS_CC);
  724. sapi_add_header_ex(default_header.header, default_header.header_len, 0, 0 TSRMLS_CC);
  725. }
  726. SG(headers_sent) = 1;
  727. if (sapi_module.send_headers) {
  728. retval = sapi_module.send_headers(&SG(sapi_headers) TSRMLS_CC);
  729. } else {
  730. retval = SAPI_HEADER_DO_SEND;
  731. }
  732. switch (retval) {
  733. case SAPI_HEADER_SENT_SUCCESSFULLY:
  734. ret = SUCCESS;
  735. break;
  736. case SAPI_HEADER_DO_SEND: {
  737. sapi_header_struct http_status_line;
  738. char buf[255];
  739. if (SG(sapi_headers).http_status_line) {
  740. http_status_line.header = SG(sapi_headers).http_status_line;
  741. http_status_line.header_len = strlen(SG(sapi_headers).http_status_line);
  742. } else {
  743. http_status_line.header = buf;
  744. http_status_line.header_len = slprintf(buf, sizeof(buf), "HTTP/1.0 %d X", SG(sapi_headers).http_response_code);
  745. }
  746. sapi_module.send_header(&http_status_line, SG(server_context) TSRMLS_CC);
  747. }
  748. zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context) TSRMLS_CC);
  749. if(SG(sapi_headers).send_default_content_type) {
  750. sapi_header_struct default_header;
  751. sapi_get_default_content_type_header(&default_header TSRMLS_CC);
  752. sapi_module.send_header(&default_header, SG(server_context) TSRMLS_CC);
  753. sapi_free_header(&default_header);
  754. }
  755. sapi_module.send_header(NULL, SG(server_context) TSRMLS_CC);
  756. ret = SUCCESS;
  757. break;
  758. case SAPI_HEADER_SEND_FAILED:
  759. SG(headers_sent) = 0;
  760. ret = FAILURE;
  761. break;
  762. }
  763. sapi_send_headers_free(TSRMLS_C);
  764. return ret;
  765. }
  766. SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries TSRMLS_DC)
  767. {
  768. sapi_post_entry *p=post_entries;
  769. while (p->content_type) {
  770. if (sapi_register_post_entry(p TSRMLS_CC) == FAILURE) {
  771. return FAILURE;
  772. }
  773. p++;
  774. }
  775. return SUCCESS;
  776. }
  777. SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
  778. {
  779. if (SG(sapi_started) && EG(in_execution)) {
  780. return FAILURE;
  781. }
  782. return zend_hash_add(&SG(known_post_content_types),
  783. post_entry->content_type, post_entry->content_type_len+1,
  784. (void *) post_entry, sizeof(sapi_post_entry), NULL);
  785. }
  786. SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
  787. {
  788. if (SG(sapi_started) && EG(in_execution)) {
  789. return;
  790. }
  791. zend_hash_del(&SG(known_post_content_types), post_entry->content_type,
  792. post_entry->content_type_len+1);
  793. }
  794. SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D))
  795. {
  796. TSRMLS_FETCH();
  797. if (SG(sapi_started) && EG(in_execution)) {
  798. return FAILURE;
  799. }
  800. sapi_module.default_post_reader = default_post_reader;
  801. return SUCCESS;
  802. }
  803. SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC))
  804. {
  805. TSRMLS_FETCH();
  806. if (SG(sapi_started) && EG(in_execution)) {
  807. return FAILURE;
  808. }
  809. sapi_module.treat_data = treat_data;
  810. return SUCCESS;
  811. }
  812. SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D))
  813. {
  814. TSRMLS_FETCH();
  815. if (SG(sapi_started) && EG(in_execution)) {
  816. return FAILURE;
  817. }
  818. sapi_module.input_filter = input_filter;
  819. sapi_module.input_filter_init = input_filter_init;
  820. return SUCCESS;
  821. }
  822. SAPI_API int sapi_flush(TSRMLS_D)
  823. {
  824. if (sapi_module.flush) {
  825. sapi_module.flush(SG(server_context));
  826. return SUCCESS;
  827. } else {
  828. return FAILURE;
  829. }
  830. }
  831. SAPI_API struct stat *sapi_get_stat(TSRMLS_D)
  832. {
  833. if (sapi_module.get_stat) {
  834. return sapi_module.get_stat(TSRMLS_C);
  835. } else {
  836. if (!SG(request_info).path_translated || (VCWD_STAT(SG(request_info).path_translated, &SG(global_stat)) == -1)) {
  837. return NULL;
  838. }
  839. return &SG(global_stat);
  840. }
  841. }
  842. SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC)
  843. {
  844. if (sapi_module.getenv) {
  845. char *value, *tmp = sapi_module.getenv(name, name_len TSRMLS_CC);
  846. if (tmp) {
  847. value = estrdup(tmp);
  848. } else {
  849. return NULL;
  850. }
  851. sapi_module.input_filter(PARSE_ENV, name, &value, strlen(value), NULL TSRMLS_CC);
  852. return value;
  853. }
  854. return NULL;
  855. }
  856. SAPI_API int sapi_get_fd(int *fd TSRMLS_DC)
  857. {
  858. if (sapi_module.get_fd) {
  859. return sapi_module.get_fd(fd TSRMLS_CC);
  860. } else {
  861. return FAILURE;
  862. }
  863. }
  864. SAPI_API int sapi_force_http_10(TSRMLS_D)
  865. {
  866. if (sapi_module.force_http_10) {
  867. return sapi_module.force_http_10(TSRMLS_C);
  868. } else {
  869. return FAILURE;
  870. }
  871. }
  872. SAPI_API int sapi_get_target_uid(uid_t *obj TSRMLS_DC)
  873. {
  874. if (sapi_module.get_target_uid) {
  875. return sapi_module.get_target_uid(obj TSRMLS_CC);
  876. } else {
  877. return FAILURE;
  878. }
  879. }
  880. SAPI_API int sapi_get_target_gid(gid_t *obj TSRMLS_DC)
  881. {
  882. if (sapi_module.get_target_gid) {
  883. return sapi_module.get_target_gid(obj TSRMLS_CC);
  884. } else {
  885. return FAILURE;
  886. }
  887. }
  888. SAPI_API time_t sapi_get_request_time(TSRMLS_D)
  889. {
  890. if(SG(global_request_time)) return SG(global_request_time);
  891. if (sapi_module.get_request_time && SG(server_context)) {
  892. SG(global_request_time) = sapi_module.get_request_time(TSRMLS_C);
  893. } else {
  894. SG(global_request_time) = time(0);
  895. }
  896. return SG(global_request_time);
  897. }
  898. SAPI_API void sapi_terminate_process(TSRMLS_D) {
  899. if (sapi_module.terminate_process) {
  900. sapi_module.terminate_process(TSRMLS_C);
  901. }
  902. }
  903. /*
  904. * Local variables:
  905. * tab-width: 4
  906. * c-basic-offset: 4
  907. * End:
  908. * vim600: sw=4 ts=4 fdm=marker
  909. * vim<600: sw=4 ts=4
  910. */