Annotation of embedaddon/php/sapi/continuity/capi.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:   | Author: Alex Leigh <php (at) postfin (dot) com>                      |
        !            16:   +----------------------------------------------------------------------+
        !            17: */
        !            18: 
        !            19: /* For more information on Continuity: http://www.ashpool.com/ */
        !            20: 
        !            21: /*
        !            22:  * This code is based on the PHP5 SAPI module for NSAPI by Jayakumar
        !            23:  * Muthukumarasamy
        !            24:  */
        !            25: 
        !            26: /* PHP includes */
        !            27: #define CONTINUITY 1
        !            28: #define CAPI_DEBUG
        !            29: 
        !            30: /* Define for CDP specific extensions */
        !            31: #undef CONTINUITY_CDPEXT
        !            32: 
        !            33: #include "php.h"
        !            34: #include "php_variables.h"
        !            35: #include "ext/standard/info.h"
        !            36: #include "php_ini.h"
        !            37: #include "php_globals.h"
        !            38: #include "SAPI.h"
        !            39: #include "php_main.h"
        !            40: #include "php_version.h"
        !            41: #include "TSRM.h"
        !            42: #include "ext/standard/php_standard.h"
        !            43: 
        !            44: /*
        !            45:  * CAPI includes
        !            46:  */
        !            47: #include <continuity.h>
        !            48: #include <http.h>
        !            49: 
        !            50: #define NSLS_D         struct capi_request_context *request_context
        !            51: #define NSLS_DC                , NSLS_D
        !            52: #define NSLS_C         request_context
        !            53: #define NSLS_CC                , NSLS_C
        !            54: #define NSG(v)         (request_context->v)
        !            55: 
        !            56: /*
        !            57:  * ZTS needs to be defined for CAPI to work
        !            58:  */
        !            59: #if !defined(ZTS)
        !            60: #error "CAPI module needs ZTS to be defined"
        !            61: #endif
        !            62: 
        !            63: /*
        !            64:  * Structure to encapsulate the CAPI request in SAPI
        !            65:  */
        !            66: typedef struct capi_request_context {
        !            67:    httpTtrans *t;
        !            68:    int read_post_bytes;
        !            69: } capi_request_context;
        !            70: 
        !            71: /**************/
        !            72: 
        !            73: PHP_MINIT_FUNCTION(continuity);
        !            74: PHP_MSHUTDOWN_FUNCTION(continuity);
        !            75: PHP_RINIT_FUNCTION(continuity);
        !            76: PHP_RSHUTDOWN_FUNCTION(continuity);
        !            77: PHP_MINFO_FUNCTION(continuity);
        !            78:         
        !            79: PHP_FUNCTION(continuity_virtual);
        !            80: PHP_FUNCTION(continuity_request_headers);
        !            81: PHP_FUNCTION(continuity_response_headers);
        !            82: 
        !            83: const zend_function_entry continuity_functions[] = {
        !            84:         {NULL, NULL, NULL}
        !            85: };
        !            86: 
        !            87: zend_module_entry continuity_module_entry = {
        !            88:         STANDARD_MODULE_HEADER,
        !            89:         "continuity",
        !            90:         continuity_functions,   
        !            91:         PHP_MINIT(continuity),
        !            92:         PHP_MSHUTDOWN(continuity),
        !            93:         NULL,
        !            94:         NULL,
        !            95:         PHP_MINFO(continuity),
        !            96:         NO_VERSION_YET,
        !            97:         STANDARD_MODULE_PROPERTIES
        !            98: };
        !            99: 
        !           100: PHP_MINIT_FUNCTION(continuity)
        !           101: {
        !           102:         return SUCCESS;
        !           103: }
        !           104: 
        !           105: PHP_MSHUTDOWN_FUNCTION(continuity)
        !           106: {
        !           107:         return SUCCESS;
        !           108: }
        !           109: 
        !           110: PHP_MINFO_FUNCTION(continuity)
        !           111: {
        !           112:         php_info_print_table_start();
        !           113:         php_info_print_table_row(2, "Continuity Module Revision", "$Revision: 321634 $");
        !           114:         php_info_print_table_row(2, "Server Version", conFget_build());
        !           115: #ifdef CONTINUITY_CDPEXT
        !           116:        php_info_print_table_row(2,"CDP Extensions", "enabled");
        !           117: #else
        !           118:        php_info_print_table_row(2,"CDP Extensions", "disabled");
        !           119: #endif
        !           120:         php_info_print_table_end();
        !           121:         
        !           122: /*        DISPLAY_INI_ENTRIES(); */
        !           123: }
        !           124: 
        !           125: /**************/
        !           126: 
        !           127: /*
        !           128:  * sapi_capi_ub_write: Write len bytes to the connection output.
        !           129:  */
        !           130: static int sapi_capi_ub_write(const char *str, unsigned int str_length TSRMLS_DC)
        !           131: {
        !           132:    int retval;
        !           133:    capi_request_context *rc;
        !           134: 
        !           135:    rc = (capi_request_context *) SG(server_context);
        !           136:    retval = httpFwrite(rc->t, (char *) str, str_length);
        !           137:    if (retval == -1 || retval == 0)
        !           138:       php_handle_aborted_connection();
        !           139:    return retval;
        !           140: }
        !           141: 
        !           142: /*
        !           143:  * sapi_capi_header_handler: Add/update response headers with those provided
        !           144:  * by the PHP engine.
        !           145:  */
        !           146: static int sapi_capi_header_handler(sapi_header_struct * sapi_header, sapi_headers_struct * sapi_headers TSRMLS_DC)
        !           147: {
        !           148:    char *header_name, *header_content, *p;
        !           149:    capi_request_context *rc = (capi_request_context *) SG(server_context);
        !           150: 
        !           151:    lstFset_delete_key(rc->t->res_hdrs, "Content-Type");
        !           152: 
        !           153:    header_name = sapi_header->header;
        !           154:    header_content = p = strchr(header_name, ':');
        !           155:    if (p == NULL) {
        !           156:       return 0;
        !           157:    }
        !           158:    *p = 0;
        !           159:    do {
        !           160:       header_content++;
        !           161:    } while (*header_content == ' ');
        !           162: 
        !           163:    lstFset_add(rc->t->res_hdrs, header_name, header_content);
        !           164: 
        !           165:    *p = ':';                   /* restore '*p' */
        !           166: 
        !           167:    efree(sapi_header->header);
        !           168: 
        !           169:    return 0;                   /* don't use the default SAPI mechanism, CAPI
        !           170:                                 * duplicates this functionality */
        !           171: }
        !           172: 
        !           173: /*
        !           174:  * sapi_capi_send_headers: Transmit the headers to the client. This has the
        !           175:  * effect of starting the response under Continuity.
        !           176:  */
        !           177: static int sapi_capi_send_headers(sapi_headers_struct * sapi_headers TSRMLS_DC)
        !           178: {
        !           179:    int retval;
        !           180:    capi_request_context *rc = (capi_request_context *) SG(server_context);
        !           181: 
        !           182:    /*
        !           183:     * We could probably just do this in the header_handler. But, I don't know
        !           184:     * what the implication of doing it there is.
        !           185:     */
        !           186: 
        !           187:    if (SG(sapi_headers).send_default_content_type) {
        !           188:       /* lstFset_delete_key(rc->t->res_hdrs, "Content-Type"); */
        !           189:       lstFset_update(rc->t->res_hdrs, "Content-Type", "text/html");
        !           190:    }
        !           191:    httpFset_status(rc->t, SG(sapi_headers).http_response_code, NULL);
        !           192:    httpFstart_response(rc->t);
        !           193: 
        !           194:    return SAPI_HEADER_SENT_SUCCESSFULLY;
        !           195: 
        !           196: }
        !           197: 
        !           198: static int sapi_capi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
        !           199: {
        !           200:    unsigned int max_read, total_read = 0;
        !           201:    capi_request_context *rc = (capi_request_context *) SG(server_context);
        !           202: 
        !           203:    if (rc->read_post_bytes == -1) {
        !           204:       max_read = MIN(count_bytes, SG(request_info).content_length);
        !           205:    } else {
        !           206:       if (rc->read_post_bytes == 0)
        !           207:         return 0;
        !           208:       max_read = MIN(count_bytes, (SG(request_info).content_length - rc->read_post_bytes));
        !           209:    }
        !           210: 
        !           211:    total_read = httpFread(rc->t, buffer, max_read);
        !           212: 
        !           213:    if (total_read < 0)
        !           214:       total_read = -1;
        !           215:    else
        !           216:       rc->read_post_bytes = total_read;
        !           217: 
        !           218:    return total_read;
        !           219: }
        !           220: 
        !           221: /*
        !           222:  * sapi_capi_read_cookies: Return cookie information into PHP.
        !           223:  */
        !           224: static char *sapi_capi_read_cookies(TSRMLS_D)
        !           225: {
        !           226:    char *cookie_string;
        !           227:    capi_request_context *rc = (capi_request_context *) SG(server_context);
        !           228: 
        !           229:    cookie_string = lstFset_get(rc->t->req_hdrs, "cookie");
        !           230:    return cookie_string;
        !           231: }
        !           232: 
        !           233: static void sapi_capi_register_server_variables(zval * track_vars_array TSRMLS_DC)
        !           234: {
        !           235:    capi_request_context *rc = (capi_request_context *) SG(server_context);
        !           236:    size_t i;
        !           237:    char *value;
        !           238:    char buf[128];
        !           239: 
        !           240:    /* PHP_SELF and REQUEST_URI */
        !           241:    value = lstFset_get(rc->t->vars, "uri");
        !           242:    if (value != NULL) {
        !           243:       php_register_variable("PHP_SELF", value, track_vars_array TSRMLS_CC);
        !           244:       php_register_variable("REQUEST_URI", value, track_vars_array TSRMLS_CC);
        !           245:    }
        !           246:  
        !           247:    /* COUNTRY CODE */
        !           248:    value = lstFset_get(rc->t->vars, "ccode");
        !           249:    if(value!=NULL)
        !           250:      php_register_variable("COUNTRY_CODE", value, track_vars_array TSRMLS_CC);
        !           251: 
        !           252:    /* argv */
        !           253:    value = lstFset_get(rc->t->vars, "query");
        !           254:    if (value != NULL)
        !           255:       php_register_variable("argv", value, track_vars_array TSRMLS_CC);
        !           256: 
        !           257:    /* GATEWAY_INTERFACE */
        !           258:    php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC);
        !           259: 
        !           260:    /* SERVER_NAME and HTTP_HOST */
        !           261:    value = lstFset_get(rc->t->req_hdrs, "host");
        !           262:    if (value != NULL) {
        !           263:       php_register_variable("HTTP_HOST", value, track_vars_array TSRMLS_CC);
        !           264:       /* TODO: This should probably scrub the port value if one is present. */
        !           265:       php_register_variable("SERVER_NAME", value, track_vars_array TSRMLS_CC);
        !           266:    }
        !           267:    /* SERVER_SOFTWARE */
        !           268:    value = lstFset_get(rc->t->res_hdrs, "Server");
        !           269:    if (value != NULL)
        !           270:       php_register_variable("SERVER_SOFTWARE", value, track_vars_array TSRMLS_CC);
        !           271: 
        !           272:    /* SERVER_PROTOCOL */
        !           273:    value = lstFset_get(rc->t->vars, "protocol");
        !           274:    if (value != NULL)
        !           275:       php_register_variable("SERVER_PROTOCOL", value, track_vars_array TSRMLS_CC);
        !           276: 
        !           277:    /* REQUEST_METHOD */
        !           278:    value = lstFset_get(rc->t->vars, "method");
        !           279:    if (value != NULL)
        !           280:       php_register_variable("REQUEST_METHOD", value, track_vars_array TSRMLS_CC);
        !           281: 
        !           282:    /* QUERY_STRING */
        !           283:    value = lstFset_get(rc->t->vars, "query");
        !           284:    if (value != NULL)
        !           285:       php_register_variable("QUERY_STRING", value, track_vars_array TSRMLS_CC);
        !           286: 
        !           287:    /* DOCUMENT_ROOT */
        !           288:    value = lstFset_get(rc->t->vars, "docroot");
        !           289:    if (value != NULL)
        !           290:       php_register_variable("DOCUMENT_ROOT", value, track_vars_array TSRMLS_CC);
        !           291: 
        !           292:    /* HTTP_ACCEPT */
        !           293:    value = lstFset_get(rc->t->req_hdrs, "accept");
        !           294:    if (value != NULL)
        !           295:       php_register_variable("HTTP_ACCEPT", value, track_vars_array TSRMLS_CC);
        !           296: 
        !           297:    /* HTTP_ACCEPT_CHARSET */
        !           298:    value = lstFset_get(rc->t->req_hdrs, "accept-charset");
        !           299:    if (value != NULL)
        !           300:       php_register_variable("HTTP_ACCEPT_CHARSET", value, track_vars_array TSRMLS_CC);
        !           301: 
        !           302:    /* HTTP_ACCEPT_ENCODING */
        !           303:    value = lstFset_get(rc->t->req_hdrs, "accept-encoding");
        !           304:    if (value != NULL)
        !           305:       php_register_variable("HTTP_ACCEPT_ENCODING", value, track_vars_array TSRMLS_CC);
        !           306: 
        !           307:    /* HTTP_ACCEPT_LANGUAGE */
        !           308:    value = lstFset_get(rc->t->req_hdrs, "accept-language");
        !           309:    if (value != NULL)
        !           310:       php_register_variable("HTTP_ACCEPT_LANGUAGE", value, track_vars_array TSRMLS_CC);
        !           311: 
        !           312:    /* HTTP_CONNECTION */
        !           313:    value = lstFset_get(rc->t->req_hdrs, "connection");
        !           314:    if (value != NULL)
        !           315:       php_register_variable("HTTP_CONNECTION", value, track_vars_array TSRMLS_CC);
        !           316: 
        !           317:    /* HTTP_REFERER */
        !           318:    value = lstFset_get(rc->t->req_hdrs, "referer");
        !           319:    if (value != NULL)
        !           320:       php_register_variable("HTTP_REFERER", value, track_vars_array TSRMLS_CC);
        !           321: 
        !           322:    /* HTTP_USER_AGENT */
        !           323:    value = lstFset_get(rc->t->req_hdrs, "user-agent");
        !           324:    if (value != NULL)
        !           325:       php_register_variable("HTTP_USER_AGENT", value, track_vars_array TSRMLS_CC);
        !           326: 
        !           327:    /* REMOTE_ADDR */
        !           328:    utlFip_to_str(rc->t->cli_ipv4_addr, buf, sizeof(buf));
        !           329:    php_register_variable("REMOTE_ADDR", buf, track_vars_array TSRMLS_CC);
        !           330: 
        !           331:    /* REMOTE_PORT */
        !           332: 
        !           333:    /* SCRIPT_FILENAME and PATH_TRANSLATED */
        !           334:    value = lstFset_get(rc->t->vars, "path");
        !           335:    if (value != NULL) {
        !           336:       php_register_variable("SCRIPT_FILENAME", value, track_vars_array TSRMLS_CC);
        !           337:       php_register_variable("PATH_TRANSLATED", value, track_vars_array TSRMLS_CC);
        !           338:    }
        !           339:    /* SERVER_ADMIN */
        !           340:    /* Not applicable */
        !           341: 
        !           342:    /* SERVER_PORT */
        !           343: 
        !           344: }
        !           345: 
        !           346: static void capi_log_message(char *message)
        !           347: {
        !           348:    TSRMLS_FETCH();
        !           349:    capi_request_context *rc = (capi_request_context *) SG(server_context);
        !           350:    logFmsg(0, "mod/php: %s", message);
        !           351: }
        !           352: 
        !           353: static int php_capi_startup(sapi_module_struct *sapi_module);
        !           354: 
        !           355: sapi_module_struct capi_sapi_module = {
        !           356:    "Continuity",                       /* name */
        !           357:    "Continuity Server Enterprise Edition",     /* pretty name */
        !           358: 
        !           359:    php_capi_startup,           /* startup */
        !           360:    php_module_shutdown_wrapper,        /* shutdown */
        !           361: 
        !           362:    NULL,                       /* activate */
        !           363:    NULL,                       /* deactivate */
        !           364: 
        !           365:    sapi_capi_ub_write,         /* unbuffered write */
        !           366:    NULL,                       /* flush */
        !           367:    NULL,                       /* get uid */
        !           368:    NULL,                       /* getenv */
        !           369: 
        !           370:    php_error,                  /* error handler */
        !           371: 
        !           372:    sapi_capi_header_handler,   /* header handler */
        !           373:    sapi_capi_send_headers,     /* send headers handler */
        !           374:    NULL,                       /* send header handler */
        !           375: 
        !           376:    sapi_capi_read_post,                /* read POST data */
        !           377:    sapi_capi_read_cookies,     /* read Cookies */
        !           378: 
        !           379:    sapi_capi_register_server_variables,        /* register server variables */
        !           380:    capi_log_message,           /* Log message */
        !           381:    NULL,                       /* Get request time */
        !           382:    NULL,                       /* Child terminate */
        !           383: 
        !           384:    NULL,                       /* Block interruptions */
        !           385:    NULL,                       /* Unblock interruptions */
        !           386: 
        !           387:    STANDARD_SAPI_MODULE_PROPERTIES
        !           388: };
        !           389: 
        !           390: static int php_capi_startup(sapi_module_struct *sapi_module) {
        !           391:   if(php_module_startup(sapi_module,&continuity_module_entry,1)==FAILURE) {
        !           392:     return FAILURE;
        !           393:   }
        !           394:   return SUCCESS;
        !           395: }
        !           396: 
        !           397: 
        !           398: static char *
        !           399:  capi_strdup(char *str)
        !           400: {
        !           401:    if (str != NULL)
        !           402:       return strFcopy(str);
        !           403:    return NULL;
        !           404: }
        !           405: 
        !           406: static void capi_free(void *addr)
        !           407: {
        !           408:    if (addr != NULL)
        !           409:       free(addr);
        !           410: }
        !           411: 
        !           412: static void capi_request_ctor(NSLS_D TSRMLS_DC)
        !           413: {
        !           414:    char *query_string = lstFset_get(NSG(t->vars), "query");
        !           415:    char *uri = lstFset_get(NSG(t->vars), "uri");
        !           416:    char *path_info = lstFset_get(NSG(t->vars), "path-info");
        !           417:    char *path_translated = lstFset_get(NSG(t->vars), "path");
        !           418:    char *request_method = lstFset_get(NSG(t->vars), "method");
        !           419:    char *content_type = lstFset_get(NSG(t->req_hdrs), "content-type");
        !           420:    char *content_length = lstFset_get(NSG(t->req_hdrs), "content-length");
        !           421: 
        !           422:    SG(request_info).query_string = capi_strdup(query_string);
        !           423:    SG(request_info).request_uri = capi_strdup(uri);
        !           424:    SG(request_info).request_method = capi_strdup(request_method);
        !           425:    SG(request_info).path_translated = capi_strdup(path_translated);
        !           426:    SG(request_info).content_type = capi_strdup(content_type);
        !           427:    SG(request_info).content_length = (content_length == NULL) ? 0 : strtoul(content_length, 0, 0);
        !           428:    SG(sapi_headers).http_response_code = 200;
        !           429: }
        !           430: 
        !           431: static void capi_request_dtor(NSLS_D TSRMLS_DC)
        !           432: {
        !           433:    capi_free(SG(request_info).query_string);
        !           434:    capi_free(SG(request_info).request_uri);
        !           435:    capi_free(SG(request_info).request_method);
        !           436:    capi_free(SG(request_info).path_translated);
        !           437:    capi_free(SG(request_info).content_type);
        !           438: }
        !           439: 
        !           440: int capi_module_main(NSLS_D TSRMLS_DC)
        !           441: {
        !           442:    zend_file_handle file_handle;
        !           443: 
        !           444:    if (php_request_startup(TSRMLS_C) == FAILURE) {
        !           445:       return FAILURE;
        !           446:    }
        !           447:    file_handle.type = ZEND_HANDLE_FILENAME;
        !           448:    file_handle.filename = SG(request_info).path_translated;
        !           449:    file_handle.free_filename = 0;
        !           450:    file_handle.opened_path = NULL;
        !           451: 
        !           452:    php_execute_script(&file_handle TSRMLS_CC);
        !           453:    php_request_shutdown(NULL);
        !           454: 
        !           455:    return SUCCESS;
        !           456: }
        !           457: 
        !           458: int phpFinit(lstTset * opt)
        !           459: {
        !           460:    php_core_globals *core_globals;
        !           461: 
        !           462:    tsrm_startup(128, 1, 0, NULL);
        !           463:    core_globals = ts_resource(core_globals_id);
        !           464: 
        !           465:    logFmsg(0, "mod/php: PHP Interface v3 (module)");
        !           466:    logFmsg(0, "mod/php: Copyright (c) 1999-2005 The PHP Group. All rights reserved.");
        !           467: 
        !           468:    sapi_startup(&capi_sapi_module);
        !           469:    capi_sapi_module.startup(&capi_sapi_module);
        !           470: 
        !           471:    return STATUS_PROCEED;
        !           472: }
        !           473: 
        !           474: int phpFservice(httpTtrans * t, lstTset * opts)
        !           475: {
        !           476:    int retval;
        !           477:    capi_request_context *request_context;
        !           478: 
        !           479:    TSRMLS_FETCH();
        !           480: 
        !           481:    request_context = (capi_request_context *) malloc(sizeof(capi_request_context));
        !           482:    request_context->t = t;
        !           483:    request_context->read_post_bytes = -1;
        !           484: 
        !           485:    SG(server_context) = request_context;
        !           486: 
        !           487:    capi_request_ctor(NSLS_C TSRMLS_CC);
        !           488:    retval = capi_module_main(NSLS_C TSRMLS_CC);
        !           489:    capi_request_dtor(NSLS_C TSRMLS_CC);
        !           490: 
        !           491:    free(request_context);
        !           492: 
        !           493:    /*
        !           494:     * This call is ostensibly provided to free the memory from PHP/TSRM when
        !           495:     * the thread terminated, but, it leaks a structure in some hash list
        !           496:     * according to the developers. Not calling this will leak the entire
        !           497:     * interpreter, around 100k, but calling it and then terminating the
        !           498:     * thread will leak the struct (around a k). The only answer with the
        !           499:     * current TSRM implementation is to reuse the threads that allocate TSRM
        !           500:     * resources.
        !           501:     */
        !           502:    /* ts_free_thread(); */
        !           503: 
        !           504:    if (retval == SUCCESS) {
        !           505:       return STATUS_EXIT;
        !           506:    } else {
        !           507:       return STATUS_ERROR;
        !           508:    }
        !           509: }

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