/* +----------------------------------------------------------------------+ | 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. | +----------------------------------------------------------------------+ | Author: | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_fcgi.h" #include #include "multipart_parser.h" #include "multipart_parser.c" static int le_fcgi; const zend_function_entry fcgi_functions[] = { PHP_FE(confirm_fcgi_compiled, NULL) /* For testing, remove later. */ PHP_FE(fcgi_init, NULL) PHP_FE(fcgi_fini, NULL) PHP_FE(fcgi_accept, NULL) PHP_FE(fcgi_finish, NULL) PHP_FE(fcgi_getparam, NULL) PHP_FE(fcgi_echo, NULL) PHP_FE(fcgi_getcontent, NULL) PHP_FE_END /* Must be the last line in fcgi_functions[] */ }; zend_module_entry fcgi_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "fcgi", fcgi_functions, PHP_MINIT(fcgi), PHP_MSHUTDOWN(fcgi), PHP_RINIT(fcgi), /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN(fcgi), /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO(fcgi), #if ZEND_MODULE_API_NO >= 20010901 PHP_FCGI_VERSION, #endif STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_FCGI ZEND_GET_MODULE(fcgi) #endif PHP_MINIT_FUNCTION(fcgi) { /* If you have INI entries, uncomment these lines REGISTER_INI_ENTRIES(); */ return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(fcgi) { /* uncomment this line if you have INI entries UNREGISTER_INI_ENTRIES(); */ return SUCCESS; } PHP_RINIT_FUNCTION(fcgi) { return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(fcgi) { return SUCCESS; } PHP_MINFO_FUNCTION(fcgi) { php_info_print_table_start(); php_info_print_table_header(2, "fcgi support", "enabled"); php_info_print_table_end(); } PHP_FUNCTION(confirm_fcgi_compiled) { char *arg = NULL; int arg_len, len; char *strg; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { return; } len = sprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "fcgi", arg); RETURN_STRINGL(strg, len, 0); } PHP_FUNCTION(fcgi_init) { } PHP_FUNCTION(fcgi_fini) { } static FCGX_Stream* stInstream; static FCGX_Stream* stOutstream; static FCGX_Stream* stErrstream; static FCGX_ParamArray stParams; PHP_FUNCTION(fcgi_accept) { int ret = FCGX_Accept(&stInstream,&stOutstream,&stErrstream,&stParams); if(stInstream == NULL) { RETVAL_LONG(-1); } if(stOutstream == NULL) { RETVAL_LONG(-1); } if(stErrstream == NULL) { RETVAL_LONG(-1); } RETVAL_LONG(ret); } PHP_FUNCTION(fcgi_getparam) { char *arg = NULL; int arg_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { return; } const char* ret = FCGX_GetParam(arg, stParams); ret = (ret == NULL) ? "" : ret; char* result = estrdup(ret); RETURN_STRINGL(result,strlen(result),0); } static int content_length() { const char* pbuf = FCGX_GetParam("CONTENT_LENGTH", stParams); if(pbuf) { if(strlen(pbuf) == 0) return 0; else return atoi(pbuf); } else { return 0; } } //////////////////////////////////////////////////////////////////////////////////// // rfc1867 callback static char* g_pcontent = NULL; int read_header_name(multipart_parser* p, const char *at, size_t length) { // printf("%.*s: ", length, at); return 0; } // rfc1867 callback int read_header_value(multipart_parser* p, const char *at, size_t length) { // printf("%.*s\n", length, at); if (NULL == g_pcontent) return 0; char* pbegin = strstr(at, "\""); if (!pbegin) return 0; ++pbegin; const char* pend = strstr(pbegin, "\""); if (!pend) return 0; const int len = pend - pbegin; strncat(g_pcontent, pbegin, len); strcat(g_pcontent, "="); return 0; } // rfc1867 callback int read_part_data(multipart_parser* p, const char *at, size_t length) { // printf("%.*s\n", length, at); if (NULL == g_pcontent) return 0; strncat(g_pcontent, at, length); strcat(g_pcontent, "&"); return 0; } PHP_FUNCTION(fcgi_getcontent) { int con_len = content_length(); if(con_len) { char* pCon = (char*)malloc(con_len + 1); con_len = FCGX_GetStr(pCon, con_len, stInstream); pCon[con_len] = '\0'; // post webform boundary proccess const char* pbuf = FCGX_GetParam("CONTENT_TYPE", stParams); if(pbuf) { const char* boundary_begin = strstr(pbuf, "boundary"); if (boundary_begin) { boundary_begin = boundary_begin + strlen("boundary"); boundary_begin = strstr(boundary_begin, "="); if (boundary_begin) { ++boundary_begin; const int boundary_len = strlen(boundary_begin) + 3; char* boundary_value = (char*)malloc(boundary_len); if (boundary_value) { memset(boundary_value, 0, boundary_len); strcat(boundary_value, "--"); strcat(boundary_value, boundary_begin); g_pcontent = (char*)malloc(con_len + 1); memset(g_pcontent, 0, con_len + 1); multipart_parser_settings callbacks; memset(&callbacks, 0, sizeof(multipart_parser_settings)); callbacks.on_header_field = read_header_name; callbacks.on_header_value = read_header_value; callbacks.on_part_data = read_part_data; multipart_parser* parser = multipart_parser_init(boundary_value, &callbacks); if (parser) { multipart_parser_execute(parser, pCon, con_len); multipart_parser_free(parser); } if(g_pcontent != NULL) { int len = strlen(g_pcontent); if(len > 0 && g_pcontent[len - 1] == '&') { g_pcontent[len - 1] = '\0'; } } char* result = estrdup(g_pcontent); free(g_pcontent); g_pcontent = NULL; RETURN_STRINGL(result, strlen(result),0); } } } } // normal proccess char* result = estrdup(pCon); RETURN_STRINGL(result,strlen(result),0); } else { char* result = estrdup(""); RETURN_STRINGL(result,strlen(result),0); } } PHP_FUNCTION(fcgi_echo) { char *arg = NULL; int arg_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { return; } if(arg != NULL) { FCGX_PutS(arg,stOutstream); } } PHP_FUNCTION(fcgi_finish) { FCGX_Finish(); }