📄 xmlrpc-epi-php.c
字号:
outBuf = XMLRPC_REQUEST_ToXML(xResponse, &buf_len); if(outBuf) { RETVAL_STRINGL(outBuf, buf_len, 1); free(outBuf); } /* cleanup after ourselves. what a sty! */ XMLRPC_RequestFree(xResponse, 0); } } /* or as native php types? */ else { *return_value = *data.return_data; zval_copy_ctor(return_value); } /* cleanup after ourselves. what a sty! */ zval_dtor(data.xmlrpc_method); FREE_ZVAL(data.xmlrpc_method); zval_dtor(data.return_data); FREE_ZVAL(data.return_data); if(xAnswer) { XMLRPC_CleanupValue(xAnswer); } XMLRPC_RequestFree(xRequest, 1); } }}/* {{{ proto int xmlrpc_server_add_introspection_data(handle server, array desc) Adds introspection documentation */PHP_FUNCTION(xmlrpc_server_add_introspection_data){ zval *handle, *desc; int type; xmlrpc_server_data* server; /* get some params. should be 2 */ if ( !(ARG_COUNT(ht) == 2) || getParameters(ht, ARG_COUNT(ht), &handle, &desc) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } server = zend_list_find(Z_LVAL_P(handle), &type); if (type == le_xmlrpc_server) { XMLRPC_VALUE xDesc = PHP_to_XMLRPC(desc TSRMLS_CC); if (xDesc) { int retval = XMLRPC_ServerAddIntrospectionData(server->server_ptr, xDesc); XMLRPC_CleanupValue(xDesc); RETURN_LONG(retval); } } RETURN_LONG(0);}/* {{{ proto array xmlrpc_parse_method_descriptions(string xml) Decodes XML into a list of method descriptions */PHP_FUNCTION(xmlrpc_parse_method_descriptions){ zval* arg1, *retval; if( !(ARG_COUNT(ht) == 1) || getParameters(ht, ARG_COUNT(ht), &arg1) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } convert_to_string(arg1); if(return_value_used) { STRUCT_XMLRPC_ERROR err = {0}; XMLRPC_VALUE xVal = XMLRPC_IntrospectionCreateDescription(Z_STRVAL_P(arg1), &err); if(xVal) { retval = XMLRPC_to_PHP(xVal); if(retval) { *return_value = *retval; zval_copy_ctor(return_value); } /* dust, sweep, and mop */ XMLRPC_CleanupValue(xVal); } 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 create introspection data", err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error); } else { zend_error(E_WARNING, "Invalid xml structure. Unable to create introspection data"); } zend_error(E_WARNING, "xml parse error. no method description created"); } }}/************* type data *************/#define XMLRPC_TYPE_COUNT 9#define XMLRPC_VECTOR_TYPE_COUNT 4#define TYPE_STR_MAP_SIZE (XMLRPC_TYPE_COUNT + XMLRPC_VECTOR_TYPE_COUNT)/* return a string matching a given xmlrpc type */static const char** get_type_str_mapping(void){ static const char* str_mapping[TYPE_STR_MAP_SIZE]; static int first = 1; if (first) { /* warning. do not add/delete without changing size define */ str_mapping[xmlrpc_none] = "none"; str_mapping[xmlrpc_empty] = "empty"; str_mapping[xmlrpc_base64] = "base64"; str_mapping[xmlrpc_boolean] = "boolean"; str_mapping[xmlrpc_datetime] = "datetime"; str_mapping[xmlrpc_double] = "double"; str_mapping[xmlrpc_int] = "int"; str_mapping[xmlrpc_string] = "string"; str_mapping[xmlrpc_vector] = "vector"; str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_none] = "none"; str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_array] = "array"; str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_mixed] = "mixed"; str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_struct] = "struct"; first = 0; } return (const char**)str_mapping;}/* map an xmlrpc type to a string */const char* xmlrpc_type_as_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype){ const char** str_mapping = get_type_str_mapping(); if (vtype == xmlrpc_vector_none) { return str_mapping[type]; } else { return str_mapping[XMLRPC_TYPE_COUNT + vtype]; }}/* map a string to an xmlrpc type */XMLRPC_VALUE_TYPE xmlrpc_str_as_type(const char* str){ const char** str_mapping = get_type_str_mapping(); int i; if (str) { for (i = 0; i < XMLRPC_TYPE_COUNT; i++) { if (!strcmp(str_mapping[i], str)) { return (XMLRPC_VALUE_TYPE) i; } } } return xmlrpc_none;}/* map a string to an xmlrpc vector type */XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type(const char* str){ const char** str_mapping = get_type_str_mapping(); int i; if (str) { for (i = XMLRPC_TYPE_COUNT; i < TYPE_STR_MAP_SIZE; i++) { if (!strcmp(str_mapping[i], str)) { return (XMLRPC_VECTOR_TYPE) (i - XMLRPC_TYPE_COUNT); } } } return xmlrpc_none;}/* set a given value to a particular type. * note: this only works on strings, and only for date and base64, * which do not have native php types. black magic lies herein. */int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE newtype){ int bSuccess = FAILURE; /* we only really care about strings because they can represent * base64 and datetime. all other types have corresponding php types */ if (Z_TYPE_P(value) == IS_STRING) { if (newtype == xmlrpc_base64 || newtype == xmlrpc_datetime) { const char* typestr = xmlrpc_type_as_str(newtype, xmlrpc_vector_none); zval* type; MAKE_STD_ZVAL(type); Z_TYPE_P(type) = IS_STRING; Z_STRVAL_P(type) = estrdup(typestr); Z_STRLEN_P(type) = strlen(typestr); if(newtype == xmlrpc_datetime) { XMLRPC_VALUE v = XMLRPC_CreateValueDateTime_ISO8601(NULL, value->value.str.val); if(v) { time_t timestamp = XMLRPC_GetValueDateTime(v); if(timestamp) { pval* ztimestamp; MAKE_STD_ZVAL(ztimestamp); ztimestamp->type = IS_LONG; ztimestamp->value.lval = timestamp; convert_to_object(value); if(SUCCESS == zend_hash_update(value->value.obj.properties, OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void *) &type, sizeof(zval *), NULL)) { bSuccess = zend_hash_update(value->value.obj.properties, OBJECT_VALUE_TS_ATTR, sizeof(OBJECT_VALUE_TS_ATTR), (void *) &ztimestamp, sizeof(zval *), NULL); } } XMLRPC_CleanupValue(v); } } else { convert_to_object(value); bSuccess = zend_hash_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void *) &type, sizeof(zval *), NULL); } } } return bSuccess;}/* return xmlrpc type of a php value */XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue){ XMLRPC_VALUE_TYPE type = xmlrpc_none; if (value) { switch (Z_TYPE_P(value)) { case IS_NULL: type = xmlrpc_base64; break; #ifndef BOOL_AS_LONG /* Right thing to do, but it breaks some legacy code. */ case IS_BOOL: type = xmlrpc_boolean; break; #else case IS_BOOL: #endif case IS_LONG: case IS_RESOURCE: type = xmlrpc_int; break; case IS_DOUBLE: type = xmlrpc_double; break; case IS_CONSTANT: type = xmlrpc_string; break; case IS_STRING: type = xmlrpc_string; break; case IS_ARRAY: case IS_CONSTANT_ARRAY: type = xmlrpc_vector; break; case IS_OBJECT: { zval** attr; type = xmlrpc_vector; if (zend_hash_find(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void**) &attr) == SUCCESS) { if (Z_TYPE_PP(attr) == IS_STRING) { type = xmlrpc_str_as_type(Z_STRVAL_PP(attr)); } } break; } } /* if requested, return an unmolested (magic removed) copy of the value */ if (newvalue) { zval** val; if ((type == xmlrpc_base64 && Z_TYPE_P(value) != IS_NULL) || type == xmlrpc_datetime) { if (zend_hash_find(Z_OBJPROP_P(value), OBJECT_VALUE_ATTR, sizeof(OBJECT_VALUE_ATTR), (void**) &val) == SUCCESS) { *newvalue = *val; } } else { *newvalue = value; } } } return type;}/* {{{ proto bool xmlrpc_set_type(string value, string type) Sets xmlrpc type, base64 or datetime, for a PHP string value */PHP_FUNCTION(xmlrpc_set_type){ zval* arg, *type; XMLRPC_VALUE_TYPE vtype; if (!(ARG_COUNT(ht) == 2) || getParameters(ht, ARG_COUNT(ht), &arg, &type) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ }#if ZEND_MODULE_API_NO < 20010901 if (!ParameterPassedByReference(ht,1)) { zend_error(E_WARNING,"first argument to xmlrpc_set_type() passed by value, expecting reference"); }#endif convert_to_string(type); vtype = xmlrpc_str_as_type(Z_STRVAL_P(type)); if (vtype != xmlrpc_none) { if (set_zval_xmlrpc_type(arg, vtype) == SUCCESS) { RETURN_TRUE; } } else { zend_error(E_WARNING,"invalid type '%s' passed to xmlrpc_set_type()", Z_STRVAL_P(type)); } RETURN_FALSE;}/* {{{ proto string xmlrpc_get_type(mixed value) Gets xmlrpc type for a PHP value. Especially useful for base64 and datetime strings */PHP_FUNCTION(xmlrpc_get_type){ zval* arg; XMLRPC_VALUE_TYPE type; XMLRPC_VECTOR_TYPE vtype = xmlrpc_vector_none; if (!(ARG_COUNT(ht) == 1) || getParameters(ht, ARG_COUNT(ht), &arg) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } type = get_zval_xmlrpc_type(arg, 0); if (type == xmlrpc_vector) { vtype = determine_vector_type((Z_TYPE_P(arg) == IS_OBJECT) ? Z_OBJPROP_P(arg) : Z_ARRVAL_P(arg)); } RETURN_STRING((char*) xmlrpc_type_as_str(type, vtype), 1);}/* {{{ proto bool xmlrpc_is_fault(array) Determines if an array value represents an XMLRPC fault. */PHP_FUNCTION(xmlrpc_is_fault){ zval* arg, **val; if (!(ARG_COUNT(ht) == 1) || getParameters(ht, ARG_COUNT(ht), &arg) == FAILURE) { WRONG_PARAM_COUNT; /* prints/logs a warning and returns */ } if (Z_TYPE_P(arg) != IS_ARRAY) { php_error(E_NOTICE, "%s(): Array argument expected", get_active_function_name(TSRMLS_C)); } else { /* The "correct" way to do this would be to call the xmlrpc * library XMLRPC_ValueIsFault() func. However, doing that * would require us to create an xmlrpc value from the php * array, which is rather expensive, especially if it was * a big array. Thus, we resort to this not so clever hackery. */ if( zend_hash_find(Z_ARRVAL_P(arg), FAULT_CODE, FAULT_CODE_LEN + 1, (void**) &val) == SUCCESS && zend_hash_find(Z_ARRVAL_P(arg), FAULT_STRING, FAULT_STRING_LEN + 1, (void**) &val) == SUCCESS) { RETURN_TRUE; } } RETURN_FALSE;}/* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -