cvs: pecl /xmlrpci CREDITS EXPERIMENTAL config.m4 config.w32 php_xmlrpci.h xmlrpci.c

From: Date: Mon, 14 Feb 2005 01:25:28 +0000
Subject: cvs: pecl /xmlrpci CREDITS EXPERIMENTAL config.m4 config.w32 php_xmlrpci.h xmlrpci.c
Groups: php.pecl.cvs 
Request: Send a blank email to pecl-cvs+get-2559@lists.php.net to get a copy of this message
john Sun Feb 13 20:25:28 2005 EDT Added files: /pecl/xmlrpci CREDITS EXPERIMENTAL config.m4 config.w32 php_xmlrpci.h xmlrpci.c Log: Adding the first 'working' version of XML-RPCi to PECL

http://cvs.php.net/co.php/pecl/xmlrpci/config.m4?r=1.1&p=1 Index: pecl/xmlrpci/config.m4 +++ pecl/xmlrpci/config.m4 dnl $Id: config.m4,v 1.1 2005/02/14 01:25:28 john Exp $ dnl config.m4 for extension xmlrpci PHP_ARG_ENABLE(xmlrpci, whether to enable improved XML-RPC support, [ --enable-xmlrpci Include improved XML-RPC support.]) if test -z "$PHP_LIBXML_DIR"; then PHP_ARG_WITH(libxml-dir, libxml2 install dir, [ --with-libxml-dir=DIR XML: libxml2 install prefix], no, no) fi if test "$PHP_XMLRPCI" != "no" && test "$PHP_LIBXML" != "no"; then PHP_SETUP_LIBXML(SOAP_SHARED_LIBADD, [ AC_DEFINE(HAVE_XMLRPCI,1,[ ]) PHP_NEW_EXTENSION(xmlrpci, xmlrpci.c, $ext_shared) PHP_SUBST(XMLRPCI_SHARED_LIBADD) ], [ AC_MSG_ERROR([xml2-config not found. Please check your libxml2 installation.]) ]) fi http://cvs.php.net/co.php/pecl/xmlrpci/config.w32?r=1.1&p=1 Index: pecl/xmlrpci/config.w32 +++ pecl/xmlrpci/config.w32 // $Id: config.w32,v 1.1 2005/02/14 01:25:28 john Exp $ // vim:ft=javascript ARG_ENABLE("xmlrpci", "Improved XML-RPC support", "no"); if (PHP_XMLRPCI != "no" && PHP_LIBXML == "yes") { EXTENSION('xmlrpci', 'xmlrpci.c'); AC_DEFINE('HAVE_PHP_XMLRPCI', 1, "Improved XML-RPCI support"); if (!PHP_SOAP_SHARED) { ADD_FLAG('CFLAGS_SOAP', "/D LIBXML_STATIC "); } ADD_EXTENSION_DEP('xmlrpci', 'libxml'); } http://cvs.php.net/co.php/pecl/xmlrpci/php_xmlrpci.h?r=1.1&p=1 Index: pecl/xmlrpci/php_xmlrpci.h +++ pecl/xmlrpci/php_xmlrpci.h /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 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_0.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: John Coggeshall <john@php.net> | +----------------------------------------------------------------------+ */ /* $Id: php_xmlrpci.h,v 1.1 2005/02/14 01:25:28 john Exp $ */ #ifndef PHP_XMLRPCI_H #define PHP_XMLRPCI_H #define XMLRPCI_VERSION "broken" #define XMLRPC_DATETIME_FORMAT "Ymd\\TH:i:s" extern zend_module_entry xmlrpci_module_entry; #define phpext_xmlrpci_ptr &xmlrpci_module_entry #ifdef PHP_WIN32 #define PHP_XMLRPCI_API __declspec(dllexport) #else #define PHP_XMLRPCI_API #endif #ifdef ZTS #include "TSRM.h" #endif #include <libxml/parser.h> #include <libxml/xpath.h> #ifdef HAVE_PHP_DOMXML # include "ext/domxml/php_domxml.h" #endif #ifndef PHP_HAVE_STREAMS # error You lose - must be compiled against PHP 4.3.0 or later #endif #ifndef PHP_WIN32 # define TRUE 1 # define FALSE 0 # define stricmp strcasecmp #endif #define XMLRPCI_METHOD_MAP(name, func_name, arg_types) \ ZEND_NAMED_FE(name, ZEND_FN(func_name), arg_types) #define XMLRPCI_RPC_METHOD(name) PHP_FUNCTION(xmlrpci_rpc_ ##name) #define XMLRPCI_RPC_ME(name, param) XMLRPCI_METHOD_MAP(name, xmlrpci_rpc_ ##name, param) #define XMLRPCI_VAL_METHOD(name) PHP_FUNCTION(xmlrpci_val_ ##name) #define XMLRPCI_VAL_ME(name, param) XMLRPCI_METHOD_MAP(name, xmlrpci_val_ ##name, param) #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif PHP_MINIT_FUNCTION(xmlrpci); PHP_MSHUTDOWN_FUNCTION(xmlrpci); PHP_RINIT_FUNCTION(xmlrpci); PHP_RSHUTDOWN_FUNCTION(xmlrpci); PHP_MINFO_FUNCTION(xmlrpci); XMLRPCI_RPC_METHOD(__construct); XMLRPCI_VAL_METHOD(__construct); #define XMLRPC_DATETIME 0 #define XMLRPC_BASE64 1 #endif /* PHP_XMLRPCI_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ http://cvs.php.net/co.php/pecl/xmlrpci/xmlrpci.c?r=1.1&p=1 Index: pecl/xmlrpci/xmlrpci.c +++ pecl/xmlrpci/xmlrpci.c /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 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_0.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: John Coggeshall <john@php.net> | +----------------------------------------------------------------------+ */ /* $Id: xmlrpci.c,v 1.1 2005/02/14 01:25:28 john Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "ext/standard/base64.h" #include "ext/standard/php_parsedate.h" #include "ext/standard/php_smart_str.h" #include "safe_mode.h" #include "Zend/zend_exceptions.h" #include "Zend/zend_object_handlers.h" #include "Zend/zend_API.h" #include "php_xmlrpci.h" static void xmlrpci_object_free_storage(void * TSRMLS_DC); static zend_object_value xmlrpci_object_new_rpc(zend_class_entry * TSRMLS_DC); static zval * xmlrpci_instanciate(zend_class_entry *, zval * TSRMLS_DC); static int xmlrpci_method_call_handler(char *, INTERNAL_FUNCTION_PARAMETERS); static union _zend_function *xmlrpci_method_get_handler(zval **, char *, int TSRMLS_DD); static void xmlrpci_add_node_from_zval(xmlNodePtr, zval * TSRMLS_DC); static zval *xmlrpci_return_zval_from_value_node(xmlNodePtr TSRMLS_DC); #define REGISTER_XMLRPCI_CLASS(classname, name, parent, __flags) \ { \ zend_class_entry ce; \ INIT_CLASS_ENTRY(ce, # classname, xmlrpci_funcs_ ## name); \ ce.create_object = xmlrpci_object_new_ ## name; \ xmlrpci_ce_ ## name = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \ xmlrpci_ce_ ## name->ce_flags |= __flags; \ memcpy(&xmlrpci_object_handlers_ ## name, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \ xmlrpci_object_handlers_ ## name.clone_obj = NULL; \ xmlrpci_object_handlers_ ## name.get_class_entry = xmlrpci_get_ce_ ## name; \ } #define XMLRPCI_SET_CONTEXT \ zval *object; \ object = getThis(); typedef enum { is_rpc, is_val } xmlrpci_obj_type; typedef struct _XMLRPCI_RPCObj XMLRPCI_Obj; struct _XMLRPCI_RPCObj { zend_object std; xmlrpci_obj_type type; /* for rpc objects */ char *server_addy; php_stream_context *context; /* for val objects */ int val_type; unsigned long timestamp; unsigned char *base64_data; }; static zend_class_entry *xmlrpci_ce_rpc; static zend_class_entry *xmlrpci_ce_val; static zend_object_handlers xmlrpci_object_handlers_rpc; static zend_object_handlers xmlrpci_object_handlers_val; function_entry xmlrpci_functions[] = { {NULL, NULL, NULL} }; function_entry xmlrpci_funcs_rpc[] = { XMLRPCI_RPC_ME(__construct, NULL) {NULL, NULL, NULL} }; function_entry xmlrpci_funcs_val[] = { XMLRPCI_VAL_ME(__construct, NULL) {NULL, NULL, NULL} }; zend_module_entry xmlrpci_module_entry = { STANDARD_MODULE_HEADER, "xmlrpci", xmlrpci_functions, PHP_MINIT(xmlrpci), PHP_MSHUTDOWN(xmlrpci), NULL, NULL, PHP_MINFO(xmlrpci), XMLRPCI_VERSION, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_XMLRPCI ZEND_GET_MODULE(xmlrpci) #endif static zend_class_entry *xmlrpci_get_ce_rpc(zval *object TSRMLS_DC) { return xmlrpci_ce_rpc; } static zend_class_entry *xmlrpci_get_ce_val(zval *object TSRMLS_DC) { return xmlrpci_ce_val; } static void xmlrpci_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval, xmlrpci_obj_type objtype TSRMLS_DC) { XMLRPCI_Obj *intern; zval *tmp; intern = emalloc(sizeof(XMLRPCI_Obj)); memset(intern, 0, sizeof(XMLRPCI_Obj)); intern->std.ce = class_type; ALLOC_HASHTABLE(intern->std.properties); zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); switch(objtype) { case is_rpc: break; case is_val: break; default: break; } retval->handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) xmlrpci_object_free_storage, NULL TSRMLS_CC); retval->handlers = handlers; } static zval * xmlrpci_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC) { if (!object) { ALLOC_ZVAL(object); } Z_TYPE_P(object) = IS_OBJECT; object_init_ex(object, pce); object->refcount = 1; object->is_ref = 1; return object; } static zend_object_value xmlrpci_object_new_rpc(zend_class_entry *class_type TSRMLS_DC) { zend_object_value retval; xmlrpci_object_new(class_type, &xmlrpci_object_handlers_rpc, &retval, is_rpc TSRMLS_CC); return retval; } static zend_object_value xmlrpci_object_new_val(zend_class_entry *class_type TSRMLS_DC) { zend_object_value retval; xmlrpci_object_new(class_type, &xmlrpci_object_handlers_val, &retval, is_val TSRMLS_CC); return retval; } static void xmlrpci_object_free_storage(void *object TSRMLS_DC) { XMLRPCI_Obj *intern = (XMLRPCI_Obj *)object; zend_hash_destroy(intern->std.properties); FREE_HASHTABLE(intern->std.properties); if(intern->server_addy) { efree(intern->server_addy); } if(intern->base64_data) { efree(intern->base64_data); } if(intern->context) { php_stream_context_free(intern->context); } efree(object); } PHP_MINIT_FUNCTION(xmlrpci) { REGISTER_XMLRPCI_CLASS(xmlrpc, rpc, NULL, 0); REGISTER_XMLRPCI_CLASS(xmlrpcval, val, NULL, ZEND_ACC_FINAL_CLASS); xmlrpci_object_handlers_rpc.call_method = xmlrpci_method_call_handler; xmlrpci_object_handlers_rpc.get_method = xmlrpci_method_get_handler; REGISTER_LONG_CONSTANT("XMLRPC_DATETIME", XMLRPC_DATETIME, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XMLRPC_BASE64", XMLRPC_BASE64, CONST_CS | CONST_PERSISTENT); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(xmlrpci) { xmlCleanupParser(); return SUCCESS; } /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(xmlrpci) { php_info_print_table_start(); php_info_print_table_header(2, "XML-RPCi support", "enabled"); php_info_print_table_end(); } /* }}} */ static PHP_FUNCTION(xmlrpci_method_handler) { Z_OBJ_HANDLER_P(getThis(), call_method)( ((zend_internal_function*)EG(function_state_ptr)->function)->function_name, INTERNAL_FUNCTION_PARAM_PASSTHRU); } static void xmlrpci_add_val_class_node(xmlNodePtr value, XMLRPCI_Obj *obj) { zval *datestr = NULL; zval *params[2]; zval *fbc; switch(obj->val_type) { case XMLRPC_DATETIME: MAKE_STD_ZVAL(datestr); MAKE_STD_ZVAL(fbc); MAKE_STD_ZVAL(params[0]); MAKE_STD_ZVAL(params[1]); ZVAL_STRING(fbc, "date", 1); ZVAL_STRING(params[0], XMLRPC_DATETIME_FORMAT, 1); ZVAL_LONG(params[1], obj->timestamp); if(call_user_function(EG(function_table), NULL, fbc, datestr, 2, params TSRMLS_CC) == FAILURE) { zend_error(E_WARNING, "Could not call formatted date..."); } xmlNewChild(value, NULL, "dateTime.iso8601", Z_STRVAL_P(datestr)); zval_ptr_dtor(&fbc); zval_ptr_dtor(&datestr); zval_ptr_dtor(&params[0]); zval_ptr_dtor(&params[1]); break; case XMLRPC_BASE64: xmlNewChild(value, NULL, "base64", obj->base64_data); break; default: /** Error condition **/ break; } } /* there has got to be a better way.... */ static int xmlrpci_is_hash_assoc(HashTable *hash) { HashPosition pos; char *string_key; uint string_key_len; ulong num_key; zval **entry; zend_hash_internal_pointer_reset_ex(hash, &pos); while(zend_hash_get_current_data_ex(hash, (void **)&entry, &pos) == SUCCESS) { if(zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, FALSE, &pos) == HASH_KEY_IS_STRING) { return TRUE; } zend_hash_move_forward_ex(hash, &pos); } return FALSE; } static void xmlrpci_add_array_node(xmlNodePtr value, zval *array) { xmlNodePtr data, structnode, member; HashPosition pos; HashTable *hash; zval **entry; char *string_key = NULL; uint string_key_len; ulong num_key; char num_string[128]; hash = Z_ARRVAL_P(array); if(xmlrpci_is_hash_assoc(hash)) { structnode = xmlNewChild(value, NULL, "struct", NULL); zend_hash_internal_pointer_reset_ex(hash, &pos); while(zend_hash_get_current_data_ex(hash, (void **)&entry, &pos) == SUCCESS) { member = xmlNewChild(structnode, NULL, "member", NULL); if(zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, TRUE, &pos) == HASH_KEY_IS_LONG) { php_sprintf(num_string, "%ld", num_key); string_key = (char *)&num_string; } xmlNewChild(member, NULL, "name", string_key); xmlrpci_add_node_from_zval(xmlNewChild(member, NULL, "value", NULL), *entry TSRMLS_CC); if(string_key && (string_key != (char *)&num_string)) { efree(string_key); string_key = NULL; } zend_hash_move_forward_ex(hash, &pos); } } else { data = xmlNewChild(xmlNewChild(value, NULL, "array", NULL), NULL, "data", NULL); zend_hash_internal_pointer_reset_ex(hash, &pos); while(zend_hash_get_current_data_ex(hash, (void **)&entry, &pos) == SUCCESS) { xmlrpci_add_node_from_zval(xmlNewChild(data, NULL, "value", NULL), *entry TSRMLS_CC); zend_hash_move_forward_ex(hash, &pos); } } } static void xmlrpci_add_node_from_zval(xmlNodePtr parent, zval *value TSRMLS_DC) { switch(Z_TYPE_P(value)) { case IS_STRING: convert_to_string(value); xmlNewChild(parent, NULL, "string", Z_STRVAL_P(value)); break; case IS_LONG: convert_to_string(value); xmlNewChild(parent, NULL, "int", Z_STRVAL_P(value)); break; case IS_DOUBLE: convert_to_string(value); xmlNewChild(parent, NULL, "double", Z_STRVAL_P(value)); break; case IS_BOOL: xmlNewChild(parent, NULL, "boolean", Z_LVAL_P(value) ? "1" : "0"); break; case IS_OBJECT: /** TODO: Add check to make sure the object is actually ours.. */ xmlrpci_add_val_class_node(parent, (XMLRPCI_Obj *)zend_object_store_get_object(value TSRMLS_CC)); break; case IS_ARRAY: xmlrpci_add_array_node(parent, value); break; } } static void xmlrpci_add_param_nodes(xmlNodePtr params, int nargs, zval ***args TSRMLS_DC) { int i; zval *tmp; xmlNodePtr value; for (i = nargs-1; i >= 0; i--) { tmp = *args[nargs - i - 1]; ZVAL_ADDREF(tmp); SEPARATE_ZVAL(&tmp); value = xmlNewChild(xmlNewChild(params, NULL, "param", NULL), NULL, "value", NULL); xmlrpci_add_node_from_zval(value, tmp); zval_ptr_dtor(&tmp); } } static xmlDocPtr xmlrpci_perform_rpc_call(XMLRPCI_Obj *obj, char *request) { php_stream_context *context = php_stream_context_alloc(); php_stream *stream; smart_str response = {0}; char *buf = emalloc(1024); xmlDocPtr retval; zval *method; zval *content; zval *headers; MAKE_STD_ZVAL(headers); MAKE_STD_ZVAL(method); MAKE_STD_ZVAL(content); ZVAL_STRING(method, "POST", 1); ZVAL_STRING(content, request, 1); ZVAL_STRING(headers, "Content-type: text/xml", 1); php_stream_context_set_option(context, "http", "method", method); php_stream_context_set_option(context, "http", "content", content); php_stream_context_set_option(context, "http", "header", headers); zval_ptr_dtor(&method); zval_ptr_dtor(&content); zval_ptr_dtor(&headers); stream = php_stream_open_wrapper_ex(obj->server_addy, "rb", 0, NULL, context); if(!stream) { zend_error(E_ERROR, "Couldn't open stream!"); return NULL; } while(!php_stream_eof(stream)) { if(php_stream_gets(stream, buf, 1024)) { smart_str_appends(&response, buf); } else { break; } } smart_str_0(&response); retval = xmlReadMemory(response.c, response.len, "xmlrpc_response.xml", NULL, 0); php_stream_close(stream); smart_str_free(&response); efree(buf); return retval; } static xmlNodePtr xmlrpci_find_node_by_name(xmlNodePtr node, char *name) { xmlNode *cur_node = NULL, *res = NULL; for(cur_node = node; cur_node; cur_node = cur_node->next) { if(cur_node->type == XML_ELEMENT_NODE) { if(!strcmp(cur_node->name, name)) { return cur_node; } } res = xmlrpci_find_node_by_name(cur_node->children, name); if(res) { return res; } } return NULL; } /* sorta hackish, but the struct is static and this is fast. */ static void xmlrpci_generate_fault(xmlNodePtr node, INTERNAL_FUNCTION_PARAMETERS) { char *code = NULL, *message = NULL; if(node->children) if(node->children->next) if(node->children->next->next) if(node->children->next->next->next) if(node->children->next->next->next->children) if(node->children->next->next->next->children->next) if(node->children->next->next->next->children->next->children) { code = estrdup(node->children->next->next->next->children->next->children->content); } if(node->next) if(node->next->next) if(node->next->next->children) if(node->next->next->children->next) if(node->next->next->children->next->next) if(node->next->next->children->next->next->next) if(node->next->next->children->next->next->next->children) if(node->next->next->children->next->next->next->children->next) if(node->next->next->children->next->next->next->children->next->children) { message = estrdup(node->next->next->children->next->next->next->children->next->children->content); } if(!code || !message) { zend_throw_exception_ex(zend_exception_get_default(), -1, "XML-RPC fault received, but had invalid response"); } else { zval *zcode; MAKE_STD_ZVAL(zcode); ZVAL_STRING(zcode, code, FALSE); convert_to_long(zcode); zend_throw_exception_ex(zend_exception_get_default(), Z_LVAL_P(zcode), message); zval_ptr_dtor(&zcode); } if(code) { efree(code); } if(message) { efree(message); } } #define xmlrpci_subnode(__node) ((__node->children) ? ((__node->children->next) ? (__node->children->next) : (__node->children)) : NULL) #define xmlrpci_subnode_name(__node) xmlrpci_subnode(__node)->name #define xmlrpci_subnode_value(__node) xmlrpci_subnode(__node)->content #define xmlrpci_subsubnode(__node) xmlrpci_subnode(xmlrpci_subnode(__node)) #define xmlrpci_node_name(__node) (__node->name) #define xmlrpci_node_type(__node, __type) (!strcmp(xmlrpci_node_name(__node), #__type)) #define xmlrpci_node_value(__node) (__node->content) #define xmlrpci_next_node(__node) ((__node->next) ? (__node->next->next) ? __node->next->next : __node->next : NULL) static inline void xmlrpci_add_member_to_zval(xmlNodePtr member, zval *array TSRMLS_DC) { xmlNodePtr submember; char *key = NULL; zval *val; if(Z_TYPE_P(array) != IS_ARRAY) { return; } if(!xmlrpci_node_type(member, member)) { return; } submember = xmlrpci_subnode(member); if(xmlrpci_node_type(submember, name)) { key = estrdup(xmlrpci_node_value(xmlrpci_subnode(submember))); submember = xmlrpci_next_node(xmlrpci_subnode(member)); if(!xmlrpci_node_type(submember, value)) { if(key) efree(key); return; } else { val = xmlrpci_return_zval_from_value_node(submember TSRMLS_CC); } } else if(xmlrpci_node_type(submember, value)) { val = xmlrpci_return_zval_from_value_node(submember TSRMLS_CC); submember = xmlrpci_next_node(xmlrpci_subnode(member)); if(!xmlrpci_node_type(submember, value)) { zval_ptr_dtor(&val); return; } else { val = xmlrpci_return_zval_from_value_node(submember TSRMLS_CC); } key = estrdup(xmlrpci_node_value(submember)); } add_assoc_zval(array, key, val); if(key) { efree(key); } } static inline zval *xmlrpci_struct_from_value_node(xmlNodePtr node TSRMLS_DC) { zval *t; xmlNodePtr cur_member; MAKE_STD_ZVAL(t); if(!xmlrpci_node_type(node, value)) { ZVAL_NULL(t) return t; } // Advance to struct node... node = xmlrpci_subnode(node); if(!xmlrpci_node_type(xmlrpci_subnode(node), member)) { /* Should have at least one <member> node */ ZVAL_NULL(t) return t; } cur_member = xmlrpci_subnode(node); array_init(t); do { xmlrpci_add_member_to_zval(cur_member, t TSRMLS_CC); } while((cur_member = xmlrpci_next_node(cur_member))); return t; } static inline zval *xmlrpci_array_from_value_node(xmlNodePtr node TSRMLS_DC) { zval *t; xmlNodePtr cur_index; MAKE_STD_ZVAL(t); if(!xmlrpci_node_type(node, value)) { ZVAL_NULL(t); return t; } if(!xmlrpci_node_type(xmlrpci_subnode(node), array)) { ZVAL_NULL(t); return t; } if(!xmlrpci_node_type(xmlrpci_subsubnode(node), data)) { ZVAL_NULL(t); return t; } array_init(t); if(xmlrpci_subnode(xmlrpci_subsubnode(node))) { cur_index = xmlrpci_subnode(xmlrpci_subsubnode(node)); do { zval *temp = xmlrpci_return_zval_from_value_node(cur_index TSRMLS_CC); if(temp) { add_next_index_zval(t, temp); } } while((cur_index = xmlrpci_next_node(cur_index))); } return t; } static inline zval *xmlrpci_datetime_from_value_node(xmlNodePtr node TSRMLS_DC) { zval *t; MAKE_STD_ZVAL(t); if(!xmlrpci_node_type(node, value)) { ZVAL_NULL(t); return t; } if(!xmlrpci_subnode(node)) { /** ERROR, should have been something here. */ ZVAL_NULL(t) return t; } if(!xmlrpci_node_type(xmlrpci_subnode(node), dateTime.iso8601)) { /* ERROR, should have been dateTime */ ZVAL_NULL(t) return t; } if(!xmlrpci_subsubnode(node)) { /* ERROR, should have been something here. */ ZVAL_NULL(t) return t; } ZVAL_LONG(t, php_parse_date(xmlrpci_node_value(xmlrpci_subsubnode(node)), NULL)); return t; } static inline zval *xmlrpci_double_from_value_node(xmlNodePtr node TSRMLS_DC) { zval *t; MAKE_STD_ZVAL(t); if(!xmlrpci_node_type(node, value)) { ZVAL_NULL(t); return t; } if(!xmlrpci_subnode(node)) { /** ERROR, should have been something here. */ ZVAL_NULL(t); return t; } if(!xmlrpci_node_type(xmlrpci_subnode(node), double)) { /* ERROR, should have been double */ ZVAL_NULL(t); return t; } if(!xmlrpci_subsubnode(node)) { /* ERROR, should have been something here. */ ZVAL_NULL(t); return t; } ZVAL_STRING(t, xmlrpci_node_value(xmlrpci_subsubnode(node)), TRUE); convert_to_double(t); return t; } static inline zval *xmlrpci_boolean_from_value_node(xmlNodePtr node TSRMLS_DC) { zval *t; MAKE_STD_ZVAL(t); if(!xmlrpci_node_type(node, value)) { ZVAL_NULL(t); return t; } if(!xmlrpci_subnode(node)) { /** ERROR, should have been something here. */ ZVAL_NULL(t) return t; } if(!xmlrpci_node_type(xmlrpci_subnode(node), boolean)) { /* ERROR, should have been boolean */ ZVAL_NULL(t) return t; } if(!xmlrpci_subsubnode(node)) { /* ERROR, should have been something here. */ ZVAL_NULL(t) return t; } ZVAL_STRING(t, xmlrpci_node_value(xmlrpci_subsubnode(node)), TRUE); convert_to_boolean(t); return t; } static inline zval *xmlrpci_int_from_value_node(xmlNodePtr node TSRMLS_DC) { zval *t; MAKE_STD_ZVAL(t); if(!xmlrpci_node_type(node, value)) { ZVAL_NULL(t); return t; } if(!xmlrpci_subnode(node)) { /** ERROR, should have been something here. */ ZVAL_NULL(t); return t; } if(!xmlrpci_node_type(xmlrpci_subnode(node), int) && !xmlrpci_node_type(xmlrpci_subnode(node), i4)) { /* ERROR, should have been int or i4 */ ZVAL_NULL(t); return t; } if(!xmlrpci_subsubnode(node)) { /* ERROR, should have been something here. */ ZVAL_NULL(t); return t; } ZVAL_STRING(t, xmlrpci_node_value(xmlrpci_subsubnode(node)), TRUE); convert_to_long(t); return t; } static inline zval *xmlrpci_string_from_value_node(xmlNodePtr node TSRMLS_DC) { zval *t; char *string = NULL; MAKE_STD_ZVAL(t); if(!xmlrpci_node_type(node, value)) { ZVAL_NULL(t); return t; } if(node->children) { if(!node->children->next) { string = (node->children->content) ? (char *)node->children->content : ""; ZVAL_STRING(t, string, TRUE); } else { if(xmlrpci_subnode(node)) if(xmlrpci_subsubnode(node)) { string = xmlrpci_node_value(xmlrpci_subsubnode(node)); } ZVAL_STRING(t, (string) ? string : "", TRUE); } } return t; } static zval *xmlrpci_return_zval_from_value_node(xmlNodePtr value TSRMLS_DC) { zval *t; if(xmlrpci_subnode(value)) { if(xmlrpci_node_type(xmlrpci_subnode(value), text) || xmlrpci_node_type(xmlrpci_subnode(value), string)) { return xmlrpci_string_from_value_node(value TSRMLS_CC); } else if(xmlrpci_node_type(xmlrpci_subnode(value), int) || xmlrpci_node_type(xmlrpci_subnode(value), i4)) { return xmlrpci_int_from_value_node(value TSRMLS_CC); } else if(xmlrpci_node_type(xmlrpci_subnode(value), boolean)) { return xmlrpci_boolean_from_value_node(value TSRMLS_CC); } else if(xmlrpci_node_type(xmlrpci_subnode(value), double)) { return xmlrpci_double_from_value_node(value TSRMLS_CC); } else if(xmlrpci_node_type(xmlrpci_subnode(value), struct)) { return xmlrpci_struct_from_value_node(value TSRMLS_CC); } else if(xmlrpci_node_type(xmlrpci_subnode(value), array)) { return xmlrpci_array_from_value_node(value TSRMLS_CC); } else if(xmlrpci_node_type(xmlrpci_subnode(value), dateTime.iso8601)) { return xmlrpci_datetime_from_value_node(value TSRMLS_CC); } } MAKE_STD_ZVAL(t); ZVAL_NULL(t); return t; } static void xmlrpci_generate_result(xmlNodePtr result, INTERNAL_FUNCTION_PARAMETERS) { zval *t = NULL; t = xmlrpci_return_zval_from_value_node(result TSRMLS_CC); *return_value = *t; zval_copy_ctor(return_value); zval_ptr_dtor(&t); } static int xmlrpci_process_response(xmlDocPtr response, INTERNAL_FUNCTION_PARAMETERS) { xmlNode *root= NULL, *res = NULL; root = xmlDocGetRootElement(response); if(!root->children || !root->children->next) { zend_error(E_ERROR, "Bogus response"); } res = root->children->next; if(!strcmp(res->name, "fault")) { if(res->children->next) if(res->children->next->children->next) if(res->children->next->children->next) if(res->children->next->children->next->children->next) { xmlNodePtr faultinfo = res->children->next->children->next->children->next; fprintf(stderr, "%s\n", faultinfo->name); zend_throw_exception_ex(zend_exception_get_default(), 999, "Unparsed Fault."); // xmlrpci_generate_fault(faultinfo, INTERNAL_FUNCTION_PARAM_PASSTHRU); return FAILURE; } } else if (!strcmp(res->name, "params")) { if(res->children) if(res->children->next) if(res->children->next->children) if(res->children->next->children->next) { xmlNodePtr result = res->children->next->children->next; xmlrpci_generate_result(result, INTERNAL_FUNCTION_PARAM_PASSTHRU); } } return SUCCESS; } static int xmlrpci_method_call_handler(char *method, INTERNAL_FUNCTION_PARAMETERS) { xmlDocPtr response; xmlDoc *doc; xmlNodePtr methodCall = NULL, methodName = NULL, params = NULL; zval ***args = NULL; int nargs, called_nargs, buf_size; xmlChar *buf; char *called_method; zend_bool args_modified; XMLRPCI_SET_CONTEXT; nargs = ZEND_NUM_ARGS(); if (nargs) { args = (zval ***)safe_emalloc(sizeof(zval *), nargs, 0); zend_get_parameters_array_ex(nargs, args); } /* hackish, but it works. */ if(!strcmp(method, "__call")) { if(nargs - 1 < 0) { if(nargs) { efree(args); } zend_error(E_ERROR, "When using __call() you must specify a function name"); RETVAL_FALSE; return FAILURE; } called_method = estrdup(Z_STRVAL_P(*args[0])); called_nargs = nargs-1; *args++; args_modified = TRUE; } else { called_method = estrdup(method); called_nargs = nargs; args_modified = FALSE; } doc = xmlNewDoc("1.0"); doc->encoding = xmlStrdup((xmlChar*)"UTF-8"); doc->charset = XML_CHAR_ENCODING_UTF8; methodCall = xmlNewDocNode(doc, NULL, "methodCall", NULL); xmlDocSetRootElement(doc, methodCall); methodName = xmlNewChild(methodCall, NULL, "methodName", called_method); if(called_nargs) { params = xmlNewChild(methodCall, NULL, "params", NULL); xmlrpci_add_param_nodes(params, called_nargs, args TSRMLS_CC); } xmlDocDumpMemory(doc, &buf, &buf_size); response = xmlrpci_perform_rpc_call((XMLRPCI_Obj *)zend_object_store_get_object(object TSRMLS_CC), buf); if(!response) { zend_error(E_ERROR, "Did not get a XML response tree back!"); } else { xmlrpci_process_response(response, INTERNAL_FUNCTION_PARAM_PASSTHRU); } if(args_modified) { *args--; } if(nargs) { efree(args); } efree(called_method); xmlFreeDoc(doc); xmlFreeDoc(response); return SUCCESS; } static union _zend_function *xmlrpci_method_get_handler(zval **object_ptr, char *name, int len TSRMLS_DC) { zend_internal_function f, *fptr = NULL; union _zend_function *func; XMLRPCI_Obj *obj; zval *object = *object_ptr; obj = (XMLRPCI_Obj *)zend_object_store_get_object(object TSRMLS_CC); f.type = ZEND_OVERLOADED_FUNCTION; f.num_args = 0; f.arg_info = NULL; f.scope = obj->std.ce; f.fn_flags = 0; f.function_name = name; f.handler = PHP_FN(xmlrpci_method_handler); fptr = &f; if (fptr) { /* duplicate this into a new chunk of emalloc'd memory, * since the engine will efree it */ func = emalloc(sizeof(*fptr)); memcpy(func, fptr, sizeof(*fptr)); return func; } return NULL; } XMLRPCI_VAL_METHOD(__construct) { zval *value; int type, base64_len; XMLRPCI_Obj *obj; XMLRPCI_SET_CONTEXT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &type, &value) == FAILURE) { RETURN_FALSE; } obj = (XMLRPCI_Obj *)zend_object_store_get_object(object TSRMLS_CC); obj->val_type = type; switch(type) { case XMLRPC_DATETIME: obj->timestamp = Z_LVAL_P(value); break; case XMLRPC_BASE64: obj->base64_data = php_base64_encode(Z_STRVAL_P(value), Z_STRLEN_P(value), &base64_len); break; default: /** Error condition **/ break; } } XMLRPCI_RPC_METHOD(__construct) { char *server_addy; int server_addy_len; XMLRPCI_Obj *obj; XMLRPCI_SET_CONTEXT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_addy, &server_addy_len) == FAILURE) { RETURN_FALSE; } obj = (XMLRPCI_Obj *)zend_object_store_get_object(object TSRMLS_CC); obj->server_addy = estrdup(server_addy); } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */
« previous php.pecl.cvs (#2559) next »