📄 xmlrpc-epi-php.c
字号:
#endif convert_to_string(xml); convert_to_string(method); if(ARG_COUNT(ht) == 3) { convert_to_string(encoding); } if(return_value_used) { zval* retval = decode_request_worker(xml, encoding, method); if(retval) { *return_value = *retval; FREE_ZVAL(retval); } }}/* }}} *//* {{{ proto array xmlrpc_decode(string xml [, string encoding]) Decodes XML into native PHP types */PHP_FUNCTION(xmlrpc_decode){ zval* arg1, *arg2 = NULL; if( !(ARG_COUNT(ht) == 1 || ARG_COUNT(ht) == 2) || getParameters(ht, ARG_COUNT(ht), &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } convert_to_string(arg1); if(ARG_COUNT(ht) == 2) { convert_to_string(arg2); } if(return_value_used) { zval* retval = decode_request_worker(arg1, arg2, NULL); if(retval) { *return_value = *retval; FREE_ZVAL(retval); } }}/* }}} *//************************** server related methods **************************//* {{{ proto handle xmlrpc_server_create(void) Creates an xmlrpc server */PHP_FUNCTION(xmlrpc_server_create){ if(ARG_COUNT(ht) != 0) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } if(return_value_used) { zval *method_map, *introspection_map; MAKE_STD_ZVAL(method_map); MAKE_STD_ZVAL(introspection_map); if(array_init(method_map) == SUCCESS && array_init(introspection_map) == SUCCESS) { /* allocate server data. free'd in destroy_server_data() */ xmlrpc_server_data *server = emalloc(sizeof(xmlrpc_server_data)); if(server) { server->method_map = method_map; server->introspection_map = introspection_map; server->server_ptr = XMLRPC_ServerCreate(); XMLRPC_ServerRegisterIntrospectionCallback(server->server_ptr, php_xmlrpc_introspection_callback); /* store for later use */ ZEND_REGISTER_RESOURCE(return_value,server, le_xmlrpc_server); } } }}/* {{{ proto int xmlrpc_server_destroy(handle server) Destroys server resources */PHP_FUNCTION(xmlrpc_server_destroy){ zval* arg1; int bSuccess = FAILURE; if(ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } if(Z_TYPE_P(arg1) == IS_RESOURCE) { int type; xmlrpc_server_data *server = zend_list_find(Z_LVAL_P(arg1), &type); if(server && type == le_xmlrpc_server) { bSuccess = zend_list_delete(Z_LVAL_P(arg1)); /* called by hashtable destructor * destroy_server_data(server); */ } } RETVAL_LONG(bSuccess == SUCCESS);} /* called by xmlrpc C engine as method handler for all registered methods. * it then calls the corresponding PHP function to handle the method. */static XMLRPC_VALUE php_xmlrpc_callback(XMLRPC_SERVER server, XMLRPC_REQUEST xRequest, void* data){ xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data; zval* xmlrpc_params; zval* callback_params[3]; TSRMLS_FETCH(); /* convert xmlrpc to native php types */ xmlrpc_params = XMLRPC_to_PHP(XMLRPC_RequestGetData(xRequest)); /* setup data hoojum */ callback_params[0] = pData->xmlrpc_method; callback_params[1] = xmlrpc_params; callback_params[2] = pData->caller_params; /* Use same C function for all methods */ /* php func prototype: function user_func($method_name, $xmlrpc_params, $user_params) */ call_user_function(CG(function_table), NULL, pData->php_function, pData->return_data, 3, callback_params TSRMLS_CC); pData->php_executed = 1; zval_dtor(xmlrpc_params); FREE_ZVAL(xmlrpc_params); return NULL;}/* called by the C server when it first receives an introspection request. We pass this on to * our PHP listeners, if any */static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data){ zval *retval_ptr, **php_function; zval* callback_params[1]; xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data; TSRMLS_FETCH(); MAKE_STD_ZVAL(retval_ptr); Z_TYPE_P(retval_ptr) = IS_NULL; /* setup data hoojum */ callback_params[0] = pData->caller_params; /* loop through and call all registered callbacks */ zend_hash_internal_pointer_reset(Z_ARRVAL_P(pData->server->introspection_map)); while(1) { if(zend_hash_get_current_data(Z_ARRVAL_P(pData->server->introspection_map), (void**)&php_function) == SUCCESS) { /* php func prototype: function string user_func($user_params) */ if(call_user_function(CG(function_table), NULL, *php_function, retval_ptr, 1, callback_params TSRMLS_CC) == SUCCESS) { XMLRPC_VALUE xData; STRUCT_XMLRPC_ERROR err = {0}; /* return value should be a string */ convert_to_string(retval_ptr); xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL_P(retval_ptr), &err); if(xData) { if(!XMLRPC_ServerAddIntrospectionData(server, xData)) { zend_error(E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", Z_STRVAL_PP(php_function)); } XMLRPC_CleanupValue(xData); } else { /* could not create description */ if(err.xml_elem_error.parser_code) { zend_error(E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %s()", err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, Z_STRVAL_PP(php_function)); } else { zend_error(E_WARNING, "Unable to add introspection data returned from %s()", Z_STRVAL_PP(php_function)); } } } else { /* user func failed */ zend_error(E_WARNING, "Error calling user introspection callback: %s()", Z_STRVAL_PP(php_function)); } } else { break; } zend_hash_move_forward(Z_ARRVAL_P(pData->server->introspection_map)); } /* so we don't call the same callbacks ever again */ zend_hash_clean(Z_ARRVAL_P(pData->server->introspection_map));}/* {{{ proto bool xmlrpc_server_register_method(handle server, string method_name, string function) Register a PHP function to handle method matching method_name */PHP_FUNCTION(xmlrpc_server_register_method){ zval* method_key, *method_name, *handle, *method_name_save; int type; xmlrpc_server_data* server; /* get some params. should be 3 */ if( !(ARG_COUNT(ht) == 3) || getParameters(ht, ARG_COUNT(ht), &handle, &method_key, &method_name) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } server = zend_list_find(Z_LVAL_P(handle), &type); if(type == le_xmlrpc_server) { /* register with C engine. every method just calls our standard callback, * and it then dispatches to php as necessary */ if(XMLRPC_ServerRegisterMethod(server->server_ptr, Z_STRVAL_P(method_key), php_xmlrpc_callback)) { /* save for later use */ MAKE_STD_ZVAL(method_name_save); *method_name_save = *method_name; zval_copy_ctor(method_name_save); /* register our php method */ add_zval(server->method_map, Z_STRVAL_P(method_key), &method_name_save); RETURN_BOOL(1); } } RETURN_BOOL(0);}/* {{{ proto bool xmlrpc_server_register_introspection_callback(handle server, string function) Register a PHP function to generate documentation */PHP_FUNCTION(xmlrpc_server_register_introspection_callback){ zval* method_name, *handle, *method_name_save; int type; xmlrpc_server_data* server; /* get some params. should be 2 */ if( !(ARG_COUNT(ht) == 2) || getParameters(ht, ARG_COUNT(ht), &handle, &method_name) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } server = zend_list_find(Z_LVAL_P(handle), &type); if(type == le_xmlrpc_server) { { /* save for later use */ MAKE_STD_ZVAL(method_name_save); *method_name_save = *method_name; zval_copy_ctor(method_name_save); /* register our php method */ add_zval(server->introspection_map, NULL, &method_name_save); RETURN_BOOL(1); } } RETURN_BOOL(0);}/* this function is itchin for a re-write *//* {{{ proto mixed xmlrpc_server_call_method(handle server, string xml, mixed user_data [, array output_options]) Parses XML requests and call methods */PHP_FUNCTION(xmlrpc_server_call_method){ xmlrpc_callback_data data = {0}; XMLRPC_REQUEST xRequest; STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS input_opts; xmlrpc_server_data* server; zval *rawxml, *caller_params, *handle, *output_opts; int type; php_output_options out; /* get params. 3 or 4 params ok */ if(ARG_COUNT(ht) == 4) { if(getParameters(ht, ARG_COUNT(ht), &handle, &rawxml, &caller_params, &output_opts) != SUCCESS) { WRONG_PARAM_COUNT; } /* user output options */ set_output_options(&out, output_opts); } else if(ARG_COUNT(ht) == 3) { if(getParameters(ht, ARG_COUNT(ht), &handle, &rawxml, &caller_params) != SUCCESS) { WRONG_PARAM_COUNT; } /* user output options */ set_output_options(&out, NULL); } else { WRONG_PARAM_COUNT; } server = zend_list_find(Z_LVAL_P(handle), &type); if(type == le_xmlrpc_server) { /* HACK: use output encoding for now */ input_opts.xml_elem_opts.encoding = utf8_get_encoding_id_from_string(out.xmlrpc_out.xml_elem_opts.encoding); /* generate an XMLRPC_REQUEST from the raw xml input */ xRequest = XMLRPC_REQUEST_FromXML(Z_STRVAL_P(rawxml), Z_STRLEN_P(rawxml), &input_opts); if(xRequest) { const char* methodname = XMLRPC_RequestGetMethodName(xRequest); zval** php_function; XMLRPC_VALUE xAnswer = NULL; MAKE_STD_ZVAL(data.xmlrpc_method); /* init. very important. spent a frustrating day finding this out. */ MAKE_STD_ZVAL(data.return_data); Z_TYPE_P(data.return_data) = IS_NULL; /* in case value is never init'd, we don't dtor to think it is a string or something */ Z_TYPE_P(data.xmlrpc_method) = IS_NULL; if (!methodname) { methodname = ""; } /* setup some data to pass to the callback function */ Z_STRVAL_P(data.xmlrpc_method) = estrdup(methodname); Z_STRLEN_P(data.xmlrpc_method) = strlen(methodname); Z_TYPE_P(data.xmlrpc_method) = IS_STRING; data.caller_params = caller_params; data.php_executed = 0; data.server = server; /* check if the called method has been previous registered */ if(zend_hash_find(Z_ARRVAL_P(server->method_map), Z_STRVAL_P(data.xmlrpc_method), Z_STRLEN_P(data.xmlrpc_method) + 1, (void**)&php_function) == SUCCESS) { data.php_function = *php_function; } /* We could just call the php method directly ourselves at this point, but we do this * with a C callback in case the xmlrpc library ever implements some cool usage stats, * or somesuch. */ xAnswer = XMLRPC_ServerCallMethod(server->server_ptr, xRequest, &data); if(xAnswer) { if(out.b_php_out) { zval_dtor(data.return_data); FREE_ZVAL(data.return_data); data.return_data = XMLRPC_to_PHP(xAnswer); } } else if(data.php_executed) { if(!out.b_php_out) { xAnswer = PHP_to_XMLRPC(data.return_data TSRMLS_CC); } } /* should we return data as xml? */ if(!out.b_php_out) { XMLRPC_REQUEST xResponse = XMLRPC_RequestNew(); if(xResponse) { char* outBuf = 0; int buf_len = 0; /* automagically determine output serialization type from request type */ if (out.b_auto_version) { XMLRPC_REQUEST_OUTPUT_OPTIONS opts = XMLRPC_RequestGetOutputOptions(xRequest); if (opts) { out.xmlrpc_out.version = opts->version; } } /* set some required request hoojum */ XMLRPC_RequestSetOutputOptions(xResponse, &out.xmlrpc_out); XMLRPC_RequestSetRequestType(xResponse, xmlrpc_request_response); XMLRPC_RequestSetData(xResponse, xAnswer); XMLRPC_RequestSetMethodName(xResponse, methodname); /* generate xml */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -