Back to index

php5  5.3.10
sapi_apache2.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Sascha Schumann <sascha@schumann.cx>                        |
00016    |          Parts based on Apache 1.3 SAPI module by                    |
00017    |          Rasmus Lerdorf and Zeev Suraski                             |
00018    +----------------------------------------------------------------------+
00019  */
00020 
00021 /* $Id: sapi_apache2.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 
00023 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
00024 
00025 #include "php.h"
00026 #include "php_main.h"
00027 #include "php_ini.h"
00028 #include "php_variables.h"
00029 #include "SAPI.h"
00030 
00031 #include <fcntl.h>
00032 
00033 #include "ext/standard/php_smart_str.h"
00034 #ifndef NETWARE
00035 #include "ext/standard/php_standard.h"
00036 #else
00037 #include "ext/standard/basic_functions.h"
00038 #endif
00039 
00040 #include "apr_strings.h"
00041 #include "ap_config.h"
00042 #include "util_filter.h"
00043 #include "httpd.h"
00044 #include "http_config.h"
00045 #include "http_request.h"
00046 #include "http_core.h"
00047 #include "http_protocol.h"
00048 #include "http_log.h"
00049 #include "http_main.h"
00050 #include "util_script.h"
00051 #include "http_core.h"
00052 #include "ap_mpm.h"
00053 
00054 #include "php_apache.h"
00055 
00056 #ifdef PHP_WIN32
00057 # if _MSC_VER <= 1300
00058 #  include "win32/php_strtoi64.h"
00059 # endif
00060 #endif
00061 
00062 /* UnixWare and Netware define shutdown to _shutdown, which causes problems later
00063  * on when using a structure member named shutdown. Since this source
00064  * file does not use the system call shutdown, it is safe to #undef it.K
00065  */
00066 #undef shutdown
00067 
00068 #define PHP_MAGIC_TYPE "application/x-httpd-php"
00069 #define PHP_SOURCE_MAGIC_TYPE "application/x-httpd-php-source"
00070 #define PHP_SCRIPT "php5-script"
00071 
00072 /* A way to specify the location of the php.ini dir in an apache directive */
00073 char *apache2_php_ini_path_override = NULL;
00074 
00075 static int
00076 php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
00077 {
00078        request_rec *r;
00079        php_struct *ctx;
00080 
00081        ctx = SG(server_context);
00082        r = ctx->r;
00083 
00084        if (ap_rwrite(str, str_length, r) < 0) {
00085               php_handle_aborted_connection();
00086        }
00087 
00088        return str_length; /* we always consume all the data passed to us. */
00089 }
00090 
00091 static int
00092 php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
00093 {
00094        php_struct *ctx;
00095        char *val, *ptr;
00096 
00097        ctx = SG(server_context);
00098 
00099        switch (op) {
00100               case SAPI_HEADER_DELETE:
00101                      apr_table_unset(ctx->r->headers_out, sapi_header->header);
00102                      return 0;
00103 
00104               case SAPI_HEADER_DELETE_ALL:
00105                      apr_table_clear(ctx->r->headers_out);
00106                      return 0;
00107 
00108               case SAPI_HEADER_ADD:
00109               case SAPI_HEADER_REPLACE:
00110                      val = strchr(sapi_header->header, ':');
00111 
00112                      if (!val) {
00113                             return 0;
00114                      }
00115                      ptr = val;
00116 
00117                      *val = '\0';
00118 
00119                      do {
00120                             val++;
00121                      } while (*val == ' ');
00122 
00123                      if (!strcasecmp(sapi_header->header, "content-type")) {
00124                             if (ctx->content_type) {
00125                                    efree(ctx->content_type);
00126                             }
00127                             ctx->content_type = estrdup(val);
00128                      } else if (!strcasecmp(sapi_header->header, "content-length")) {
00129 #ifdef PHP_WIN32
00130 # ifdef APR_HAS_LARGE_FILES
00131                             ap_set_content_length(ctx->r, (apr_off_t) _strtoui64(val, (char **)NULL, 10));
00132 # else
00133                             ap_set_content_length(ctx->r, (apr_off_t) strtol(val, (char **)NULL, 10));
00134 # endif
00135 #else
00136                             ap_set_content_length(ctx->r, (apr_off_t) strtol(val, (char **)NULL, 10));
00137 #endif
00138                      } else if (op == SAPI_HEADER_REPLACE) {
00139                             apr_table_set(ctx->r->headers_out, sapi_header->header, val);
00140                      } else {
00141                             apr_table_add(ctx->r->headers_out, sapi_header->header, val);
00142                      }
00143 
00144                      *ptr = ':';
00145 
00146                      return SAPI_HEADER_ADD;
00147 
00148               default:
00149                      return 0;
00150        }
00151 }
00152 
00153 static int
00154 php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
00155 {
00156        php_struct *ctx = SG(server_context);
00157        const char *sline = SG(sapi_headers).http_status_line;
00158 
00159        ctx->r->status = SG(sapi_headers).http_response_code;
00160 
00161        /* httpd requires that r->status_line is set to the first digit of
00162         * the status-code: */
00163        if (sline && strlen(sline) > 12 && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
00164               ctx->r->status_line = apr_pstrdup(ctx->r->pool, sline + 9);
00165               ctx->r->proto_num = 1000 + (sline[7]-'0');
00166               if ((sline[7]-'0') == 0) {
00167                      apr_table_set(ctx->r->subprocess_env, "force-response-1.0", "true");
00168               }
00169        }
00170 
00171        /*     call ap_set_content_type only once, else each time we call it,
00172               configured output filters for that content type will be added */
00173        if (!ctx->content_type) {
00174               ctx->content_type = sapi_get_default_content_type(TSRMLS_C);
00175        }
00176        ap_set_content_type(ctx->r, apr_pstrdup(ctx->r->pool, ctx->content_type));
00177        efree(ctx->content_type);
00178        ctx->content_type = NULL;
00179 
00180        return SAPI_HEADER_SENT_SUCCESSFULLY;
00181 }
00182 
00183 static int
00184 php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
00185 {
00186        apr_size_t len, tlen=0;
00187        php_struct *ctx = SG(server_context);
00188        request_rec *r;
00189        apr_bucket_brigade *brigade;
00190 
00191        r = ctx->r;
00192        brigade = ctx->brigade;
00193        len = count_bytes;
00194 
00195        /*
00196         * This loop is needed because ap_get_brigade() can return us partial data
00197         * which would cause premature termination of request read. Therefor we
00198         * need to make sure that if data is available we fill the buffer completely.
00199         */
00200 
00201        while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
00202               apr_brigade_flatten(brigade, buf, &len);
00203               apr_brigade_cleanup(brigade);
00204               tlen += len;
00205               if (tlen == count_bytes || !len) {
00206                      break;
00207               }
00208               buf += len;
00209               len = count_bytes - tlen;
00210        }
00211 
00212        return tlen;
00213 }
00214 
00215 static struct stat*
00216 php_apache_sapi_get_stat(TSRMLS_D)
00217 {
00218        php_struct *ctx = SG(server_context);
00219 
00220        ctx->finfo.st_uid = ctx->r->finfo.user;
00221        ctx->finfo.st_gid = ctx->r->finfo.group;
00222        ctx->finfo.st_dev = ctx->r->finfo.device;
00223        ctx->finfo.st_ino = ctx->r->finfo.inode;
00224 #if defined(NETWARE) && defined(CLIB_STAT_PATCH)
00225        ctx->finfo.st_atime.tv_sec = apr_time_sec(ctx->r->finfo.atime);
00226        ctx->finfo.st_mtime.tv_sec = apr_time_sec(ctx->r->finfo.mtime);
00227        ctx->finfo.st_ctime.tv_sec = apr_time_sec(ctx->r->finfo.ctime);
00228 #else
00229        ctx->finfo.st_atime = apr_time_sec(ctx->r->finfo.atime);
00230        ctx->finfo.st_mtime = apr_time_sec(ctx->r->finfo.mtime);
00231        ctx->finfo.st_ctime = apr_time_sec(ctx->r->finfo.ctime);
00232 #endif
00233 
00234        ctx->finfo.st_size = ctx->r->finfo.size;
00235        ctx->finfo.st_nlink = ctx->r->finfo.nlink;
00236 
00237        return &ctx->finfo;
00238 }
00239 
00240 static char *
00241 php_apache_sapi_read_cookies(TSRMLS_D)
00242 {
00243        php_struct *ctx = SG(server_context);
00244        const char *http_cookie;
00245 
00246        http_cookie = apr_table_get(ctx->r->headers_in, "cookie");
00247 
00248        /* The SAPI interface should use 'const char *' */
00249        return (char *) http_cookie;
00250 }
00251 
00252 static char *
00253 php_apache_sapi_getenv(char *name, size_t name_len TSRMLS_DC)
00254 {
00255        php_struct *ctx = SG(server_context);
00256        const char *env_var;
00257 
00258        if (ctx == NULL) {
00259               return NULL;
00260        }
00261 
00262        env_var = apr_table_get(ctx->r->subprocess_env, name);
00263 
00264        return (char *) env_var;
00265 }
00266 
00267 static void
00268 php_apache_sapi_register_variables(zval *track_vars_array TSRMLS_DC)
00269 {
00270        php_struct *ctx = SG(server_context);
00271        const apr_array_header_t *arr = apr_table_elts(ctx->r->subprocess_env);
00272        char *key, *val;
00273        int new_val_len;
00274 
00275        APR_ARRAY_FOREACH_OPEN(arr, key, val)
00276               if (!val) {
00277                      val = "";
00278               }
00279               if (sapi_module.input_filter(PARSE_SERVER, key, &val, strlen(val), &new_val_len TSRMLS_CC)) {
00280                      php_register_variable_safe(key, val, new_val_len, track_vars_array TSRMLS_CC);
00281               }
00282        APR_ARRAY_FOREACH_CLOSE()
00283 
00284        if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len TSRMLS_CC)) {
00285               php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array TSRMLS_CC);
00286        }
00287 }
00288 
00289 static void
00290 php_apache_sapi_flush(void *server_context)
00291 {
00292        php_struct *ctx;
00293        request_rec *r;
00294        TSRMLS_FETCH();
00295 
00296        ctx = server_context;
00297 
00298        /* If we haven't registered a server_context yet,
00299         * then don't bother flushing. */
00300        if (!server_context) {
00301               return;
00302        }
00303 
00304        r = ctx->r;
00305 
00306        sapi_send_headers(TSRMLS_C);
00307 
00308        r->status = SG(sapi_headers).http_response_code;
00309        SG(headers_sent) = 1;
00310 
00311        if (ap_rflush(r) < 0 || r->connection->aborted) {
00312               php_handle_aborted_connection();
00313        }
00314 }
00315 
00316 static void php_apache_sapi_log_message(char *msg)
00317 {
00318        php_struct *ctx;
00319        TSRMLS_FETCH();
00320 
00321        ctx = SG(server_context);
00322 
00323        if (ctx == NULL) { /* we haven't initialized our ctx yet, oh well */
00324               ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "%s", msg);
00325        } else {
00326               ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, "%s", msg);
00327        }
00328 }
00329 
00330 static void php_apache_sapi_log_message_ex(char *msg, request_rec *r)
00331 {
00332        if (r) {
00333               ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, msg, r->filename);
00334        } else {
00335               php_apache_sapi_log_message(msg);
00336        }
00337 }
00338 
00339 static time_t php_apache_sapi_get_request_time(TSRMLS_D)
00340 {
00341        php_struct *ctx = SG(server_context);
00342        return apr_time_sec(ctx->r->request_time);
00343 }
00344 
00345 extern zend_module_entry php_apache_module;
00346 
00347 static int php_apache2_startup(sapi_module_struct *sapi_module)
00348 {
00349        if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) {
00350               return FAILURE;
00351        }
00352        return SUCCESS;
00353 }
00354 
00355 static sapi_module_struct apache2_sapi_module = {
00356        "apache2handler",
00357        "Apache 2.0 Handler",
00358 
00359        php_apache2_startup,                      /* startup */
00360        php_module_shutdown_wrapper,                     /* shutdown */
00361 
00362        NULL,                                     /* activate */
00363        NULL,                                     /* deactivate */
00364 
00365        php_apache_sapi_ub_write,                 /* unbuffered write */
00366        php_apache_sapi_flush,                           /* flush */
00367        php_apache_sapi_get_stat,                 /* get uid */
00368        php_apache_sapi_getenv,                          /* getenv */
00369 
00370        php_error,                                /* error handler */
00371 
00372        php_apache_sapi_header_handler,                  /* header handler */
00373        php_apache_sapi_send_headers,                    /* send headers handler */
00374        NULL,                                     /* send header handler */
00375 
00376        php_apache_sapi_read_post,                /* read POST data */
00377        php_apache_sapi_read_cookies,                    /* read Cookies */
00378 
00379        php_apache_sapi_register_variables,
00380        php_apache_sapi_log_message,                     /* Log message */
00381        php_apache_sapi_get_request_time,         /* Request Time */
00382        NULL,                                     /* Child Terminate */
00383 
00384        STANDARD_SAPI_MODULE_PROPERTIES
00385 };
00386 
00387 static apr_status_t php_apache_server_shutdown(void *tmp)
00388 {
00389        apache2_sapi_module.shutdown(&apache2_sapi_module);
00390        sapi_shutdown();
00391 #ifdef ZTS
00392        tsrm_shutdown();
00393 #endif
00394        return APR_SUCCESS;
00395 }
00396 
00397 static apr_status_t php_apache_child_shutdown(void *tmp)
00398 {
00399        apache2_sapi_module.shutdown(&apache2_sapi_module);
00400 #if defined(ZTS) && !defined(PHP_WIN32)
00401        tsrm_shutdown();
00402 #endif
00403        return APR_SUCCESS;
00404 }
00405 
00406 static void php_apache_add_version(apr_pool_t *p)
00407 {
00408        TSRMLS_FETCH();
00409        if (PG(expose_php)) {
00410               ap_add_version_component(p, "PHP/" PHP_VERSION);
00411        }
00412 }
00413 
00414 static int php_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
00415 {
00416 #ifndef ZTS
00417        int threaded_mpm;
00418 
00419        ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
00420        if(threaded_mpm) {
00421               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.");
00422               return DONE;
00423        }
00424 #endif
00425        /* When this is NULL, apache won't override the hard-coded default
00426         * php.ini path setting. */
00427        apache2_php_ini_path_override = NULL;
00428        return OK;
00429 }
00430 
00431 static int
00432 php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
00433 {
00434        void *data = NULL;
00435        const char *userdata_key = "apache2hook_post_config";
00436 
00437        /* Apache will load, unload and then reload a DSO module. This
00438         * prevents us from starting PHP until the second load. */
00439        apr_pool_userdata_get(&data, userdata_key, s->process->pool);
00440        if (data == NULL) {
00441               /* We must use set() here and *not* setn(), otherwise the
00442                * static string pointed to by userdata_key will be mapped
00443                * to a different location when the DSO is reloaded and the
00444                * pointers won't match, causing get() to return NULL when
00445                * we expected it to return non-NULL. */
00446               apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, s->process->pool);
00447               return OK;
00448        }
00449 
00450        /* Set up our overridden path. */
00451        if (apache2_php_ini_path_override) {
00452               apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override;
00453        }
00454 #ifdef ZTS
00455        tsrm_startup(1, 1, 0, NULL);
00456 #endif
00457        sapi_startup(&apache2_sapi_module);
00458        apache2_sapi_module.startup(&apache2_sapi_module);
00459        apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null);
00460        php_apache_add_version(pconf);
00461 
00462        return OK;
00463 }
00464 
00465 static apr_status_t php_server_context_cleanup(void *data_)
00466 {
00467        void **data = data_;
00468        *data = NULL;
00469        return APR_SUCCESS;
00470 }
00471 
00472 static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC)
00473 {
00474        char *content_length;
00475        const char *auth;
00476 
00477        SG(sapi_headers).http_response_code = !r->status ? HTTP_OK : r->status;
00478        SG(request_info).content_type = apr_table_get(r->headers_in, "Content-Type");
00479        SG(request_info).query_string = apr_pstrdup(r->pool, r->args);
00480        SG(request_info).request_method = r->method;
00481        SG(request_info).proto_num = r->proto_num;
00482        SG(request_info).request_uri = apr_pstrdup(r->pool, r->uri);
00483        SG(request_info).path_translated = apr_pstrdup(r->pool, r->filename);
00484        r->no_local_copy = 1;
00485 
00486        content_length = (char *) apr_table_get(r->headers_in, "Content-Length");
00487        SG(request_info).content_length = (content_length ? atol(content_length) : 0);
00488 
00489        apr_table_unset(r->headers_out, "Content-Length");
00490        apr_table_unset(r->headers_out, "Last-Modified");
00491        apr_table_unset(r->headers_out, "Expires");
00492        apr_table_unset(r->headers_out, "ETag");
00493        if (!PG(safe_mode) || (PG(safe_mode) && !ap_auth_type(r))) {
00494               auth = apr_table_get(r->headers_in, "Authorization");
00495               php_handle_auth_data(auth TSRMLS_CC);
00496               if (SG(request_info).auth_user == NULL && r->user) {
00497                      SG(request_info).auth_user = estrdup(r->user);
00498               }
00499               ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
00500        } else {
00501               SG(request_info).auth_user = NULL;
00502               SG(request_info).auth_password = NULL;
00503        }
00504        return php_request_startup(TSRMLS_C);
00505 }
00506 
00507 static void php_apache_request_dtor(request_rec *r TSRMLS_DC)
00508 {
00509        php_request_shutdown(NULL);
00510 }
00511 
00512 static void php_apache_ini_dtor(request_rec *r, request_rec *p TSRMLS_DC)
00513 {
00514        if (strcmp(r->protocol, "INCLUDED")) {
00515               zend_try { zend_ini_deactivate(TSRMLS_C); } zend_end_try();
00516        } else {
00517 typedef struct {
00518        HashTable config;
00519 } php_conf_rec;
00520               char *str;
00521               uint str_len;
00522               php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php5_module);
00523 
00524               for (zend_hash_internal_pointer_reset(&c->config);
00525                      zend_hash_get_current_key_ex(&c->config, &str, &str_len, NULL, 0,  NULL) == HASH_KEY_IS_STRING;
00526                      zend_hash_move_forward(&c->config)
00527               ) {
00528                      zend_restore_ini_entry(str, str_len, ZEND_INI_STAGE_SHUTDOWN);
00529               }
00530        }
00531        if (p) {
00532               ((php_struct *)SG(server_context))->r = p;
00533        } else {
00534               apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
00535        }
00536 }
00537 
00538 static int php_handler(request_rec *r)
00539 {
00540        php_struct * volatile ctx;
00541        void *conf;
00542        apr_bucket_brigade * volatile brigade;
00543        apr_bucket *bucket;
00544        apr_status_t rv;
00545        request_rec * volatile parent_req = NULL;
00546        TSRMLS_FETCH();
00547 
00548 #define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req TSRMLS_CC);
00549 
00550        conf = ap_get_module_config(r->per_dir_config, &php5_module);
00551 
00552        /* apply_config() needs r in some cases, so allocate server_context early */
00553        ctx = SG(server_context);
00554        if (ctx == NULL || (ctx && ctx->request_processed && !strcmp(r->protocol, "INCLUDED"))) {
00555 normal:
00556               ctx = SG(server_context) = apr_pcalloc(r->pool, sizeof(*ctx));
00557               /* register a cleanup so we clear out the SG(server_context)
00558                * after each request. Note: We pass in the pointer to the
00559                * server_context in case this is handled by a different thread.
00560                */
00561               apr_pool_cleanup_register(r->pool, (void *)&SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null);
00562               ctx->r = r;
00563               ctx = NULL; /* May look weird to null it here, but it is to catch the right case in the first_try later on */
00564        } else {
00565               parent_req = ctx->r;
00566               ctx->r = r;
00567        }
00568        apply_config(conf);
00569 
00570        if (strcmp(r->handler, PHP_MAGIC_TYPE) && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(r->handler, PHP_SCRIPT)) {
00571               /* Check for xbithack in this case. */
00572               if (!AP2(xbithack) || strcmp(r->handler, "text/html") || !(r->finfo.protection & APR_UEXECUTE)) {
00573                      PHPAP_INI_OFF;
00574                      return DECLINED;
00575               }
00576        }
00577 
00578        /* Give a 404 if PATH_INFO is used but is explicitly disabled in
00579         * the configuration; default behaviour is to accept. */
00580        if (r->used_path_info == AP_REQ_REJECT_PATH_INFO
00581               && r->path_info && r->path_info[0]) {
00582               PHPAP_INI_OFF;
00583               return HTTP_NOT_FOUND;
00584        }
00585 
00586        /* handle situations where user turns the engine off */
00587        if (!AP2(engine)) {
00588               PHPAP_INI_OFF;
00589               return DECLINED;
00590        }
00591 
00592        if (r->finfo.filetype == 0) {
00593               php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r);
00594               PHPAP_INI_OFF;
00595               return HTTP_NOT_FOUND;
00596        }
00597        if (r->finfo.filetype == APR_DIR) {
00598               php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r);
00599               PHPAP_INI_OFF;
00600               return HTTP_FORBIDDEN;
00601        }
00602 
00603        /* Setup the CGI variables if this is the main request */
00604        if (r->main == NULL ||
00605               /* .. or if the sub-request environment differs from the main-request. */
00606               r->subprocess_env != r->main->subprocess_env
00607        ) {
00608               /* setup standard CGI variables */
00609               ap_add_common_vars(r);
00610               ap_add_cgi_vars(r);
00611        }
00612 
00613 zend_first_try {
00614 
00615        if (ctx == NULL) {
00616               brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
00617               ctx = SG(server_context);
00618               ctx->brigade = brigade;
00619 
00620               if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) {
00621                      zend_bailout();
00622               }
00623        } else {
00624               if (!parent_req) {
00625                      parent_req = ctx->r;
00626               }
00627               if (parent_req && parent_req->handler &&
00628                             strcmp(parent_req->handler, PHP_MAGIC_TYPE) &&
00629                             strcmp(parent_req->handler, PHP_SOURCE_MAGIC_TYPE) &&
00630                             strcmp(parent_req->handler, PHP_SCRIPT)) {
00631                      if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) {
00632                             zend_bailout();
00633                      }
00634               }
00635 
00636               /*
00637                * check if comming due to ErrorDocument
00638                * We make a special exception of 413 (Invalid POST request) as the invalidity of the request occurs
00639                * during processing of the request by PHP during POST processing. Therefor we need to re-use the exiting
00640                * PHP instance to handle the request rather then creating a new one.
00641               */
00642               if (parent_req && parent_req->status != HTTP_OK && parent_req->status != 413 && strcmp(r->protocol, "INCLUDED")) {
00643                      parent_req = NULL;
00644                      goto normal;
00645               }
00646               ctx->r = r;
00647               brigade = ctx->brigade;
00648        }
00649 
00650        if (AP2(last_modified)) {
00651               ap_update_mtime(r, r->finfo.mtime);
00652               ap_set_last_modified(r);
00653        }
00654 
00655        /* Determine if we need to parse the file or show the source */
00656        if (strncmp(r->handler, PHP_SOURCE_MAGIC_TYPE, sizeof(PHP_SOURCE_MAGIC_TYPE) - 1) == 0) {
00657               zend_syntax_highlighter_ini syntax_highlighter_ini;
00658               php_get_highlight_struct(&syntax_highlighter_ini);
00659               highlight_file((char *)r->filename, &syntax_highlighter_ini TSRMLS_CC);
00660        } else {
00661               zend_file_handle zfd;
00662 
00663               zfd.type = ZEND_HANDLE_FILENAME;
00664               zfd.filename = (char *) r->filename;
00665               zfd.free_filename = 0;
00666               zfd.opened_path = NULL;
00667 
00668               if (!parent_req) {
00669                      php_execute_script(&zfd TSRMLS_CC);
00670               } else {
00671                      zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &zfd);
00672               }
00673 
00674               apr_table_set(r->notes, "mod_php_memory_usage",
00675                      apr_psprintf(ctx->r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
00676        }
00677 
00678 } zend_end_try();
00679 
00680        if (!parent_req) {
00681               php_apache_request_dtor(r TSRMLS_CC);
00682               ctx->request_processed = 1;
00683               bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
00684               APR_BRIGADE_INSERT_TAIL(brigade, bucket);
00685 
00686               rv = ap_pass_brigade(r->output_filters, brigade);
00687               if (rv != APR_SUCCESS || r->connection->aborted) {
00688 zend_first_try {
00689                      php_handle_aborted_connection();
00690 } zend_end_try();
00691               }
00692               apr_brigade_cleanup(brigade);
00693        } else {
00694               ctx->r = parent_req;
00695        }
00696 
00697        return OK;
00698 }
00699 
00700 static void php_apache_child_init(apr_pool_t *pchild, server_rec *s)
00701 {
00702        apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null);
00703 }
00704 
00705 void php_ap2_register_hook(apr_pool_t *p)
00706 {
00707        ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
00708        ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
00709        ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
00710        ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
00711 }
00712 
00713 /*
00714  * Local variables:
00715  * tab-width: 4
00716  * c-basic-offset: 4
00717  * End:
00718  * vim600: sw=4 ts=4 fdm=marker
00719  * vim<600: sw=4 ts=4
00720  */