Annotation of embedaddon/php/main/SAPI.c, revision 1.1.1.4

1.1       misho       1: /* 
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:    | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      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:    | Original design:  Shane Caraveo <shane@caraveo.com>                  |
                     16:    | Authors: Andi Gutmans <andi@zend.com>                                |
                     17:    |          Zeev Suraski <zeev@zend.com>                                |
                     18:    +----------------------------------------------------------------------+
                     19: */
                     20: 
1.1.1.2   misho      21: /* $Id$ */
1.1       misho      22: 
                     23: #include <ctype.h>
                     24: #include <sys/stat.h>
                     25: 
                     26: #include "php.h"
                     27: #include "SAPI.h"
                     28: #include "php_variables.h"
                     29: #include "php_ini.h"
                     30: #include "ext/standard/php_string.h"
                     31: #include "ext/standard/pageinfo.h"
                     32: #if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
                     33: #include "ext/pcre/php_pcre.h"
                     34: #endif
                     35: #ifdef ZTS
                     36: #include "TSRM.h"
                     37: #endif
                     38: #ifdef HAVE_SYS_TIME_H
                     39: #include <sys/time.h>
1.1.1.2   misho      40: #elif defined(PHP_WIN32)
                     41: #include "win32/time.h"
1.1       misho      42: #endif
                     43: 
                     44: #include "rfc1867.h"
                     45: 
                     46: #ifdef PHP_WIN32
                     47: #define STRCASECMP stricmp
                     48: #else
                     49: #define STRCASECMP strcasecmp
                     50: #endif
                     51: 
                     52: #include "php_content_types.h"
                     53: 
                     54: #ifdef ZTS
                     55: SAPI_API int sapi_globals_id;
                     56: #else
                     57: sapi_globals_struct sapi_globals;
                     58: #endif
                     59: 
                     60: static void sapi_globals_ctor(sapi_globals_struct *sapi_globals TSRMLS_DC)
                     61: {
                     62:        memset(sapi_globals, 0, sizeof(*sapi_globals));
                     63:        zend_hash_init_ex(&sapi_globals->known_post_content_types, 5, NULL, NULL, 1, 0);
                     64:        php_setup_sapi_content_types(TSRMLS_C);
                     65: }
                     66: 
                     67: static void sapi_globals_dtor(sapi_globals_struct *sapi_globals TSRMLS_DC)
                     68: {
                     69:        zend_hash_destroy(&sapi_globals->known_post_content_types);
                     70: }
                     71: 
                     72: /* True globals (no need for thread safety) */
                     73: SAPI_API sapi_module_struct sapi_module;
                     74: 
                     75: 
                     76: SAPI_API void sapi_startup(sapi_module_struct *sf)
                     77: {
1.1.1.2   misho      78: #ifdef ZEND_SIGNALS
                     79:        zend_signal_startup();
                     80: #endif
                     81: 
1.1       misho      82:        sf->ini_entries = NULL;
                     83:        sapi_module = *sf;
                     84: 
                     85: #ifdef ZTS
                     86:        ts_allocate_id(&sapi_globals_id, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor);
                     87: # ifdef PHP_WIN32
                     88:        _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
                     89: # endif
                     90: #else
                     91:        sapi_globals_ctor(&sapi_globals);
                     92: #endif
                     93: 
                     94:        virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
                     95: 
                     96: #ifdef PHP_WIN32
                     97:        tsrm_win32_startup();
                     98: #endif
                     99: 
                    100:        reentrancy_startup();
                    101: }
                    102: 
                    103: SAPI_API void sapi_shutdown(void)
                    104: {
                    105: #ifdef ZTS
                    106:        ts_free_id(sapi_globals_id);
                    107: #else
                    108:        sapi_globals_dtor(&sapi_globals);
                    109: #endif
                    110: 
                    111:        reentrancy_shutdown();
                    112: 
                    113:        virtual_cwd_shutdown();
                    114: 
                    115: #ifdef PHP_WIN32
                    116:        tsrm_win32_shutdown();
                    117: #endif
                    118: }
                    119: 
                    120: 
                    121: SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
                    122: {
                    123:        efree(sapi_header->header);
                    124: }
                    125: 
1.1.1.2   misho     126: /* {{{ proto bool header_register_callback(mixed callback)
                    127:    call a header function */
                    128: PHP_FUNCTION(header_register_callback)
                    129: {
                    130:        zval *callback_func;
                    131:        char *callback_name;
                    132:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback_func) == FAILURE) {
                    133:                return;
                    134:        }
                    135:        
                    136:        if (!zend_is_callable(callback_func, 0, &callback_name TSRMLS_CC)) {
                    137:                efree(callback_name);
                    138:                RETURN_FALSE;
                    139:        }
1.1.1.4 ! misho     140: 
1.1.1.2   misho     141:        efree(callback_name);
                    142: 
                    143:        if (SG(callback_func)) {
                    144:                zval_ptr_dtor(&SG(callback_func));
                    145:                SG(fci_cache) = empty_fcall_info_cache;
                    146:        }
                    147: 
                    148:        SG(callback_func) = callback_func;
1.1.1.4 ! misho     149: 
        !           150:        Z_ADDREF_P(SG(callback_func));
        !           151: 
