Annotation of embedaddon/php/sapi/apache_hooks/mod_php5.c, revision 1.1.1.4

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

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