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.

444 lines
12 KiB

27 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
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
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP version 4.0 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.0 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_0.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. #include <ctype.h>
  21. #include <sys/stat.h>
  22. #include "php.h"
  23. #include "SAPI.h"
  24. #ifdef ZTS
  25. #include "TSRM.h"
  26. #endif
  27. #include "rfc1867.h"
  28. #ifdef PHP_WIN32
  29. #define STRCASECMP stricmp
  30. #else
  31. #define STRCASECMP strcasecmp
  32. #endif
  33. SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
  34. static sapi_post_entry supported_post_entries[] = {
  35. #if HAVE_FDFLIB
  36. { "application/vnd.fdf", sizeof("application/vnd.fdf")-1, sapi_read_standard_form_data },
  37. #endif
  38. { NULL, 0, NULL }
  39. };
  40. static HashTable known_post_content_types;
  41. SAPI_API void (*sapi_error)(int error_type, const char *message, ...);
  42. #ifdef ZTS
  43. SAPI_API int sapi_globals_id;
  44. #else
  45. sapi_globals_struct sapi_globals;
  46. #endif
  47. /* True globals (no need for thread safety) */
  48. sapi_module_struct sapi_module;
  49. SAPI_API void (*sapi_error)(int error_type, const char *message, ...);
  50. SAPI_API void sapi_startup(sapi_module_struct *sf)
  51. {
  52. sapi_module = *sf;
  53. zend_hash_init(&known_post_content_types, 5, NULL, NULL, 1);
  54. sapi_register_post_entries(supported_post_entries);
  55. #ifdef ZTS
  56. sapi_globals_id = ts_allocate_id(sizeof(sapi_globals_struct), NULL, NULL);
  57. #endif
  58. reentrancy_startup();
  59. php_global_startup_internal_extensions();
  60. }
  61. SAPI_API void sapi_shutdown(void)
  62. {
  63. reentrancy_shutdown();
  64. php_global_shutdown_internal_extensions();
  65. zend_hash_destroy(&known_post_content_types);
  66. }
  67. SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
  68. {
  69. efree(sapi_header->header);
  70. }
  71. SAPI_API void sapi_handle_post(void *arg SLS_DC)
  72. {
  73. if (SG(request_info).post_entry) {
  74. SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg SLS_CC);
  75. efree(SG(request_info).post_data);
  76. efree(SG(request_info).content_type_dup);
  77. SG(request_info).content_type_dup = NULL;
  78. }
  79. }
  80. static void sapi_read_post_data(SLS_D)
  81. {
  82. sapi_post_entry *post_entry;
  83. uint content_type_length = strlen(SG(request_info).content_type);
  84. char *content_type = estrndup(SG(request_info).content_type, content_type_length);
  85. char *p;
  86. char oldchar=0;
  87. void (*post_reader_func)(SLS_D);
  88. /* dedicated implementation for increased performance:
  89. * - Make the content type lowercase
  90. * - Trim descriptive data, stay with the content-type only
  91. */
  92. for (p=content_type; p<content_type+content_type_length; p++) {
  93. switch (*p) {
  94. case ';':
  95. case ',':
  96. case ' ':
  97. content_type_length = p-content_type;
  98. oldchar = *p;
  99. *p = 0;
  100. break;
  101. default:
  102. *p = tolower(*p);
  103. break;
  104. }
  105. }
  106. if (zend_hash_find(&known_post_content_types, content_type, content_type_length+1, (void **) &post_entry)==SUCCESS) {
  107. SG(request_info).post_entry = post_entry;
  108. post_reader_func = post_entry->post_reader;
  109. } else {
  110. if (!sapi_module.default_post_reader) {
  111. sapi_module.sapi_error(E_COMPILE_ERROR, "Unsupported content type: '%s'", content_type);
  112. return;
  113. }
  114. SG(request_info).post_entry = NULL;
  115. post_reader_func = sapi_module.default_post_reader;
  116. }
  117. if (oldchar) {
  118. *(p-1) = oldchar;
  119. }
  120. post_reader_func(SLS_C);
  121. SG(request_info).content_type_dup = content_type;
  122. }
  123. SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
  124. {
  125. int read_bytes, total_read_bytes=0;
  126. int allocated_bytes=SAPI_POST_BLOCK_SIZE+1;
  127. SG(request_info).post_data = emalloc(allocated_bytes);
  128. for (;;) {
  129. read_bytes = sapi_module.read_post(SG(request_info).post_data+total_read_bytes, SAPI_POST_BLOCK_SIZE SLS_CC);
  130. if (read_bytes<=0) {
  131. break;
  132. }
  133. total_read_bytes += read_bytes;
  134. if (read_bytes < SAPI_POST_BLOCK_SIZE) {
  135. break;
  136. }
  137. if (total_read_bytes+SAPI_POST_BLOCK_SIZE >= allocated_bytes) {
  138. allocated_bytes = total_read_bytes+SAPI_POST_BLOCK_SIZE+1;
  139. SG(request_info).post_data = erealloc(SG(request_info).post_data, allocated_bytes);
  140. }
  141. }
  142. SG(request_info).post_data[total_read_bytes] = 0; /* terminating NULL */
  143. SG(request_info).post_data_length = total_read_bytes;
  144. }
  145. SAPI_API void sapi_activate(SLS_D)
  146. {
  147. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
  148. SG(sapi_headers).send_default_content_type = 1;
  149. SG(sapi_headers).http_response_code = 200;
  150. SG(sapi_headers).http_status_line = NULL;
  151. SG(headers_sent) = 0;
  152. SG(read_post_bytes) = 0;
  153. SG(request_info).post_data = NULL;
  154. SG(request_info).current_user = NULL;
  155. SG(request_info).current_user_length = 0;
  156. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  157. SG(request_info).headers_only = 1;
  158. } else {
  159. SG(request_info).headers_only = 0;
  160. }
  161. if (SG(server_context)) {
  162. if (SG(request_info).request_method
  163. && !strcmp(SG(request_info).request_method, "POST")) {
  164. if (!SG(request_info).content_type) {
  165. sapi_module.sapi_error(E_COMPILE_ERROR, "No content-type in POST request");
  166. }
  167. sapi_read_post_data(SLS_C);
  168. }
  169. SG(request_info).cookie_data = sapi_module.read_cookies(SLS_C);
  170. if (sapi_module.activate) {
  171. sapi_module.activate(SLS_C);
  172. }
  173. }
  174. }
  175. SAPI_API void sapi_deactivate(SLS_D)
  176. {
  177. zend_llist_destroy(&SG(sapi_headers).headers);
  178. if (SG(request_info).post_data) {
  179. efree(SG(request_info).post_data);
  180. }
  181. if (SG(request_info).auth_user) {
  182. efree(SG(request_info).auth_user);
  183. }
  184. if (SG(request_info).auth_password) {
  185. efree(SG(request_info).auth_password);
  186. }
  187. if (SG(request_info).content_type_dup) {
  188. efree(SG(request_info).content_type_dup);
  189. }
  190. if (SG(request_info).current_user) {
  191. efree(SG(request_info).current_user);
  192. }
  193. if (sapi_module.deactivate) {
  194. sapi_module.deactivate(SLS_C);
  195. }
  196. }
  197. SAPI_API void sapi_initialize_empty_request(SLS_D)
  198. {
  199. SG(server_context) = NULL;
  200. SG(request_info).request_method = NULL;
  201. SG(request_info).auth_user = SG(request_info).auth_password = NULL;
  202. SG(request_info).content_type_dup = NULL;
  203. }
  204. static int sapi_extract_response_code(const char *header_line)
  205. {
  206. int code = 200;
  207. const char *ptr;
  208. for (ptr = header_line; *ptr; ptr++) {
  209. if (*ptr == ' ' && *(ptr + 1) != ' ') {
  210. code = atoi(ptr + 1);
  211. break;
  212. }
  213. }
  214. return code;
  215. }
  216. /* This function expects a *duplicated* string, that was previously emalloc()'d.
  217. * Pointers sent to this functions will be automatically freed by the framework.
  218. */
  219. SAPI_API int sapi_add_header(char *header_line, uint header_line_len)
  220. {
  221. int retval;
  222. sapi_header_struct sapi_header;
  223. char *colon_offset;
  224. SLS_FETCH();
  225. if (SG(headers_sent)) {
  226. char *output_start_filename = php_get_output_start_filename();
  227. int output_start_lineno = php_get_output_start_lineno();
  228. if (output_start_filename) {
  229. sapi_module.sapi_error(E_WARNING, "Cannot add header information - headers already sent by (output started at %s:%d)",
  230. output_start_filename, output_start_lineno);
  231. } else {
  232. sapi_module.sapi_error(E_WARNING, "Cannot add header information - headers already sent");
  233. }
  234. efree(header_line);
  235. return FAILURE;
  236. }
  237. sapi_header.header = header_line;
  238. sapi_header.header_len = header_line_len;
  239. /* Check the header for a few cases that we have special support for in SAPI */
  240. if (header_line_len>=5
  241. && !memcmp(header_line, "HTTP/", 5)) {
  242. /* filter out the response code */
  243. SG(sapi_headers).http_response_code = sapi_extract_response_code(header_line);
  244. SG(sapi_headers).http_status_line = header_line;
  245. return SUCCESS;
  246. } else {
  247. colon_offset = strchr(header_line, ':');
  248. if (colon_offset) {
  249. *colon_offset = 0;
  250. if (!STRCASECMP(header_line, "Content-Type")) {
  251. SG(sapi_headers).send_default_content_type = 0;
  252. } else if (!STRCASECMP(header_line, "Location")) {
  253. SG(sapi_headers).http_response_code = 302; /* redirect */
  254. } else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
  255. SG(sapi_headers).http_response_code = 401; /* authentication-required */
  256. }
  257. *colon_offset = ':';
  258. }
  259. }
  260. if (sapi_module.header_handler) {
  261. retval = sapi_module.header_handler(&sapi_header, &SG(sapi_headers) SLS_CC);
  262. } else {
  263. retval = SAPI_HEADER_ADD;
  264. }
  265. if (retval & SAPI_HEADER_DELETE_ALL) {
  266. zend_llist_clean(&SG(sapi_headers).headers);
  267. }
  268. if (retval & SAPI_HEADER_ADD) {
  269. zend_llist_add_element(&SG(sapi_headers).headers, (void *) &sapi_header);
  270. }
  271. return SUCCESS;
  272. }
  273. SAPI_API int sapi_send_headers()
  274. {
  275. int retval;
  276. int ret = FAILURE;
  277. sapi_header_struct default_header = { SAPI_DEFAULT_CONTENT_TYPE, sizeof(SAPI_DEFAULT_CONTENT_TYPE)-1 };
  278. SLS_FETCH();
  279. if (SG(headers_sent)) {
  280. return SUCCESS;
  281. }
  282. if (sapi_module.send_headers) {
  283. retval = sapi_module.send_headers(&SG(sapi_headers) SLS_CC);
  284. } else {
  285. retval = SAPI_HEADER_DO_SEND;
  286. }
  287. switch (retval) {
  288. case SAPI_HEADER_SENT_SUCCESSFULLY:
  289. SG(headers_sent) = 1;
  290. ret = SUCCESS;
  291. break;
  292. case SAPI_HEADER_DO_SEND:
  293. if (SG(sapi_headers).http_status_line) {
  294. sapi_header_struct http_status_line;
  295. http_status_line.header = SG(sapi_headers).http_status_line;
  296. http_status_line.header_len = strlen(SG(sapi_headers).http_status_line);
  297. sapi_module.send_header(&http_status_line, SG(server_context));
  298. }
  299. zend_llist_apply_with_argument(&SG(sapi_headers).headers, (void (*)(void *, void *)) sapi_module.send_header, SG(server_context));
  300. if(SG(sapi_headers).send_default_content_type) {
  301. sapi_module.send_header(&default_header,SG(server_context));
  302. }
  303. sapi_module.send_header(NULL, SG(server_context));
  304. SG(headers_sent) = 1;
  305. ret = SUCCESS;
  306. break;
  307. case SAPI_HEADER_SEND_FAILED:
  308. ret = FAILURE;
  309. break;
  310. }
  311. if (SG(sapi_headers).http_status_line) {
  312. efree(SG(sapi_headers).http_status_line);
  313. }
  314. return ret;
  315. }
  316. SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries)
  317. {
  318. sapi_post_entry *p=post_entries;
  319. while (p->content_type) {
  320. if (sapi_register_post_entry(p)==FAILURE) {
  321. return FAILURE;
  322. }
  323. p++;
  324. }
  325. return SUCCESS;
  326. }
  327. SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry)
  328. {
  329. 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);
  330. }
  331. SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry)
  332. {
  333. zend_hash_del(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1);
  334. }
  335. SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(SLS_D))
  336. {
  337. sapi_module.default_post_reader = default_post_reader;
  338. return SUCCESS;
  339. }
  340. SAPI_API int sapi_flush()
  341. {
  342. if (sapi_module.flush) {
  343. SLS_FETCH();
  344. sapi_module.flush(SG(server_context));
  345. return SUCCESS;
  346. } else {
  347. return FAILURE;
  348. }
  349. }
  350. SAPI_API struct stat *sapi_get_stat()
  351. {
  352. SLS_FETCH();
  353. if (sapi_module.get_stat) {
  354. return sapi_module.get_stat(SLS_C);
  355. } else {
  356. if (!SG(request_info).path_translated || (stat(SG(request_info).path_translated, &SG(global_stat))==-1)) {
  357. return NULL;
  358. }
  359. return &SG(global_stat);
  360. }
  361. }
  362. SAPI_API char *sapi_getenv(char *name, int name_len)
  363. {
  364. if (sapi_module.getenv) {
  365. SLS_FETCH();
  366. return sapi_module.getenv(name, name_len SLS_CC);
  367. } else {
  368. return NULL;
  369. }
  370. }