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.

916 lines
24 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
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
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
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
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
26 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
27 years ago
27 years ago
25 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
26 years ago
26 years ago
26 years ago
26 years ago
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
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
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
27 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP version 4.0 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2001 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. | 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. #define NO_REGEX_EXTRA_H
  22. #ifdef WIN32
  23. #include <winsock2.h>
  24. #include <stddef.h>
  25. #endif
  26. #include "zend.h"
  27. #include "php.h"
  28. #include "php_variables.h"
  29. #include "httpd.h"
  30. #include "http_config.h"
  31. #if MODULE_MAGIC_NUMBER > 19980712
  32. # include "ap_compat.h"
  33. #else
  34. # if MODULE_MAGIC_NUMBER > 19980324
  35. # include "compat.h"
  36. # endif
  37. #endif
  38. #include "http_core.h"
  39. #include "http_main.h"
  40. #include "http_protocol.h"
  41. #include "http_request.h"
  42. #include "http_log.h"
  43. #include "php_ini.h"
  44. #include "php_globals.h"
  45. #include "SAPI.h"
  46. #include "php_main.h"
  47. #include "zend_compile.h"
  48. #include "zend_execute.h"
  49. #include "zend_highlight.h"
  50. #include "zend_indent.h"
  51. #include "ext/standard/php_standard.h"
  52. #include "util_script.h"
  53. #include "mod_php4.h"
  54. #undef shutdown
  55. /* {{{ Prototypes
  56. */
  57. int apache_php_module_main(request_rec *r, int display_source_mode CLS_DC ELS_DC PLS_DC SLS_DC);
  58. void php_save_umask(void);
  59. void php_restore_umask(void);
  60. int sapi_apache_read_post(char *buffer, uint count_bytes SLS_DC);
  61. char *sapi_apache_read_cookies(SLS_D);
  62. int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers SLS_DC);
  63. int sapi_apache_send_headers(sapi_headers_struct *sapi_headers SLS_DC);
  64. static int send_php(request_rec *r, int display_source_mode, char *filename);
  65. static int send_parsed_php(request_rec * r);
  66. static int send_parsed_php_source(request_rec * r);
  67. int php_xbithack_handler(request_rec * r);
  68. void php_init_handler(server_rec *s, pool *p);
  69. /* }}} */
  70. #if MODULE_MAGIC_NUMBER >= 19970728
  71. static void php_child_exit_handler(server_rec *s, pool *p);
  72. #endif
  73. #if MODULE_MAGIC_NUMBER > 19961007
  74. #define CONST_PREFIX const
  75. #else
  76. #define CONST_PREFIX
  77. #endif
  78. CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
  79. CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  80. CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  81. CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  82. CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
  83. CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
  84. /* ### these should be defined in mod_php4.h or somewhere else */
  85. #define USE_PATH 1
  86. #define IGNORE_URL 2
  87. module MODULE_VAR_EXPORT php4_module;
  88. int saved_umask;
  89. static unsigned char apache_php_initialized;
  90. typedef struct _php_per_dir_entry {
  91. char *key;
  92. char *value;
  93. uint key_length;
  94. uint value_length;
  95. int type;
  96. } php_per_dir_entry;
  97. /* some systems are missing these from their header files */
  98. /* {{{ php_save_umask
  99. */
  100. void php_save_umask(void)
  101. {
  102. saved_umask = umask(077);
  103. umask(saved_umask);
  104. }
  105. /* }}} */
  106. /* {{{ sapi_apache_ub_write
  107. */
  108. static int sapi_apache_ub_write(const char *str, uint str_length)
  109. {
  110. int ret=0;
  111. SLS_FETCH();
  112. if (SG(server_context)) {
  113. ret = rwrite(str, str_length, (request_rec *) SG(server_context));
  114. }
  115. if (ret != str_length) {
  116. php_handle_aborted_connection();
  117. }
  118. return ret;
  119. }
  120. /* }}} */
  121. /* {{{ sapi_apache_flush
  122. */
  123. static void sapi_apache_flush(void *server_context)
  124. {
  125. if (server_context) {
  126. #if MODULE_MAGIC_NUMBER > 19970110
  127. rflush((request_rec *) server_context);
  128. #else
  129. bflush((request_rec *) server_context->connection->client);
  130. #endif
  131. }
  132. }
  133. /* }}} */
  134. /* {{{ sapi_apache_read_post
  135. */
  136. int sapi_apache_read_post(char *buffer, uint count_bytes SLS_DC)
  137. {
  138. uint total_read_bytes=0, read_bytes;
  139. request_rec *r = (request_rec *) SG(server_context);
  140. void (*handler)(int);
  141. handler = signal(SIGPIPE, SIG_IGN);
  142. while (total_read_bytes<count_bytes) {
  143. hard_timeout("Read POST information", r); /* start timeout timer */
  144. read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes);
  145. reset_timeout(r);
  146. if (read_bytes<=0) {
  147. break;
  148. }
  149. total_read_bytes += read_bytes;
  150. }
  151. signal(SIGPIPE, handler);
  152. return total_read_bytes;
  153. }
  154. /* }}} */
  155. /* {{{ sapi_apache_read_cookies
  156. */
  157. char *sapi_apache_read_cookies(SLS_D)
  158. {
  159. return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE");
  160. }
  161. /* }}} */
  162. /* {{{ sapi_apache_header_handler
  163. */
  164. int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers SLS_DC)
  165. {
  166. char *header_name, *header_content, *p;
  167. request_rec *r = (request_rec *) SG(server_context);
  168. header_name = sapi_header->header;
  169. header_content = p = strchr(header_name, ':');
  170. if (!p) {
  171. return 0;
  172. }
  173. *p = 0;
  174. do {
  175. header_content++;
  176. } while (*header_content==' ');
  177. if (!strcasecmp(header_name, "Content-Type")) {
  178. r->content_type = pstrdup(r->pool, header_content);
  179. } else if (!strcasecmp(header_name, "Set-Cookie")) {
  180. table_add(r->headers_out, header_name, header_content);
  181. } else {
  182. table_set(r->headers_out, header_name, header_content);
  183. }
  184. *p = ':'; /* a well behaved header handler shouldn't change its original arguments */
  185. efree(sapi_header->header);
  186. return 0; /* don't use the default SAPI mechanism, Apache duplicates this functionality */
  187. }
  188. /* }}} */
  189. /* {{{ sapi_apache_send_headers
  190. */
  191. int sapi_apache_send_headers(sapi_headers_struct *sapi_headers SLS_DC)
  192. {
  193. if(SG(server_context) == NULL) { /* server_context is not here anymore */
  194. return SAPI_HEADER_SEND_FAILED;
  195. }
  196. ((request_rec *) SG(server_context))->status = SG(sapi_headers).http_response_code;
  197. send_http_header((request_rec *) SG(server_context));
  198. return SAPI_HEADER_SENT_SUCCESSFULLY;
  199. }
  200. /* }}} */
  201. /* {{{ sapi_apache_register_server_variables
  202. */
  203. static void sapi_apache_register_server_variables(zval *track_vars_array ELS_DC SLS_DC PLS_DC)
  204. {
  205. register int i;
  206. array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env);
  207. table_entry *elts = (table_entry *) arr->elts;
  208. zval **path_translated;
  209. HashTable *symbol_table;
  210. for (i = 0; i < arr->nelts; i++) {
  211. char *val;
  212. if (elts[i].val) {
  213. val = elts[i].val;
  214. } else {
  215. val = empty_string;
  216. }
  217. php_register_variable(elts[i].key, val, track_vars_array ELS_CC PLS_CC);
  218. }
  219. /* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
  220. if (track_vars_array) {
  221. symbol_table = track_vars_array->value.ht;
  222. } else if (PG(register_globals)) {
  223. /* should never happen nowadays */
  224. symbol_table = EG(active_symbol_table);
  225. } else {
  226. symbol_table = NULL;
  227. }
  228. if (symbol_table
  229. && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"))
  230. && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) {
  231. php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array ELS_CC PLS_CC);
  232. }
  233. php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array ELS_CC PLS_CC);
  234. }
  235. /* }}} */
  236. /* {{{ php_apache_startup
  237. */
  238. static int php_apache_startup(sapi_module_struct *sapi_module)
  239. {
  240. if (php_module_startup(sapi_module) == FAILURE
  241. || zend_startup_module(&apache_module_entry) == FAILURE) {
  242. return FAILURE;
  243. } else {
  244. return SUCCESS;
  245. }
  246. }
  247. /* }}} */
  248. /* {{{ php_apache_log_message
  249. */
  250. static void php_apache_log_message(char *message)
  251. {
  252. SLS_FETCH();
  253. if (SG(server_context)) {
  254. #if MODULE_MAGIC_NUMBER >= 19970831
  255. aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
  256. #else
  257. log_error(message, ((request_rec *) SG(server_context))->server);
  258. #endif
  259. } else {
  260. fprintf(stderr, "%s", message);
  261. fprintf(stderr, "\n");
  262. }
  263. }
  264. /* }}} */
  265. /* {{{ php_apache_request_shutdown
  266. */
  267. static void php_apache_request_shutdown(void *dummy)
  268. {
  269. SLS_FETCH();
  270. APLS_FETCH();
  271. AP(in_request)=0;
  272. SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */
  273. php_request_shutdown(dummy);
  274. }
  275. /* }}} */
  276. /* {{{ php_apache_sapi_activate
  277. */
  278. static int php_apache_sapi_activate(SLS_D)
  279. {
  280. request_rec *r = (request_rec *) SG(server_context);
  281. APLS_FETCH();
  282. /*
  283. * For the Apache module version, this bit of code registers a cleanup
  284. * function that gets triggered when our request pool is destroyed.
  285. * We need this because at any point in our code we can be interrupted
  286. * and that may happen before we have had time to free our memory.
  287. * The php_request_shutdown function needs to free all outstanding allocated
  288. * memory.
  289. */
  290. block_alarms();
  291. register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec);
  292. AP(in_request)=1;
  293. unblock_alarms();
  294. /* Override the default headers_only value - sometimes "GET" requests should actually only
  295. * send headers.
  296. */
  297. SG(request_info).headers_only = r->header_only;
  298. return SUCCESS;
  299. }
  300. /* }}} */
  301. /* {{{ php_apache_get_stat
  302. */
  303. static struct stat *php_apache_get_stat(SLS_D)
  304. {
  305. return &((request_rec *) SG(server_context))->finfo;
  306. }
  307. /* }}} */
  308. /* {{{ php_apache_getenv
  309. */
  310. static char *php_apache_getenv(char *name, size_t name_len SLS_DC)
  311. {
  312. return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name);
  313. }
  314. /* }}} */
  315. /* {{{ sapi_module_struct apache_sapi_module
  316. */
  317. static sapi_module_struct apache_sapi_module = {
  318. "apache", /* name */
  319. "Apache", /* pretty name */
  320. php_apache_startup, /* startup */
  321. php_module_shutdown_wrapper, /* shutdown */
  322. php_apache_sapi_activate, /* activate */
  323. NULL, /* deactivate */
  324. sapi_apache_ub_write, /* unbuffered write */
  325. sapi_apache_flush, /* flush */
  326. php_apache_get_stat, /* get uid */
  327. php_apache_getenv, /* getenv */
  328. php_error, /* error handler */
  329. sapi_apache_header_handler, /* header handler */
  330. sapi_apache_send_headers, /* send headers handler */
  331. NULL, /* send header handler */
  332. sapi_apache_read_post, /* read POST data */
  333. sapi_apache_read_cookies, /* read Cookies */
  334. sapi_apache_register_server_variables, /* register server variables */
  335. php_apache_log_message, /* Log message */
  336. NULL, /* php.ini path override */
  337. #ifdef PHP_WIN32
  338. NULL,
  339. NULL,
  340. #else
  341. block_alarms, /* Block interruptions */
  342. unblock_alarms, /* Unblock interruptions */
  343. #endif
  344. STANDARD_SAPI_MODULE_PROPERTIES
  345. };
  346. /* }}} */
  347. /* {{{ php_restore_umask
  348. */
  349. void php_restore_umask(void)
  350. {
  351. umask(saved_umask);
  352. }
  353. /* }}} */
  354. /* {{{ init_request_info
  355. */
  356. static void init_request_info(SLS_D)
  357. {
  358. request_rec *r = ((request_rec *) SG(server_context));
  359. char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH");
  360. const char *authorization=NULL;
  361. char *tmp;
  362. SG(request_info).query_string = r->args;
  363. SG(request_info).path_translated = r->filename;
  364. SG(request_info).request_uri = r->uri;
  365. SG(request_info).request_method = (char *)r->method;
  366. SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
  367. SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
  368. SG(sapi_headers).http_response_code = r->status;
  369. if (r->headers_in) {
  370. authorization = table_get(r->headers_in, "Authorization");
  371. }
  372. if (authorization
  373. /* && !auth_type(r) */
  374. && !strcasecmp(getword(r->pool, &authorization, ' '), "Basic")) {
  375. tmp = uudecode(r->pool, authorization);
  376. SG(request_info).auth_user = getword_nulls_nc(r->pool, &tmp, ':');
  377. if (SG(request_info).auth_user) {
  378. r->connection->user = pstrdup(r->connection->pool,SG(request_info).auth_user);
  379. r->connection->ap_auth_type = "Basic";
  380. SG(request_info).auth_user = estrdup(SG(request_info).auth_user);
  381. }
  382. SG(request_info).auth_password = tmp;
  383. if (SG(request_info).auth_password) {
  384. SG(request_info).auth_password = estrdup(SG(request_info).auth_password);
  385. }
  386. } else {
  387. SG(request_info).auth_user = NULL;
  388. SG(request_info).auth_password = NULL;
  389. }
  390. }
  391. /* }}} */
  392. /* {{{ php_apache_alter_ini_entries
  393. */
  394. static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry)
  395. {
  396. 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, PHP_INI_STAGE_ACTIVATE);
  397. return 0;
  398. }
  399. /* }}} */
  400. /* {{{ php_apache_get_default_mimetype
  401. */
  402. static char *php_apache_get_default_mimetype(request_rec *r SLS_DC)
  403. {
  404. char *mimetype;
  405. if (SG(default_mimetype) || SG(default_charset)) {
  406. /* Assume output will be of the default MIME type. Individual
  407. scripts may change this later. */
  408. char *tmpmimetype;
  409. tmpmimetype = sapi_get_default_content_type(SLS_C);
  410. mimetype = pstrdup(r->pool, tmpmimetype);
  411. efree(tmpmimetype);
  412. } else {
  413. mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET;
  414. }
  415. return mimetype;
  416. }
  417. /* }}} */
  418. /* {{{ send_php
  419. */
  420. static int send_php(request_rec *r, int display_source_mode, char *filename)
  421. {
  422. int retval;
  423. HashTable *per_dir_conf;
  424. SLS_FETCH();
  425. ELS_FETCH();
  426. CLS_FETCH();
  427. PLS_FETCH();
  428. APLS_FETCH();
  429. if (AP(in_request)) {
  430. zend_file_handle fh;
  431. fh.filename = r->filename;
  432. fh.opened_path = NULL;
  433. fh.free_filename = 0;
  434. fh.type = ZEND_HANDLE_FILENAME;
  435. zend_execute_scripts(ZEND_INCLUDE CLS_CC ELS_CC, 1, &fh);
  436. return OK;
  437. }
  438. if (setjmp(EG(bailout))!=0) {
  439. return OK;
  440. }
  441. /* We don't accept OPTIONS requests, but take everything else */
  442. if (r->method_number == M_OPTIONS) {
  443. r->allowed |= (1 << METHODS) - 1;
  444. return DECLINED;
  445. }
  446. /* Make sure file exists */
  447. if (filename == NULL && r->finfo.st_mode == 0) {
  448. return DECLINED;
  449. }
  450. per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php4_module);
  451. if (per_dir_conf) {
  452. zend_hash_apply((HashTable *) per_dir_conf, (int (*)(void *)) php_apache_alter_ini_entries);
  453. }
  454. /* If PHP parser engine has been turned off with an "engine off"
  455. * directive, then decline to handle this request
  456. */
  457. if (!AP(engine)) {
  458. r->content_type = php_apache_get_default_mimetype(r SLS_CC);
  459. r->allowed |= (1 << METHODS) - 1;
  460. if (setjmp(EG(bailout))==0) {
  461. zend_ini_deactivate(ELS_C);
  462. }
  463. return DECLINED;
  464. }
  465. if (filename == NULL) {
  466. filename = r->filename;
  467. }
  468. /* Apache 1.2 has a more complex mechanism for reading POST data */
  469. #if MODULE_MAGIC_NUMBER > 19961007
  470. if ((retval = setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
  471. if (setjmp(EG(bailout))==0) {
  472. zend_ini_deactivate(ELS_C);
  473. }
  474. return retval;
  475. }
  476. #endif
  477. if (AP(last_modified)) {
  478. #if MODULE_MAGIC_NUMBER < 19970912
  479. if ((retval = set_last_modified(r, r->finfo.st_mtime))) {
  480. if (setjmp(EG(bailout))==0) {
  481. zend_ini_deactivate(ELS_C);
  482. }
  483. return retval;
  484. }
  485. #else
  486. update_mtime (r, r->finfo.st_mtime);
  487. set_last_modified(r);
  488. set_etag(r);
  489. #endif
  490. }
  491. /* Assume output will be of the default MIME type. Individual
  492. scripts may change this later in the request. */
  493. r->content_type = php_apache_get_default_mimetype(r SLS_CC);
  494. /* Init timeout */
  495. hard_timeout("send", r);
  496. SG(server_context) = r;
  497. php_save_umask();
  498. add_common_vars(r);
  499. add_cgi_vars(r);
  500. init_request_info(SLS_C);
  501. apache_php_module_main(r, display_source_mode CLS_CC ELS_CC PLS_CC SLS_CC);
  502. /* Done, restore umask, turn off timeout, close file and return */
  503. php_restore_umask();
  504. kill_timeout(r);
  505. return OK;
  506. }
  507. /* }}} */
  508. /* {{{ send_parsed_php
  509. */
  510. static int send_parsed_php(request_rec * r)
  511. {
  512. int result = send_php(r, 0, NULL);
  513. #if MEMORY_LIMIT
  514. {
  515. char mem_usage[ 32 ];
  516. ALS_FETCH()
  517. sprintf(mem_usage,"%u", (int) AG(allocated_memory_peak));
  518. ap_table_setn(r->notes, "mod_php_memory_usage", ap_pstrdup(r->pool,mem_usage));
  519. }
  520. #endif
  521. return result;
  522. }
  523. /* }}} */
  524. /* {{{ send_parsed_php_source
  525. */
  526. static int send_parsed_php_source(request_rec * r)
  527. {
  528. return send_php(r, 1, NULL);
  529. }
  530. /* }}} */
  531. /* {{{ estroy_per_dir_entry
  532. */
  533. static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  534. {
  535. free(per_dir_entry->key);
  536. free(per_dir_entry->value);
  537. }
  538. /* }}} */
  539. /* {{{ copy_per_dir_entry
  540. */
  541. static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  542. {
  543. php_per_dir_entry tmp = *per_dir_entry;
  544. per_dir_entry->key = (char *) malloc(tmp.key_length+1);
  545. memcpy(per_dir_entry->key, tmp.key, tmp.key_length);
  546. per_dir_entry->key[per_dir_entry->key_length] = 0;
  547. per_dir_entry->value = (char *) malloc(tmp.value_length+1);
  548. memcpy(per_dir_entry->value, tmp.value, tmp.value_length);
  549. per_dir_entry->value[per_dir_entry->value_length] = 0;
  550. }
  551. /* }}} */
  552. /* {{{ should_overwrite_per_dir_entry
  553. */
  554. static zend_bool should_overwrite_per_dir_entry(php_per_dir_entry *orig_per_dir_entry, php_per_dir_entry *new_per_dir_entry)
  555. {
  556. if (new_per_dir_entry->type==PHP_INI_SYSTEM
  557. && orig_per_dir_entry->type!=PHP_INI_SYSTEM) {
  558. return 1;
  559. } else {
  560. return 0;
  561. }
  562. }
  563. /* }}} */
  564. /* {{{ php_destroy_per_dir_info
  565. */
  566. static void php_destroy_per_dir_info(HashTable *per_dir_info)
  567. {
  568. zend_hash_destroy(per_dir_info);
  569. free(per_dir_info);
  570. }
  571. /* }}} */
  572. /* {{{ php_create_dir
  573. */
  574. static void *php_create_dir(pool *p, char *dummy)
  575. {
  576. HashTable *per_dir_info;
  577. per_dir_info = (HashTable *) malloc(sizeof(HashTable));
  578. zend_hash_init(per_dir_info, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1);
  579. register_cleanup(p, (void *) per_dir_info, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) zend_hash_destroy);
  580. return per_dir_info;
  581. }
  582. /* }}} */
  583. /* {{{ php_merge_dir
  584. */
  585. static void *php_merge_dir(pool *p, void *basev, void *addv)
  586. {
  587. /* This function *must* return addv, and not modify basev */
  588. zend_hash_merge_ex((HashTable *) addv, (HashTable *) basev, (copy_ctor_func_t) copy_per_dir_entry, sizeof(php_per_dir_entry), (zend_bool (*)(void *, void *)) should_overwrite_per_dir_entry);
  589. return addv;
  590. }
  591. /* }}} */
  592. /* {{{ php_apache_value_handler_ex
  593. */
  594. CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
  595. {
  596. php_per_dir_entry per_dir_entry;
  597. if (!apache_php_initialized) {
  598. apache_php_initialized = 1;
  599. #ifdef ZTS
  600. tsrm_startup(1, 1, 0, NULL);
  601. #endif
  602. sapi_startup(&apache_sapi_module);
  603. php_apache_startup(&apache_sapi_module);
  604. }
  605. per_dir_entry.type = mode;
  606. if (strcasecmp(arg2, "none") == 0) {
  607. arg2 = "";
  608. }
  609. per_dir_entry.key_length = strlen(arg1);
  610. per_dir_entry.value_length = strlen(arg2);
  611. per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1);
  612. memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);
  613. per_dir_entry.key[per_dir_entry.key_length] = 0;
  614. per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1);
  615. memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length);
  616. per_dir_entry.value[per_dir_entry.value_length] = 0;
  617. zend_hash_update((HashTable *) conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL);
  618. return NULL;
  619. }
  620. /* }}} */
  621. /* {{{ php_apache_value_handler
  622. */
  623. CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  624. {
  625. return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
  626. }
  627. /* }}} */
  628. /* {{{ php_apache_admin_value_handler
  629. */
  630. CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  631. {
  632. return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
  633. }
  634. /* }}} */
  635. /* {{{ php_apache_flag_handler_ex
  636. */
  637. CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
  638. {
  639. char bool_val[2];
  640. if (!strcasecmp(arg2, "On")) {
  641. bool_val[0] = '1';
  642. } else {
  643. bool_val[0] = '0';
  644. }
  645. bool_val[1] = 0;
  646. return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode);
  647. }
  648. /* }}} */
  649. /* {{{ php_apache_flag_handler
  650. */
  651. CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  652. {
  653. return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
  654. }
  655. /* }}} */
  656. /* {{{ php_apache_admin_flag_handler
  657. */
  658. CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  659. {
  660. return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
  661. }
  662. /* }}} */
  663. /* {{{ int php_xbithack_handler(request_rec * r)
  664. */
  665. int php_xbithack_handler(request_rec * r)
  666. {
  667. php_apache_info_struct *conf;
  668. conf = (php_apache_info_struct *) get_module_config(r->per_dir_config, &php4_module);
  669. if (!(r->finfo.st_mode & S_IXUSR)) {
  670. r->allowed |= (1 << METHODS) - 1;
  671. return DECLINED;
  672. }
  673. if (conf->xbithack == 0) {
  674. r->allowed |= (1 << METHODS) - 1;
  675. return DECLINED;
  676. }
  677. return send_parsed_php(r);
  678. }
  679. /* }}} */
  680. /* {{{ apache_php_module_shutdown_wrapper
  681. */
  682. static void apache_php_module_shutdown_wrapper(void)
  683. {
  684. apache_php_initialized = 0;
  685. apache_sapi_module.shutdown(&apache_sapi_module);
  686. #if MODULE_MAGIC_NUMBER >= 19970728
  687. /* This function is only called on server exit if the apache API
  688. * child_exit handler exists, so shutdown globally
  689. */
  690. sapi_shutdown();
  691. #endif
  692. #ifdef ZTS
  693. tsrm_shutdown();
  694. #endif
  695. }
  696. /* }}} */
  697. #if MODULE_MAGIC_NUMBER >= 19970728
  698. /* {{{ php_child_exit_handler
  699. */
  700. static void php_child_exit_handler(server_rec *s, pool *p)
  701. {
  702. /* apache_php_initialized = 0; */
  703. apache_sapi_module.shutdown(&apache_sapi_module);
  704. #ifdef ZTS
  705. tsrm_shutdown();
  706. #endif
  707. }
  708. /* }}} */
  709. #endif
  710. /* {{{ void php_init_handler(server_rec *s, pool *p)
  711. */
  712. void php_init_handler(server_rec *s, pool *p)
  713. {
  714. register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);
  715. if (!apache_php_initialized) {
  716. apache_php_initialized = 1;
  717. #ifdef ZTS
  718. tsrm_startup(1, 1, 0, NULL);
  719. #endif
  720. sapi_startup(&apache_sapi_module);
  721. php_apache_startup(&apache_sapi_module);
  722. }
  723. #if MODULE_MAGIC_NUMBER >= 19980527
  724. {
  725. PLS_FETCH();
  726. if (PG(expose_php)) {
  727. ap_add_version_component("PHP/" PHP_VERSION);
  728. }
  729. }
  730. #endif
  731. }
  732. /* }}} */
  733. /* {{{ handler_rec php_handlers[]
  734. */
  735. handler_rec php_handlers[] =
  736. {
  737. {"application/x-httpd-php", send_parsed_php},
  738. {"application/x-httpd-php-source", send_parsed_php_source},
  739. {"text/html", php_xbithack_handler},
  740. {NULL}
  741. };
  742. /* }}} */
  743. /* {{{ command_rec php_commands[]
  744. */
  745. command_rec php_commands[] =
  746. {
  747. {"php_value", php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"},
  748. {"php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"},
  749. {"php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"},
  750. {"php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"},
  751. {NULL}
  752. };
  753. /* }}} */
  754. /* {{{ odule MODULE_VAR_EXPORT php4_module
  755. */
  756. module MODULE_VAR_EXPORT php4_module =
  757. {
  758. STANDARD_MODULE_STUFF,
  759. php_init_handler, /* initializer */
  760. php_create_dir, /* per-directory config creator */
  761. php_merge_dir, /* dir merger */
  762. NULL, /* per-server config creator */
  763. NULL, /* merge server config */
  764. php_commands, /* command table */
  765. php_handlers, /* handlers */
  766. NULL, /* filename translation */
  767. NULL, /* check_user_id */
  768. NULL, /* check auth */
  769. NULL, /* check access */
  770. NULL, /* type_checker */
  771. NULL, /* fixups */
  772. NULL /* logger */
  773. #if MODULE_MAGIC_NUMBER >= 19970103
  774. ,NULL /* header parser */
  775. #endif
  776. #if MODULE_MAGIC_NUMBER >= 19970719
  777. ,NULL /* child_init */
  778. #endif
  779. #if MODULE_MAGIC_NUMBER >= 19970728
  780. ,php_child_exit_handler /* child_exit */
  781. #endif
  782. #if MODULE_MAGIC_NUMBER >= 19970902
  783. ,NULL /* post read-request */
  784. #endif
  785. };
  786. /* }}} */
  787. /*
  788. * Local variables:
  789. * tab-width: 4
  790. * c-basic-offset: 4
  791. * End:
  792. * vim600: sw=4 ts=4 tw=78 fdm=marker
  793. * vim<600: sw=4 ts=4 tw=78
  794. */