root/sapi/apache/mod_php5.c

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

DEFINITIONS

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

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