Annotation of embedaddon/php/sapi/apache/mod_php5.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Authors: 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: #include "http_conf_globals.h"
        !            24: 
        !            25: #ifdef NETWARE
        !            26: #define SIGPIPE SIGINT
        !            27: #endif
        !            28: 
        !            29: #undef shutdown
        !            30: 
        !            31: /* {{{ Prototypes
        !            32:  */
        !            33: int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC);
        !            34: static void php_save_umask(void);
        !            35: static void php_restore_umask(void);
        !            36: static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC);
        !            37: static char *sapi_apache_read_cookies(TSRMLS_D);
        !            38: static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC);
        !            39: static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC);
        !            40: static int send_php(request_rec *r, int display_source_mode, char *filename);
        !            41: static int send_parsed_php(request_rec * r);
        !            42: static int send_parsed_php_source(request_rec * r);
        !            43: static int php_xbithack_handler(request_rec * r);
        !            44: static void php_init_handler(server_rec *s, pool *p);
        !            45: /* }}} */
        !            46: 
        !            47: #if MODULE_MAGIC_NUMBER >= 19970728
        !            48: static void php_child_exit_handler(server_rec *s, pool *p);
        !            49: #endif
        !            50: 
        !            51: #if MODULE_MAGIC_NUMBER > 19961007
        !            52: #define CONST_PREFIX const
        !            53: #else
        !            54: #define CONST_PREFIX
        !            55: #endif
        !            56: static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
        !            57: static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
        !            58: static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
        !            59: static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
        !            60: static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
        !            61: static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2);
        !            62: 
        !            63: /* ### these should be defined in mod_php5.h or somewhere else */
        !            64: #define USE_PATH 1
        !            65: #define IGNORE_URL 2
        !            66: #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST POSSIBLE STATUS DESCRIPTION")
        !            67: 
        !            68: module MODULE_VAR_EXPORT php5_module;
        !            69: 
        !            70: int saved_umask;
        !            71: static unsigned char apache_php_initialized;
        !            72: 
        !            73: typedef struct _php_per_dir_entry {
        !            74:        char *key;
        !            75:        char *value;
        !            76:        uint key_length;
        !            77:        uint value_length;
        !            78:        int type;
        !            79:        char htaccess;
        !            80: } php_per_dir_entry;
        !            81: 
        !            82: /* some systems are missing these from their header files */
        !            83: 
        !            84: /* {{{ php_save_umask
        !            85:  */
        !            86: static void php_save_umask(void)
        !            87: {
        !            88:        saved_umask = umask(077);
        !            89:        umask(saved_umask);
        !            90: }
        !            91: /* }}} */
        !            92: 
        !            93: /* {{{ sapi_apache_ub_write
        !            94:  */
        !            95: static int sapi_apache_ub_write(const char *str, uint str_length TSRMLS_DC)
        !            96: {
        !            97:        int ret=0;
        !            98:                
        !            99:        if (SG(server_context)) {
        !           100:                ret = rwrite(str, str_length, (request_rec *) SG(server_context));
        !           101:        }
        !           102:        if (ret != str_length) {
        !           103:                php_handle_aborted_connection();
        !           104:        }
        !           105:        return ret;
        !           106: }
        !           107: /* }}} */
        !           108: 
        !           109: /* {{{ sapi_apache_flush
        !           110:  */
        !           111: static void sapi_apache_flush(void *server_context)
        !           112: {
        !           113:        if (server_context) {
        !           114: #if MODULE_MAGIC_NUMBER > 19970110
        !           115:                rflush((request_rec *) server_context);
        !           116: #else
        !           117:                bflush((request_rec *) server_context->connection->client);
        !           118: #endif
        !           119:        }
        !           120: }
        !           121: /* }}} */
        !           122: 
        !           123: /* {{{ sapi_apache_read_post
        !           124:  */
        !           125: static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC)
        !           126: {
        !           127:        int total_read_bytes=0, read_bytes;
        !           128:        request_rec *r = (request_rec *) SG(server_context);
        !           129:        void (*handler)(int);
        !           130: 
        !           131:        /*
        !           132:         * This handles the situation where the browser sends a Expect: 100-continue header
        !           133:         * and needs to recieve confirmation from the server on whether or not it can send
        !           134:         * the rest of the request. RFC 2616
        !           135:         *
        !           136:         */
        !           137:        if (!SG(read_post_bytes) && !ap_should_client_block(r)) {
        !           138:                return total_read_bytes;
        !           139:        }
        !           140:  
        !           141:        handler = signal(SIGPIPE, SIG_IGN);
        !           142:        while (total_read_bytes<count_bytes) {
        !           143:                hard_timeout("Read POST information", r); /* start timeout timer */
        !           144:                read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes);
        !           145:                reset_timeout(r);
        !           146:                if (read_bytes<=0) {
        !           147:                        break;
        !           148:                }
        !           149:                total_read_bytes += read_bytes;
        !           150:        }
        !           151:        signal(SIGPIPE, handler);       
        !           152:        return total_read_bytes;
        !           153: }
        !           154: /* }}} */
        !           155: 
        !           156: /* {{{ sapi_apache_read_cookies
        !           157:  */
        !           158: static char *sapi_apache_read_cookies(TSRMLS_D)
        !           159: {
        !           160:        return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE");
        !           161: }
        !           162: /* }}} */
        !           163: 
        !           164: /* {{{ sapi_apache_header_handler
        !           165:  */
        !           166: static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
        !           167: {
        !           168:        char *header_name, *header_content, *p;
        !           169:        request_rec *r = (request_rec *) SG(server_context);
        !           170:        if(!r) {
        !           171:                return 0;
        !           172:        }
        !           173: 
        !           174:        switch(op) {
        !           175:                case SAPI_HEADER_DELETE_ALL:
        !           176:                        clear_table(r->headers_out);
        !           177:                        return 0;
        !           178: 
        !           179:                case SAPI_HEADER_DELETE:
        !           180:                        table_unset(r->headers_out, sapi_header->header);
        !           181:                        return 0;
        !           182: 
        !           183:                case SAPI_HEADER_ADD:
        !           184:                case SAPI_HEADER_REPLACE:
        !           185:                        header_name = sapi_header->header;
        !           186: 
        !           187:                        header_content = p = strchr(header_name, ':');
        !           188:                        if (!p) {
        !           189:                                return 0;
        !           190:                        }
        !           191: 
        !           192:                        *p = 0;
        !           193:                        do {
        !           194:                                header_content++;
        !           195:                        } while (*header_content==' ');
        !           196: 
        !           197:                        if (!strcasecmp(header_name, "Content-Type")) {
        !           198:                                r->content_type = pstrdup(r->pool, header_content);
        !           199:                        } else if (!strcasecmp(header_name, "Content-Length")) {
        !           200:                                ap_set_content_length(r, strtol(header_content, (char **)NULL, 10));
        !           201:                        } else if (!strcasecmp(header_name, "Set-Cookie")) {
        !           202:                                table_add(r->headers_out, header_name, header_content);
        !           203:                        } else if (op == SAPI_HEADER_REPLACE) {
        !           204:                                table_set(r->headers_out, header_name, header_content);
        !           205:                        } else {
        !           206:                                table_add(r->headers_out, header_name, header_content);
        !           207:                        }
        !           208: 
        !           209:                        *p = ':';  /* a well behaved header handler shouldn't change its original arguments */
        !           210: 
        !           211:                        return SAPI_HEADER_ADD;
        !           212: 
        !           213:                default:
        !           214:                        return 0;
        !           215:        }
        !           216: }
        !           217: /* }}} */
        !           218: 
        !           219: /* {{{ sapi_apache_send_headers
        !           220:  */
        !           221: static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
        !           222: {
        !           223:        request_rec *r = SG(server_context);
        !           224:        const char *sline = SG(sapi_headers).http_status_line;
        !           225:        int sline_len;
        !           226: 
        !           227:        if(r == NULL) { /* server_context is not here anymore */
        !           228:                return SAPI_HEADER_SEND_FAILED;
        !           229:        }
        !           230: 
        !           231:        r->status = SG(sapi_headers).http_response_code;
        !           232: 
        !           233:        /* httpd requires that r->status_line is set to the first digit of
        !           234:         * the status-code: */
        !           235:        if (sline && ((sline_len = strlen(sline)) > 12) && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ' && sline[12] == ' ') {
        !           236:                if ((sline_len - 9) > MAX_STATUS_LENGTH) {
        !           237:                        r->status_line = ap_pstrndup(r->pool, sline + 9, MAX_STATUS_LENGTH);
        !           238:                } else {
        !           239:                        r->status_line = ap_pstrndup(r->pool, sline + 9, sline_len - 9);
        !           240:                }
        !           241:        }
        !           242: 
        !           243:        if(r->status==304) {
        !           244:                send_error_response(r,0);
        !           245:        } else {
        !           246:                send_http_header(r);
        !           247:        }
        !           248:        return SAPI_HEADER_SENT_SUCCESSFULLY;
        !           249: }
        !           250: /* }}} */
        !           251: 
        !           252: /* {{{ sapi_apache_register_server_variables
        !           253:  */
        !           254: static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_DC)
        !           255: {
        !           256:        register int i;
        !           257:        array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env);
        !           258:        table_entry *elts = (table_entry *) arr->elts;
        !           259:        zval **path_translated;
        !           260:        HashTable *symbol_table;
        !           261:        unsigned int new_val_len;
        !           262: 
        !           263:        for (i = 0; i < arr->nelts; i++) {
        !           264:                char *val;
        !           265:                int val_len;
        !           266: 
        !           267:                if (elts[i].val) {
        !           268:                        val = elts[i].val;
        !           269:                } else {
        !           270:                        val = "";
        !           271:                }
        !           272:                val_len = strlen(val);
        !           273:                if (sapi_module.input_filter(PARSE_SERVER, elts[i].key, &val, val_len, &new_val_len TSRMLS_CC)) {
        !           274:                        php_register_variable_safe(elts[i].key, val, new_val_len, track_vars_array TSRMLS_CC);
        !           275:                }
        !           276:        }
        !           277: 
        !           278:        /* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
        !           279:        if (track_vars_array) {
        !           280:                symbol_table = track_vars_array->value.ht;
        !           281:        } else if (PG(register_globals)) {
        !           282:                /* should never happen nowadays */
        !           283:                symbol_table = EG(active_symbol_table);
        !           284:        } else {
        !           285:                symbol_table = NULL;
        !           286:        }
        !           287:        if (symbol_table
        !           288:                && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"))
        !           289:                && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) {
        !           290:                php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC);
        !           291:        }
        !           292: 
        !           293:        if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &((request_rec *) SG(server_context))->uri, strlen(((request_rec *) SG(server_context))->uri), &new_val_len TSRMLS_CC)) {
        !           294:                php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC);
        !           295:        }
        !           296: }
        !           297: /* }}} */
        !           298: 
        !           299: /* {{{ php_apache_startup
        !           300:  */
        !           301: static int php_apache_startup(sapi_module_struct *sapi_module)
        !           302: {
        !           303:        if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {
        !           304:                return FAILURE;
        !           305:        } else {
        !           306:                return SUCCESS;
        !           307:        }
        !           308: }
        !           309: /* }}} */
        !           310: 
        !           311: /* {{{ php_apache_log_message
        !           312:  */
        !           313: static void php_apache_log_message(char *message)
        !           314: {
        !           315:        TSRMLS_FETCH();
        !           316: 
        !           317:        if (SG(server_context)) {
        !           318: #if MODULE_MAGIC_NUMBER >= 19970831
        !           319:                aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
        !           320: #else
        !           321:                log_error(message, ((request_rec *) SG(server_context))->server);
        !           322: #endif
        !           323:        } else {
        !           324:                fprintf(stderr, "%s\n", message);
        !           325:        }
        !           326: }
        !           327: /* }}} */
        !           328: 
        !           329: /* {{{ php_apache_request_shutdown
        !           330:  */
        !           331: static void php_apache_request_shutdown(void *dummy)
        !           332: {
        !           333:        TSRMLS_FETCH();
        !           334: 
        !           335:        php_output_set_status(0 TSRMLS_CC);
        !           336:        if (AP(in_request)) {
        !           337:                AP(in_request) = 0;
        !           338:                php_request_shutdown(dummy);
        !           339:        }
        !           340:        SG(server_context) = NULL; 
        !           341:        /* 
        !           342:        * The server context (request) is NOT invalid by the time 
        !           343:        * run_cleanups() is called 
        !           344:        */
        !           345: }
        !           346: /* }}} */
        !           347: 
        !           348: /* {{{ php_apache_sapi_activate
        !           349:  */
        !           350: static int php_apache_sapi_activate(TSRMLS_D)
        !           351: {
        !           352:        request_rec *r = (request_rec *) SG(server_context); 
        !           353: 
        !           354:        /*
        !           355:         * For the Apache module version, this bit of code registers a cleanup
        !           356:         * function that gets triggered when our request pool is destroyed.
        !           357:         * We need this because at any point in our code we can be interrupted
        !           358:         * and that may happen before we have had time to free our memory.
        !           359:         * The php_request_shutdown function needs to free all outstanding allocated
        !           360:         * memory.  
        !           361:         */
        !           362:        block_alarms();
        !           363:        register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec);
        !           364:        AP(in_request)=1;
        !           365:        unblock_alarms();
        !           366: 
        !           367:        /* Override the default headers_only value - sometimes "GET" requests should actually only
        !           368:         * send headers.
        !           369:         */
        !           370:        SG(request_info).headers_only = r->header_only;
        !           371:        return SUCCESS;
        !           372: }
        !           373: /* }}} */
        !           374: 
        !           375: /* {{{ php_apache_get_stat
        !           376:  */
        !           377: static struct stat *php_apache_get_stat(TSRMLS_D)
        !           378: {
        !           379:        return &((request_rec *) SG(server_context))->finfo;
        !           380: }
        !           381: /* }}} */
        !           382: 
        !           383: /* {{{ php_apache_getenv
        !           384:  */
        !           385: static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC)
        !           386: {
        !           387:        if (SG(server_context) == NULL) {
        !           388:                return NULL;
        !           389:        }
        !           390: 
        !           391:        return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name);
        !           392: }
        !           393: /* }}} */
        !           394: 
        !           395: /* {{{ sapi_apache_get_fd
        !           396:  */
        !           397: static int sapi_apache_get_fd(int *nfd TSRMLS_DC)
        !           398: {
        !           399: #if PHP_APACHE_HAVE_CLIENT_FD
        !           400:        request_rec *r = SG(server_context);
        !           401:        int fd;
        !           402: 
        !           403:        fd = r->connection->client->fd;
        !           404:        
        !           405:        if (fd >= 0) {
        !           406:                if (nfd) *nfd = fd;
        !           407:                return SUCCESS;
        !           408:        }
        !           409: #endif
        !           410:        return FAILURE;
        !           411: }
        !           412: /* }}} */
        !           413: 
        !           414: /* {{{ sapi_apache_force_http_10
        !           415:  */
        !           416: static int sapi_apache_force_http_10(TSRMLS_D)
        !           417: {
        !           418:        request_rec *r = SG(server_context);
        !           419:        
        !           420:        r->proto_num = HTTP_VERSION(1,0);
        !           421:        
        !           422:        return SUCCESS;
        !           423: }
        !           424: /* }}} */
        !           425: 
        !           426: /* {{{ sapi_apache_get_target_uid
        !           427:  */
        !           428: static int sapi_apache_get_target_uid(uid_t *obj TSRMLS_DC)
        !           429: {
        !           430:        *obj = ap_user_id;
        !           431:        return SUCCESS;
        !           432: }
        !           433: /* }}} */
        !           434: 
        !           435: /* {{{ sapi_apache_get_target_gid
        !           436:  */
        !           437: static int sapi_apache_get_target_gid(gid_t *obj TSRMLS_DC)
        !           438: {
        !           439:        *obj = ap_group_id;
        !           440:        return SUCCESS;
        !           441: }
        !           442: /* }}} */
        !           443: 
        !           444: /* {{{ php_apache_get_request_time
        !           445:  */
        !           446: static time_t php_apache_get_request_time(TSRMLS_D)
        !           447: {
        !           448:        return ((request_rec *)SG(server_context))->request_time;
        !           449: }
        !           450: /* }}} */
        !           451: 
        !           452: /* {{{ sapi_apache_child_terminate
        !           453:  */
        !           454: static void sapi_apache_child_terminate(TSRMLS_D)
        !           455: {
        !           456: #ifndef MULTITHREAD
        !           457:        ap_child_terminate((request_rec *)SG(server_context));
        !           458: #endif
        !           459: }
        !           460: /* }}} */
        !           461: 
        !           462: /* {{{ sapi_module_struct apache_sapi_module
        !           463:  */
        !           464: static sapi_module_struct apache_sapi_module = {
        !           465:        "apache",                                               /* name */
        !           466:        "Apache",                                               /* pretty name */
        !           467:                                                                        
        !           468:        php_apache_startup,                             /* startup */
        !           469:        php_module_shutdown_wrapper,    /* shutdown */
        !           470: 
        !           471:        php_apache_sapi_activate,               /* activate */
        !           472:        NULL,                                                   /* deactivate */
        !           473: 
        !           474:        sapi_apache_ub_write,                   /* unbuffered write */
        !           475:        sapi_apache_flush,                              /* flush */
        !           476:        php_apache_get_stat,                    /* get uid */
        !           477:        php_apache_getenv,                              /* getenv */
        !           478: 
        !           479:        php_error,                                              /* error handler */
        !           480: 
        !           481:        sapi_apache_header_handler,             /* header handler */
        !           482:        sapi_apache_send_headers,               /* send headers handler */
        !           483:        NULL,                                                   /* send header handler */
        !           484: 
        !           485:        sapi_apache_read_post,                  /* read POST data */
        !           486:        sapi_apache_read_cookies,               /* read Cookies */
        !           487: 
        !           488:        sapi_apache_register_server_variables,          /* register server variables */
        !           489:        php_apache_log_message,                 /* Log message */
        !           490:        php_apache_get_request_time,    /* Get request time */
        !           491:        sapi_apache_child_terminate,
        !           492: 
        !           493:        NULL,                                                   /* php.ini path override */
        !           494: 
        !           495: #ifdef PHP_WIN32
        !           496:        NULL,
        !           497:        NULL,
        !           498: #else
        !           499:        block_alarms,                                   /* Block interruptions */
        !           500:        unblock_alarms,                                 /* Unblock interruptions */
        !           501: #endif
        !           502: 
        !           503:        NULL,                                                   /* default post reader */
        !           504:        NULL,                                                   /* treat data */
        !           505:        NULL,                                                   /* exe location */
        !           506:        0,                                                              /* ini ignore */
        !           507:        sapi_apache_get_fd,
        !           508:        sapi_apache_force_http_10,
        !           509:        sapi_apache_get_target_uid,
        !           510:        sapi_apache_get_target_gid
        !           511: };
        !           512: /* }}} */
        !           513: 
        !           514: /* {{{ php_restore_umask
        !           515:  */
        !           516: static void php_restore_umask(void)
        !           517: {
        !           518:        umask(saved_umask);
        !           519: }
        !           520: /* }}} */
        !           521: 
        !           522: /* {{{ init_request_info
        !           523:  */
        !           524: static void init_request_info(TSRMLS_D)
        !           525: {
        !           526:        request_rec *r = ((request_rec *) SG(server_context));
        !           527:        char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH");
        !           528:        const char *authorization=NULL;
        !           529:        char *tmp, *tmp_user;
        !           530: 
        !           531:        SG(request_info).query_string = r->args;
        !           532:        SG(request_info).path_translated = r->filename;
        !           533:        SG(request_info).request_uri = r->uri;
        !           534:        SG(request_info).request_method = (char *)r->method;
        !           535:        SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
        !           536:        SG(request_info).content_length = (content_length ? atol(content_length) : 0);
        !           537:        SG(sapi_headers).http_response_code = r->status;
        !           538:        SG(request_info).proto_num = r->proto_num;
        !           539: 
        !           540:        if (r->headers_in) {
        !           541:                authorization = table_get(r->headers_in, "Authorization");
        !           542:        }
        !           543: 
        !           544:        SG(request_info).auth_user = NULL;
        !           545:        SG(request_info).auth_password = NULL;
        !           546:        SG(request_info).auth_digest = NULL;
        !           547: 
        !           548:        if (authorization && (!PG(safe_mode) || (PG(safe_mode) && !auth_type(r)))) {
        !           549:                char *p = getword(r->pool, &authorization, ' ');
        !           550:                if (!strcasecmp(p, "Basic")) {
        !           551:                        tmp = uudecode(r->pool, authorization);
        !           552:                        tmp_user = getword_nulls_nc(r->pool, &tmp, ':');
        !           553:                        if (tmp_user) {
        !           554:                                r->connection->user = pstrdup(r->connection->pool, tmp_user);
        !           555:                                r->connection->ap_auth_type = "Basic";
        !           556:                                SG(request_info).auth_user = estrdup(tmp_user);
        !           557:                        }
        !           558:                        if (tmp) {
        !           559:                                SG(request_info).auth_password = estrdup(tmp);
        !           560:                        }
        !           561:                } else if (!strcasecmp(p, "Digest")) {
        !           562:                        r->connection->ap_auth_type = "Digest";
        !           563:                        SG(request_info).auth_digest = estrdup(authorization);
        !           564:                }
        !           565:        }
        !           566: }
        !           567: /* }}} */
        !           568: 
        !           569: /* {{{ php_apache_alter_ini_entries
        !           570:  */
        !           571: static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC)
        !           572: {
        !           573:        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, per_dir_entry->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE);
        !           574:        return 0;
        !           575: }
        !           576: /* }}} */
        !           577: 
        !           578: /* {{{ php_apache_get_default_mimetype
        !           579:  */
        !           580: static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC)
        !           581: {
        !           582:        
        !           583:        char *mimetype;
        !           584:        if (SG(default_mimetype) || SG(default_charset)) {
        !           585:                /* Assume output will be of the default MIME type.  Individual
        !           586:                   scripts may change this later. */
        !           587:                char *tmpmimetype;
        !           588:                tmpmimetype = sapi_get_default_content_type(TSRMLS_C);
        !           589:                mimetype = pstrdup(r->pool, tmpmimetype);
        !           590:                efree(tmpmimetype);
        !           591:        } else {
        !           592:                mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET;
        !           593:        }
        !           594:        return mimetype;
        !           595: }
        !           596: /* }}} */
        !           597: 
        !           598: /* {{{ send_php
        !           599:  */
        !           600: static int send_php(request_rec *r, int display_source_mode, char *filename)
        !           601: {
        !           602:        int retval;
        !           603:        HashTable *per_dir_conf;
        !           604:        TSRMLS_FETCH();
        !           605: 
        !           606:        if (AP(in_request)) {
        !           607:                zend_file_handle fh;
        !           608: 
        !           609:                fh.filename = r->filename;
        !           610:                fh.opened_path = NULL;
        !           611:                fh.free_filename = 0;
        !           612:                fh.type = ZEND_HANDLE_FILENAME;
        !           613: 
        !           614:                zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh);
        !           615:                return OK;
        !           616:        }
        !           617: 
        !           618:        SG(server_context) = r;
        !           619: 
        !           620:        zend_first_try {
        !           621: 
        !           622:                /* Make sure file exists */
        !           623:                if (filename == NULL && r->finfo.st_mode == 0) {
        !           624:                        return DECLINED;
        !           625:                }
        !           626: 
        !           627:                per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php5_module);
        !           628:                if (per_dir_conf) {
        !           629:                        zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
        !           630:                }
        !           631:                
        !           632:                /* If PHP parser engine has been turned off with an "engine off"
        !           633:                 * directive, then decline to handle this request
        !           634:                 */
        !           635:                if (!AP(engine)) {
        !           636:                        r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
        !           637:                        zend_try {
        !           638:                                zend_ini_deactivate(TSRMLS_C);
        !           639:                        } zend_end_try();
        !           640:                        return DECLINED;
        !           641:                }
        !           642:                if (filename == NULL) {
        !           643:                        filename = r->filename;
        !           644:                }
        !           645: 
        !           646:                /* Apache 1.2 has a more complex mechanism for reading POST data */
        !           647: #if MODULE_MAGIC_NUMBER > 19961007
        !           648:                if ((retval = setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) {
        !           649:                        zend_try {
        !           650:                                zend_ini_deactivate(TSRMLS_C);
        !           651:                        } zend_end_try();
        !           652:                        return retval;
        !           653:                }
        !           654: #endif
        !           655: 
        !           656:                if (AP(last_modified)) {
        !           657: #if MODULE_MAGIC_NUMBER < 19970912
        !           658:                        if ((retval = set_last_modified(r, r->finfo.st_mtime))) {
        !           659:                                zend_try {
        !           660:                                        zend_ini_deactivate(TSRMLS_C);
        !           661:                                } zend_end_try();
        !           662:                                return retval;
        !           663:                        }
        !           664: #else
        !           665:                        update_mtime (r, r->finfo.st_mtime);
        !           666:                        set_last_modified(r);
        !           667:                        set_etag(r);
        !           668: #endif
        !           669:                }
        !           670:                /* Assume output will be of the default MIME type.  Individual
        !           671:                   scripts may change this later in the request. */
        !           672:                r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
        !           673: 
        !           674:                /* Init timeout */
        !           675:                hard_timeout("send", r);
        !           676: 
        !           677:                php_save_umask();
        !           678:                add_common_vars(r);
        !           679:                add_cgi_vars(r);
        !           680: 
        !           681:                init_request_info(TSRMLS_C);
        !           682:                apache_php_module_main(r, display_source_mode TSRMLS_CC);
        !           683: 
        !           684:                /* Done, restore umask, turn off timeout, close file and return */
        !           685:                php_restore_umask();
        !           686:                kill_timeout(r);
        !           687:        } zend_end_try();
        !           688: 
        !           689:        return OK;
        !           690: }
        !           691: /* }}} */
        !           692: 
        !           693: /* {{{ send_parsed_php
        !           694:  */
        !           695: static int send_parsed_php(request_rec * r)
        !           696: {
        !           697:        int result = send_php(r, 0, NULL);
        !           698:        TSRMLS_FETCH();
        !           699:  
        !           700:        ap_table_setn(r->notes, "mod_php_memory_usage",
        !           701:                ap_psprintf(r->pool, "%lu", zend_memory_peak_usage(1 TSRMLS_CC)));
        !           702: 
        !           703:        return result;
        !           704: }
        !           705: /* }}} */
        !           706: 
        !           707: /* {{{ send_parsed_php_source
        !           708:  */
        !           709: static int send_parsed_php_source(request_rec * r)
        !           710: {
        !           711:        return send_php(r, 1, NULL);
        !           712: }
        !           713: /* }}} */
        !           714: 
        !           715: /* {{{ destroy_per_dir_entry
        !           716:  */
        !           717: static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry)
        !           718: {
        !           719:        free(per_dir_entry->key);
        !           720:        free(per_dir_entry->value);
        !           721: }
        !           722: /* }}} */
        !           723: 
        !           724: /* {{{ copy_per_dir_entry
        !           725:  */
        !           726: static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry)
        !           727: {
        !           728:        php_per_dir_entry tmp = *per_dir_entry;
        !           729: 
        !           730:        per_dir_entry->key = (char *) malloc(tmp.key_length+1);
        !           731:        memcpy(per_dir_entry->key, tmp.key, tmp.key_length);
        !           732:        per_dir_entry->key[per_dir_entry->key_length] = 0;
        !           733: 
        !           734:        per_dir_entry->value = (char *) malloc(tmp.value_length+1);
        !           735:        memcpy(per_dir_entry->value, tmp.value, tmp.value_length);
        !           736:        per_dir_entry->value[per_dir_entry->value_length] = 0;
        !           737: }
        !           738: /* }}} */
        !           739: 
        !           740: /* {{{ should_overwrite_per_dir_entry
        !           741:  */
        !           742: static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_per_dir_entry *new_per_dir_entry, zend_hash_key *hash_key, void *pData)
        !           743: {
        !           744:        php_per_dir_entry *orig_per_dir_entry;
        !           745: 
        !           746:        if (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &orig_per_dir_entry)==FAILURE) {
        !           747:                return 1; /* does not exist in dest, copy from source */
        !           748:        }
        !           749: 
        !           750:        if (orig_per_dir_entry->type==PHP_INI_SYSTEM
        !           751:                && new_per_dir_entry->type!=PHP_INI_SYSTEM) {
        !           752:                return 0;
        !           753:        } else {
        !           754:                return 1;
        !           755:        }
        !           756: }
        !           757: /* }}} */
        !           758: 
        !           759: /* {{{ php_destroy_per_dir_info
        !           760:  */
        !           761: static void php_destroy_per_dir_info(HashTable *per_dir_info)
        !           762: {
        !           763:        zend_hash_destroy(per_dir_info);
        !           764:        free(per_dir_info);
        !           765: }
        !           766: /* }}} */
        !           767: 
        !           768: /* {{{ php_create_dir
        !           769:  */
        !           770: static void *php_create_dir(pool *p, char *dummy)
        !           771: {
        !           772:        HashTable *per_dir_info;
        !           773: 
        !           774:        per_dir_info = (HashTable *) malloc(sizeof(HashTable));
        !           775:        zend_hash_init_ex(per_dir_info, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0);
        !           776:        register_cleanup(p, (void *) per_dir_info, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) zend_hash_destroy);
        !           777: 
        !           778:        return per_dir_info;
        !           779: }
        !           780: /* }}} */
        !           781: 
        !           782: /* {{{ php_merge_dir
        !           783:  */
        !           784: static void *php_merge_dir(pool *p, void *basev, void *addv)
        !           785: {
        !           786:        /* This function *must* not modify addv or basev */
        !           787:        HashTable *new;
        !           788: 
        !           789:        /* need a copy of addv to merge */
        !           790:        new = php_create_dir(p, "php_merge_dir");
        !           791:        zend_hash_copy(new, (HashTable *) basev, (copy_ctor_func_t) copy_per_dir_entry, NULL, sizeof(php_per_dir_entry));
        !           792: 
        !           793:        zend_hash_merge_ex(new, (HashTable *) addv, (copy_ctor_func_t) copy_per_dir_entry, sizeof(php_per_dir_entry), (merge_checker_func_t) should_overwrite_per_dir_entry, NULL);
        !           794:        return new;
        !           795: }
        !           796: /* }}} */
        !           797: 
        !           798: /* {{{ php_apache_value_handler_ex
        !           799:  */
        !           800: static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
        !           801: {
        !           802:        php_per_dir_entry per_dir_entry;
        !           803: 
        !           804:        if (!apache_php_initialized) {
        !           805:                apache_php_initialized = 1;
        !           806: #ifdef ZTS
        !           807:                tsrm_startup(1, 1, 0, NULL);
        !           808: #endif
        !           809:                sapi_startup(&apache_sapi_module);
        !           810:                php_apache_startup(&apache_sapi_module);
        !           811:        }
        !           812:        per_dir_entry.type = mode;
        !           813:        per_dir_entry.htaccess = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0);
        !           814: 
        !           815:        if (strcasecmp(arg2, "none") == 0) {
        !           816:                arg2 = "";
        !           817:        }
        !           818: 
        !           819:        per_dir_entry.key_length = strlen(arg1);
        !           820:        per_dir_entry.value_length = strlen(arg2);
        !           821: 
        !           822:        per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1);
        !           823:        memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);
        !           824:        per_dir_entry.key[per_dir_entry.key_length] = 0;
        !           825: 
        !           826:        per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1);
        !           827:        memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length);
        !           828:        per_dir_entry.value[per_dir_entry.value_length] = 0;
        !           829: 
        !           830:        zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL);
        !           831:        return NULL;
        !           832: }
        !           833: /* }}} */
        !           834: 
        !           835: /* {{{ php_apache_value_handler
        !           836:  */
        !           837: static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
        !           838: {
        !           839:        return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
        !           840: }
        !           841: /* }}} */
        !           842: 
        !           843: /* {{{ php_apache_admin_value_handler
        !           844:  */
        !           845: static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
        !           846: {
        !           847:        return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
        !           848: }
        !           849: /* }}} */
        !           850: 
        !           851: /* {{{ php_apache_flag_handler_ex
        !           852:  */
        !           853: static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
        !           854: {
        !           855:        char bool_val[2];
        !           856: 
        !           857:        if (!strcasecmp(arg2, "On") || (arg2[0] == '1' && arg2[1] == '\0')) {
        !           858:                bool_val[0] = '1';
        !           859:        } else {
        !           860:                bool_val[0] = '0';
        !           861:        }
        !           862:        bool_val[1] = 0;
        !           863:        
        !           864:        return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode);
        !           865: }
        !           866: /* }}} */
        !           867: 
        !           868: /* {{{ php_apache_flag_handler
        !           869:  */
        !           870: static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
        !           871: {
        !           872:        return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR);
        !           873: }
        !           874: /* }}} */
        !           875: 
        !           876: /* {{{ php_apache_admin_flag_handler
        !           877:  */
        !           878: static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2)
        !           879: {
        !           880:        return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM);
        !           881: }
        !           882: /* }}} */
        !           883: 
        !           884: /* {{{ php_apache_phpini_set
        !           885:  */
        !           886: static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg)
        !           887: {
        !           888:        if (apache_sapi_module.php_ini_path_override) {
        !           889:                return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored";
        !           890:        }
        !           891:        apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg);
        !           892:        return NULL;
        !           893: }
        !           894: /* }}} */
        !           895: 
        !           896: /* {{{ int php_xbithack_handler(request_rec * r)
        !           897:  */
        !           898: static int php_xbithack_handler(request_rec * r)
        !           899: {
        !           900:        HashTable *per_dir_conf;
        !           901:        TSRMLS_FETCH();
        !           902: 
        !           903:        if (!(r->finfo.st_mode & S_IXUSR)) {
        !           904:                return DECLINED;
        !           905:        }
        !           906:        per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php5_module);
        !           907:        if (per_dir_conf) {
        !           908:                zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
        !           909:        }
        !           910:        if(!AP(xbithack)) {
        !           911:                zend_try {
        !           912:                        zend_ini_deactivate(TSRMLS_C);
        !           913:                } zend_end_try();
        !           914:                return DECLINED;
        !           915:        }
        !           916:        return send_parsed_php(r);
        !           917: }
        !           918: /* }}} */
        !           919: 
        !           920: /* {{{ apache_php_module_shutdown_wrapper
        !           921:  */
        !           922: static void apache_php_module_shutdown_wrapper(void)
        !           923: {
        !           924:        apache_php_initialized = 0;
        !           925:        apache_sapi_module.shutdown(&apache_sapi_module);
        !           926: 
        !           927: #if MODULE_MAGIC_NUMBER >= 19970728
        !           928:        /* This function is only called on server exit if the apache API
        !           929:         * child_exit handler exists, so shutdown globally 
        !           930:         */
        !           931:        sapi_shutdown();
        !           932: #endif
        !           933: 
        !           934: #ifdef ZTS
        !           935:        tsrm_shutdown();
        !           936: #endif
        !           937: }
        !           938: /* }}} */
        !           939: 
        !           940: #if MODULE_MAGIC_NUMBER >= 19970728
        !           941: /* {{{ php_child_exit_handler
        !           942:  */
        !           943: static void php_child_exit_handler(server_rec *s, pool *p)
        !           944: {
        !           945: /*     apache_php_initialized = 0; */
        !           946:        apache_sapi_module.shutdown(&apache_sapi_module);
        !           947: 
        !           948: #ifdef ZTS
        !           949:        tsrm_shutdown();
        !           950: #endif
        !           951: }
        !           952: /* }}} */
        !           953: #endif
        !           954: 
        !           955: /* {{{ void php_init_handler(server_rec *s, pool *p)
        !           956:  */
        !           957: static void php_init_handler(server_rec *s, pool *p)
        !           958: {
        !           959:        register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);
        !           960:        if (!apache_php_initialized) {
        !           961:                apache_php_initialized = 1;
        !           962: #ifdef ZTS
        !           963:                tsrm_startup(1, 1, 0, NULL);
        !           964: #endif
        !           965:                sapi_startup(&apache_sapi_module);
        !           966:                php_apache_startup(&apache_sapi_module);
        !           967:        }
        !           968: #if MODULE_MAGIC_NUMBER >= 19980527
        !           969:        {
        !           970:                TSRMLS_FETCH();
        !           971:                if (PG(expose_php)) {
        !           972: #if SUHOSIN_PATCH
        !           973:                        ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
        !           974: #else
        !           975:                        ap_add_version_component("PHP/" PHP_VERSION);
        !           976: #endif
        !           977:                }
        !           978:        }
        !           979: #endif
        !           980: }
        !           981: /* }}} */
        !           982: 
        !           983: /* {{{ handler_rec php_handlers[]
        !           984:  */
        !           985: handler_rec php_handlers[] =
        !           986: {
        !           987:        {"application/x-httpd-php", send_parsed_php},
        !           988:        {"application/x-httpd-php-source", send_parsed_php_source},
        !           989:        {"text/html", php_xbithack_handler},
        !           990:        {NULL}
        !           991: };
        !           992: /* }}} */
        !           993: 
        !           994: /* {{{ command_rec php_commands[]
        !           995:  */
        !           996: command_rec php_commands[] =
        !           997: {
        !           998:        {"php_value",           php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"},
        !           999:        {"php_flag",            php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"},
        !          1000:        {"php_admin_value",     php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"},
        !          1001:        {"php_admin_flag",      php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"},
        !          1002:        {"PHPINIDir",           php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"},
        !          1003:        {NULL}
        !          1004: };
        !          1005: /* }}} */
        !          1006: 
        !          1007: /* {{{ odule MODULE_VAR_EXPORT php5_module
        !          1008:  */
        !          1009: module MODULE_VAR_EXPORT php5_module =
        !          1010: {
        !          1011:        STANDARD_MODULE_STUFF,
        !          1012:        php_init_handler,                       /* initializer */
        !          1013:        php_create_dir,                         /* per-directory config creator */
        !          1014:        php_merge_dir,                          /* dir merger */
        !          1015:        NULL,                                           /* per-server config creator */
        !          1016:        NULL,                                           /* merge server config */
        !          1017:        php_commands,                           /* command table */
        !          1018:        php_handlers,                           /* handlers */
        !          1019:        NULL,                                           /* filename translation */
        !          1020:        NULL,                                           /* check_user_id */
        !          1021:        NULL,                                           /* check auth */
        !          1022:        NULL,                                           /* check access */
        !          1023:        NULL,                                           /* type_checker */
        !          1024:        NULL,                                           /* fixups */
        !          1025:        NULL                                            /* logger */
        !          1026: #if MODULE_MAGIC_NUMBER >= 19970103
        !          1027:        , NULL                                          /* header parser */
        !          1028: #endif
        !          1029: #if MODULE_MAGIC_NUMBER >= 19970719
        !          1030:        , NULL                                          /* child_init */
        !          1031: #endif
        !          1032: #if MODULE_MAGIC_NUMBER >= 19970728
        !          1033:        , php_child_exit_handler                /* child_exit */
        !          1034: #endif
        !          1035: #if MODULE_MAGIC_NUMBER >= 19970902
        !          1036:        , NULL                                          /* post read-request */
        !          1037: #endif
        !          1038: };
        !          1039: /* }}} */
        !          1040: 
        !          1041: /*
        !          1042:  * Local variables:
        !          1043:  * tab-width: 4
        !          1044:  * c-basic-offset: 4
        !          1045:  * End:
        !          1046:  * vim600: sw=4 ts=4 fdm=marker
        !          1047:  * vim<600: sw=4 ts=4
        !          1048:  */

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