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.

691 lines
20 KiB

27 years ago
25 years ago
25 years ago
27 years ago
27 years ago
27 years ago
27 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
25 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
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 4 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2002 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.02 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.php.net/license/2_02.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 "ext/standard/php_string.h"
  26. #include "ext/standard/pageinfo.h"
  27. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  28. #include "ext/pcre/php_pcre.h"
  29. #endif
  30. #ifdef ZTS
  31. #include "TSRM.h"
  32. #endif
  33. #include "rfc1867.h"
  34. #ifdef PHP_WIN32
  35. #define STRCASECMP stricmp
  36. #else
  37. #define STRCASECMP strcasecmp
  38. #endif
  39. #include "php_content_types.h"
  40. static HashTable known_post_content_types;
  41. #ifdef ZTS
  42. SAPI_API int sapi_globals_id;
  43. #else
  44. sapi_globals_struct sapi_globals;
  45. #endif
  46. static void sapi_globals_ctor(sapi_globals_struct *sapi_globals TSRMLS_DC)
  47. {
  48. memset(sapi_globals, 0, sizeof(*sapi_globals));
  49. }
  50. /* True globals (no need for thread safety) */
  51. SAPI_API sapi_module_struct sapi_module;
  52. SAPI_API void sapi_startup(sapi_module_struct *sf)
  53. {
  54. sapi_module = *sf;
  55. zend_hash_init_ex(&known_post_content_types, 5, NULL, NULL, 1, 0);
  56. #ifdef ZTS
  57. ts_allocate_id(&sapi_globals_id, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, NULL);
  58. #else
  59. sapi_globals_ctor(&sapi_globals TSRMLS_CC);
  60. #endif
  61. #ifdef VIRTUAL_DIR
  62. virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
  63. #endif
  64. #ifdef PHP_WIN32
  65. tsrm_win32_startup();
  66. #endif
  67. reentrancy_startup();
  68. }
  69. SAPI_API void sapi_shutdown(void)
  70. {
  71. reentrancy_shutdown();
  72. #ifdef VIRTUAL_DIR
  73. virtual_cwd_shutdown();
  74. #endif
  75. #ifdef PHP_WIN32
  76. tsrm_win32_shutdown();
  77. #endif
  78. zend_hash_destroy(&known_post_content_types);
  79. }
  80. SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
  81. {
  82. efree(sapi_header->header);
  83. }
  84. SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
  85. {
  86. if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
  87. SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
  88. if (SG(request_info).post_data) {
  89. efree(SG(request_info).post_data);
  90. SG(request_info).post_data = NULL;
  91. }
  92. efree(SG(request_info).content_type_dup);
  93. SG(request_info).content_type_dup = NULL;
  94. }
  95. }
  96. static void sapi_read_post_data(TSRMLS_D)
  97. {
  98. sapi_post_entry *post_entry;
  99. uint content_type_length = strlen(SG(request_info).content_type);
  100. char *content_type = estrndup(SG(request_info).content_type, content_type_length);
  101. char *p;
  102. char oldchar=0;
  103. void (*post_reader_func)(TSRMLS_D);
  104. /* dedicated implementation for increased performance:
  105. * - Make the content type lowercase
  106. * - Trim descriptive data, stay with the content-type only
  107. */
  108. for (p=content_type; p<content_type+content_type_length; p++) {
  109. switch (*p) {
  110. case ';':
  111. case ',':
  112. case ' ':
  113. content_type_length = p-content_type;
  114. oldchar = *p;
  115. *p = 0;
  116. break;
  117. default:
  118. *p = tolower(*p);
  119. break;
  120. }
  121. }
  122. if (zend_hash_find(&known_post_content_types, content_type, content_type_length+1, (void **) &post_entry)==SUCCESS) {
  123. SG(request_info).post_entry = post_entry;
  124. post_reader_func = post_entry->post_reader;
  125. } else {
  126. if (!sapi_module.default_post_reader) {
  127. sapi_module.sapi_error(E_WARNING, "Unsupported content type: '%s'", content_type);
  128. return;
  129. }
  130. SG(request_info).post_entry = NULL;
  131. post_reader_func = sapi_module.default_post_reader;
  132. }
  133. if (oldchar) {
  134. *(p-1) = oldchar;
  135. }
  136. SG(request_info).content_type_dup = content_type;
  137. if(post_reader_func) {
  138. post_reader_func(TSRMLS_C);
  139. if(PG(always_populate_raw_post_data) && sapi_module.default_post_reader) {
  140. sapi_module.default_post_reader(TSRMLS_C);
  141. }
  142. }
  143. }
  144. SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
  145. {
  146. int read_bytes;
  147. int allocated_bytes=SAPI_POST_BLOCK_SIZE+1;
  148. if (SG(request_info).content_length > SG(post_max_size)) {
  149. php_error(E_WARNING, "POST Content-Length of %d bytes exceeds the limit of %d bytes",
  150. SG(request_info).content_length, SG(post_max_size));
  151. return;
  152. }
  153. SG(request_info).post_data = emalloc(allocated_bytes);
  154. for (;;) {
  155. read_bytes = sapi_module.read_post(SG(request_info).post_data+SG(read_post_bytes), SAPI_POST_BLOCK_SIZE TSRMLS_CC);
  156. if (read_bytes<=0) {
  157. break;
  158. }
  159. SG(read_post_bytes) += read_bytes;
  160. if (SG(read_post_bytes) > SG(post_max_size)) {
  161. php_error(E_WARNING, "Actual POST length does not match Content-Length, and exceeds %d bytes", SG(post_max_size));
  162. return;
  163. }
  164. if (read_bytes < SAPI_POST_BLOCK_SIZE) {
  165. break;
  166. }
  167. if (SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE >= allocated_bytes) {
  168. allocated_bytes = SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE+1;
  169. SG(request_info).post_data = erealloc(SG(request_info).post_data, allocated_bytes);
  170. }
  171. }
  172. SG(request_info).post_data[SG(read_post_bytes)] = 0; /* terminating NULL */
  173. SG(request_info).post_data_length = SG(read_post_bytes);
  174. }
  175. SAPI_API char *sapi_get_default_content_type(TSRMLS_D)
  176. {
  177. char *mimetype, *charset, *content_type;
  178. mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
  179. charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
  180. if (strncasecmp(mimetype, "text/", 5) == 0 && *charset) {
  181. int len = strlen(mimetype) + sizeof("; charset=") + strlen(charset);
  182. content_type = emalloc(len);
  183. snprintf(content_type, len, "%s; charset=%s", mimetype, charset);
  184. } else {
  185. content_type = estrdup(mimetype);
  186. }
  187. return content_type;
  188. }
  189. SAPI_API void sapi_get_default_content_type_header(sapi_header_struct *default_header TSRMLS_DC)
  190. {
  191. char *default_content_type = sapi_get_default_content_type(TSRMLS_C);
  192. int default_content_type_len = strlen(default_content_type);
  193. default_header->header_len = (sizeof("Content-type: ")-1) + default_content_type_len;
  194. default_header->header = emalloc(default_header->header_len+1);
  195. memcpy(default_header->header, "Content-type: ", sizeof("Content-type: "));
  196. memcpy(default_header->header+sizeof("Content-type: ")-1, default_content_type, default_content_type_len);
  197. default_header->header[default_header->header_len] = 0;
  198. efree(default_content_type);
  199. }
  200. /*
  201. * Add charset on content-type header if the MIME type starts with
  202. * "text/", the default_charset directive is not empty and
  203. * there is not already a charset option in there.
  204. *
  205. * If "mimetype" is non-NULL, it should point to a pointer allocated
  206. * with emalloc(). If a charset is added, the string will be
  207. * re-allocated and the new length is returned. If mimetype is
  208. * unchanged, 0 is returned.
  209. *
  210. */
  211. SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len TSRMLS_DC)
  212. {
  213. char *charset, *newtype;
  214. size_t newlen;
  215. charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
  216. if (*charset && strncmp(*mimetype, "text/", 5) == 0 && strstr(*mimetype, "charset=") == NULL) {
  217. newlen = len + (sizeof(";charset=")-1) + strlen(charset);
  218. newtype = emalloc(newlen + 1);
  219. PHP_STRLCPY(newtype, *mimetype, newlen + 1, len);
  220. strlcat(newtype, ";charset=", newlen + 1);
  221. if (*mimetype != NULL) {
  222. efree(*mimetype);
  223. }
  224. *mimetype = newtype;
  225. return newlen;
  226. }
  227. return 0;
  228. }
  229. /*
  230. * Called from php_request_startup() for every request.
  231. */
  232. SAPI_API void sapi_activate(TSRMLS_D)
  233. {
  234. void (*post_reader_func)(TSRMLS_D);
  235. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
  236. SG(sapi_headers).send_default_content_type = 1;
  237. /*
  238. SG(sapi_headers).http_response_code = 200;
  239. */
  240. SG(sapi_headers).http_status_line = NULL;
  241. SG(headers_sent) = 0;
  242. SG(read_post_bytes) = 0;
  243. SG(request_info).post_data = NULL;
  244. SG(request_info).current_user = NULL;
  245. SG(request_info).current_user_length = 0;
  246. SG(request_info).no_headers = 0;
  247. /* It's possible to override this general case in the activate() callback, if
  248. * necessary.
  249. */
  250. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  251. SG(request_info).headers_only = 1;
  252. } else {
  253. SG(request_info).headers_only = 0;
  254. }
  255. SG(rfc1867_uploaded_files) = NULL;
  256. if (SG(server_context)) {
  257. if (SG(request_info).request_method
  258. && !strcmp(SG(request_info).request_method, "POST")) {
  259. if (!SG(request_info).content_type) {
  260. SG(request_info).content_type_dup = NULL;
  261. if(PG(always_populate_raw_post_data)) {
  262. SG(request_info).post_entry = NULL;
  263. post_reader_func = sapi_module.default_post_reader;
  264. if(post_reader_func) {
  265. post_reader_func(TSRMLS_C);
  266. if(PG(always_populate_raw_post_data) && sapi_module.default_post_reader) {
  267. sapi_module.default_post_reader(TSRMLS_C);
  268. }
  269. }
  270. } else {
  271. sapi_module.sapi_error(E_WARNING, "No content-type in POST request");
  272. }
  273. } else {
  274. sapi_read_post_data(TSRMLS_C);
  275. }
  276. } else {
  277. SG(request_info).content_type_dup = NULL;
  278. }
  279. SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
  280. if (sapi_module.activate) {
  281. sapi_module.activate(TSRMLS_C);
  282. }
  283. }
  284. }
  285. SAPI_API void sapi_deactivate(TSRMLS_D)
  286. {
  287. zend_llist_destroy(&SG(sapi_headers).headers);
  288. if (SG(request_info).post_data) {
  289. efree(SG(request_info).post_data);
  290. }
  291. if (SG(request_info).auth_user) {
  292. efree(SG(request_info).auth_user);
  293. }
  294. if (SG(request_info).auth_password) {
  295. efree(SG(request_info).auth_password);
  296. }
  297. if (SG(request_info).content_type_dup) {
  298. efree(SG(request_info).content_type_dup);
  299. }
  300. if (SG(request_info).current_user) {
  301. efree(SG(request_info).current_user);
  302. }
  303. if (sapi_module.deactivate) {
  304. sapi_module.deactivate(TSRMLS_C);
  305. }
  306. if (SG(rfc1867_uploaded_files)) {
  307. destroy_uploaded_files_hash(TSRMLS_C);
  308. }
  309. }
  310. SAPI_API void sapi_initialize_empty_request(TSRMLS_D)
  311. {
  312. SG(server_context) = NULL;
  313. SG(request_info).request_method = NULL;
  314. SG(request_info).auth_user = SG(request_info).auth_password = NULL;
  315. SG(request_info).content_type_dup = NULL;
  316. }
  317. static int sapi_extract_response_code(const char *header_line)
  318. {
  319. int code = 200;
  320. const char *ptr;
  321. for (ptr = header_line; *ptr; ptr++) {
  322. if (*ptr == ' ' && *(ptr + 1) != ' ') {
  323. code = atoi(ptr + 1);
  324. break;
  325. }
  326. }
  327. return code;
  328. }
  329. /* This function expects a *duplicated* string, that was previously emalloc()'d.
  330. * Pointers sent to this functions will be automatically freed by the framework.
  331. */
  332. SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool duplicate, zend_bool replace TSRMLS_DC)
  333. {
  334. int retval, free_header = 0;
  335. sapi_header_struct sapi_header;
  336. char *colon_offset;
  337. long myuid = 0L;
  338. if (SG(headers_sent) && !SG(request_info).no_headers) {
  339. char *output_start_filename = php_get_output_start_filename(TSRMLS_C);
  340. int output_start_lineno = php_get_output_start_lineno(TSRMLS_C);
  341. if (output_start_filename) {
  342. sapi_module.sapi_error(E_WARNING, "Cannot add header information - headers already sent by (output started at %s:%d)",
  343. output_start_filename, output_start_lineno);
  344. } else {
  345. sapi_module.sapi_error(E_WARNING, "Cannot add header information - headers already sent");
  346. }
  347. if (!duplicate) {
  348. efree(header_line);
  349. }
  350. return FAILURE;
  351. }
  352. if (duplicate) {
  353. header_line = estrndup(header_line, header_line_len);
  354. }
  355. /* cut of trailing spaces, linefeeds and carriage-returns */
  356. while(isspace(header_line[header_line_len-1]))
  357. header_line[--header_line_len]='\0';
  358. sapi_header.header = header_line;
  359. sapi_header.header_len = header_line_len;
  360. sapi_header.replace = replace;
  361. /* Check the header for a few cases that we have special support for in SAPI */
  362. if (header_line_len>=5
  363. && !strncasecmp(header_line, "HTTP/", 5)) {
  364. /* filter out the response code */
  365. SG(sapi_headers).http_response_code = sapi_extract_response_code(header_line);
  366. SG(sapi_headers).http_status_line = header_line;
  367. return SUCCESS;
  368. } else {
  369. colon_offset = strchr(header_line, ':');
  370. if (colon_offset) {
  371. *colon_offset = 0;
  372. if (!STRCASECMP(header_line, "Content-Type")) {
  373. char *ptr = colon_offset, *mimetype = NULL, *newheader;
  374. size_t len = header_line_len - (ptr - header_line), newlen;
  375. while (*ptr == ' ' && *ptr != '\0') {
  376. ptr++;
  377. }
  378. mimetype = estrdup(ptr);
  379. newlen = sapi_apply_default_charset(&mimetype, len TSRMLS_CC);
  380. if (newlen != 0) {
  381. newlen += sizeof("Content-type: ");
  382. newheader = emalloc(newlen);
  383. PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1);
  384. strlcat(newheader, mimetype, newlen);
  385. sapi_header.header = newheader;
  386. sapi_header.header_len = newlen - 1;
  387. colon_offset = strchr(newheader, ':');
  388. *colon_offset = '\0';
  389. free_header = 1;
  390. }
  391. efree(mimetype);
  392. SG(sapi_headers).send_default_content_type = 0;
  393. } else if (!STRCASECMP(header_line, "Location")) {
  394. if (SG(sapi_headers).http_response_code < 300 ||
  395. SG(sapi_headers).http_response_code > 307) {
  396. /* Return a Found Redirect if one is not already specified */
  397. SG(sapi_headers).http_response_code = 302;
  398. }
  399. } else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
  400. int newlen;
  401. char *result, *newheader;
  402. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  403. zval *repl_temp;
  404. char *ptr = colon_offset+1;
  405. int ptr_len=0, result_len = 0;
  406. #endif
  407. SG(sapi_headers).http_response_code = 401; /* authentication-required */
  408. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  409. if(PG(safe_mode)) {
  410. myuid = php_getuid();
  411. ptr_len = strlen(ptr);
  412. MAKE_STD_ZVAL(repl_temp);
  413. Z_TYPE_P(repl_temp) = IS_STRING;
  414. Z_STRVAL_P(repl_temp) = emalloc(32);
  415. Z_STRLEN_P(repl_temp) = sprintf(Z_STRVAL_P(repl_temp), "realm=\"\\1-%ld\"", myuid);
  416. /* Modify quoted realm value */
  417. result = php_pcre_replace("/realm=\"(.*?)\"/i", 16,
  418. ptr, ptr_len,
  419. repl_temp,
  420. 0, &result_len, -1 TSRMLS_CC);
  421. if(result_len==ptr_len) {
  422. efree(result);
  423. sprintf(Z_STRVAL_P(repl_temp), "realm=\\1-%ld\\2", myuid);
  424. /* modify unquoted realm value */
  425. result = php_pcre_replace("/realm=([^\\s]+)(.*)/i", 21,
  426. ptr, ptr_len,
  427. repl_temp,
  428. 0, &result_len, -1 TSRMLS_CC);
  429. if(result_len==ptr_len) {
  430. char *lower_temp = estrdup(ptr);
  431. char conv_temp[32];
  432. int conv_len;
  433. php_strtolower(lower_temp,strlen(lower_temp));
  434. /* If there is no realm string at all, append one */
  435. if(!strstr(lower_temp,"realm")) {
  436. efree(result);
  437. conv_len = sprintf(conv_temp," realm=\"%ld\"",myuid);
  438. result = emalloc(ptr_len+conv_len+1);
  439. result_len = ptr_len+conv_len;
  440. memcpy(result, ptr, ptr_len);
  441. memcpy(result+ptr_len, conv_temp, conv_len);
  442. *(result+ptr_len+conv_len) = '\0';
  443. }
  444. efree(lower_temp);
  445. }
  446. }
  447. newlen = sizeof("WWW-Authenticate: ") + result_len;
  448. newheader = emalloc(newlen+1);
  449. sprintf(newheader,"WWW-Authenticate: %s", result);
  450. efree(header_line);
  451. sapi_header.header = newheader;
  452. sapi_header.header_len = newlen;
  453. efree(result);
  454. efree(Z_STRVAL_P(repl_temp));
  455. efree(repl_temp);
  456. }
  457. #else
  458. if(PG(safe_mode)) {
  459. myuid = php_getuid();
  460. result = emalloc(32);
  461. newlen = sprintf(result, "WWW-Authenticate: %ld", myuid);
  462. newheader = estrndup(result,newlen);
  463. efree(header_line);
  464. sapi_header.header = newheader;
  465. sapi_header.header_len = newlen;
  466. efree(result);
  467. }
  468. #endif
  469. }
  470. if (sapi_header.header==header_line) {
  471. *colon_offset = ':';
  472. }
  473. }
  474. }
  475. if (sapi_module.header_handler) {
  476. retval = sapi_module.header_handler(&sapi_header, &SG(sapi_headers) TSRMLS_CC);
  477. } else {
  478. retval = SAPI_HEADER_ADD;
  479. }
  480. if (retval & SAPI_HEADER_DELETE_ALL) {
  481. zend_llist_clean(&SG(sapi_headers).headers);
  482. }
  483. if (retval & SAPI_HEADER_ADD) {
  484. zend_llist_add_element(&SG(sapi_headers).headers, (void *) &sapi_header);
  485. }
  486. if (free_header) {
  487. efree(sapi_header.header);
  488. }
  489. return SUCCESS;
  490. }
  491. SAPI_API int sapi_send_headers(TSRMLS_D)
  492. {
  493. int retval;
  494. int ret = FAILURE;
  495. if (SG(headers_sent) || SG(request_info).no_headers) {
  496. return SUCCESS;
  497. }
  498. /* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop
  499. * in case of an error situation.
  500. */
  501. SG(headers_sent) = 1;
  502. if (sapi_module.send_headers) {
  503. retval = sapi_module.send_headers(&SG(sapi_headers) TSRMLS_CC);
  504. } else {
  505. retval = SAPI_HEADER_DO_SEND;
  506. }
  507. switch (retval) {
  508. case SAPI_HEADER_SENT_SUCCESSFULLY:
  509. ret = SUCCESS;
  510. break;
  511. case SAPI_HEADER_DO_SEND:
  512. if (SG(sapi_headers).http_status_line) {
  513. sapi_header_struct http_status_line;
  514. http_status_line.header = SG(sapi_headers).http_status_line;
  515. http_status_line.header_len = strlen(SG(sapi_headers).http_status_line);
  516. sapi_module.send_header(&http_status_line, SG(server_context) TSRMLS_CC);
  517. }
  518. zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context) TSRMLS_CC);
  519. if(SG(sapi_headers).send_default_content_type) {
  520. sapi_header_struct default_header;
  521. sapi_get_default_content_type_header(&default_header TSRMLS_CC);
  522. sapi_module.send_header(&default_header, SG(server_context) TSRMLS_CC);
  523. sapi_free_header(&default_header);
  524. }
  525. sapi_module.send_header(NULL, SG(server_context) TSRMLS_CC);
  526. ret = SUCCESS;
  527. break;
  528. case SAPI_HEADER_SEND_FAILED:
  529. SG(headers_sent) = 0;
  530. ret = FAILURE;
  531. break;
  532. }
  533. if (SG(sapi_headers).http_status_line) {
  534. efree(SG(sapi_headers).http_status_line);
  535. }
  536. return ret;
  537. }
  538. SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries)
  539. {
  540. sapi_post_entry *p=post_entries;
  541. while (p->content_type) {
  542. if (sapi_register_post_entry(p)==FAILURE) {
  543. return FAILURE;
  544. }
  545. p++;
  546. }
  547. return SUCCESS;
  548. }
  549. SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry)
  550. {
  551. return zend_hash_add(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1, (void *) post_entry, sizeof(sapi_post_entry), NULL);
  552. }
  553. SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry)
  554. {
  555. zend_hash_del(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1);
  556. }
  557. SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D))
  558. {
  559. sapi_module.default_post_reader = default_post_reader;
  560. return SUCCESS;
  561. }
  562. SAPI_API int sapi_flush(TSRMLS_D)
  563. {
  564. if (sapi_module.flush) {
  565. sapi_module.flush(SG(server_context));
  566. return SUCCESS;
  567. } else {
  568. return FAILURE;
  569. }
  570. }
  571. SAPI_API struct stat *sapi_get_stat(TSRMLS_D)
  572. {
  573. if (sapi_module.get_stat) {
  574. return sapi_module.get_stat(TSRMLS_C);
  575. } else {
  576. if (!SG(request_info).path_translated || (VCWD_STAT(SG(request_info).path_translated, &SG(global_stat))==-1)) {
  577. return NULL;
  578. }
  579. return &SG(global_stat);
  580. }
  581. }
  582. SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC)
  583. {
  584. if (sapi_module.getenv) {
  585. return sapi_module.getenv(name, name_len TSRMLS_CC);
  586. } else {
  587. return NULL;
  588. }
  589. }
  590. /*
  591. * Local variables:
  592. * tab-width: 4
  593. * c-basic-offset: 4
  594. * End:
  595. * vim600: sw=4 ts=4 fdm=marker
  596. * vim<600: sw=4 ts=4
  597. */