Annotation of embedaddon/php/sapi/apache_hooks/mod_php5.c, revision 1.1.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 at through the world-wide-web at                                                      |
                     10:    | http://www.php.net/license/3_01.txt                                                             |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to                 |
                     13:    | license@php.net so we can mail you a copy immediately.                          |
                     14:    +----------------------------------------------------------------------+
                     15:    | Authors: Rasmus Lerdorf <rasmus@php.net>                                                    |
                     16:    | (with helpful hints from Dean Gaudet <dgaudet@arctic.org>                   |
                     17:    | PHP 4.0 patches by Zeev Suraski <zeev@zend.com>                                     |
                     18:    +----------------------------------------------------------------------+
                     19:  */
                     20: /* $Id: mod_php5.c 321634 2012-01-01 13:15:04Z felipe $ */
                     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
                    278:         * and needs to recieve confirmation from the server on whether or not it can send
                    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 if (PG(register_globals)) {
                    407:                /* should never happen nowadays */
                    408:                symbol_table = EG(active_symbol_table);
                    409:        } else {
                    410:                symbol_table = NULL;
                    411:        }
                    412:        if (symbol_table
                    413:                && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"))
                    414:                && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) {
                    415:                php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC);
                    416:        }
                    417: 
                    418:        php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC);
                    419: }
                    420: /* }}} */
                    421: 
                    422: /* {{{ php_apache_startup
                    423:  */
                    424: static int php_apache_startup(sapi_module_struct *sapi_module)
                    425: {
                    426:        if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {
                    427:                return FAILURE;
                    428:        } else {
                    429:                return SUCCESS;
                    430:        }
                    431: }
                    432: /* }}} */
                    433: 
                    434: /* {{{ php_apache_log_message
                    435:  */
                    436: static void php_apache_log_message(char *message)
                    437: {
                    438:        TSRMLS_FETCH();
                    439: 
                    440:        if (SG(server_context)) {
                    441: #if MODULE_MAGIC_NUMBER >= 19970831
                    442:                aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
                    443: #else
                    444:                log_error(message, ((request_rec *) SG(server_context))->server);
                    445: #endif
                    446:        } else {
                    447:                fprintf(stderr, "%s", message);
                    448:                fprintf(stderr, "\n");
                    449:        }
                    450: }
                    451: /* }}} */
                    452: 
                    453: /* {{{ php_apache_request_shutdown
                    454:  */
                    455: static void php_apache_request_shutdown(void *dummy)
                    456: {
                    457:        TSRMLS_FETCH();
                    458:        AP(current_hook) = AP_CLEANUP;
                    459:        php_output_set_status(0 TSRMLS_CC);
                    460:        SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */
                    461:        if(SG(sapi_started)) {
                    462:                php_request_shutdown(dummy);
                    463:                SG(sapi_started) = 0;
                    464:        }
                    465:        AP(in_request) = 0;
                    466:        if(AP(setup_env)) {
                    467:                AP(setup_env) = 0;
                    468:        }
                    469:        AP(current_hook) = AP_WAITING_FOR_REQUEST;
                    470:        AP(headers_sent) = 0;
                    471: }
                    472: /* }}} */
                    473: 
                    474: /* {{{ php_apache_sapi_activate
                    475:  */
                    476: static int php_apache_sapi_activate(TSRMLS_D)
                    477: {
                    478:        request_rec *r = (request_rec *) SG(server_context); 
                    479: 
                    480:        /*
                    481:         * For the Apache module version, this bit of code registers a cleanup
                    482:         * function that gets triggered when our request pool is destroyed.
                    483:         * We need this because at any point in our code we can be interrupted
                    484:         * and that may happen before we have had time to free our memory.
                    485:         * The php_request_shutdown function needs to free all outstanding allocated
                    486:         * memory.  
                    487:         */
                    488:        block_alarms();
                    489:        register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec);
                    490:        AP(in_request)=1;
                    491:        unblock_alarms();
                    492: 
                    493:        /* Override the default headers_only value - sometimes "GET" requests should actually only
                    494:         * send headers.
                    495:         */
                    496:        SG(request_info).headers_only = r->header_only;
                    497:        return SUCCESS;
                    498: }
                    499: /* }}} */
                    500: 
                    501: /* {{{ php_apache_get_stat
                    502:  */
                    503: static struct stat *php_apache_get_stat(TSRMLS_D)
                    504: {
                    505:        return &((request_rec *) SG(server_context))->finfo;
                    506: }
                    507: /* }}} */
                    508: 
                    509: /* {{{ php_apache_getenv
                    510:  */
                    511: static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC)
                    512: {
                    513:        return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name);
                    514: }
                    515: /* }}} */
                    516: 
                    517: /* {{{ sapi_module_struct apache_sapi_module
                    518:  */
                    519: static sapi_module_struct apache_sapi_module = {
                    520:        "apache",                                               /* name */
                    521:        "Apache",                                               /* pretty name */
                    522:                                                                        
                    523:        php_apache_startup,                             /* startup */
                    524:        php_module_shutdown_wrapper,    /* shutdown */
                    525: 
                    526:        php_apache_sapi_activate,               /* activate */
                    527:        NULL,                                                   /* deactivate */
                    528: 
                    529:        sapi_apache_ub_write,                   /* unbuffered write */
                    530:        sapi_apache_flush,                              /* flush */
                    531:        php_apache_get_stat,                    /* get uid */
                    532:        php_apache_getenv,                              /* getenv */
                    533: 
                    534:        php_error,                                              /* error handler */
                    535: 
                    536:        sapi_apache_header_handler,             /* header handler */
                    537:        sapi_apache_send_headers,               /* send headers handler */
                    538:        NULL,                                                   /* send header handler */
                    539: 
                    540:        sapi_apache_read_post,                  /* read POST data */
                    541:        sapi_apache_read_cookies,               /* read Cookies */
                    542: 
                    543:        sapi_apache_register_server_variables,          /* register server variables */
                    544:        php_apache_log_message,                 /* Log message */
                    545:        NULL,                                                   /* Get request time */
                    546:        NULL,                                   /* child terminate */
                    547: 
                    548:        NULL,                                                   /* php.ini path override */
                    549: 
                    550: #ifdef PHP_WIN32
                    551:        NULL,
                    552:        NULL,
                    553: #else
                    554:        block_alarms,                                   /* Block interruptions */
                    555:        unblock_alarms,                                 /* Unblock interruptions */
                    556: #endif
                    557: 
                    558:        NULL,                           /* default post reader */
                    559:        NULL,                           /* treat data */
                    560:        NULL,                           /* exe location */
                    561:        0,                              /* ini ignore */
                    562:        NULL
                    563:        
                    564: };
                    565: /* }}} */
                    566: 
                    567: /* {{{ php_restore_umask
                    568:  */
                    569: static void php_restore_umask(void)
                    570: {
                    571:        umask(saved_umask);
                    572: }
                    573: /* }}} */
                    574: 
                    575: /* {{{ init_request_info
                    576:  */
                    577: static void init_request_info(TSRMLS_D)
                    578: {
                    579:        request_rec *r = ((request_rec *) SG(server_context));
                    580:        char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH");
                    581:        const char *authorization=NULL;
                    582:        char *tmp, *tmp_user;
                    583: 
                    584:        SG(request_info).query_string = r->args;
                    585:        SG(request_info).path_translated = r->filename;
                    586:        SG(request_info).request_uri = r->uri;
                    587:        SG(request_info).request_method = (char *)r->method;
                    588:        SG(request_info).proto_num = r->proto_num;
                    589:        SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
                    590:        SG(request_info).content_length = (content_length ? atol(content_length) : 0);
                    591:        SG(sapi_headers).http_response_code = r->status;
                    592: 
                    593:        if (r->headers_in) {
                    594:                authorization = table_get(r->headers_in, "Authorization");
                    595:        }
                    596: 
                    597:        SG(request_info).auth_user = NULL;
                    598:        SG(request_info).auth_password = NULL;
                    599: 
                    600:        if (authorization && !auth_type(r)) {
                    601:         if (!strcasecmp(getword(r->pool, &authorization, ' '), "Basic")) {
                    602:             tmp = uudecode(r->pool, authorization);
                    603:             tmp_user = getword_nulls_nc(r->pool, &tmp, ':');
                    604:             if (tmp_user) {
                    605:                 r->connection->user = pstrdup(r->connection->pool, tmp_user);
                    606:                 r->connection->ap_auth_type = "Basic";
                    607:                 SG(request_info).auth_user = estrdup(tmp_user);
                    608:             }
                    609:             if (tmp) {
                    610:                 SG(request_info).auth_password = estrdup(tmp);
                    611:             }
                    612:                } else if  (!strcasecmp(getword(r->pool, &authorization, ' '), "Digest")) {
                    613:             r->connection->ap_auth_type = "Digest";
                    614:             SG(request_info).auth_digest = estrdup(authorization);
                    615:                }
                    616:        }
                    617: }
                    618: /* }}} */
                    619: 
                    620: /* {{{ php_apache_alter_ini_entries
                    621:  */
                    622: static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC)
                    623: {
                    624:        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);
                    625:        return 0;
                    626: }
                    627: /* }}} */
                    628: 
                    629: /* {{{ php_apache_get_default_mimetype
                    630:  */
                    631: static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC)
                    632: {
                    633:        
                    634:        char *mimetype;
                    635:        if (SG(default_mimetype) || SG(default_charset)) {
                    636:                /* Assume output will be of the default MIME type.  Individual
                    637:                   scripts may change this later. */
                    638:                char *tmpmimetype;
                    639:                tmpmimetype = sapi_get_default_content_type(TSRMLS_C);
                    640:                mimetype = pstrdup(r->pool, tmpmimetype);
                    641:                efree(tmpmimetype);
                    642:        } else {
                    643:                mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET;
                    644:        }
                    645:        return mimetype;
                    646: }
                    647: /* }}} */
                    648: 
                    649: /* {{{ send_php
                    650:  */
                    651: static int send_php(request_rec *r, int display_source_mode, char *filename)
                    652: {
                    653:        int retval;
                    654:        php_per_dir_config *per_dir_conf;
                    655:        TSRMLS_FETCH();
                    656:        if (AP(in_request)) {
                    657:                zend_file_handle fh;
                    658: 
                    659:                fh.filename = r->filename;
                    660:                fh.opened_path = NULL;
                    661:                fh.free_filename = 0;
                    662:                fh.type = ZEND_HANDLE_FILENAME;
                    663: 
                    664:                zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh);
                    665:                return OK;
                    666:        }
                    667: 
                    668:        zend_first_try {
                    669: 
                    670:                /* Make sure file exists */
                    671:                if (filename == NULL && r->finfo.st_mode == 0) {
                    672:                        return DECLINED;
                    673:                }
                    674: 
                    675:                per_dir_conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                    676:                if (per_dir_conf) {
                    677:                        zend_hash_apply((HashTable *) per_dir_conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
                    678:                }
                    679: 
                    680:                /* If PHP parser engine has been turned off with an "engine off"
                    681:                 * directive, then decline to handle this request
                    682:                 */
                    683:                if (!AP(engine)) {
                    684:                        r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
                    685:                        r->allowed |= (1 << METHODS) - 1;
                    686:                        zend_try {
                    687:                                zend_ini_deactivate(TSRMLS_C);
                    688:                        } zend_end_try();
                    689:                        return DECLINED;
                    690:                }
                    691:                if (filename == NULL) {
                    692:                        filename = r->filename;
                    693:                }
                    694: 
                    695:                /* Apache 1.2 has a more complex mechanism for reading POST data */
                    696: #if MODULE_MAGIC_NUMBER > 19961007
                    697:                if ((retval = setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
                    698:                        zend_try {
                    699:                                zend_ini_deactivate(TSRMLS_C);
                    700:                        } zend_end_try();
                    701:                        return retval;
                    702:                }
                    703: #endif
                    704: 
                    705:                if (AP(last_modified)) {
                    706: #if MODULE_MAGIC_NUMBER < 19970912
                    707:                        if ((retval = set_last_modified(r, r->finfo.st_mtime))) {
                    708:                                zend_try {
                    709:                                        zend_ini_deactivate(TSRMLS_C);
                    710:                                } zend_end_try();
                    711:                                return retval;
                    712:                        }
                    713: #else
                    714:                        update_mtime (r, r->finfo.st_mtime);
                    715:                        set_last_modified(r);
                    716:                        set_etag(r);
                    717: #endif
                    718:                }
                    719:                /* Assume output will be of the default MIME type.  Individual
                    720:                   scripts may change this later in the request. */
                    721:                r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
                    722: 
                    723:                /* Init timeout */
                    724:                hard_timeout("send", r);
                    725: 
                    726:                SG(server_context) = r;
                    727:                
                    728:                php_save_umask();
                    729:                if(!AP(setup_env)) {
                    730:                        AP(setup_env) = 1;
                    731:                        add_common_vars(r);
                    732:                        add_cgi_vars(r);
                    733:                }
                    734:                init_request_info(TSRMLS_C);
                    735:                apache_php_module_main(r, display_source_mode TSRMLS_CC);
                    736:                
                    737:                /* Done, restore umask, turn off timeout, close file and return */
                    738:                php_restore_umask();
                    739:                kill_timeout(r);
                    740:        } zend_end_try();
                    741: 
                    742:        return OK;
                    743: }
                    744: /* }}} */
                    745: 
                    746: /* {{{ send_parsed_php
                    747:  */
                    748: static int send_parsed_php(request_rec * r)
                    749: {
                    750:        int result = send_php(r, 0, NULL);
                    751:        TSRMLS_FETCH();
                    752:  
                    753:        ap_table_setn(r->notes, "mod_php_memory_usage",
                    754:                ap_psprintf(r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
                    755: 
                    756:        return result;
                    757: }
                    758: /* }}} */
                    759: 
                    760: /* {{{ send_parsed_php_source
                    761:  */
                    762: static int send_parsed_php_source(request_rec * r)
                    763: {
                    764:        return send_php(r, 1, NULL);
                    765: }
                    766: /* }}} */
                    767: 
                    768: 
                    769: /* {{{ destroy_per_dir_entry
                    770:  */
                    771: static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry)
                    772: {
                    773:        free(per_dir_entry->key);
                    774:        free(per_dir_entry->value);
                    775: }
                    776: /* }}} */
                    777: 
                    778: /* {{{ copy_per_dir_entry
                    779:  */
                    780: static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry)
                    781: {
                    782:        php_per_dir_entry tmp = *per_dir_entry;
                    783: 
                    784:        per_dir_entry->key = (char *) malloc(tmp.key_length+1);
                    785:        memcpy(per_dir_entry->key, tmp.key, tmp.key_length);
                    786:        per_dir_entry->key[per_dir_entry->key_length] = 0;
                    787: 
                    788:        per_dir_entry->value = (char *) malloc(tmp.value_length+1);
                    789:        memcpy(per_dir_entry->value, tmp.value, tmp.value_length);
                    790:        per_dir_entry->value[per_dir_entry->value_length] = 0;
                    791: }
                    792: /* }}} */
                    793: 
                    794: /* {{{ should_overwrite_per_dir_entry;
                    795: 
                    796:  */
                    797: 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)
                    798: {
                    799:        php_per_dir_entry *new_per_dir_entry;
                    800: 
                    801:        if (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &new_per_dir_entry)==FAILURE) {
                    802:                return 1; /* does not exist in dest, copy from source */
                    803:        }
                    804: 
                    805:        if (new_per_dir_entry->type==PHP_INI_SYSTEM
                    806:                && orig_per_dir_entry->type!=PHP_INI_SYSTEM) {
                    807:                return 1;
                    808:        } else {
                    809:                return 0;
                    810:        }
                    811: }
                    812: /* }}} */
                    813: /* {{{ php_destroy_per_server_info
                    814:  */
                    815: static void php_destroy_per_server_info(php_per_server_config *conf)
                    816: {
                    817:        php_handler_stack_destroy(&conf->requires);
                    818:        php_handler_stack_destroy(&conf->uri_handlers);
                    819: }
                    820: /* }}} */
                    821: 
                    822: /* {{{ php_destroy_per_dir_info
                    823:  */
                    824: static void php_destroy_per_dir_info(php_per_dir_config *conf) 
                    825: {
                    826:        zend_hash_destroy(conf->ini_settings);
                    827:        php_handler_stack_destroy(&conf->response_handlers);
                    828:        php_handler_stack_destroy(&conf->auth_handlers);
                    829:        php_handler_stack_destroy(&conf->access_handlers);
                    830:        php_handler_stack_destroy(&conf->type_handlers);
                    831:        php_handler_stack_destroy(&conf->fixup_handlers);
                    832:        php_handler_stack_destroy(&conf->logger_handlers);
                    833:        php_handler_stack_destroy(&conf->post_read_handlers);
                    834:        php_handler_stack_destroy(&conf->headers_handlers);
                    835:        free(conf->ini_settings);
                    836: }
                    837: /* }}} */
                    838: 
                    839: /* {{{ php_create_server
                    840:  */
                    841: static void *php_create_server(pool *p, char *dummy)
                    842: {
                    843:        php_per_server_config *conf;
                    844:        conf = (php_per_server_config *) malloc(sizeof(php_per_server_config));
                    845:        register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_server_info, (void (*)(void *)) php_destroy_per_server_info);
                    846:        
                    847:        sapi_stack_init_ex(&conf->requires, 1);
                    848:        sapi_stack_init_ex(&conf->uri_handlers, 1);
                    849:        return conf;
                    850: }
                    851:        
                    852: /* }}} */
                    853: 
                    854: 
                    855: /* {{{ php_create_dir
                    856:  */
                    857: static void *php_create_dir(pool *p, char *dummy)
                    858: {
                    859:        php_per_dir_config *conf;
                    860:        conf = (php_per_dir_config *) malloc(sizeof(php_per_dir_config));
                    861:        conf->ini_settings = (HashTable *) malloc(sizeof(HashTable));
                    862:        zend_hash_init_ex(conf->ini_settings, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0);
                    863:        sapi_stack_init_ex(&conf->response_handlers, 1);
                    864:        sapi_stack_init_ex(&conf->headers_handlers, 1);
                    865:        sapi_stack_init_ex(&conf->auth_handlers, 1);
                    866:        sapi_stack_init_ex(&conf->access_handlers, 1);
                    867:        sapi_stack_init_ex(&conf->type_handlers, 1);
                    868:        sapi_stack_init_ex(&conf->fixup_handlers, 1);
                    869:        sapi_stack_init_ex(&conf->logger_handlers, 1);
                    870:        sapi_stack_init_ex(&conf->post_read_handlers, 1);
                    871:        register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) php_destroy_per_dir_info);
                    872:        
                    873:        return conf;
                    874: }
                    875: 
                    876: /* }}} */
                    877: 
                    878: /* {{{ php_merge_dir
                    879:  */
                    880: static void *php_merge_dir(pool *p, void *basev, void *addv)
                    881: {
                    882:        php_per_dir_config *a = (php_per_dir_config *) addv;
                    883:        php_per_dir_config *b = (php_per_dir_config *) basev;
                    884:        /* This function *must* return addv, and not modify basev */
                    885:        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);
                    886:        a->headers_handlers = (a->headers_handlers.top)?a->headers_handlers:b->headers_handlers;
                    887:        a->auth_handlers = (a->auth_handlers.top)?a->auth_handlers:b->auth_handlers;
                    888:        a->access_handlers = (a->access_handlers.top)?a->access_handlers:b->access_handlers;
                    889:        a->type_handlers = (a->type_handlers.top)?a->type_handlers:b->type_handlers;
                    890:        a->fixup_handlers = (a->fixup_handlers.top)?a->fixup_handlers:b->fixup_handlers;
                    891:        a->logger_handlers = (a->logger_handlers.top)?a->logger_handlers:b->logger_handlers;
                    892:        a->post_read_handlers = (a->post_read_handlers.top)?a->post_read_handlers:b->post_read_handlers;
                    893:        a->response_handlers = (a->response_handlers.top)?a->response_handlers:b->response_handlers;
                    894:        return a;
                    895: }
                    896: /* }}} */
                    897: 
                    898: /* {{{ php_apache_value_handler_ex
                    899:  */
                    900: static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
                    901: {
                    902:        php_per_dir_entry per_dir_entry;
                    903: 
                    904:        if (!apache_php_initialized) {
                    905:                apache_php_initialized = 1;
                    906: #ifdef ZTS
                    907:                tsrm_startup(1, 1, 0, NULL);
                    908: #endif
                    909:                sapi_startup(&apache_sapi_module);
                    910:                php_apache_startup(&apache_sapi_module);
                    911:        }
                    912:        per_dir_entry.type = mode;
                    913: 
                    914:        if (strcasecmp(arg2, "none") == 0) {
                    915:                arg2 = "";
                    916:        }
                    917: 
                    918:        per_dir_entry.key_length = strlen(arg1);
                    919:        per_dir_entry.value_length = strlen(arg2);
                    920: 
                    921:        per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1);
                    922:        memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);
                    923:        per_dir_entry.key[per_dir_entry.key_length] = 0;
                    924: 
                    925:        per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1);
                    926:        memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length);
                    927:        per_dir_entry.value[per_dir_entry.value_length] = 0;
                    928: 
                    929:        zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL);
                    930:        return NULL;
                    931: }
                    932: /* }}} */
                    933: 
                    934: static CONST_PREFIX char *php_set_server_handler(server_rec *s, char *arg1, long handler_stage, long handler_type)
                    935: {
                    936:        php_per_server_config *conf;
                    937:        php_handler *handler;
                    938:        handler = (php_handler *) malloc(sizeof(php_handler));
                    939:        handler->type = handler_type;
                    940:        handler->stage = handler_stage;
                    941:        handler->name = strdup(arg1);
                    942:        conf = get_module_config(s->module_config, &php5_module);
                    943:        switch(handler_stage) {
                    944:                case AP_URI_TRANS:
                    945:                        sapi_stack_push(&conf->uri_handlers, handler);
                    946:                        break;
                    947:                default:
                    948:                        sapi_stack_push(&conf->requires, handler);
                    949:                        break;
                    950:        }
                    951:        return NULL;
                    952: }
                    953: 
                    954: static CONST_PREFIX char *php_set_dir_handler(php_per_dir_config *conf, char *arg1, long handler_stage, long handler_type)
                    955: {
                    956:        php_handler *handler;
                    957:        handler = (php_handler *) malloc(sizeof(php_handler));
                    958:        handler->type = handler_type;
                    959:        handler->stage = handler_stage;
                    960:        handler->name = strdup(arg1);
                    961:        switch(handler_stage) {
                    962:                case AP_POST_READ:
                    963:                        sapi_stack_push(&conf->post_read_handlers, handler);
                    964:                        break;
                    965:                case AP_HEADER_PARSE:
                    966:                        sapi_stack_push(&conf->headers_handlers, handler);
                    967:                        break;
                    968:                case AP_ACCESS_CONTROL:
                    969:                        sapi_stack_push(&conf->access_handlers, handler);
                    970:                        break;
                    971:                case AP_AUTHENTICATION:
                    972:                        sapi_stack_push(&conf->auth_handlers, handler);
                    973:                        break;
                    974:                case AP_AUTHORIZATION:
                    975:                        break;
                    976:                case AP_TYPE_CHECKING:
                    977:                        sapi_stack_push(&conf->type_handlers, handler);
                    978:                        break;
                    979:                case AP_FIXUP:
                    980:                        sapi_stack_push(&conf->fixup_handlers, handler);
                    981:                        break;
                    982:                case AP_RESPONSE:
                    983:                        sapi_stack_push(&conf->response_handlers, handler);
                    984:                        break;
                    985:                case AP_LOGGING:
                    986:                        sapi_stack_push(&conf->logger_handlers, handler);
                    987:                        break;
                    988:                default:
                    989:                        break;
                    990:        }
                    991:        return NULL;
                    992: }
                    993: 
                    994: /* {{{ php_set_uri_handler 
                    995:  */
                    996: static CONST_PREFIX char *php_set_uri_handler(cmd_parms *cmd, void *dummy, char *arg1)
                    997: {
                    998:        return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_FILE);
                    999: }
                   1000: /* }}} */
                   1001: 
                   1002: /* {{{ php_set_uri_handler_code */
                   1003: static CONST_PREFIX char *php_set_uri_handler_code(cmd_parms *cmd, void *dummy, char *arg1)
                   1004: {
                   1005:        return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_METHOD);
                   1006: }
                   1007: /* }}} */
                   1008: 
                   1009: /* {{{ php_set_header_handler
                   1010:  */
                   1011: static CONST_PREFIX char *php_set_header_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1012: {
                   1013:        return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_FILE);
                   1014: }
                   1015: static CONST_PREFIX char *php_set_header_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1016: {
                   1017:        return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_METHOD);
                   1018: }
                   1019: /* }}} */
                   1020: 
                   1021: /* {{{ php_set_auth_handler 
                   1022:  */
                   1023: static CONST_PREFIX char *php_set_auth_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1024: {
                   1025:        return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_FILE);
                   1026: }
                   1027: static CONST_PREFIX char *php_set_auth_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1028: {
                   1029:        return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_METHOD);
                   1030: }
                   1031: 
                   1032: /* }}} */
                   1033: 
                   1034: /* {{{ php_set_access_handler
                   1035:  */
                   1036: static CONST_PREFIX char *php_set_access_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1037: {
                   1038:        return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_FILE);
                   1039: }
                   1040: static CONST_PREFIX char *php_set_access_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1041: {
                   1042:        return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_METHOD);
                   1043: }
                   1044: 
                   1045: /* }}} */
                   1046: 
                   1047: /* {{{ php_set_type_handler
                   1048:  */
                   1049: static CONST_PREFIX char *php_set_type_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1050: {
                   1051:        return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_FILE);
                   1052: }
                   1053: static CONST_PREFIX char *php_set_type_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1054: {
                   1055:        return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_METHOD);
                   1056: }
                   1057: 
                   1058: /* }}} */
                   1059: 
                   1060: /* {{{ php_set_fixup_handler
                   1061:  */
                   1062: static CONST_PREFIX char *php_set_fixup_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1063: {
                   1064:        return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_FILE);
                   1065: }
                   1066: static CONST_PREFIX char *php_set_fixup_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1067: {
                   1068:        return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_METHOD);
                   1069: }
                   1070: /* }}} */
                   1071: 
                   1072: /* {{{ php_set_logger_handler
                   1073:  */
                   1074: static CONST_PREFIX char *php_set_logger_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1075: {
                   1076:        return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_FILE);
                   1077: }
                   1078: static CONST_PREFIX char *php_set_logger_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1079: {
                   1080:        return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_METHOD);
                   1081: }
                   1082: 
                   1083: /* }}} */ 
                   1084: 
                   1085: /* {{{ php_set_post_read_handler
                   1086:  */
                   1087: static CONST_PREFIX char *php_set_post_read_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1088: {
                   1089:        return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_FILE);
                   1090: }
                   1091: static CONST_PREFIX char *php_set_post_read_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1092: {
                   1093:        return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_METHOD);
                   1094: }
                   1095: 
                   1096: 
                   1097: /* }}} */
                   1098: 
                   1099: /* {{{ php_set_require
                   1100:  */
                   1101: 
                   1102: static CONST_PREFIX char *php_set_require(cmd_parms *cmd, void *dummy, char *arg1)
                   1103: {
                   1104:        return php_set_server_handler(cmd->server, arg1, 0, AP_HANDLER_TYPE_FILE);
                   1105: }
                   1106: /* }}} */
                   1107: 
                   1108: /* {{{ php_set_response_handler
                   1109:  */
                   1110: static CONST_PREFIX char *php_set_response_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1111: {
                   1112:        return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_FILE);
                   1113: }
                   1114: static CONST_PREFIX char *php_set_response_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
                   1115: {
                   1116:        return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_METHOD);
                   1117: }
                   1118: /* }}} */
                   1119:        
                   1120: /* {{{ php_apache_value_handler
                   1121:  */
                   1122: static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
                   1123: {
                   1124:        return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR);
                   1125: }
                   1126: /* }}} */
                   1127: 
                   1128: /* {{{ php_apache_admin_value_handler
                   1129:  */
                   1130: static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
                   1131: {
                   1132:        return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM);
                   1133: }
                   1134: /* }}} */
                   1135: 
                   1136: /* {{{ php_apache_flag_handler_ex
                   1137:  */
                   1138: static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
                   1139: {
                   1140:        char bool_val[2];
                   1141: 
                   1142:        if (!strcasecmp(arg2, "On")) {
                   1143:                bool_val[0] = '1';
                   1144:        } else {
                   1145:                bool_val[0] = '0';
                   1146:        }
                   1147:        bool_val[1] = 0;
                   1148:        
                   1149:        return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode);
                   1150: }
                   1151: /* }}} */
                   1152: 
                   1153: /* {{{ php_apache_flag_handler
                   1154:  */
                   1155: static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
                   1156: {
                   1157:        return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR);
                   1158: }
                   1159: /* }}} */
                   1160: 
                   1161: /* {{{ php_apache_admin_flag_handler
                   1162:  */
                   1163: static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
                   1164: {
                   1165:        return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM);
                   1166: }
                   1167: /* }}} */
                   1168: 
                   1169: /* {{{ php_apache_phpini_set
                   1170:  */
                   1171: static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg)
                   1172: {
                   1173:        if (apache_sapi_module.php_ini_path_override) {
                   1174:                return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored";
                   1175:        }
                   1176:        apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg);
                   1177:        return NULL;
                   1178: }
                   1179: /* }}} */
                   1180: 
                   1181: /* {{{ int php_xbithack_handler(request_rec * r)
                   1182:  */
                   1183: static int php_xbithack_handler(request_rec * r)
                   1184: {
                   1185:        php_per_dir_config *conf;
                   1186:        TSRMLS_FETCH();
                   1187: 
                   1188:        if (!(r->finfo.st_mode & S_IXUSR)) {
                   1189:                r->allowed |= (1 << METHODS) - 1;
                   1190:                return DECLINED;
                   1191:        }
                   1192:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1193:        if (conf) {
                   1194:                zend_hash_apply((HashTable *) conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
                   1195:        }
                   1196:        if(!AP(xbithack)) {
                   1197:                r->allowed |= (1 << METHODS) - 1;
                   1198:                zend_try {
                   1199:                        zend_ini_deactivate(TSRMLS_C);
                   1200:                } zend_end_try();
                   1201:                return DECLINED;
                   1202:        }
                   1203:        return send_parsed_php(r);
                   1204: }
                   1205: /* }}} */
                   1206: 
                   1207: /* {{{ apache_php_module_shutdown_wrapper
                   1208:  */
                   1209: static void apache_php_module_shutdown_wrapper(void)
                   1210: {
                   1211:        apache_php_initialized = 0;
                   1212:        apache_sapi_module.shutdown(&apache_sapi_module);
                   1213: 
                   1214: #if MODULE_MAGIC_NUMBER >= 19970728
                   1215:        /* This function is only called on server exit if the apache API
                   1216:         * child_exit handler exists, so shutdown globally 
                   1217:         */
                   1218:        sapi_shutdown();
                   1219: #endif
                   1220: 
                   1221: #ifdef ZTS
                   1222:        tsrm_shutdown();
                   1223: #endif
                   1224: }
                   1225: /* }}} */
                   1226: 
                   1227: #if MODULE_MAGIC_NUMBER >= 19970728
                   1228: /* {{{ php_child_exit_handler
                   1229:  */
                   1230: static void php_child_exit_handler(server_rec *s, pool *p)
                   1231: {
                   1232: /*     apache_php_initialized = 0; */
                   1233:        apache_sapi_module.shutdown(&apache_sapi_module);
                   1234: 
                   1235: #ifdef ZTS
                   1236:        tsrm_shutdown();
                   1237: #endif
                   1238: }
                   1239: /* }}} */
                   1240: #endif
                   1241: 
                   1242: /* {{{ void php_init_handler(server_rec *s, pool *p)
                   1243:  */
                   1244: static void php_init_handler(server_rec *s, pool *p)
                   1245: {
                   1246:        register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);
                   1247:        if (!apache_php_initialized) {
                   1248:                apache_php_initialized = 1;
                   1249: #ifdef ZTS
                   1250:                tsrm_startup(1, 1, 0, NULL);
                   1251: #endif
                   1252:                sapi_startup(&apache_sapi_module);
                   1253:                php_apache_startup(&apache_sapi_module);
                   1254:        }
                   1255: #if MODULE_MAGIC_NUMBER >= 19980527
                   1256:        {
                   1257:                TSRMLS_FETCH();
                   1258:                if (PG(expose_php)) {
                   1259: #if SUHOSIN_PATCH
                   1260:                        ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
                   1261: #else
                   1262:                        ap_add_version_component("PHP/" PHP_VERSION);
                   1263: #endif
                   1264:                }
                   1265:        }
                   1266: #endif
                   1267: }
                   1268: /* }}} */
                   1269: 
                   1270: static int php_run_hook(php_handler *handler, request_rec *r)
                   1271: {
                   1272:        zval *ret = NULL;
                   1273:        php_per_dir_config *conf;
                   1274: 
                   1275:        TSRMLS_FETCH();
                   1276: 
                   1277:        if(!AP(apache_config_loaded)) {
                   1278:                conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1279:                if (conf)
                   1280:                           zend_hash_apply((HashTable *)conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
                   1281:                AP(apache_config_loaded) = 1;
                   1282:        }
                   1283:        if (!handler->name) {
                   1284:                return DECLINED;
                   1285:        }
                   1286:        php_save_umask();
                   1287:        if (!AP(setup_env)) {
                   1288:                AP(setup_env) = 1;
                   1289:                add_common_vars(r);
                   1290:                add_cgi_vars(r);
                   1291:        }
                   1292:        SG(server_context) = r;
                   1293:        init_request_info(TSRMLS_C);
                   1294:        apache_php_module_hook(r, handler, &ret TSRMLS_CC);
                   1295:        php_restore_umask();
                   1296:        kill_timeout(r);
                   1297:        if (ret) {
                   1298:                convert_to_long(ret);
                   1299:                return Z_LVAL_P(ret);
                   1300:        }
                   1301:        return HTTP_INTERNAL_SERVER_ERROR;
                   1302: }
                   1303:  
                   1304: 
                   1305: static int php_uri_translation(request_rec *r)
                   1306: {      
                   1307:        php_per_server_config *conf;
                   1308:        TSRMLS_FETCH();
                   1309:        AP(current_hook) = AP_URI_TRANS;
                   1310:        conf = (php_per_server_config *) get_module_config(r->server->module_config, &php5_module);
                   1311:        return sapi_stack_apply_with_argument_stop_if_equals(&conf->uri_handlers, 
                   1312:                        ZEND_STACK_APPLY_BOTTOMUP, 
                   1313:                        (int (*)(void *element, void *)) php_run_hook, r, OK);
                   1314: }
                   1315: 
                   1316: static int php_header_hook(request_rec *r)
                   1317: {
                   1318:        php_per_dir_config *conf;
                   1319:        TSRMLS_FETCH();
                   1320:        AP(current_hook) = AP_HEADER_PARSE;
                   1321:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1322:        return sapi_stack_apply_with_argument_stop_if_http_error(&conf->headers_handlers,
                   1323:                        ZEND_STACK_APPLY_BOTTOMUP,
                   1324:                        (int (*)(void *element, void *)) php_run_hook, r);
                   1325: }
                   1326: 
                   1327: static int php_auth_hook(request_rec *r)
                   1328: {
                   1329:        php_per_dir_config *conf;
                   1330:        TSRMLS_FETCH();
                   1331:        AP(current_hook) = AP_AUTHENTICATION;
                   1332:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1333:        return sapi_stack_apply_with_argument_stop_if_equals(&conf->auth_handlers, 
                   1334:                        ZEND_STACK_APPLY_BOTTOMUP, 
                   1335:                        (int (*)(void *element, void *)) php_run_hook, r, OK);
                   1336: }
                   1337: 
                   1338: static int php_access_hook(request_rec *r)
                   1339: {
                   1340:        php_per_dir_config *conf;
                   1341:        int status = DECLINED;
                   1342:        TSRMLS_FETCH();
                   1343:        AP(current_hook) = AP_ACCESS_CONTROL;
                   1344:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1345:        status =  sapi_stack_apply_with_argument_stop_if_http_error(&conf->access_handlers,
                   1346:                        ZEND_STACK_APPLY_BOTTOMUP,
                   1347:                        (int (*)(void *element, void *)) php_run_hook, r);
                   1348:        return status;
                   1349: 
                   1350: }
                   1351: 
                   1352: static int php_type_hook(request_rec *r)
                   1353: {
                   1354:        php_per_dir_config *conf;
                   1355:        TSRMLS_FETCH();
                   1356:        AP(current_hook) = AP_TYPE_CHECKING;
                   1357:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1358:        return sapi_stack_apply_with_argument_stop_if_equals(&conf->type_handlers,
                   1359:                        ZEND_STACK_APPLY_BOTTOMUP,
                   1360:                        (int (*)(void *element, void *)) php_run_hook,
                   1361:                        r, OK);
                   1362: }
                   1363: 
                   1364: static int php_fixup_hook(request_rec *r)
                   1365: {
                   1366:        php_per_dir_config *conf;
                   1367:        TSRMLS_FETCH();
                   1368:        AP(current_hook) = AP_FIXUP;
                   1369:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1370:        return sapi_stack_apply_with_argument_stop_if_http_error(&conf->fixup_handlers,
                   1371:                        ZEND_STACK_APPLY_BOTTOMUP,
                   1372:                        (int (*)(void *element, void *)) php_run_hook,
                   1373:                        r);
                   1374: }
                   1375: 
                   1376: static int php_logger_hook(request_rec *r)
                   1377: {
                   1378:        php_per_dir_config *conf;
                   1379:        TSRMLS_FETCH();
                   1380:        AP(current_hook) = AP_LOGGING;
                   1381:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1382:        return sapi_stack_apply_with_argument_stop_if_http_error(&conf->logger_handlers,
                   1383:                        ZEND_STACK_APPLY_BOTTOMUP,
                   1384:                        (int (*)(void *element, void *)) php_run_hook,
                   1385:                        r);
                   1386: }
                   1387:  
                   1388: static int php_post_read_hook(request_rec *r)
                   1389: {
                   1390:        php_per_dir_config *conf;
                   1391:        php_per_server_config *svr;
                   1392:        TSRMLS_FETCH();
                   1393:        AP(current_hook) = AP_POST_READ;
                   1394:        svr = get_module_config(r->server->module_config, &php5_module);
                   1395:        if(ap_is_initial_req(r)) {
                   1396:                sapi_stack_apply_with_argument_all(&svr->requires, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r);
                   1397:        }
                   1398:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1399:        return sapi_stack_apply_with_argument_stop_if_http_error(&conf->post_read_handlers,
                   1400:                        ZEND_STACK_APPLY_BOTTOMUP,
                   1401:                        (int (*)(void *element, void *)) php_run_hook, r);
                   1402: }
                   1403: 
                   1404: static int php_response_handler(request_rec *r)
                   1405: {
                   1406:        php_per_dir_config *conf;
                   1407:        TSRMLS_FETCH();
                   1408:        AP(current_hook) = AP_RESPONSE;
                   1409:        conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
                   1410:        return sapi_stack_apply_with_argument_all(&conf->response_handlers, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r);
                   1411: }
                   1412: 
                   1413: /* {{{ handler_rec php_handlers[]
                   1414:  */
                   1415: handler_rec php_handlers[] =
                   1416: {
                   1417:        {"application/x-httpd-php", send_parsed_php},
                   1418:        {"application/x-httpd-php-source", send_parsed_php_source},
                   1419:        {"text/html", php_xbithack_handler},
                   1420:                {"php-script", php_response_handler},
                   1421:        {NULL}
                   1422: };
                   1423: /* }}} */
                   1424: 
                   1425: /* {{{ command_rec php_commands[]
                   1426:  */
                   1427: command_rec php_commands[] =
                   1428: {
                   1429:        {"php_value",           php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"},
                   1430:        {"phpUriHandler",               php_set_uri_handler, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"},
                   1431:        {"phpUriHandlerMethod",         php_set_uri_handler_code, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"},
                   1432: #if MODULE_MAGIC_NUMBER >= 19970103
                   1433:        {"phpHeaderHandler",            php_set_header_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1434:        {"phpHeaderHandlerMethod",              php_set_header_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1435: #endif
                   1436:        {"phpAuthHandler",              php_set_auth_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1437:        {"phpAuthHandlerMethod",                php_set_auth_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1438:        {"phpAccessHandler",            php_set_access_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1439:        {"phpAccessHandlerMethod",              php_set_access_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1440:        {"phpTypeHandler",              php_set_type_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1441:        {"phpTypeHandlerMethod",                php_set_type_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1442:        {"phpFixupHandler",             php_set_fixup_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1443:        {"phpFixupHandlerMethod",               php_set_fixup_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1444:        {"phpLoggerHandler",                    php_set_logger_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1445:        {"phpLoggerHandlerMethod",              php_set_logger_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1446: #if MODULE_MAGIC_NUMBER >= 19970902
                   1447:        {"phpPostReadHandler",          php_set_post_read_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1448:        {"phpPostReadHandlerMethod",            php_set_post_read_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1449:        {"phpRequire",          php_set_require, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1450:        {"phpResponseHandler",          php_set_response_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1451:        {"phpResponseHandlerMethod",            php_set_response_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
                   1452: #endif
                   1453:        {"php_flag",            php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"},
                   1454:        {"php_admin_value",     php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"},
                   1455:        {"php_admin_flag",      php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"},
                   1456:        {"PHPINIDir",       php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"},
                   1457:        {NULL}
                   1458: };
                   1459: /* }}} */
                   1460: 
                   1461: /* {{{ module MODULE_VAR_EXPORT php5_module
                   1462:  */
                   1463: module MODULE_VAR_EXPORT php5_module =
                   1464: {
                   1465:        STANDARD_MODULE_STUFF,
                   1466:        php_init_handler,                       /* initializer */
                   1467:        php_create_dir,                         /* per-directory config creator */
                   1468:        php_merge_dir,                          /* dir merger */
                   1469:        php_create_server,                      /* per-server config creator */
                   1470:        NULL,                                           /* merge server config */
                   1471:        php_commands,                           /* command table */
                   1472:        php_handlers,                           /* handlers */
                   1473:        php_uri_translation,            /* filename translation */
                   1474:        NULL,                                           /* check_user_id */
                   1475:        php_auth_hook,                          /* check auth */
                   1476:        php_access_hook,                        /* check access */
                   1477:        php_type_hook,                          /* type_checker */
                   1478:        php_fixup_hook,                         /* fixups */
                   1479:        php_logger_hook                         /* logger */
                   1480: #if MODULE_MAGIC_NUMBER >= 19970103
                   1481:        , php_header_hook                                               /* header parser */
                   1482: #endif
                   1483: #if MODULE_MAGIC_NUMBER >= 19970719
                   1484:        , NULL                                          /* child_init */
                   1485: #endif
                   1486: #if MODULE_MAGIC_NUMBER >= 19970728
                   1487:        , php_child_exit_handler        /* child_exit */
                   1488: #endif
                   1489: #if MODULE_MAGIC_NUMBER >= 19970902
                   1490:        , php_post_read_hook                                            /* post read-request */
                   1491: #endif
                   1492: };
                   1493: /* }}} */
                   1494: 
                   1495: /*
                   1496:  * Local variables:
                   1497:  * tab-width: 4
                   1498:  * c-basic-offset: 4
                   1499:  * End:
                   1500:  * vim600: sw=4 ts=4 fdm=marker
                   1501:  * vim<600: sw=4 ts=4
                   1502:  */

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