root/sapi/apache2handler/sapi_apache2.c

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

DEFINITIONS

This source file includes following definitions.
  1. ZEND_TSRMLS_CACHE_DEFINE
  2. php_apache_sapi_header_handler
  3. php_apache_sapi_send_headers
  4. php_apache_sapi_read_post
  5. php_apache_sapi_get_stat
  6. php_apache_sapi_read_cookies
  7. php_apache_sapi_getenv
  8. php_apache_sapi_register_variables
  9. php_apache_sapi_flush
  10. php_apache_sapi_log_message
  11. php_apache_sapi_log_message_ex
  12. php_apache_sapi_get_request_time
  13. php_apache2_startup
  14. php_apache_server_shutdown
  15. php_apache_child_shutdown
  16. php_apache_add_version
  17. php_pre_config
  18. php_apache_server_startup
  19. php_server_context_cleanup
  20. php_apache_request_ctor
  21. php_apache_request_dtor
  22. php_apache_ini_dtor
  23. php_handler
  24. php_apache_child_init
  25. php_ap2_register_hook

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   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: Sascha Schumann <sascha@schumann.cx>                        |
  16    |          Parts based on Apache 1.3 SAPI module by                    |
  17    |          Rasmus Lerdorf and Zeev Suraski                             |
  18    +----------------------------------------------------------------------+
  19  */
  20 
  21 /* $Id$ */
  22 
  23 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
  24 
  25 #include "php.h"
  26 #include "php_main.h"
  27 #include "php_ini.h"
  28 #include "php_variables.h"
  29 #include "SAPI.h"
  30 
  31 #include <fcntl.h>
  32 
  33 #include "zend_smart_str.h"
  34 #ifndef NETWARE
  35 #include "ext/standard/php_standard.h"
  36 #else
  37 #include "ext/standard/basic_functions.h"
  38 #endif
  39 
  40 #include "apr_strings.h"
  41 #include "ap_config.h"
  42 #include "util_filter.h"
  43 #include "httpd.h"
  44 #include "http_config.h"
  45 #include "http_request.h"
  46 #include "http_core.h"
  47 #include "http_protocol.h"
  48 #include "http_log.h"
  49 #include "http_main.h"
  50 #include "util_script.h"
  51 #include "http_core.h"
  52 #include "ap_mpm.h"
  53 
  54 #include "php_apache.h"
  55 
  56 /* UnixWare and Netware define shutdown to _shutdown, which causes problems later
  57  * on when using a structure member named shutdown. Since this source
  58  * file does not use the system call shutdown, it is safe to #undef it.K
  59  */
  60 #undef shutdown
  61 
  62 #define PHP_MAGIC_TYPE "application/x-httpd-php"
  63 #define PHP_SOURCE_MAGIC_TYPE "application/x-httpd-php-source"
  64 #define PHP_SCRIPT "php7-script"
  65 
  66 /* A way to specify the location of the php.ini dir in an apache directive */
  67 char *apache2_php_ini_path_override = NULL;
  68 #if defined(PHP_WIN32) && defined(ZTS)
  69 ZEND_TSRMLS_CACHE_DEFINE()
  70 #endif
  71 
  72 static size_t
  73 php_apache_sapi_ub_write(const char *str, size_t str_length)
  74 {
  75         request_rec *r;
  76         php_struct *ctx;
  77 
  78         ctx = SG(server_context);
  79         r = ctx->r;
  80 
  81         if (ap_rwrite(str, str_length, r) < 0) {
  82                 php_handle_aborted_connection();
  83         }
  84 
  85         return str_length; /* we always consume all the data passed to us. */
  86 }
  87 
  88 static int
  89 php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers)
  90 {
  91         php_struct *ctx;
  92         char *val, *ptr;
  93 
  94         ctx = SG(server_context);
  95 
  96         switch (op) {
  97                 case SAPI_HEADER_DELETE:
  98                         apr_table_unset(ctx->r->headers_out, sapi_header->header);
  99                         return 0;
 100 
 101                 case SAPI_HEADER_DELETE_ALL:
 102                         apr_table_clear(ctx->r->headers_out);
 103                         return 0;
 104 
 105                 case SAPI_HEADER_ADD:
 106                 case SAPI_HEADER_REPLACE:
 107                         val = strchr(sapi_header->header, ':');
 108 
 109                         if (!val) {
 110                                 return 0;
 111                         }
 112                         ptr = val;
 113 
 114                         *val = '\0';
 115 
 116                         do {
 117                                 val++;
 118                         } while (*val == ' ');
 119 
 120                         if (!strcasecmp(sapi_header->header, "content-type")) {
 121                                 if (ctx->content_type) {
 122                                         efree(ctx->content_type);
 123                                 }
 124                                 ctx->content_type = estrdup(val);
 125                         } else if (!strcasecmp(sapi_header->header, "content-length")) {
 126                                 apr_off_t clen = 0;
 127 
 128                                 if (APR_SUCCESS != apr_strtoff(&clen, val, (char **) NULL, 10)) {
 129                                         /* We'll fall back to strtol, since that's what we used to
 130                                          * do anyway. */
 131                                         clen = (apr_off_t) strtol(val, (char **) NULL, 10);
 132                                 }
 133 
 134                                 ap_set_content_length(ctx->r, clen);
 135                         } else if (op == SAPI_HEADER_REPLACE) {
 136                                 apr_table_set(ctx->r->headers_out, sapi_header->header, val);
 137                         } else {
 138                                 apr_table_add(ctx->r->headers_out, sapi_header->header, val);
 139                         }
 140 
 141                         *ptr = ':';
 142 
 143                         return SAPI_HEADER_ADD;
 144 
 145                 default:
 146                         return 0;
 147         }
 148 }
 149 
 150 static int
 151 php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers)
 152 {
 153         php_struct *ctx = SG(server_context);
 154         const char *sline = SG(sapi_headers).http_status_line;
 155 
 156         ctx->r->status = SG(sapi_headers).http_response_code;
 157 
 158         /* httpd requires that r->status_line is set to the first digit of
 159          * the status-code: */
 160         if (sline && strlen(sline) > 12 && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
 161                 ctx->r->status_line = apr_pstrdup(ctx->r->pool, sline + 9);
 162                 ctx->r->proto_num = 1000 + (sline[7]-'0');
 163                 if ((sline[7]-'0') == 0) {
 164                         apr_table_set(ctx->r->subprocess_env, "force-response-1.0", "true");
 165                 }
 166         }
 167 
 168         /*      call ap_set_content_type only once, else each time we call it,
 169                 configured output filters for that content type will be added */
 170         if (!ctx->content_type) {
 171                 ctx->content_type = sapi_get_default_content_type();
 172         }
 173         ap_set_content_type(ctx->r, apr_pstrdup(ctx->r->pool, ctx->content_type));
 174         efree(ctx->content_type);
 175         ctx->content_type = NULL;
 176 
 177         return SAPI_HEADER_SENT_SUCCESSFULLY;
 178 }
 179 
 180 static apr_size_t
 181 php_apache_sapi_read_post(char *buf, size_t count_bytes)
 182 {
 183         apr_size_t len, tlen=0;
 184         php_struct *ctx = SG(server_context);
 185         request_rec *r;
 186         apr_bucket_brigade *brigade;
 187 
 188         r = ctx->r;
 189         brigade = ctx->brigade;
 190         len = count_bytes;
 191 
 192         /*
 193          * This loop is needed because ap_get_brigade() can return us partial data
 194          * which would cause premature termination of request read. Therefor we
 195          * need to make sure that if data is available we fill the buffer completely.
 196          */
 197 
 198         while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
 199                 apr_brigade_flatten(brigade, buf, &len);
 200                 apr_brigade_cleanup(brigade);
 201                 tlen += len;
 202                 if (tlen == count_bytes || !len) {
 203                         break;
 204                 }
 205                 buf += len;
 206                 len = count_bytes - tlen;
 207         }
 208 
 209         return tlen;
 210 }
 211 
 212 static zend_stat_t*
 213 php_apache_sapi_get_stat(void)
 214 {
 215         php_struct *ctx = SG(server_context);
 216 
 217 #ifdef PHP_WIN32
 218         ctx->finfo.st_uid = 0;
 219         ctx->finfo.st_gid = 0;
 220 #else
 221         ctx->finfo.st_uid = ctx->r->finfo.user;
 222         ctx->finfo.st_gid = ctx->r->finfo.group;
 223 #endif
 224         ctx->finfo.st_dev = ctx->r->finfo.device;
 225         ctx->finfo.st_ino = ctx->r->finfo.inode;
 226 #if defined(NETWARE) && defined(CLIB_STAT_PATCH)
 227         ctx->finfo.st_atime.tv_sec = apr_time_sec(ctx->r->finfo.atime);
 228         ctx->finfo.st_mtime.tv_sec = apr_time_sec(ctx->r->finfo.mtime);
 229         ctx->finfo.st_ctime.tv_sec = apr_time_sec(ctx->r->finfo.ctime);
 230 #else
 231         ctx->finfo.st_atime = apr_time_sec(ctx->r->finfo.atime);
 232         ctx->finfo.st_mtime = apr_time_sec(ctx->r->finfo.mtime);
 233         ctx->finfo.st_ctime = apr_time_sec(ctx->r->finfo.ctime);
 234 #endif
 235 
 236         ctx->finfo.st_size = ctx->r->finfo.size;
 237         ctx->finfo.st_nlink = ctx->r->finfo.nlink;
 238 
 239         return &ctx->finfo;
 240 }
 241 
 242 static char *
 243 php_apache_sapi_read_cookies(void)
 244 {
 245         php_struct *ctx = SG(server_context);
 246         const char *http_cookie;
 247 
 248         http_cookie = apr_table_get(ctx->r->headers_in, "cookie");
 249 
 250         /* The SAPI interface should use 'const char *' */
 251         return (char *) http_cookie;
 252 }
 253 
 254 static char *
 255 php_apache_sapi_getenv(char *name, size_t name_len)
 256 {
 257         php_struct *ctx = SG(server_context);
 258         const char *env_var;
 259 
 260         if (ctx == NULL) {
 261                 return NULL;
 262         }
 263 
 264         env_var = apr_table_get(ctx->r->subprocess_env, name);
 265 
 266         return (char *) env_var;
 267 }
 268 
 269 static void
 270 php_apache_sapi_register_variables(zval *track_vars_array)
 271 {
 272         php_struct *ctx = SG(server_context);
 273         const apr_array_header_t *arr = apr_table_elts(ctx->r->subprocess_env);
 274         char *key, *val;
 275         size_t new_val_len;
 276 
 277         APR_ARRAY_FOREACH_OPEN(arr, key, val)
 278                 if (!val) {
 279                         val = "";
 280                 }
 281                 if (sapi_module.input_filter(PARSE_SERVER, key, &val, strlen(val), &new_val_len)) {
 282                         php_register_variable_safe(key, val, new_val_len, track_vars_array);
 283                 }
 284         APR_ARRAY_FOREACH_CLOSE()
 285 
 286         if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len)) {
 287                 php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array);
 288         }
 289 }
 290 
 291 static void
 292 php_apache_sapi_flush(void *server_context)
 293 {
 294         php_struct *ctx;
 295         request_rec *r;
 296 
 297         ctx = server_context;
 298 
 299         /* If we haven't registered a server_context yet,
 300          * then don't bother flushing. */
 301         if (!server_context) {
 302                 return;
 303         }
 304 
 305         r = ctx->r;
 306 
 307         sapi_send_headers();
 308 
 309         r->status = SG(sapi_headers).http_response_code;
 310         SG(headers_sent) = 1;
 311 
 312         if (ap_rflush(r) < 0 || r->connection->aborted) {
 313                 php_handle_aborted_connection();
 314         }
 315 }
 316 
 317 static void php_apache_sapi_log_message(char *msg)
 318 {
 319         php_struct *ctx;
 320 
 321         ctx = SG(server_context);
 322 
 323         if (ctx == NULL) { /* we haven't initialized our ctx yet, oh well */
 324                 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "%s", msg);
 325         } else {
 326                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, "%s", msg);
 327         }
 328 }
 329 
 330 static void php_apache_sapi_log_message_ex(char *msg, request_rec *r)
 331 {
 332         if (r) {
 333                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, msg, r->filename);
 334         } else {
 335                 php_apache_sapi_log_message(msg);
 336         }
 337 }
 338 
 339 static double php_apache_sapi_get_request_time(void)
 340 {
 341         php_struct *ctx = SG(server_context);
 342         return ((double) apr_time_as_msec(ctx->r->request_time)) / 1000.0;
 343 }
 344 
 345 extern zend_module_entry php_apache_module;
 346 
 347 static int php_apache2_startup(sapi_module_struct *sapi_module)
 348 {
 349         if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) {
 350                 return FAILURE;
 351         }
 352         return SUCCESS;
 353 }
 354 
 355 static sapi_module_struct apache2_sapi_module = {
 356         "apache2handler",
 357         "Apache 2.0 Handler",
 358 
 359         php_apache2_startup,                            /* startup */
 360         php_module_shutdown_wrapper,                    /* shutdown */
 361 
 362         NULL,                                           /* activate */
 363         NULL,                                           /* deactivate */
 364 
 365         php_apache_sapi_ub_write,                       /* unbuffered write */
 366         php_apache_sapi_flush,                          /* flush */
 367         php_apache_sapi_get_stat,                       /* get uid */
 368         php_apache_sapi_getenv,                         /* getenv */
 369 
 370         php_error,                                      /* error handler */
 371 
 372         php_apache_sapi_header_handler,                 /* header handler */
 373         php_apache_sapi_send_headers,                   /* send headers handler */
 374         NULL,                                           /* send header handler */
 375 
 376         php_apache_sapi_read_post,                      /* read POST data */
 377         php_apache_sapi_read_cookies,                   /* read Cookies */
 378 
 379         php_apache_sapi_register_variables,
 380         php_apache_sapi_log_message,                    /* Log message */
 381         php_apache_sapi_get_request_time,               /* Request Time */
 382         NULL,                                           /* Child Terminate */
 383 
 384         STANDARD_SAPI_MODULE_PROPERTIES
 385 };
 386 
 387 static apr_status_t php_apache_server_shutdown(void *tmp)
 388 {
 389         apache2_sapi_module.shutdown(&apache2_sapi_module);
 390         sapi_shutdown();
 391 #ifdef ZTS
 392         tsrm_shutdown();
 393 #endif
 394         return APR_SUCCESS;
 395 }
 396 
 397 static apr_status_t php_apache_child_shutdown(void *tmp)
 398 {
 399         apache2_sapi_module.shutdown(&apache2_sapi_module);
 400 #if defined(ZTS) && !defined(PHP_WIN32)
 401         tsrm_shutdown();
 402 #endif
 403         return APR_SUCCESS;
 404 }
 405 
 406 static void php_apache_add_version(apr_pool_t *p)
 407 {
 408         if (PG(expose_php)) {
 409                 ap_add_version_component(p, "PHP/" PHP_VERSION);
 410         }
 411 }
 412 
 413 static int php_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
 414 {
 415 #ifndef ZTS
 416         int threaded_mpm;
 417 
 418         ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
 419         if(threaded_mpm) {
 420                 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 0, "Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe.  You need to recompile PHP.");
 421                 return DONE;
 422         }
 423 #endif
 424         /* When this is NULL, apache won't override the hard-coded default
 425          * php.ini path setting. */
 426         apache2_php_ini_path_override = NULL;
 427         return OK;
 428 }
 429 
 430 static int
 431 php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
 432 {
 433         void *data = NULL;
 434         const char *userdata_key = "apache2hook_post_config";
 435 
 436         /* Apache will load, unload and then reload a DSO module. This
 437          * prevents us from starting PHP until the second load. */
 438         apr_pool_userdata_get(&data, userdata_key, s->process->pool);
 439         if (data == NULL) {
 440                 /* We must use set() here and *not* setn(), otherwise the
 441                  * static string pointed to by userdata_key will be mapped
 442                  * to a different location when the DSO is reloaded and the
 443                  * pointers won't match, causing get() to return NULL when
 444                  * we expected it to return non-NULL. */
 445                 apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, s->process->pool);
 446                 return OK;
 447         }
 448 
 449         /* Set up our overridden path. */
 450         if (apache2_php_ini_path_override) {
 451                 apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override;
 452         }
 453 #ifdef ZTS
 454         tsrm_startup(1, 1, 0, NULL);
 455         (void)ts_resource(0);
 456         ZEND_TSRMLS_CACHE_UPDATE();
 457 #endif
 458 
 459 #ifdef ZEND_SIGNALS
 460         zend_signal_startup();
 461 #endif
 462 
 463         sapi_startup(&apache2_sapi_module);
 464         apache2_sapi_module.startup(&apache2_sapi_module);
 465         apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null);
 466         php_apache_add_version(pconf);
 467 
 468         return OK;
 469 }
 470 
 471 static apr_status_t php_server_context_cleanup(void *data_)
 472 {
 473         void **data = data_;
 474         *data = NULL;
 475         return APR_SUCCESS;
 476 }
 477 
 478 static int php_apache_request_ctor(request_rec *r, php_struct *ctx)
 479 {
 480         char *content_length;
 481         const char *auth;
 482 
 483         SG(sapi_headers).http_response_code = !r->status ? HTTP_OK : r->status;
 484         SG(request_info).content_type = apr_table_get(r->headers_in, "Content-Type");
 485         SG(request_info).query_string = apr_pstrdup(r->pool, r->args);
 486         SG(request_info).request_method = r->method;
 487         SG(request_info).proto_num = r->proto_num;
 488         SG(request_info).request_uri = apr_pstrdup(r->pool, r->uri);
 489         SG(request_info).path_translated = apr_pstrdup(r->pool, r->filename);
 490         r->no_local_copy = 1;
 491 
 492         content_length = (char *) apr_table_get(r->headers_in, "Content-Length");
 493         if (content_length) {
 494                 ZEND_ATOL(SG(request_info).content_length, content_length);
 495         } else {
 496                 SG(request_info).content_length = 0;
 497         }
 498 
 499         apr_table_unset(r->headers_out, "Content-Length");
 500         apr_table_unset(r->headers_out, "Last-Modified");
 501         apr_table_unset(r->headers_out, "Expires");
 502         apr_table_unset(r->headers_out, "ETag");
 503 
 504         auth = apr_table_get(r->headers_in, "Authorization");
 505         php_handle_auth_data(auth);
 506 
 507         if (SG(request_info).auth_user == NULL && r->user) {
 508                 SG(request_info).auth_user = estrdup(r->user);
 509         }
 510 
 511         ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
 512 
 513         return php_request_startup();
 514 }
 515 
 516 static void php_apache_request_dtor(request_rec *r)
 517 {
 518         php_request_shutdown(NULL);
 519 }
 520 
 521 static void php_apache_ini_dtor(request_rec *r, request_rec *p)
 522 {
 523         if (strcmp(r->protocol, "INCLUDED")) {
 524                 zend_try { zend_ini_deactivate(); } zend_end_try();
 525         } else {
 526 typedef struct {
 527         HashTable config;
 528 } php_conf_rec;
 529                 zend_string *str;
 530                 php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php7_module);
 531 
 532                 ZEND_HASH_FOREACH_STR_KEY(&c->config, str) {
 533                         zend_restore_ini_entry(str, ZEND_INI_STAGE_SHUTDOWN);
 534                 } ZEND_HASH_FOREACH_END();
 535         }
 536         if (p) {
 537                 ((php_struct *)SG(server_context))->r = p;
 538         } else {
 539                 apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
 540         }
 541 }
 542 
 543 static int php_handler(request_rec *r)
 544 {
 545         php_struct * volatile ctx;
 546         void *conf;
 547         apr_bucket_brigade * volatile brigade;
 548         apr_bucket *bucket;
 549         apr_status_t rv;
 550         request_rec * volatile parent_req = NULL;
 551 #ifdef ZTS
 552         /* initial resource fetch */
 553         (void)ts_resource(0);
 554         ZEND_TSRMLS_CACHE_UPDATE();
 555 #endif
 556 
 557 #define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req);
 558 
 559         conf = ap_get_module_config(r->per_dir_config, &php7_module);
 560 
 561         /* apply_config() needs r in some cases, so allocate server_context early */
 562         ctx = SG(server_context);
 563         if (ctx == NULL || (ctx && ctx->request_processed && !strcmp(r->protocol, "INCLUDED"))) {
 564 normal:
 565                 ctx = SG(server_context) = apr_pcalloc(r->pool, sizeof(*ctx));
 566                 /* register a cleanup so we clear out the SG(server_context)
 567                  * after each request. Note: We pass in the pointer to the
 568                  * server_context in case this is handled by a different thread.
 569                  */
 570                 apr_pool_cleanup_register(r->pool, (void *)&SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null);
 571                 ctx->r = r;
 572                 ctx = NULL; /* May look weird to null it here, but it is to catch the right case in the first_try later on */
 573         } else {
 574                 parent_req = ctx->r;
 575                 ctx->r = r;
 576         }
 577         apply_config(conf);
 578 
 579         if (strcmp(r->handler, PHP_MAGIC_TYPE) && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(r->handler, PHP_SCRIPT)) {
 580                 /* Check for xbithack in this case. */
 581                 if (!AP2(xbithack) || strcmp(r->handler, "text/html") || !(r->finfo.protection & APR_UEXECUTE)) {
 582                         PHPAP_INI_OFF;
 583                         return DECLINED;
 584                 }
 585         }
 586 
 587         /* Give a 404 if PATH_INFO is used but is explicitly disabled in
 588          * the configuration; default behaviour is to accept. */
 589         if (r->used_path_info == AP_REQ_REJECT_PATH_INFO
 590                 && r->path_info && r->path_info[0]) {
 591                 PHPAP_INI_OFF;
 592                 return HTTP_NOT_FOUND;
 593         }
 594 
 595         /* handle situations where user turns the engine off */
 596         if (!AP2(engine)) {
 597                 PHPAP_INI_OFF;
 598                 return DECLINED;
 599         }
 600 
 601         if (r->finfo.filetype == 0) {
 602                 php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r);
 603                 PHPAP_INI_OFF;
 604                 return HTTP_NOT_FOUND;
 605         }
 606         if (r->finfo.filetype == APR_DIR) {
 607                 php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r);
 608                 PHPAP_INI_OFF;
 609                 return HTTP_FORBIDDEN;
 610         }
 611 
 612         /* Setup the CGI variables if this is the main request */
 613         if (r->main == NULL ||
 614                 /* .. or if the sub-request environment differs from the main-request. */
 615                 r->subprocess_env != r->main->subprocess_env
 616         ) {
 617                 /* setup standard CGI variables */
 618                 ap_add_common_vars(r);
 619                 ap_add_cgi_vars(r);
 620         }
 621 
 622 zend_first_try {
 623 
 624         if (ctx == NULL) {
 625                 brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
 626                 ctx = SG(server_context);
 627                 ctx->brigade = brigade;
 628 
 629                 if (php_apache_request_ctor(r, ctx)!=SUCCESS) {
 630                         zend_bailout();
 631                 }
 632         } else {
 633                 if (!parent_req) {
 634                         parent_req = ctx->r;
 635                 }
 636                 if (parent_req && parent_req->handler &&
 637                                 strcmp(parent_req->handler, PHP_MAGIC_TYPE) &&
 638                                 strcmp(parent_req->handler, PHP_SOURCE_MAGIC_TYPE) &&
 639                                 strcmp(parent_req->handler, PHP_SCRIPT)) {
 640                         if (php_apache_request_ctor(r, ctx)!=SUCCESS) {
 641                                 zend_bailout();
 642                         }
 643                 }
 644 
 645                 /*
 646                  * check if coming due to ErrorDocument
 647                  * We make a special exception of 413 (Invalid POST request) as the invalidity of the request occurs
 648                  * during processing of the request by PHP during POST processing. Therefor we need to re-use the exiting
 649                  * PHP instance to handle the request rather then creating a new one.
 650                 */
 651                 if (parent_req && parent_req->status != HTTP_OK && parent_req->status != 413 && strcmp(r->protocol, "INCLUDED")) {
 652                         parent_req = NULL;
 653                         goto normal;
 654                 }
 655                 ctx->r = r;
 656                 brigade = ctx->brigade;
 657         }
 658 
 659         if (AP2(last_modified)) {
 660                 ap_update_mtime(r, r->finfo.mtime);
 661                 ap_set_last_modified(r);
 662         }
 663 
 664         /* Determine if we need to parse the file or show the source */
 665         if (strncmp(r->handler, PHP_SOURCE_MAGIC_TYPE, sizeof(PHP_SOURCE_MAGIC_TYPE) - 1) == 0) {
 666                 zend_syntax_highlighter_ini syntax_highlighter_ini;
 667                 php_get_highlight_struct(&syntax_highlighter_ini);
 668                 highlight_file((char *)r->filename, &syntax_highlighter_ini);
 669         } else {
 670                 zend_file_handle zfd;
 671 
 672                 zfd.type = ZEND_HANDLE_FILENAME;
 673                 zfd.filename = (char *) r->filename;
 674                 zfd.free_filename = 0;
 675                 zfd.opened_path = NULL;
 676 
 677                 if (!parent_req) {
 678                         php_execute_script(&zfd);
 679                 } else {
 680                         zend_execute_scripts(ZEND_INCLUDE, NULL, 1, &zfd);
 681                 }
 682 
 683                 apr_table_set(r->notes, "mod_php_memory_usage",
 684                         apr_psprintf(ctx->r->pool, "%" APR_SIZE_T_FMT, zend_memory_peak_usage(1)));
 685         }
 686 
 687 } zend_end_try();
 688 
 689         if (!parent_req) {
 690                 php_apache_request_dtor(r);
 691                 ctx->request_processed = 1;
 692                 bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
 693                 APR_BRIGADE_INSERT_TAIL(brigade, bucket);
 694 
 695                 rv = ap_pass_brigade(r->output_filters, brigade);
 696                 if (rv != APR_SUCCESS || r->connection->aborted) {
 697 zend_first_try {
 698                         php_handle_aborted_connection();
 699 } zend_end_try();
 700                 }
 701                 apr_brigade_cleanup(brigade);
 702                 apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
 703         } else {
 704                 ctx->r = parent_req;
 705         }
 706 
 707         return OK;
 708 }
 709 
 710 static void php_apache_child_init(apr_pool_t *pchild, server_rec *s)
 711 {
 712         apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null);
 713 }
 714 
 715 void php_ap2_register_hook(apr_pool_t *p)
 716 {
 717         ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
 718         ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
 719         ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
 720 #ifdef ZEND_SIGNALS
 721         ap_hook_child_init(zend_signal_init, NULL, NULL, APR_HOOK_MIDDLE);
 722 #endif
 723         ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
 724 }
 725 
 726 /*
 727  * Local variables:
 728  * tab-width: 4
 729  * c-basic-offset: 4
 730  * End:
 731  * vim600: sw=4 ts=4 fdm=marker
 732  * vim<600: sw=4 ts=4
 733  */

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