Annotation of embedaddon/php/sapi/apache2handler/sapi_apache2.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 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: sapi_apache2.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            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 "ext/standard/php_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: #ifdef PHP_WIN32
        !            57: # if _MSC_VER <= 1300
        !            58: #  include "win32/php_strtoi64.h"
        !            59: # endif
        !            60: #endif
        !            61: 
        !            62: /* UnixWare and Netware define shutdown to _shutdown, which causes problems later
        !            63:  * on when using a structure member named shutdown. Since this source
        !            64:  * file does not use the system call shutdown, it is safe to #undef it.K
        !            65:  */
        !            66: #undef shutdown
        !            67: 
        !            68: #define PHP_MAGIC_TYPE "application/x-httpd-php"
        !            69: #define PHP_SOURCE_MAGIC_TYPE "application/x-httpd-php-source"
        !            70: #define PHP_SCRIPT "php5-script"
        !            71: 
        !            72: /* A way to specify the location of the php.ini dir in an apache directive */
        !            73: char *apache2_php_ini_path_override = NULL;
        !            74: 
        !            75: static int
        !            76: php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
        !            77: {
        !            78:        request_rec *r;
        !            79:        php_struct *ctx;
        !            80: 
        !            81:        ctx = SG(server_context);
        !            82:        r = ctx->r;
        !            83: 
        !            84:        if (ap_rwrite(str, str_length, r) < 0) {
        !            85:                php_handle_aborted_connection();
        !            86:        }
        !            87: 
        !            88:        return str_length; /* we always consume all the data passed to us. */
        !            89: }
        !            90: 
        !            91: static int
        !            92: php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
        !            93: {
        !            94:        php_struct *ctx;
        !            95:        char *val, *ptr;
        !            96: 
        !            97:        ctx = SG(server_context);
        !            98: 
        !            99:        switch (op) {
        !           100:                case SAPI_HEADER_DELETE:
        !           101:                        apr_table_unset(ctx->r->headers_out, sapi_header->header);
        !           102:                        return 0;
        !           103: 
        !           104:                case SAPI_HEADER_DELETE_ALL:
        !           105:                        apr_table_clear(ctx->r->headers_out);
        !           106:                        return 0;
        !           107: 
        !           108:                case SAPI_HEADER_ADD:
        !           109:                case SAPI_HEADER_REPLACE:
        !           110:                        val = strchr(sapi_header->header, ':');
        !           111: 
        !           112:                        if (!val) {
        !           113:                                return 0;
        !           114:                        }
        !           115:                        ptr = val;
        !           116: 
        !           117:                        *val = '\0';
        !           118: 
        !           119:                        do {
        !           120:                                val++;
        !           121:                        } while (*val == ' ');
        !           122: 
        !           123:                        if (!strcasecmp(sapi_header->header, "content-type")) {
        !           124:                                if (ctx->content_type) {
        !           125:                                        efree(ctx->content_type);
        !           126:                                }
        !           127:                                ctx->content_type = estrdup(val);
        !           128:                        } else if (!strcasecmp(sapi_header->header, "content-length")) {
        !           129: #ifdef PHP_WIN32
        !           130: # ifdef APR_HAS_LARGE_FILES
        !           131:                                ap_set_content_length(ctx->r, (apr_off_t) _strtoui64(val, (char **)NULL, 10));
        !           132: # else
        !           133:                                ap_set_content_length(ctx->r, (apr_off_t) strtol(val, (char **)NULL, 10));
        !           134: # endif
        !           135: #else
        !           136:                                ap_set_content_length(ctx->r, (apr_off_t) strtol(val, (char **)NULL, 10));
        !           137: #endif
        !           138:                        } else if (op == SAPI_HEADER_REPLACE) {
        !           139:                                apr_table_set(ctx->r->headers_out, sapi_header->header, val);
        !           140:                        } else {
        !           141:                                apr_table_add(ctx->r->headers_out, sapi_header->header, val);
        !           142:                        }
        !           143: 
        !           144:                        *ptr = ':';
        !           145: 
        !           146:                        return SAPI_HEADER_ADD;
        !           147: 
        !           148:                default:
        !           149:                        return 0;
        !           150:        }
        !           151: }
        !           152: 
        !           153: static int
        !           154: php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
        !           155: {
        !           156:        php_struct *ctx = SG(server_context);
        !           157:        const char *sline = SG(sapi_headers).http_status_line;
        !           158: 
        !           159:        ctx->r->status = SG(sapi_headers).http_response_code;
        !           160: 
        !           161:        /* httpd requires that r->status_line is set to the first digit of
        !           162:         * the status-code: */
        !           163:        if (sline && strlen(sline) > 12 && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
        !           164:                ctx->r->status_line = apr_pstrdup(ctx->r->pool, sline + 9);
        !           165:                ctx->r->proto_num = 1000 + (sline[7]-'0');
        !           166:                if ((sline[7]-'0') == 0) {
        !           167:                        apr_table_set(ctx->r->subprocess_env, "force-response-1.0", "true");
        !           168:                }
        !           169:        }
        !           170: 
        !           171:        /*      call ap_set_content_type only once, else each time we call it,
        !           172:                configured output filters for that content type will be added */
        !           173:        if (!ctx->content_type) {
        !           174:                ctx->content_type = sapi_get_default_content_type(TSRMLS_C);
        !           175:        }
        !           176:        ap_set_content_type(ctx->r, apr_pstrdup(ctx->r->pool, ctx->content_type));
        !           177:        efree(ctx->content_type);
        !           178:        ctx->content_type = NULL;
        !           179: 
        !           180:        return SAPI_HEADER_SENT_SUCCESSFULLY;
        !           181: }
        !           182: 
        !           183: static int
        !           184: php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
        !           185: {
        !           186:        apr_size_t len, tlen=0;
        !           187:        php_struct *ctx = SG(server_context);
        !           188:        request_rec *r;
        !           189:        apr_bucket_brigade *brigade;
        !           190: 
        !           191:        r = ctx->r;
        !           192:        brigade = ctx->brigade;
        !           193:        len = count_bytes;
        !           194: 
        !           195:        /*
        !           196:         * This loop is needed because ap_get_brigade() can return us partial data
        !           197:         * which would cause premature termination of request read. Therefor we
        !           198:         * need to make sure that if data is available we fill the buffer completely.
        !           199:         */
        !           200: 
        !           201:        while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
        !           202:                apr_brigade_flatten(brigade, buf, &len);
        !           203:                apr_brigade_cleanup(brigade);
        !           204:                tlen += len;
        !           205:                if (tlen == count_bytes || !len) {
        !           206:                        break;
        !           207:                }
        !           208:                buf += len;
        !           209:                len = count_bytes - tlen;
        !           210:        }
        !           211: 
        !           212:        return tlen;
        !           213: }
        !           214: 
        !           215: static struct stat*
        !           216: php_apache_sapi_get_stat(TSRMLS_D)
        !           217: {
        !           218:        php_struct *ctx = SG(server_context);
        !           219: 
        !           220:        ctx->finfo.st_uid = ctx->r->finfo.user;
        !           221:        ctx->finfo.st_gid = ctx->r->finfo.group;
        !           222:        ctx->finfo.st_dev = ctx->r->finfo.device;
        !           223:        ctx->finfo.st_ino = ctx->r->finfo.inode;
        !           224: #if defined(NETWARE) && defined(CLIB_STAT_PATCH)
        !           225:        ctx->finfo.st_atime.tv_sec = apr_time_sec(ctx->r->finfo.atime);
        !           226:        ctx->finfo.st_mtime.tv_sec = apr_time_sec(ctx->r->finfo.mtime);
        !           227:        ctx->finfo.st_ctime.tv_sec = apr_time_sec(ctx->r->finfo.ctime);
        !           228: #else
        !           229:        ctx->finfo.st_atime = apr_time_sec(ctx->r->finfo.atime);
        !           230:        ctx->finfo.st_mtime = apr_time_sec(ctx->r->finfo.mtime);
        !           231:        ctx->finfo.st_ctime = apr_time_sec(ctx->r->finfo.ctime);
        !           232: #endif
        !           233: 
        !           234:        ctx->finfo.st_size = ctx->r->finfo.size;
        !           235:        ctx->finfo.st_nlink = ctx->r->finfo.nlink;
        !           236: 
        !           237:        return &ctx->finfo;
        !           238: }
        !           239: 
        !           240: static char *
        !           241: php_apache_sapi_read_cookies(TSRMLS_D)
        !           242: {
        !           243:        php_struct *ctx = SG(server_context);
        !           244:        const char *http_cookie;
        !           245: 
        !           246:        http_cookie = apr_table_get(ctx->r->headers_in, "cookie");
        !           247: 
        !           248:        /* The SAPI interface should use 'const char *' */
        !           249:        return (char *) http_cookie;
        !           250: }
        !           251: 
        !           252: static char *
        !           253: php_apache_sapi_getenv(char *name, size_t name_len TSRMLS_DC)
        !           254: {
        !           255:        php_struct *ctx = SG(server_context);
        !           256:        const char *env_var;
        !           257: 
        !           258:        if (ctx == NULL) {
        !           259:                return NULL;
        !           260:        }
        !           261: 
        !           262:        env_var = apr_table_get(ctx->r->subprocess_env, name);
        !           263: 
        !           264:        return (char *) env_var;
        !           265: }
        !           266: 
        !           267: static void
        !           268: php_apache_sapi_register_variables(zval *track_vars_array TSRMLS_DC)
        !           269: {
        !           270:        php_struct *ctx = SG(server_context);
        !           271:        const apr_array_header_t *arr = apr_table_elts(ctx->r->subprocess_env);
        !           272:        char *key, *val;
        !           273:        int new_val_len;
        !           274: 
        !           275:        APR_ARRAY_FOREACH_OPEN(arr, key, val)
        !           276:                if (!val) {
        !           277:                        val = "";
        !           278:                }
        !           279:                if (sapi_module.input_filter(PARSE_SERVER, key, &val, strlen(val), &new_val_len TSRMLS_CC)) {
        !           280:                        php_register_variable_safe(key, val, new_val_len, track_vars_array TSRMLS_CC);
        !           281:                }
        !           282:        APR_ARRAY_FOREACH_CLOSE()
        !           283: 
        !           284:        if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len TSRMLS_CC)) {
        !           285:                php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array TSRMLS_CC);
        !           286:        }
        !           287: }
        !           288: 
        !           289: static void
        !           290: php_apache_sapi_flush(void *server_context)
        !           291: {
        !           292:        php_struct *ctx;
        !           293:        request_rec *r;
        !           294:        TSRMLS_FETCH();
        !           295: 
        !           296:        ctx = server_context;
        !           297: 
        !           298:        /* If we haven't registered a server_context yet,
        !           299:         * then don't bother flushing. */
        !           300:        if (!server_context) {
        !           301:                return;
        !           302:        }
        !           303: 
        !           304:        r = ctx->r;
        !           305: 
        !           306:        sapi_send_headers(TSRMLS_C);
        !           307: 
        !           308:        r->status = SG(sapi_headers).http_response_code;
        !           309:        SG(headers_sent) = 1;
        !           310: 
        !           311:        if (ap_rflush(r) < 0 || r->connection->aborted) {
        !           312:                php_handle_aborted_connection();
        !           313:        }
        !           314: }
        !           315: 
        !           316: static void php_apache_sapi_log_message(char *msg)
        !           317: {
        !           318:        php_struct *ctx;
        !           319:        TSRMLS_FETCH();
        !           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 time_t php_apache_sapi_get_request_time(TSRMLS_D)
        !           340: {
        !           341:        php_struct *ctx = SG(server_context);
        !           342:        return apr_time_sec(ctx->r->request_time);
        !           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:        TSRMLS_FETCH();
        !           409:        if (PG(expose_php)) {
        !           410: #if SUHOSIN_PATCH
        !           411:                ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch");
        !           412: #else
        !           413:                ap_add_version_component(p, "PHP/" PHP_VERSION);
        !           414: #endif
        !           415:        }
        !           416: }
        !           417: 
        !           418: static int php_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
        !           419: {
        !           420: #ifndef ZTS
        !           421:        int threaded_mpm;
        !           422: 
        !           423:        ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
        !           424:        if(threaded_mpm) {
        !           425:                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.");
        !           426:                return DONE;
        !           427:        }
        !           428: #endif
        !           429:        /* When this is NULL, apache won't override the hard-coded default
        !           430:         * php.ini path setting. */
        !           431:        apache2_php_ini_path_override = NULL;
        !           432:        return OK;
        !           433: }
        !           434: 
        !           435: static int
        !           436: php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
        !           437: {
        !           438:        void *data = NULL;
        !           439:        const char *userdata_key = "apache2hook_post_config";
        !           440: 
        !           441:        /* Apache will load, unload and then reload a DSO module. This
        !           442:         * prevents us from starting PHP until the second load. */
        !           443:        apr_pool_userdata_get(&data, userdata_key, s->process->pool);
        !           444:        if (data == NULL) {
        !           445:                /* We must use set() here and *not* setn(), otherwise the
        !           446:                 * static string pointed to by userdata_key will be mapped
        !           447:                 * to a different location when the DSO is reloaded and the
        !           448:                 * pointers won't match, causing get() to return NULL when
        !           449:                 * we expected it to return non-NULL. */
        !           450:                apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, s->process->pool);
        !           451:                return OK;
        !           452:        }
        !           453: 
        !           454:        /* Set up our overridden path. */
        !           455:        if (apache2_php_ini_path_override) {
        !           456:                apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override;
        !           457:        }
        !           458: #ifdef ZTS
        !           459:        tsrm_startup(1, 1, 0, NULL);
        !           460: #endif
        !           461:        sapi_startup(&apache2_sapi_module);
        !           462:        apache2_sapi_module.startup(&apache2_sapi_module);
        !           463:        apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null);
        !           464:        php_apache_add_version(pconf);
        !           465: 
        !           466:        return OK;
        !           467: }
        !           468: 
        !           469: static apr_status_t php_server_context_cleanup(void *data_)
        !           470: {
        !           471:        void **data = data_;
        !           472:        *data = NULL;
        !           473:        return APR_SUCCESS;
        !           474: }
        !           475: 
        !           476: static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC)
        !           477: {
        !           478:        char *content_length;
        !           479:        const char *auth;
        !           480: 
        !           481:        SG(sapi_headers).http_response_code = !r->status ? HTTP_OK : r->status;
        !           482:        SG(request_info).content_type = apr_table_get(r->headers_in, "Content-Type");
        !           483:        SG(request_info).query_string = apr_pstrdup(r->pool, r->args);
        !           484:        SG(request_info).request_method = r->method;
        !           485:        SG(request_info).proto_num = r->proto_num;
        !           486:        SG(request_info).request_uri = apr_pstrdup(r->pool, r->uri);
        !           487:        SG(request_info).path_translated = apr_pstrdup(r->pool, r->filename);
        !           488:        r->no_local_copy = 1;
        !           489: 
        !           490:        content_length = (char *) apr_table_get(r->headers_in, "Content-Length");
        !           491:        SG(request_info).content_length = (content_length ? atol(content_length) : 0);
        !           492: 
        !           493:        apr_table_unset(r->headers_out, "Content-Length");
        !           494:        apr_table_unset(r->headers_out, "Last-Modified");
        !           495:        apr_table_unset(r->headers_out, "Expires");
        !           496:        apr_table_unset(r->headers_out, "ETag");
        !           497:        if (!PG(safe_mode) || (PG(safe_mode) && !ap_auth_type(r))) {
        !           498:                auth = apr_table_get(r->headers_in, "Authorization");
        !           499:                php_handle_auth_data(auth TSRMLS_CC);
        !           500:                if (SG(request_info).auth_user == NULL && r->user) {
        !           501:                        SG(request_info).auth_user = estrdup(r->user);
        !           502:                }
        !           503:                ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
        !           504:        } else {
        !           505:                SG(request_info).auth_user = NULL;
        !           506:                SG(request_info).auth_password = NULL;
        !           507:        }
        !           508:        return php_request_startup(TSRMLS_C);
        !           509: }
        !           510: 
        !           511: static void php_apache_request_dtor(request_rec *r TSRMLS_DC)
        !           512: {
        !           513:        php_request_shutdown(NULL);
        !           514: }
        !           515: 
        !           516: static void php_apache_ini_dtor(request_rec *r, request_rec *p TSRMLS_DC)
        !           517: {
        !           518:        if (strcmp(r->protocol, "INCLUDED")) {
        !           519:                zend_try { zend_ini_deactivate(TSRMLS_C); } zend_end_try();
        !           520:        } else {
        !           521: typedef struct {
        !           522:        HashTable config;
        !           523: } php_conf_rec;
        !           524:                char *str;
        !           525:                uint str_len;
        !           526:                php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php5_module);
        !           527: 
        !           528:                for (zend_hash_internal_pointer_reset(&c->config);
        !           529:                        zend_hash_get_current_key_ex(&c->config, &str, &str_len, NULL, 0,  NULL) == HASH_KEY_IS_STRING;
        !           530:                        zend_hash_move_forward(&c->config)
        !           531:                ) {
        !           532:                        zend_restore_ini_entry(str, str_len, ZEND_INI_STAGE_SHUTDOWN);
        !           533:                }
        !           534:        }
        !           535:        if (p) {
        !           536:                ((php_struct *)SG(server_context))->r = p;
        !           537:        } else {
        !           538:                apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
        !           539:        }
        !           540: }
        !           541: 
        !           542: static int php_handler(request_rec *r)
        !           543: {
        !           544:        php_struct * volatile ctx;
        !           545:        void *conf;
        !           546:        apr_bucket_brigade * volatile brigade;
        !           547:        apr_bucket *bucket;
        !           548:        apr_status_t rv;
        !           549:        request_rec * volatile parent_req = NULL;
        !           550:        TSRMLS_FETCH();
        !           551: 
        !           552: #define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req TSRMLS_CC);
        !           553: 
        !           554:        conf = ap_get_module_config(r->per_dir_config, &php5_module);
        !           555: 
        !           556:        /* apply_config() needs r in some cases, so allocate server_context early */
        !           557:        ctx = SG(server_context);
        !           558:        if (ctx == NULL || (ctx && ctx->request_processed && !strcmp(r->protocol, "INCLUDED"))) {
        !           559: normal:
        !           560:                ctx = SG(server_context) = apr_pcalloc(r->pool, sizeof(*ctx));
        !           561:                /* register a cleanup so we clear out the SG(server_context)
        !           562:                 * after each request. Note: We pass in the pointer to the
        !           563:                 * server_context in case this is handled by a different thread.
        !           564:                 */
        !           565:                apr_pool_cleanup_register(r->pool, (void *)&SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null);
        !           566:                ctx->r = r;
        !           567:                ctx = NULL; /* May look weird to null it here, but it is to catch the right case in the first_try later on */
        !           568:        } else {
        !           569:                parent_req = ctx->r;
        !           570:                ctx->r = r;
        !           571:        }
        !           572:        apply_config(conf);
        !           573: 
        !           574:        if (strcmp(r->handler, PHP_MAGIC_TYPE) && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(r->handler, PHP_SCRIPT)) {
        !           575:                /* Check for xbithack in this case. */
        !           576:                if (!AP2(xbithack) || strcmp(r->handler, "text/html") || !(r->finfo.protection & APR_UEXECUTE)) {
        !           577:                        PHPAP_INI_OFF;
        !           578:                        return DECLINED;
        !           579:                }
        !           580:        }
        !           581: 
        !           582:        /* Give a 404 if PATH_INFO is used but is explicitly disabled in
        !           583:         * the configuration; default behaviour is to accept. */
        !           584:        if (r->used_path_info == AP_REQ_REJECT_PATH_INFO
        !           585:                && r->path_info && r->path_info[0]) {
        !           586:                PHPAP_INI_OFF;
        !           587:                return HTTP_NOT_FOUND;
        !           588:        }
        !           589: 
        !           590:        /* handle situations where user turns the engine off */
        !           591:        if (!AP2(engine)) {
        !           592:                PHPAP_INI_OFF;
        !           593:                return DECLINED;
        !           594:        }
        !           595: 
        !           596:        if (r->finfo.filetype == 0) {
        !           597:                php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r);
        !           598:                PHPAP_INI_OFF;
        !           599:                return HTTP_NOT_FOUND;
        !           600:        }
        !           601:        if (r->finfo.filetype == APR_DIR) {
        !           602:                php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r);
        !           603:                PHPAP_INI_OFF;
        !           604:                return HTTP_FORBIDDEN;
        !           605:        }
        !           606: 
        !           607:        /* Setup the CGI variables if this is the main request */
        !           608:        if (r->main == NULL ||
        !           609:                /* .. or if the sub-request environment differs from the main-request. */
        !           610:                r->subprocess_env != r->main->subprocess_env
        !           611:        ) {
        !           612:                /* setup standard CGI variables */
        !           613:                ap_add_common_vars(r);
        !           614:                ap_add_cgi_vars(r);
        !           615:        }
        !           616: 
        !           617: zend_first_try {
        !           618: 
        !           619:        if (ctx == NULL) {
        !           620:                brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
        !           621:                ctx = SG(server_context);
        !           622:                ctx->brigade = brigade;
        !           623: 
        !           624:                if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) {
        !           625:                        zend_bailout();
        !           626:                }
        !           627:        } else {
        !           628:                if (!parent_req) {
        !           629:                        parent_req = ctx->r;
        !           630:                }
        !           631:                if (parent_req && parent_req->handler &&
        !           632:                                strcmp(parent_req->handler, PHP_MAGIC_TYPE) &&
        !           633:                                strcmp(parent_req->handler, PHP_SOURCE_MAGIC_TYPE) &&
        !           634:                                strcmp(parent_req->handler, PHP_SCRIPT)) {
        !           635:                        if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) {
        !           636:                                zend_bailout();
        !           637:                        }
        !           638:                }
        !           639: 
        !           640:                /*
        !           641:                 * check if comming due to ErrorDocument
        !           642:                 * We make a special exception of 413 (Invalid POST request) as the invalidity of the request occurs
        !           643:                 * during processing of the request by PHP during POST processing. Therefor we need to re-use the exiting
        !           644:                 * PHP instance to handle the request rather then creating a new one.
        !           645:                */
        !           646:                if (parent_req && parent_req->status != HTTP_OK && parent_req->status != 413 && strcmp(r->protocol, "INCLUDED")) {
        !           647:                        parent_req = NULL;
        !           648:                        goto normal;
        !           649:                }
        !           650:                ctx->r = r;
        !           651:                brigade = ctx->brigade;
        !           652:        }
        !           653: 
        !           654:        if (AP2(last_modified)) {
        !           655:                ap_update_mtime(r, r->finfo.mtime);
        !           656:                ap_set_last_modified(r);
        !           657:        }
        !           658: 
        !           659:        /* Determine if we need to parse the file or show the source */
        !           660:        if (strncmp(r->handler, PHP_SOURCE_MAGIC_TYPE, sizeof(PHP_SOURCE_MAGIC_TYPE) - 1) == 0) {
        !           661:                zend_syntax_highlighter_ini syntax_highlighter_ini;
        !           662:                php_get_highlight_struct(&syntax_highlighter_ini);
        !           663:                highlight_file((char *)r->filename, &syntax_highlighter_ini TSRMLS_CC);
        !           664:        } else {
        !           665:                zend_file_handle zfd;
        !           666: 
        !           667:                zfd.type = ZEND_HANDLE_FILENAME;
        !           668:                zfd.filename = (char *) r->filename;
        !           669:                zfd.free_filename = 0;
        !           670:                zfd.opened_path = NULL;
        !           671: 
        !           672:                if (!parent_req) {
        !           673:                        php_execute_script(&zfd TSRMLS_CC);
        !           674:                } else {
        !           675:                        zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &zfd);
        !           676:                }
        !           677: 
        !           678:                apr_table_set(r->notes, "mod_php_memory_usage",
        !           679:                        apr_psprintf(ctx->r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
        !           680:        }
        !           681: 
        !           682: } zend_end_try();
        !           683: 
        !           684:        if (!parent_req) {
        !           685:                php_apache_request_dtor(r TSRMLS_CC);
        !           686:                ctx->request_processed = 1;
        !           687:                bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
        !           688:                APR_BRIGADE_INSERT_TAIL(brigade, bucket);
        !           689: 
        !           690:                rv = ap_pass_brigade(r->output_filters, brigade);
        !           691:                if (rv != APR_SUCCESS || r->connection->aborted) {
        !           692: zend_first_try {
        !           693:                        php_handle_aborted_connection();
        !           694: } zend_end_try();
        !           695:                }
        !           696:                apr_brigade_cleanup(brigade);
        !           697:        } else {
        !           698:                ctx->r = parent_req;
        !           699:        }
        !           700: 
        !           701:        return OK;
        !           702: }
        !           703: 
        !           704: static void php_apache_child_init(apr_pool_t *pchild, server_rec *s)
        !           705: {
        !           706:        apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null);
        !           707: }
        !           708: 
        !           709: void php_ap2_register_hook(apr_pool_t *p)
        !           710: {
        !           711:        ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
        !           712:        ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
        !           713:        ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
        !           714:        ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
        !           715: }
        !           716: 
        !           717: /*
        !           718:  * Local variables:
        !           719:  * tab-width: 4
        !           720:  * c-basic-offset: 4
        !           721:  * End:
        !           722:  * vim600: sw=4 ts=4 fdm=marker
        !           723:  * vim<600: sw=4 ts=4
        !           724:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>