1.1.1.2   misho     152:        RETURN_TRUE;
                    153: }
                    154: /* }}} */
                    155: 
                    156: static void sapi_run_header_callback(TSRMLS_D)
                    157: {
                    158:        int   error;
                    159:        zend_fcall_info fci;
1.1.1.4 ! misho     160:        char *callback_name = NULL;
        !           161:        char *callback_error = NULL;
1.1.1.2   misho     162:        zval *retval_ptr = NULL;
1.1.1.4 ! misho     163:        
        !           164:        if (zend_fcall_info_init(SG(callback_func), 0, &fci, &SG(fci_cache), &callback_name, &callback_error TSRMLS_CC) == SUCCESS) {
        !           165:                fci.retval_ptr_ptr = &retval_ptr;
        !           166:                
        !           167:                error = zend_call_function(&fci, &SG(fci_cache) TSRMLS_CC);
        !           168:                if (error == FAILURE) {
        !           169:                        goto callback_failed;
        !           170:                } else if (retval_ptr) {
        !           171:                        zval_ptr_dtor(&retval_ptr);
        !           172:                }
        !           173:        } else {
        !           174: callback_failed:
1.1.1.2   misho     175:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the sapi_header_callback");
                    176:        }
1.1.1.4 ! misho     177:        
        !           178:        if (callback_name) {
        !           179:                efree(callback_name);
        !           180:        }
        !           181:        if (callback_error) {
        !           182:                efree(callback_error);
        !           183:        }       
1.1.1.2   misho     184: }
1.1       misho     185: 
                    186: SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
                    187: {
                    188:        if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
                    189:                SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
                    190:                if (SG(request_info).post_data) {
                    191:                        efree(SG(request_info).post_data);
                    192:                        SG(request_info).post_data = NULL;
                    193:                }
                    194:                efree(SG(request_info).content_type_dup);
                    195:                SG(request_info).content_type_dup = NULL;
                    196:        }
                    197: }
                    198: 
                    199: static void sapi_read_post_data(TSRMLS_D)
                    200: {
                    201:        sapi_post_entry *post_entry;
                    202:        uint content_type_length = strlen(SG(request_info).content_type);
                    203:        char *content_type = estrndup(SG(request_info).content_type, content_type_length);
                    204:        char *p;
                    205:        char oldchar=0;
                    206:        void (*post_reader_func)(TSRMLS_D) = NULL;
                    207: 
                    208: 
                    209:        /* dedicated implementation for increased performance:
                    210:         * - Make the content type lowercase
                    211:         * - Trim descriptive data, stay with the content-type only
                    212:         */
                    213:        for (p=content_type; p<content_type+content_type_length; p++) {
                    214:                switch (*p) {
                    215:                        case ';':
                    216:                        case ',':
                    217:                        case ' ':
                    218:                                content_type_length = p-content_type;
                    219:                                oldchar = *p;
                    220:                                *p = 0;
                    221:                                break;
                    222:                        default:
                    223:                                *p = tolower(*p);
                    224:                                break;
                    225:                }
                    226:        }
                    227: 
                    228:        /* now try to find an appropriate POST content handler */
                    229:        if (zend_hash_find(&SG(known_post_content_types), content_type,
                    230:                        content_type_length+1, (void **) &post_entry) == SUCCESS) {
                    231:                /* found one, register it for use */
                    232:                SG(request_info).post_entry = post_entry;
                    233:                post_reader_func = post_entry->post_reader;
                    234:        } else {
                    235:                /* fallback */
                    236:                SG(request_info).post_entry = NULL;
                    237:                if (!sapi_module.default_post_reader) {
                    238:                        /* no default reader ? */
                    239:                        SG(request_info).content_type_dup = NULL;
                    240:                        sapi_module.sapi_error(E_WARNING, "Unsupported content type:  '%s'", content_type);
                    241:                        return;
                    242:                }
                    243:        }
                    244:        if (oldchar) {
                    245:                *(p-1) = oldchar;
                    246:        }
                    247: 
                    248:        SG(request_info).content_type_dup = content_type;
                    249: 
                    250:        if(post_reader_func) {
                    251:                post_reader_func(TSRMLS_C);
                    252:        }
                    253: 
                    254:        if(sapi_module.default_post_reader) {
                    255:                sapi_module.default_post_reader(TSRMLS_C);
                    256:        }
                    257: }
                    258: 
                    259: 
                    260: SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
                    261: {
                    262:        int read_bytes;
                    263:        int allocated_bytes=SAPI_POST_BLOCK_SIZE+1;
                    264: 
                    265:        if ((SG(post_max_size) > 0) && (SG(request_info).content_length > SG(post_max_size))) {
                    266:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes",
                    267:                                        SG(request_info).content_length, SG(post_max_size));
                    268:                return;
                    269:        }
                    270:        SG(request_info).post_data = emalloc(allocated_bytes);
                    271: 
                    272:        for (;;) {
                    273:                read_bytes = sapi_module.read_post(SG(request_info).post_data+SG(read_post_bytes), SAPI_POST_BLOCK_SIZE TSRMLS_CC);
                    274:                if (read_bytes<=0) {
                    275:                        break;
                    276:                }
                    277:                SG(read_post_bytes) += read_bytes;
                    278:                if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
                    279:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
                    280:                        break;
                    281:                }
                    282:                if (read_bytes < SAPI_POST_BLOCK_SIZE) {
                    283:                        break;
                    284:                }
                    285:                if (SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE >= allocated_bytes) {
                    286:                        allocated_bytes = SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE+1;
                    287:                        SG(request_info).post_data = erealloc(SG(request_info).post_data, allocated_bytes);
                    288:                }
                    289:        }
                    290:        SG(request_info).post_data[SG(read_post_bytes)] = 0;  /* terminating NULL */
                    291:        SG(request_info).post_data_length = SG(read_post_bytes);
                    292: }
                    293: 
                    294: 
1.1.1.2   misho     295: static inline char *get_default_content_type(uint prefix_len, uint *len TSRMLS_DC)
1.1       misho     296: {
                    297:        char *mimetype, *charset, *content_type;
1.1.1.2   misho     298:        uint mimetype_len, charset_len;
1.1       misho     299: 
1.1.1.2   misho     300:        if (SG(default_mimetype)) {
                    301:                mimetype = SG(default_mimetype);
                    302:                mimetype_len = strlen(SG(default_mimetype));
                    303:        } else {
                    304:                mimetype = SAPI_DEFAULT_MIMETYPE;
                    305:                mimetype_len = sizeof(SAPI_DEFAULT_MIMETYPE) - 1;
                    306:        }
                    307:        if (SG(default_charset)) {
                    308:                charset = SG(default_charset);
                    309:                charset_len = strlen(SG(default_charset));
                    310:        } else {
                    311:                charset = SAPI_DEFAULT_CHARSET;
                    312:                charset_len = sizeof(SAPI_DEFAULT_CHARSET) - 1;
                    313:        }
                    314: 
                    315:        if (*charset && strncasecmp(mimetype, "text/", 5) == 0) {
                    316:                char *p;
1.1       misho     317: 
1.1.1.2   misho     318:                *len = prefix_len + mimetype_len + sizeof("; charset=") - 1 + charset_len;
                    319:                content_type = (char*)emalloc(*len + 1);
                    320:                p = content_type + prefix_len;
                    321:                memcpy(p, mimetype, mimetype_len);
                    322:                p += mimetype_len;
                    323:                memcpy(p, "; charset=", sizeof("; charset=") - 1);
                    324:                p += sizeof("; charset=") - 1;
                    325:                memcpy(p, charset, charset_len + 1);
1.1       misho     326:        } else {
1.1.1.2   misho     327:                *len = prefix_len + mimetype_len;
                    328:                content_type = (char*)emalloc(*len + 1);
                    329:                memcpy(content_type + prefix_len, mimetype, mimetype_len + 1);
1.1       misho     330:        }
                    331:        return content_type;
                    332: }
                    333: 
                    334: 
1.1.1.2   misho     335: SAPI_API char *sapi_get_default_content_type(TSRMLS_D)
                    336: {
                    337:        uint len;
                    338: 
                    339:        return get_default_content_type(0, &len TSRMLS_CC);
                    340: }
                    341: 
                    342: 
1.1       misho     343: SAPI_API void sapi_get_default_content_type_header(sapi_header_struct *default_header TSRMLS_DC)
                    344: {
1.1.1.2   misho     345:     uint len;
1.1       misho     346: 
1.1.1.2   misho     347:        default_header->header = get_default_content_type(sizeof("Content-type: ")-1, &len TSRMLS_CC);
                    348:        default_header->header_len = len;
                    349:        memcpy(default_header->header, "Content-type: ", sizeof("Content-type: ") - 1);
1.1       misho     350: }
                    351: 
                    352: /*
                    353:  * Add charset on content-type header if the MIME type starts with
                    354:  * "text/", the default_charset directive is not empty and
                    355:  * there is not already a charset option in there.
                    356:  *
                    357:  * If "mimetype" is non-NULL, it should point to a pointer allocated
                    358:  * with emalloc().  If a charset is added, the string will be
                    359:  * re-allocated and the new length is returned.  If mimetype is
                    360:  * unchanged, 0 is returned.
                    361:  *
                    362:  */
                    363: SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len TSRMLS_DC)
                    364: {
                    365:        char *charset, *newtype;
                    366:        size_t newlen;
                    367:        charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
                    368: 
                    369:        if (*mimetype != NULL) {
                    370:                if (*charset && strncmp(*mimetype, "text/", 5) == 0 && strstr(*mimetype, "charset=") == NULL) {
                    371:                        newlen = len + (sizeof(";charset=")-1) + strlen(charset);
                    372:                        newtype = emalloc(newlen + 1);
                    373:                        PHP_STRLCPY(newtype, *mimetype, newlen + 1, len);
                    374:                        strlcat(newtype, ";charset=", newlen + 1);
                    375:                        strlcat(newtype, charset, newlen + 1);
                    376:                        efree(*mimetype);
                    377:                        *mimetype = newtype;
                    378:                        return newlen;
                    379:                }
                    380:        }
                    381:        return 0;
                    382: }
                    383: 
                    384: SAPI_API void sapi_activate_headers_only(TSRMLS_D)
                    385: {
                    386:        if (SG(request_info).headers_read == 1)
                    387:                return;
                    388:        SG(request_info).headers_read = 1;
                    389:        zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), 
                    390:                        (void (*)(void *)) sapi_free_header, 0);
                    391:        SG(sapi_headers).send_default_content_type = 1;
                    392: 
                    393:        /* SG(sapi_headers).http_response_code = 200; */ 
                    394:        SG(sapi_headers).http_status_line = NULL;
                    395:        SG(sapi_headers).mimetype = NULL;
                    396:        SG(read_post_bytes) = 0;
                    397:        SG(request_info).post_data = NULL;
                    398:        SG(request_info).raw_post_data = NULL;
                    399:        SG(request_info).current_user = NULL;
                    400:        SG(request_info).current_user_length = 0;
                    401:        SG(request_info).no_headers = 0;
                    402:        SG(request_info).post_entry = NULL;
                    403:        SG(global_request_time) = 0;
                    404: 
                    405:        /*
                    406:         * It's possible to override this general case in the activate() callback, 
                    407:         * if necessary.
                    408:         */
                    409:        if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
                    410:                SG(request_info).headers_only = 1;
                    411:        } else {
                    412:                SG(request_info).headers_only = 0;
                    413:        }
                    414:        if (SG(server_context)) {
                    415:                SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
                    416:                if (sapi_module.activate) {
                    417:                        sapi_module.activate(TSRMLS_C);
                    418:                }
                    419:        }
                    420:        if (sapi_module.input_filter_init ) {
                    421:                sapi_module.input_filter_init(TSRMLS_C);
                    422:        }
                    423: }
                    424: 
                    425: /*
                    426:  * Called from php_request_startup() for every request.
                    427:  */
                    428: 
                    429: SAPI_API void sapi_activate(TSRMLS_D)
                    430: {
                    431:        zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
                    432:        SG(sapi_headers).send_default_content_type = 1;
                    433: 
                    434:        /*
                    435:        SG(sapi_headers).http_response_code = 200;
                    436:        */
                    437:        SG(sapi_headers).http_status_line = NULL;
                    438:        SG(sapi_headers).mimetype = NULL;
                    439:        SG(headers_sent) = 0;
1.1.1.2   misho     440:        SG(callback_run) = 0;
                    441:        SG(callback_func) = NULL;
1.1       misho     442:        SG(read_post_bytes) = 0;
                    443:        SG(request_info).post_data = NULL;
                    444:        SG(request_info).raw_post_data = NULL;
                    445:        SG(request_info).current_user = NULL;
                    446:        SG(request_info).current_user_length = 0;
                    447:        SG(request_info).no_headers = 0;
                    448:        SG(request_info).post_entry = NULL;
                    449:        SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
                    450:        SG(global_request_time) = 0;
                    451: 
1.1.1.2   misho     452:        /* It's possible to override this general case in the activate() callback, if necessary. */
1.1       misho     453:        if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
                    454:                SG(request_info).headers_only = 1;
                    455:        } else {
                    456:                SG(request_info).headers_only = 0;
                    457:        }
                    458:        SG(rfc1867_uploaded_files) = NULL;
                    459: 
1.1.1.2   misho     460:        /* Handle request method */
1.1       misho     461:        if (SG(server_context)) {
1.1.1.2   misho     462:                if (PG(enable_post_data_reading) && SG(request_info).request_method) {
                    463:                        if (SG(request_info).content_type && !strcmp(SG(request_info).request_method, "POST")) {
                    464:                                /* HTTP POST may contain form data to be processed into variables
                    465:                                 * depending on given content type */
1.1       misho     466:                                sapi_read_post_data(TSRMLS_C);
                    467:                        } else {
1.1.1.2   misho     468:                                /* Any other method with content payload will fill $HTTP_RAW_POST_DATA 
                    469:                                 * if it is enabled by always_populate_raw_post_data. 
                    470:                                 * It's up to the webserver to decide whether to allow a method or not. */
1.1       misho     471:                                SG(request_info).content_type_dup = NULL;
1.1.1.2   misho     472:                                if (sapi_module.default_post_reader) {
1.1       misho     473:                                        sapi_module.default_post_reader(TSRMLS_C);
                    474:                                }
                    475:                        }
                    476:                } else {
                    477:                        SG(request_info).content_type_dup = NULL;
                    478:                }
                    479: 
                    480:                /* Cookies */
                    481:                SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
1.1.1.2   misho     482: 
1.1       misho     483:                if (sapi_module.activate) {
                    484:                        sapi_module.activate(TSRMLS_C);
                    485:                }
                    486:        }
1.1.1.2   misho     487:        if (sapi_module.input_filter_init) {
1.1       misho     488:                sapi_module.input_filter_init(TSRMLS_C);
                    489:        }
                    490: }
                    491: 
                    492: 
                    493: static void sapi_send_headers_free(TSRMLS_D)
                    494: {
                    495:        if (SG(sapi_headers).http_status_line) {
                    496:                efree(SG(sapi_headers).http_status_line);
                    497:                SG(sapi_headers).http_status_line = NULL;
                    498:        }
                    499: }
                    500:        
                    501: SAPI_API void sapi_deactivate(TSRMLS_D)
                    502: {
                    503:        zend_llist_destroy(&SG(sapi_headers).headers);
                    504:        if (SG(request_info).post_data) {
                    505:                efree(SG(request_info).post_data);
                    506:        }  else         if (SG(server_context)) {
                    507:                if(sapi_module.read_post) { 
                    508:                        /* make sure we've consumed all request input data */
                    509:                        char dummy[SAPI_POST_BLOCK_SIZE];
                    510:                        int read_bytes;
                    511: 
                    512:                        while((read_bytes = sapi_module.read_post(dummy, sizeof(dummy)-1 TSRMLS_CC)) > 0) {
                    513:                                SG(read_post_bytes) += read_bytes;
                    514:                        }
                    515:                }
                    516:        }
                    517:        if (SG(request_info).raw_post_data) {
                    518:                efree(SG(request_info).raw_post_data);
                    519:        } 
                    520:        if (SG(request_info).auth_user) {
                    521:                efree(SG(request_info).auth_user);
                    522:        }
                    523:        if (SG(request_info).auth_password) {
                    524:                efree(SG(request_info).auth_password);
                    525:        }
                    526:        if (SG(request_info).auth_digest) {
                    527:                efree(SG(request_info).auth_digest);
                    528:        }
                    529:        if (SG(request_info).content_type_dup) {
                    530:                efree(SG(request_info).content_type_dup);
                    531:        }
                    532:        if (SG(request_info).current_user) {
                    533:                efree(SG(request_info).current_user);
                    534:        }
                    535:        if (sapi_module.deactivate) {
                    536:                sapi_module.deactivate(TSRMLS_C);
                    537:        }
                    538:        if (SG(rfc1867_uploaded_files)) {
                    539:                destroy_uploaded_files_hash(TSRMLS_C);
                    540:        }
                    541:        if (SG(sapi_headers).mimetype) {
                    542:                efree(SG(sapi_headers).mimetype);
                    543:                SG(sapi_headers).mimetype = NULL;
                    544:        }
                    545:        sapi_send_headers_free(TSRMLS_C);
                    546:        SG(sapi_started) = 0;
                    547:        SG(headers_sent) = 0;
1.1.1.2   misho     548:        SG(callback_run) = 0;
                    549:        if (SG(callback_func)) {
                    550:                zval_ptr_dtor(&SG(callback_func));
                    551:        }
1.1       misho     552:        SG(request_info).headers_read = 0;
                    553:        SG(global_request_time) = 0;
                    554: }
                    555: 
                    556: 
                    557: SAPI_API void sapi_initialize_empty_request(TSRMLS_D)
                    558: {
                    559:        SG(server_context) = NULL;
                    560:        SG(request_info).request_method = NULL;
                    561:        SG(request_info).auth_digest = SG(request_info).auth_user = SG(request_info).auth_password = NULL;
                    562:        SG(request_info).content_type_dup = NULL;
                    563: }
                    564: 
                    565: 
                    566: static int sapi_extract_response_code(const char *header_line)
                    567: {
                    568:        int code = 200;
                    569:        const char *ptr;
                    570: 
                    571:        for (ptr = header_line; *ptr; ptr++) {
                    572:                if (*ptr == ' ' && *(ptr + 1) != ' ') {
                    573:                        code = atoi(ptr + 1);
                    574:                        break;
                    575:                }
                    576:        }
                    577:        
                    578:        return code;
                    579: }
                    580: 
                    581: 
                    582: static void sapi_update_response_code(int ncode TSRMLS_DC)
                    583: {
                    584:        /* if the status code did not change, we do not want
                    585:           to change the status line, and no need to change the code */
                    586:        if (SG(sapi_headers).http_response_code == ncode) {
                    587:                return;
                    588:        }
                    589: 
                    590:        if (SG(sapi_headers).http_status_line) {
                    591:                efree(SG(sapi_headers).http_status_line);
                    592:                SG(sapi_headers).http_status_line = NULL;
                    593:        }
                    594:        SG(sapi_headers).http_response_code = ncode;
                    595: }
                    596: 
1.1.1.3   misho     597: /* 
                    598:  * since zend_llist_del_element only remove one matched item once,
                    599:  * we should remove them by ourself
                    600:  */
                    601: static void sapi_remove_header(zend_llist *l, char *name, uint len) {
                    602:        sapi_header_struct *header;
                    603:        zend_llist_element *next;
                    604:        zend_llist_element *current=l->head;
                    605: 
                    606:        while (current) {
                    607:                header = (sapi_header_struct *)(current->data);
                    608:                next = current->next;
                    609:                if (header->header_len > len && header->header[len] == ':'
                    610:                                && !strncasecmp(header->header, name, len)) {
                    611:                        if (current->prev) {
                    612:                                current->prev->next = next;
                    613:                        } else {
                    614:                                l->head = next;
                    615:                        }
                    616:                        if (next) {
                    617:                                next->prev = current->prev;
                    618:                        } else {
                    619:                                l->tail = current->prev;
                    620:                        }
                    621:                        sapi_free_header(header);
                    622:                        efree(current);
                    623:                        --l->count;
                    624:                }
                    625:                current = next;
                    626:        }
1.1       misho     627: }
                    628: 
                    629: SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool duplicate, zend_bool replace TSRMLS_DC)
                    630: {
                    631:        sapi_header_line ctr = {0};
                    632:        int r;
                    633:        
                    634:        ctr.line = header_line;
                    635:        ctr.line_len = header_line_len;
                    636: 
                    637:        r = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD,
                    638:                        &ctr TSRMLS_CC);
                    639: 
                    640:        if (!duplicate)
                    641:                efree(header_line);
                    642: 
                    643:        return r;
                    644: }
                    645: 
1.1.1.2   misho     646: static void sapi_header_add_op(sapi_header_op_enum op, sapi_header_struct *sapi_header TSRMLS_DC)
                    647: {
                    648:        if (!sapi_module.header_handler ||
                    649:                (SAPI_HEADER_ADD & sapi_module.header_handler(sapi_header, op, &SG(sapi_headers) TSRMLS_CC))) {
                    650:                if (op == SAPI_HEADER_REPLACE) {
                    651:                        char *colon_offset = strchr(sapi_header->header, ':');
                    652: 
                    653:                        if (colon_offset) {
                    654:                                char sav = *colon_offset;
                    655: 
                    656:                                *colon_offset = 0;
1.1.1.3   misho     657:                        sapi_remove_header(&SG(sapi_headers).headers, sapi_header->header, strlen(sapi_header->header));
1.1.1.2   misho     658:                                *colon_offset = sav;
                    659:                        }
                    660:                }
                    661:                zend_llist_add_element(&SG(sapi_headers).headers, (void *) sapi_header);
                    662:        } else {
                    663:                sapi_free_header(sapi_header);
                    664:        }
                    665: }
                    666: 
1.1       misho     667: SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
                    668: {
                    669:        sapi_header_struct sapi_header;
                    670:        char *colon_offset;
                    671:        char *header_line;
                    672:        uint header_line_len;
                    673:        int http_response_code;
1.1.1.2   misho     674: 
1.1       misho     675:        if (SG(headers_sent) && !SG(request_info).no_headers) {
1.1.1.2   misho     676:                const char *output_start_filename = php_output_get_start_filename(TSRMLS_C);
                    677:                int output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
1.1       misho     678: 
                    679:                if (output_start_filename) {
                    680:                        sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)",
                    681:                                output_start_filename, output_start_lineno);
                    682:                } else {
                    683:                        sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent");
                    684:                }
                    685:                return FAILURE;
                    686:        }
                    687: 
                    688:        switch (op) {
                    689:                case SAPI_HEADER_SET_STATUS:
                    690:                        sapi_update_response_code((int)(zend_intptr_t) arg TSRMLS_CC);
                    691:                        return SUCCESS;
                    692: 
                    693:                case SAPI_HEADER_ADD:
                    694:                case SAPI_HEADER_REPLACE:
                    695:                case SAPI_HEADER_DELETE: {
                    696:                                sapi_header_line *p = arg;
                    697: 
                    698:                                if (!p->line || !p->line_len) {
                    699:                                        return FAILURE;
                    700:                                }
                    701:                                header_line = p->line;
                    702:                                header_line_len = p->line_len;
                    703:                                http_response_code = p->response_code;
                    704:                                break;
                    705:                        }
                    706: 
                    707:                case SAPI_HEADER_DELETE_ALL:
                    708:                        if (sapi_module.header_handler) {
                    709:                                sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
                    710:                        }
                    711:                        zend_llist_clean(&SG(sapi_headers).headers);
                    712:                        return SUCCESS;
                    713: 
                    714:                default:
                    715:                        return FAILURE;
                    716:        }
                    717: 
                    718:        header_line = estrndup(header_line, header_line_len);
                    719: 
1.1.1.4 ! misho     720:        /* cut off trailing spaces, linefeeds and carriage-returns */
1.1.1.2   misho     721:        if (header_line_len && isspace(header_line[header_line_len-1])) {
                    722:                do {
                    723:                        header_line_len--;
                    724:                } while(header_line_len && isspace(header_line[header_line_len-1]));
                    725:                header_line[header_line_len]='\0';
                    726:        }
1.1       misho     727:        
                    728:        if (op == SAPI_HEADER_DELETE) {
                    729:                if (strchr(header_line, ':')) {
                    730:                        efree(header_line);
                    731:                        sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon.");
                    732:                        return FAILURE;
                    733:                }
1.1.1.2   misho     734:                if (sapi_module.header_handler) {
                    735:                        sapi_header.header = header_line;
                    736:                        sapi_header.header_len = header_line_len;
                    737:                        sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
                    738:                }
1.1.1.3   misho     739:                sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len);
1.1.1.2   misho     740:                efree(header_line);
                    741:                return SUCCESS;
1.1       misho     742:        } else {
1.1.1.2   misho     743:                /* new line/NUL character safety check */
                    744:                int i;
                    745:                for (i = 0; i < header_line_len; i++) {
                    746:                        /* RFC 2616 allows new lines if followed by SP or HT */
                    747:                        int illegal_break =
                    748:                                        (header_line[i+1] != ' ' && header_line[i+1] != '\t')
                    749:                                        && (
                    750:                                                header_line[i] == '\n'
                    751:                                                || (header_line[i] == '\r' && header_line[i+1] != '\n'));
                    752:                        if (illegal_break) {
                    753:                                efree(header_line);
                    754:                                sapi_module.sapi_error(E_WARNING, "Header may not contain "
                    755:                                                "more than a single header, new line detected");
                    756:                                return FAILURE;
                    757:                        }
                    758:                        if (header_line[i] == '\0') {
                    759:                                efree(header_line);
                    760:                                sapi_module.sapi_error(E_WARNING, "Header may not contain NUL bytes");
                    761:                                return FAILURE;
1.1       misho     762:                        }
                    763:                }
                    764:        }
                    765: 
                    766:        sapi_header.header = header_line;
                    767:        sapi_header.header_len = header_line_len;
                    768: 
                    769:        /* Check the header for a few cases that we have special support for in SAPI */
                    770:        if (header_line_len>=5 
                    771:                && !strncasecmp(header_line, "HTTP/", 5)) {
                    772:                /* filter out the response code */
                    773:                sapi_update_response_code(sapi_extract_response_code(header_line) TSRMLS_CC);
                    774:                /* sapi_update_response_code doesn't free the status line if the code didn't change */
                    775:                if (SG(sapi_headers).http_status_line) {
                    776:                        efree(SG(sapi_headers).http_status_line);
                    777:                }
                    778:                SG(sapi_headers).http_status_line = header_line;
                    779:                return SUCCESS;
                    780:        } else {
                    781:                colon_offset = strchr(header_line, ':');
                    782:                if (colon_offset) {
                    783:                        *colon_offset = 0;
                    784:                        if (!STRCASECMP(header_line, "Content-Type")) {
                    785:                                char *ptr = colon_offset+1, *mimetype = NULL, *newheader;
                    786:                                size_t len = header_line_len - (ptr - header_line), newlen;
                    787:                                while (*ptr == ' ') {
                    788:                                        ptr++;
                    789:                                        len--;
                    790:                                }
                    791: 
                    792:                                /* Disable possible output compression for images */
                    793:                                if (!strncmp(ptr, "image/", sizeof("image/")-1)) {
                    794:                                        zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
                    795:                                }
                    796: 
                    797:                                mimetype = estrdup(ptr);
                    798:                                newlen = sapi_apply_default_charset(&mimetype, len TSRMLS_CC);
                    799:                                if (!SG(sapi_headers).mimetype){
                    800:                                        SG(sapi_headers).mimetype = estrdup(mimetype);
                    801:                                }
                    802: 
                    803:                                if (newlen != 0) {
                    804:                                        newlen += sizeof("Content-type: ");
                    805:                                        newheader = emalloc(newlen);
                    806:                                        PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1);
                    807:                                        strlcat(newheader, mimetype, newlen);
                    808:                                        sapi_header.header = newheader;
                    809:                                        sapi_header.header_len = newlen - 1;
                    810:                                        efree(header_line);
                    811:                                }
                    812:                                efree(mimetype);
                    813:                                SG(sapi_headers).send_default_content_type = 0;
1.1.1.2   misho     814:                        } else if (!STRCASECMP(header_line, "Content-Length")) {
                    815:                                /* Script is setting Content-length. The script cannot reasonably
                    816:                                 * know the size of the message body after compression, so it's best
                    817:                                 * do disable compression altogether. This contributes to making scripts
                    818:                                 * portable between setups that have and don't have zlib compression
                    819:                                 * enabled globally. See req #44164 */
                    820:                                zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"),
                    821:                                        "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
1.1       misho     822:                        } else if (!STRCASECMP(header_line, "Location")) {
                    823:                                if ((SG(sapi_headers).http_response_code < 300 ||
                    824:                                        SG(sapi_headers).http_response_code > 307) &&
                    825:                                        SG(sapi_headers).http_response_code != 201) {
                    826:                                        /* Return a Found Redirect if one is not already specified */
                    827:                                        if (http_response_code) { /* user specified redirect code */
                    828:                                                sapi_update_response_code(http_response_code TSRMLS_CC);
                    829:                                        } else if (SG(request_info).proto_num > 1000 && 
                    830:                                           SG(request_info).request_method && 
                    831:                                           strcmp(SG(request_info).request_method, "HEAD") &&
                    832:                                           strcmp(SG(request_info).request_method, "GET")) {
                    833:                                                sapi_update_response_code(303 TSRMLS_CC);
                    834:                                        } else {
                    835:                                                sapi_update_response_code(302 TSRMLS_CC);
                    836:                                        }
                    837:                                }
                    838:                        } else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
                    839:                                sapi_update_response_code(401 TSRMLS_CC); /* authentication-required */
                    840:                        }
                    841:                        if (sapi_header.header==header_line) {
                    842:                                *colon_offset = ':';
                    843:                        }
                    844:                }
                    845:        }
                    846:        if (http_response_code) {
                    847:                sapi_update_response_code(http_response_code TSRMLS_CC);
                    848:        }
