root/sapi/pi3web/pi3web_sapi.c

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

DEFINITIONS

This source file includes following definitions.
  1. php_info_pi3web
  2. zend_pi3web_ub_write
  3. sapi_pi3web_header_handler
  4. accumulate_header_length
  5. concat_header
  6. sapi_pi3web_send_headers
  7. php_pi3web_startup
  8. sapi_pi3web_read_post
  9. sapi_pi3web_read_cookies
  10. init_request_info
  11. sapi_pi3web_register_variables
  12. PHP5_wrapper
  13. PHP5_startup
  14. PHP5_shutdown

   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    | Pi3Web version 2.0                                                   |
  16    +----------------------------------------------------------------------+
  17    | This file is committed by the Pi3 development group.                 |
  18    | (pi3web.sourceforge.net)                                             |
  19    |                                                                      |
  20    | Author: Holger Zimmermann (zimpel@users.sourceforge.net)             |
  21    +----------------------------------------------------------------------+
  22  */
  23 
  24 /* $Id$ */
  25 
  26 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
  27 
  28 #include "php.h"
  29 #include "php_main.h"
  30 #include "php_variables.h"
  31 #include "SAPI.h"
  32 #include "php_globals.h"
  33 #include "ext/standard/info.h"
  34 #include "zend_highlight.h"
  35 #include "zend_indent.h"
  36 #include "zend_alloc.h"
  37 #include "ext/standard/basic_functions.h"
  38 #include "TSRM/TSRM.h"
  39 #include "PiAPI.h"
  40 #include "Pi3API.h"
  41 
  42 #include "pi3web_sapi.h"
  43 
  44 #define PI3WEB_SERVER_VAR_BUF_SIZE 1024
  45 
  46 int IWasLoaded=0;
  47 
  48 
  49 static void php_info_pi3web(ZEND_MODULE_INFO_FUNC_ARGS)
  50 {
  51         char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE];
  52         DWORD variable_len;
  53         LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
  54         PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID);
  55         PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 );   
  56 
  57         PUTS("<table border=0 cellpadding=3 cellspacing=1 width=600 align=center>\n");
  58         PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">Pi3Web Server Information</th></tr>\n");
  59         php_info_print_table_header(2, "Information Field", "Value");
  60         php_info_print_table_row(2, "Pi3Web SAPI module version", "$Id$");
  61         php_info_print_table_row(2, "Server Name Stamp", HTTPCore_getServerStamp());
  62         snprintf(variable_buf, 511, "%d", HTTPCore_debugEnabled());
  63         php_info_print_table_row(2, "Debug Enabled", variable_buf);
  64         PIPlatform_getCurrentDirectory( variable_buf, PI3WEB_SERVER_VAR_BUF_SIZE);
  65         php_info_print_table_row(2, "Current Path", variable_buf);
  66         if (lpCB->GetServerVariable(lpCB->ConnID, "SERVER_NAME", variable_buf, &variable_len)
  67                 && variable_buf[0]) {
  68                 php_info_print_table_row(2, "Main Virtual Hostname", variable_buf);
  69         };
  70         snprintf(variable_buf, 511, "%d", PIPlatform_getProcessId());
  71         php_info_print_table_row(2, "Server PID", variable_buf);
  72         php_info_print_table_row(2, "Server Platform", PIPlatform_getDescription());
  73 
  74         PUTS("</table><br />"); 
  75 
  76         PUTS("<table border=0 cellpadding=3 cellspacing=1 width=600 align=center>\n");
  77         PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">HTTP Request Information</th></tr>\n");
  78         php_info_print_table_row(2, "HTTP Request Line", lpCB->lpszReq);
  79         PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">HTTP Headers</th></tr>\n");
  80         php_info_print_table_header(2, "Server Variable", "Value");
  81 
  82         /* --- loop over all registered server variables --- */
  83         for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
  84         {       
  85                 PCHAR pKey;
  86                 PIDBIterator_current( pIter, &pKey );
  87                 if ( !pKey ) { /* sanity */ continue; };                                                                                
  88 
  89                 variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
  90                 if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len)
  91                         && variable_buf[0]) {
  92                         php_info_print_table_row(2, pKey, variable_buf);
  93                 } else if (PIPlatform_getLastError() == PIAPI_EINVAL) {
  94                         char *tmp_variable_buf;
  95 
  96                         tmp_variable_buf = (char *) emalloc(variable_len);
  97                         if (lpCB->GetServerVariable(lpCB->ConnID, pKey, tmp_variable_buf, &variable_len)
  98                                 && variable_buf[0]) {
  99                                 php_info_print_table_row(2, pKey, tmp_variable_buf);
 100                         }
 101                         efree(tmp_variable_buf);
 102                 }
 103         }
 104 
 105         PUTS("</table>");
 106 }
 107 
 108 
 109 static zend_module_entry php_pi3web_module = {
 110         STANDARD_MODULE_HEADER,
 111         "PI3WEB",
 112         NULL,
 113         NULL,
 114         NULL,
 115         NULL,
 116         NULL,
 117         php_info_pi3web,
 118         NULL,
 119         STANDARD_MODULE_PROPERTIES
 120 };
 121 
 122 
 123 static int zend_pi3web_ub_write(const char *str, uint str_length TSRMLS_DC)
 124 {
 125         DWORD num_bytes = str_length;
 126         LPCONTROL_BLOCK cb;
 127         
 128         cb = (LPCONTROL_BLOCK) SG(server_context);
 129 
 130         if ( !IWasLoaded ) return 0;
 131         cb->WriteClient(cb->ConnID, (char *) str, &num_bytes, 0 );
 132 
 133         if (num_bytes != str_length)
 134                 php_handle_aborted_connection();
 135         return num_bytes;
 136 }
 137 
 138 
 139 static int sapi_pi3web_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
 140 {
 141         return SAPI_HEADER_ADD;
 142 }
 143 
 144 
 145 static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC)
 146 {
 147         *total_length += sapi_header->header_len+2;
 148 }
 149 
 150 
 151 static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC)
 152 {
 153         memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len);
 154         *combined_headers_ptr += sapi_header->header_len;
 155         **combined_headers_ptr = '\r';
 156         (*combined_headers_ptr)++;
 157         **combined_headers_ptr = '\n';
 158         (*combined_headers_ptr)++;
 159 }
 160 
 161 
 162 static int sapi_pi3web_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
 163 {
 164         uint total_length = 2;          /* account for the trailing \r\n */
 165         char *combined_headers, *combined_headers_ptr;
 166         LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
 167         sapi_header_struct default_content_type;
 168         
 169         if ( !IWasLoaded ) return SAPI_HEADER_SENT_SUCCESSFULLY;
 170 
 171 
 172         if (SG(sapi_headers).send_default_content_type) {
 173                 sapi_get_default_content_type_header(&default_content_type TSRMLS_CC);
 174                 accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC);
 175         }
 176         zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC);
 177 
 178         /* Generate headers */
 179         combined_headers = (char *) emalloc(total_length+1);
 180         combined_headers_ptr = combined_headers;
 181         if (SG(sapi_headers).send_default_content_type) {
 182                 concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC);
 183                 sapi_free_header(&default_content_type); /* we no longer need it */
 184         }
 185         zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC);
 186         *combined_headers_ptr++ = '\r';
 187         *combined_headers_ptr++ = '\n';
 188         *combined_headers_ptr = 0;
 189 
 190         lpCB->dwHttpStatusCode = SG(sapi_headers).http_response_code;
 191         lpCB->SendHeaderFunction(lpCB->ConnID, &total_length, (LPDWORD) combined_headers);
 192 
 193         efree(combined_headers);
 194         if (SG(sapi_headers).http_status_line) {
 195                 efree(SG(sapi_headers).http_status_line);
 196                 SG(sapi_headers).http_status_line = 0;
 197         }
 198         return SAPI_HEADER_SENT_SUCCESSFULLY;
 199 }
 200 
 201 
 202 static int php_pi3web_startup(sapi_module_struct *sapi_module)
 203 {
 204         if (php_module_startup(sapi_module, &php_pi3web_module, 1)==FAILURE) {
 205                 return FAILURE;
 206         } else {
 207                 return SUCCESS;
 208         }
 209 }
 210 
 211 
 212 static int sapi_pi3web_read_post(char *buffer, uint count_bytes TSRMLS_DC)
 213 {
 214         LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
 215         DWORD read_from_buf=0;
 216         DWORD read_from_input=0;
 217         DWORD total_read=0;
 218 
 219         if ((DWORD)SG(read_post_bytes) < lpCB->cbAvailable) {
 220                 read_from_buf = MIN(lpCB->cbAvailable-SG(read_post_bytes), count_bytes);
 221                 memcpy(buffer, lpCB->lpbData+SG(read_post_bytes), read_from_buf);
 222                 total_read += read_from_buf;
 223         }
 224         if (read_from_buf<count_bytes
 225                 && (SG(read_post_bytes)+read_from_buf) < lpCB->cbTotalBytes) {
 226                 DWORD cbRead=0, cbSize;
 227 
 228                 read_from_input = MIN(count_bytes-read_from_buf, lpCB->cbTotalBytes-SG(read_post_bytes)-read_from_buf);
 229                 while (cbRead < read_from_input) {
 230                         cbSize = read_from_input - cbRead;
 231                         if (!lpCB->ReadClient(lpCB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) {
 232                                 break;
 233                         }
 234                         cbRead += cbSize;
 235                 }
 236                 total_read += cbRead;
 237         }
 238         
 239         /* removed after re-testing POST with Pi3Web 2.0.2 */
 240         /* SG(read_post_bytes) += total_read; */
 241         return total_read;
 242 }
 243 
 244 
 245 static char *sapi_pi3web_read_cookies(TSRMLS_D)
 246 {
 247         LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
 248         char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE];
 249         DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
 250 
 251         if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) {
 252                 return estrndup(variable_buf, variable_len);
 253         } else if (PIPlatform_getLastError()==PIAPI_EINVAL) {
 254                 char *tmp_variable_buf = (char *) emalloc(variable_len+1);
 255 
 256                 if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) {
 257                         tmp_variable_buf[variable_len] = 0;
 258                         return tmp_variable_buf;
 259                 } else {
 260                         efree(tmp_variable_buf);
 261                 }
 262         }
 263         return NULL;
 264 }
 265 
 266 static void init_request_info(LPCONTROL_BLOCK lpCB TSRMLS_DC)
 267 {
 268         SG(server_context) = lpCB;
 269         SG(request_info).request_method  = lpCB->lpszMethod;
 270         SG(request_info).query_string    = lpCB->lpszQueryString;
 271         SG(request_info).path_translated = lpCB->lpszPathTranslated;
 272         SG(request_info).request_uri     = lpCB->lpszUri;
 273         SG(request_info).content_type    = lpCB->lpszContentType;
 274         SG(request_info).content_length  = lpCB->cbTotalBytes;
 275         SG(request_info).auth_user       = (lpCB->lpszUser) ? (char *)estrdup((const char *)(lpCB->lpszUser)) : 0;
 276         SG(request_info).auth_password   = (lpCB->lpszPassword) ? (char *)estrdup((const char *)(lpCB->lpszPassword)) : 0;
 277         SG(sapi_headers).http_response_code = 200;
 278 }
 279 
 280 static void sapi_pi3web_register_variables(zval *track_vars_array TSRMLS_DC)
 281 {
 282         char static_variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE];
 283         char *variable_buf;
 284         DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
 285         LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
 286         PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID);
 287         PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 );   
 288 
 289         /* --- loop over all registered server variables --- */                         
 290         for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
 291         {       
 292                 PCHAR pKey;
 293                 PIDBIterator_current( pIter, &pKey );
 294                 if ( !pKey ) { /* sanity */ continue; };                                                                                
 295 
 296                 variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
 297                 if (lpCB->GetServerVariable(lpCB->ConnID, pKey, static_variable_buf, &variable_len)
 298                         && (variable_len > 1)) {
 299                         php_register_variable(pKey, static_variable_buf, track_vars_array TSRMLS_CC);
 300                 } else if (PIPlatform_getLastError()==PIAPI_EINVAL) {
 301                         variable_buf = (char *) emalloc(variable_len);
 302                         if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len)) {
 303                                 php_register_variable(pKey, variable_buf, track_vars_array TSRMLS_CC);
 304                         }
 305                         efree(variable_buf);
 306                 }
 307 
 308         }
 309 
 310 
 311         /* PHP_SELF support */
 312         variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
 313         if (lpCB->GetServerVariable(lpCB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len)
 314                 && (variable_len > 1)) {
 315                 php_register_variable("PHP_SELF", static_variable_buf, track_vars_array TSRMLS_CC);
 316         }
 317 }
 318 
 319 static sapi_module_struct pi3web_sapi_module = {
 320         "pi3web",                               /* name */
 321         "PI3WEB",                               /* pretty name */
 322 
 323         php_pi3web_startup,                     /* startup */
 324         php_module_shutdown_wrapper,            /* shutdown */
 325         NULL,                                   /* activate */
 326         NULL,                                   /* deactivate */
 327         zend_pi3web_ub_write,                   /* unbuffered write */
 328         NULL,                                   /* flush */
 329         NULL,                                   /* get uid */
 330         NULL,                                   /* getenv */
 331         php_error,                              /* error handler */
 332         sapi_pi3web_header_handler,             /* header handler */
 333         sapi_pi3web_send_headers,               /* send headers handler */
 334         NULL,                                   /* send header handler */
 335         sapi_pi3web_read_post,                  /* read POST data */
 336         sapi_pi3web_read_cookies,               /* read Cookies */
 337         sapi_pi3web_register_variables, /* register server variables */
 338         NULL,                                   /* Log message */
 339         NULL,                                   /* Get request time */
 340         NULL,                                   /* Child terminate */
 341 
 342         STANDARD_SAPI_MODULE_PROPERTIES
 343 };
 344 
 345 MODULE_API DWORD PHP5_wrapper(LPCONTROL_BLOCK lpCB)
 346 {
 347         zend_file_handle file_handle = {0};
 348         int iRet = PIAPI_COMPLETED;
 349         TSRMLS_FETCH();
 350 
 351         zend_first_try {
 352                 file_handle.filename = lpCB->lpszFileName;
 353                 file_handle.free_filename = 0;
 354                 file_handle.type = ZEND_HANDLE_FILENAME;
 355                 file_handle.opened_path = NULL;
 356 
 357                 init_request_info(lpCB TSRMLS_CC);
 358                 php_request_startup(TSRMLS_C);
 359 
 360                 switch ( lpCB->dwBehavior ) {
 361                         case PHP_MODE_STANDARD:
 362                                 iRet = ( php_execute_script( &file_handle TSRMLS_CC ) ) ?
 363                                         PIAPI_COMPLETED : PIAPI_ERROR;
 364                                 break;
 365                         case PHP_MODE_HIGHLIGHT: {
 366                                 zend_syntax_highlighter_ini syntax_highlighter_ini;
 367                                 if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS )
 368                                         {
 369                                         php_get_highlight_struct( &syntax_highlighter_ini );
 370                                         zend_highlight( &syntax_highlighter_ini TSRMLS_CC );
 371                                         }
 372                                 else
 373                                         {
 374                                         iRet = PIAPI_ERROR;
 375                                         };
 376                                 };
 377                                 break;
 378                         case PHP_MODE_INDENT: {
 379                                 sapi_header_line ctr = {0};
 380 
 381                                 ctr.line = "Content-Type: text/plain";
 382                                 ctr.line_len = strlen(ctr.line);
 383                                 
 384                                 sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
 385                           }
 386                                 if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS )
 387                                         {
 388                                         zend_indent();
 389                                         }
 390                                 else
 391                                         {
 392                                         iRet = PIAPI_ERROR;
 393                                         };
 394                                 break;
 395                         case PHP_MODE_LINT:
 396                                 iRet = (php_lint_script(&file_handle TSRMLS_CC) == SUCCESS) ?
 397                                         PIAPI_COMPLETED : PIAPI_ERROR;
 398                                 break;
 399                         default:
 400                                 iRet = PIAPI_ERROR;;
 401                         }
 402 
 403                 if (SG(request_info).cookie_data) {
 404                         efree(SG(request_info).cookie_data);
 405                 };
 406 
 407                 php_request_shutdown(NULL);
 408         } zend_catch {
 409                 iRet = PIAPI_ERROR;
 410         } zend_end_try();
 411         return iRet;
 412 }
 413 
 414 MODULE_API BOOL PHP5_startup() {
 415         tsrm_startup(1, 1, 0, NULL);
 416         sapi_startup(&pi3web_sapi_module);
 417         if (pi3web_sapi_module.startup) {
 418                 pi3web_sapi_module.startup(&pi3web_sapi_module);
 419         };
 420         IWasLoaded = 1;
 421         return IWasLoaded;
 422 };
 423 
 424 MODULE_API BOOL PHP5_shutdown() {
 425         if (pi3web_sapi_module.shutdown) {
 426                 pi3web_sapi_module.shutdown(&pi3web_sapi_module);
 427         };
 428         sapi_shutdown();
 429         tsrm_shutdown();
 430         IWasLoaded = 0;
 431         return !IWasLoaded;
 432 };
 433 
 434 /*
 435  * Local variables:
 436  * tab-width: 4
 437  * c-basic-offset: 4
 438  * End:
 439  */

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