mod_php5.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 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_php5.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 php5_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 receive 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, "Content-Length")) {
  174. ap_set_content_length(r, strtol(header_content, (char **)NULL, 10));
  175. } else if (!strcasecmp(header_name, "Set-Cookie")) {
  176. table_add(r->headers_out, header_name, header_content);
  177. } else if (op == SAPI_HEADER_REPLACE) {
  178. table_set(r->headers_out, header_name, header_content);
  179. } else {
  180. table_add(r->headers_out, header_name, header_content);
  181. }
  182. *p = ':'; /* a well behaved header handler shouldn't change its original arguments */
  183. return SAPI_HEADER_ADD;
  184. default:
  185. return 0;
  186. }
  187. }
  188. /* }}} */
  189. /* {{{ sapi_apache_send_headers
  190. */
  191. static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  192. {
  193. request_rec *r = SG(server_context);
  194. const char *sline = SG(sapi_headers).http_status_line;
  195. int sline_len;
  196. if(r == NULL) { /* server_context is not here anymore */
  197. return SAPI_HEADER_SEND_FAILED;
  198. }
  199. r->status = SG(sapi_headers).http_response_code;
  200. /* httpd requires that r->status_line is set to the first digit of
  201. * the status-code: */
  202. if (sline && ((sline_len = strlen(sline)) > 12) && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ' && sline[12] == ' ') {
  203. if ((sline_len - 9) > MAX_STATUS_LENGTH) {
  204. r->status_line = ap_pstrndup(r->pool, sline + 9, MAX_STATUS_LENGTH);
  205. } else {
  206. r->status_line = ap_pstrndup(r->pool, sline + 9, sline_len - 9);
  207. }
  208. }
  209. if(r->status==304) {
  210. send_error_response(r,0);
  211. } else {
  212. send_http_header(r);
  213. }
  214. return SAPI_HEADER_SENT_SUCCESSFULLY;
  215. }
  216. /* }}} */
  217. /* {{{ sapi_apache_register_server_variables
  218. */
  219. static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_DC)
  220. {
  221. register int i;
  222. array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env);
  223. table_entry *elts = (table_entry *) arr->elts;
  224. zval **path_translated;
  225. HashTable *symbol_table;
  226. unsigned int new_val_len;
  227. for (i = 0; i < arr->nelts; i++) {
  228. char *val;
  229. int val_len;
  230. if (elts[i].val) {
  231. val = elts[i].val;
  232. } else {
  233. val = "";
  234. }
  235. val_len = strlen(val);
  236. if (sapi_module.input_filter(PARSE_SERVER, elts[i].key, &val, val_len, &new_val_len TSRMLS_CC)) {
  237. php_register_variable_safe(elts[i].key, val, new_val_len, track_vars_array TSRMLS_CC);
  238. }
  239. }
  240. /* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
  241. if (track_vars_array) {
  242. symbol_table = track_vars_array->value.ht;
  243. } else {
  244. symbol_table = NULL;
  245. }
  246. if (symbol_table
  247. && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"))
  248. && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) {
  249. php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC);
  250. }
  251. 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)) {
  252. php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC);
  253. }
  254. }
  255. /* }}} */
  256. /* {{{ php_apache_startup
  257. */
  258. static int php_apache_startup(sapi_module_struct *sapi_module)
  259. {
  260. if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {
  261. return FAILURE;
  262. } else {
  263. return SUCCESS;
  264. }
  265. }
  266. /* }}} */
  267. /* {{{ php_apache_log_message
  268. */
  269. static void php_apache_log_message(char *message TSRMLS_DC)
  270. {
  271. if (SG(server_context)) {
  272. #if MODULE_MAGIC_NUMBER >= 19970831
  273. aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
  274. #else
  275. log_error(message, ((request_rec *) SG(server_context))->server);
  276. #endif
  277. } else {
  278. fprintf(stderr, "%s\n", message);
  279. }
  280. }
  281. /* }}} */
  282. /* {{{ php_apache_request_shutdown
  283. */
  284. static void php_apache_request_shutdown(void *dummy)
  285. {
  286. TSRMLS_FETCH();
  287. php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
  288. if (AP(in_request)) {
  289. AP(in_request) = 0;
  290. php_request_shutdown(dummy);
  291. }
  292. SG(server_context) = NULL;
  293. /*
  294. * The server context (request) is NOT invalid by the time
  295. * run_cleanups() is called
  296. */
  297. }
  298. /* }}} */
  299. /* {{{ php_apache_sapi_activate
  300. */
  301. static int php_apache_sapi_activate(TSRMLS_D)
  302. {
  303. request_rec *r = (request_rec *) SG(server_context);
  304. /*
  305. * For the Apache module version, this bit of code registers a cleanup
  306. * function that gets triggered when our request pool is destroyed.
  307. * We need this because at any point in our code we can be interrupted
  308. * and that may happen before we have had time to free our memory.
  309. * The php_request_shutdown function needs to free all outstanding allocated
  310. * memory.
  311. */
  312. block_alarms();
  313. register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec);
  314. AP(in_request)=1;
  315. unblock_alarms();
  316. /* Override the default headers_only value - sometimes "GET" requests should actually only
  317. * send headers.
  318. */
  319. SG(request_info).headers_only = r->header_only;
  320. return SUCCESS;
  321. }
  322. /* }}} */
  323. /* {{{ php_apache_get_stat
  324. */
  325. static struct stat *php_apache_get_stat(TSRMLS_D)
  326. {
  327. return &((request_rec *) SG(server_context))->finfo;
  328. }
  329. /* }}} */
  330. /* {{{ php_apache_getenv
  331. */
  332. static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC)
  333. {
  334. if (SG(server_context) == NULL) {
  335. return NULL;
  336. }
  337. return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name);
  338. }
  339. /* }}} */
  340. /* {{{ sapi_apache_get_fd
  341. */
  342. static int sapi_apache_get_fd(int *nfd TSRMLS_DC)
  343. {
  344. #if PHP_APACHE_HAVE_CLIENT_FD
  345. request_rec *r = SG(server_context);
  346. int fd;
  347. fd = r->connection->client->fd;
  348. if (fd >= 0) {
  349. if (nfd) *nfd = fd;
  350. return SUCCESS;
  351. }
  352. #endif
  353. return FAILURE;
  354. }
  355. /* }}} */
  356. /* {{{ sapi_apache_force_http_10
  357. */
  358. static int sapi_apache_force_http_10(TSRMLS_D)
  359. {
  360. request_rec *r = SG(server_context);
  361. r->proto_num = HTTP_VERSION(1,0);
  362. return SUCCESS;
  363. }
  364. /* }}} */
  365. /* {{{ sapi_apache_get_target_uid
  366. */
  367. static int sapi_apache_get_target_uid(uid_t *obj TSRMLS_DC)
  368. {
  369. *obj = ap_user_id;
  370. return SUCCESS;
  371. }
  372. /* }}} */
  373. /* {{{ sapi_apache_get_target_gid
  374. */
  375. static int sapi_apache_get_target_gid(gid_t *obj TSRMLS_DC)
  376. {
  377. *obj = ap_group_id;
  378. return SUCCESS;
  379. }
  380. /* }}} */
  381. /* {{{ php_apache_get_request_time
  382. */
  383. static double php_apache_get_request_time(TSRMLS_D)
  384. {
  385. return (double) ((request_rec *)SG(server_context))->request_time;
  386. }
  387. /* }}} */
  388. /* {{{ sapi_apache_child_terminate
  389. */
  390. static void sapi_apache_child_terminate(TSRMLS_D)
  391. {
  392. #ifndef MULTITHREAD
  393. ap_child_terminate((request_rec *)SG(server_context));
  394. #endif
  395. }
  396. /* }}} */
  397. /* {{{ sapi_module_struct apache_sapi_module
  398. */
  399. static sapi_module_struct apache_sapi_module = {
  400. "apache", /* name */
  401. "Apache", /* pretty name */
  402. php_apache_startup, /* startup */
  403. php_module_shutdown_wrapper, /* shutdown */
  404. php_apache_sapi_activate, /* activate */
  405. NULL, /* deactivate */
  406. sapi_apache_ub_write, /* unbuffered write */
  407. sapi_apache_flush, /* flush */
  408. php_apache_get_stat, /* get uid */
  409. php_apache_getenv, /* getenv */
  410. php_error, /* error handler */
  411. sapi_apache_header_handler, /* header handler */
  412. sapi_apache_send_headers, /* send headers handler */
  413. NULL, /* send header handler */
  414. sapi_apache_read_post, /* read POST data */
  415. sapi_apache_read_cookies, /* read Cookies */
  416. sapi_apache_register_server_variables, /* register server variables */
  417. php_apache_log_message, /* Log message */
  418. php_apache_get_request_time, /* Get request time */
  419. sapi_apache_child_terminate,
  420. NULL, /* php.ini path override */
  421. #ifdef PHP_WIN32
  422. NULL,
  423. NULL,
  424. #else
  425. block_alarms, /* Block interruptions */
  426. unblock_alarms, /* Unblock interruptions */
  427. #endif
  428. NULL, /* default post reader */
  429. NULL, /* treat data */
  430. NULL, /* exe location */
  431. 0, /* ini ignore */
  432. 0, /* ini ignore cwd */
  433. sapi_apache_get_fd,
  434. sapi_apache_force_http_10,
  435. sapi_apache_get_target_uid,
  436. sapi_apache_get_target_gid
  437. };
  438. /* }}} */
  439. /* {{{ php_restore_umask
  440. */
  441. static void php_restore_umask(void)
  442. {
  443. umask(saved_umask);
  444. }
  445. /* }}} */
  446. /* {{{ init_request_info
  447. */
  448. static void init_request_info(TSRMLS_D)
  449. {
  450. request_rec *r = ((request_rec *) SG(server_context));
  451. char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH");
  452. const char *authorization=NULL;
  453. char *tmp, *tmp_user;
  454. SG(request_info).query_string = r->args;
  455. SG(request_info).path_translated = r->filename;
  456. SG(request_info).request_uri = r->uri;
  457. SG(request_info).request_method = (char *)r->method;
  458. SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
  459. SG(request_info).content_length = (content_length ? atol(content_length) : 0);
  460. SG(sapi_headers).http_response_code = r->status;
  461. SG(request_info).proto_num = r->proto_num;
  462. if (r->headers_in) {
  463. authorization = table_get(r->headers_in, "Authorization");
  464. }
  465. SG(request_info).auth_user = NULL;
  466. SG(request_info).auth_password = NULL;
  467. SG(request_info).auth_digest = NULL;
  468. if (authorization) {
  469. char *p = getword(r->pool, &authorization, ' ');
  470. if (!strcasecmp(p, "Basic")) {
  471. tmp = uudecode(r->pool, authorization);
  472. tmp_user = getword_nulls_nc(r->pool, &tmp, ':');
  473. if (tmp_user) {
  474. r->connection->user = pstrdup(r->connection->pool, tmp_user);
  475. r->connection->ap_auth_type = "Basic";
  476. SG(request_info).auth_user = estrdup(tmp_user);
  477. }
  478. if (tmp) {
  479. SG(request_info).auth_password = estrdup(tmp);
  480. }
  481. } else if (!strcasecmp(p, "Digest")) {
  482. r->connection->ap_auth_type = "Digest";
  483. SG(request_info).auth_digest = estrdup(authorization);
  484. }
  485. }
  486. }
  487. /* }}} */
  488. /* {{{ php_apache_alter_ini_entries
  489. */
  490. static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC)
  491. {
  492. 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);
  493. return 0;
  494. }
  495. /* }}} */
  496. /* {{{ php_apache_get_default_mimetype
  497. */
  498. static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC)
  499. {
  500. char *mimetype;
  501. if (SG(default_mimetype) || SG(default_charset)) {
  502. /* Assume output will be of the default MIME type. Individual
  503. scripts may change this later. */
  504. char *tmpmimetype;
  505. tmpmimetype = sapi_get_default_content_type(TSRMLS_C);
  506. mimetype = pstrdup(r->pool, tmpmimetype);
  507. efree(tmpmimetype);
  508. } else {
  509. mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET;
  510. }
  511. return mimetype;
  512. }
  513. /* }}} */
  514. /* {{{ send_php
  515. */
  516. static int send_php(request_rec *r, int display_source_mode, char *filename)
  517. {
  518. int retval;
  519. HashTable *per_dir_conf;
  520. TSRMLS_FETCH();
  521. if (AP(in_request)) {
  522. zend_file_handle fh;
  523. fh.filename = r->filename;
  524. fh.opened_path = NULL;
  525. fh.free_filename = 0;
  526. fh.type = ZEND_HANDLE_FILENAME;
  527. zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh);
  528. return OK;
  529. }
  530. SG(server_context) = r;
  531. zend_first_try {
  532. /* Make sure file exists */
  533. if (filename == NULL && r->finfo.st_mode == 0) {
  534. return DECLINED;
  535. }
  536. per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php5_module);
  537. if (per_dir_conf) {
  538. zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
  539. }
  540. /* If PHP parser engine has been turned off with an "engine off"
  541. * directive, then decline to handle this request
  542. */
  543. if (!AP(engine)) {
  544. r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
  545. zend_try {
  546. zend_ini_deactivate(TSRMLS_C);
  547. } zend_end_try();
  548. return DECLINED;
  549. }
  550. if (filename == NULL) {
  551. filename = r->filename;
  552. }
  553. /* Apache 1.2 has a more complex mechanism for reading POST data */
  554. #if MODULE_MAGIC_NUMBER > 19961007
  555. if ((retval = setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) {
  556. zend_try {
  557. zend_ini_deactivate(TSRMLS_C);
  558. } zend_end_try();
  559. return retval;
  560. }
  561. #endif
  562. if (AP(last_modified)) {
  563. #if MODULE_MAGIC_NUMBER < 19970912
  564. if ((retval = set_last_modified(r, r->finfo.st_mtime))) {
  565. zend_try {
  566. zend_ini_deactivate(TSRMLS_C);
  567. } zend_end_try();
  568. return retval;
  569. }
  570. #else
  571. update_mtime (r, r->finfo.st_mtime);
  572. set_last_modified(r);
  573. set_etag(r);
  574. #endif
  575. }
  576. /* Assume output will be of the default MIME type. Individual
  577. scripts may change this later in the request. */
  578. r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
  579. /* Init timeout */
  580. hard_timeout("send", r);
  581. php_save_umask();
  582. add_common_vars(r);
  583. add_cgi_vars(r);
  584. init_request_info(TSRMLS_C);
  585. apache_php_module_main(r, display_source_mode TSRMLS_CC);
  586. /* Done, restore umask, turn off timeout, close file and return */
  587. php_restore_umask();
  588. kill_timeout(r);
  589. } zend_end_try();
  590. return OK;
  591. }
  592. /* }}} */
  593. /* {{{ send_parsed_php
  594. */
  595. static int send_parsed_php(request_rec * r)
  596. {
  597. int result = send_php(r, 0, NULL);
  598. TSRMLS_FETCH();
  599. ap_table_setn(r->notes, "mod_php_memory_usage",
  600. ap_psprintf(r->pool, "%lu", zend_memory_peak_usage(1 TSRMLS_CC)));
  601. return result;
  602. }
  603. /* }}} */
  604. /* {{{ send_parsed_php_source
  605. */
  606. static int send_parsed_php_source(request_rec * r)
  607. {
  608. return send_php(r, 1, NULL);
  609. }
  610. /* }}} */
  611. /* {{{ destroy_per_dir_entry
  612. */
  613. static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  614. {
  615. free(per_dir_entry->key);
  616. free(per_dir_entry->value);
  617. }
  618. /* }}} */
  619. /* {{{ copy_per_dir_entry
  620. */
  621. static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  622. {
  623. php_per_dir_entry tmp = *per_dir_entry;
  624. per_dir_entry->key = (char *) malloc(tmp.key_length+1);
  625. memcpy(per_dir_entry->key, tmp.key, tmp.key_length);
  626. per_dir_entry->key[per_dir_entry->key_length] = 0;
  627. per_dir_entry->value = (char *) malloc(tmp.value_length+1);
  628. memcpy(per_dir_entry->value, tmp.value, tmp.value_length);
  629. per_dir_entry->value[per_dir_entry->value_length] = 0;
  630. }
  631. /* }}} */
  632. /* {{{ should_overwrite_per_dir_entry
  633. */
  634. 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)
  635. {
  636. php_per_dir_entry *orig_per_dir_entry;
  637. if (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &orig_per_dir_entry)==FAILURE) {
  638. return 1; /* does not exist in dest, copy from source */
  639. }
  640. if (orig_per_dir_entry->type==PHP_INI_SYSTEM
  641. && new_per_dir_entry->type!=PHP_INI_SYSTEM) {
  642. return 0;
  643. } else {
  644. return 1;
  645. }
  646. }
  647. /* }}} */
  648. /* {{{ php_destroy_per_dir_info
  649. */
  650. static void php_destroy_per_dir_info(HashTable *per_dir_info)
  651. {
  652. zend_hash_destroy(per_dir_info);
  653. free(per_dir_info);
  654. }
  655. /* }}} */
  656. /* {{{ php_create_dir
  657. */
  658. static void *php_create_dir(pool *p, char *dummy)
  659. {
  660. HashTable *per_dir_info;
  661. per_dir_info = (HashTable *) malloc(sizeof(HashTable));
  662. zend_hash_init_ex(per_dir_info, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0);
  663. register_cleanup(p, (void *) per_dir_info, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) zend_hash_destroy);
  664. return per_dir_info;
  665. }
  666. /* }}} */
  667. /* {{{ php_merge_dir
  668. */
  669. static void *php_merge_dir(pool *p, void *basev, void *addv)
  670. {
  671. /* This function *must* not modify addv or basev */
  672. HashTable *new;
  673. /* need a copy of addv to merge */
  674. new = php_create_dir(p, "php_merge_dir");
  675. zend_hash_copy(new, (HashTable *) basev, (copy_ctor_func_t) copy_per_dir_entry, NULL, sizeof(php_per_dir_entry));
  676. 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);
  677. return new;
  678. }
  679. /* }}} */
  680. /* {{{ php_apache_value_handler_ex
  681. */
  682. static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
  683. {
  684. php_per_dir_entry per_dir_entry;
  685. if (!apache_php_initialized) {
  686. apache_php_initialized = 1;
  687. #ifdef ZTS
  688. tsrm_startup(1, 1, 0, NULL);
  689. #endif
  690. sapi_startup(&apache_sapi_module);
  691. php_apache_startup(&apache_sapi_module);
  692. }
  693. per_dir_entry.type = mode;
  694. per_dir_entry.htaccess = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0);
  695. if (strcasecmp(arg2, "none") == 0) {
  696. arg2 = "";
  697. }
  698. per_dir_entry.key_length = strlen(arg1);
  699. per_dir_entry.value_length = strlen(arg2);
  700. per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1);
  701. memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);
  702. per_dir_entry.key[per_dir_entry.key_length] = 0;
  703. per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1);
  704. memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length);
  705. per_dir_entry.value[per_dir_entry.value_length] = 0;
  706. zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL);
  707. return NULL;
  708. }
  709. /* }}} */
  710. /* {{{ php_apache_value_handler
  711. */
  712. static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  713. {
  714. return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
  715. }
  716. /* }}} */
  717. /* {{{ php_apache_admin_value_handler
  718. */
  719. static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  720. {
  721. return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
  722. }
  723. /* }}} */
  724. /* {{{ php_apache_flag_handler_ex
  725. */
  726. static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
  727. {
  728. char bool_val[2];
  729. if (!strcasecmp(arg2, "On") || (arg2[0] == '1' && arg2[1] == '\0')) {
  730. bool_val[0] = '1';
  731. } else {
  732. bool_val[0] = '0';
  733. }
  734. bool_val[1] = 0;
  735. return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode);
  736. }
  737. /* }}} */
  738. /* {{{ php_apache_flag_handler
  739. */
  740. static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  741. {
  742. return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
  743. }
  744. /* }}} */
  745. /* {{{ php_apache_admin_flag_handler
  746. */
  747. static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
  748. {
  749. return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
  750. }
  751. /* }}} */
  752. /* {{{ php_apache_phpini_set
  753. */
  754. static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg)
  755. {
  756. if (apache_sapi_module.php_ini_path_override) {
  757. return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored";
  758. }
  759. apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg);
  760. return NULL;
  761. }
  762. /* }}} */
  763. /* {{{ int php_xbithack_handler(request_rec * r)
  764. */
  765. static int php_xbithack_handler(request_rec * r)
  766. {
  767. HashTable *per_dir_conf;
  768. TSRMLS_FETCH();
  769. if (!(r->finfo.st_mode & S_IXUSR)) {
  770. return DECLINED;
  771. }
  772. per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php5_module);
  773. if (per_dir_conf) {
  774. zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
  775. }
  776. if(!AP(xbithack)) {
  777. zend_try {
  778. zend_ini_deactivate(TSRMLS_C);
  779. } zend_end_try();
  780. return DECLINED;
  781. }
  782. return send_parsed_php(r);
  783. }
  784. /* }}} */
  785. /* {{{ apache_php_module_shutdown_wrapper
  786. */
  787. static void apache_php_module_shutdown_wrapper(void)
  788. {
  789. apache_php_initialized = 0;
  790. apache_sapi_module.shutdown(&apache_sapi_module);
  791. #if MODULE_MAGIC_NUMBER >= 19970728
  792. /* This function is only called on server exit if the apache API
  793. * child_exit handler exists, so shutdown globally
  794. */
  795. sapi_shutdown();
  796. #endif
  797. #ifdef ZTS
  798. tsrm_shutdown();
  799. #endif
  800. }
  801. /* }}} */
  802. #if MODULE_MAGIC_NUMBER >= 19970728
  803. /* {{{ php_child_exit_handler
  804. */
  805. static void php_child_exit_handler(server_rec *s, pool *p)
  806. {
  807. /* apache_php_initialized = 0; */
  808. apache_sapi_module.shutdown(&apache_sapi_module);
  809. #ifdef ZTS
  810. tsrm_shutdown();
  811. #endif
  812. }
  813. /* }}} */
  814. #endif
  815. /* {{{ void php_init_handler(server_rec *s, pool *p)
  816. */
  817. static void php_init_handler(server_rec *s, pool *p)
  818. {
  819. register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);
  820. if (!apache_php_initialized) {
  821. apache_php_initialized = 1;
  822. #ifdef ZTS
  823. tsrm_startup(1, 1, 0, NULL);
  824. #endif
  825. sapi_startup(&apache_sapi_module);
  826. php_apache_startup(&apache_sapi_module);
  827. }
  828. #if MODULE_MAGIC_NUMBER >= 19980527
  829. {
  830. TSRMLS_FETCH();
  831. if (PG(expose_php)) {
  832. ap_add_version_component("PHP/" PHP_VERSION);
  833. }
  834. }
  835. #endif
  836. }
  837. /* }}} */
  838. /* {{{ handler_rec php_handlers[]
  839. */
  840. handler_rec php_handlers[] =
  841. {
  842. {"application/x-httpd-php", send_parsed_php},
  843. {"application/x-httpd-php-source", send_parsed_php_source},
  844. {"text/html", php_xbithack_handler},
  845. {NULL}
  846. };
  847. /* }}} */
  848. /* {{{ command_rec php_commands[]
  849. */
  850. command_rec php_commands[] =
  851. {
  852. {"php_value", php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"},
  853. {"php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"},
  854. {"php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"},
  855. {"php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"},
  856. {"PHPINIDir", php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"},
  857. {NULL}
  858. };
  859. /* }}} */
  860. /* {{{ odule MODULE_VAR_EXPORT php5_module
  861. */
  862. module MODULE_VAR_EXPORT php5_module =
  863. {
  864. STANDARD_MODULE_STUFF,
  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. */