1.1.1.2   misho     849:        sapi_header_add_op(op, &sapi_header TSRMLS_CC);
1.1       misho     850:        return SUCCESS;
                    851: }
                    852: 
                    853: 
                    854: SAPI_API int sapi_send_headers(TSRMLS_D)
                    855: {
                    856:        int retval;
                    857:        int ret = FAILURE;
                    858: 
1.1.1.2   misho     859:        if (SG(headers_sent) || SG(request_info).no_headers || SG(callback_run)) {
1.1       misho     860:                return SUCCESS;
                    861:        }
                    862: 
                    863:        /* Success-oriented.  We set headers_sent to 1 here to avoid an infinite loop
                    864:         * in case of an error situation.
                    865:         */
                    866:        if (SG(sapi_headers).send_default_content_type && sapi_module.send_headers) {
                    867:                sapi_header_struct default_header;
1.1.1.2   misho     868:            uint len;
                    869: 
                    870:                SG(sapi_headers).mimetype = get_default_content_type(0, &len TSRMLS_CC);
                    871:                default_header.header_len = sizeof("Content-type: ") - 1 + len;
                    872:                default_header.header = emalloc(default_header.header_len + 1);
                    873:                memcpy(default_header.header, "Content-type: ", sizeof("Content-type: ") - 1);
                    874:                memcpy(default_header.header + sizeof("Content-type: ") - 1, SG(sapi_headers).mimetype, len + 1);
                    875:                sapi_header_add_op(SAPI_HEADER_ADD, &default_header TSRMLS_CC);
                    876:                SG(sapi_headers).send_default_content_type = 0;
                    877:        }
                    878: 
                    879:        if (SG(callback_func) && !SG(callback_run)) {
                    880:                SG(callback_run) = 1;
                    881:                sapi_run_header_callback(TSRMLS_C);
1.1       misho     882:        }
                    883: 
                    884:        SG(headers_sent) = 1;
                    885: 
                    886:        if (sapi_module.send_headers) {
                    887:                retval = sapi_module.send_headers(&SG(sapi_headers) TSRMLS_CC);
                    888:        } else {
                    889:                retval = SAPI_HEADER_DO_SEND;
                    890:        }
                    891: 
                    892:        switch (retval) {
                    893:                case SAPI_HEADER_SENT_SUCCESSFULLY:
                    894:                        ret = SUCCESS;
                    895:                        break;
                    896:                case SAPI_HEADER_DO_SEND: {
                    897:                                sapi_header_struct http_status_line;
                    898:                                char buf[255];
                    899: 
                    900:                                if (SG(sapi_headers).http_status_line) {
                    901:                                        http_status_line.header = SG(sapi_headers).http_status_line;
                    902:                                        http_status_line.header_len = strlen(SG(sapi_headers).http_status_line);
                    903:                                } else {
                    904:                                        http_status_line.header = buf;
                    905:                                        http_status_line.header_len = slprintf(buf, sizeof(buf), "HTTP/1.0 %d X", SG(sapi_headers).http_response_code);
                    906:                                }
                    907:                                sapi_module.send_header(&http_status_line, SG(server_context) TSRMLS_CC);
                    908:                        }
                    909:                        zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context) TSRMLS_CC);
                    910:                        if(SG(sapi_headers).send_default_content_type) {
                    911:                                sapi_header_struct default_header;
                    912: 
                    913:                                sapi_get_default_content_type_header(&default_header TSRMLS_CC);
                    914:                                sapi_module.send_header(&default_header, SG(server_context) TSRMLS_CC);
                    915:                                sapi_free_header(&default_header);
                    916:                        }
                    917:                        sapi_module.send_header(NULL, SG(server_context) TSRMLS_CC);
                    918:                        ret = SUCCESS;
                    919:                        break;
                    920:                case SAPI_HEADER_SEND_FAILED:
                    921:                        SG(headers_sent) = 0;
                    922:                        ret = FAILURE;
                    923:                        break;
                    924:        }
                    925: 
                    926:        sapi_send_headers_free(TSRMLS_C);
                    927: 
                    928:        return ret;
                    929: }
                    930: 
                    931: 
                    932: SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries TSRMLS_DC)
                    933: {
                    934:        sapi_post_entry *p=post_entries;
                    935: 
                    936:        while (p->content_type) {
                    937:                if (sapi_register_post_entry(p TSRMLS_CC) == FAILURE) {
                    938:                        return FAILURE;
                    939:                }
                    940:                p++;
                    941:        }
                    942:        return SUCCESS;
                    943: }
                    944: 
                    945: 
                    946: SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
                    947: {
                    948:        if (SG(sapi_started) && EG(in_execution)) {
                    949:                return FAILURE;
                    950:        }
                    951:        return zend_hash_add(&SG(known_post_content_types),
                    952:                        post_entry->content_type, post_entry->content_type_len+1,
                    953:                        (void *) post_entry, sizeof(sapi_post_entry), NULL);
                    954: }
                    955: 
                    956: SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
                    957: {
                    958:        if (SG(sapi_started) && EG(in_execution)) {
                    959:                return;
                    960:        }
                    961:        zend_hash_del(&SG(known_post_content_types), post_entry->content_type,
                    962:                        post_entry->content_type_len+1);
                    963: }
                    964: 
                    965: 
1.1.1.2   misho     966: SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D) TSRMLS_DC)
1.1       misho     967: {
                    968:        if (SG(sapi_started) && EG(in_execution)) {
                    969:                return FAILURE;
                    970:        }
                    971:        sapi_module.default_post_reader = default_post_reader;
                    972:        return SUCCESS;
                    973: }
                    974: 
                    975: 
1.1.1.2   misho     976: SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC) TSRMLS_DC)
1.1       misho     977: {
                    978:        if (SG(sapi_started) && EG(in_execution)) {
                    979:                return FAILURE;
                    980:        }
                    981:        sapi_module.treat_data = treat_data;
                    982:        return SUCCESS;
                    983: }
                    984: 
1.1.1.2   misho     985: SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D) TSRMLS_DC)
1.1       misho     986: {
                    987:        if (SG(sapi_started) && EG(in_execution)) {
                    988:                return FAILURE;
                    989:        }
                    990:        sapi_module.input_filter = input_filter;
                    991:        sapi_module.input_filter_init = input_filter_init;
                    992:        return SUCCESS;
                    993: }
                    994: 
                    995: SAPI_API int sapi_flush(TSRMLS_D)
                    996: {
                    997:        if (sapi_module.flush) {
                    998:                sapi_module.flush(SG(server_context));
                    999:                return SUCCESS;
                   1000:        } else {
                   1001:                return FAILURE;
                   1002:        }
                   1003: }
                   1004: 
                   1005: SAPI_API struct stat *sapi_get_stat(TSRMLS_D)
                   1006: {
                   1007:        if (sapi_module.get_stat) {
                   1008:                return sapi_module.get_stat(TSRMLS_C);
                   1009:        } else {
                   1010:                if (!SG(request_info).path_translated || (VCWD_STAT(SG(request_info).path_translated, &SG(global_stat)) == -1)) {
                   1011:                        return NULL;
                   1012:                }
                   1013:                return &SG(global_stat);
                   1014:        }
                   1015: }
                   1016: 
                   1017: SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC)
                   1018: {
                   1019:        if (sapi_module.getenv) { 
                   1020:                char *value, *tmp = sapi_module.getenv(name, name_len TSRMLS_CC);
                   1021:                if (tmp) {
                   1022:                        value = estrdup(tmp);
                   1023:                } else {
                   1024:                        return NULL;
                   1025:                }
1.1.1.3   misho    1026:                if (sapi_module.input_filter) {
                   1027:                        sapi_module.input_filter(PARSE_STRING, name, &value, strlen(value), NULL TSRMLS_CC);
                   1028:                }
1.1       misho    1029:                return value;
                   1030:        }
                   1031:        return NULL;
                   1032: }
                   1033: 
                   1034: SAPI_API int sapi_get_fd(int *fd TSRMLS_DC)
                   1035: {
                   1036:        if (sapi_module.get_fd) {
                   1037:                return sapi_module.get_fd(fd TSRMLS_CC);
                   1038:        } else {
                   1039:                return FAILURE;
                   1040:        }
                   1041: }
                   1042: 
                   1043: SAPI_API int sapi_force_http_10(TSRMLS_D)
                   1044: {
                   1045:        if (sapi_module.force_http_10) {
                   1046:                return sapi_module.force_http_10(TSRMLS_C);
                   1047:        } else {
                   1048:                return FAILURE;
                   1049:        }
                   1050: }
                   1051: 
                   1052: 
                   1053: SAPI_API int sapi_get_target_uid(uid_t *obj TSRMLS_DC)
                   1054: {
                   1055:        if (sapi_module.get_target_uid) {
                   1056:                return sapi_module.get_target_uid(obj TSRMLS_CC);
                   1057:        } else {
                   1058:                return FAILURE;
                   1059:        }
                   1060: }
                   1061: 
                   1062: SAPI_API int sapi_get_target_gid(gid_t *obj TSRMLS_DC)
                   1063: {
                   1064:        if (sapi_module.get_target_gid) {
                   1065:                return sapi_module.get_target_gid(obj TSRMLS_CC);
                   1066:        } else {
                   1067:                return FAILURE;
                   1068:        }
                   1069: }
                   1070: 
1.1.1.2   misho    1071: SAPI_API double sapi_get_request_time(TSRMLS_D)
1.1       misho    1072: {
                   1073:        if(SG(global_request_time)) return SG(global_request_time);
                   1074: 
                   1075:        if (sapi_module.get_request_time && SG(server_context)) {
                   1076:                SG(global_request_time) = sapi_module.get_request_time(TSRMLS_C);
                   1077:        } else {
1.1.1.2   misho    1078:                struct timeval tp = {0};
                   1079:                if (!gettimeofday(&tp, NULL)) {
                   1080:                        SG(global_request_time) = (double)(tp.tv_sec + tp.tv_usec / 1000000.00);
                   1081:                } else {
                   1082:                        SG(global_request_time) = (double)time(0);
                   1083:                }
1.1       misho    1084:        }
                   1085:        return SG(global_request_time);
                   1086: }
                   1087: 
                   1088: SAPI_API void sapi_terminate_process(TSRMLS_D) {
                   1089:        if (sapi_module.terminate_process) {
                   1090:                sapi_module.terminate_process(TSRMLS_C);
                   1091:        }
                   1092: }
                   1093: 
                   1094: /*
                   1095:  * Local variables:
                   1096:  * tab-width: 4
                   1097:  * c-basic-offset: 4
                   1098:  * End:
                   1099:  * vim600: sw=4 ts=4 fdm=marker
                   1100:  * vim<600: sw=4 ts=4
                   1101:  */

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