/*-*- mode: C; tab-width:4 -*-*/ /* wait */ #include #include /* miscellaneous */ #include #include #include #include #include "php_java.h" #include "php_globals.h" #include "ext/standard/info.h" #include "java_bridge.h" #ifdef ZEND_ENGINE_2 #include "zend_interfaces.h" #include "zend_exceptions.h" #include "zend_builtin_functions.h" #endif EXT_DECLARE_MODULE_GLOBALS(EXT) struct cfg *EXT_GLOBAL (cfg) = 0; #ifdef __MINGW32__ static int java_errno=0; int *__errno (void) { return &java_errno; } #define php_info_print_table_row(a, b, c) \ php_info_print_table_row_ex(a, "java", b, c) #endif PHP_RINIT_FUNCTION(EXT) { if(JG(jenv)) { php_error(E_ERROR, "php_mod_"/**/EXT_NAME()/**/"(%d): Synchronization problem, rinit with active connection called. Cannot continue, aborting now. Please report this to: php-java-bridge-users@lists.sourceforge.net",59); } JG(is_closed)=0; return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(EXT) { if(JG(jenv)) { if(*JG(jenv)) { if((*JG(jenv))->peer) { EXT_GLOBAL(protocol_end)(JG(jenv)); /* free servlet session */ close((*JG(jenv))->peer); } if((*JG(jenv))->s) free((*JG(jenv))->s); if((*JG(jenv))->send) free((*JG(jenv))->send); if((*JG(jenv))->server_name) free((*JG(jenv))->server_name); if((*JG(jenv))->cookie_name) free((*JG(jenv))->cookie_name); if((*JG(jenv))->cookie_value) free((*JG(jenv))->cookie_value); free(*JG(jenv)); } free(JG(jenv)); } JG(jenv) = NULL; JG(is_closed)=1; return SUCCESS; } EXT_FUNCTION(EXT_GLOBAL(last_exception_get)) { proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT; (*jenv)->writeInvokeBegin(jenv, 0, "lastException", 0, 'P', return_value); (*jenv)->writeInvokeEnd(jenv); } EXT_FUNCTION(EXT_GLOBAL(last_exception_clear)) { proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT; (*jenv)->writeInvokeBegin(jenv, 0, "lastException", 0, 'P', return_value); (*jenv)->writeObject(jenv, 0); (*jenv)->writeInvokeEnd(jenv); } EXT_FUNCTION(EXT_GLOBAL(set_file_encoding)) { zval **enc; proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &enc) == FAILURE) WRONG_PARAM_COUNT; convert_to_string_ex(enc); (*jenv)->writeInvokeBegin(jenv, 0, "setFileEncoding", 0, 'I', return_value); (*jenv)->writeString(jenv, Z_STRVAL_PP(enc), Z_STRLEN_PP(enc)); (*jenv)->writeInvokeEnd(jenv); } static void require(INTERNAL_FUNCTION_PARAMETERS) { zval **path; proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &path) == FAILURE) WRONG_PARAM_COUNT; convert_to_string_ex(path); (*jenv)->writeInvokeBegin(jenv, 0, "setJarLibraryPath", 0, 'I', return_value); (*jenv)->writeString(jenv, Z_STRVAL_PP(path), Z_STRLEN_PP(path)); (*jenv)->writeInvokeEnd(jenv); } EXT_FUNCTION(EXT_GLOBAL(set_library_path)) { require(INTERNAL_FUNCTION_PARAM_PASSTHRU); } EXT_FUNCTION(EXT_GLOBAL(require)) { require(INTERNAL_FUNCTION_PARAM_PASSTHRU); } EXT_FUNCTION(EXT_GLOBAL(instanceof)) { zval **pobj, **pclass; long obj, class; proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &pobj, &pclass) == FAILURE) WRONG_PARAM_COUNT; convert_to_object_ex(pobj); convert_to_object_ex(pclass); obj = 0; EXT_GLOBAL(get_jobject_from_object)(*pobj, &obj TSRMLS_CC); if(!obj) { zend_error(E_ERROR, "Argument #1 for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C)); return; } class = 0; EXT_GLOBAL(get_jobject_from_object)(*pclass, &class TSRMLS_CC); if(!class) { zend_error(E_ERROR, "Arument #2 for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C)); return; } (*jenv)->writeInvokeBegin(jenv, 0, "InstanceOf", 0, 'I', return_value); (*jenv)->writeObject(jenv, obj); (*jenv)->writeObject(jenv, class); (*jenv)->writeInvokeEnd(jenv); } EXT_FUNCTION(EXT_GLOBAL(get_session)) { proxyenv *jenv; zval **session; if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &session) == FAILURE) WRONG_PARAM_COUNT; if(JG(jenv)) { php_error(E_ERROR, "This script has already selected a backend. Please call "/**/EXT_NAME()/**/"_get_session() before calling any of the "/**/EXT_NAME()/**/"functions."); } convert_to_string_ex(session); jenv=EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) RETURN_NULL(); (*jenv)->writeInvokeBegin(jenv, 0, "getSession", 0, 'I', return_value); (*jenv)->writeString(jenv, Z_STRVAL_PP(session), Z_STRLEN_PP(session)); (*jenv)->writeBoolean(jenv, 0); (*jenv)->writeLong(jenv, 1400); (*jenv)->writeInvokeEnd(jenv); } EXT_FUNCTION(EXT_GLOBAL(get_server_name)) { proxyenv *jenv; if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT; jenv = EXT_GLOBAL(try_connect_to_server)(TSRMLS_C); if(jenv && (*jenv)->server_name) { RETURN_STRING((*jenv)->server_name, 1); } RETURN_NULL(); } EXT_FUNCTION(EXT_GLOBAL(reset)) { proxyenv *jenv; if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT; jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) RETURN_NULL(); (*jenv)->writeInvokeBegin(jenv, 0, "reset", 0, 'I', return_value); (*jenv)->writeInvokeEnd(jenv); } EXT_FUNCTION(EXT_GLOBAL(get_values)) { proxyenv *jenv; zval **pobj; long obj; jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) RETURN_NULL(); if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &pobj) == FAILURE) WRONG_PARAM_COUNT; #ifdef ZEND_ENGINE_2 convert_to_object_ex(pobj); obj = 0; EXT_GLOBAL(get_jobject_from_object)(*pobj, &obj TSRMLS_CC); if(!obj) { zend_error(E_ERROR, "Argument for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C)); return; } (*jenv)->writeInvokeBegin(jenv, 0, "getValues", 0, 'I', return_value); (*jenv)->writeObject(jenv, obj); (*jenv)->writeInvokeEnd(jenv); #else COPY_PZVAL_TO_ZVAL(*return_value, *pobj); #endif } EXT_FUNCTION(EXT_GLOBAL(closure)) { proxyenv *jenv; int key_type; char *string_key; ulong num_key; zval **pobj, **pclass; long obj, class; zend_class_entry *ce = 0; if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &pobj, &pclass) == FAILURE) WRONG_PARAM_COUNT; //convert_to_object_ex(pobj); //convert_to_object_ex(pclass); jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) RETURN_NULL(); if (Z_TYPE_PP(pobj) == IS_OBJECT) ce = Z_OBJCE_PP(pobj); if (!ce) WRONG_PARAM_COUNT; /* FIXME: proper message */ class = 0; EXT_GLOBAL(get_jobject_from_object)(*pclass, &class TSRMLS_CC); if(!class) { zend_error(E_ERROR, "Argument #1 for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C)); return; } (*jenv)->writeInvokeBegin(jenv, 0, "makeClosure", 0, 'I', return_value); (*jenv)->writeLong(jenv, (long)*pobj); (*jenv)->writeObject(jenv, class); /* FIXME: check for array */ (*jenv)->writeCompositeBegin_a(jenv); zend_hash_internal_pointer_reset(&ce->function_table); while ((key_type = zend_hash_get_current_key(&ce->function_table, &string_key, &num_key, 1)) != HASH_KEY_NON_EXISTANT) { if (key_type == HASH_KEY_IS_STRING) { (*jenv)->writePairBegin(jenv); (*jenv)->writeString(jenv, string_key, strlen(string_key)); (*jenv)->writePairEnd(jenv); } zend_hash_move_forward(&ce->function_table); } (*jenv)->writeCompositeEnd(jenv); (*jenv)->writeInvokeEnd(jenv); } function_entry EXT_GLOBAL(functions)[] = { EXT_FE(EXT_GLOBAL(last_exception_get), NULL) EXT_FE(EXT_GLOBAL(last_exception_clear), NULL) EXT_FE(EXT_GLOBAL(set_file_encoding), NULL) EXT_FE(EXT_GLOBAL(require), NULL) EXT_FE(EXT_GLOBAL(set_library_path), NULL) EXT_FE(EXT_GLOBAL(instanceof), NULL) EXT_FE(EXT_GLOBAL(get_session), NULL) EXT_FE(EXT_GLOBAL(get_server_name), NULL) EXT_FE(EXT_GLOBAL(reset), NULL) EXT_FE(EXT_GLOBAL(get_values), NULL) EXT_FE(EXT_GLOBAL(closure), NULL) {NULL, NULL, NULL} }; zend_module_entry EXT_GLOBAL(module_entry) = { STANDARD_MODULE_HEADER, EXT_NAME(), EXT_GLOBAL(functions), EXT_MINIT(EXT), EXT_MSHUTDOWN(EXT), EXT_RINIT(EXT), EXT_RSHUTDOWN(EXT), EXT_MINFO(EXT), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; #if defined(COMPILE_DL_JAVA) || defined(COMPILE_DL_MONO) EXT_GET_MODULE(EXT) #endif int EXT_GLOBAL(ini_updated), EXT_GLOBAL(ini_last_updated); zend_class_entry *EXT_GLOBAL(class_entry); zend_class_entry *EXT_GLOBAL(class_class_entry); zend_class_entry *EXT_GLOBAL(exception_class_entry); #ifdef ZEND_ENGINE_2 zend_object_handlers EXT_GLOBAL(handlers); #endif static PHP_INI_MH(OnIniHosts) { if (new_value) { EXT_GLOBAL(cfg)->hosts=new_value; EXT_GLOBAL(ini_updated)|=U_HOSTS; } return SUCCESS; } static PHP_INI_MH(OnIniServlet) { if (new_value) { EXT_GLOBAL(cfg)->servlet=new_value; EXT_GLOBAL(ini_updated)|=U_SERVLET; } return SUCCESS; } static PHP_INI_MH(OnIniSockname) { if (new_value) { EXT_GLOBAL(cfg)->sockname=new_value; EXT_GLOBAL(ini_updated)|=U_SOCKNAME; } return SUCCESS; } static PHP_INI_MH(OnIniClassPath) { if (new_value) { EXT_GLOBAL(cfg)->classpath =new_value; EXT_GLOBAL(ini_updated)|=U_CLASSPATH; } return SUCCESS; } static PHP_INI_MH(OnIniLibPath) { if (new_value) { EXT_GLOBAL(cfg)->ld_library_path = new_value; EXT_GLOBAL(ini_updated)|=U_LIBRARY_PATH; } return SUCCESS; } static PHP_INI_MH(OnIniJava) { if (new_value) { EXT_GLOBAL(cfg)->vm = new_value; EXT_GLOBAL(ini_updated)|=U_JAVA; } return SUCCESS; } static PHP_INI_MH(OnIniJavaHome) { if (new_value) { EXT_GLOBAL(cfg)->vm_home = new_value; EXT_GLOBAL(ini_updated)|=U_JAVA_HOME; } return SUCCESS; } static PHP_INI_MH(OnIniLogLevel) { if (new_value) { EXT_GLOBAL(cfg)->logLevel = new_value; EXT_GLOBAL(cfg)->logLevel_val=atoi(EXT_GLOBAL(cfg)->logLevel); EXT_GLOBAL(ini_updated)|=U_LOGLEVEL; } return SUCCESS; } static PHP_INI_MH(OnIniLogFile) { if (new_value) { EXT_GLOBAL(cfg)->logFile = new_value; EXT_GLOBAL(ini_updated)|=U_LOGFILE; } return SUCCESS; } PHP_INI_BEGIN() PHP_INI_ENTRY(EXT_NAME()/**/".servlet", NULL, PHP_INI_SYSTEM, OnIniServlet) PHP_INI_ENTRY(EXT_NAME()/**/".socketname", NULL, PHP_INI_SYSTEM, OnIniSockname) PHP_INI_ENTRY(EXT_NAME()/**/".hosts", NULL, PHP_INI_SYSTEM, OnIniHosts) PHP_INI_ENTRY(EXT_NAME()/**/".classpath", NULL, PHP_INI_SYSTEM, OnIniClassPath) PHP_INI_ENTRY(EXT_NAME()/**/".libpath", NULL, PHP_INI_SYSTEM, OnIniLibPath) PHP_INI_ENTRY(EXT_NAME()/**/"."/**/EXT_NAME()/**/"", NULL, PHP_INI_ALL, OnIniJava) PHP_INI_ENTRY(EXT_NAME()/**/"."/**/EXT_NAME()/**/"_home", NULL, PHP_INI_ALL, OnIniJavaHome) PHP_INI_ENTRY(EXT_NAME()/**/".log_level", NULL, PHP_INI_ALL, OnIniLogLevel) PHP_INI_ENTRY(EXT_NAME()/**/".log_file", NULL, PHP_INI_ALL, OnIniLogFile) PHP_INI_END() /* vm_alloc_globals_ctor(zend_vm_globals *vm_globals) */ static void EXT_GLOBAL(alloc_globals_ctor)(EXT_GLOBAL_EX(zend_,globals,_) *EXT_GLOBAL(globals) TSRMLS_DC) { EXT_GLOBAL(globals)->jenv=0; EXT_GLOBAL(globals)->is_closed=-1; } #ifdef ZEND_ENGINE_2 EXT_METHOD(EXT, EXT) { zval **argv; int argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU, EXT_NAME(), CONSTRUCTOR, 1, getThis(), argc, argv); efree(argv); } EXT_METHOD(EXT, EXT_GLOBAL(class)) { zval **argv; int argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU, EXT_NAME(), CONSTRUCTOR, 0, getThis(), argc, argv); efree(argv); } // exact copy of vm_class for jsr223 compatibility EXT_METHOD(EXT, EXT_GLOBAL_N(class)) { zval **argv; int argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU, EXT_NAME(), CONSTRUCTOR, 0, getThis(), argc, argv); efree(argv); } EXT_METHOD(EXT, __call) { zval **xargv, **argv; int i = 0, xargc, argc = ZEND_NUM_ARGS(); HashPosition pos; zval **param; argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } /* function arguments in arg#2 */ xargc = zend_hash_num_elements(Z_ARRVAL_P(argv[1])); xargv = safe_emalloc(sizeof(zval *), xargc, 0); for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(argv[1]), &pos); zend_hash_get_current_data_ex(Z_ARRVAL_P(argv[1]), (void **) ¶m, &pos) == SUCCESS; zend_hash_move_forward_ex(Z_ARRVAL_P(argv[1]), &pos)) { /*zval_add_ref(param);*/ xargv[i++] = *param; } EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU, Z_STRVAL(*argv[0]), CONSTRUCTOR_NONE, 0, getThis(), xargc, xargv); efree(argv); efree(xargv); } EXT_METHOD(EXT, __tostring) { long result = 0; if(Z_TYPE_P(getThis()) == IS_OBJECT) { EXT_GLOBAL(get_jobject_from_object)(getThis(), &result TSRMLS_CC); } if(result) { proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} (*jenv)->writeInvokeBegin(jenv, 0, "ObjectToString", 0, 'I', return_value); (*jenv)->writeObject(jenv, result); (*jenv)->writeInvokeEnd(jenv); } else { EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU, "tostring", CONSTRUCTOR_NONE, 0, getThis(), 0, NULL); } } EXT_METHOD(EXT, __set) { zval **argv; int argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(set_property_handler)(Z_STRVAL(*argv[0]), getThis(), argv[1], return_value); efree(argv); } EXT_METHOD(EXT, __destruct) { zval **argv; int argc = ZEND_NUM_ARGS(); long obj; argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_FALSE; } EXT_GLOBAL(get_jobject_from_object)(getThis(), &obj TSRMLS_CC); if(!obj) RETURN_TRUE; /* may happen when vm is not initalized */ if(JG(jenv)) (*JG(jenv))->writeUnref(JG(jenv), obj); efree(argv); RETURN_TRUE; } EXT_METHOD(EXT, __get) { zval **argv; int argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(get_property_handler)(Z_STRVAL(*argv[0]), getThis(), return_value); efree(argv); } EXT_METHOD(EXT, offsetExists) { proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); zval **argv; int argc; long obj; if(!jenv) {RETURN_NULL();} argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(get_jobject_from_object)(getThis(), &obj TSRMLS_CC); assert(obj); (*jenv)->writeInvokeBegin(jenv, 0, "getPhpMap", 0, 'I', return_value); (*jenv)->writeObject(jenv, obj); (*jenv)->writeInvokeEnd(jenv); EXT_GLOBAL(get_jobject_from_object)(return_value, &obj TSRMLS_CC); assert(obj); EXT_GLOBAL(invoke)("offsetExists", obj, argc, argv, 0, return_value TSRMLS_CC); efree(argv); } EXT_METHOD(EXT, offsetGet) { zval **argv; int argc; long obj; proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(get_jobject_from_object)(getThis(), &obj TSRMLS_CC); assert(obj); (*jenv)->writeInvokeBegin(jenv, 0, "getPhpMap", 0, 'I', return_value); (*jenv)->writeObject(jenv, obj); (*jenv)->writeInvokeEnd(jenv); EXT_GLOBAL(get_jobject_from_object)(return_value, &obj TSRMLS_CC); assert(obj); EXT_GLOBAL(invoke)("offsetGet", obj, argc, argv, 0, return_value TSRMLS_CC); efree(argv); } EXT_METHOD(EXT, offsetSet) { zval **argv; int argc; long obj; proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(get_jobject_from_object)(getThis(), &obj TSRMLS_CC); assert(obj); (*jenv)->writeInvokeBegin(jenv, 0, "getPhpMap", 0, 'I', return_value); (*jenv)->writeObject(jenv, obj); (*jenv)->writeInvokeEnd(jenv); EXT_GLOBAL(get_jobject_from_object)(return_value, &obj TSRMLS_CC); assert(obj); EXT_GLOBAL(invoke)("offsetSet", obj, argc, argv, 0, return_value TSRMLS_CC); efree(argv); } EXT_METHOD(EXT, offsetUnset) { zval **argv; int argc; long obj; proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); if(!jenv) {RETURN_NULL();} argc = ZEND_NUM_ARGS(); argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0); if (zend_get_parameters_array(ht, argc, argv) == FAILURE) { php_error(E_ERROR, "Couldn't fetch arguments into array."); RETURN_NULL(); } EXT_GLOBAL(get_jobject_from_object)(getThis(), &obj TSRMLS_CC); assert(obj); (*jenv)->writeInvokeBegin(jenv, 0, "getPhpMap", 0, 'I', return_value); (*jenv)->writeObject(jenv, obj); (*jenv)->writeInvokeEnd(jenv); EXT_GLOBAL(get_jobject_from_object)(return_value, &obj TSRMLS_CC); assert(obj); EXT_GLOBAL(invoke)("offsetUnset", obj, argc, argv, 0, return_value TSRMLS_CC); efree(argv); } static ZEND_BEGIN_ARG_INFO(arginfo_zero, 0) ZEND_END_ARG_INFO(); static ZEND_BEGIN_ARG_INFO(arginfo_get, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO(); static ZEND_BEGIN_ARG_INFO(arginfo_set, 0) ZEND_ARG_INFO(0, index) ZEND_ARG_INFO(0, newval) ZEND_END_ARG_INFO(); function_entry EXT_GLOBAL(class_functions)[] = { EXT_ME(EXT, EXT_GLOBAL_N(class), NULL, 0) EXT_ME(EXT, EXT_GLOBAL(class), NULL, 0) EXT_ME(EXT, EXT, NULL, 0) EXT_ME(EXT, __call, arginfo_set, ZEND_ACC_PUBLIC) EXT_ME(EXT, __tostring, arginfo_zero, ZEND_ACC_PUBLIC) EXT_ME(EXT, __get, arginfo_get, ZEND_ACC_PUBLIC) EXT_ME(EXT, __set, arginfo_set, ZEND_ACC_PUBLIC) EXT_ME(EXT, __destruct, arginfo_zero, ZEND_ACC_PUBLIC) EXT_ME(EXT, offsetExists, arginfo_get, ZEND_ACC_PUBLIC) EXT_ME(EXT, offsetGet, arginfo_get, ZEND_ACC_PUBLIC) EXT_ME(EXT, offsetSet, arginfo_set, ZEND_ACC_PUBLIC) EXT_ME(EXT, offsetUnset, arginfo_get, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; static zend_object_value create_object(zend_class_entry *class_type TSRMLS_DC) { /* standard initialization, copied from parent zend_API.c */ zval *tmp; zend_object *object; zend_object_value obj = zend_objects_new(&object, class_type TSRMLS_CC); ALLOC_HASHTABLE(object->properties); zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); /* real work */ obj.handlers = (zend_object_handlers*)&EXT_GLOBAL(handlers); return obj; } static zend_object_value create_exception_object(zend_class_entry *class_type TSRMLS_DC) { /* standard initialization, copied from parent zend_exceptions.c */ zval tmp, obj; zend_object *object; zval *trace; obj.value.obj = zend_objects_new(&object, class_type TSRMLS_CC); ALLOC_HASHTABLE(object->properties); zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); ALLOC_ZVAL(trace); ZVAL_NULL(trace); trace->is_ref = 0; trace->refcount = 0; zend_fetch_debug_backtrace(trace, 0 TSRMLS_CC); zend_update_property_string(zend_exception_get_default(), &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC); zend_update_property_long(zend_exception_get_default(), &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); zend_update_property(zend_exception_get_default(), &obj, "trace", sizeof("trace")-1, trace TSRMLS_CC); /* real work */ obj.value.obj.handlers = (zend_object_handlers*)&EXT_GLOBAL(handlers); return obj.value.obj; } static int cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC) { if (type==IS_STRING) { proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C); long obj = 0; zval free_obj; if(!jenv) return FAILURE; if (should_free) free_obj = *writeobj; if(jenv && (Z_TYPE_P(readobj) == IS_OBJECT)) { EXT_GLOBAL(get_jobject_from_object)(readobj, &obj TSRMLS_CC); } if(obj) { (*jenv)->writeInvokeBegin(jenv, 0, "ObjectToString", 0, 'I', writeobj); (*jenv)->writeObject(jenv, obj); (*jenv)->writeInvokeEnd(jenv); } if (should_free) zval_dtor(&free_obj); return obj?SUCCESS:FAILURE; } return FAILURE; } typedef struct { zend_object_iterator intern; long vm_iterator; zval *current_object; int type; } vm_iterator; static void iterator_dtor(zend_object_iterator *iter TSRMLS_DC) { proxyenv *jenv = JG(jenv); vm_iterator *iterator = (vm_iterator *)iter; zval_ptr_dtor((zval**)&iterator->intern.data); if (iterator->current_object) zval_ptr_dtor((zval**)&iterator->current_object); if(iterator->vm_iterator) { /* check jenv because destructor may be called after request shutdown */ if(jenv) (*jenv)->writeUnref(jenv, iterator->vm_iterator); iterator->vm_iterator = 0; } efree(iterator); } static int iterator_valid(zend_object_iterator *iter TSRMLS_DC) { vm_iterator *iterator = (vm_iterator *)iter; return (iterator->vm_iterator && iterator->current_object) ? SUCCESS : FAILURE; } static void iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) { vm_iterator *iterator = (vm_iterator *)iter; *data = &iterator->current_object; } static int iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) { vm_iterator *iterator = (vm_iterator *)iter; zval *presult; MAKE_STD_ZVAL(presult); ZVAL_NULL(presult); EXT_GLOBAL(invoke)("currentKey", iterator->vm_iterator, 0, 0, 0, presult TSRMLS_CC); if(ZVAL_IS_NULL(presult)) { zval_ptr_dtor((zval**)&presult); return HASH_KEY_NON_EXISTANT; } if(iterator->type == HASH_KEY_IS_STRING) { size_t strlen = Z_STRLEN_P(presult); *str_key = emalloc(strlen+1); memcpy(*str_key, Z_STRVAL_P(presult), strlen); (*str_key)[strlen]=0; // len+1 is due to a bug in php. It assignes the len with // key->value.str.len = str_key_len-1; In the evaluator the // obtained length is always increased by one, except for the // return value from iterator_current_key. So we must do this // ourselfs. The author's intention was probably to discard the // termination character, but that's pointless, if php expects our // string to be null terminated why does it ask for the string // length? And if it doesn't expect a null terminated string, why // does it decrease the obtained length by one? *str_key_len = strlen+1; } else { ulong i =(unsigned long)atol((char*)Z_STRVAL_P(presult)); *int_key = i; } zval_ptr_dtor((zval**)&presult); return iterator->type; } static void init_current_data(vm_iterator *iterator TSRMLS_DC) { MAKE_STD_ZVAL(iterator->current_object); ZVAL_NULL(iterator->current_object); EXT_GLOBAL(invoke)("currentData", iterator->vm_iterator, 0, 0, 0, iterator->current_object TSRMLS_CC); } static void iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) { zval *presult; vm_iterator *iterator = (vm_iterator *)iter; proxyenv *jenv = JG(jenv); MAKE_STD_ZVAL(presult); ZVAL_NULL(presult); if (iterator->current_object) { zval_ptr_dtor((zval**)&iterator->current_object); iterator->current_object = NULL; } (*jenv)->writeInvokeBegin(jenv, iterator->vm_iterator, "moveForward", 0, 'I', presult); (*jenv)->writeInvokeEnd(jenv); if(Z_BVAL_P(presult)) init_current_data(iterator TSRMLS_CC); zval_ptr_dtor((zval**)&presult); } static zend_object_iterator_funcs EXT_GLOBAL(iterator_funcs) = { iterator_dtor, iterator_valid, iterator_current_data, iterator_current_key, iterator_move_forward, NULL }; static zend_object_iterator *get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) { zval *presult; proxyenv *jenv = JG(jenv); vm_iterator *iterator = emalloc(sizeof *iterator); long vm_iterator, obj; MAKE_STD_ZVAL(presult); ZVAL_NULL(presult); object->refcount++; iterator->intern.data = (void*)object; iterator->intern.funcs = &EXT_GLOBAL(iterator_funcs); EXT_GLOBAL(get_jobject_from_object)(object, &obj TSRMLS_CC); assert(obj); (*jenv)->writeInvokeBegin(jenv, 0, "getPhpMap", 0, 'I', presult); (*jenv)->writeObject(jenv, obj); (*jenv)->writeInvokeEnd(jenv); EXT_GLOBAL(get_jobject_from_object)(presult, &vm_iterator TSRMLS_CC); if (!vm_iterator) return NULL; iterator->vm_iterator = vm_iterator; (*jenv)->writeInvokeBegin(jenv, vm_iterator, "getType", 0, 'I', presult); (*jenv)->writeInvokeEnd(jenv); iterator->type = Z_BVAL_P(presult) ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG; (*jenv)->writeInvokeBegin(jenv, vm_iterator, "hasMore", 0, 'I', presult); (*jenv)->writeInvokeEnd(jenv); if(Z_BVAL_P(presult)) init_current_data(iterator TSRMLS_CC); zval_ptr_dtor((zval**)&presult); return (zend_object_iterator*)iterator; } static void make_lambda(zend_internal_function *f, void (*handler)(INTERNAL_FUNCTION_PARAMETERS)) { f->type = ZEND_INTERNAL_FUNCTION; f->handler = handler; f->function_name = NULL; f->scope = NULL; f->fn_flags = 0; f->prototype = NULL; f->num_args = 0; f->arg_info = NULL; f->pass_rest_by_reference = 0; } #else void EXT_GLOBAL(call_function_handler4)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) { pval *object = property_reference->object; zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data; char *name = Z_STRVAL(function_name->element); int arg_count = ZEND_NUM_ARGS(); pval **arguments = (pval **) emalloc(sizeof(pval *)*arg_count); short createInstance; enum constructor constructor = CONSTRUCTOR_NONE; getParametersArray(ht, arg_count, arguments); createInstance = strcmp(EXT_NAME()/**/"_class", name) && strcmp(EXT_NAME()/**/"class", name); if(!strcmp(EXT_NAME(), name) || !createInstance) constructor = CONSTRUCTOR; EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU, name, constructor, createInstance, object, arg_count, arguments); efree(arguments); pval_destructor(&function_name->element); } static pval get_property_handler(zend_property_reference *property_reference) { pval presult, *object; zend_llist_element *element; zend_overloaded_element *property; char *name; element = property_reference->elements_list->head; property=(zend_overloaded_element *)element->data; name = Z_STRVAL(property->element); object = property_reference->object; EXT_GLOBAL(get_property_handler)(name, object, &presult); pval_destructor(&property->element); return presult; } static int set_property_handler(zend_property_reference *property_reference, pval *value) { int result; pval dummy, *object; zend_llist_element *element; zend_overloaded_element *property; char *name; element = property_reference->elements_list->head; property=(zend_overloaded_element *)element->data; name = Z_STRVAL(property->element); object = property_reference->object; result = EXT_GLOBAL(set_property_handler) (name, object, value, &dummy); pval_destructor(&property->element); return result; } #endif PHP_MINIT_FUNCTION(EXT) { zend_class_entry *parent; #ifndef ZEND_ENGINE_2 zend_class_entry ce; INIT_OVERLOADED_CLASS_ENTRY(ce, EXT_NAME(), NULL, EXT_GLOBAL(call_function_handler4), get_property_handler, set_property_handler); EXT_GLOBAL(class_entry) = zend_register_internal_class(&ce TSRMLS_CC); INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"_class", NULL); parent = (zend_class_entry *) EXT_GLOBAL(class_entry); zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"class", NULL); parent = (zend_class_entry *) EXT_GLOBAL(class_entry); zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); #else zend_class_entry ce; zend_internal_function call, get, set; make_lambda(&call, EXT_FN(EXT_GLOBAL(__call))); make_lambda(&get, EXT_FN(EXT_GLOBAL(__get))); make_lambda(&set, EXT_FN(EXT_GLOBAL(__set))); INIT_OVERLOADED_CLASS_ENTRY(ce, EXT_NAME(), EXT_GLOBAL(class_functions), (zend_function*)&call, (zend_function*)&get, (zend_function*)&set); memcpy(&EXT_GLOBAL(handlers), zend_get_std_object_handlers(), sizeof EXT_GLOBAL(handlers)); //EXT_GLOBAL(handlers).clone_obj = clone; EXT_GLOBAL(handlers).cast_object = cast; EXT_GLOBAL(class_entry) = zend_register_internal_class(&ce TSRMLS_CC); EXT_GLOBAL(class_entry)->get_iterator = get_iterator; EXT_GLOBAL(class_entry)->create_object = create_object; zend_class_implements(EXT_GLOBAL(class_entry) TSRMLS_CC, 1, zend_ce_arrayaccess); INIT_OVERLOADED_CLASS_ENTRY(ce, EXT_NAME()/**/"_exception", EXT_GLOBAL(class_functions), (zend_function*)&call, (zend_function*)&get, (zend_function*)&set); parent = (zend_class_entry *) zend_exception_get_default(); EXT_GLOBAL(exception_class_entry) = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); // only cast and clone; no iterator, no array access EXT_GLOBAL(exception_class_entry)->create_object = create_exception_object; INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"_class", EXT_GLOBAL(class_functions)); parent = (zend_class_entry *) EXT_GLOBAL(class_entry); EXT_GLOBAL(class_class_entry) = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); /* compatibility with the jsr implementation */ INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"class", EXT_GLOBAL(class_functions)); parent = (zend_class_entry *) EXT_GLOBAL(class_entry); zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"exception", EXT_GLOBAL(class_functions)); parent = (zend_class_entry *) EXT_GLOBAL(exception_class_entry); EXT_GLOBAL(exception_class_entry) = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); #endif EXT_INIT_MODULE_GLOBALS(EXT, EXT_GLOBAL(alloc_globals_ctor), NULL); assert(!EXT_GLOBAL (cfg) ); if(!EXT_GLOBAL (cfg) ) EXT_GLOBAL (cfg) = malloc(sizeof *EXT_GLOBAL (cfg) ); if(!EXT_GLOBAL (cfg) ) exit(9); if(REGISTER_INI_ENTRIES()==SUCCESS) { /* set the default values for all undefined */ extern void EXT_GLOBAL(init_cfg) (); EXT_GLOBAL(init_cfg) (); memset(&EXT_GLOBAL(cfg)->saddr, 0, sizeof EXT_GLOBAL(cfg)->saddr); #ifndef CFG_JAVA_SOCKET_INET EXT_GLOBAL(cfg)->saddr.sun_family = AF_LOCAL; memset(EXT_GLOBAL(cfg)->saddr.sun_path, 0, sizeof EXT_GLOBAL(cfg)->saddr.sun_path); strcpy(EXT_GLOBAL(cfg)->saddr.sun_path, EXT_GLOBAL(cfg)->sockname); # ifdef HAVE_ABSTRACT_NAMESPACE *EXT_GLOBAL(cfg)->saddr.sun_path=0; # endif #else EXT_GLOBAL(cfg)->saddr.sin_family = AF_INET; EXT_GLOBAL(cfg)->saddr.sin_port=htons(atoi(EXT_GLOBAL(cfg)->sockname)); EXT_GLOBAL(cfg)->saddr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); #endif } assert(!EXT_GLOBAL(ini_last_updated)); EXT_GLOBAL(ini_last_updated)=EXT_GLOBAL(ini_updated); EXT_GLOBAL(ini_updated)=0; EXT_GLOBAL(start_server) (); return SUCCESS; } PHP_MINFO_FUNCTION(EXT) { short is_local; char*s=EXT_GLOBAL(get_server_string) (); char*server = EXT_GLOBAL(test_server) (0, &is_local); short is_level = ((EXT_GLOBAL (ini_last_updated)&U_LOGLEVEL)!=0); php_info_print_table_start(); php_info_print_table_row(2, EXT_NAME()/**/" support", "Enabled"); php_info_print_table_row(2, EXT_NAME()/**/" bridge", EXT_GLOBAL(bridge_version)); #if !defined(__MINGW32__) && EXTENSION == JAVA php_info_print_table_row(2, EXT_NAME()/**/".libpath", EXT_GLOBAL(cfg)->ld_library_path); php_info_print_table_row(2, EXT_NAME()/**/".classpath", EXT_GLOBAL(cfg)->classpath); #endif #ifndef __MINGW32__ php_info_print_table_row(2, EXT_NAME()/**/"."/**/EXT_NAME()/**/"_home", EXT_GLOBAL(cfg)->vm_home); php_info_print_table_row(2, EXT_NAME()/**/"."/**/EXT_NAME(), EXT_GLOBAL(cfg)->vm); if(strlen(EXT_GLOBAL(cfg)->logFile)==0) php_info_print_table_row(2, EXT_NAME()/**/".log_file", ""); else php_info_print_table_row(2, EXT_NAME()/**/".log_file", EXT_GLOBAL(cfg)->logFile); php_info_print_table_row(2, EXT_NAME()/**/".log_level", is_level ? EXT_GLOBAL(cfg)->logLevel : "no value (use backend's default level)"); #endif php_info_print_table_row(2, EXT_NAME()/**/".hosts", EXT_GLOBAL(cfg)->hosts); #if EXTENSION == JAVA php_info_print_table_row(2, EXT_NAME()/**/".servlet", EXT_GLOBAL(get_servlet_context) ()?EXT_GLOBAL(get_servlet_context) ():"Off"); #endif #ifndef __MINGW32__ php_info_print_table_row(2, EXT_NAME()/**/" command", s); #endif php_info_print_table_row(2, EXT_NAME()/**/" status", server?"running":"not running"); php_info_print_table_row(2, EXT_NAME()/**/" server", server?server:"localhost"); php_info_print_table_end(); free(server); free(s); } PHP_MSHUTDOWN_FUNCTION(EXT) { extern void EXT_GLOBAL(shutdown_library) (); extern void EXT_GLOBAL(destroy_cfg) (int); EXT_GLOBAL(destroy_cfg) (EXT_GLOBAL(ini_last_updated)); EXT_GLOBAL(ini_last_updated)=0; UNREGISTER_INI_ENTRIES(); EXT_GLOBAL(shutdown_library) (); assert(EXT_GLOBAL (cfg)); if(EXT_GLOBAL (cfg) ) { free(EXT_GLOBAL (cfg) ); EXT_GLOBAL (cfg) = 0; } return SUCCESS; } #ifndef PHP_WRAPPER_H #error must include php_wrapper.h #endif