root/sapi/isapi/php5isapi.c

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

DEFINITIONS

This source file includes following definitions.
  1. php_info_isapi
  2. sapi_isapi_ub_write
  3. sapi_isapi_header_handler
  4. accumulate_header_length
  5. concat_header
  6. sapi_isapi_send_headers
  7. php_isapi_startup
  8. sapi_isapi_read_post
  9. sapi_isapi_read_cookies
  10. sapi_isapi_register_zeus_ssl_variables
  11. sapi_isapi_register_zeus_variables
  12. sapi_isapi_register_iis_variables
  13. sapi_isapi_register_server_variables2
  14. sapi_isapi_register_server_variables
  15. GetFilterVersion
  16. HttpFilterProc
  17. init_request_info
  18. php_isapi_report_exception
  19. GetExtensionVersion
  20. my_endthread
  21. exceptionhandler
  22. HttpExtensionProc
  23. __declspec

   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    | Authors: Zeev Suraski <zeev@zend.com>                                |
  16    |          Ben Mansell <ben@zeus.com> (Zeus Support)                   |
  17    +----------------------------------------------------------------------+
  18  */
  19 /* $Id$ */
  20 
  21 #include "php.h"
  22 #include <httpext.h>
  23 #include <httpfilt.h>
  24 #include <httpext.h>
  25 #include "php_main.h"
  26 #include "SAPI.h"
  27 #include "php_globals.h"
  28 #include "ext/standard/info.h"
  29 #include "php_variables.h"
  30 #include "php_ini.h"
  31 
  32 #ifdef PHP_WIN32
  33 # include <process.h>
  34 #else
  35 # define __try
  36 # define __except(val)
  37 # define __declspec(foo)
  38 #endif
  39 
  40 
  41 #ifdef WITH_ZEUS
  42 # include "httpext.h"
  43 # include <errno.h>
  44 # define GetLastError() errno
  45 #endif
  46 
  47 #ifdef PHP_WIN32
  48 #define PHP_ENABLE_SEH
  49 #endif
  50 
  51 /* 
  52 uncomment the following lines to turn off 
  53 exception trapping when running under a debugger 
  54 
  55 #ifdef _DEBUG
  56 #undef PHP_ENABLE_SEH
  57 #endif
  58 */
  59 
  60 #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST POSSIBLE STATUS DESCRIPTION")
  61 #define ISAPI_SERVER_VAR_BUF_SIZE 1024
  62 #define ISAPI_POST_DATA_BUF 1024
  63 
  64 static zend_bool bFilterLoaded=0;
  65 static zend_bool bTerminateThreadsOnError=0;
  66 
  67 static char *isapi_special_server_variable_names[] = {
  68         "ALL_HTTP",
  69         "HTTPS",
  70 #ifndef WITH_ZEUS
  71         "SCRIPT_NAME",
  72 #endif
  73         NULL
  74 };
  75 
  76 #define NUM_SPECIAL_VARS                (sizeof(isapi_special_server_variable_names)/sizeof(char *))
  77 #define SPECIAL_VAR_ALL_HTTP    0
  78 #define SPECIAL_VAR_HTTPS               1
  79 #define SPECIAL_VAR_PHP_SELF    2
  80 
  81 static char *isapi_server_variable_names[] = {
  82         "AUTH_PASSWORD",
  83         "AUTH_TYPE",
  84         "AUTH_USER",
  85         "CONTENT_LENGTH",
  86         "CONTENT_TYPE",
  87         "PATH_TRANSLATED",
  88         "QUERY_STRING",
  89         "REMOTE_ADDR",
  90         "REMOTE_HOST",
  91         "REMOTE_USER",
  92         "REQUEST_METHOD",
  93         "SERVER_NAME",
  94         "SERVER_PORT",
  95         "SERVER_PROTOCOL",
  96         "SERVER_SOFTWARE",
  97 #ifndef WITH_ZEUS
  98         "APPL_MD_PATH",
  99         "APPL_PHYSICAL_PATH",
 100         "INSTANCE_ID",
 101         "INSTANCE_META_PATH",
 102         "LOGON_USER",
 103         "REQUEST_URI",
 104         "URL",
 105 #else
 106         "DOCUMENT_ROOT",
 107 #endif
 108         NULL
 109 };
 110 
 111 
 112 static char *isapi_secure_server_variable_names[] = {
 113         "CERT_COOKIE",
 114         "CERT_FLAGS",
 115         "CERT_ISSUER",
 116         "CERT_KEYSIZE",
 117         "CERT_SECRETKEYSIZE",
 118         "CERT_SERIALNUMBER",
 119         "CERT_SERVER_ISSUER",
 120         "CERT_SERVER_SUBJECT",
 121         "CERT_SUBJECT",
 122         "HTTPS_KEYSIZE",
 123         "HTTPS_SECRETKEYSIZE",
 124         "HTTPS_SERVER_ISSUER",
 125         "HTTPS_SERVER_SUBJECT",
 126         "SERVER_PORT_SECURE",
 127 #ifdef WITH_ZEUS
 128         "SSL_CLIENT_CN",
 129         "SSL_CLIENT_EMAIL",
 130         "SSL_CLIENT_OU",
 131         "SSL_CLIENT_O",
 132         "SSL_CLIENT_L",
 133         "SSL_CLIENT_ST",
 134         "SSL_CLIENT_C",
 135         "SSL_CLIENT_I_CN",
 136         "SSL_CLIENT_I_EMAIL",
 137         "SSL_CLIENT_I_OU",
 138         "SSL_CLIENT_I_O",
 139         "SSL_CLIENT_I_L",
 140         "SSL_CLIENT_I_ST",
 141         "SSL_CLIENT_I_C",       
 142 #endif
 143         NULL
 144 };
 145 
 146 
 147 static void php_info_isapi(ZEND_MODULE_INFO_FUNC_ARGS)
 148 {
 149         char **p;
 150         char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 151         DWORD variable_len;
 152         char **all_variables[] = {
 153                 isapi_server_variable_names,
 154                 isapi_special_server_variable_names,
 155                 isapi_secure_server_variable_names,
 156                 NULL
 157         };
 158         char ***server_variable_names;
 159         LPEXTENSION_CONTROL_BLOCK lpECB;
 160 
 161         lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
 162 
 163         php_info_print_table_start();
 164         php_info_print_table_header(2, "Server Variable", "Value");
 165         server_variable_names = all_variables;
 166         while (*server_variable_names) {
 167                 p = *server_variable_names;
 168                 while (*p) {
 169                         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 170                         if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len)
 171                                 && variable_buf[0]) {
 172                                 php_info_print_table_row(2, *p, variable_buf);
 173                         } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 174                                 char *tmp_variable_buf;
 175 
 176                                 tmp_variable_buf = (char *) emalloc(variable_len);
 177                                 if (lpECB->GetServerVariable(lpECB->ConnID, *p, tmp_variable_buf, &variable_len)
 178                                         && variable_buf[0]) {
 179                                         php_info_print_table_row(2, *p, tmp_variable_buf);
 180                                 }
 181                                 efree(tmp_variable_buf);
 182                         }
 183                         p++;
 184                 }
 185                 server_variable_names++;
 186         }
 187         php_info_print_table_end();
 188 }
 189 
 190 
 191 static zend_module_entry php_isapi_module = {
 192     STANDARD_MODULE_HEADER,
 193         "ISAPI",
 194         NULL,
 195         NULL,
 196         NULL,
 197         NULL,
 198         NULL,
 199         php_info_isapi,
 200     NULL,
 201         STANDARD_MODULE_PROPERTIES
 202 };
 203 
 204 
 205 static int sapi_isapi_ub_write(const char *str, uint str_length TSRMLS_DC)
 206 {
 207         DWORD num_bytes = str_length;
 208         LPEXTENSION_CONTROL_BLOCK ecb;
 209         
 210         ecb = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
 211         if (ecb->WriteClient(ecb->ConnID, (char *) str, &num_bytes, HSE_IO_SYNC) == FALSE) {
 212                 php_handle_aborted_connection();
 213         }
 214         return num_bytes;
 215 }
 216 
 217 
 218 static int sapi_isapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
 219 {
 220         return SAPI_HEADER_ADD;
 221 }
 222 
 223 
 224 
 225 static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC)
 226 {
 227         *total_length += sapi_header->header_len+2;
 228 }
 229 
 230 
 231 static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC)
 232 {
 233         memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len);
 234         *combined_headers_ptr += sapi_header->header_len;
 235         **combined_headers_ptr = '\r';
 236         (*combined_headers_ptr)++;
 237         **combined_headers_ptr = '\n';
 238         (*combined_headers_ptr)++;
 239 }
 240 
 241 
 242 static int sapi_isapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
 243 {
 244         uint total_length = 2;          /* account for the trailing \r\n */
 245         char *combined_headers, *combined_headers_ptr;
 246         LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
 247         HSE_SEND_HEADER_EX_INFO header_info;
 248         sapi_header_struct default_content_type;
 249         char *status_buf = NULL;
 250 
 251         /* Obtain headers length */
 252         if (SG(sapi_headers).send_default_content_type) {
 253                 sapi_get_default_content_type_header(&default_content_type TSRMLS_CC);
 254                 accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC);
 255         }
 256         zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC);
 257 
 258         /* Generate headers */
 259         combined_headers = (char *) emalloc(total_length+1);
 260         combined_headers_ptr = combined_headers;
 261         if (SG(sapi_headers).send_default_content_type) {
 262                 concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC);
 263                 sapi_free_header(&default_content_type); /* we no longer need it */
 264         }
 265         zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC);
 266         *combined_headers_ptr++ = '\r';
 267         *combined_headers_ptr++ = '\n';
 268         *combined_headers_ptr = 0;
 269 
 270         switch (SG(sapi_headers).http_response_code) {
 271                 case 200:
 272                         header_info.pszStatus = "200 OK";
 273                         break;
 274                 case 302:
 275                         header_info.pszStatus = "302 Moved Temporarily";
 276                         break;
 277                 case 401:
 278                         header_info.pszStatus = "401 Authorization Required";
 279                         break;
 280                 default: {
 281                         const char *sline = SG(sapi_headers).http_status_line;
 282                         int sline_len;
 283                         
 284                         /* httpd requires that r->status_line is set to the first digit of
 285                          * the status-code: */
 286                         if (sline && ((sline_len = strlen(sline)) > 12) && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
 287                                 if ((sline_len - 9) > MAX_STATUS_LENGTH) {
 288                                         status_buf = estrndup(sline + 9, MAX_STATUS_LENGTH);
 289                                 } else {
 290                                         status_buf = estrndup(sline + 9, sline_len - 9);
 291                                 }
 292                         } else {
 293                                 status_buf = emalloc(MAX_STATUS_LENGTH + 1);
 294                                 snprintf(status_buf, MAX_STATUS_LENGTH, "%d Undescribed", SG(sapi_headers).http_response_code);
 295                         }
 296                         header_info.pszStatus = status_buf;
 297                         break;
 298                 }
 299         }
 300         header_info.cchStatus = strlen(header_info.pszStatus);
 301         header_info.pszHeader = combined_headers;
 302         header_info.cchHeader = total_length;
 303         header_info.fKeepConn = FALSE;
 304         lpECB->dwHttpStatusCode = SG(sapi_headers).http_response_code;
 305 
 306         lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
 307 
 308         efree(combined_headers);
 309         if (status_buf) {
 310                 efree(status_buf);
 311         }
 312         return SAPI_HEADER_SENT_SUCCESSFULLY;
 313 }
 314 
 315 
 316 static int php_isapi_startup(sapi_module_struct *sapi_module)
 317 {
 318         if (php_module_startup(sapi_module, &php_isapi_module, 1)==FAILURE) {
 319                 return FAILURE;
 320         } else {
 321                 bTerminateThreadsOnError = (zend_bool) INI_INT("isapi.terminate_threads_on_error");
 322                 return SUCCESS;
 323         }
 324 }
 325 
 326 
 327 static int sapi_isapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
 328 {
 329         LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
 330         DWORD read_from_buf=0;
 331         DWORD read_from_input=0;
 332         DWORD total_read=0;
 333 
 334         if ((DWORD) SG(read_post_bytes) < lpECB->cbAvailable) {
 335                 read_from_buf = MIN(lpECB->cbAvailable-SG(read_post_bytes), count_bytes);
 336                 memcpy(buffer, lpECB->lpbData+SG(read_post_bytes), read_from_buf);
 337                 total_read += read_from_buf;
 338         }
 339         if (read_from_buf<count_bytes
 340                 && (SG(read_post_bytes)+read_from_buf) < lpECB->cbTotalBytes) {
 341                 DWORD cbRead=0, cbSize;
 342 
 343                 read_from_input = MIN(count_bytes-read_from_buf, lpECB->cbTotalBytes-SG(read_post_bytes)-read_from_buf);
 344                 while (cbRead < read_from_input) {
 345                         cbSize = read_from_input - cbRead;
 346                         if (!lpECB->ReadClient(lpECB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) {
 347                                 break;
 348                         }
 349                         cbRead += cbSize;
 350                 }
 351                 total_read += cbRead;
 352         }
 353         return total_read;
 354 }
 355 
 356 
 357 static char *sapi_isapi_read_cookies(TSRMLS_D)
 358 {
 359         LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
 360         char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 361         DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 362 
 363         if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) {
 364                 return estrndup(variable_buf, variable_len);
 365         } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
 366                 char *tmp_variable_buf = (char *) emalloc(variable_len+1);
 367 
 368                 if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) {
 369                         tmp_variable_buf[variable_len] = 0;
 370                         return tmp_variable_buf;
 371                 } else {
 372                         efree(tmp_variable_buf);
 373                 }
 374         }
 375         return STR_EMPTY_ALLOC();
 376 }
 377 
 378 
 379 #ifdef WITH_ZEUS
 380 
 381 static void sapi_isapi_register_zeus_ssl_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC)
 382 {
 383         char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 384         DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 385         char static_cons_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 386         /*
 387          * We need to construct the /C=.../ST=...
 388          * DN's for SSL_CLIENT_DN and SSL_CLIENT_I_DN
 389          */
 390         strcpy( static_cons_buf, "/C=" );
 391         if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_C", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
 392                 strlcat( static_cons_buf, static_variable_buf,  ISAPI_SERVER_VAR_BUF_SIZE);
 393         }
 394         strlcat( static_cons_buf, "/ST=",  ISAPI_SERVER_VAR_BUF_SIZE);
 395         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 396         if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_ST", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
 397                 strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE );
 398         }
 399         php_register_variable( "SSL_CLIENT_DN", static_cons_buf, track_vars_array TSRMLS_CC );
 400         
 401         strcpy( static_cons_buf, "/C=" );
 402         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 403         if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_I_C", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
 404                 strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE );
 405         }
 406         strlcat( static_cons_buf, "/ST=", ISAPI_SERVER_VAR_BUF_SIZE);
 407         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 408         if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_I_ST", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
 409                 strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE );
 410         }
 411         php_register_variable( "SSL_CLIENT_I_DN", static_cons_buf, track_vars_array TSRMLS_CC );        
 412 }
 413 
 414 static void sapi_isapi_register_zeus_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC)
 415 {
 416         char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 417         DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 418         DWORD scriptname_len = ISAPI_SERVER_VAR_BUF_SIZE;
 419         DWORD pathinfo_len = 0;
 420         char *strtok_buf = NULL;
 421 
 422         /* Get SCRIPT_NAME, we use this to work out which bit of the URL
 423          * belongs in PHP's version of PATH_INFO
 424          */
 425         lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &scriptname_len);
 426 
 427         /* Adjust Zeus' version of PATH_INFO, set PHP_SELF,
 428          * and generate REQUEST_URI
 429          */
 430         if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
 431 
 432                 /* PHP_SELF is just PATH_INFO */
 433                 php_register_variable( "PHP_SELF", static_variable_buf, track_vars_array TSRMLS_CC );
 434 
 435                 /* Chop off filename to get just the 'real' PATH_INFO' */
 436                 pathinfo_len = variable_len - scriptname_len;
 437                 php_register_variable( "PATH_INFO", static_variable_buf + scriptname_len - 1, track_vars_array TSRMLS_CC );
 438                 /* append query string to give url... extra byte for '?' */
 439                 if ( strlen(lpECB->lpszQueryString) + variable_len + 1 < ISAPI_SERVER_VAR_BUF_SIZE ) {
 440                         /* append query string only if it is present... */
 441                         if ( strlen(lpECB->lpszQueryString) ) {
 442                                 static_variable_buf[ variable_len - 1 ] = '?';
 443                                 strcpy( static_variable_buf + variable_len, lpECB->lpszQueryString );
 444                         }
 445                         php_register_variable( "URL", static_variable_buf, track_vars_array TSRMLS_CC );
 446                         php_register_variable( "REQUEST_URI", static_variable_buf, track_vars_array TSRMLS_CC );
 447                 }
 448         }
 449 
 450         /* Get and adjust PATH_TRANSLATED to what PHP wants */
 451         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 452         if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_TRANSLATED", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
 453                 static_variable_buf[ variable_len - pathinfo_len - 1 ] = '\0';
 454                 php_register_variable( "PATH_TRANSLATED", static_variable_buf, track_vars_array TSRMLS_CC );
 455         }
 456 
 457         /* Bring in the AUTHENTICATION stuff as needed */
 458         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 459         if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_USER", static_variable_buf, &variable_len) && static_variable_buf[0] )  {
 460                 php_register_variable( "PHP_AUTH_USER", static_variable_buf, track_vars_array TSRMLS_CC );
 461         }
 462         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 463         if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_PASSWORD", static_variable_buf, &variable_len) && static_variable_buf[0] )  {
 464                 php_register_variable( "PHP_AUTH_PW", static_variable_buf, track_vars_array TSRMLS_CC );
 465         }
 466         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 467         if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_TYPE", static_variable_buf, &variable_len) && static_variable_buf[0] )  {
 468                 php_register_variable( "AUTH_TYPE", static_variable_buf, track_vars_array TSRMLS_CC );
 469         }
 470         
 471         /* And now, for the SSL variables (if applicable) */
 472         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 473         if ( lpECB->GetServerVariable(lpECB->ConnID, "CERT_COOKIE", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
 474                 sapi_isapi_register_zeus_ssl_variables( lpECB, track_vars_array TSRMLS_CC );
 475         }
 476         /* Copy some of the variables we need to meet Apache specs */
 477         variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 478         if ( lpECB->GetServerVariable(lpECB->ConnID, "SERVER_SOFTWARE", static_variable_buf, &variable_len) && static_variable_buf[0] )  {
 479                 php_register_variable( "SERVER_SIGNATURE", static_variable_buf, track_vars_array TSRMLS_CC );
 480         }
 481 }
 482 #else
 483 
 484 static void sapi_isapi_register_iis_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC)
 485 {
 486         char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 487         char path_info_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 488         DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 489         DWORD scriptname_len = ISAPI_SERVER_VAR_BUF_SIZE;
 490         DWORD pathinfo_len = 0;
 491         HSE_URL_MAPEX_INFO humi;
 492 
 493         /* Get SCRIPT_NAME, we use this to work out which bit of the URL
 494          * belongs in PHP's version of PATH_INFO.  SCRIPT_NAME also becomes PHP_SELF.
 495          */
 496         lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &scriptname_len);
 497         php_register_variable("SCRIPT_FILENAME", SG(request_info).path_translated, track_vars_array TSRMLS_CC);
 498 
 499         /* Adjust IIS' version of PATH_INFO, set PHP_SELF,
 500          * and generate REQUEST_URI
 501          * Get and adjust PATH_TRANSLATED to what PHP wants
 502          */
 503         if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
 504 
 505                 /* Chop off filename to get just the 'real' PATH_INFO' */
 506                 php_register_variable( "ORIG_PATH_INFO", static_variable_buf, track_vars_array TSRMLS_CC );
 507                 pathinfo_len = variable_len - scriptname_len;
 508                 strncpy(path_info_buf, static_variable_buf + scriptname_len - 1, sizeof(path_info_buf)-1);
 509                 php_register_variable( "PATH_INFO", path_info_buf, track_vars_array TSRMLS_CC );
 510                 /* append query string to give url... extra byte for '?' */
 511                 if ( strlen(lpECB->lpszQueryString) + variable_len + 1 < ISAPI_SERVER_VAR_BUF_SIZE ) {
 512                         /* append query string only if it is present... */
 513                         if ( strlen(lpECB->lpszQueryString) ) {
 514                                 static_variable_buf[ variable_len - 1 ] = '?';
 515                                 strcpy( static_variable_buf + variable_len, lpECB->lpszQueryString );
 516                         }
 517                         php_register_variable( "URL", static_variable_buf, track_vars_array TSRMLS_CC );
 518                         php_register_variable( "REQUEST_URI", static_variable_buf, track_vars_array TSRMLS_CC );
 519                 }
 520                 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 521                 if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_TRANSLATED", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
 522                         php_register_variable( "ORIG_PATH_TRANSLATED", static_variable_buf, track_vars_array TSRMLS_CC );
 523                 }
 524                 if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, path_info_buf, &pathinfo_len, (LPDWORD) &humi)) {
 525                         /* Remove trailing \  */
 526                         if (humi.lpszPath[variable_len-2] == '\\') {
 527                                 humi.lpszPath[variable_len-2] = 0;
 528                         }
 529                         php_register_variable("PATH_TRANSLATED", humi.lpszPath, track_vars_array TSRMLS_CC);
 530                 }
 531         }
 532 
 533         static_variable_buf[0] = '/';
 534         static_variable_buf[1] = 0;
 535         variable_len = 2;
 536         if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, static_variable_buf, &variable_len, (LPDWORD) &humi)) {
 537                 /* Remove trailing \  */
 538                 if (humi.lpszPath[variable_len-2] == '\\') {
 539                         humi.lpszPath[variable_len-2] = 0;
 540                 }
 541                 php_register_variable("DOCUMENT_ROOT", humi.lpszPath, track_vars_array TSRMLS_CC);
 542         }
 543 
 544         if (!SG(request_info).auth_user || !SG(request_info).auth_password || 
 545                 !SG(request_info).auth_user[0] || !SG(request_info).auth_password[0]) {
 546                 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 547                 if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_AUTHORIZATION", static_variable_buf, &variable_len)
 548                         && static_variable_buf[0]) {
 549                         php_handle_auth_data(static_variable_buf TSRMLS_CC);
 550                 }
 551         }
 552 
 553         if (SG(request_info).auth_user)  {
 554                 php_register_variable("PHP_AUTH_USER", SG(request_info).auth_user, track_vars_array TSRMLS_CC );
 555         }
 556         if (SG(request_info).auth_password) {
 557                 php_register_variable("PHP_AUTH_PW", SG(request_info).auth_password, track_vars_array TSRMLS_CC );
 558         }
 559 }
 560 #endif
 561 
 562 static void sapi_isapi_register_server_variables2(char **server_variables, LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array, char **recorded_values TSRMLS_DC)
 563 {
 564         char **p=server_variables;
 565         DWORD variable_len;
 566         char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 567         char *variable_buf;
 568 
 569         while (*p) {
 570                 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 571                 if (lpECB->GetServerVariable(lpECB->ConnID, *p, static_variable_buf, &variable_len)
 572                         && static_variable_buf[0]) {
 573                         php_register_variable(*p, static_variable_buf, track_vars_array TSRMLS_CC);
 574                         if (recorded_values) {
 575                                 recorded_values[p-server_variables] = estrndup(static_variable_buf, variable_len);
 576                         }
 577                 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 578                         variable_buf = (char *) emalloc(variable_len+1);
 579                         if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len)
 580                                 && variable_buf[0]) {
 581                                 php_register_variable(*p, variable_buf, track_vars_array TSRMLS_CC);
 582                         }
 583                         if (recorded_values) {
 584                                 recorded_values[p-server_variables] = variable_buf;
 585                         } else {
 586                                 efree(variable_buf);
 587                         }
 588                 } else { /* for compatibility with Apache SAPIs */
 589                         php_register_variable(*p, "", track_vars_array TSRMLS_CC);
 590                 }
 591                 p++;
 592         }
 593 }
 594 
 595 
 596 static void sapi_isapi_register_server_variables(zval *track_vars_array TSRMLS_DC)
 597 {
 598         DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 599         char *variable;
 600         char *strtok_buf = NULL;
 601         char *isapi_special_server_variables[NUM_SPECIAL_VARS];
 602         LPEXTENSION_CONTROL_BLOCK lpECB;
 603 
 604         lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
 605 
 606         /* Register the special ISAPI variables */
 607         memset(isapi_special_server_variables, 0, sizeof(isapi_special_server_variables));
 608         sapi_isapi_register_server_variables2(isapi_special_server_variable_names, lpECB, track_vars_array, isapi_special_server_variables TSRMLS_CC);
 609         if (SG(request_info).cookie_data) {
 610                 php_register_variable("HTTP_COOKIE", SG(request_info).cookie_data, track_vars_array TSRMLS_CC);
 611         }
 612 
 613         /* Register the standard ISAPI variables */
 614         sapi_isapi_register_server_variables2(isapi_server_variable_names, lpECB, track_vars_array, NULL TSRMLS_CC);
 615 
 616         if (isapi_special_server_variables[SPECIAL_VAR_HTTPS]
 617                 && (atoi(isapi_special_server_variables[SPECIAL_VAR_HTTPS])
 618                 || !strcasecmp(isapi_special_server_variables[SPECIAL_VAR_HTTPS], "on"))
 619         ) {
 620                 /* Register SSL ISAPI variables */
 621                 sapi_isapi_register_server_variables2(isapi_secure_server_variable_names, lpECB, track_vars_array, NULL TSRMLS_CC);
 622         }
 623 
 624         if (isapi_special_server_variables[SPECIAL_VAR_HTTPS]) {
 625                 efree(isapi_special_server_variables[SPECIAL_VAR_HTTPS]);
 626         }
 627 
 628 
 629 #ifdef WITH_ZEUS
 630         sapi_isapi_register_zeus_variables(lpECB, track_vars_array TSRMLS_CC);
 631 #else
 632         sapi_isapi_register_iis_variables(lpECB, track_vars_array TSRMLS_CC);
 633 #endif
 634 
 635         /* PHP_SELF support */
 636         if (isapi_special_server_variables[SPECIAL_VAR_PHP_SELF]) {
 637                 php_register_variable("PHP_SELF", isapi_special_server_variables[SPECIAL_VAR_PHP_SELF], track_vars_array TSRMLS_CC);
 638                 efree(isapi_special_server_variables[SPECIAL_VAR_PHP_SELF]);
 639         }
 640 
 641         if (isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP]) {
 642                 /* Register the internal bits of ALL_HTTP */
 643                 variable = php_strtok_r(isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP], "\r\n", &strtok_buf);
 644                 while (variable) {
 645                         char *colon = strchr(variable, ':');
 646 
 647                         if (colon) {
 648                                 char *value = colon+1;
 649 
 650                                 while (*value==' ') {
 651                                         value++;
 652                                 }
 653                                 *colon = 0;
 654                                 php_register_variable(variable, value, track_vars_array TSRMLS_CC);
 655                                 *colon = ':';
 656                         }
 657                         variable = php_strtok_r(NULL, "\r\n", &strtok_buf);
 658                 }
 659                 efree(isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP]);
 660         }
 661 }
 662 
 663 
 664 static sapi_module_struct isapi_sapi_module = {
 665         "isapi",                                                /* name */
 666         "ISAPI",                                                /* pretty name */
 667                                                                         
 668         php_isapi_startup,                              /* startup */
 669         php_module_shutdown_wrapper,    /* shutdown */
 670 
 671         NULL,                                                   /* activate */
 672         NULL,                                                   /* deactivate */
 673 
 674         sapi_isapi_ub_write,                    /* unbuffered write */
 675         NULL,                                                   /* flush */
 676         NULL,                                                   /* get uid */
 677         NULL,                                                   /* getenv */
 678 
 679         php_error,                                              /* error handler */
 680 
 681         sapi_isapi_header_handler,              /* header handler */
 682         sapi_isapi_send_headers,                /* send headers handler */
 683         NULL,                                                   /* send header handler */
 684 
 685         sapi_isapi_read_post,                   /* read POST data */
 686         sapi_isapi_read_cookies,                /* read Cookies */
 687 
 688         sapi_isapi_register_server_variables,   /* register server variables */
 689         NULL,                                                   /* Log message */
 690         NULL,                                                   /* Get request time */
 691         NULL,                                                   /* Child terminate */
 692 
 693         STANDARD_SAPI_MODULE_PROPERTIES
 694 };
 695 
 696 
 697 BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pFilterVersion)
 698 {
 699         bFilterLoaded = 1;
 700         pFilterVersion->dwFilterVersion = HTTP_FILTER_REVISION;
 701         strcpy(pFilterVersion->lpszFilterDesc, isapi_sapi_module.pretty_name);
 702         pFilterVersion->dwFlags= (SF_NOTIFY_AUTHENTICATION | SF_NOTIFY_PREPROC_HEADERS);
 703         return TRUE;
 704 }
 705 
 706 
 707 DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
 708 {
 709         TSRMLS_FETCH();
 710 
 711         switch (notificationType) {
 712                 case SF_NOTIFY_PREPROC_HEADERS:
 713                         SG(request_info).auth_user = NULL;
 714                         SG(request_info).auth_password = NULL;
 715                         SG(request_info).auth_digest = NULL;
 716                         break;
 717                 case SF_NOTIFY_AUTHENTICATION: {
 718                                 char *auth_user = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszUser;
 719                                 char *auth_password = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszPassword;
 720 
 721                                 if (auth_user && auth_user[0]) {
 722                                         SG(request_info).auth_user = estrdup(auth_user);
 723                                 }       
 724                                 if (auth_password && auth_password[0]) {
 725                                         SG(request_info).auth_password = estrdup(auth_password);
 726                                 }
 727                                 return SF_STATUS_REQ_HANDLED_NOTIFICATION;
 728                         }
 729                         break;
 730         }
 731         return SF_STATUS_REQ_NEXT_NOTIFICATION;
 732 }
 733 
 734 
 735 static void init_request_info(LPEXTENSION_CONTROL_BLOCK lpECB TSRMLS_DC)
 736 {
 737         DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
 738         char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
 739 #ifndef WITH_ZEUS
 740         HSE_URL_MAPEX_INFO humi;
 741 #endif
 742 
 743         SG(request_info).request_method = lpECB->lpszMethod;
 744         SG(request_info).query_string = lpECB->lpszQueryString;
 745         SG(request_info).request_uri = lpECB->lpszPathInfo;
 746         SG(request_info).content_type = lpECB->lpszContentType;
 747         SG(request_info).content_length = lpECB->cbTotalBytes;
 748         SG(sapi_headers).http_response_code = 200;  /* I think dwHttpStatusCode is invalid at this stage -RL */
 749         if (!bFilterLoaded) { /* we don't have valid ISAPI Filter information */
 750                 SG(request_info).auth_user = SG(request_info).auth_password = SG(request_info).auth_digest = NULL;
 751         }
 752 
 753 #ifdef WITH_ZEUS
 754         /* PATH_TRANSLATED can contain extra PATH_INFO stuff after the
 755          * file being loaded, so we must use SCRIPT_FILENAME instead
 756          */
 757         if(lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_FILENAME", static_variable_buf, &variable_len)) {
 758                 SG(request_info).path_translated = estrdup(static_variable_buf);
 759         } else 
 760 #else
 761         /* happily, IIS gives us SCRIPT_NAME which is correct (without PATH_INFO stuff)
 762            so we can just map that to the physical path and we have our filename */
 763 
 764         lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len);
 765         if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, static_variable_buf, &variable_len, (LPDWORD) &humi)) {
 766                 SG(request_info).path_translated = estrdup(humi.lpszPath);
 767         } else 
 768 #endif
 769                 /* if mapping fails, default to what the server tells us */
 770                 SG(request_info).path_translated = estrdup(lpECB->lpszPathTranslated);
 771 
 772         /* some server configurations allow '..' to slip through in the
 773            translated path.   We'll just refuse to handle such a path. */
 774         if (strstr(SG(request_info).path_translated,"..")) {
 775                 SG(sapi_headers).http_response_code = 404;
 776                 efree(SG(request_info).path_translated);
 777                 SG(request_info).path_translated = NULL;
 778         }
 779 }
 780 
 781 
 782 static void php_isapi_report_exception(char *message, int message_len TSRMLS_DC)
 783 {
 784         if (!SG(headers_sent)) {
 785                 HSE_SEND_HEADER_EX_INFO header_info;
 786                 LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
 787 
 788                 header_info.pszStatus = "500 Internal Server Error";
 789                 header_info.cchStatus = strlen(header_info.pszStatus);
 790                 header_info.pszHeader = "Content-Type: text/html\r\n\r\n";
 791                 header_info.cchHeader = strlen(header_info.pszHeader);
 792 
 793                 lpECB->dwHttpStatusCode = 500;
 794                 lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
 795                 SG(headers_sent)=1;
 796         }
 797         sapi_isapi_ub_write(message, message_len TSRMLS_CC);
 798 }
 799 
 800 
 801 BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
 802 {
 803         pVer->dwExtensionVersion = HSE_VERSION;
 804 #ifdef WITH_ZEUS
 805         strncpy( pVer->lpszExtensionDesc, isapi_sapi_module.name, HSE_MAX_EXT_DLL_NAME_LEN);
 806 #else
 807         lstrcpyn(pVer->lpszExtensionDesc, isapi_sapi_module.name, HSE_MAX_EXT_DLL_NAME_LEN);
 808 #endif
 809         return TRUE;
 810 }
 811 
 812 
 813 static void my_endthread()
 814 {
 815 #ifdef PHP_WIN32
 816         if (bTerminateThreadsOnError) {
 817                 _endthread();
 818         }
 819 #endif
 820 }
 821 
 822 #ifdef PHP_WIN32
 823 /* ep is accessible only in the context of the __except expression,
 824  * so we have to call this function to obtain it.
 825  */
 826 BOOL exceptionhandler(LPEXCEPTION_POINTERS *e, LPEXCEPTION_POINTERS ep)
 827 {
 828         *e=ep;
 829         return TRUE;
 830 }
 831 #endif
 832 
 833 DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
 834 {
 835         zend_file_handle file_handle;
 836         zend_bool stack_overflown=0;
 837         int retval = FAILURE;
 838 #ifdef PHP_ENABLE_SEH
 839         LPEXCEPTION_POINTERS e;
 840 #endif
 841         TSRMLS_FETCH();
 842 
 843         zend_first_try {
 844 #ifdef PHP_ENABLE_SEH
 845                 __try {
 846 #endif
 847                         init_request_info(lpECB TSRMLS_CC);
 848                         SG(server_context) = lpECB;
 849 
 850                         php_request_startup(TSRMLS_C);
 851 
 852                         file_handle.filename = SG(request_info).path_translated;
 853                         file_handle.free_filename = 0;
 854                         file_handle.type = ZEND_HANDLE_FILENAME;
 855                         file_handle.opened_path = NULL;
 856 
 857                         /* open the script here so we can 404 if it fails */
 858                         if (file_handle.filename)
 859                                 retval = php_fopen_primary_script(&file_handle TSRMLS_CC);
 860 
 861                         if (!file_handle.filename || retval == FAILURE) {
 862                                 SG(sapi_headers).http_response_code = 404;
 863                                 PUTS("No input file specified.\n");
 864                         } else {
 865                                 php_execute_script(&file_handle TSRMLS_CC);
 866                         }
 867 
 868                         if (SG(request_info).cookie_data) {
 869                                 efree(SG(request_info).cookie_data);
 870                         }
 871                         if (SG(request_info).path_translated)
 872                                 efree(SG(request_info).path_translated);
 873 #ifdef PHP_ENABLE_SEH
 874                 } __except(exceptionhandler(&e, GetExceptionInformation())) {
 875                         char buf[1024];
 876                         if (_exception_code()==EXCEPTION_STACK_OVERFLOW) {
 877                                 LPBYTE lpPage;
 878                                 static SYSTEM_INFO si;
 879                                 static MEMORY_BASIC_INFORMATION mi;
 880                                 static DWORD dwOldProtect;
 881 
 882                                 GetSystemInfo(&si);
 883 
 884                                 /* Get page ESP is pointing to */
 885                                 _asm mov lpPage, esp;
 886 
 887                                 /* Get stack allocation base */
 888                                 VirtualQuery(lpPage, &mi, sizeof(mi));
 889 
 890                                 /* Go to the page below the current page */
 891                                 lpPage = (LPBYTE) (mi.BaseAddress) - si.dwPageSize;
 892 
 893                                 /* Free pages below current page */
 894                                 if (!VirtualFree(mi.AllocationBase, (LPBYTE)lpPage - (LPBYTE) mi.AllocationBase, MEM_DECOMMIT)) {
 895                                         _endthread();
 896                                 }
 897 
 898                                 /* Restore the guard page */
 899                                 if (!VirtualProtect(lpPage, si.dwPageSize, PAGE_GUARD | PAGE_READWRITE, &dwOldProtect)) {
 900                                         _endthread();
 901                                 }
 902 
 903                                 CG(unclean_shutdown)=1;
 904                                 _snprintf(buf, sizeof(buf)-1,"PHP has encountered a Stack overflow");
 905                                 php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC);
 906                         } else if (_exception_code()==EXCEPTION_ACCESS_VIOLATION) {
 907                                 _snprintf(buf, sizeof(buf)-1,"PHP has encountered an Access Violation at %p", e->ExceptionRecord->ExceptionAddress);
 908                                 php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC);
 909                                 my_endthread();
 910                         } else {
 911                                 _snprintf(buf, sizeof(buf)-1,"PHP has encountered an Unhandled Exception Code %d at %p", e->ExceptionRecord->ExceptionCode , e->ExceptionRecord->ExceptionAddress);
 912                                 php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC);
 913                                 my_endthread();
 914                         }
 915                 }
 916 #endif
 917 #ifdef PHP_ENABLE_SEH
 918                 __try {
 919                         php_request_shutdown(NULL);
 920                 } __except(EXCEPTION_EXECUTE_HANDLER) {
 921                         my_endthread();
 922                 }
 923 #else
 924                 php_request_shutdown(NULL);
 925 #endif
 926         } zend_catch {
 927                 zend_try {
 928                         php_request_shutdown(NULL);
 929                 } zend_end_try();
 930                 return HSE_STATUS_ERROR;
 931         } zend_end_try();
 932 
 933         return HSE_STATUS_SUCCESS;
 934 }
 935 
 936 
 937 
 938 __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 939 {
 940         switch (fdwReason) {
 941                 case DLL_PROCESS_ATTACH:
 942 #ifdef WITH_ZEUS
 943                         tsrm_startup(128, 1, TSRM_ERROR_LEVEL_CORE, "TSRM.log");
 944 #else
 945                         tsrm_startup(128, 1, TSRM_ERROR_LEVEL_CORE, "C:\\TSRM.log");
 946 #endif
 947                         sapi_startup(&isapi_sapi_module);
 948                         if (isapi_sapi_module.startup) {
 949                                 isapi_sapi_module.startup(&sapi_module);
 950                         }
 951                         break;
 952                 case DLL_THREAD_ATTACH:
 953                         break;
 954                 case DLL_THREAD_DETACH:
 955                         ts_free_thread();
 956                         break;
 957                 case DLL_PROCESS_DETACH:
 958                         if (isapi_sapi_module.shutdown) {
 959                                 isapi_sapi_module.shutdown(&sapi_module);
 960                         }
 961                         sapi_shutdown();
 962                         tsrm_shutdown();
 963                         break;
 964         }
 965         return TRUE;
 966 }
 967 
 968 /*
 969  * Local variables:
 970  * tab-width: 4
 971  * c-basic-offset: 4
 972  * End:
 973  */

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