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>