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.

1041 lines
28 KiB

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
Generalized server-API build process on UNIX. Each SAPI implementation now has its own directory under sapi/, just like extensions have theirs under ext/. To make the final targets appear in the main dir, the top-level Makefile includes sapi/NN/Makefile.inc from the selected sapi backend. This is a plan Makefile stub without any autoconf substitutions. Each SAPI backend also has its own config.m4 like extensions (read at the end of diversion 2) and config.h.stub files. Each SAPI backend has to contain: config.m4: just like for extensions, this file contains autoconf/automake directives that end up in the configure script. The only difference is that the sapi config.m4 files are read in diversion (output block) 2 instead of 3. The sapi config.m4 files should set two variables: PHP_SAPI (which sapi backend to choose) and SAPI_TARGET (the name of the resulting library or program, previously BINNAME). If they are not specified, they will default to "cgi" and "php", respectively. Makefile.inc: has to exist, has to define "INSTALL_IT" to the command used to install the final target (or ":" for no operation). It also has to define a plain Makefile rule (without autoconf substitutions) to build $(SAPI_TARGET) Makefile.am: just what you think. Make sure your target is called "libphpsapi_NNN.a", where NNN is the value of PHP_SAPI. Some testing and fixing probably remains. To make everything hang together, I've done some ugly tricks that I can imagine causing some problems. I've built and run the CGI version and built the Apache DSO.
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
25 years ago
25 years ago
26 years ago
26 years ago
23 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
26 years ago
26 years ago
26 years ago
24 years ago
27 years ago
27 years ago
27 years ago
19 years ago
21 years ago
27 years ago
26 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
27 years ago
25 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
24 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
27 years ago
27 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2008 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. | Authors: Rasmus Lerdorf <rasmus@php.net> |
  16. | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> |
  17. | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> |
  18. +----------------------------------------------------------------------+
  19. */
  20. /* $Id$ */
  21. #include "php_apache_http.h"
  22. #include "http_conf_globals.h"
  23. #ifdef NETWARE
  24. #define SIGPIPE SIGINT
  25. #endif
  26. #undef shutdown
  27. /* {{{ Prototypes
  28. */
  29. int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC);
  30. static void php_save_umask(void);
  31. static void php_restore_umask(void);
  32. static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC);
  33. static char *sapi_apache_read_cookies(TSRMLS_D);
  34. static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC);
  35. static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC);
  36. static int send_php(request_rec *r, int display_source_mode, char *filename);
  37. static int send_parsed_php(request_rec * r);
  38. static int send_parsed_php_source(request_rec * r);
  39. static int php_xbithack_handler(request_rec * r);
  40. static void php_init_handler(server_rec *s, pool *p);
  41. /* }}} */
  42. #if MODULE_MAGIC_NUMBER >= 19970728
  43. static void php_child_exit_handler(server_rec *s, pool *p);
  44. #endif
  45. #if MODULE_MAGIC_NUMBER > 19961007
  46. #define CONST_PREFIX const
  47. #else
  48. #define CONST_PREFIX
  49. #endif
  50. static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
  51. static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  52. static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  53. static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  54. static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
  55. static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  56. /* ### these should be defined in mod_php.h or somewhere else */
  57. #define USE_PATH 1
  58. #define IGNORE_URL 2
  59. #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST POSSIBLE STATUS DESCRIPTION")
  60. module MODULE_VAR_EXPORT php6_module;
  61. int saved_umask;
  62. static unsigned char apache_php_initialized;
  63. typedef struct _php_per_dir_entry {
  64. char *key;
  65. char *value;
  66. uint key_length;
  67. uint value_length;
  68. int type;
  69. char htaccess;
  70. } php_per_dir_entry;
  71. /* some systems are missing these from their header files */
  72. /* {{{ php_save_umask
  73. */
  74. static void php_save_umask(void)
  75. {
  76. saved_umask = umask(077);
  77. umask(saved_umask);
  78. }
  79. /* }}} */
  80. /* {{{ sapi_apache_ub_write
  81. */
  82. static int sapi_apache_ub_write(const char *str, uint str_length TSRMLS_DC)
  83. {
  84. int ret=0;
  85. if (SG(server_context)) {
  86. ret = rwrite(str, str_length, (request_rec *) SG(server_context));
  87. }
  88. if (ret != str_length) {
  89. php_handle_aborted_connection();
  90. }
  91. return ret;
  92. }
  93. /* }}} */
  94. /* {{{ sapi_apache_flush
  95. */
  96. static void sapi_apache_flush(void *server_context)
  97. {
  98. if (server_context) {
  99. #if MODULE_MAGIC_NUMBER > 19970110
  100. rflush((request_rec *) server_context);
  101. #else
  102. bflush((request_rec *) server_context->connection->client);
  103. #endif
  104. }
  105. }
  106. /* }}} */
  107. /* {{{ sapi_apache_read_post
  108. */
  109. static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC)
  110. {
  111. int total_read_bytes=0, read_bytes;
  112. request_rec *r = (request_rec *) SG(server_context);
  113. void (*handler)(int);
  114. /*
  115. * This handles the situation where the browser sends a Expect: 100-continue header
  116. * and needs to recieve confirmation from the server on whether or not it can send
  117. * the rest of the request. RFC 2616
  118. *
  119. */
  120. if (!SG(read_post_bytes) && !ap_should_client_block(r)) {
  121. return total_read_bytes;
  122. }
  123. handler = signal(SIGPIPE, SIG_IGN);
  124. while (total_read_bytes<count_bytes) {
  125. hard_timeout("Read POST information", r); /* start timeout timer */
  126. read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes);
  127. reset_timeout(r);
  128. if (read_bytes<=0) {
  129. break;
  130. }
  131. total_read_bytes += read_bytes;
  132. }
  133. signal(SIGPIPE, handler);
  134. return total_read_bytes;
  135. }
  136. /* }}} */
  137. /* {{{ sapi_apache_read_cookies
  138. */
  139. static char *sapi_apache_read_cookies(TSRMLS_D)
  140. {
  141. return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE");
  142. }
  143. /* }}} */
  144. /* {{{ sapi_apache_header_handler
  145. */
  146. static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
  147. {
  148. char *header_name, *header_content, *p;
  149. request_rec *r = (request_rec *) SG(server_context);
  150. if(!r) {
  151. return 0;
  152. }
  153. switch(op) {
  154. case SAPI_HEADER_DELETE_ALL:
  155. clear_table(r->headers_out);
  156. return 0;
  157. case SAPI_HEADER_DELETE:
  158. table_unset(r->headers_out, sapi_header->header);
  159. return 0;
  160. case SAPI_HEADER_ADD:
  161. case SAPI_HEADER_REPLACE:
  162. header_name = sapi_header->header;
  163. header_content = p = strchr(header_name, ':');
  164. if (!p) {
  165. return 0;
  166. }
  167. *p = 0;
  168. do {
  169. header_content++;
  170. } while (*header_content==' ');
  171. if (!strcasecmp(header_name, "Content-Type")) {
  172. r->content_type = pstrdup(r->pool, header_content);
  173. } else if (!strcasecmp(header_name, "Set-Cookie")) {
  174. table_add(r->headers_out, header_name, header_content);
  175. } else if (op == SAPI_HEADER_REPLACE) {
  176. table_set(r->headers_out, header_name, header_content);
  177. } else {
  178. table_add(r->headers_out, header_name, header_content);
  179. }
  180. *p = ':'; /* a well behaved header handler shouldn't change its original arguments */
  181. return SAPI_HEADER_ADD;
  182. default:
  183. return 0;
  184. }
  185. }
  186. /* }}} */
  187. /* {{{ sapi_apache_send_headers
  188. */
  189. static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  190. {
  191. request_rec *r = SG(server_context);
  192. const char *sline = SG(sapi_headers).http_status_line;
  193. int sline_len;
  194. if(r == NULL) { /* server_context is not here anymore */
  195. return SAPI_HEADER_SEND_FAILED;
  196. }
  197. r->status = SG(sapi_headers).http_response_code;
  198. /* httpd requires that r->status_line is set to the first digit of
  199. * the status-code: */
  200. if (sline && ((sline_len = strlen(sline)) > 12) && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ' && sline[12] == ' ') {
  201. if ((sline_len - 9) > MAX_STATUS_LENGTH) {
  202. r->status_line = ap_pstrndup(r->pool, sline + 9, MAX_STATUS_LENGTH);
  203. } else {
  204. r->status_line = ap_pstrndup(r->pool, sline + 9, sline_len - 9);
  205. }
  206. }
  207. if(r->status==304) {
  208. send_error_response(r,0);
  209. } else {
  210. send_http_header(r);
  211. }
  212. return SAPI_HEADER_SENT_SUCCESSFULLY;
  213. }
  214. /* }}} */
  215. /* {{{ sapi_apache_register_server_variables
  216. */
  217. static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_DC)
  218. {
  219. register int i;
  220. array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env);
  221. table_entry *elts = (table_entry *) arr->elts;
  222. zval **path_translated;
  223. HashTable *symbol_table;
  224. unsigned int new_val_len;
  225. for (i = 0; i < arr->nelts; i++) {
  226. char *val;
  227. int val_len;
  228. if (elts[i].val) {
  229. val = elts[i].val;
  230. } else {
  231. val = "";
  232. }
  233. val_len = strlen(val);
  234. if (sapi_module.input_filter(PARSE_SERVER, elts[i].key, &val, val_len, &new_val_len TSRMLS_CC)) {
  235. php_register_variable_safe(elts[i].key, val, new_val_len, track_vars_array TSRMLS_CC);
  236. }
  237. }
  238. /* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
  239. if (track_vars_array) {
  240. symbol_table = track_vars_array->value.ht;
  241. } else {
  242. symbol_table = NULL;
  243. }
  244. if (symbol_table
  245. && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"))
  246. && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) {
  247. php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC);
  248. }
  249. if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &((request_rec *) SG(server_context))->uri, strlen(((request_rec *) SG(server_context))->uri), &new_val_len TSRMLS_CC)) {
  250. php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC);
  251. }
  252. }
  253. /* }}} */
  254. /* {{{ php_apache_startup
  255. */
  256. static int php_apache_startup(sapi_module_struct *sapi_module)
  257. {
  258. if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {
  259. return FAILURE;
  260. } else {
  261. return SUCCESS;
  262. }
  263. }
  264. /* }}} */
  265. /* {{{ php_apache_log_message
  266. */
  267. static void php_apache_log_message(char *message)
  268. {
  269. TSRMLS_FETCH();
  270. if (SG(server_context)) {
  271. #if MODULE_MAGIC_NUMBER >= 19970831
  272. aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
  273. #else
  274. log_error(message, ((request_rec *) SG(server_context))->server);
  275. #endif
  276. } else {
  277. fprintf(stderr, "%s\n", message);
  278. }
  279. }
  280. /* }}} */
  281. /* {{{ php_apache_request_shutdown
  282. */
  283. static void php_apache_request_shutdown(void *dummy)
  284. {
  285. TSRMLS_FETCH();
  286. php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
  287. if (AP(in_request)) {
  288. AP(in_request) = 0;
  289. php_request_shutdown(dummy);
  290. }
  291. SG(server_context) = NULL;
  292. /*
  293. * The server context (request) is NOT invalid by the time
  294. * run_cleanups() is called
  295. */
  296. }
  297. /* }}} */
  298. /* {{{ php_apache_sapi_activate
  299. */
  300. static int php_apache_sapi_activate(TSRMLS_D)
  301. {
  302. request_rec *r = (request_rec *) SG(server_context);
  303. /*
  304. * For the Apache module version, this bit of code registers a cleanup
  305. * function that gets triggered when our request pool is destroyed.
  306. * We need this because at any point in our code we can be interrupted
  307. * and that may happen before we have had time to free our memory.
  308. * The php_request_shutdown function needs to free all outstanding allocated
  309. * memory.
  310. */
  311. block_alarms();
  312. register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec);
  313. AP(in_request)=1;
  314. unblock_alarms();
  315. /* Override the default headers_only value - sometimes "GET" requests should actually only
  316. * send headers.
  317. */
  318. SG(request_info).headers_only = r->header_only;
  319. return SUCCESS;
  320. }
  321. /* }}} */
  322. /* {{{ php_apache_get_stat
  323. */
  324. static struct stat *php_apache_get_stat(TSRMLS_D)
  325. {
  326. return &((request_rec *) SG(server_context))->finfo;
  327. }
  328. /* }}} */
  329. /* {{{ php_apache_getenv
  330. */
  331. static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC)
  332. {
  333. if (SG(server_context) == NULL) {
  334. return NULL;
  335. }
  336. return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name);
  337. }
  338. /* }}} */
  339. /* {{{ sapi_apache_get_fd
  340. */
  341. static int sapi_apache_get_fd(int *nfd TSRMLS_DC)
  342. {
  343. #if PHP_APACHE_HAVE_CLIENT_FD
  344. request_rec *r = SG(server_context);
  345. int fd;
  346. fd = r->connection->client->fd;
  347. if (fd >= 0) {
  348. if (nfd) *nfd = fd;
  349. return SUCCESS;
  350. }
  351. #endif
  352. return FAILURE;
  353. }
  354. /* }}} */
  355. /* {{{ sapi_apache_force_http_10
  356. */
  357. static int sapi_apache_force_http_10(TSRMLS_D)
  358. {
  359. request_rec *r = SG(server_context);
  360. r->proto_num = HTTP_VERSION(1,0);
  361. return SUCCESS;
  362. }
  363. /* }}} */
  364. /* {{{ sapi_apache_get_target_uid
  365. */
  366. static int sapi_apache_get_target_uid(uid_t *obj TSRMLS_DC)
  367. {
  368. *obj = ap_user_id;
  369. return SUCCESS;
  370. }
  371. /* }}} */
  372. /* {{{ sapi_apache_get_target_gid
  373. */
  374. static int sapi_apache_get_target_gid(gid_t *obj TSRMLS_DC)
  375. {
  376. *obj = ap_group_id;
  377. return SUCCESS;
  378. }
  379. /* }}} */
  380. /* {{{ php_apache_get_request_time
  381. */
  382. static time_t php_apache_get_request_time(TSRMLS_D)
  383. {
  384. return ((request_rec *)SG(server_context))->request_time;
  385. }
  386. /* }}} */
  387. /* {{{ sapi_apache_child_terminate
  388. */
  389. static void sapi_apache_child_terminate(TSRMLS_D)
  390. {
  391. #ifndef MULTITHREAD
  392. ap_child_terminate((request_rec *)SG(server_context));
  393. #endif
  394. }
  395. /* }}} */
  396. /* {{{ sapi_module_struct apache_sapi_module
  397. */
  398. static sapi_module_struct apache_sapi_module = {
  399. "apache", /* name */
  400. "Apache", /* pretty name */
  401. php_apache_startup, /* startup */
  402. php_module_shutdown_wrapper, /* shutdown */
  403. php_apache_sapi_activate, /* activate */
  404. NULL, /* deactivate */
  405. sapi_apache_ub_write, /* unbuffered write */
  406. sapi_apache_flush, /* flush */
  407. php_apache_get_stat, /* get uid */
  408. php_apache_getenv, /* getenv */
  409. php_error, /* error handler */
  410. sapi_apache_header_handler, /* header handler */
  411. sapi_apache_send_headers, /* send headers handler */
  412. NULL, /* send header handler */
  413. sapi_apache_read_post, /* read POST data */
  414. sapi_apache_read_cookies, /* read Cookies */
  415. sapi_apache_register_server_variables, /* register server variables */
  416. php_apache_log_message, /* Log message */
  417. php_apache_get_request_time, /* Get request time */
  418. sapi_apache_child_terminate,
  419. NULL, /* php.ini path override */
  420. #ifdef PHP_WIN32
  421. NULL,
  422. NULL,
  423. #else
  424. block_alarms, /* Block interruptions */
  425. unblock_alarms, /* Unblock interruptions */
  426. #endif
  427. NULL, /* default post reader */
  428. NULL, /* treat data */
  429. NULL, /* exe location */
  430. 0, /* ini ignore */
  431. sapi_apache_get_fd,
  432. sapi_apache_force_http_10,
  433. sapi_apache_get_target_uid,
  434. sapi_apache_get_target_gid
  435. };
  436. /* }}} */
  437. /* {{{ php_restore_umask
  438. */
  439. static void php_restore_umask(void)
  440. {
  441. umask(saved_umask);
  442. }
  443. /* }}} */
  444. /* {{{ init_request_info
  445. */
  446. static void init_request_info(TSRMLS_D)
  447. {
  448. request_rec *r = ((request_rec *) SG(server_context));
  449. char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH");
  450. const char *authorization=NULL;
  451. char *tmp, *tmp_user;
  452. SG(request_info).query_string = r->args;
  453. SG(request_info).path_translated = r->filename;
  454. SG(request_info).request_uri = r->uri;
  455. SG(request_info).request_method = (char *)r->method;
  456. SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
  457. SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
  458. SG(sapi_headers).http_response_code = r->status;
  459. SG(request_info).proto_num = r->proto_num;
  460. if (r->headers_in) {
  461. authorization = table_get(r->headers_in, "Authorization");
  462. }
  463. SG(request_info).auth_user = NULL;
  464. SG(request_info).auth_password = NULL;
  465. SG(request_info).auth_digest = NULL;
  466. if (authorization) {
  467. char *p = getword(r->pool, &authorization, ' ');
  468. if (!strcasecmp(p, "Basic")) {
  469. tmp = uudecode(r->pool, authorization);
  470. tmp_user = getword_nulls_nc(r->pool, &tmp, ':');
  471. if (tmp_user) {
  472. r->connection->user = pstrdup(r->connection->pool, tmp_user);
  473. r->connection->ap_auth_type = "Basic";
  474. SG(request_info).auth_user = estrdup(tmp_user);
  475. }
  476. if (tmp) {
  477. SG(request_info).auth_password = estrdup(tmp);
  478. }
  479. } else if (!strcasecmp(p, "Digest")) {
  480. r->connection->ap_auth_type = "Digest";
  481. SG(request_info).auth_digest = estrdup(authorization);
  482. }
  483. }
  484. }
  485. /* }}} */
  486. /* {{{ php_apache_alter_ini_entries
  487. */
  488. static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC)
  489. {
  490. zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, per_dir_entry->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE);
  491. return 0;
  492. }
  493. /* }}} */
  494. /* {{{ php_apache_get_default_mimetype
  495. */
  496. static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC)
  497. {
  498. char *mimetype;
  499. /* Assume output will be of the default MIME type. Individual
  500. scripts may change this later. */
  501. char *tmpmimetype;
  502. tmpmimetype = sapi_get_default_content_type(TSRMLS_C);
  503. mimetype = pstrdup(r->pool, tmpmimetype);
  504. efree(tmpmimetype);
  505. return mimetype;
  506. }
  507. /* }}} */
  508. /* {{{ send_php
  509. */
  510. static int send_php(request_rec *r, int display_source_mode, char *filename)
  511. {
  512. int retval;
  513. HashTable *per_dir_conf;
  514. TSRMLS_FETCH();
  515. if (AP(in_request)) {
  516. zend_file_handle fh;
  517. fh.filename = r->filename;
  518. fh.opened_path = NULL;
  519. fh.free_filename = 0;
  520. fh.type = ZEND_HANDLE_FILENAME;
  521. zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh);
  522. return OK;
  523. }
  524. SG(server_context) = r;
  525. zend_first_try {
  526. /* Make sure file exists */
  527. if (filename == NULL && r->finfo.st_mode == 0) {
  528. return DECLINED;
  529. }
  530. per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php6_module);
  531. if (per_dir_conf) {
  532. zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
  533. }
  534. /* If PHP parser engine has been turned off with an "engine off"
  535. * directive, then decline to handle this request
  536. */
  537. if (!AP(engine)) {
  538. r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
  539. zend_try {
  540. zend_ini_deactivate(TSRMLS_C);
  541. } zend_end_try();
  542. return DECLINED;
  543. }
  544. if (filename == NULL) {
  545. filename = r->filename;
  546. }
  547. /* Apache 1.2 has a more complex mechanism for reading POST data */
  548. #if MODULE_MAGIC_NUMBER > 19961007
  549. if ((retval = setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) {
  550. zend_try {
  551. zend_ini_deactivate(TSRMLS_C);
  552. } zend_end_try();
  553. return retval;
  554. }
  555. #endif
  556. if (AP(last_modified)) {
  557. #if MODULE_MAGIC_NUMBER < 19970912
  558. if ((retval = set_last_modified(r, r->finfo.st_mtime))) {
  559. zend_try {
  560. zend_ini_deactivate(TSRMLS_C);
  561. } zend_end_try();
  562. return retval;
  563. }
  564. #else
  565. update_mtime (r, r->finfo.st_mtime);
  566. set_last_modified(r);
  567. set_etag(r);
  568. #endif
  569. }
  570. /* Assume output will be of the default MIME type. Individual
  571. scripts may change this later in the request. */
  572. r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
  573. /* Init timeout */
  574. hard_timeout("send", r);
  575. php_save_umask();
  576. add_common_vars(r);
  577. add_cgi_vars(r);
  578. init_request_info(TSRMLS_C);
  579. apache_php_module_main(r, display_source_mode TSRMLS_CC);
  580. /* Done, restore umask, turn off timeout, close file and return */
  581. php_restore_umask();
  582. kill_timeout(r);
  583. } zend_end_try();
  584. return OK;
  585. }
  586. /* }}} */
  587. /* {{{ send_parsed_php
  588. */
  589. static int send_parsed_php(request_rec * r)
  590. {
  591. int result = send_php(r, 0, NULL);
  592. TSRMLS_FETCH();
  593. ap_table_setn(r->notes, "mod_php_memory_usage",
  594. ap_psprintf(r->pool, "%lu", zend_memory_peak_usage(1 TSRMLS_CC)));
  595. return result;
  596. }
  597. /* }}} */
  598. /* {{{ send_parsed_php_source
  599. */
  600. static int send_parsed_php_source(request_rec * r)
  601. {
  602. return send_php(r, 1, NULL);
  603. }
  604. /* }}} */
  605. /* {{{ destroy_per_dir_entry
  606. */
  607. static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  608. {
  609. free(per_dir_entry->key);
  610. free(per_dir_entry->value);
  611. }
  612. /* }}} */
  613. /* {{{ copy_per_dir_entry
  614. */
  615. static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  616. {
  617. php_per_dir_entry tmp = *per_dir_entry;
  618. per_dir_entry->key = (char *) malloc(tmp.key_length+1);
  619. memcpy(per_dir_entry->key, tmp.key, tmp.key_length);
  620. per_dir_entry->key[per_dir_entry->key_length] = 0;
  621. per_dir_entry->value = (char *) malloc(tmp.value_length+1);
  622. memcpy(per_dir_entry->value, tmp.value, tmp.value_length);
  623. per_dir_entry->value[per_dir_entry->value_length] = 0;
  624. }
  625. /* }}} */
  626. /* {{{ should_overwrite_per_dir_entry
  627. */
  628. static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_per_dir_entry *new_per_dir_entry, zend_hash_key *hash_key, void *pData)
  629. {
  630. php_per_dir_entry *orig_per_dir_entry;
  631. if (zend_u_hash_find(target_ht, hash_key->type, hash_key->arKey, hash_key->nKeyLength, (void **) &orig_per_dir_entry)==FAILURE) {
  632. return 1; /* does not exist in dest, copy from source */
  633. }
  634. if (orig_per_dir_entry->type==PHP_INI_SYSTEM
  635. && new_per_dir_entry->type!=PHP_INI_SYSTEM) {
  636. return 0;
  637. } else {
  638. return 1;
  639. }
  640. }
  641. /* }}} */
  642. /* {{{ php_destroy_per_dir_info
  643. */
  644. static void php_destroy_per_dir_info(HashTable *per_dir_info)
  645. {
  646. zend_hash_destroy(per_dir_info);
  647. free(per_dir_info);
  648. }
  649. /* }}} */
  650. /* {{{ php_create_dir
  651. */
  652. static void *php_create_dir(pool *p, char *dummy)
  653. {
  654. HashTable *per_dir_info;
  655. per_dir_info = (HashTable *) malloc(sizeof(HashTable));
  656. zend_hash_init_ex(per_dir_info, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0);
  657. register_cleanup(p, (void *) per_dir_info, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) zend_hash_destroy);
  658. return per_dir_info;
  659. }
  660. /* }}} */
  661. /* {{{ php_merge_dir
  662. */
  663. static void *php_merge_dir(pool *p, void *basev, void *addv)
  664. {
  665. /* This function *must* not modify addv or basev */
  666. HashTable *new;
  667. /* need a copy of addv to merge */
  668. new = php_create_dir(p, "php_merge_dir");
  669. zend_hash_copy(new, (HashTable *) basev, (copy_ctor_func_t) copy_per_dir_entry, NULL, sizeof(php_per_dir_entry));
  670. zend_hash_merge_ex(new, (HashTable *) addv, (copy_ctor_func_t) copy_per_dir_entry, sizeof(php_per_dir_entry), (merge_checker_func_t) should_overwrite_per_dir_entry, NULL);
  671. return new;
  672. }
  673. /* }}} */
  674. /* {{{ php_apache_value_handler_ex
  675. */
  676. static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
  677. {
  678. php_per_dir_entry per_dir_entry;
  679. if (!apache_php_initialized) {
  680. apache_php_initialized = 1;
  681. #ifdef ZTS
  682. tsrm_startup(1, 1, 0, NULL);
  683. #endif
  684. sapi_startup(&apache_sapi_module);
  685. php_apache_startup(&apache_sapi_module);
  686. }
  687. per_dir_entry.type = mode;
  688. per_dir_entry.htaccess = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0);
  689. if (strcasecmp(arg2, "none") == 0) {
  690. arg2 = "";
  691. }
  692. per_dir_entry.key_length = strlen(arg1);
  693. per_dir_entry.value_length = strlen(arg2);
  694. per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1);
  695. memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);
  696. per_dir_entry.key[per_dir_entry.key_length] = 0;
  697. per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1);
  698. memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length);
  699. per_dir_entry.value[per_dir_entry.value_length] = 0;
  700. zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL);
  701. return NULL;
  702. }
  703. /* }}} */
  704. /* {{{ php_apache_value_handler
  705. */
  706. static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  707. {
  708. return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
  709. }
  710. /* }}} */
  711. /* {{{ php_apache_admin_value_handler
  712. */
  713. static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  714. {
  715. return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
  716. }
  717. /* }}} */
  718. /* {{{ php_apache_flag_handler_ex
  719. */
  720. static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
  721. {
  722. char bool_val[2];
  723. if (!strcasecmp(arg2, "On") || (arg2[0] == '1' && arg2[1] == '\0')) {
  724. bool_val[0] = '1';
  725. } else {
  726. bool_val[0] = '0';
  727. }
  728. bool_val[1] = 0;
  729. return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode);
  730. }
  731. /* }}} */
  732. /* {{{ php_apache_flag_handler
  733. */
  734. static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  735. {
  736. return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
  737. }
  738. /* }}} */
  739. /* {{{ php_apache_admin_flag_handler
  740. */
  741. static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  742. {
  743. return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
  744. }
  745. /* }}} */
  746. /* {{{ php_apache_phpini_set
  747. */
  748. static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg)
  749. {
  750. if (apache_sapi_module.php_ini_path_override) {
  751. return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored";
  752. }
  753. apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg);
  754. return NULL;
  755. }
  756. /* }}} */
  757. /* {{{ int php_xbithack_handler(request_rec * r)
  758. */
  759. static int php_xbithack_handler(request_rec * r)
  760. {
  761. HashTable *per_dir_conf;
  762. TSRMLS_FETCH();
  763. if (!(r->finfo.st_mode & S_IXUSR)) {
  764. return DECLINED;
  765. }
  766. per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php6_module);
  767. if (per_dir_conf) {
  768. zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
  769. }
  770. if(!AP(xbithack)) {
  771. zend_try {
  772. zend_ini_deactivate(TSRMLS_C);
  773. } zend_end_try();
  774. return DECLINED;
  775. }
  776. return send_parsed_php(r);
  777. }
  778. /* }}} */
  779. /* {{{ apache_php_module_shutdown_wrapper
  780. */
  781. static void apache_php_module_shutdown_wrapper(void)
  782. {
  783. apache_php_initialized = 0;
  784. apache_sapi_module.shutdown(&apache_sapi_module);
  785. #if MODULE_MAGIC_NUMBER >= 19970728
  786. /* This function is only called on server exit if the apache API
  787. * child_exit handler exists, so shutdown globally
  788. */
  789. sapi_shutdown();
  790. #endif
  791. #ifdef ZTS
  792. tsrm_shutdown();
  793. #endif
  794. }
  795. /* }}} */
  796. #if MODULE_MAGIC_NUMBER >= 19970728
  797. /* {{{ php_child_exit_handler
  798. */
  799. static void php_child_exit_handler(server_rec *s, pool *p)
  800. {
  801. /* apache_php_initialized = 0; */
  802. apache_sapi_module.shutdown(&apache_sapi_module);
  803. #ifdef ZTS
  804. tsrm_shutdown();
  805. #endif
  806. }
  807. /* }}} */
  808. #endif
  809. /* {{{ void php_init_handler(server_rec *s, pool *p)
  810. */
  811. static void php_init_handler(server_rec *s, pool *p)
  812. {
  813. register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);
  814. if (!apache_php_initialized) {
  815. apache_php_initialized = 1;
  816. #ifdef ZTS
  817. tsrm_startup(1, 1, 0, NULL);
  818. #endif
  819. sapi_startup(&apache_sapi_module);
  820. php_apache_startup(&apache_sapi_module);
  821. }
  822. #if MODULE_MAGIC_NUMBER >= 19980527
  823. {
  824. TSRMLS_FETCH();
  825. if (PG(expose_php)) {
  826. ap_add_version_component("PHP/" PHP_VERSION);
  827. }
  828. }
  829. #endif
  830. }
  831. /* }}} */
  832. /* {{{ handler_rec php_handlers[]
  833. */
  834. handler_rec php_handlers[] =
  835. {
  836. {"application/x-httpd-php", send_parsed_php},
  837. {"application/x-httpd-php-source", send_parsed_php_source},
  838. {"text/html", php_xbithack_handler},
  839. {NULL}
  840. };
  841. /* }}} */
  842. /* {{{ command_rec php_commands[]
  843. */
  844. command_rec php_commands[] =
  845. {
  846. {"php_value", php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"},
  847. {"php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"},
  848. {"php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"},
  849. {"php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"},
  850. {"PHPINIDir", php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"},
  851. {NULL}
  852. };
  853. /* }}} */
  854. /* {{{ odule MODULE_VAR_EXPORT php6_module
  855. */
  856. module MODULE_VAR_EXPORT php6_module =
  857. {
  858. MODULE_MAGIC_NUMBER_MAJOR,
  859. MODULE_MAGIC_NUMBER_MINOR,
  860. -1,
  861. "mod_php6.c",
  862. NULL,
  863. NULL,
  864. MODULE_MAGIC_COOKIE,
  865. php_init_handler, /* initializer */
  866. php_create_dir, /* per-directory config creator */
  867. php_merge_dir, /* dir merger */
  868. NULL, /* per-server config creator */
  869. NULL, /* merge server config */
  870. php_commands, /* command table */
  871. php_handlers, /* handlers */
  872. NULL, /* filename translation */
  873. NULL, /* check_user_id */
  874. NULL, /* check auth */
  875. NULL, /* check access */
  876. NULL, /* type_checker */
  877. NULL, /* fixups */
  878. NULL /* logger */
  879. #if MODULE_MAGIC_NUMBER >= 19970103
  880. , NULL /* header parser */
  881. #endif
  882. #if MODULE_MAGIC_NUMBER >= 19970719
  883. , NULL /* child_init */
  884. #endif
  885. #if MODULE_MAGIC_NUMBER >= 19970728
  886. , php_child_exit_handler /* child_exit */
  887. #endif
  888. #if MODULE_MAGIC_NUMBER >= 19970902
  889. , NULL /* post read-request */
  890. #endif
  891. };
  892. /* }}} */
  893. /*
  894. * Local variables:
  895. * tab-width: 4
  896. * c-basic-offset: 4
  897. * End:
  898. * vim600: sw=4 ts=4 fdm=marker
  899. * vim<600: sw=4 ts=4
  900. */