Back to index

php5  5.3.10
pi3web_sapi.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Pi3Web version 2.0                                                   |
00016    +----------------------------------------------------------------------+
00017    | This file is committed by the Pi3 development group.                 |
00018    | (pi3web.sourceforge.net)                                             |
00019    |                                                                      |
00020    | Author: Holger Zimmermann (zimpel@users.sourceforge.net)             |
00021    +----------------------------------------------------------------------+
00022  */
00023 
00024 /* $Id: pi3web_sapi.c 321634 2012-01-01 13:15:04Z felipe $ */
00025 
00026 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
00027 
00028 #include "php.h"
00029 #include "php_main.h"
00030 #include "php_variables.h"
00031 #include "SAPI.h"
00032 #include "php_globals.h"
00033 #include "ext/standard/info.h"
00034 #include "zend_highlight.h"
00035 #include "zend_indent.h"
00036 #include "zend_alloc.h"
00037 #include "ext/standard/basic_functions.h"
00038 #include "TSRM/TSRM.h"
00039 #include "PiAPI.h"
00040 #include "Pi3API.h"
00041 
00042 #include "pi3web_sapi.h"
00043 
00044 #define PI3WEB_SERVER_VAR_BUF_SIZE 1024
00045 
00046 int IWasLoaded=0;
00047 
00048 
00049 static void php_info_pi3web(ZEND_MODULE_INFO_FUNC_ARGS)
00050 {
00051        char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE];
00052        DWORD variable_len;
00053        LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
00054        PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID);
00055        PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 ); 
00056 
00057        PUTS("<table border=0 cellpadding=3 cellspacing=1 width=600 align=center>\n");
00058        PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">Pi3Web Server Information</th></tr>\n");
00059        php_info_print_table_header(2, "Information Field", "Value");
00060        php_info_print_table_row(2, "Pi3Web SAPI module version", "$Id: pi3web_sapi.c 321634 2012-01-01 13:15:04Z felipe $");
00061        php_info_print_table_row(2, "Server Name Stamp", HTTPCore_getServerStamp());
00062        snprintf(variable_buf, 511, "%d", HTTPCore_debugEnabled());
00063        php_info_print_table_row(2, "Debug Enabled", variable_buf);
00064        PIPlatform_getCurrentDirectory( variable_buf, PI3WEB_SERVER_VAR_BUF_SIZE);
00065        php_info_print_table_row(2, "Current Path", variable_buf);
00066        if (lpCB->GetServerVariable(lpCB->ConnID, "SERVER_NAME", variable_buf, &variable_len)
00067               && variable_buf[0]) {
00068               php_info_print_table_row(2, "Main Virtual Hostname", variable_buf);
00069        };
00070        snprintf(variable_buf, 511, "%d", PIPlatform_getProcessId());
00071        php_info_print_table_row(2, "Server PID", variable_buf);
00072        php_info_print_table_row(2, "Server Platform", PIPlatform_getDescription());
00073 
00074        PUTS("</table><br />");     
00075 
00076        PUTS("<table border=0 cellpadding=3 cellspacing=1 width=600 align=center>\n");
00077        PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">HTTP Request Information</th></tr>\n");
00078        php_info_print_table_row(2, "HTTP Request Line", lpCB->lpszReq);
00079        PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">HTTP Headers</th></tr>\n");
00080        php_info_print_table_header(2, "Server Variable", "Value");
00081 
00082        /* --- loop over all registered server variables --- */
00083        for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
00084        {      
00085               PCHAR pKey;
00086               PIDBIterator_current( pIter, &pKey );
00087               if ( !pKey ) { /* sanity */ continue; };                                                                 
00088 
00089               variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
00090               if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len)
00091                      && variable_buf[0]) {
00092                      php_info_print_table_row(2, pKey, variable_buf);
00093               } else if (PIPlatform_getLastError() == PIAPI_EINVAL) {
00094                      char *tmp_variable_buf;
00095 
00096                      tmp_variable_buf = (char *) emalloc(variable_len);
00097                      if (lpCB->GetServerVariable(lpCB->ConnID, pKey, tmp_variable_buf, &variable_len)
00098                             && variable_buf[0]) {
00099                             php_info_print_table_row(2, pKey, tmp_variable_buf);
00100                      }
00101                      efree(tmp_variable_buf);
00102               }
00103        }
00104 
00105        PUTS("</table>");
00106 }
00107 
00108 
00109 static zend_module_entry php_pi3web_module = {
00110        STANDARD_MODULE_HEADER,
00111        "PI3WEB",
00112        NULL,
00113        NULL,
00114        NULL,
00115        NULL,
00116        NULL,
00117        php_info_pi3web,
00118        NULL,
00119        STANDARD_MODULE_PROPERTIES
00120 };
00121 
00122 
00123 static int zend_pi3web_ub_write(const char *str, uint str_length TSRMLS_DC)
00124 {
00125        DWORD num_bytes = str_length;
00126        LPCONTROL_BLOCK cb;
00127        
00128        cb = (LPCONTROL_BLOCK) SG(server_context);
00129 
00130        if ( !IWasLoaded ) return 0;
00131        cb->WriteClient(cb->ConnID, (char *) str, &num_bytes, 0 );
00132 
00133        if (num_bytes != str_length)
00134               php_handle_aborted_connection();
00135        return num_bytes;
00136 }
00137 
00138 
00139 static int sapi_pi3web_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
00140 {
00141        return SAPI_HEADER_ADD;
00142 }
00143 
00144 
00145 static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC)
00146 {
00147        *total_length += sapi_header->header_len+2;
00148 }
00149 
00150 
00151 static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC)
00152 {
00153        memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len);
00154        *combined_headers_ptr += sapi_header->header_len;
00155        **combined_headers_ptr = '\r';
00156        (*combined_headers_ptr)++;
00157        **combined_headers_ptr = '\n';
00158        (*combined_headers_ptr)++;
00159 }
00160 
00161 
00162 static int sapi_pi3web_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
00163 {
00164        uint total_length = 2;             /* account for the trailing \r\n */
00165        char *combined_headers, *combined_headers_ptr;
00166        LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
00167        sapi_header_struct default_content_type;
00168        
00169        if ( !IWasLoaded ) return SAPI_HEADER_SENT_SUCCESSFULLY;
00170 
00171 
00172        if (SG(sapi_headers).send_default_content_type) {
00173               sapi_get_default_content_type_header(&default_content_type TSRMLS_CC);
00174               accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC);
00175        }
00176        zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC);
00177 
00178        /* Generate headers */
00179        combined_headers = (char *) emalloc(total_length+1);
00180        combined_headers_ptr = combined_headers;
00181        if (SG(sapi_headers).send_default_content_type) {
00182               concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC);
00183               sapi_free_header(&default_content_type); /* we no longer need it */
00184        }
00185        zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC);
00186        *combined_headers_ptr++ = '\r';
00187        *combined_headers_ptr++ = '\n';
00188        *combined_headers_ptr = 0;
00189 
00190        lpCB->dwHttpStatusCode = SG(sapi_headers).http_response_code;
00191        lpCB->SendHeaderFunction(lpCB->ConnID, &total_length, (LPDWORD) combined_headers);
00192 
00193        efree(combined_headers);
00194        if (SG(sapi_headers).http_status_line) {
00195               efree(SG(sapi_headers).http_status_line);
00196               SG(sapi_headers).http_status_line = 0;
00197        }
00198        return SAPI_HEADER_SENT_SUCCESSFULLY;
00199 }
00200 
00201 
00202 static int php_pi3web_startup(sapi_module_struct *sapi_module)
00203 {
00204        if (php_module_startup(sapi_module, &php_pi3web_module, 1)==FAILURE) {
00205               return FAILURE;
00206        } else {
00207               return SUCCESS;
00208        }
00209 }
00210 
00211 
00212 static int sapi_pi3web_read_post(char *buffer, uint count_bytes TSRMLS_DC)
00213 {
00214        LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
00215        DWORD read_from_buf=0;
00216        DWORD read_from_input=0;
00217        DWORD total_read=0;
00218 
00219        if ((DWORD)SG(read_post_bytes) < lpCB->cbAvailable) {
00220               read_from_buf = MIN(lpCB->cbAvailable-SG(read_post_bytes), count_bytes);
00221               memcpy(buffer, lpCB->lpbData+SG(read_post_bytes), read_from_buf);
00222               total_read += read_from_buf;
00223        }
00224        if (read_from_buf<count_bytes
00225               && (SG(read_post_bytes)+read_from_buf) < lpCB->cbTotalBytes) {
00226               DWORD cbRead=0, cbSize;
00227 
00228               read_from_input = MIN(count_bytes-read_from_buf, lpCB->cbTotalBytes-SG(read_post_bytes)-read_from_buf);
00229               while (cbRead < read_from_input) {
00230                      cbSize = read_from_input - cbRead;
00231                      if (!lpCB->ReadClient(lpCB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) {
00232                             break;
00233                      }
00234                      cbRead += cbSize;
00235               }
00236               total_read += cbRead;
00237        }
00238        
00239        /* removed after re-testing POST with Pi3Web 2.0.2 */
00240        /* SG(read_post_bytes) += total_read; */
00241        return total_read;
00242 }
00243 
00244 
00245 static char *sapi_pi3web_read_cookies(TSRMLS_D)
00246 {
00247        LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
00248        char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE];
00249        DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
00250 
00251        if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) {
00252               return estrndup(variable_buf, variable_len);
00253        } else if (PIPlatform_getLastError()==PIAPI_EINVAL) {
00254               char *tmp_variable_buf = (char *) emalloc(variable_len+1);
00255 
00256               if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) {
00257                      tmp_variable_buf[variable_len] = 0;
00258                      return tmp_variable_buf;
00259               } else {
00260                      efree(tmp_variable_buf);
00261               }
00262        }
00263        return NULL;
00264 }
00265 
00266 static void init_request_info(LPCONTROL_BLOCK lpCB TSRMLS_DC)
00267 {
00268        SG(server_context) = lpCB;
00269        SG(request_info).request_method  = lpCB->lpszMethod;
00270        SG(request_info).query_string    = lpCB->lpszQueryString;
00271        SG(request_info).path_translated = lpCB->lpszPathTranslated;
00272        SG(request_info).request_uri     = lpCB->lpszUri;
00273        SG(request_info).content_type    = lpCB->lpszContentType;
00274        SG(request_info).content_length  = lpCB->cbTotalBytes;
00275        SG(request_info).auth_user       = (lpCB->lpszUser) ? (char *)estrdup((const char *)(lpCB->lpszUser)) : 0;
00276        SG(request_info).auth_password   = (lpCB->lpszPassword) ? (char *)estrdup((const char *)(lpCB->lpszPassword)) : 0;
00277        SG(sapi_headers).http_response_code = 200;
00278 }
00279 
00280 static void sapi_pi3web_register_variables(zval *track_vars_array TSRMLS_DC)
00281 {
00282        char static_variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE];
00283        char *variable_buf;
00284        DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
00285        LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context);
00286        PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID);
00287        PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 ); 
00288 
00289        /* --- loop over all registered server variables --- */                      
00290        for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
00291        {      
00292               PCHAR pKey;
00293               PIDBIterator_current( pIter, &pKey );
00294               if ( !pKey ) { /* sanity */ continue; };                                                                 
00295 
00296               variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
00297               if (lpCB->GetServerVariable(lpCB->ConnID, pKey, static_variable_buf, &variable_len)
00298                      && (variable_len > 1)) {
00299                      php_register_variable(pKey, static_variable_buf, track_vars_array TSRMLS_CC);
00300               } else if (PIPlatform_getLastError()==PIAPI_EINVAL) {
00301                      variable_buf = (char *) emalloc(variable_len);
00302                      if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len)) {
00303                             php_register_variable(pKey, variable_buf, track_vars_array TSRMLS_CC);
00304                      }
00305                      efree(variable_buf);
00306               }
00307 
00308        }
00309 
00310 
00311        /* PHP_SELF support */
00312        variable_len = PI3WEB_SERVER_VAR_BUF_SIZE;
00313        if (lpCB->GetServerVariable(lpCB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len)
00314               && (variable_len > 1)) {
00315               php_register_variable("PHP_SELF", static_variable_buf, track_vars_array TSRMLS_CC);
00316        }
00317 }
00318 
00319 static sapi_module_struct pi3web_sapi_module = {
00320        "pi3web",                          /* name */
00321        "PI3WEB",                          /* pretty name */
00322 
00323        php_pi3web_startup,                /* startup */
00324        php_module_shutdown_wrapper,              /* shutdown */
00325        NULL,                              /* activate */
00326        NULL,                              /* deactivate */
00327        zend_pi3web_ub_write,                     /* unbuffered write */
00328        NULL,                              /* flush */
00329        NULL,                              /* get uid */
00330        NULL,                              /* getenv */
00331        php_error,                         /* error handler */
00332        sapi_pi3web_header_handler,        /* header handler */
00333        sapi_pi3web_send_headers,          /* send headers handler */
00334        NULL,                              /* send header handler */
00335        sapi_pi3web_read_post,                    /* read POST data */
00336        sapi_pi3web_read_cookies,          /* read Cookies */
00337        sapi_pi3web_register_variables,    /* register server variables */
00338        NULL,                              /* Log message */
00339        NULL,                              /* Get request time */
00340        NULL,                              /* Child terminate */
00341 
00342        STANDARD_SAPI_MODULE_PROPERTIES
00343 };
00344 
00345 MODULE_API DWORD PHP5_wrapper(LPCONTROL_BLOCK lpCB)
00346 {
00347        zend_file_handle file_handle = {0};
00348        int iRet = PIAPI_COMPLETED;
00349        TSRMLS_FETCH();
00350 
00351        zend_first_try {
00352               file_handle.filename = lpCB->lpszFileName;
00353               file_handle.free_filename = 0;
00354               file_handle.type = ZEND_HANDLE_FILENAME;
00355               file_handle.opened_path = NULL;
00356 
00357               init_request_info(lpCB TSRMLS_CC);
00358               php_request_startup(TSRMLS_C);
00359 
00360               switch ( lpCB->dwBehavior ) {
00361                      case PHP_MODE_STANDARD:
00362                             iRet = ( php_execute_script( &file_handle TSRMLS_CC ) ) ?
00363                                    PIAPI_COMPLETED : PIAPI_ERROR;
00364                             break;
00365                      case PHP_MODE_HIGHLIGHT: {
00366                             zend_syntax_highlighter_ini syntax_highlighter_ini;
00367                             if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS )
00368                                    {
00369                                    php_get_highlight_struct( &syntax_highlighter_ini );
00370                                    zend_highlight( &syntax_highlighter_ini TSRMLS_CC );
00371                                    }
00372                             else
00373                                    {
00374                                    iRet = PIAPI_ERROR;
00375                                    };
00376                             };
00377                             break;
00378                      case PHP_MODE_INDENT: {
00379                             sapi_header_line ctr = {0};
00380 
00381                             ctr.line = "Content-Type: text/plain";
00382                             ctr.line_len = strlen(ctr.line);
00383                             
00384                             sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
00385                        }
00386                             if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS )
00387                                    {
00388                                    zend_indent();
00389                                    }
00390                             else
00391                                    {
00392                                    iRet = PIAPI_ERROR;
00393                                    };
00394                             break;
00395                      case PHP_MODE_LINT:
00396                             iRet = (php_lint_script(&file_handle TSRMLS_CC) == SUCCESS) ?
00397                                    PIAPI_COMPLETED : PIAPI_ERROR;
00398                             break;
00399                      default:
00400                             iRet = PIAPI_ERROR;;
00401                      }
00402 
00403               if (SG(request_info).cookie_data) {
00404                      efree(SG(request_info).cookie_data);
00405               };
00406 
00407               php_request_shutdown(NULL);
00408        } zend_catch {
00409               iRet = PIAPI_ERROR;
00410        } zend_end_try();
00411        return iRet;
00412 }
00413 
00414 MODULE_API BOOL PHP5_startup() {
00415        tsrm_startup(1, 1, 0, NULL);
00416        sapi_startup(&pi3web_sapi_module);
00417        if (pi3web_sapi_module.startup) {
00418               pi3web_sapi_module.startup(&pi3web_sapi_module);
00419        };
00420        IWasLoaded = 1;
00421        return IWasLoaded;
00422 };
00423 
00424 MODULE_API BOOL PHP5_shutdown() {
00425        if (pi3web_sapi_module.shutdown) {
00426               pi3web_sapi_module.shutdown(&pi3web_sapi_module);
00427        };
00428        sapi_shutdown();
00429        tsrm_shutdown();
00430        IWasLoaded = 0;
00431        return !IWasLoaded;
00432 };
00433 
00434 /*
00435  * Local variables:
00436  * tab-width: 4
00437  * c-basic-offset: 4
00438  * End:
00439  */