/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2015 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Pi3Web version 2.0 | +----------------------------------------------------------------------+ | This file is committed by the Pi3 development group. | | (pi3web.sourceforge.net) | | | | Author: Holger Zimmermann (zimpel@users.sourceforge.net) | +----------------------------------------------------------------------+ */ /* $Id$ */ #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS #include "php.h" #include "php_main.h" #include "php_variables.h" #include "SAPI.h" #include "php_globals.h" #include "ext/standard/info.h" #include "zend_highlight.h" #include "zend_indent.h" #include "zend_alloc.h" #include "ext/standard/basic_functions.h" #include "TSRM/TSRM.h" #include "PiAPI.h" #include "Pi3API.h" #include "pi3web_sapi.h" #define PI3WEB_SERVER_VAR_BUF_SIZE 1024 int IWasLoaded=0; static void php_info_pi3web(ZEND_MODULE_INFO_FUNC_ARGS) { char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE]; DWORD variable_len; LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID); PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 ); PUTS("\n"); PUTS("\n"); php_info_print_table_header(2, "Information Field", "Value"); php_info_print_table_row(2, "Pi3Web SAPI module version", "$Id$"); php_info_print_table_row(2, "Server Name Stamp", HTTPCore_getServerStamp()); snprintf(variable_buf, 511, "%d", HTTPCore_debugEnabled()); php_info_print_table_row(2, "Debug Enabled", variable_buf); PIPlatform_getCurrentDirectory( variable_buf, PI3WEB_SERVER_VAR_BUF_SIZE); php_info_print_table_row(2, "Current Path", variable_buf); if (lpCB->GetServerVariable(lpCB->ConnID, "SERVER_NAME", variable_buf, &variable_len) && variable_buf[0]) { php_info_print_table_row(2, "Main Virtual Hostname", variable_buf); }; snprintf(variable_buf, 511, "%d", PIPlatform_getProcessId()); php_info_print_table_row(2, "Server PID", variable_buf); php_info_print_table_row(2, "Server Platform", PIPlatform_getDescription()); PUTS("
Pi3Web Server Information

