root/sapi/aolserver/aolserver.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_ns_sapi_ub_write
  2. php_ns_sapi_header_handler
  3. php_ns_sapi_send_headers
  4. php_ns_sapi_read_post
  5. php_ns_sapi_read_cookies
  6. php_info_aolserver
  7. PHP_FUNCTION
  8. php_ns_startup
  9. php_ns_sapi_register_variables
  10. php_ns_module_main
  11. php_ns_request_ctor
  12. php_ns_request_dtor
  13. php_ns_request_handler
  14. php_ns_config
  15. php_ns_server_shutdown
  16. Ns_ModuleInit

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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$ */
  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$");
 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

/* [<][>][^][v][top][bottom][index][help] */