Annotation of embedaddon/php/sapi/aolserver/aolserver.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: Sascha Schumann <sascha@schumann.cx> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /*
! 20: * TODO:
! 21: * - write documentation
! 22: * - CGI/1.1 conformance
! 23: */
! 24:
! 25: /* $Id: aolserver.c 321634 2012-01-01 13:15:04Z felipe $ */
! 26:
! 27: /* conflict between PHP and AOLserver headers */
! 28: #define Debug php_Debug
! 29: #include "php.h"
! 30: #undef Debug
! 31:
! 32: #ifdef HAVE_AOLSERVER
! 33:
! 34: #ifndef ZTS
! 35: #error AOLserver module is only useable in thread-safe mode
! 36: #endif
! 37:
! 38: #include "ext/standard/info.h"
! 39: #define SECTION(name) PUTS("<h2>" name "</h2>\n")
! 40:
! 41: #define NS_BUF_SIZE 511
! 42:
! 43: #include "php_ini.h"
! 44: #include "php_globals.h"
! 45: #include "SAPI.h"
! 46: #include "php_main.h"
! 47: #include "php_variables.h"
! 48:
! 49: #include "ns.h"
! 50:
! 51: #include "php_version.h"
! 52:
! 53: /* This symbol is used by AOLserver to tell the API version we expect */
! 54:
! 55: int Ns_ModuleVersion = 1;
! 56:
! 57: #define NSG(v) TSRMG(ns_globals_id, ns_globals_struct *, v)
! 58:
! 59: /* php_ns_context is per-server (thus only once at all) */
! 60:
! 61: typedef struct {
! 62: sapi_module_struct *sapi_module;
! 63: char *ns_server;
! 64: char *ns_module;
! 65: } php_ns_context;
! 66:
! 67: /* ns_globals_struct is per-thread */
! 68:
! 69: typedef struct {
! 70: Ns_Conn *conn;
! 71: size_t data_avail;
! 72: } ns_globals_struct;
! 73:
! 74: /* TSRM id */
! 75:
! 76: static int ns_globals_id;
! 77:
! 78: /* global context */
! 79:
! 80: static php_ns_context *global_context;
! 81:
! 82: static void php_ns_config(php_ns_context *ctx, char global);
! 83:
! 84: /*
! 85: * php_ns_sapi_ub_write() writes data to the client connection.
! 86: */
! 87:
! 88: static int
! 89: php_ns_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
! 90: {
! 91: int n;
! 92: uint sent = 0;
! 93:
! 94: while (str_length > 0) {
! 95: n = Ns_ConnWrite(NSG(conn), (void *) str, str_length);
! 96:
! 97: if (n == -1)
! 98: php_handle_aborted_connection();
! 99:
! 100: str += n;
! 101: sent += n;
! 102: str_length -= n;
! 103: }
! 104:
! 105: return sent;
! 106: }
! 107:
! 108: /*
! 109: * php_ns_sapi_header_handler() sets a HTTP reply header to be
! 110: * sent to the client.
! 111: */
! 112:
! 113: static int
! 114: php_ns_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
! 115: {
! 116: char *header_name, *header_content;
! 117: char *p;
! 118:
! 119: header_name = sapi_header->header;
! 120: header_content = p = strchr(header_name, ':');
! 121:
! 122: if (p) {
! 123: *p = '\0';
! 124: do {
! 125: header_content++;
! 126: } while (*header_content == ' ');
! 127:
! 128: if (!strcasecmp(header_name, "Content-type")) {
! 129: Ns_ConnSetTypeHeader(NSG(conn), header_content);
! 130: } else {
! 131: Ns_ConnSetHeaders(NSG(conn), header_name, header_content);
! 132: }
! 133:
! 134: *p = ':';
! 135: }
! 136:
! 137: sapi_free_header(sapi_header);
! 138:
! 139: return 0;
! 140: }
! 141:
! 142: /*
! 143: * php_ns_sapi_send_headers() flushes the headers to the client.
! 144: * Called before real content is sent by PHP.
! 145: */
! 146:
! 147: static int
! 148: php_ns_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
! 149: {
! 150: if(SG(sapi_headers).send_default_content_type) {
! 151: Ns_ConnSetRequiredHeaders(NSG(conn), "text/html", 0);
! 152: }
! 153:
! 154: Ns_ConnFlushHeaders(NSG(conn), SG(sapi_headers).http_response_code);
! 155:
! 156: return SAPI_HEADER_SENT_SUCCESSFULLY;
! 157: }
! 158:
! 159: /*
! 160: * php_ns_sapi_read_post() reads a specified number of bytes from
! 161: * the client. Used for POST/PUT requests.
! 162: */
! 163:
! 164: static int
! 165: php_ns_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
! 166: {
! 167: uint max_read;
! 168: uint total_read = 0;
! 169:
! 170: max_read = MIN(NSG(data_avail), count_bytes);
! 171:
! 172: total_read = Ns_ConnRead(NSG(conn), buf, max_read);
! 173:
! 174: if(total_read == NS_ERROR) {
! 175: total_read = -1;
! 176: } else {
! 177: NSG(data_avail) -= total_read;
! 178: }
! 179:
! 180: return total_read;
! 181: }
! 182:
! 183: /*
! 184: * php_ns_sapi_read_cookies() returns the Cookie header from
! 185: * the HTTP request header
! 186: */
! 187:
! 188: static char *php_ns_sapi_read_cookies(TSRMLS_D)
! 189: {
! 190: int i;
! 191: char *http_cookie = NULL;
! 192:
! 193: i = Ns_SetIFind(NSG(conn->headers), "cookie");
! 194: if(i != -1) {
! 195: http_cookie = Ns_SetValue(NSG(conn->headers), i);
! 196: }
! 197:
! 198: return http_cookie;
! 199: }
! 200:
! 201: static void php_info_aolserver(ZEND_MODULE_INFO_FUNC_ARGS)
! 202: {
! 203: char buf[512];
! 204: int uptime = Ns_InfoUptime();
! 205: int i;
! 206:
! 207: php_info_print_table_start();
! 208: php_info_print_table_row(2, "SAPI module version", "$Id: aolserver.c 321634 2012-01-01 13:15:04Z felipe $");
! 209: php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
! 210: php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
! 211: php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
! 212: php_info_print_table_row(2, "Installation path", Ns_InfoHomePath());
! 213: php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname());
! 214: php_info_print_table_row(2, "Source code label", Ns_InfoLabel());
! 215: php_info_print_table_row(2, "Server platform", Ns_InfoPlatform());
! 216: snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
! 217: php_info_print_table_row(2, "Server version", buf);
! 218: snprintf(buf, 511, "%d day(s), %02d:%02d:%02d",
! 219: uptime / 86400,
! 220: (uptime / 3600) % 24,
! 221: (uptime / 60) % 60,
! 222: uptime % 60);
! 223: php_info_print_table_row(2, "Server uptime", buf);
! 224: php_info_print_table_end();
! 225:
! 226: SECTION("HTTP Headers Information");
! 227: php_info_print_table_start();
! 228: php_info_print_table_colspan_header(2, "HTTP Request Headers");
! 229: php_info_print_table_row(2, "HTTP Request", NSG(conn)->request->line);
! 230: for (i = 0; i < Ns_SetSize(NSG(conn)->headers); i++) {
! 231: php_info_print_table_row(2, Ns_SetKey(NSG(conn)->headers, i), Ns_SetValue(NSG(conn)->headers, i));
! 232: }
! 233:
! 234: php_info_print_table_colspan_header(2, "HTTP Response Headers");
! 235: for (i = 0; i < Ns_SetSize(NSG(conn)->outputheaders); i++) {
! 236: php_info_print_table_row(2, Ns_SetKey(NSG(conn)->outputheaders, i), Ns_SetValue(NSG(conn)->outputheaders, i));
! 237: }
! 238: php_info_print_table_end();
! 239: }
! 240:
! 241: PHP_FUNCTION(getallheaders);
! 242:
! 243: /* {{{ arginfo */
! 244: ZEND_BEGIN_ARG_INFO(arginfo_aolserver_getallheaders, 0)
! 245: ZEND_END_ARG_INFO()
! 246: /* }}} */
! 247:
! 248: static const zend_function_entry aolserver_functions[] = {
! 249: PHP_FE(getallheaders, arginfo_aolserver_getallheaders)
! 250: {NULL, NULL, NULL}
! 251: };
! 252:
! 253: static zend_module_entry php_aolserver_module = {
! 254: STANDARD_MODULE_HEADER,
! 255: "AOLserver",
! 256: aolserver_functions,
! 257: NULL,
! 258: NULL,
! 259: NULL,
! 260: NULL,
! 261: php_info_aolserver,
! 262: NULL,
! 263: STANDARD_MODULE_PROPERTIES
! 264: };
! 265:
! 266: PHP_FUNCTION(getallheaders)
! 267: {
! 268: int i;
! 269:
! 270: array_init(return_value);
! 271:
! 272: for (i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) {
! 273: char *key = Ns_SetKey(NSG(conn->headers), i);
! 274: char *value = Ns_SetValue(NSG(conn->headers), i);
! 275:
! 276: add_assoc_string(return_value, key, value, 1);
! 277: }
! 278: }
! 279:
! 280: static int
! 281: php_ns_startup(sapi_module_struct *sapi_module)
! 282: {
! 283: if (php_module_startup(sapi_module, &php_aolserver_module, 1) == FAILURE) {
! 284: return FAILURE;
! 285: } else {
! 286: return SUCCESS;
! 287: }
! 288: }
! 289:
! 290:
! 291: /*
! 292: * php_ns_sapi_register_variables() populates the php script environment
! 293: * with a number of variables. HTTP_* variables are created for
! 294: * the HTTP header data, so that a script can access these.
! 295: */
! 296:
! 297: #define ADD_STRINGX(name, buf) \
! 298: php_register_variable(name, buf, track_vars_array TSRMLS_CC)
! 299:
! 300: #define ADD_STRING(name) \
! 301: ADD_STRINGX(name, buf)
! 302:
! 303: static void
! 304: php_ns_sapi_register_variables(zval *track_vars_array TSRMLS_DC)
! 305: {
! 306: int i;
! 307: char buf[NS_BUF_SIZE + 1];
! 308: char *tmp;
! 309:
! 310: for(i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) {
! 311: char *key = Ns_SetKey(NSG(conn->headers), i);
! 312: char *value = Ns_SetValue(NSG(conn->headers), i);
! 313: char *p;
! 314: char c;
! 315:
! 316: snprintf(buf, NS_BUF_SIZE, "HTTP_%s", key);
! 317:
! 318: for(p = buf + 5; (c = *p); p++) {
! 319: c = toupper(c);
! 320: if(c < 'A' || c > 'Z') {
! 321: c = '_';
! 322: }
! 323: *p = c;
! 324: }
! 325:
! 326: ADD_STRINGX(buf, value);
! 327: }
! 328:
! 329: snprintf(buf, NS_BUF_SIZE, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
! 330: ADD_STRING("SERVER_SOFTWARE");
! 331: snprintf(buf, NS_BUF_SIZE, "HTTP/%1.1f", NSG(conn)->request->version);
! 332: ADD_STRING("SERVER_PROTOCOL");
! 333:
! 334: ADD_STRINGX("REQUEST_METHOD", NSG(conn)->request->method);
! 335:
! 336: if(NSG(conn)->request->query)
! 337: ADD_STRINGX("QUERY_STRING", NSG(conn)->request->query);
! 338:
! 339: ADD_STRINGX("SERVER_BUILDDATE", Ns_InfoBuildDate());
! 340:
! 341: ADD_STRINGX("REMOTE_ADDR", Ns_ConnPeer(NSG(conn)));
! 342:
! 343: snprintf(buf, NS_BUF_SIZE, "%d", Ns_ConnPeerPort(NSG(conn)));
! 344: ADD_STRING("REMOTE_PORT");
! 345:
! 346: snprintf(buf, NS_BUF_SIZE, "%d", Ns_ConnPort(NSG(conn)));
! 347: ADD_STRING("SERVER_PORT");
! 348:
! 349: tmp = Ns_ConnHost(NSG(conn));
! 350: if (tmp)
! 351: ADD_STRINGX("SERVER_NAME", tmp);
! 352:
! 353: ADD_STRINGX("PATH_TRANSLATED", SG(request_info).path_translated);
! 354: ADD_STRINGX("REQUEST_URI", SG(request_info).request_uri);
! 355: ADD_STRINGX("PHP_SELF", SG(request_info).request_uri);
! 356:
! 357: ADD_STRINGX("GATEWAY_INTERFACE", "CGI/1.1");
! 358:
! 359: snprintf(buf, NS_BUF_SIZE, "%d", Ns_InfoBootTime());
! 360: ADD_STRING("SERVER_BOOTTIME");
! 361: }
! 362:
! 363:
! 364:
! 365: /* this structure is static (as in "it does not change") */
! 366:
! 367: static sapi_module_struct aolserver_sapi_module = {
! 368: "aolserver",
! 369: "AOLserver",
! 370:
! 371: php_ns_startup, /* startup */
! 372: php_module_shutdown_wrapper, /* shutdown */
! 373:
! 374: NULL, /* activate */
! 375: NULL, /* deactivate */
! 376:
! 377: php_ns_sapi_ub_write, /* unbuffered write */
! 378: NULL, /* flush */
! 379: NULL, /* get uid */
! 380: NULL, /* getenv */
! 381:
! 382: php_error, /* error handler */
! 383:
! 384: php_ns_sapi_header_handler, /* header handler */
! 385: php_ns_sapi_send_headers, /* send headers handler */
! 386: NULL, /* send header handler */
! 387:
! 388: php_ns_sapi_read_post, /* read POST data */
! 389: php_ns_sapi_read_cookies, /* read Cookies */
! 390:
! 391: php_ns_sapi_register_variables,
! 392: NULL, /* Log message */
! 393: NULL, /* Get request time */
! 394: NULL, /* child terminate */
! 395:
! 396: STANDARD_SAPI_MODULE_PROPERTIES
! 397: };
! 398:
! 399: /*
! 400: * php_ns_module_main() is called by the per-request handler and
! 401: * "executes" the script
! 402: */
! 403:
! 404: static int
! 405: php_ns_module_main(TSRMLS_D)
! 406: {
! 407: zend_file_handle file_handle;
! 408:
! 409: file_handle.type = ZEND_HANDLE_FILENAME;
! 410: file_handle.filename = SG(request_info).path_translated;
! 411: file_handle.free_filename = 0;
! 412: file_handle.opened_path = NULL;
! 413:
! 414: php_ns_config(global_context, 0);
! 415: if (php_request_startup(TSRMLS_C) == FAILURE) {
! 416: return NS_ERROR;
! 417: }
! 418:
! 419: php_execute_script(&file_handle TSRMLS_CC);
! 420: php_request_shutdown(NULL);
! 421:
! 422: return NS_OK;
! 423: }
! 424:
! 425: /*
! 426: * php_ns_request_ctor() initializes the per-request data structure
! 427: * and fills it with data provided by the web server
! 428: */
! 429:
! 430: static void
! 431: php_ns_request_ctor(TSRMLS_D)
! 432: {
! 433: char *server;
! 434: Ns_DString ds;
! 435: char *root;
! 436: int index;
! 437: char *tmp;
! 438:
! 439: server = Ns_ConnServer(NSG(conn));
! 440:
! 441: #define safe_strdup(x) ((x)?strdup((x)):NULL)
! 442: SG(request_info).query_string = safe_strdup(NSG(conn->request->query));
! 443:
! 444: Ns_DStringInit(&ds);
! 445: Ns_UrlToFile(&ds, server, NSG(conn->request->url));
! 446:
! 447: /* path_translated is the absolute path to the file */
! 448: SG(request_info).path_translated = safe_strdup(Ns_DStringValue(&ds));
! 449: Ns_DStringFree(&ds);
! 450: root = Ns_PageRoot(server);
! 451: SG(request_info).request_uri = strdup(SG(request_info).path_translated + strlen(root));
! 452: SG(request_info).request_method = NSG(conn)->request->method;
! 453: if(NSG(conn)->request->version > 1.0) SG(request_info).proto_num = 1001;
! 454: else SG(request_info).proto_num = 1000;
! 455: SG(request_info).content_length = Ns_ConnContentLength(NSG(conn));
! 456: index = Ns_SetIFind(NSG(conn)->headers, "content-type");
! 457: SG(request_info).content_type = index == -1 ? NULL :
! 458: Ns_SetValue(NSG(conn)->headers, index);
! 459: SG(sapi_headers).http_response_code = 200;
! 460:
! 461: tmp = Ns_ConnAuthUser(NSG(conn));
! 462: if (tmp)
! 463: tmp = estrdup(tmp);
! 464: SG(request_info).auth_user = tmp;
! 465:
! 466: tmp = Ns_ConnAuthPasswd(NSG(conn));
! 467: if (tmp)
! 468: tmp = estrdup(tmp);
! 469: SG(request_info).auth_password = tmp;
! 470:
! 471: NSG(data_avail) = SG(request_info).content_length;
! 472: }
! 473:
! 474: /*
! 475: * php_ns_request_dtor() destroys all data associated with
! 476: * the per-request structure
! 477: */
! 478:
! 479: static void
! 480: php_ns_request_dtor(TSRMLS_D)
! 481: {
! 482: free(SG(request_info).path_translated);
! 483: if (SG(request_info).query_string)
! 484: free(SG(request_info).query_string);
! 485: free(SG(request_info).request_uri);
! 486: }
! 487:
! 488: /*
! 489: * The php_ns_request_handler() is called per request and handles
! 490: * everything for one request.
! 491: */
! 492:
! 493: static int
! 494: php_ns_request_handler(void *context, Ns_Conn *conn)
! 495: {
! 496: int status = NS_OK;
! 497: TSRMLS_FETCH();
! 498:
! 499: NSG(conn) = conn;
! 500:
! 501: SG(server_context) = global_context;
! 502:
! 503: php_ns_request_ctor(TSRMLS_C);
! 504:
! 505: status = php_ns_module_main(TSRMLS_C);
! 506:
! 507: php_ns_request_dtor(TSRMLS_C);
! 508:
! 509: return status;
! 510: }
! 511:
! 512: /*
! 513: * php_ns_config() fetches the configuration data.
! 514: *
! 515: * It understands the "map" and "php_value" command.
! 516: */
! 517:
! 518: static void
! 519: php_ns_config(php_ns_context *ctx, char global)
! 520: {
! 521: int i;
! 522: char *path;
! 523: Ns_Set *set;
! 524:
! 525: path = Ns_ConfigGetPath(ctx->ns_server, ctx->ns_module, NULL);
! 526: set = Ns_ConfigGetSection(path);
! 527:
! 528: for (i = 0; set && i < Ns_SetSize(set); i++) {
! 529: char *key = Ns_SetKey(set, i);
! 530: char *value = Ns_SetValue(set, i);
! 531:
! 532: if (global && !strcasecmp(key, "map")) {
! 533: Ns_Log(Notice, "Registering PHP for \"%s\"", value);
! 534: Ns_RegisterRequest(ctx->ns_server, "GET", value, php_ns_request_handler, NULL, ctx, 0);
! 535: Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0);
! 536: Ns_RegisterRequest(ctx->ns_server, "HEAD", value, php_ns_request_handler, NULL, ctx, 0);
! 537:
! 538: /*
! 539: * Deactivated for now. The ini system will cause random crashes when
! 540: * accessed from here (since there are no locks to protect the global
! 541: * known_directives)
! 542: */
! 543:
! 544: } else if (!global && !strcasecmp(key, "php_value")) {
! 545: Ns_Log(Notice, "php_value has been deactivated temporarily. Please use a php.ini file to pass directives to PHP. Thanks.");
! 546: #if 0
! 547: char *val;
! 548:
! 549: val = strchr(value, ' ');
! 550: if (val) {
! 551: char *new_key;
! 552:
! 553: new_key = estrndup(value, val - value);
! 554:
! 555: do {
! 556: val++;
! 557: } while(*val == ' ');
! 558:
! 559: Ns_Log(Debug, "PHP configuration option '%s=%s'", new_key, val);
! 560: zend_alter_ini_entry(new_key, strlen(new_key) + 1, val,
! 561: strlen(val) + 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
! 562:
! 563: efree(new_key);
! 564: }
! 565: #endif
! 566: }
! 567:
! 568: }
! 569: }
! 570:
! 571: /*
! 572: * php_ns_server_shutdown() performs the last steps before the
! 573: * server exits. Shutdowns basic services and frees memory
! 574: */
! 575:
! 576: static void
! 577: php_ns_server_shutdown(void *context)
! 578: {
! 579: php_ns_context *ctx = (php_ns_context *) context;
! 580:
! 581: ctx->sapi_module->shutdown(ctx->sapi_module);
! 582: sapi_shutdown();
! 583: tsrm_shutdown();
! 584:
! 585: free(ctx->ns_module);
! 586: free(ctx->ns_server);
! 587: free(ctx);
! 588: }
! 589:
! 590: /*
! 591: * Ns_ModuleInit() is called by AOLserver once at startup
! 592: *
! 593: * This functions allocates basic structures and initializes
! 594: * basic services.
! 595: */
! 596:
! 597: int Ns_ModuleInit(char *server, char *module)
! 598: {
! 599: php_ns_context *ctx;
! 600:
! 601: tsrm_startup(1, 1, 0, NULL);
! 602: sapi_startup(&aolserver_sapi_module);
! 603: sapi_module.startup(&aolserver_sapi_module);
! 604:
! 605: /* TSRM is used to allocate a per-thread structure */
! 606: ts_allocate_id(&ns_globals_id, sizeof(ns_globals_struct), NULL, NULL);
! 607:
! 608: /* the context contains data valid for all threads */
! 609: ctx = malloc(sizeof *ctx);
! 610: ctx->sapi_module = &aolserver_sapi_module;
! 611: ctx->ns_server = strdup(server);
! 612: ctx->ns_module = strdup(module);
! 613:
! 614: /* read the configuration */
! 615: php_ns_config(ctx, 1);
! 616:
! 617: global_context = ctx;
! 618:
! 619: /* register shutdown handler */
! 620: Ns_RegisterServerShutdown(server, php_ns_server_shutdown, ctx);
! 621:
! 622: return NS_OK;
! 623: }
! 624:
! 625: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>