"); PUTS("\n"); PUTS("\n"); php_info_print_table_row(2, "HTTP Request Line", lpCB->lpszReq); PUTS("\n"); php_info_print_table_header(2, "Server Variable", "Value"); /* --- loop over all registered server variables --- */ for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) ) { PCHAR pKey; PIDBIterator_current( pIter, &pKey ); if ( !pKey ) { /* sanity */ continue; }; variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len) && variable_buf[0]) { php_info_print_table_row(2, pKey, variable_buf); } else if (PIPlatform_getLastError() == PIAPI_EINVAL) { char *tmp_variable_buf; tmp_variable_buf = (char *) emalloc(variable_len); if (lpCB->GetServerVariable(lpCB->ConnID, pKey, tmp_variable_buf, &variable_len) && variable_buf[0]) { php_info_print_table_row(2, pKey, tmp_variable_buf); } efree(tmp_variable_buf); } } PUTS("
HTTP Request Information
HTTP Headers
"); } static zend_module_entry php_pi3web_module = { STANDARD_MODULE_HEADER, "PI3WEB", NULL, NULL, NULL, NULL, NULL, php_info_pi3web, NULL, STANDARD_MODULE_PROPERTIES }; static int zend_pi3web_ub_write(const char *str, uint str_length TSRMLS_DC) { DWORD num_bytes = str_length; LPCONTROL_BLOCK cb; cb = (LPCONTROL_BLOCK) SG(server_context); if ( !IWasLoaded ) return 0; cb->WriteClient(cb->ConnID, (char *) str, &num_bytes, 0 ); if (num_bytes != str_length) php_handle_aborted_connection(); return num_bytes; } static int sapi_pi3web_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) { return SAPI_HEADER_ADD; } static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC) { *total_length += sapi_header->header_len+2; } static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC) { memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len); *combined_headers_ptr += sapi_header->header_len; **combined_headers_ptr = '\r'; (*combined_headers_ptr)++; **combined_headers_ptr = '\n'; (*combined_headers_ptr)++; } static int sapi_pi3web_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) { uint total_length = 2; /* account for the trailing \r\n */ char *combined_headers, *combined_headers_ptr; LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); sapi_header_struct default_content_type; if ( !IWasLoaded ) return SAPI_HEADER_SENT_SUCCESSFULLY; if (SG(sapi_headers).send_default_content_type) { sapi_get_default_content_type_header(&default_content_type TSRMLS_CC); accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC); } zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC); /* Generate headers */ combined_headers = (char *) emalloc(total_length+1); combined_headers_ptr = combined_headers; if (SG(sapi_headers).send_default_content_type) { concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC); sapi_free_header(&default_content_type); /* we no longer need it */ } zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC); *combined_headers_ptr++ = '\r'; *combined_headers_ptr++ = '\n'; *combined_headers_ptr = 0; lpCB->dwHttpStatusCode = SG(sapi_headers).http_response_code; lpCB->SendHeaderFunction(lpCB->ConnID, &total_length, (LPDWORD) combined_headers); efree(combined_headers); if (SG(sapi_headers).http_status_line) { efree(SG(sapi_headers).http_status_line); SG(sapi_headers).http_status_line = 0; } return SAPI_HEADER_SENT_SUCCESSFULLY; } static int php_pi3web_startup(sapi_module_struct *sapi_module) { if (php_module_startup(sapi_module, &php_pi3web_module, 1)==FAILURE) { return FAILURE; } else { return SUCCESS; } } static int sapi_pi3web_read_post(char *buffer, uint count_bytes TSRMLS_DC) { LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); DWORD read_from_buf=0; DWORD read_from_input=0; DWORD total_read=0; if ((DWORD)SG(read_post_bytes) < lpCB->cbAvailable) { read_from_buf = MIN(lpCB->cbAvailable-SG(read_post_bytes), count_bytes); memcpy(buffer, lpCB->lpbData+SG(read_post_bytes), read_from_buf); total_read += read_from_buf; } if (read_from_bufcbTotalBytes) { DWORD cbRead=0, cbSize; read_from_input = MIN(count_bytes-read_from_buf, lpCB->cbTotalBytes-SG(read_post_bytes)-read_from_buf); while (cbRead < read_from_input) { cbSize = read_from_input - cbRead; if (!lpCB->ReadClient(lpCB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) { break; } cbRead += cbSize; } total_read += cbRead; } /* removed after re-testing POST with Pi3Web 2.0.2 */ /* SG(read_post_bytes) += total_read; */ return total_read; } static char *sapi_pi3web_read_cookies(TSRMLS_D) { LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE]; DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) { return estrndup(variable_buf, variable_len); } else if (PIPlatform_getLastError()==PIAPI_EINVAL) { char *tmp_variable_buf = (char *) emalloc(variable_len+1); if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) { tmp_variable_buf[variable_len] = 0; return tmp_variable_buf; } else { efree(tmp_variable_buf); } } return NULL; } static void init_request_info(LPCONTROL_BLOCK lpCB TSRMLS_DC) { SG(server_context) = lpCB; SG(request_info).request_method = lpCB->lpszMethod; SG(request_info).query_string = lpCB->lpszQueryString; SG(request_info).path_translated = lpCB->lpszPathTranslated; SG(request_info).request_uri = lpCB->lpszUri; SG(request_info).content_type = lpCB->lpszContentType; SG(request_info).content_length = lpCB->cbTotalBytes; SG(request_info).auth_user = (lpCB->lpszUser) ? (char *)estrdup((const char *)(lpCB->lpszUser)) : 0; SG(request_info).auth_password = (lpCB->lpszPassword) ? (char *)estrdup((const char *)(lpCB->lpszPassword)) : 0; SG(sapi_headers).http_response_code = 200; } static void sapi_pi3web_register_variables(zval *track_vars_array TSRMLS_DC) { char static_variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE]; char *variable_buf; DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID); PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 ); /* --- loop over all registered server variables --- */ for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) ) { PCHAR pKey; PIDBIterator_current( pIter, &pKey ); if ( !pKey ) { /* sanity */ continue; }; variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; if (lpCB->GetServerVariable(lpCB->ConnID, pKey, static_variable_buf, &variable_len) && (variable_len > 1)) { php_register_variable(pKey, static_variable_buf, track_vars_array TSRMLS_CC); } else if (PIPlatform_getLastError()==PIAPI_EINVAL) { variable_buf = (char *) emalloc(variable_len); if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len)) { php_register_variable(pKey, variable_buf, track_vars_array TSRMLS_CC); } efree(variable_buf); } } /* PHP_SELF support */ variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; if (lpCB->GetServerVariable(lpCB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len) && (variable_len > 1)) { php_register_variable("PHP_SELF", static_variable_buf, track_vars_array TSRMLS_CC); } } static sapi_module_struct pi3web_sapi_module = { "pi3web", /* name */ "PI3WEB", /* pretty name */ php_pi3web_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ NULL, /* activate */ NULL, /* deactivate */ zend_pi3web_ub_write, /* unbuffered write */ NULL, /* flush */ NULL, /* get uid */ NULL, /* getenv */ php_error, /* error handler */ sapi_pi3web_header_handler, /* header handler */ sapi_pi3web_send_headers, /* send headers handler */ NULL, /* send header handler */ sapi_pi3web_read_post, /* read POST data */ sapi_pi3web_read_cookies, /* read Cookies */ sapi_pi3web_register_variables, /* register server variables */ NULL, /* Log message */ NULL, /* Get request time */ NULL, /* Child terminate */ STANDARD_SAPI_MODULE_PROPERTIES }; MODULE_API DWORD PHP5_wrapper(LPCONTROL_BLOCK lpCB) { zend_file_handle file_handle = {0}; int iRet = PIAPI_COMPLETED; TSRMLS_FETCH(); zend_first_try { file_handle.filename = lpCB->lpszFileName; file_handle.free_filename = 0; file_handle.type = ZEND_HANDLE_FILENAME; file_handle.opened_path = NULL; init_request_info(lpCB TSRMLS_CC); php_request_startup(TSRMLS_C); switch ( lpCB->dwBehavior ) { case PHP_MODE_STANDARD: iRet = ( php_execute_script( &file_handle TSRMLS_CC ) ) ? PIAPI_COMPLETED : PIAPI_ERROR; break; case PHP_MODE_HIGHLIGHT: { zend_syntax_highlighter_ini syntax_highlighter_ini; if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS ) { php_get_highlight_struct( &syntax_highlighter_ini ); zend_highlight( &syntax_highlighter_ini TSRMLS_CC ); } else { iRet = PIAPI_ERROR; }; }; break; case PHP_MODE_INDENT: { sapi_header_line ctr = {0}; ctr.line = "Content-Type: text/plain"; ctr.line_len = strlen(ctr.line); sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); } if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS ) { zend_indent(); } else { iRet = PIAPI_ERROR; }; break; case PHP_MODE_LINT: iRet = (php_lint_script(&file_handle TSRMLS_CC) == SUCCESS) ? PIAPI_COMPLETED : PIAPI_ERROR; break; default: iRet = PIAPI_ERROR;; } if (SG(request_info).cookie_data) { efree(SG(request_info).cookie_data); }; php_request_shutdown(NULL); } zend_catch { iRet = PIAPI_ERROR; } zend_end_try(); return iRet; } MODULE_API BOOL PHP5_startup() { tsrm_startup(1, 1, 0, NULL); sapi_startup(&pi3web_sapi_module); if (pi3web_sapi_module.startup) { pi3web_sapi_module.startup(&pi3web_sapi_module); }; IWasLoaded = 1; return IWasLoaded; }; MODULE_API BOOL PHP5_shutdown() { if (pi3web_sapi_module.shutdown) { pi3web_sapi_module.shutdown(&pi3web_sapi_module); }; sapi_shutdown(); tsrm_shutdown(); IWasLoaded = 0; return !IWasLoaded; }; /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */