From 98d0faa2eeddfe260bd337c69b00734b7cff2375 Mon Sep 17 00:00:00 2001 From: mataes2007 Date: Sat, 26 Nov 2011 15:54:11 +0000 Subject: added mBot git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@217 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- mBot/src/libphp/phpenv.cpp | 1502 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1502 insertions(+) create mode 100644 mBot/src/libphp/phpenv.cpp (limited to 'mBot/src/libphp/phpenv.cpp') diff --git a/mBot/src/libphp/phpenv.cpp b/mBot/src/libphp/phpenv.cpp new file mode 100644 index 0000000..cf82192 --- /dev/null +++ b/mBot/src/libphp/phpenv.cpp @@ -0,0 +1,1502 @@ +/* + +Miranda Scripting Plugin for Miranda-IM +Copyright 2004-2006 Piotr Pawluczuk (www.pawluczuk.info) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "libphp.h" +#include "internals.h" +#include "svar.h" +#include "phpenv.h" + +#define UH(s) (unsigned char*)(s) +#define PHPWS php_error_docref(NULL TSRMLS_CC,E_WARNING, +#define PHPWE );return +#define PHPWSE(s) php_error_docref(NULL TSRMLS_CC,E_WARNING,s);return + +void php_phpenv_sapi_error(int type, const char *fmt, ...); +int php_phpenv_ub_write(const char *str, unsigned int str_length TSRMLS_DC); +void php_phpenv_log_message(char *message); +int php_phpenv_startup(sapi_module_struct *sapi_module); +char* php_phpenv_read_cookies(TSRMLS_D); +void php_phpenv_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC); +void php_phpenv_flush(void *server_context); +int php_phpenv_read_post(char *buffer, uint count_bytes TSRMLS_DC); +int php_phpenv_deactivate(TSRMLS_D); +char* php_phpenv_getenv(char *name, size_t name_len TSRMLS_DC); +void php_phpenv_register_variables(zval *track_vars_array TSRMLS_DC); +int php_set_ini_entry(char *entry, char *value, int stage); +int php_update_ini_file(TSRMLS_D); + +///////////////////////////////////// +//GLOBALS +///////////////////////////////////// +extern LPHP_FREE g_free; +extern LPHP_MALLOC g_malloc; +extern LPHP_OUTPUT g_std_out; +extern LPHP_OUTPUT g_std_err; +extern CRITICAL_SECTION g_csection; + +extern sVARmap g_vars; +extern sFCNmap g_fcns; +sTHRlst g_php_threads; + +unsigned long g_stat_num_executions = 0; +unsigned long g_stat_num_errors = 0; +unsigned long g_stat_num_threads = 0; + +unsigned long g_tls_key = 0; + +zend_function_entry* g_zend_functions = NULL; + +/* declaration of functions to be exported */ +ZEND_FUNCTION(mt_echo); +ZEND_FUNCTION(mt_clock); +ZEND_FUNCTION(mt_getvar); +ZEND_FUNCTION(mt_delvar); +ZEND_FUNCTION(mt_setvar); +ZEND_FUNCTION(mt_isvar); +ZEND_FUNCTION(mt_call); +PHP_MINIT_FUNCTION(mt_module_entry); + +/* compiled function list so Zend knows what's in this module */ +zend_function_entry mt_functions[] = +{ + PHP_FE(mt_echo,NULL)// UH("s")) //ok + PHP_FE(mt_clock,NULL)// UH(""))//ok + PHP_FE(mt_getvar,NULL)// UH("s")) + PHP_FE(mt_delvar,NULL)// UH("s")) + PHP_FE(mt_setvar,NULL)// UH("ssl")) + PHP_FE(mt_isvar,NULL) + PHP_FE(mt_call,NULL)// UH("s|ssss")) + //////////////////////////////// + {NULL, NULL, NULL} +}; + +/* compiled module information */ +static zend_module_entry mt_module_entry = +{ + STANDARD_MODULE_HEADER, + "libphp (www.piopawlu.net)", + mt_functions, + PHP_MINIT(mt_module_entry), + NULL, + NULL, + NULL, + NULL, + NO_VERSION_YET, + STANDARD_MODULE_PROPERTIES +}; + +PHP_MINIT_FUNCTION(mt_module_entry) +{ + if(g_php_module && ((zend_module_entry*)g_php_module)->module_startup_func) + { + ((zend_module_entry*)g_php_module)->module_startup_func(INIT_FUNC_ARGS_PASSTHRU); + } + return SUCCESS; +} + +static sapi_module_struct phpenv_sapi_module = { + "libphp 1.0.0.8", /* name */ + "libPHP", /* pretty name */ + + php_phpenv_startup, /* startup */ + php_module_shutdown_wrapper, /* shutdown */ + + NULL, /* activate */ + php_phpenv_deactivate, /* deactivate */ + + php_phpenv_ub_write, /* unbuffered write */ + php_phpenv_flush, /* flush */ + NULL, /* get uid */ + php_phpenv_getenv, /* getenv */ + + php_phpenv_sapi_error, /* error handler */ + + NULL, /* header handler */ + NULL, /* send headers handler */ + php_phpenv_send_header, /* send header handler */ + + php_phpenv_read_post, /* read POST data */ + php_phpenv_read_cookies, /* read Cookies */ + + php_phpenv_register_variables, /* register server variables */ + php_phpenv_log_message, /* Log message */ + + NULL, /* Block interruptions */ + NULL, /* Unblock interruptions */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + +ZEND_FUNCTION(mt_echo) +{ + char* str; + long strl; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str,&strl) == FAILURE){ + PHPWSE("mt_echo takes exactly one string parameter!"); + } + + g_std_out(str,strl); + RETURN_LONG(1); +} + +ZEND_FUNCTION(mt_clock) +{ + RETURN_LONG(clock()); +} + +ZEND_FUNCTION(mt_call) +{ + char *cmd=NULL, *par1=NULL, *par2=NULL, *par3=NULL, *par4=NULL, *tmp=NULL; + long cmd_l=0, par1_l=0, par2_l=0, par3_l=0, par4_l=0; + long np = 0; + long rt = 0; + void* rv = NULL; + const lphp_funct* f; + sFCNmap::const_iterator it; + + #define xtol(a) strtol(a,NULL,0) + + sPHPENV* ctx = (sPHPENV*)SG(server_context); + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ssss", + &cmd,&cmd_l,&par1,&par1_l,&par2,&par2_l,&par3,&par3_l,&par4,&par4_l) == FAILURE || !cmd_l || strlen(cmd)<1) + { + PHPWSE("Not enough parameters given!"); + return; + } + + it = g_fcns.find(cmd); + if(it == g_fcns.end() || !it->second.ptr){ + PHPWS "Function %s is not defined!", cmd PHPWE; + return; + } + f = &it->second; + + rt = f->pinfo & 0x03; + + try + { + switch(f->lp) + { + case 0: + { + LPHP_GEN0 g0 = (LPHP_GEN0)f->ptr; + rv = g0(ctx->c_param); + break; + } + case 1: + { + LPHP_GEN1 g1 = (LPHP_GEN1)f->ptr; + rv = g1(ctx->c_param,(f->pinfo & 0x0C)?((void*)par1):((void*)xtol(par1))); + break; + } + case 2: + { + LPHP_GEN2 g2 = (LPHP_GEN2)f->ptr; + rv = g2(ctx->c_param,(f->pinfo & 0x0C)?((void*)par1):((void*)xtol(par1)), + (f->pinfo & 0x30)?((void*)par2):((void*)xtol(par2))); + break; + } + case 3: + { + LPHP_GEN3 g3 = (LPHP_GEN3)f->ptr; + rv = g3(ctx->c_param,(f->pinfo & 0x0C)?((void*)par1):((void*)xtol(par1)), + (f->pinfo & 0x30)?((void*)par2):((void*)xtol(par2)), + (f->pinfo & 0xC0)?((void*)par3):((void*)xtol(par3))); + break; + } + case 4: + { + LPHP_GEN4 g4 = (LPHP_GEN4)f->ptr; + rv = g4(ctx->c_param,(f->pinfo & 0x000C)?((void*)par1):((void*)atol(par1)), + (f->pinfo & 0x0030)?((void*)par2):((void*)xtol(par2)), + (f->pinfo & 0x00C0)?((void*)par3):((void*)xtol(par3)), + (f->pinfo & 0x0300)?((void*)par4):((void*)xtol(par4))); + break; + } + default: + PHPWS "You can't call a function taking %u parameters!", f->lp PHPWE; + return; + } + + if(rt == 0){ + RETURN_LONG((long)rv); + }else if(rt == 1){ + if(rv){ + tmp = estrdup((const char*)rv); + g_free((void*)rv); + RETURN_STRING(tmp,FALSE); + }else{ + RETURN_FALSE; + } + }else{ + RETURN_LONG(1); + } + } + catch(...) + { + PHPWS "An exception occured while executing the %s function!", cmd PHPWE; + return; + } +} + + +int return_var(zval* out,unsigned char* data) +{ + int kt; + char* key; + char* str; + double* dbl; + ulong nk=0; + ulong* tmp; + zval* val; + int toff = 0; + unsigned char* od = data; + + while(*data != 'X') + { + val = NULL; + if(*data == '%'){ + kt = 0; + data++; + }else if(*data == '>'){ + kt = HASH_KEY_IS_STRING; + tmp = (ulong*)(++data); + key = (char*)data + 4; + data += *tmp + 4; + }else{ + kt = HASH_KEY_IS_LONG; + tmp = (ulong*)(++data); + nk = *tmp; + data += 4; + } + + val = NULL; + MAKE_STD_ZVAL(val); + + switch(*data++) + { + case 'S': + tmp = (ulong*)(data); + data += 4; + str = (char*)data; + ZVAL_STRINGL(val,str,*tmp,1); + data += *tmp; + break; + case 'L': + tmp = (ulong*)(data); + data += 4; + ZVAL_LONG(val,*tmp); + break; + case 'D': + dbl = (double*)(data); + data += 8; + ZVAL_DOUBLE(val,*dbl); + break; + case 'B': + ZVAL_BOOL(val,*data++); + break; + case 'N': + ZVAL_NULL(val); + break; + case 'A': + if(array_init(val)==FAILURE || !(toff = return_var(val,data))){ + return 0; + }else{ + data += toff; + } + break; + default: + return 0; + }//switch + if(kt == HASH_KEY_IS_STRING){ + add_assoc_zval(out,key,val); + }else if(kt == HASH_KEY_IS_LONG){ + add_index_zval(out,nk,val); + }else{ + add_next_index_zval(out,val); + } + }data++; + + return (data - od); +} + +ZEND_FUNCTION(mt_getvar) +{ + cLock(g_csection); + + char* vname = NULL; + long vnl = 0; + const sVar* sv = NULL; + sVARmap::const_iterator it; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&vname,&vnl) == FAILURE){ + PHPWSE("You've not provided the numeber of parameters the function needs!"); + return; + } + + it = g_vars.find(vname); + + if(it == g_vars.end()){ + PHPWS "Variable %s is not defined!", vname PHPWE; + } + + sv = &it->second; + + if(sv->type == SV_LONG || sv->type == SV_WORD){ + RETVAL_LONG(sv->lval); + }else if(sv->type == SV_LPOINTER){ + RETVAL_LONG(*((long*)sv->lval)); + }else if(sv->type == SV_DOUBLE){ + RETVAL_DOUBLE(sv->dval); + }else if(sv->type == SV_STRING){ + RETVAL_STRING(sv->str.val,1); + }else if(sv->type == SV_ARRAY){ + if(array_init(return_value)==FAILURE){ + PHPWSE("Could not initialize array!"); + } + return_var(return_value,(unsigned char*)(sv->str.val + 1)); + }else if(sv->type == SV_NULL){ + RETVAL_NULL(); + return; + }else{ + PHPWS "Unknown variable type %u!", sv->type PHPWE; + RETURN_FALSE; + } +} + +ZEND_FUNCTION(mt_delvar) +{ + char* vname = NULL; + long vnl = 0; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&vname,&vnl) == FAILURE || !vnl){ + PHPWSE("No parameters given!"); + } + + if(LPHP_DelVar(vname)){ + RETURN_LONG(1); + }else{ + PHPWS "Variable %s wasn't defined!", vname PHPWE; + } +} + +ZEND_FUNCTION(mt_isvar) +{ + char* vname = NULL; + long vnl = 0; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&vname,&vnl) == FAILURE || !vnl){ + PHPWSE("No parameters given!"); + } + + RETURN_LONG(LPHP_IsVar(vname)); +} + +int make_var(zval* v,cutMemf* mf,bool keep_idx) +{ + unsigned long t1; + unsigned long t2; + + if(v->type == IS_STRING){ + t1 = v->value.str.len; + mf->putc('S'); + mf->write(&t1,4); + mf->write(v->value.str.val,t1); + }else if(v->type == IS_LONG){ + mf->putc('L'); + mf->write(&v->value.lval,4); + }else if(v->type == IS_DOUBLE){ + mf->putc('D'); + mf->write(&v->value.dval,8); + }else if(v->type == IS_BOOL){ + mf->putc('B'); + mf->write(&v->value.lval,1); + }else if(v->type == IS_NULL){ + mf->putc('N'); + }else if(v->type == IS_ARRAY){ + HashPosition pos; + zval** aitem; + zval* aval; + uint str_len; + char *str; + ulong num_key = 0; + + mf->putc('A'); + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(v),&pos); + while(zend_hash_get_current_data_ex(Z_ARRVAL_P(v),(void**)&aitem,&pos) == SUCCESS) + { + aval = *aitem; + if(!aval)return 0; + + if(!keep_idx){ + mf->putc('%'); + }else{ + t2 = zend_hash_get_current_key_ex(Z_ARRVAL_P(v),&str,&str_len,&num_key,0,&pos); + if(t2 == HASH_KEY_IS_STRING){ + mf->putc('>'); + str_len++; + mf->write(&str_len,4); + mf->write(str,str_len-1); + mf->putc('\0'); + }else{ + mf->putc('@'); + mf->write(&num_key,4); + } + } + + make_var(aval,mf,keep_idx); + zend_hash_move_forward_ex(Z_ARRVAL_P(v), &pos); + } + mf->putc('X'); + }else{ + return 1; + } + return 1; +} + +ZEND_FUNCTION(mt_setvar) +{ + char* vname = NULL; + long vnl = 0; + zval* val; + void* mem; + zend_bool create = 1; + zend_bool keep_idx = 0; + cutMemf mf; + sVar sv; + sVARmap::iterator it; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|bb",&vname,&vnl,&val,&create,&keep_idx) == FAILURE){ + PHPWSE("Not enough parameters given!"); + return; + } + + if(!create && (it = g_vars.find(vname)) == g_vars.end()){ + RETURN_LONG(0); + } + + if(val->type == IS_STRING){ + sVariable(&sv,SV_STRING,(char*)val->value.str.val,0,0); + }else if(val->type == IS_DOUBLE){ + sVariable(&sv,val->value.dval,0); + }else if(val->type == IS_LONG || val->type == IS_BOOL){ + sVariable(&sv,SV_LONG,(void*)(val->value.lval),0,0); + }else if(val->type == IS_ARRAY){ + if(!mf.create(512) || !make_var(val,&mf,keep_idx!=0)){ + PHPWSE("Could not create variable!"); + } + mf.putc(0); + mem = svar_malloc(vnl = mf.size()); + if(!mem){ + mf.close(); + PHPWSE("Could not allocate memory!"); + }else{ + memcpy(mem,mf.getdata(),vnl); + mf.close(); + sVariable(&sv,SV_ARRAY,mem,vnl,0); + } + }else if(val->type == IS_NULL){ + sVariable(&sv,SV_NULL,0,0,0); + }else{ + PHPWSE("Unsupported variable type!"); + } + + if(!create){ + it->second = sv; + }else{ + g_vars[vname] = sv; + vnl = 1; + } + + if(vnl){ + RETURN_LONG(1); + }else{ + svar_freevar(&sv); + } + PHPWSE("Could not put the variable into the bucket!"); +} +//////////////////////////////// +//GO_PHPSCRIPT +//////////////////////////////// + +int GO_EvalString(sEPHP* ephp TSRMLS_DC) +{ + zval pv; + zval fn; + zval *rv = NULL; + zval **args[16] = {NULL}; + zval *argv[16] = {0}; + zval *local_retval_ptr = NULL; + zend_op_array *new_op_array; + int retval = FAILURE; + const char* pt = ephp->pszPT; + long pc = (!pt)?(0):(strlen(pt)); + + zend_op_array *original_active_op_array = EG(active_op_array); + zend_function_state *original_function_state_ptr = EG(function_state_ptr); + zend_uchar original_handle_op_arrays; + zval **original_return_value_ptr_ptr = NULL; + zend_op **original_opline_ptr = NULL; + + if(pc > 16){ + return FAILURE; + }else if(pt){ + for(int i=0;ipArguments,char*); + if(tmp){ + ZVAL_STRING(argv[i],tmp,0); + }else{ + ZVAL_NULL(argv[i]); + } + } + break; + case 'S': + { + char** tmp = va_arg(ephp->pArguments,char**); + if(tmp && *tmp){ + ZVAL_STRING(argv[i],*tmp,1); + }else{ + ZVAL_NULL(argv[i]); + } + } + break; + case 'd': + case 'l': + case 'u': + case 'c': + case 'x': + { + long tmp = va_arg(ephp->pArguments,long); + ZVAL_LONG(argv[i],tmp); + } + break; + case 'U': + case 'D': + case 'X': + case 'C': + case 'L': + { + long* tmp = va_arg(ephp->pArguments,long*); + ZVAL_LONG(argv[i],*tmp); + } + break; + case 'f': + { + float tmp = va_arg(ephp->pArguments,float); + ZVAL_DOUBLE(argv[i],tmp); + } + break; + case 'q': + { + double tmp = va_arg(ephp->pArguments,double); + ZVAL_DOUBLE(argv[i],tmp); + } + break; + case 'b': + { + int tmp = va_arg(ephp->pArguments,int); + ZVAL_BOOL(argv[i],tmp); + } + break; + case 'm'://string array + { + char** tmp = va_arg(ephp->pArguments,char**); + long n = 0; + + if(!tmp){ + ZVAL_LONG(argv[i],0); + }else{ + if(array_init(argv[i])==FAILURE){ + goto CleanUp; + } + while(*tmp){ + add_index_string(argv[i],n++,*tmp,0); + tmp++; + } + } + } + break; + case 'v': + { + lphp_vparam* tmp = va_arg(ephp->pArguments,lphp_vparam*); + if(!tmp){ + ZVAL_LONG(argv[i],0); + }else{ + if(tmp->type == LPHP_STRING){ + ZVAL_STRINGL(argv[i],(char*)tmp->data,tmp->length,0); + }else{ + ZVAL_LONG(argv[i],(long)tmp->data); + } + } + } + break; + default: + pc = i+1; + goto CleanUp; + }//switch(*pt) + args[i] = &argv[i]; + } + } + + if(ephp->pszFunction){ + fn.value.str.len = strlen(ephp->pszFunction); + fn.value.str.val = (char*)ephp->pszFunction; + fn.type = IS_STRING; + } + + pv.value.str.len = strlen(ephp->pszBody); + pv.value.str.val = (char*)ephp->pszBody; + pv.type = IS_STRING; + + original_handle_op_arrays = CG(handle_op_arrays); + CG(handle_op_arrays) = 0; + try{ + new_op_array = compile_string(&pv,(ephp->pszFile)?((char*)ephp->pszFile):((char*)ephp->pszFunction) TSRMLS_CC); + }catch(...){ + CG(handle_op_arrays) = original_handle_op_arrays; + return FAILURE; + } + CG(handle_op_arrays) = original_handle_op_arrays; + + if (new_op_array) + { + original_return_value_ptr_ptr = EG(return_value_ptr_ptr); + original_opline_ptr = EG(opline_ptr); + + EG(return_value_ptr_ptr) = &local_retval_ptr; + EG(active_op_array) = new_op_array; + + try{ + zend_execute(new_op_array TSRMLS_CC); + }catch(...){ + goto Skip; + } + + if(ephp->pszFunction){ + retval = call_user_function_ex(CG(function_table),NULL,&fn,&rv,pc,(pc)?args:NULL,0,NULL TSRMLS_CC); + }else{ + retval = SUCCESS; + } + + if(rv){ + sPHPENV* ctx = (sPHPENV*)SG(server_context); + if(rv->type == IS_LONG || rv->type == IS_BOOL){ + ctx->m_flags |= PHPENV_FLAG_NUMERIC_RESULT; + ctx->r_value = (const char*)rv->value.lval; + }else if(rv->type == IS_DOUBLE){ + ctx->m_flags |= PHPENV_FLAG_NUMERIC_RESULT; + ctx->r_value = (const char*)((long)rv->value.dval); + }else if(rv->type == IS_STRING){ + ctx->r_value = (const char*)g_malloc(rv->value.str.len+1); + if(ctx->r_value){ + memcpy((void*)ctx->r_value,rv->value.str.val,rv->value.str.len); + ((char*)ctx->r_value)[rv->value.str.len]='\0'; + } + }else{ + ctx->m_flags |= PHPENV_FLAG_NUMERIC_RESULT; + ctx->r_value = NULL; + } + zval_ptr_dtor(&rv); + } + + EG(return_value_ptr_ptr) = &local_retval_ptr; + + if(local_retval_ptr){ + zval_ptr_dtor(&local_retval_ptr); + } +Skip: + EG(no_extensions)=0; + EG(opline_ptr) = original_opline_ptr; + EG(active_op_array) = original_active_op_array; + EG(function_state_ptr) = original_function_state_ptr; + EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; + destroy_op_array(new_op_array TSRMLS_CC); + efree(new_op_array); + } else { + retval = FAILURE; + } +CleanUp: + for(int i=0;itype = IS_LONG; + argv[i]->value.lval = 0; + FREE_ZVAL(argv[i]); + } + return retval; +} + +int GO_PhpExecute2(sEPHP* ephp) +{ + ephp->th_id = GetCurrentThreadId(); + if(!GO_PhpExecute2Locked(ephp)){ + g_stat_num_errors++; + return FALSE; + }else{ + return TRUE; + } + return 0; +} + +/* frees all resources allocated for the current thread */ + +struct TSRMENTRY{ + void **storage; + int count; + unsigned long thread_id; + TSRMENTRY *next; +}; + +TSRMENTRY* GetParentEntry(unsigned long tid) +{ + cLock(g_csection); + + TSRMENTRY* tmp = NULL; + tmp = (TSRMENTRY*)TlsGetValue(g_tls_key); + + g_stat_num_executions++; + + while(tmp) + { + if(tmp->thread_id == tid){ + break; + } + tmp = tmp->next; + } + return tmp; +} + +int exceptionhandler(LPEXCEPTION_POINTERS *e, LPEXCEPTION_POINTERS ep) +{ + *e=ep; + return TRUE; +} + +int GO_LockThread(unsigned long thID) +{ + cLock(g_csection); + + sTHRlst::iterator it; + it = g_php_threads.find(thID); + + if(it != g_php_threads.end()){ + return FALSE; + } + g_php_threads[thID] = 1; + return TRUE; +} + +int GO_UnlockThread(unsigned long thID) +{ + extern int g_initialized; + + if(!g_initialized){ + //we do not want it, cause another thread is cleaning up... + return TRUE; + } + + cLock(g_csection); + + sTHRlst::iterator it; + it = g_php_threads.find(thID); + + if(it == g_php_threads.end()){ + return FALSE; + } + + g_php_threads.erase(it); + return TRUE; +} + +int GO_PhpExecute2Locked(sEPHP* ephp) +{ + long rv = 0xff00ff00; + long result = 0; + long started = 0; + void ***tsrm_ls = NULL; + sPHPENV php_ctx; + LPEXCEPTION_POINTERS e; + int parent_to = 0; + int branch = 0; + TSRMENTRY* parent = GetParentEntry(ephp->th_id); + TSRMENTRY* tht; + TSRMENTRY op; + ///////////////////////////// + //check if this is not a php call + ///////////////////////////// + if(!GO_LockThread(ephp->th_id)){ + branch = 1; + g_stat_num_threads++; + } + + if(branch && parent){ + tsrm_ls = (void ***) ts_resource_ex(0,NULL); + parent_to = EG(timeout_seconds); + EG(timeout_seconds) = 0; + + memcpy(&op,parent,sizeof(op)); + memset(parent,0,sizeof(op)); + TlsSetValue(g_tls_key,NULL); + } + + __try + { + tsrm_ls = (void ***) ts_resource_ex(0,NULL); + } + __except(exceptionhandler(&e, GetExceptionInformation())){ + if(branch && parent){ + memcpy(parent,&op,sizeof(op)); + TlsSetValue(g_tls_key,parent); + tsrm_ls = (void ***) ts_resource_ex(0,NULL); + EG(timeout_seconds) = parent_to; + }else{ + GO_UnlockThread(ephp->th_id); + } + lphp_error(MT_LOG_EXCEPTION,e,"[%s],ts_resource_ex(0,NULL);\r\n",ephp->pszFile); + } + + tht = GetParentEntry(ephp->th_id); + ////////////////// + SG(server_context) = &php_ctx; + + ////////////////// + php_ctx.r_out = ephp->pOut; + php_ctx.m_flags = (ephp->pOut)?(1):(0); + php_ctx.c_param = (void*)ephp->c_param; + php_ctx.script_path = ephp->pszFile; + ////////////////// + if(!ephp->pszBody || tsrm_ls == NULL){ + goto End; + } + ////////////////// + php_update_ini_file(TSRMLS_C); + SG(options) |= SAPI_OPTION_NO_CHDIR; + ////////////////// + zend_first_try + ////////////////// + { + __try + { + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + + php_request_startup(TSRMLS_C);started = 1; + rv = GO_EvalString(ephp TSRMLS_CC); + result = (rv == SUCCESS); + } + __except(exceptionhandler(&e, GetExceptionInformation())){ + lphp_error(MT_LOG_EXCEPTION,e,"[%s],php_execute_script();\r\n",ephp->pszFile); + } + } + ////////////////// + zend_catch + { + result = 0xffffffff; + } + zend_end_try(); + ////////////////// + + if(result != 1){ + lphp_error(MT_LOG_ERROR,NULL,"[%s],php_execute_script [%.8x][%.8x]\r\n",ephp->pszFile,rv,result); + }else{ + if(ephp->cFlags & 0x01) + { + if(php_ctx.m_flags & PHPENV_FLAG_NUMERIC_RESULT) + { + ephp->cResType = 0x00; + ephp->res.lval = (long)php_ctx.r_value; + } + else if(php_ctx.r_value) + { + ephp->cResType = 0x01; + if(ephp->res.str.val && ephp->res.str.len){ + strncpy(ephp->res.str.val,(const char*)php_ctx.r_value,ephp->res.str.len); + }else{ + ephp->res.str.val = _strdup((const char*)php_ctx.r_value); + ephp->res.str.len = strlen((const char*)php_ctx.r_value); + g_free((void*)php_ctx.r_value); + } + } + else + { + ephp->cResType = 0x00; + ephp->res.str.val = NULL; + ephp->res.str.len = 0; + } + } + } + + if(started == 1){ + __try + { + php_request_shutdown(NULL); + } + __except(exceptionhandler(&e, GetExceptionInformation())){ + lphp_error(MT_LOG_EXCEPTION,e,"[%s],php_request_shutdown(NULL);\r\n",ephp->pszFile); + } + } + + if(branch && parent) + { + __try{ + ts_free_thread(); + }__except(exceptionhandler(&e, GetExceptionInformation())){ + lphp_error(MT_LOG_EXCEPTION,e,"[%s],ts_free_thread();\r\n",ephp->pszFile); + } + if(parent){ + memcpy(parent,&op,sizeof(op)); + TlsSetValue(g_tls_key,parent); + tsrm_ls = (void ***) ts_resource_ex(0,NULL); + EG(timeout_seconds) = parent_to; + } + }else{ + GO_UnlockThread(ephp->th_id); + } +End: + return (result == 1); +} + +int GO_PhpExecute(const char* script,std::string* out,cutFile* redir_out,long mode, + const char* querystring,void* cparam,PHPENV_CB fpCb) +{ + long rv = 0xff00ff00; + long result = 0; + long started = 0; + void ***tsrm_ls = NULL; + unsigned long thread_id = GetCurrentThreadId(); + sPHPENV php_ctx; + zend_file_handle file_handle = {0}; + zval* ret_val = NULL; + char full_path[260] = {0}; + ///////////////////////////// + //check if this is not a php call + ///////////////////////////// + + if(!GO_LockThread(thread_id)){ + lphp_error(MT_LOG_ERROR,NULL,"You must not call php from another php script!"); + return 0; + } + + try + { + tsrm_ls = (void ***) ts_resource_ex(0, NULL); + } + catch(LPEXCEPTION_POINTERS e) + { + lphp_error(MT_LOG_EXCEPTION,e,"ts_resource_ex(0,NULL);"); + goto End; + } + + + ////////////////// + SG(server_context) = &php_ctx; + ////////////////// + php_ctx.r_out = redir_out; + php_ctx.m_flags = (redir_out)?(1):(0); + php_ctx.c_param = cparam; + php_ctx.fp_callback = fpCb; + php_ctx.query_string = querystring; + php_ctx.script_path = (mode == PHPENV_MODE_SCRIPT)?"":script; + ////////////////// + if(!script || !strlen(script) || tsrm_ls == NULL){ + goto End; + } + ////////////////// + php_update_ini_file(TSRMLS_C); + ////////////////// + if(mode & PHPENV_MODE_FILE) + { + if(!fpCb){ + goto End; + } + + strncpy(full_path,script,sizeof(full_path)); + } + ////////////////// + SG(options) |= SAPI_OPTION_NO_CHDIR; + ////////////////// + zend_first_try + ////////////////// + { + try + { + if(mode & PHPENV_MODE_SCRIPT) + { + if(!(mode & PHPENV_MODE_ALLOWHDR)) + { + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + } + else + { + if(!fpCb){ + goto End; + } + } + + php_request_startup(TSRMLS_C);started = 1; + rv = zend_eval_string((char*)script,NULL,"libphp (www.piopawlu.net)" TSRMLS_CC); + result = (rv == SUCCESS); + } + else + { + file_handle.filename = full_path; + file_handle.free_filename = 0; + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.opened_path = NULL; + + php_ctx.post_len = (long)fpCb(LPHP_CB_POST_LENGTH,0,0,cparam); + php_ctx.post_data = (unsigned char*)fpCb(LPHP_CB_POST_DATA,0,0,cparam); + php_ctx.content_length = (long)fpCb(LPHP_CB_GETCL,0,0,cparam); + php_ctx.content_type = (const char*)fpCb(LPHP_CB_GETCT,0,0,cparam); + + SG(request_info).cookie_data = (char*)fpCb(LPHP_CB_GETCOOKIE,0,0,cparam); + SG(request_info).request_method = (const char*)fpCb(LPHP_CB_GETMETHOD,0,0,cparam); + SG(request_info).content_type = php_ctx.content_type; + SG(request_info).content_length = php_ctx.post_len; + SG(request_info).path_translated = full_path; + SG(request_info).query_string = (querystring)?((char*)querystring):((char*)""); + ////////// + php_request_startup(TSRMLS_C);started = 1; + php_execute_simple_script(&file_handle, &ret_val TSRMLS_CC); + result = 1; + } + + if(out && php_ctx.r_value){ + *out = php_ctx.r_value; + } + } + catch(LPEXCEPTION_POINTERS e) + { + lphp_error(MT_LOG_EXCEPTION,e,"php_execute_script();"); + } + } + ////////////////// + zend_catch + ////////////////// + { + result = 0xffffffff; + } + ////////////////// + zend_end_try(); + ////////////////// + + if(result != 1){ + lphp_error(MT_LOG_ERROR,NULL,"php_execute_script [%.8x][%.8x]",rv,result); + } + + if(started == 1) + { + try{ + php_request_shutdown(NULL); + } + catch(LPEXCEPTION_POINTERS e) + { + lphp_error(MT_LOG_EXCEPTION,e,"php_request_shutdown(NULL);"); + } + } + +End: + GO_UnlockThread(thread_id); + return (result == 1); +} + +int GO_PhpGlobalInit() +{ + const char* php_ini = NULL; + void*** key = NULL; + TSRMENTRY* te; + unsigned long php_tc = g_pref_ul("/cfg/php/tc",10,1); + sVar sv; + + php_ini = g_pref("/cfg/php/ini"); + phpenv_sapi_module.php_ini_path_override = (php_ini)?(php_ini):"php.ini"; + + if(!tsrm_startup(64,1,NULL,NULL)){ + return FALSE; + } + + //g_tls_key + key = (void ***) ts_resource_ex(0,NULL); + if(key){ + for(int i=0;i<512;i++){ + te = (TSRMENTRY*)TlsGetValue(i); + if(te && ((void***)te) == key){ + g_tls_key = i; + break; + } + } + if(!g_tls_key){ + tsrm_shutdown(); + return FALSE; + } + }else{ + tsrm_shutdown(); + return FALSE; + } + + + sapi_startup(&phpenv_sapi_module); + + if(phpenv_sapi_module.startup){ + phpenv_sapi_module.startup(&phpenv_sapi_module); + } + + sVariable(&sv,SV_LPOINTER,&g_stat_num_executions, 0, 1); + g_vars["/stat/php/num_execs"] = sv; + + sVariable(&sv,SV_LPOINTER,&g_stat_num_errors, 0, 1); + g_vars["/stat/php/num_errors"] = sv; + + sVariable(&sv,SV_LPOINTER,&g_stat_num_threads, 0, 1); + g_vars["/stat/php/num_threads"] = sv; + + return TRUE; +} +int GO_PhpGlobalDeInit() +{ + HANDLE hThread; + + //lock further execution and wait for all the threads remaining + cLock(g_csection); + sTHRlst::iterator it = g_php_threads.begin(); + + while(it != g_php_threads.end()) + { + cULock(); + hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, it->first); + if(hThread != NULL){ + if(WaitForSingleObject(hThread, 2000) != WAIT_OBJECT_0){ + TerminateThread(hThread, -1); + } + CloseHandle(hThread); + } + cLLock(); + it++; + } + + if(phpenv_sapi_module.shutdown) + { + try{ + phpenv_sapi_module.shutdown(&sapi_module); + }catch(...){} + } + + try{ + tsrm_shutdown(); + }catch(...){} + + mt_module_entry.functions = mt_functions; + if(g_zend_functions){ + free(g_zend_functions); + g_zend_functions = NULL; + } + return TRUE; +} + +int php_phpenv_ub_write(const char *str, unsigned int str_length TSRMLS_DC) +{ + sPHPENV* ctx = (sPHPENV*)SG(server_context); + + SG(headers_sent) = 1; + + if(ctx->fp_callback){ + ctx->fp_callback(1,0,0,ctx->c_param); + } + + if(ctx->r_out){ + ctx->r_out->write((void*)str,str_length); + return SUCCESS; + } + +#ifdef _DEBUG + g_std_out(str, strlen(str)); + return SUCCESS; +#else + if((ctx->m_flags & PHPENV_FLAG_DISABLE_OUTPUT)){ + return SUCCESS; + }else{ + g_std_out(str,strlen(str)); + return SUCCESS; + } +#endif +} +void php_phpenv_sapi_error(int type, const char *fmt, ...) +{ + char error[1024]; + + va_list ap; + va_start(ap, fmt); + _vsnprintf(error,sizeof(error)-1,fmt,ap); + php_phpenv_ub_write(error,strlen(error),0); + va_end(ap); +} +void php_phpenv_log_message(char *message) +{ + g_std_err(message,strlen(message)); +} + +int php_set_ini_entry(char *entry, char *value, int stage) +{ + return (SUCCESS == zend_alter_ini_entry(entry, strlen(entry) + 1, value, strlen(value) + 1,PHP_INI_SYSTEM, stage)); +} +int php_phpenv_startup(sapi_module_struct *sapi_module) +{ + if(g_php_module == NULL) + { + mt_module_entry.functions = mt_functions; + if(php_module_startup(sapi_module,&mt_module_entry,1)==FAILURE){ + return FAILURE; + } + return SUCCESS; + } + else //new functions + { + long c1 = 0; + long c2 = 0; + long c = 0; + long x = 0; + zend_function_entry* cfe = mt_functions; + //count our own functions + while(cfe->fname){ + c1++; + cfe++; + } + //count given functions + cfe = ((zend_module_entry*)g_php_module)->functions; + while(cfe->fname){ + c2++; + cfe++; + } + c = c1 + c2; + + g_zend_functions = (zend_function_entry*)malloc((c + 1)*sizeof(zend_module_entry)); + if(!g_zend_functions){ + return FAILURE; + } + memset(g_zend_functions,0,(c + 1)*sizeof(zend_module_entry)); + //copy our own functions + cfe = mt_functions; + for(int i=0;ifunctions; + for(int i=0;ifp_callback) + { + return (char*)ctx->fp_callback(LPHP_CB_GETCOOKIE,0,0,ctx->c_param); + } + else{ + return NULL; + } + return 0; +} + +void php_phpenv_flush(void *server_context) +{ + return; +} + +void php_phpenv_register_variables(zval *track_vars_array TSRMLS_DC) +{ + sPHPENV* ctx = (sPHPENV*)SG(server_context); + const char* rm = "GET"; + const char* rv = NULL; + char temp[64]; + + if(ctx->fp_callback) + { + rm = (const char*)ctx->fp_callback(LPHP_CB_GETMETHOD,0,0,ctx->c_param); + + php_register_variable("REQUEST_METHOD",(char*)rm,track_vars_array TSRMLS_CC); + + if(ctx->content_type){ + php_register_variable("CONTENT_TYPE",(char*)ctx->content_type,track_vars_array TSRMLS_CC); + } + + _snprintf(temp,sizeof(temp)-1,"%u",ctx->content_length); + php_register_variable("CONTENT_LENGTH",temp,track_vars_array TSRMLS_CC); + + if(ctx->script_path){ + php_register_variable("PATH_TRANSLATED",(char*)ctx->script_path,track_vars_array TSRMLS_CC); + } + if(ctx->query_string){ + php_register_variable("QUERY_STRING",(char*)ctx->query_string,track_vars_array TSRMLS_CC); + } + + rm = (const char*)ctx->fp_callback(LPHP_CB_GETVARS,0,0,ctx->c_param); + if(rm){ + while(*rm){ + rv = rm + strlen(rm) + 1; + php_register_variable((char*)rm,(char*)rv,track_vars_array TSRMLS_CC); + rm = rv + strlen(rv) + 1; + } + } + } + php_import_environment_variables(track_vars_array TSRMLS_CC); +} + +int php_phpenv_read_post(char *buffer, uint count_bytes TSRMLS_DC) +{ + sPHPENV* ctx = (sPHPENV*)SG(server_context); + unsigned long to_read = 0; + unsigned long rd_left = 0; + + if(!ctx || !ctx->post_data){ + return 0; + } + + rd_left = ctx->post_len - ctx->post_read; + to_read = (rd_left >= count_bytes)?count_bytes:rd_left; + if(to_read <= 0){ + return 0; + } + + memcpy(buffer,(ctx->post_data + ctx->post_read),to_read); + ctx->post_read += to_read; + *(buffer + to_read) = '\0'; + return to_read; + return 0; +} + +void php_phpenv_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) +{ + if(!sapi_header)return; + sPHPENV* ctx = (sPHPENV*)SG(server_context); + if(ctx && ctx->fp_callback){ + ctx->fp_callback(LPHP_CB_SETHDR,(void*)sapi_header->header,(void*)sapi_header->replace,ctx->c_param); + } +} +int php_phpenv_deactivate(TSRMLS_D){ + return SUCCESS; +} + +char* php_phpenv_getenv(char *name, size_t name_len TSRMLS_DC) +{ + sPHPENV* ctx = (sPHPENV*)SG(server_context); + + if(ctx->fp_callback){ + return (char*)ctx->fp_callback(LPHP_CB_GETENV,(void*)name,NULL,ctx->c_param); + }else{ + return getenv(name); + } + return NULL; +} + +int php_update_ini_file(TSRMLS_D) +{ + sPHPENV* ctx = (sPHPENV*)SG(server_context); + + if(!ctx->fp_callback && g_pref_ul("/cfg/php/noupd",10)){ + return 1; + } + + char inc_path_full[512]; + char* tmp = (char*)g_pref("/cfg/php/root"); + const char* root_dir = (tmp)?(tmp):(""); + + try + { + tmp = (char*)g_pref("/cfg/php/sessions"); + if(tmp && !php_set_ini_entry("session.save_path", (char*)tmp, PHP_INI_STAGE_ACTIVATE)){ + return 0; + } + + tmp = (char*)g_pref("/cfg/php/includes"); + if(tmp && !php_set_ini_entry("include_path", (char*)tmp, PHP_INI_STAGE_ACTIVATE)){ + return 0; + } + + if(ctx->fp_callback && ctx->script_path) + { + strncpy(inc_path_full+1,ctx->script_path,sizeof(inc_path_full)-2); + *inc_path_full = 0; + tmp = inc_path_full + strlen(ctx->script_path); + while(*tmp) + { + if(*tmp == '\\' || *tmp == '/'){ + *tmp='\0'; + break; + }else{ + tmp--; + if(!(*tmp)){ + *tmp = (char)(0xff); + } + } + } + + if(*tmp!=0xFF){ + if(!php_set_ini_entry("doc_root", (char*)(inc_path_full+1), PHP_INI_STAGE_ACTIVATE))return 0; + } + } + else + { + tmp = (char*)g_pref("/cfg/php/doc_root"); + if(tmp && !php_set_ini_entry("doc_root", (char*)tmp, PHP_INI_STAGE_ACTIVATE)){ + return 0; + } + } + + tmp = (char*)g_pref("/cfg/php/uploads"); + if(tmp && !php_set_ini_entry("upload_tmp_dir", (char*)tmp, PHP_INI_STAGE_ACTIVATE)){ + return 0; + } + + tmp = (char*)g_pref("/cfg/php/extensions"); + if(tmp && !php_set_ini_entry("extension_dir",(char*)tmp, PHP_INI_STAGE_ACTIVATE)){ + return 0; + } + return 1; + } + catch(...) + { + return 0; + } + return 1; +} \ No newline at end of file -- cgit v1.2.3