root/sapi/apache_hooks/mod_php5.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sapi_stack_init_ex
  2. sapi_stack_push
  3. sapi_stack_pop
  4. sapi_stack_destroy
  5. sapi_stack_apply_with_argument_all
  6. sapi_stack_apply_with_argument_stop_if_equals
  7. sapi_stack_apply_with_argument_stop_if_http_error
  8. php_handler_stack_destroy
  9. php_save_umask
  10. sapi_apache_ub_write
  11. sapi_apache_flush
  12. sapi_apache_read_post
  13. sapi_apache_read_cookies
  14. sapi_apache_header_handler
  15. sapi_apache_send_headers
  16. sapi_apache_register_server_variables
  17. php_apache_startup
  18. php_apache_log_message
  19. php_apache_request_shutdown
  20. php_apache_sapi_activate
  21. php_apache_get_stat
  22. php_apache_getenv
  23. php_restore_umask
  24. init_request_info
  25. php_apache_alter_ini_entries
  26. php_apache_get_default_mimetype
  27. send_php
  28. send_parsed_php
  29. send_parsed_php_source
  30. destroy_per_dir_entry
  31. copy_per_dir_entry
  32. should_overwrite_per_dir_entry
  33. php_destroy_per_server_info
  34. php_destroy_per_dir_info
  35. php_create_server
  36. php_create_dir
  37. php_merge_dir
  38. php_apache_value_handler_ex
  39. php_set_server_handler
  40. php_set_dir_handler
  41. php_set_uri_handler
  42. php_set_uri_handler_code
  43. php_set_header_handler
  44. php_set_header_handler_code
  45. php_set_auth_handler
  46. php_set_auth_handler_code
  47. php_set_access_handler
  48. php_set_access_handler_code
  49. php_set_type_handler
  50. php_set_type_handler_code
  51. php_set_fixup_handler
  52. php_set_fixup_handler_code
  53. php_set_logger_handler
  54. php_set_logger_handler_code
  55. php_set_post_read_handler
  56. php_set_post_read_handler_code
  57. php_set_require
  58. php_set_response_handler
  59. php_set_response_handler_code
  60. php_apache_value_handler
  61. php_apache_admin_value_handler
  62. php_apache_flag_handler_ex
  63. php_apache_flag_handler
  64. php_apache_admin_flag_handler
  65. php_apache_phpini_set
  66. php_xbithack_handler
  67. apache_php_module_shutdown_wrapper
  68. php_child_exit_handler
  69. php_init_handler
  70. php_run_hook
  71. php_uri_translation
  72. php_header_hook
  73. php_auth_hook
  74. php_access_hook
  75. php_type_hook
  76. php_fixup_hook
  77. php_logger_hook
  78. php_post_read_hook
  79. php_response_handler

   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 at through the world-wide-web at                           |
  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 
  22 #include "php_apache_http.h"
  23 
  24 #ifdef NETWARE
  25 #define SIGPIPE SIGINT
  26 #endif
  27 
  28 #undef shutdown
  29 
  30 /* {{{ Prototypes
  31  */
  32 int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC);
  33 static void php_save_umask(void);
  34 static void php_restore_umask(void);
  35 static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC);
  36 static char *sapi_apache_read_cookies(TSRMLS_D);
  37 static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC);
  38 static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC);
  39 static int send_php(request_rec *r, int display_source_mode, char *filename);
  40 static int send_parsed_php(request_rec * r);
  41 static int send_parsed_php_source(request_rec * r);
  42 static int php_xbithack_handler(request_rec * r);
  43 static void php_init_handler(server_rec *s, pool *p);
  44 /* }}} */
  45 
  46 #if MODULE_MAGIC_NUMBER >= 19970728
  47 static void php_child_exit_handler(server_rec *s, pool *p);
  48 #endif
  49 
  50 #if MODULE_MAGIC_NUMBER > 19961007
  51 #define CONST_PREFIX const
  52 #else
  53 #define CONST_PREFIX
  54 #endif
  55 
  56 
  57 typedef struct _sapi_stack {
  58                 int top, max, persistent;
  59                 void **elements;
  60 } sapi_stack;
  61 
  62 typedef struct _php_per_dir_config {
  63         HashTable *ini_settings;
  64         sapi_stack headers_handlers;
  65         sapi_stack auth_handlers;
  66         sapi_stack access_handlers;
  67         sapi_stack type_handlers;
  68         sapi_stack fixup_handlers;
  69         sapi_stack logger_handlers;
  70         sapi_stack post_read_handlers;
  71         sapi_stack response_handlers;
  72 } php_per_dir_config;
  73 
  74 typedef struct _php_per_server_config {
  75         sapi_stack uri_handlers;
  76         sapi_stack requires;
  77 } php_per_server_config;
  78 
  79 
  80 static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
  81 static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
  82 static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
  83 static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
  84 static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
  85 static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
  86 
  87 /* ### these should be defined in mod_php5.h or somewhere else */
  88 #define USE_PATH 1
  89 #define IGNORE_URL 2
  90 
  91 module MODULE_VAR_EXPORT php5_module;
  92 
  93 int saved_umask;
  94 /* static int setup_env = 0; */
  95 static unsigned char apache_php_initialized;
  96 
  97 typedef struct _php_per_dir_entry {
  98         char *key;
  99         char *value;
 100         uint key_length;
 101         uint value_length;
 102         int type;
 103 } php_per_dir_entry;
 104 
 105 /* some systems are missing these from their header files */
 106 
 107 /* {{{ zend stack utility functions
 108  */
 109 
 110 /* This code is ripped part and parcel from zend_stack.[ch].  Assuming that the
 111    patch supporting zend_stack_init_ex is applied, all but the bottom two 
 112    module-specific iterators will be removed
 113  */
 114 
 115 int sapi_stack_init_ex(sapi_stack *stack, int persistent)
 116 {
 117                 stack->top = 0;
 118                 stack->persistent = persistent;
 119                 stack->elements = (void **) pemalloc(sizeof(void **) * STACK_BLOCK_SIZE,  persistent);
 120                 if (!stack->elements) {
 121                                 return FAILURE;
 122                 } else {
 123                                 stack->max = STACK_BLOCK_SIZE;
 124                                 return SUCCESS;
 125                 }
 126 }
 127 int sapi_stack_push(sapi_stack *stack, void *element)
 128 {
 129                 if (stack->top >= stack->max) {          /* we need to allocate more memory */
 130                                 stack->elements = (void **) perealloc(stack->elements,
 131                                                                    (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)), stack->persistent);
 132                                 if (!stack->elements) {
 133                                                 return FAILURE;
 134                                 }
 135                 }
 136                 stack->elements[stack->top] = (void *) element;
 137                 return stack->top++;
 138 }
 139 void* sapi_stack_pop(sapi_stack *stack) {
 140         if(stack->top == 0) {
 141                 return NULL;
 142         }
 143         else {
 144                 return stack->elements[--stack->top];
 145         }
 146 }
 147 
 148 int sapi_stack_destroy(sapi_stack *stack)
 149 {
 150                 return SUCCESS;
 151 }
 152 
 153 int sapi_stack_apply_with_argument_all(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)
 154 {
 155                 int i, retval;   
 156 
 157                 switch (type) {                         
 158                                 case ZEND_STACK_APPLY_TOPDOWN:
 159                                                 for (i=stack->top-1; i>=0; i--) {
 160                                                                 retval = apply_function(stack->elements[i], arg); 
 161                                                 }
 162                                                 break;
 163                                 case ZEND_STACK_APPLY_BOTTOMUP:
 164                                                 for (i=0; i<stack->top; i++) {          
 165                                                                 retval = apply_function(stack->elements[i], arg);
 166                                                 }         
 167                                                 break;
 168                 }
 169                 return retval;
 170 }
 171 
 172 
 173 int sapi_stack_apply_with_argument_stop_if_equals(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg, int stopval)
 174 {
 175         int i;
 176         int ret = DECLINED;
 177         switch (type) {
 178                 case ZEND_STACK_APPLY_TOPDOWN:
 179                         for (i=stack->top-1; i>=0; i--) {
 180                                 if ((ret = apply_function(stack->elements[i], arg)) == stopval) {
 181                                         break;
 182                                 }
 183                         }
 184                         break;
 185                 case ZEND_STACK_APPLY_BOTTOMUP:
 186                         for (i=0; i<stack->top; i++) {
 187                                 if ((ret = apply_function(stack->elements[i], arg)) == stopval) {
 188                                         break;
 189                                 }
 190                         }
 191                         break;
 192         }
 193         return ret;
 194 }
 195 
 196 int sapi_stack_apply_with_argument_stop_if_http_error(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)
 197 {
 198         int i;
 199         int ret = DECLINED;
 200         switch (type) {
 201                 case ZEND_STACK_APPLY_TOPDOWN:
 202                         for (i=stack->top-1; i>=0; i--) {
 203                                 if ((ret = apply_function(stack->elements[i], arg)) > 0) {
 204                                         break;
 205                                 }
 206                         }
 207                         break;
 208                 case ZEND_STACK_APPLY_BOTTOMUP:
 209                         for (i=0; i<stack->top; i++) {
 210                                 if ((ret = apply_function(stack->elements[i], arg)) > 0) {
 211                                         break;
 212                                 }
 213                         }
 214                         break;
 215         }
 216         return ret;
 217 }
 218 
 219 void php_handler_stack_destroy(sapi_stack *stack)
 220 {
 221         php_handler *ph;
 222         while((ph = (php_handler *)sapi_stack_pop(stack)) != NULL) {
 223                 free(ph->name);
 224                 free(ph);
 225         }
 226 }
 227 /* }}} */ 
 228 
 229 /* {{{ php_save_umask
 230  */
 231 static void php_save_umask(void)
 232 {
 233         saved_umask = umask(077);
 234         umask(saved_umask);
 235 }
 236 /* }}} */
 237 
 238 /* {{{ sapi_apache_ub_write
 239  */
 240 static int sapi_apache_ub_write(const char *str, uint str_length TSRMLS_DC)
 241 {
 242         int ret=0;
 243                 
 244         if (SG(server_context)) {
 245                 ret = rwrite(str, str_length, (request_rec *) SG(server_context));
 246         }
 247         if (ret != str_length) {
 248                 php_handle_aborted_connection();
 249         }
 250         return ret;
 251 }
 252 /* }}} */
 253 
 254 /* {{{ sapi_apache_flush
 255  */
 256 static void sapi_apache_flush(void *server_context)
 257 {
 258         if (server_context) {
 259 #if MODULE_MAGIC_NUMBER > 19970110
 260                 rflush((request_rec *) server_context);
 261 #else
 262                 bflush((request_rec *) server_context->connection->client);
 263 #endif
 264         }
 265 }
 266 /* }}} */
 267 
 268 /* {{{ sapi_apache_read_post
 269  */
 270 static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC)
 271 {
 272         uint total_read_bytes=0, read_bytes;
 273         request_rec *r = (request_rec *) SG(server_context);
 274         void (*handler)(int);
 275 
 276         /*
 277          * This handles the situation where the browser sends a Expect: 100-continue header
 278          * and needs to receive confirmation from the server on whether or not it can send
 279          * the rest of the request. RFC 2616
 280          *
 281          */
 282         if (!SG(read_post_bytes) && !ap_should_client_block(r)) {
 283                 return total_read_bytes;
 284         }
 285  
 286         handler = signal(SIGPIPE, SIG_IGN);
 287         while (total_read_bytes<count_bytes) {
 288                 hard_timeout("Read POST information", r); /* start timeout timer */
 289                 read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes);
 290                 reset_timeout(r);
 291                 if (read_bytes<=0) {
 292                         break;
 293                 }
 294                 total_read_bytes += read_bytes;
 295         }
 296         signal(SIGPIPE, handler);       
 297         return total_read_bytes;
 298 }
 299 /* }}} */
 300 
 301 /* {{{ sapi_apache_read_cookies
 302  */
 303 static char *sapi_apache_read_cookies(TSRMLS_D)
 304 {
 305         return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE");
 306 }
 307 /* }}} */
 308 
 309 /* {{{ sapi_apache_header_handler
 310  */
 311 static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
 312 {
 313         char *header_name, *header_content, *p;
 314         request_rec *r = (request_rec *) SG(server_context);
 315         if(!r) {
 316                 return 0;
 317         }
 318 
 319         switch(op) {
 320                 case SAPI_HEADER_DELETE_ALL:
 321                         clear_table(r->headers_out);
 322                         return 0;
 323 
 324                 case SAPI_HEADER_DELETE:
 325                         table_unset(r->headers_out, sapi_header->header);
 326                         return 0;
 327 
 328                 case SAPI_HEADER_ADD:
 329                 case SAPI_HEADER_REPLACE:
 330                         header_name = sapi_header->header;
 331 
 332                         header_content = p = strchr(header_name, ':');
 333                         if (!p) {
 334                                 return 0;
 335                         }
 336 
 337                         *p = 0;
 338                         do {
 339                                 header_content++;
 340                         } while (*header_content==' ');
 341 
 342                         if (!strcasecmp(header_name, "Content-Type")) {
 343                                 r->content_type = pstrdup(r->pool, header_content);
 344                         } else if (!strcasecmp(header_name, "Set-Cookie")) {
 345                                 table_add(r->headers_out, header_name, header_content);
 346                         } else if (op == SAPI_HEADER_REPLACE) {
 347                                 table_set(r->headers_out, header_name, header_content);
 348                         } else {
 349                                 table_add(r->headers_out, header_name, header_content);
 350                         }
 351 
 352                         *p = ':';  /* a well behaved header handler shouldn't change its original arguments */
 353 
 354                         return SAPI_HEADER_ADD;
 355 
 356                 default:
 357                         return 0;
 358         }
 359 }
 360 /* }}} */
 361 
 362 /* {{{ sapi_apache_send_headers
 363  */
 364 static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
 365 {
 366         if(SG(server_context) == NULL) { /* server_context is not here anymore */
 367                 return SAPI_HEADER_SEND_FAILED;
 368         }
 369 
 370         ((request_rec *) SG(server_context))->status = SG(sapi_headers).http_response_code;
 371         /* check that we haven't sent headers already, we use our own
 372          * headers_sent since we may send headers at anytime 
 373          */
 374         if(!AP(headers_sent)) {
 375                 send_http_header((request_rec *) SG(server_context));
 376                 AP(headers_sent) = 1;
 377         }
 378         return SAPI_HEADER_SENT_SUCCESSFULLY;
 379 }
 380 /* }}} */
 381 
 382 /* {{{ sapi_apache_register_server_variables
 383  */
 384 static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_DC)
 385 {
 386         register int i;
 387         array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env);
 388         table_entry *elts = (table_entry *) arr->elts;
 389         zval **path_translated;
 390         HashTable *symbol_table;
 391 
 392         for (i = 0; i < arr->nelts; i++) {
 393                 char *val;
 394 
 395                 if (elts[i].val) {
 396                         val = elts[i].val;
 397                 } else {
 398                         val = "";
 399                 }
 400                 php_register_variable(elts[i].key, val, track_vars_array  TSRMLS_CC);
 401         }
 402 
 403         /* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
 404         if (track_vars_array) {
 405                 symbol_table = track_vars_array->value.ht;
 406         } else {
 407                 symbol_table = NULL;
 408         }
 409         if (symbol_table
 410                 && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"))
 411                 && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) {
 412                 php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC);
 413         }
 414 
 415         php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC);
 416 }
 417 /* }}} */
 418 
 419 /* {{{ php_apache_startup
 420  */
 421 static int php_apache_startup(sapi_module_struct *sapi_module)
 422 {
 423         if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {
 424                 return FAILURE;
 425         } else {
 426                 return SUCCESS;
 427         }
 428 }
 429 /* }}} */
 430 
 431 /* {{{ php_apache_log_message
 432  */
 433 static void php_apache_log_message(char *message TSRMLS_DC)
 434 {
 435         if (SG(server_context)) {
 436 #if MODULE_MAGIC_NUMBER >= 19970831
 437                 aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
 438 #else
 439                 log_error(message, ((request_rec *) SG(server_context))->server);
 440 #endif
 441         } else {
 442                 fprintf(stderr, "%s", message);
 443                 fprintf(stderr, "\n");
 444         }
 445 }
 446 /* }}} */
 447 
 448 /* {{{ php_apache_request_shutdown
 449  */
 450 static void php_apache_request_shutdown(void *dummy)
 451 {
 452         TSRMLS_FETCH();
 453         AP(current_hook) = AP_CLEANUP;
 454         php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
 455         SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */
 456         if(SG(sapi_started)) {
 457                 php_request_shutdown(dummy);
 458                 SG(sapi_started) = 0;
 459         }
 460         AP(in_request) = 0;
 461         if(AP(setup_env)) {
 462                 AP(setup_env) = 0;
 463         }
 464         AP(current_hook) = AP_WAITING_FOR_REQUEST;
 465         AP(headers_sent) = 0;
 466 }
 467 /* }}} */
 468 
 469 /* {{{ php_apache_sapi_activate
 470  */
 471 static int php_apache_sapi_activate(TSRMLS_D)
 472 {
 473         request_rec *r = (request_rec *) SG(server_context); 
 474 
 475         /*
 476          * For the Apache module version, this bit of code registers a cleanup
 477          * function that gets triggered when our request pool is destroyed.
 478          * We need this because at any point in our code we can be interrupted
 479          * and that may happen before we have had time to free our memory.
 480          * The php_request_shutdown function needs to free all outstanding allocated
 481          * memory.  
 482          */
 483         block_alarms();
 484         register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec);
 485         AP(in_request)=1;
 486         unblock_alarms();
 487 
 488         /* Override the default headers_only value - sometimes "GET" requests should actually only
 489          * send headers.
 490          */
 491         SG(request_info).headers_only = r->header_only;
 492         return SUCCESS;
 493 }
 494 /* }}} */
 495 
 496 /* {{{ php_apache_get_stat
 497  */
 498 static struct stat *php_apache_get_stat(TSRMLS_D)
 499 {
 500         return &((request_rec *) SG(server_context))->finfo;
 501 }
 502 /* }}} */
 503 
 504 /* {{{ php_apache_getenv
 505  */
 506 static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC)
 507 {
 508         return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name);
 509 }
 510 /* }}} */
 511 
 512 /* {{{ sapi_module_struct apache_sapi_module
 513  */
 514 static sapi_module_struct apache_sapi_module = {
 515         "apache",                                               /* name */
 516         "Apache",                                               /* pretty name */
 517                                                                         
 518         php_apache_startup,                             /* startup */
 519         php_module_shutdown_wrapper,    /* shutdown */
 520 
 521         php_apache_sapi_activate,               /* activate */
 522         NULL,                                                   /* deactivate */
 523 
 524         sapi_apache_ub_write,                   /* unbuffered write */
 525         sapi_apache_flush,                              /* flush */
 526         php_apache_get_stat,                    /* get uid */
 527         php_apache_getenv,                              /* getenv */
 528 
 529         php_error,                                              /* error handler */
 530 
 531         sapi_apache_header_handler,             /* header handler */
 532         sapi_apache_send_headers,               /* send headers handler */
 533         NULL,                                                   /* send header handler */
 534 
 535         sapi_apache_read_post,                  /* read POST data */
 536         sapi_apache_read_cookies,               /* read Cookies */
 537 
 538         sapi_apache_register_server_variables,          /* register server variables */
 539         php_apache_log_message,                 /* Log message */
 540         NULL,                                                   /* Get request time */
 541         NULL,                                   /* child terminate */
 542 
 543         NULL,                                                   /* php.ini path override */
 544 
 545 #ifdef PHP_WIN32
 546         NULL,
 547         NULL,
 548 #else
 549         block_alarms,                                   /* Block interruptions */
 550         unblock_alarms,                                 /* Unblock interruptions */
 551 #endif
 552 
 553         NULL,                           /* default post reader */
 554         NULL,                           /* treat data */
 555         NULL,                           /* exe location */
 556         0,                              /* ini ignore */
 557         NULL
 558         
 559 };
 560 /* }}} */
 561 
 562 /* {{{ php_restore_umask
 563  */
 564 static void php_restore_umask(void)
 565 {
 566         umask(saved_umask);
 567 }
 568 /* }}} */
 569 
 570 /* {{{ init_request_info
 571  */
 572 static void init_request_info(TSRMLS_D)
 573 {
 574         request_rec *r = ((request_rec *) SG(server_context));
 575         char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH");
 576         const char *authorization=NULL;
 577         char *tmp, *tmp_user;
 578 
 579         SG(request_info).query_string = r->args;
 580         SG(request_info).path_translated = r->filename;
 581         SG(request_info).request_uri = r->uri;
 582         SG(request_info).request_method = (char *)r->method;
 583         SG(request_info).proto_num = r->proto_num;
 584         SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
 585         SG(request_info).content_length = (content_length ? atol(content_length) : 0);
 586         SG(sapi_headers).http_response_code = r->status;
 587 
 588         if (r->headers_in) {
 589                 authorization = table_get(r->headers_in, "Authorization");
 590         }
 591 
 592         SG(request_info).auth_user = NULL;
 593         SG(request_info).auth_password = NULL;
 594 
 595         if (authorization && !auth_type(r)) {
 596         if (!strcasecmp(getword(r->pool, &authorization, ' '), "Basic")) {
 597             tmp = uudecode(r->pool, authorization);
 598             tmp_user = getword_nulls_nc(r->pool, &tmp, ':');
 599             if (tmp_user) {
 600                 r->connection->user = pstrdup(r->connection->pool, tmp_user);
 601                 r->connection->ap_auth_type = "Basic";
 602                 SG(request_info).auth_user = estrdup(tmp_user);
 603             }
 604             if (tmp) {
 605                 SG(request_info).auth_password = estrdup(tmp);
 606             }
 607                 } else if  (!strcasecmp(getword(r->pool, &authorization, ' '), "Digest")) {
 608             r->connection->ap_auth_type = "Digest";
 609             SG(request_info).auth_digest = estrdup(authorization);
 610                 }
 611         }
 612 }
 613 /* }}} */
 614 
 615 /* {{{ php_apache_alter_ini_entries
 616  */
 617 static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC)
 618 {
 619         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);
 620         return 0;
 621 }
 622 /* }}} */
 623 
 624 /* {{{ php_apache_get_default_mimetype
 625  */
 626 static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC)
 627 {
 628         
 629         char *mimetype;
 630         if (SG(default_mimetype) || SG(default_charset)) {
 631                 /* Assume output will be of the default MIME type.  Individual
 632                    scripts may change this later. */
 633                 char *tmpmimetype;
 634                 tmpmimetype = sapi_get_default_content_type(TSRMLS_C);
 635                 mimetype = pstrdup(r->pool, tmpmimetype);
 636                 efree(tmpmimetype);
 637         } else {
 638                 mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET;
 639         }
 640         return mimetype;
 641 }
 642 /* }}} */
 643 
 644 /* {{{ send_php
 645  */
 646 static int send_php(request_rec *r, int display_source_mode, char *filename)
 647 {
 648         int retval;
 649         php_per_dir_config *per_dir_conf;
 650         TSRMLS_FETCH();
 651         if (AP(in_request)) {
 652                 zend_file_handle fh;
 653 
 654                 fh.filename = r->filename;
 655                 fh.opened_path = NULL;
 656                 fh.free_filename = 0;
 657                 fh.type = ZEND_HANDLE_FILENAME;
 658 
 659                 zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh);
 660                 return OK;
 661         }
 662 
 663         zend_first_try {
 664 
 665                 /* Make sure file exists */
 666                 if (filename == NULL && r->finfo.st_mode == 0) {
 667                         return DECLINED;
 668                 }
 669 
 670                 per_dir_conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 671                 if (per_dir_conf) {
 672                         zend_hash_apply((HashTable *) per_dir_conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
 673                 }
 674 
 675                 /* If PHP parser engine has been turned off with an "engine off"
 676                  * directive, then decline to handle this request
 677                  */
 678                 if (!AP(engine)) {
 679                         r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
 680                         r->allowed |= (1 << METHODS) - 1;
 681                         zend_try {
 682                                 zend_ini_deactivate(TSRMLS_C);
 683                         } zend_end_try();
 684                         return DECLINED;
 685                 }
 686                 if (filename == NULL) {
 687                         filename = r->filename;
 688                 }
 689 
 690                 /* Apache 1.2 has a more complex mechanism for reading POST data */
 691 #if MODULE_MAGIC_NUMBER > 19961007
 692                 if ((retval = setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
 693                         zend_try {
 694                                 zend_ini_deactivate(TSRMLS_C);
 695                         } zend_end_try();
 696                         return retval;
 697                 }
 698 #endif
 699 
 700                 if (AP(last_modified)) {
 701 #if MODULE_MAGIC_NUMBER < 19970912
 702                         if ((retval = set_last_modified(r, r->finfo.st_mtime))) {
 703                                 zend_try {
 704                                         zend_ini_deactivate(TSRMLS_C);
 705                                 } zend_end_try();
 706                                 return retval;
 707                         }
 708 #else
 709                         update_mtime (r, r->finfo.st_mtime);
 710                         set_last_modified(r);
 711                         set_etag(r);
 712 #endif
 713                 }
 714                 /* Assume output will be of the default MIME type.  Individual
 715                    scripts may change this later in the request. */
 716                 r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
 717 
 718                 /* Init timeout */
 719                 hard_timeout("send", r);
 720 
 721                 SG(server_context) = r;
 722                 
 723                 php_save_umask();
 724                 if(!AP(setup_env)) {
 725                         AP(setup_env) = 1;
 726                         add_common_vars(r);
 727                         add_cgi_vars(r);
 728                 }
 729                 init_request_info(TSRMLS_C);
 730                 apache_php_module_main(r, display_source_mode TSRMLS_CC);
 731                 
 732                 /* Done, restore umask, turn off timeout, close file and return */
 733                 php_restore_umask();
 734                 kill_timeout(r);
 735         } zend_end_try();
 736 
 737         return OK;
 738 }
 739 /* }}} */
 740 
 741 /* {{{ send_parsed_php
 742  */
 743 static int send_parsed_php(request_rec * r)
 744 {
 745         int result = send_php(r, 0, NULL);
 746         TSRMLS_FETCH();
 747  
 748         ap_table_setn(r->notes, "mod_php_memory_usage",
 749                 ap_psprintf(r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
 750 
 751         return result;
 752 }
 753 /* }}} */
 754 
 755 /* {{{ send_parsed_php_source
 756  */
 757 static int send_parsed_php_source(request_rec * r)
 758 {
 759         return send_php(r, 1, NULL);
 760 }
 761 /* }}} */
 762 
 763 
 764 /* {{{ destroy_per_dir_entry
 765  */
 766 static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry)
 767 {
 768         free(per_dir_entry->key);
 769         free(per_dir_entry->value);
 770 }
 771 /* }}} */
 772 
 773 /* {{{ copy_per_dir_entry
 774  */
 775 static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry)
 776 {
 777         php_per_dir_entry tmp = *per_dir_entry;
 778 
 779         per_dir_entry->key = (char *) malloc(tmp.key_length+1);
 780         memcpy(per_dir_entry->key, tmp.key, tmp.key_length);
 781         per_dir_entry->key[per_dir_entry->key_length] = 0;
 782 
 783         per_dir_entry->value = (char *) malloc(tmp.value_length+1);
 784         memcpy(per_dir_entry->value, tmp.value, tmp.value_length);
 785         per_dir_entry->value[per_dir_entry->value_length] = 0;
 786 }
 787 /* }}} */
 788 
 789 /* {{{ should_overwrite_per_dir_entry;
 790 
 791  */
 792 static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_per_dir_entry *orig_per_dir_entry, zend_hash_key *hash_key, void *pData)
 793 {
 794         php_per_dir_entry *new_per_dir_entry;
 795 
 796         if (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &new_per_dir_entry)==FAILURE) {
 797                 return 1; /* does not exist in dest, copy from source */
 798         }
 799 
 800         if (new_per_dir_entry->type==PHP_INI_SYSTEM
 801                 && orig_per_dir_entry->type!=PHP_INI_SYSTEM) {
 802                 return 1;
 803         } else {
 804                 return 0;
 805         }
 806 }
 807 /* }}} */
 808 /* {{{ php_destroy_per_server_info
 809  */
 810 static void php_destroy_per_server_info(php_per_server_config *conf)
 811 {
 812         php_handler_stack_destroy(&conf->requires);
 813         php_handler_stack_destroy(&conf->uri_handlers);
 814 }
 815 /* }}} */
 816 
 817 /* {{{ php_destroy_per_dir_info
 818  */
 819 static void php_destroy_per_dir_info(php_per_dir_config *conf) 
 820 {
 821         zend_hash_destroy(conf->ini_settings);
 822         php_handler_stack_destroy(&conf->response_handlers);
 823         php_handler_stack_destroy(&conf->auth_handlers);
 824         php_handler_stack_destroy(&conf->access_handlers);
 825         php_handler_stack_destroy(&conf->type_handlers);
 826         php_handler_stack_destroy(&conf->fixup_handlers);
 827         php_handler_stack_destroy(&conf->logger_handlers);
 828         php_handler_stack_destroy(&conf->post_read_handlers);
 829         php_handler_stack_destroy(&conf->headers_handlers);
 830         free(conf->ini_settings);
 831 }
 832 /* }}} */
 833 
 834 /* {{{ php_create_server
 835  */
 836 static void *php_create_server(pool *p, char *dummy)
 837 {
 838         php_per_server_config *conf;
 839         conf = (php_per_server_config *) malloc(sizeof(php_per_server_config));
 840         register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_server_info, (void (*)(void *)) php_destroy_per_server_info);
 841         
 842         sapi_stack_init_ex(&conf->requires, 1);
 843         sapi_stack_init_ex(&conf->uri_handlers, 1);
 844         return conf;
 845 }
 846         
 847 /* }}} */
 848 
 849 
 850 /* {{{ php_create_dir
 851  */
 852 static void *php_create_dir(pool *p, char *dummy)
 853 {
 854         php_per_dir_config *conf;
 855         conf = (php_per_dir_config *) malloc(sizeof(php_per_dir_config));
 856         conf->ini_settings = (HashTable *) malloc(sizeof(HashTable));
 857         zend_hash_init_ex(conf->ini_settings, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0);
 858         sapi_stack_init_ex(&conf->response_handlers, 1);
 859         sapi_stack_init_ex(&conf->headers_handlers, 1);
 860         sapi_stack_init_ex(&conf->auth_handlers, 1);
 861         sapi_stack_init_ex(&conf->access_handlers, 1);
 862         sapi_stack_init_ex(&conf->type_handlers, 1);
 863         sapi_stack_init_ex(&conf->fixup_handlers, 1);
 864         sapi_stack_init_ex(&conf->logger_handlers, 1);
 865         sapi_stack_init_ex(&conf->post_read_handlers, 1);
 866         register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) php_destroy_per_dir_info);
 867         
 868         return conf;
 869 }
 870 
 871 /* }}} */
 872 
 873 /* {{{ php_merge_dir
 874  */
 875 static void *php_merge_dir(pool *p, void *basev, void *addv)
 876 {
 877         php_per_dir_config *a = (php_per_dir_config *) addv;
 878         php_per_dir_config *b = (php_per_dir_config *) basev;
 879         /* This function *must* return addv, and not modify basev */
 880         zend_hash_merge_ex((HashTable *) a->ini_settings, (HashTable *) b->ini_settings, (copy_ctor_func_t) copy_per_dir_entry, sizeof(php_per_dir_entry), (merge_checker_func_t) should_overwrite_per_dir_entry, NULL);
 881         a->headers_handlers = (a->headers_handlers.top)?a->headers_handlers:b->headers_handlers;
 882         a->auth_handlers = (a->auth_handlers.top)?a->auth_handlers:b->auth_handlers;
 883         a->access_handlers = (a->access_handlers.top)?a->access_handlers:b->access_handlers;
 884         a->type_handlers = (a->type_handlers.top)?a->type_handlers:b->type_handlers;
 885         a->fixup_handlers = (a->fixup_handlers.top)?a->fixup_handlers:b->fixup_handlers;
 886         a->logger_handlers = (a->logger_handlers.top)?a->logger_handlers:b->logger_handlers;
 887         a->post_read_handlers = (a->post_read_handlers.top)?a->post_read_handlers:b->post_read_handlers;
 888         a->response_handlers = (a->response_handlers.top)?a->response_handlers:b->response_handlers;
 889         return a;
 890 }
 891 /* }}} */
 892 
 893 /* {{{ php_apache_value_handler_ex
 894  */
 895 static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
 896 {
 897         php_per_dir_entry per_dir_entry;
 898 
 899         if (!apache_php_initialized) {
 900                 apache_php_initialized = 1;
 901 #ifdef ZTS
 902                 tsrm_startup(1, 1, 0, NULL);
 903 #endif
 904                 sapi_startup(&apache_sapi_module);
 905                 php_apache_startup(&apache_sapi_module);
 906         }
 907         per_dir_entry.type = mode;
 908 
 909         if (strcasecmp(arg2, "none") == 0) {
 910                 arg2 = "";
 911         }
 912 
 913         per_dir_entry.key_length = strlen(arg1);
 914         per_dir_entry.value_length = strlen(arg2);
 915 
 916         per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1);
 917         memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);
 918         per_dir_entry.key[per_dir_entry.key_length] = 0;
 919 
 920         per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1);
 921         memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length);
 922         per_dir_entry.value[per_dir_entry.value_length] = 0;
 923 
 924         zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL);
 925         return NULL;
 926 }
 927 /* }}} */
 928 
 929 static CONST_PREFIX char *php_set_server_handler(server_rec *s, char *arg1, long handler_stage, long handler_type)
 930 {
 931         php_per_server_config *conf;
 932         php_handler *handler;
 933         handler = (php_handler *) malloc(sizeof(php_handler));
 934         handler->type = handler_type;
 935         handler->stage = handler_stage;
 936         handler->name = strdup(arg1);
 937         conf = get_module_config(s->module_config, &php5_module);
 938         switch(handler_stage) {
 939                 case AP_URI_TRANS:
 940                         sapi_stack_push(&conf->uri_handlers, handler);
 941                         break;
 942                 default:
 943                         sapi_stack_push(&conf->requires, handler);
 944                         break;
 945         }
 946         return NULL;
 947 }
 948 
 949 static CONST_PREFIX char *php_set_dir_handler(php_per_dir_config *conf, char *arg1, long handler_stage, long handler_type)
 950 {
 951         php_handler *handler;
 952         handler = (php_handler *) malloc(sizeof(php_handler));
 953         handler->type = handler_type;
 954         handler->stage = handler_stage;
 955         handler->name = strdup(arg1);
 956         switch(handler_stage) {
 957                 case AP_POST_READ:
 958                         sapi_stack_push(&conf->post_read_handlers, handler);
 959                         break;
 960                 case AP_HEADER_PARSE:
 961                         sapi_stack_push(&conf->headers_handlers, handler);
 962                         break;
 963                 case AP_ACCESS_CONTROL:
 964                         sapi_stack_push(&conf->access_handlers, handler);
 965                         break;
 966                 case AP_AUTHENTICATION:
 967                         sapi_stack_push(&conf->auth_handlers, handler);
 968                         break;
 969                 case AP_AUTHORIZATION:
 970                         break;
 971                 case AP_TYPE_CHECKING:
 972                         sapi_stack_push(&conf->type_handlers, handler);
 973                         break;
 974                 case AP_FIXUP:
 975                         sapi_stack_push(&conf->fixup_handlers, handler);
 976                         break;
 977                 case AP_RESPONSE:
 978                         sapi_stack_push(&conf->response_handlers, handler);
 979                         break;
 980                 case AP_LOGGING:
 981                         sapi_stack_push(&conf->logger_handlers, handler);
 982                         break;
 983                 default:
 984                         break;
 985         }
 986         return NULL;
 987 }
 988 
 989 /* {{{ php_set_uri_handler 
 990  */
 991 static CONST_PREFIX char *php_set_uri_handler(cmd_parms *cmd, void *dummy, char *arg1)
 992 {
 993         return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_FILE);
 994 }
 995 /* }}} */
 996 
 997 /* {{{ php_set_uri_handler_code */
 998 static CONST_PREFIX char *php_set_uri_handler_code(cmd_parms *cmd, void *dummy, char *arg1)
 999 {
1000         return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_METHOD);
1001 }
1002 /* }}} */
1003 
1004 /* {{{ php_set_header_handler
1005  */
1006 static CONST_PREFIX char *php_set_header_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1007 {
1008         return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_FILE);
1009 }
1010 static CONST_PREFIX char *php_set_header_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1011 {
1012         return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_METHOD);
1013 }
1014 /* }}} */
1015 
1016 /* {{{ php_set_auth_handler 
1017  */
1018 static CONST_PREFIX char *php_set_auth_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1019 {
1020         return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_FILE);
1021 }
1022 static CONST_PREFIX char *php_set_auth_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1023 {
1024         return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_METHOD);
1025 }
1026 
1027 /* }}} */
1028 
1029 /* {{{ php_set_access_handler
1030  */
1031 static CONST_PREFIX char *php_set_access_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1032 {
1033         return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_FILE);
1034 }
1035 static CONST_PREFIX char *php_set_access_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1036 {
1037         return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_METHOD);
1038 }
1039 
1040 /* }}} */
1041 
1042 /* {{{ php_set_type_handler
1043  */
1044 static CONST_PREFIX char *php_set_type_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1045 {
1046         return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_FILE);
1047 }
1048 static CONST_PREFIX char *php_set_type_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1049 {
1050         return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_METHOD);
1051 }
1052 
1053 /* }}} */
1054 
1055 /* {{{ php_set_fixup_handler
1056  */
1057 static CONST_PREFIX char *php_set_fixup_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1058 {
1059         return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_FILE);
1060 }
1061 static CONST_PREFIX char *php_set_fixup_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1062 {
1063         return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_METHOD);
1064 }
1065 /* }}} */
1066 
1067 /* {{{ php_set_logger_handler
1068  */
1069 static CONST_PREFIX char *php_set_logger_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1070 {
1071         return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_FILE);
1072 }
1073 static CONST_PREFIX char *php_set_logger_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1074 {
1075         return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_METHOD);
1076 }
1077 
1078 /* }}} */ 
1079 
1080 /* {{{ php_set_post_read_handler
1081  */
1082 static CONST_PREFIX char *php_set_post_read_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1083 {
1084         return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_FILE);
1085 }
1086 static CONST_PREFIX char *php_set_post_read_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1087 {
1088         return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_METHOD);
1089 }
1090 
1091 
1092 /* }}} */
1093 
1094 /* {{{ php_set_require
1095  */
1096 
1097 static CONST_PREFIX char *php_set_require(cmd_parms *cmd, void *dummy, char *arg1)
1098 {
1099         return php_set_server_handler(cmd->server, arg1, 0, AP_HANDLER_TYPE_FILE);
1100 }
1101 /* }}} */
1102 
1103 /* {{{ php_set_response_handler
1104  */
1105 static CONST_PREFIX char *php_set_response_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1106 {
1107         return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_FILE);
1108 }
1109 static CONST_PREFIX char *php_set_response_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
1110 {
1111         return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_METHOD);
1112 }
1113 /* }}} */
1114         
1115 /* {{{ php_apache_value_handler
1116  */
1117 static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
1118 {
1119         return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR);
1120 }
1121 /* }}} */
1122 
1123 /* {{{ php_apache_admin_value_handler
1124  */
1125 static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
1126 {
1127         return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM);
1128 }
1129 /* }}} */
1130 
1131 /* {{{ php_apache_flag_handler_ex
1132  */
1133 static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
1134 {
1135         char bool_val[2];
1136 
1137         if (!strcasecmp(arg2, "On")) {
1138                 bool_val[0] = '1';
1139         } else {
1140                 bool_val[0] = '0';
1141         }
1142         bool_val[1] = 0;
1143         
1144         return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode);
1145 }
1146 /* }}} */
1147 
1148 /* {{{ php_apache_flag_handler
1149  */
1150 static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
1151 {
1152         return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR);
1153 }
1154 /* }}} */
1155 
1156 /* {{{ php_apache_admin_flag_handler
1157  */
1158 static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
1159 {
1160         return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM);
1161 }
1162 /* }}} */
1163 
1164 /* {{{ php_apache_phpini_set
1165  */
1166 static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg)
1167 {
1168         if (apache_sapi_module.php_ini_path_override) {
1169                 return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored";
1170         }
1171         apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg);
1172         return NULL;
1173 }
1174 /* }}} */
1175 
1176 /* {{{ int php_xbithack_handler(request_rec * r)
1177  */
1178 static int php_xbithack_handler(request_rec * r)
1179 {
1180         php_per_dir_config *conf;
1181         TSRMLS_FETCH();
1182 
1183         if (!(r->finfo.st_mode & S_IXUSR)) {
1184                 r->allowed |= (1 << METHODS) - 1;
1185                 return DECLINED;
1186         }
1187         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1188         if (conf) {
1189                 zend_hash_apply((HashTable *) conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
1190         }
1191         if(!AP(xbithack)) {
1192                 r->allowed |= (1 << METHODS) - 1;
1193                 zend_try {
1194                         zend_ini_deactivate(TSRMLS_C);
1195                 } zend_end_try();
1196                 return DECLINED;
1197         }
1198         return send_parsed_php(r);
1199 }
1200 /* }}} */
1201 
1202 /* {{{ apache_php_module_shutdown_wrapper
1203  */
1204 static void apache_php_module_shutdown_wrapper(void)
1205 {
1206         apache_php_initialized = 0;
1207         apache_sapi_module.shutdown(&apache_sapi_module);
1208 
1209 #if MODULE_MAGIC_NUMBER >= 19970728
1210         /* This function is only called on server exit if the apache API
1211          * child_exit handler exists, so shutdown globally 
1212          */
1213         sapi_shutdown();
1214 #endif
1215 
1216 #ifdef ZTS
1217         tsrm_shutdown();
1218 #endif
1219 }
1220 /* }}} */
1221 
1222 #if MODULE_MAGIC_NUMBER >= 19970728
1223 /* {{{ php_child_exit_handler
1224  */
1225 static void php_child_exit_handler(server_rec *s, pool *p)
1226 {
1227 /*      apache_php_initialized = 0; */
1228         apache_sapi_module.shutdown(&apache_sapi_module);
1229 
1230 #ifdef ZTS
1231         tsrm_shutdown();
1232 #endif
1233 }
1234 /* }}} */
1235 #endif
1236 
1237 /* {{{ void php_init_handler(server_rec *s, pool *p)
1238  */
1239 static void php_init_handler(server_rec *s, pool *p)
1240 {
1241         register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);
1242         if (!apache_php_initialized) {
1243                 apache_php_initialized = 1;
1244 #ifdef ZTS
1245                 tsrm_startup(1, 1, 0, NULL);
1246 #endif
1247                 sapi_startup(&apache_sapi_module);
1248                 php_apache_startup(&apache_sapi_module);
1249         }
1250 #if MODULE_MAGIC_NUMBER >= 19980527
1251         {
1252                 TSRMLS_FETCH();
1253                 if (PG(expose_php)) {
1254                         ap_add_version_component("PHP/" PHP_VERSION);
1255                 }
1256         }
1257 #endif
1258 }
1259 /* }}} */
1260 
1261 static int php_run_hook(php_handler *handler, request_rec *r)
1262 {
1263         zval *ret = NULL;
1264         php_per_dir_config *conf;
1265 
1266         TSRMLS_FETCH();
1267 
1268         if(!AP(apache_config_loaded)) {
1269                 conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1270                 if (conf)
1271                            zend_hash_apply((HashTable *)conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
1272                 AP(apache_config_loaded) = 1;
1273         }
1274         if (!handler->name) {
1275                 return DECLINED;
1276         }
1277         php_save_umask();
1278         if (!AP(setup_env)) {
1279                 AP(setup_env) = 1;
1280                 add_common_vars(r);
1281                 add_cgi_vars(r);
1282         }
1283         SG(server_context) = r;
1284         init_request_info(TSRMLS_C);
1285         apache_php_module_hook(r, handler, &ret TSRMLS_CC);
1286         php_restore_umask();
1287         kill_timeout(r);
1288         if (ret) {
1289                 convert_to_long(ret);
1290                 return Z_LVAL_P(ret);
1291         }
1292         return HTTP_INTERNAL_SERVER_ERROR;
1293 }
1294  
1295 
1296 static int php_uri_translation(request_rec *r)
1297 {       
1298         php_per_server_config *conf;
1299         TSRMLS_FETCH();
1300         AP(current_hook) = AP_URI_TRANS;
1301         conf = (php_per_server_config *) get_module_config(r->server->module_config, &php5_module);
1302         return sapi_stack_apply_with_argument_stop_if_equals(&conf->uri_handlers, 
1303                         ZEND_STACK_APPLY_BOTTOMUP, 
1304                         (int (*)(void *element, void *)) php_run_hook, r, OK);
1305 }
1306 
1307 static int php_header_hook(request_rec *r)
1308 {
1309         php_per_dir_config *conf;
1310         TSRMLS_FETCH();
1311         AP(current_hook) = AP_HEADER_PARSE;
1312         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1313         return sapi_stack_apply_with_argument_stop_if_http_error(&conf->headers_handlers,
1314                         ZEND_STACK_APPLY_BOTTOMUP,
1315                         (int (*)(void *element, void *)) php_run_hook, r);
1316 }
1317 
1318 static int php_auth_hook(request_rec *r)
1319 {
1320         php_per_dir_config *conf;
1321         TSRMLS_FETCH();
1322         AP(current_hook) = AP_AUTHENTICATION;
1323         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1324         return sapi_stack_apply_with_argument_stop_if_equals(&conf->auth_handlers, 
1325                         ZEND_STACK_APPLY_BOTTOMUP, 
1326                         (int (*)(void *element, void *)) php_run_hook, r, OK);
1327 }
1328 
1329 static int php_access_hook(request_rec *r)
1330 {
1331         php_per_dir_config *conf;
1332         int status = DECLINED;
1333         TSRMLS_FETCH();
1334         AP(current_hook) = AP_ACCESS_CONTROL;
1335         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1336         status =  sapi_stack_apply_with_argument_stop_if_http_error(&conf->access_handlers,
1337                         ZEND_STACK_APPLY_BOTTOMUP,
1338                         (int (*)(void *element, void *)) php_run_hook, r);
1339         return status;
1340 
1341 }
1342 
1343 static int php_type_hook(request_rec *r)
1344 {
1345         php_per_dir_config *conf;
1346         TSRMLS_FETCH();
1347         AP(current_hook) = AP_TYPE_CHECKING;
1348         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1349         return sapi_stack_apply_with_argument_stop_if_equals(&conf->type_handlers,
1350                         ZEND_STACK_APPLY_BOTTOMUP,
1351                         (int (*)(void *element, void *)) php_run_hook,
1352                         r, OK);
1353 }
1354 
1355 static int php_fixup_hook(request_rec *r)
1356 {
1357         php_per_dir_config *conf;
1358         TSRMLS_FETCH();
1359         AP(current_hook) = AP_FIXUP;
1360         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1361         return sapi_stack_apply_with_argument_stop_if_http_error(&conf->fixup_handlers,
1362                         ZEND_STACK_APPLY_BOTTOMUP,
1363                         (int (*)(void *element, void *)) php_run_hook,
1364                         r);
1365 }
1366 
1367 static int php_logger_hook(request_rec *r)
1368 {
1369         php_per_dir_config *conf;
1370         TSRMLS_FETCH();
1371         AP(current_hook) = AP_LOGGING;
1372         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1373         return sapi_stack_apply_with_argument_stop_if_http_error(&conf->logger_handlers,
1374                         ZEND_STACK_APPLY_BOTTOMUP,
1375                         (int (*)(void *element, void *)) php_run_hook,
1376                         r);
1377 }
1378  
1379 static int php_post_read_hook(request_rec *r)
1380 {
1381         php_per_dir_config *conf;
1382         php_per_server_config *svr;
1383         TSRMLS_FETCH();
1384         AP(current_hook) = AP_POST_READ;
1385         svr = get_module_config(r->server->module_config, &php5_module);
1386         if(ap_is_initial_req(r)) {
1387                 sapi_stack_apply_with_argument_all(&svr->requires, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r);
1388         }
1389         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1390         return sapi_stack_apply_with_argument_stop_if_http_error(&conf->post_read_handlers,
1391                         ZEND_STACK_APPLY_BOTTOMUP,
1392                         (int (*)(void *element, void *)) php_run_hook, r);
1393 }
1394 
1395 static int php_response_handler(request_rec *r)
1396 {
1397         php_per_dir_config *conf;
1398         TSRMLS_FETCH();
1399         AP(current_hook) = AP_RESPONSE;
1400         conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
1401         return sapi_stack_apply_with_argument_all(&conf->response_handlers, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r);
1402 }
1403 
1404 /* {{{ handler_rec php_handlers[]
1405  */
1406 handler_rec php_handlers[] =
1407 {
1408         {"application/x-httpd-php", send_parsed_php},
1409         {"application/x-httpd-php-source", send_parsed_php_source},
1410         {"text/html", php_xbithack_handler},
1411                 {"php-script", php_response_handler},
1412         {NULL}
1413 };
1414 /* }}} */
1415 
1416 /* {{{ command_rec php_commands[]
1417  */
1418 command_rec php_commands[] =
1419 {
1420         {"php_value",           php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"},
1421         {"phpUriHandler",               php_set_uri_handler, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"},
1422         {"phpUriHandlerMethod",         php_set_uri_handler_code, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"},
1423 #if MODULE_MAGIC_NUMBER >= 19970103
1424         {"phpHeaderHandler",            php_set_header_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1425         {"phpHeaderHandlerMethod",              php_set_header_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1426 #endif
1427         {"phpAuthHandler",              php_set_auth_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1428         {"phpAuthHandlerMethod",                php_set_auth_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1429         {"phpAccessHandler",            php_set_access_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1430         {"phpAccessHandlerMethod",              php_set_access_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1431         {"phpTypeHandler",              php_set_type_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1432         {"phpTypeHandlerMethod",                php_set_type_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1433         {"phpFixupHandler",             php_set_fixup_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1434         {"phpFixupHandlerMethod",               php_set_fixup_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1435         {"phpLoggerHandler",                    php_set_logger_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1436         {"phpLoggerHandlerMethod",              php_set_logger_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1437 #if MODULE_MAGIC_NUMBER >= 19970902
1438         {"phpPostReadHandler",          php_set_post_read_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1439         {"phpPostReadHandlerMethod",            php_set_post_read_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1440         {"phpRequire",          php_set_require, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1441         {"phpResponseHandler",          php_set_response_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1442         {"phpResponseHandlerMethod",            php_set_response_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
1443 #endif
1444         {"php_flag",            php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"},
1445         {"php_admin_value",     php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"},
1446         {"php_admin_flag",      php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"},
1447         {"PHPINIDir",       php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"},
1448         {NULL}
1449 };
1450 /* }}} */
1451 
1452 /* {{{ module MODULE_VAR_EXPORT php5_module
1453  */
1454 module MODULE_VAR_EXPORT php5_module =
1455 {
1456         STANDARD_MODULE_STUFF,
1457         php_init_handler,                       /* initializer */
1458         php_create_dir,                         /* per-directory config creator */
1459         php_merge_dir,                          /* dir merger */
1460         php_create_server,                      /* per-server config creator */
1461         NULL,                                           /* merge server config */
1462         php_commands,                           /* command table */
1463         php_handlers,                           /* handlers */
1464         php_uri_translation,            /* filename translation */
1465         NULL,                                           /* check_user_id */
1466         php_auth_hook,                          /* check auth */
1467         php_access_hook,                        /* check access */
1468         php_type_hook,                          /* type_checker */
1469         php_fixup_hook,                         /* fixups */
1470         php_logger_hook                         /* logger */
1471 #if MODULE_MAGIC_NUMBER >= 19970103
1472         , php_header_hook                                               /* header parser */
1473 #endif
1474 #if MODULE_MAGIC_NUMBER >= 19970719
1475         , NULL                                          /* child_init */
1476 #endif
1477 #if MODULE_MAGIC_NUMBER >= 19970728
1478         , php_child_exit_handler        /* child_exit */
1479 #endif
1480 #if MODULE_MAGIC_NUMBER >= 19970902
1481         , php_post_read_hook                                            /* post read-request */
1482 #endif
1483 };
1484 /* }}} */
1485 
1486 /*
1487  * Local variables:
1488  * tab-width: 4
1489  * c-basic-offset: 4
1490  * End:
1491  * vim600: sw=4 ts=4 fdm=marker
1492  * vim<600: sw=4 ts=4
1493  */

/* [<][>][^][v][top][bottom][index][help] */