2001-09-06 04:13:30 +00:00
/*
This file is part of , or distributed with , libXMLRPC - a C library for
xml - encoded function calls .
Author : Dan Libby ( dan @ libby . com )
Epinions . com may be contacted at feedback @ epinions - inc . com
*/
/*
Copyright 2001 Epinions , Inc .
Subject to the following 3 conditions , Epinions , Inc . permits you , free
of charge , to ( a ) use , copy , distribute , modify , perform and display this
software and associated documentation files ( the " Software " ) , and ( b )
permit others to whom the Software is furnished to do so as well .
1 ) The above copyright notice and this permission notice shall be included
without modification in all copies or substantial portions of the
Software .
2 ) THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT ANY WARRANTY OR CONDITION OF
ANY KIND , EXPRESS , IMPLIED OR STATUTORY , INCLUDING WITHOUT LIMITATION ANY
IMPLIED WARRANTIES OF ACCURACY , MERCHANTABILITY , FITNESS FOR A PARTICULAR
PURPOSE OR NONINFRINGEMENT .
3 ) IN NO EVENT SHALL EPINIONS , INC . BE LIABLE FOR ANY DIRECT , INDIRECT ,
SPECIAL , INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
OF OR IN CONNECTION WITH THE SOFTWARE ( HOWEVER ARISING , INCLUDING
NEGLIGENCE ) , EVEN IF EPINIONS , INC . IS AWARE OF THE POSSIBILITY OF SUCH
DAMAGES .
*/
/* auto-generated portions of this file are also subject to the php license */
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2009-03-10 23:40:06 +00:00
| PHP Version 6 |
2001-09-06 04:13:30 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2008-12-31 11:12:40 +00:00
| Copyright ( c ) 1997 - 2009 The PHP Group |
2001-09-06 04:13:30 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 13:10:10 +00:00
| This source file is subject to version 3.01 of the PHP license , |
2001-09-06 04:13:30 +00:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2006-01-01 13:10:10 +00:00
| http : //www.php.net/license/3_01.txt |
2001-09-06 04:13:30 +00:00
| 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 . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-02-28 08:29:35 +00:00
| Author : Dan Libby |
2001-09-06 04:13:30 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2003-07-19 19:11:01 +00:00
/* $Id$ */
2001-10-30 02:33:13 +00:00
/**********************************************************************
* BUGS : *
* - when calling a php user function , there appears to be no way to *
* distinguish between a return value of null , and no return value *
* at all . The xml serialization layer ( s ) will then return a value *
* of null , when the right thing may be no value at all . ( SOAP ) *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-30 02:57:13 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2001-09-06 04:13:30 +00:00
# include "php.h"
2001-10-25 06:51:13 +00:00
# include "ext/standard/info.h"
2009-05-14 12:30:06 +00:00
# include "ext/date/php_date.h"
2001-09-06 04:13:30 +00:00
# include "php_ini.h"
# include "php_xmlrpc.h"
# include "xmlrpc.h"
2002-07-05 04:43:55 +00:00
# define PHP_EXT_VERSION "0.51"
2001-10-11 23:33:59 +00:00
2001-10-26 12:54:55 +00:00
static int le_xmlrpc_server ;
2001-09-06 04:13:30 +00:00
2008-06-28 22:19:24 +00:00
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_encode , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , value )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_decode , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , value )
ZEND_ARG_INFO ( 0 , encoding )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_decode_request , 0 , 0 , 2 )
ZEND_ARG_INFO ( 0 , xml )
ZEND_ARG_INFO ( 1 , method )
ZEND_ARG_INFO ( 0 , encoding )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_encode_request , 0 , 0 , 2 )
ZEND_ARG_INFO ( 0 , method )
2008-07-20 15:52:07 +00:00
ZEND_ARG_INFO ( 0 , params )
2008-06-28 22:19:24 +00:00
ZEND_ARG_INFO ( 0 , output_options )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_set_type , 0 , 0 , 2 )
ZEND_ARG_INFO ( 1 , value )
ZEND_ARG_INFO ( 0 , type )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_is_fault , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , arg )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO ( arginfo_xmlrpc_server_create , 0 )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_server_destroy , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , server )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_server_register_method , 0 , 0 , 3 )
ZEND_ARG_INFO ( 0 , server )
ZEND_ARG_INFO ( 0 , method_name )
ZEND_ARG_INFO ( 0 , function )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_server_call_method , 0 , 0 , 3 )
ZEND_ARG_INFO ( 0 , server )
ZEND_ARG_INFO ( 0 , xml )
ZEND_ARG_INFO ( 0 , user_data )
ZEND_ARG_INFO ( 0 , output_options )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_parse_method_descriptions , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , xml )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_server_add_introspection_data , 0 , 0 , 2 )
ZEND_ARG_INFO ( 0 , server )
ZEND_ARG_INFO ( 0 , desc )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_xmlrpc_server_register_introspection_callback , 0 , 0 , 2 )
ZEND_ARG_INFO ( 0 , server )
ZEND_ARG_INFO ( 0 , function )
ZEND_END_ARG_INFO ( )
/* }}} */
2007-09-27 18:28:44 +00:00
const zend_function_entry xmlrpc_functions [ ] = {
2008-06-28 22:19:24 +00:00
PHP_FE ( xmlrpc_encode , arginfo_xmlrpc_encode )
PHP_FE ( xmlrpc_decode , arginfo_xmlrpc_decode )
PHP_FE ( xmlrpc_decode_request , arginfo_xmlrpc_decode_request )
PHP_FE ( xmlrpc_encode_request , arginfo_xmlrpc_encode_request )
PHP_FE ( xmlrpc_get_type , arginfo_xmlrpc_encode )
PHP_FE ( xmlrpc_set_type , arginfo_xmlrpc_set_type )
PHP_FE ( xmlrpc_is_fault , arginfo_xmlrpc_is_fault )
PHP_FE ( xmlrpc_server_create , arginfo_xmlrpc_server_create )
PHP_FE ( xmlrpc_server_destroy , arginfo_xmlrpc_server_destroy )
PHP_FE ( xmlrpc_server_register_method , arginfo_xmlrpc_server_register_method )
PHP_FE ( xmlrpc_server_call_method , arginfo_xmlrpc_server_call_method )
PHP_FE ( xmlrpc_parse_method_descriptions , arginfo_xmlrpc_parse_method_descriptions )
PHP_FE ( xmlrpc_server_add_introspection_data , arginfo_xmlrpc_server_add_introspection_data )
PHP_FE ( xmlrpc_server_register_introspection_callback , arginfo_xmlrpc_server_register_introspection_callback )
2002-03-14 12:20:53 +00:00
{ NULL , NULL , NULL }
2001-09-06 04:13:30 +00:00
} ;
zend_module_entry xmlrpc_module_entry = {
2002-03-14 12:20:53 +00:00
STANDARD_MODULE_HEADER ,
" xmlrpc " ,
xmlrpc_functions ,
PHP_MINIT ( xmlrpc ) ,
2007-01-12 12:31:31 +00:00
NULL ,
NULL ,
NULL ,
2002-03-14 12:20:53 +00:00
PHP_MINFO ( xmlrpc ) ,
PHP_EXT_VERSION ,
STANDARD_MODULE_PROPERTIES
2001-09-06 04:13:30 +00:00
} ;
# ifdef COMPILE_DL_XMLRPC
ZEND_GET_MODULE ( xmlrpc )
# endif
/*******************************
* local structures and defines *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-14 12:20:53 +00:00
/* per server data */
2001-09-06 04:13:30 +00:00
typedef struct _xmlrpc_server_data {
2002-03-14 12:20:53 +00:00
zval * method_map ;
zval * introspection_map ;
XMLRPC_SERVER server_ptr ;
2001-09-06 04:13:30 +00:00
} xmlrpc_server_data ;
2002-03-14 12:20:53 +00:00
/* how to format output */
2001-09-06 04:13:30 +00:00
typedef struct _php_output_options {
2002-03-14 12:20:53 +00:00
int b_php_out ;
2001-10-30 02:33:13 +00:00
int b_auto_version ;
2002-03-14 12:20:53 +00:00
STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS xmlrpc_out ;
2001-09-06 04:13:30 +00:00
} php_output_options ;
2002-03-14 12:20:53 +00:00
/* data passed to C callback */
2001-09-06 04:13:30 +00:00
typedef struct _xmlrpc_callback_data {
2002-03-14 12:20:53 +00:00
zval * xmlrpc_method ;
zval * php_function ;
zval * caller_params ;
zval * return_data ;
xmlrpc_server_data * server ;
char php_executed ;
2001-09-06 04:13:30 +00:00
} xmlrpc_callback_data ;
2002-03-14 12:20:53 +00:00
/* output options */
# define OUTPUT_TYPE_KEY "output_type"
# define OUTPUT_TYPE_KEY_LEN (sizeof(OUTPUT_TYPE_KEY) - 1)
2001-09-06 04:13:30 +00:00
# define OUTPUT_TYPE_VALUE_PHP "php"
# define OUTPUT_TYPE_VALUE_XML "xml"
2002-03-14 12:20:53 +00:00
# define VERBOSITY_KEY "verbosity"
# define VERBOSITY_KEY_LEN (sizeof(VERBOSITY_KEY) - 1)
2001-09-06 04:13:30 +00:00
# define VERBOSITY_VALUE_NO_WHITE_SPACE "no_white_space"
2002-03-14 12:20:53 +00:00
# define VERBOSITY_VALUE_NEWLINES_ONLY "newlines_only"
# define VERBOSITY_VALUE_PRETTY "pretty"
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
# define ESCAPING_KEY "escaping"
# define ESCAPING_KEY_LEN (sizeof(ESCAPING_KEY) - 1)
# define ESCAPING_VALUE_CDATA "cdata"
2001-09-06 04:13:30 +00:00
# define ESCAPING_VALUE_NON_ASCII "non-ascii"
# define ESCAPING_VALUE_NON_PRINT "non-print"
2002-03-14 12:20:53 +00:00
# define ESCAPING_VALUE_MARKUP "markup"
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
# define VERSION_KEY "version"
# define VERSION_KEY_LEN (sizeof(VERSION_KEY) - 1)
2001-09-06 04:13:30 +00:00
# define VERSION_VALUE_SIMPLE "simple"
# define VERSION_VALUE_XMLRPC "xmlrpc"
2001-10-30 02:33:13 +00:00
# define VERSION_VALUE_SOAP11 "soap 1.1"
2002-03-14 12:20:53 +00:00
# define VERSION_VALUE_AUTO "auto"
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
# define ENCODING_KEY "encoding"
2001-09-06 04:13:30 +00:00
# define ENCODING_KEY_LEN (sizeof(ENCODING_KEY) - 1)
# define ENCODING_DEFAULT "iso-8859-1"
2002-03-14 12:20:53 +00:00
/* value types */
# define OBJECT_TYPE_ATTR "xmlrpc_type"
2001-09-06 04:13:30 +00:00
# define OBJECT_VALUE_ATTR "scalar"
2002-07-05 04:43:55 +00:00
# define OBJECT_VALUE_TS_ATTR "timestamp"
2001-09-06 04:13:30 +00:00
2002-07-05 04:43:55 +00:00
/* faults */
# define FAULT_CODE "faultCode"
# define FAULT_CODE_LEN (sizeof(FAULT_CODE) - 1)
# define FAULT_STRING "faultString"
# define FAULT_STRING_LEN (sizeof(FAULT_STRING) - 1)
2001-09-06 04:13:30 +00:00
/***********************
* forward declarations *
* * * * * * * * * * * * * * * * * * * * * * */
2002-03-14 12:20:53 +00:00
XMLRPC_VALUE_TYPE get_zval_xmlrpc_type ( zval * value , zval * * newvalue ) ;
2001-09-06 04:13:30 +00:00
static void php_xmlrpc_introspection_callback ( XMLRPC_SERVER server , void * data ) ;
2002-03-14 12:20:53 +00:00
int sset_zval_xmlrpc_type ( zval * value , XMLRPC_VALUE_TYPE type ) ;
2008-08-24 00:45:20 +00:00
zval * decode_request_worker ( char * xml_in , int xml_in_len , char * encoding_in , zval * method_name_out ) ;
2001-10-25 06:51:13 +00:00
const char * xmlrpc_type_as_str ( XMLRPC_VALUE_TYPE type , XMLRPC_VECTOR_TYPE vtype ) ;
XMLRPC_VALUE_TYPE xmlrpc_str_as_type ( const char * str ) ;
XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type ( const char * str ) ;
2002-03-14 12:20:53 +00:00
int set_zval_xmlrpc_type ( zval * value , XMLRPC_VALUE_TYPE type ) ;
2001-09-06 04:13:30 +00:00
/*********************
* startup / shutdown *
* * * * * * * * * * * * * * * * * * * * */
2008-08-15 22:13:58 +00:00
static void destroy_server_data ( xmlrpc_server_data * server TSRMLS_DC ) /* { { { */
2002-03-14 12:20:53 +00:00
{
if ( server ) {
XMLRPC_ServerDestroy ( server - > server_ptr ) ;
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
zval_dtor ( server - > method_map ) ;
FREE_ZVAL ( server - > method_map ) ;
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
zval_dtor ( server - > introspection_map ) ;
FREE_ZVAL ( server - > introspection_map ) ;
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
efree ( server ) ;
}
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* called when server is being destructed. either when xmlrpc_server_destroy
2002-03-14 12:20:53 +00:00
* is called , or when request ends . */
2007-07-12 10:04:42 +00:00
static void xmlrpc_server_destructor ( zend_rsrc_list_entry * rsrc TSRMLS_DC ) /* { { { */
2001-10-21 17:23:39 +00:00
{
2002-03-14 12:20:53 +00:00
if ( rsrc & & rsrc - > ptr ) {
2008-08-15 22:13:58 +00:00
destroy_server_data ( ( xmlrpc_server_data * ) rsrc - > ptr TSRMLS_CC ) ;
2002-03-14 12:20:53 +00:00
}
2001-10-21 17:23:39 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-10-21 17:23:39 +00:00
2001-09-06 04:13:30 +00:00
/* module init */
2007-07-12 10:04:42 +00:00
PHP_MINIT_FUNCTION ( xmlrpc ) /* {{{ */
2001-09-06 04:13:30 +00:00
{
2002-03-14 12:20:53 +00:00
le_xmlrpc_server = zend_register_list_destructors_ex ( xmlrpc_server_destructor , NULL , " xmlrpc server " , module_number ) ;
return SUCCESS ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* display info in phpinfo() */
2007-07-12 10:04:42 +00:00
PHP_MINFO_FUNCTION ( xmlrpc ) /* {{{ */
2001-09-06 04:13:30 +00:00
{
2002-03-14 12:20:53 +00:00
php_info_print_table_start ( ) ;
php_info_print_table_row ( 2 , " core library version " , XMLRPC_GetVersionString ( ) ) ;
php_info_print_table_row ( 2 , " php extension version " , PHP_EXT_VERSION ) ;
php_info_print_table_row ( 2 , " author " , " Dan Libby " ) ;
php_info_print_table_row ( 2 , " homepage " , " http://xmlrpc-epi.sourceforge.net " ) ;
php_info_print_table_row ( 2 , " open sourced by " , " Epinions.com " ) ;
php_info_print_table_end ( ) ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/*******************
2007-07-12 10:04:42 +00:00
* random utilities *
* * * * * * * * * * * * * * * * * * */
2001-09-06 04:13:30 +00:00
/* Utility functions for adding data types to arrays, with or without key (assoc, non-assoc).
* Could easily be further generalized to work with objects .
*/
2001-10-25 06:51:13 +00:00
#if 0
2002-03-14 12:20:53 +00:00
static int add_long ( zval * list , char * id , int num ) {
if ( id ) return add_assoc_long ( list , id , num ) ;
else return add_next_index_long ( list , num ) ;
2001-09-06 04:13:30 +00:00
}
2002-03-14 12:20:53 +00:00
static int add_double ( zval * list , char * id , double num ) {
if ( id ) return add_assoc_double ( list , id , num ) ;
else return add_next_index_double ( list , num ) ;
2001-09-06 04:13:30 +00:00
}
2002-03-14 12:20:53 +00:00
static int add_string ( zval * list , char * id , char * string , int duplicate ) {
if ( id ) return add_assoc_string ( list , id , string , duplicate ) ;
else return add_next_index_string ( list , string , duplicate ) ;
2001-09-06 04:13:30 +00:00
}
2002-03-14 12:20:53 +00:00
static int add_stringl ( zval * list , char * id , char * string , uint length , int duplicate ) {
if ( id ) return add_assoc_stringl ( list , id , string , length , duplicate ) ;
else return add_next_index_stringl ( list , string , length , duplicate ) ;
2001-09-06 04:13:30 +00:00
}
2001-10-25 06:51:13 +00:00
# endif
2007-07-12 10:04:42 +00:00
static int add_zval ( zval * list , const char * id , zval * * val ) /* { { { */
2002-03-14 12:20:53 +00:00
{
if ( list & & val ) {
if ( id ) {
2006-04-12 15:14:43 +00:00
int id_len = strlen ( id ) ;
if ( ! ( id_len > 1 & & id [ 0 ] = = ' 0 ' ) & & is_numeric_string ( ( char * ) id , id_len , NULL , NULL , 0 ) = = IS_LONG ) {
long index = strtol ( id , NULL , 0 ) ;
return zend_hash_index_update ( Z_ARRVAL_P ( list ) , index , ( void * ) val , sizeof ( zval * * ) , NULL ) ;
} else {
return zend_hash_update ( Z_ARRVAL_P ( list ) , ( char * ) id , strlen ( id ) + 1 , ( void * ) val , sizeof ( zval * * ) , NULL ) ;
}
2002-03-14 12:20:53 +00:00
} else {
return zend_hash_next_index_insert ( Z_ARRVAL_P ( list ) , ( void * ) val , sizeof ( zval * * ) , NULL ) ;
}
}
/* what is the correct return on error? */
return 0 ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
# define my_zend_hash_get_current_key(ht, my_key, num_index) zend_hash_get_current_key(ht, my_key, num_index, 0)
/*************************
2007-07-12 10:04:42 +00:00
* input / output options *
* * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-06 04:13:30 +00:00
/* parse an array (user input) into output options suitable for use by xmlrpc engine
2002-03-14 12:20:53 +00:00
* and determine whether to return data as xml or php vars */
2007-07-12 10:04:42 +00:00
static void set_output_options ( php_output_options * options , zval * output_opts ) /* { { { */
2002-03-14 12:20:53 +00:00
{
if ( options ) {
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
/* defaults */
options - > b_php_out = 0 ;
2001-10-30 02:33:13 +00:00
options - > b_auto_version = 1 ;
2002-03-14 12:20:53 +00:00
options - > xmlrpc_out . version = xmlrpc_version_1_0 ;
options - > xmlrpc_out . xml_elem_opts . encoding = ENCODING_DEFAULT ;
options - > xmlrpc_out . xml_elem_opts . verbosity = xml_elem_pretty ;
options - > xmlrpc_out . xml_elem_opts . escaping = xml_elem_markup_escaping | xml_elem_non_ascii_escaping | xml_elem_non_print_escaping ;
if ( output_opts & & Z_TYPE_P ( output_opts ) = = IS_ARRAY ) {
zval * * val ;
/* type of output (xml/php) */
if ( zend_hash_find ( Z_ARRVAL_P ( output_opts ) , OUTPUT_TYPE_KEY , OUTPUT_TYPE_KEY_LEN + 1 , ( void * * ) & val ) = = SUCCESS ) {
if ( Z_TYPE_PP ( val ) = = IS_STRING ) {
if ( ! strcmp ( Z_STRVAL_PP ( val ) , OUTPUT_TYPE_VALUE_PHP ) ) {
options - > b_php_out = 1 ;
} else if ( ! strcmp ( Z_STRVAL_PP ( val ) , OUTPUT_TYPE_VALUE_XML ) ) {
options - > b_php_out = 0 ;
}
}
}
/* verbosity of generated xml */
if ( zend_hash_find ( Z_ARRVAL_P ( output_opts ) , VERBOSITY_KEY , VERBOSITY_KEY_LEN + 1 , ( void * * ) & val ) = = SUCCESS ) {
if ( Z_TYPE_PP ( val ) = = IS_STRING ) {
if ( ! strcmp ( Z_STRVAL_PP ( val ) , VERBOSITY_VALUE_NO_WHITE_SPACE ) ) {
options - > xmlrpc_out . xml_elem_opts . verbosity = xml_elem_no_white_space ;
} else if ( ! strcmp ( Z_STRVAL_PP ( val ) , VERBOSITY_VALUE_NEWLINES_ONLY ) ) {
options - > xmlrpc_out . xml_elem_opts . verbosity = xml_elem_newlines_only ;
} else if ( ! strcmp ( Z_STRVAL_PP ( val ) , VERBOSITY_VALUE_PRETTY ) ) {
options - > xmlrpc_out . xml_elem_opts . verbosity = xml_elem_pretty ;
}
}
}
/* version of xml to output */
if ( zend_hash_find ( Z_ARRVAL_P ( output_opts ) , VERSION_KEY , VERSION_KEY_LEN + 1 , ( void * * ) & val ) = = SUCCESS ) {
if ( Z_TYPE_PP ( val ) = = IS_STRING ) {
options - > b_auto_version = 0 ;
if ( ! strcmp ( Z_STRVAL_PP ( val ) , VERSION_VALUE_XMLRPC ) ) {
options - > xmlrpc_out . version = xmlrpc_version_1_0 ;
} else if ( ! strcmp ( Z_STRVAL_PP ( val ) , VERSION_VALUE_SIMPLE ) ) {
options - > xmlrpc_out . version = xmlrpc_version_simple ;
} else if ( ! strcmp ( ( * val ) - > value . str . val , VERSION_VALUE_SOAP11 ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . version = xmlrpc_version_soap_1_1 ;
} else { /* if(!strcmp((*val)->value.str.val, VERSION_VALUE_AUTO)) */
options - > b_auto_version = 1 ;
2002-03-14 12:20:53 +00:00
}
}
}
2007-07-12 10:04:42 +00:00
/* encoding code set */
2008-08-24 00:45:20 +00:00
if ( zend_hash_find ( Z_ARRVAL_P ( output_opts ) , ENCODING_KEY , ENCODING_KEY_LEN + 1 , ( void * * ) & val ) = = SUCCESS ) {
if ( Z_TYPE_PP ( val ) = = IS_STRING ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . encoding = estrdup ( Z_STRVAL_PP ( val ) ) ;
}
}
/* escaping options */
2008-08-24 00:45:20 +00:00
if ( zend_hash_find ( Z_ARRVAL_P ( output_opts ) , ESCAPING_KEY , ESCAPING_KEY_LEN + 1 , ( void * * ) & val ) = = SUCCESS ) {
2007-07-12 10:04:42 +00:00
/* multiple values allowed. check if array */
2008-08-24 00:45:20 +00:00
if ( Z_TYPE_PP ( val ) = = IS_ARRAY ) {
2007-07-12 10:04:42 +00:00
zval * * iter_val ;
zend_hash_internal_pointer_reset ( Z_ARRVAL_PP ( val ) ) ;
options - > xmlrpc_out . xml_elem_opts . escaping = xml_elem_no_escaping ;
2008-08-24 00:45:20 +00:00
while ( 1 ) {
if ( zend_hash_get_current_data ( Z_ARRVAL_PP ( val ) , ( void * * ) & iter_val ) = = SUCCESS ) {
if ( Z_TYPE_PP ( iter_val ) = = IS_STRING & & Z_STRVAL_PP ( iter_val ) ) {
if ( ! strcmp ( Z_STRVAL_PP ( iter_val ) , ESCAPING_VALUE_CDATA ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping | = xml_elem_cdata_escaping ;
2008-08-24 00:45:20 +00:00
} else if ( ! strcmp ( Z_STRVAL_PP ( iter_val ) , ESCAPING_VALUE_NON_ASCII ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping | = xml_elem_non_ascii_escaping ;
2008-08-24 00:45:20 +00:00
} else if ( ! strcmp ( Z_STRVAL_PP ( iter_val ) , ESCAPING_VALUE_NON_PRINT ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping | = xml_elem_non_print_escaping ;
2008-08-24 00:45:20 +00:00
} else if ( ! strcmp ( Z_STRVAL_PP ( iter_val ) , ESCAPING_VALUE_MARKUP ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping | = xml_elem_markup_escaping ;
}
}
} else {
break ;
}
zend_hash_move_forward ( Z_ARRVAL_PP ( val ) ) ;
}
}
/* else, check for single value */
2008-08-24 00:45:20 +00:00
else if ( Z_TYPE_PP ( val ) = = IS_STRING ) {
if ( ! strcmp ( Z_STRVAL_PP ( val ) , ESCAPING_VALUE_CDATA ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping = xml_elem_cdata_escaping ;
2008-08-24 00:45:20 +00:00
} else if ( ! strcmp ( Z_STRVAL_PP ( val ) , ESCAPING_VALUE_NON_ASCII ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping = xml_elem_non_ascii_escaping ;
2008-08-24 00:45:20 +00:00
} else if ( ! strcmp ( Z_STRVAL_PP ( val ) , ESCAPING_VALUE_NON_PRINT ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping = xml_elem_non_print_escaping ;
2008-08-24 00:45:20 +00:00
} else if ( ! strcmp ( Z_STRVAL_PP ( val ) , ESCAPING_VALUE_MARKUP ) ) {
2007-07-12 10:04:42 +00:00
options - > xmlrpc_out . xml_elem_opts . escaping = xml_elem_markup_escaping ;
}
}
}
}
2002-03-14 12:20:53 +00:00
}
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/******************
2007-07-12 10:04:42 +00:00
* encode / decode *
* * * * * * * * * * * * * * * * * */
2001-09-06 04:13:30 +00:00
/* php arrays have no distinction between array and struct types.
* they even allow mixed . Thus , we determine the type by iterating
* through the entire array and figuring out each element .
* room for some optimation here if we stop after a specific # of elements .
*/
2007-07-12 10:04:42 +00:00
static XMLRPC_VECTOR_TYPE determine_vector_type ( HashTable * ht ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
int bArray = 0 , bStruct = 0 , bMixed = 0 ;
unsigned long num_index ;
2009-05-19 16:32:22 +00:00
zstr my_key ;
2007-07-12 10:04:42 +00:00
zend_hash_internal_pointer_reset ( ht ) ;
2008-08-24 00:45:20 +00:00
while ( 1 ) {
2007-07-12 10:04:42 +00:00
int res = my_zend_hash_get_current_key ( ht , & my_key , & num_index ) ;
2008-08-24 00:45:20 +00:00
if ( res = = HASH_KEY_IS_LONG ) {
if ( bStruct ) {
2007-07-12 10:04:42 +00:00
bMixed = 1 ;
break ;
}
bArray = 1 ;
2008-08-24 00:45:20 +00:00
} else if ( res = = HASH_KEY_NON_EXISTANT ) {
2007-07-12 10:04:42 +00:00
break ;
2008-08-24 00:45:20 +00:00
} else if ( res = = HASH_KEY_IS_STRING | | res = = HASH_KEY_IS_UNICODE ) {
if ( bArray ) {
2007-07-12 10:04:42 +00:00
bMixed = 1 ;
break ;
}
bStruct = 1 ;
}
zend_hash_move_forward ( ht ) ;
}
return bMixed ? xmlrpc_vector_mixed : ( bStruct ? xmlrpc_vector_struct : xmlrpc_vector_array ) ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* recursively convert php values into xmlrpc values */
2007-07-12 10:04:42 +00:00
static XMLRPC_VALUE PHP_to_XMLRPC_worker ( const char * key , zval * in_val , int depth TSRMLS_DC ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
XMLRPC_VALUE xReturn = NULL ;
2008-08-24 00:45:20 +00:00
if ( in_val ) {
2007-07-12 10:04:42 +00:00
zval * val = NULL ;
XMLRPC_VALUE_TYPE type = get_zval_xmlrpc_type ( in_val , & val ) ;
2008-08-24 00:45:20 +00:00
if ( val ) {
switch ( type ) {
2007-07-12 10:04:42 +00:00
case xmlrpc_base64 :
2008-08-24 00:45:20 +00:00
if ( Z_TYPE_P ( val ) = = IS_NULL ) {
2007-07-12 10:04:42 +00:00
xReturn = XMLRPC_CreateValueEmpty ( ) ;
2001-10-30 02:33:13 +00:00
XMLRPC_SetValueID ( xReturn , key , 0 ) ;
2007-07-12 10:04:42 +00:00
} else {
xReturn = XMLRPC_CreateValueBase64 ( key , Z_STRVAL_P ( val ) , Z_STRLEN_P ( val ) ) ;
}
break ;
case xmlrpc_datetime :
convert_to_string ( val ) ;
xReturn = XMLRPC_CreateValueDateTime_ISO8601 ( key , Z_STRVAL_P ( val ) ) ;
break ;
case xmlrpc_boolean :
convert_to_boolean ( val ) ;
xReturn = XMLRPC_CreateValueBoolean ( key , Z_LVAL_P ( val ) ) ;
break ;
case xmlrpc_int :
convert_to_long ( val ) ;
xReturn = XMLRPC_CreateValueInt ( key , Z_LVAL_P ( val ) ) ;
break ;
case xmlrpc_double :
convert_to_double ( val ) ;
xReturn = XMLRPC_CreateValueDouble ( key , Z_DVAL_P ( val ) ) ;
break ;
case xmlrpc_string :
convert_to_string ( val ) ;
xReturn = XMLRPC_CreateValueString ( key , Z_STRVAL_P ( val ) , Z_STRLEN_P ( val ) ) ;
break ;
case xmlrpc_vector :
{
unsigned long num_index ;
zval * * pIter ;
2009-05-19 16:32:22 +00:00
zstr my_key ;
2007-07-12 10:04:42 +00:00
HashTable * ht = NULL ;
ht = HASH_OF ( val ) ;
if ( ht & & ht - > nApplyCount > 1 ) {
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " XML-RPC doesn't support circular references " ) ;
return NULL ;
}
convert_to_array ( val ) ;
xReturn = XMLRPC_CreateVector ( key , determine_vector_type ( Z_ARRVAL_P ( val ) ) ) ;
zend_hash_internal_pointer_reset ( Z_ARRVAL_P ( val ) ) ;
2008-08-24 00:45:20 +00:00
while ( zend_hash_get_current_data ( Z_ARRVAL_P ( val ) , ( void * * ) & pIter ) = = SUCCESS ) {
2007-07-12 10:04:42 +00:00
int res = my_zend_hash_get_current_key ( Z_ARRVAL_P ( val ) , & my_key , & num_index ) ;
switch ( res ) {
case HASH_KEY_NON_EXISTANT :
break ;
default :
ht = HASH_OF ( * pIter ) ;
if ( ht ) {
ht - > nApplyCount + + ;
}
if ( res = = HASH_KEY_IS_LONG ) {
XMLRPC_AddValueToVector ( xReturn , PHP_to_XMLRPC_worker ( 0 , * pIter , depth + + TSRMLS_CC ) ) ;
} else {
2009-05-19 16:32:22 +00:00
XMLRPC_AddValueToVector ( xReturn , PHP_to_XMLRPC_worker ( my_key . s , * pIter , depth + + TSRMLS_CC ) ) ;
2007-07-12 10:04:42 +00:00
}
if ( ht ) {
ht - > nApplyCount - - ;
}
break ;
}
zend_hash_move_forward ( Z_ARRVAL_P ( val ) ) ;
}
}
break ;
default :
break ;
}
}
}
return xReturn ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
2007-07-12 10:04:42 +00:00
static XMLRPC_VALUE PHP_to_XMLRPC ( zval * root_val TSRMLS_DC ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
return PHP_to_XMLRPC_worker ( NULL , root_val , 0 TSRMLS_CC ) ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* recursively convert xmlrpc values into php values */
2007-07-12 10:04:42 +00:00
static zval * XMLRPC_to_PHP ( XMLRPC_VALUE el ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
zval * elem = NULL ;
const char * pStr ;
2008-08-24 00:45:20 +00:00
if ( el ) {
2007-07-12 10:04:42 +00:00
XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType ( el ) ;
MAKE_STD_ZVAL ( elem ) ; /* init. very important. spent a frustrating day finding this out. */
switch ( type ) {
case xmlrpc_empty :
Z_TYPE_P ( elem ) = IS_NULL ;
break ;
case xmlrpc_string :
pStr = XMLRPC_GetValueString ( el ) ;
2008-08-24 00:45:20 +00:00
if ( pStr ) {
2007-07-12 10:04:42 +00:00
Z_STRLEN_P ( elem ) = XMLRPC_GetValueStringLen ( el ) ;
Z_STRVAL_P ( elem ) = estrndup ( pStr , Z_STRLEN_P ( elem ) ) ;
Z_TYPE_P ( elem ) = IS_STRING ;
2003-01-14 21:02:14 +00:00
}
2007-07-12 10:04:42 +00:00
break ;
case xmlrpc_int :
Z_LVAL_P ( elem ) = XMLRPC_GetValueInt ( el ) ;
Z_TYPE_P ( elem ) = IS_LONG ;
break ;
case xmlrpc_boolean :
Z_LVAL_P ( elem ) = XMLRPC_GetValueBoolean ( el ) ;
Z_TYPE_P ( elem ) = IS_BOOL ;
break ;
case xmlrpc_double :
Z_DVAL_P ( elem ) = XMLRPC_GetValueDouble ( el ) ;
Z_TYPE_P ( elem ) = IS_DOUBLE ;
break ;
case xmlrpc_datetime :
Z_STRLEN_P ( elem ) = XMLRPC_GetValueStringLen ( el ) ;
Z_STRVAL_P ( elem ) = estrndup ( XMLRPC_GetValueDateTime_ISO8601 ( el ) , Z_STRLEN_P ( elem ) ) ;
Z_TYPE_P ( elem ) = IS_STRING ;
break ;
case xmlrpc_base64 :
pStr = XMLRPC_GetValueBase64 ( el ) ;
2008-08-24 00:45:20 +00:00
if ( pStr ) {
2007-07-12 10:04:42 +00:00
Z_STRLEN_P ( elem ) = XMLRPC_GetValueStringLen ( el ) ;
Z_STRVAL_P ( elem ) = estrndup ( pStr , Z_STRLEN_P ( elem ) ) ;
Z_TYPE_P ( elem ) = IS_STRING ;
}
break ;
case xmlrpc_vector :
array_init ( elem ) ;
{
XMLRPC_VALUE xIter = XMLRPC_VectorRewind ( el ) ;
2008-08-24 00:45:20 +00:00
while ( xIter ) {
2007-07-12 10:04:42 +00:00
zval * val = XMLRPC_to_PHP ( xIter ) ;
if ( val ) {
add_zval ( elem , XMLRPC_GetValueID ( xIter ) , & val ) ;
}
xIter = XMLRPC_VectorNext ( el ) ;
}
}
break ;
default :
break ;
2003-01-14 21:02:14 +00:00
}
2007-07-12 10:04:42 +00:00
set_zval_xmlrpc_type ( elem , type ) ;
}
return elem ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* {{{ proto string xmlrpc_encode_request(string method, mixed params)
2001-10-17 18:52:33 +00:00
Generates XML for a method request */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_encode_request )
{
2003-01-14 21:02:14 +00:00
XMLRPC_REQUEST xRequest = NULL ;
2008-08-24 00:45:20 +00:00
char * outBuf ;
2009-03-19 00:19:20 +00:00
zval * * method , * * vals , * out_opts = NULL ;
2003-01-14 21:02:14 +00:00
php_output_options out ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ZZ|a " , & method , & vals , & out_opts ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2009-03-19 00:19:20 +00:00
set_output_options ( & out , out_opts ? out_opts : 0 ) ;
2001-10-30 02:33:13 +00:00
2008-08-24 00:45:20 +00:00
if ( return_value_used ) {
2003-01-14 21:02:14 +00:00
xRequest = XMLRPC_RequestNew ( ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( xRequest ) {
2003-01-14 21:02:14 +00:00
XMLRPC_RequestSetOutputOptions ( xRequest , & out . xmlrpc_out ) ;
if ( Z_TYPE_PP ( method ) = = IS_NULL ) {
XMLRPC_RequestSetRequestType ( xRequest , xmlrpc_request_response ) ;
} else {
2006-08-14 08:15:44 +00:00
convert_to_string_ex ( method ) ;
2003-01-14 21:02:14 +00:00
XMLRPC_RequestSetMethodName ( xRequest , Z_STRVAL_PP ( method ) ) ;
XMLRPC_RequestSetRequestType ( xRequest , xmlrpc_request_call ) ;
}
if ( Z_TYPE_PP ( vals ) ! = IS_NULL ) {
2005-10-05 16:39:37 +00:00
XMLRPC_RequestSetData ( xRequest , PHP_to_XMLRPC ( * vals TSRMLS_CC ) ) ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
outBuf = XMLRPC_REQUEST_ToXML ( xRequest , 0 ) ;
2008-08-24 00:45:20 +00:00
if ( outBuf ) {
2003-01-14 21:02:14 +00:00
RETVAL_STRING ( outBuf , 1 ) ;
free ( outBuf ) ;
}
XMLRPC_RequestFree ( xRequest , 1 ) ;
}
}
2007-07-12 10:04:42 +00:00
2008-12-27 19:06:19 +00:00
if ( strcmp ( out . xmlrpc_out . xml_elem_opts . encoding , ENCODING_DEFAULT ) ! = 0 ) {
2006-11-13 12:49:18 +00:00
efree ( ( char * ) out . xmlrpc_out . xml_elem_opts . encoding ) ;
2005-06-30 22:29:36 +00:00
}
2001-09-06 04:13:30 +00:00
}
2002-03-14 12:20:53 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* {{{ proto string xmlrpc_encode(mixed value)
2001-10-17 18:52:33 +00:00
Generates XML for a PHP value */
2001-09-06 04:13:30 +00:00
PHP_FUNCTION ( xmlrpc_encode )
{
2003-01-14 21:02:14 +00:00
XMLRPC_VALUE xOut = NULL ;
zval * * arg1 ;
char * outBuf ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " Z " , & arg1 ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( return_value_used ) {
2003-01-14 21:02:14 +00:00
/* convert native php type to xmlrpc type */
2005-10-05 16:39:37 +00:00
xOut = PHP_to_XMLRPC ( * arg1 TSRMLS_CC ) ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
/* generate raw xml from xmlrpc data */
outBuf = XMLRPC_VALUE_ToXML ( xOut , 0 ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( xOut ) {
if ( outBuf ) {
2003-01-14 21:02:14 +00:00
RETVAL_STRING ( outBuf , 1 ) ;
free ( outBuf ) ;
}
/* cleanup */
XMLRPC_CleanupValue ( xOut ) ;
}
}
2001-09-06 04:13:30 +00:00
}
/* }}} */
2008-08-24 00:45:20 +00:00
zval * decode_request_worker ( char * xml_in , int xml_in_len , char * encoding_in , zval * method_name_out ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
zval * retval = NULL ;
XMLRPC_REQUEST response ;
STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS opts = { { 0 } } ;
2008-08-24 00:45:20 +00:00
opts . xml_elem_opts . encoding = encoding_in ? utf8_get_encoding_id_from_string ( encoding_in ) : ENCODING_DEFAULT ;
2007-07-12 10:04:42 +00:00
/* generate XMLRPC_REQUEST from raw xml */
2008-08-24 00:45:20 +00:00
response = XMLRPC_REQUEST_FromXML ( xml_in , xml_in_len , & opts ) ;
if ( response ) {
2007-07-12 10:04:42 +00:00
/* convert xmlrpc data to native php types */
retval = XMLRPC_to_PHP ( XMLRPC_RequestGetData ( response ) ) ;
2008-08-24 00:45:20 +00:00
if ( XMLRPC_RequestGetRequestType ( response ) = = xmlrpc_request_call ) {
if ( method_name_out ) {
2007-07-12 10:04:42 +00:00
zval_dtor ( method_name_out ) ;
Z_TYPE_P ( method_name_out ) = IS_STRING ;
Z_STRVAL_P ( method_name_out ) = estrdup ( XMLRPC_RequestGetMethodName ( response ) ) ;
Z_STRLEN_P ( method_name_out ) = strlen ( Z_STRVAL_P ( method_name_out ) ) ;
}
}
/* dust, sweep, and mop */
XMLRPC_RequestFree ( response , 1 ) ;
}
return retval ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
2001-10-17 18:52:33 +00:00
/* {{{ proto array xmlrpc_decode_request(string xml, string& method [, string encoding])
Decodes XML into native PHP types */
2001-09-06 04:13:30 +00:00
PHP_FUNCTION ( xmlrpc_decode_request )
{
2008-08-24 00:45:20 +00:00
char * xml , * encoding = NULL ;
zval * * method ;
int xml_len , encoding_len = 0 ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " sZ|s " , & xml , & xml_len , & method , & encoding , & encoding_len ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
convert_to_string_ex ( method ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( return_value_used ) {
zval * retval = decode_request_worker ( xml , xml_len , encoding_len ? encoding : NULL , * method ) ;
if ( retval ) {
2003-01-14 21:02:14 +00:00
* return_value = * retval ;
FREE_ZVAL ( retval ) ;
}
}
2001-09-06 04:13:30 +00:00
}
/* }}} */
2001-10-17 18:52:33 +00:00
/* {{{ proto array xmlrpc_decode(string xml [, string encoding])
Decodes XML into native PHP types */
2001-09-06 04:13:30 +00:00
PHP_FUNCTION ( xmlrpc_decode )
{
2008-08-24 00:45:20 +00:00
char * arg1 , * arg2 = NULL ;
int arg1_len , arg2_len = 0 ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|s " , & arg1 , & arg1_len , & arg2 , & arg2_len ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( return_value_used ) {
zval * retval = decode_request_worker ( arg1 , arg1_len , arg2_len ? arg2 : NULL , NULL ) ;
if ( retval ) {
2003-01-14 21:02:14 +00:00
* return_value = * retval ;
FREE_ZVAL ( retval ) ;
}
}
2001-09-06 04:13:30 +00:00
}
/* }}} */
/*************************
2008-08-24 00:45:20 +00:00
* server related methods *
* * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-06 04:13:30 +00:00
2003-03-01 15:40:06 +00:00
/* {{{ proto resource xmlrpc_server_create(void)
2001-10-17 18:52:33 +00:00
Creates an xmlrpc server */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_server_create )
{
2008-02-28 14:16:25 +00:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( return_value_used ) {
2003-01-14 21:02:14 +00:00
zval * method_map , * introspection_map ;
xmlrpc_server_data * server = emalloc ( sizeof ( xmlrpc_server_data ) ) ;
MAKE_STD_ZVAL ( method_map ) ;
MAKE_STD_ZVAL ( introspection_map ) ;
2007-07-12 10:04:42 +00:00
2003-01-14 21:02:14 +00:00
array_init ( method_map ) ;
array_init ( introspection_map ) ;
2007-07-12 10:04:42 +00:00
2003-01-14 21:02:14 +00:00
/* allocate server data. free'd in destroy_server_data() */
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 ) ;
}
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
2003-07-19 19:11:01 +00:00
/* {{{ proto int xmlrpc_server_destroy(resource server)
2001-10-17 18:52:33 +00:00
Destroys server resources */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_server_destroy )
{
2008-08-24 00:45:20 +00:00
zval * arg1 ;
int bSuccess = FAILURE , type ;
xmlrpc_server_data * server ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " r " , & arg1 ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
server = zend_list_find ( Z_LVAL_P ( arg1 ) , & type ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( server & & type = = le_xmlrpc_server ) {
bSuccess = zend_list_delete ( Z_LVAL_P ( arg1 ) ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
/* called by hashtable destructor
* destroy_server_data ( server ) ;
*/
2003-01-14 21:02:14 +00:00
}
RETVAL_LONG ( bSuccess = = SUCCESS ) ;
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* called by xmlrpc C engine as method handler for all registered methods.
* it then calls the corresponding PHP function to handle the method .
*/
2007-07-12 10:04:42 +00:00
static XMLRPC_VALUE php_xmlrpc_callback ( XMLRPC_SERVER server , XMLRPC_REQUEST xRequest , void * data ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
xmlrpc_callback_data * pData = ( xmlrpc_callback_data * ) data ;
zval * xmlrpc_params ;
zval * callback_params [ 3 ] ;
TSRMLS_FETCH ( ) ;
2001-09-06 04:13:30 +00:00
2007-07-12 10:04:42 +00:00
/* convert xmlrpc to native php types */
xmlrpc_params = XMLRPC_to_PHP ( XMLRPC_RequestGetData ( xRequest ) ) ;
2001-09-06 04:13:30 +00:00
2007-07-12 10:04:42 +00:00
/* setup data hoojum */
callback_params [ 0 ] = pData - > xmlrpc_method ;
callback_params [ 1 ] = xmlrpc_params ;
callback_params [ 2 ] = pData - > caller_params ;
2001-09-06 04:13:30 +00:00
2007-07-12 10:04:42 +00:00
/* Use same C function for all methods */
2001-09-06 04:13:30 +00:00
2007-07-12 10:04:42 +00:00
/* 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 ;
2001-10-30 02:33:13 +00:00
2007-11-12 11:22:00 +00:00
zval_ptr_dtor ( & xmlrpc_params ) ;
2002-04-17 07:33:39 +00:00
2001-10-30 02:33:13 +00:00
return NULL ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* called by the C server when it first receives an introspection request. We pass this on to
* our PHP listeners , if any
*/
2007-07-12 10:04:42 +00:00
static void php_xmlrpc_introspection_callback ( XMLRPC_SERVER server , void * data ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2008-07-20 15:52:07 +00:00
zval retval , * * php_function ;
2008-08-24 00:45:20 +00:00
zval * callback_params [ 1 ] ;
2008-07-20 15:52:07 +00:00
zval php_function_name ;
2007-07-12 10:04:42 +00:00
xmlrpc_callback_data * pData = ( xmlrpc_callback_data * ) data ;
TSRMLS_FETCH ( ) ;
/* 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 ) ) ;
2008-08-24 00:45:20 +00:00
while ( 1 ) {
if ( zend_hash_get_current_data ( Z_ARRVAL_P ( pData - > server - > introspection_map ) , ( void * * ) & php_function ) = = SUCCESS ) {
2008-08-02 04:40:45 +00:00
if ( zend_is_callable ( * php_function , 0 , & php_function_name TSRMLS_CC ) ) {
2008-07-20 15:52:07 +00:00
/* php func prototype: function string user_func($user_params) */
if ( call_user_function ( CG ( function_table ) , NULL , * php_function , & retval , 1 , callback_params TSRMLS_CC ) = = SUCCESS ) {
XMLRPC_VALUE xData ;
STRUCT_XMLRPC_ERROR err = { 0 } ;
2007-07-12 10:04:42 +00:00
2008-07-20 15:52:07 +00:00
/* return value should be a string */
convert_to_string ( & retval ) ;
2007-07-12 10:04:42 +00:00
2008-07-20 15:52:07 +00:00
xData = XMLRPC_IntrospectionCreateDescription ( Z_STRVAL ( retval ) , & err ) ;
2007-07-12 10:04:42 +00:00
2008-08-24 00:45:20 +00:00
if ( xData ) {
if ( ! XMLRPC_ServerAddIntrospectionData ( server , xData ) ) {
2008-07-20 15:52:07 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to add introspection data returned from %v(), improper element structure " , Z_UNIVAL ( php_function_name ) ) ;
}
XMLRPC_CleanupValue ( xData ) ;
} else {
/* could not create description */
2008-08-24 00:45:20 +00:00
if ( err . xml_elem_error . parser_code ) {
2008-07-20 15:52:07 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %v() " ,
2008-08-24 00:45:20 +00:00
err . xml_elem_error . column , err . xml_elem_error . line , err . xml_elem_error . parser_error , Z_UNIVAL ( php_function_name ) ) ;
2008-07-20 15:52:07 +00:00
} else {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to add introspection data returned from %v() " , Z_UNIVAL ( php_function_name ) ) ;
}
2007-07-12 10:04:42 +00:00
}
2008-07-20 15:52:07 +00:00
zval_dtor ( & retval ) ;
} else {
/* user func failed */
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error calling user introspection callback: %v() " , Z_UNIVAL ( php_function_name ) ) ;
2007-07-12 10:04:42 +00:00
}
2008-07-20 15:52:07 +00:00
} else {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid callback '%v' passed " , Z_UNIVAL ( php_function_name ) ) ;
2007-07-12 10:04:42 +00:00
}
2008-07-20 15:52:07 +00:00
zval_dtor ( & php_function_name ) ;
} else {
2007-07-12 10:04:42 +00:00
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 ) ) ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
2003-03-01 15:40:06 +00:00
/* {{{ proto bool xmlrpc_server_register_method(resource server, string method_name, string function)
2001-10-17 18:52:33 +00:00
Register a PHP function to handle method matching method_name */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_server_register_method )
{
2008-08-24 00:45:20 +00:00
char * method_key ;
int method_key_len ;
zval * handle , * method_name_save , * * method_name ;
2003-01-14 21:02:14 +00:00
int type ;
xmlrpc_server_data * server ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " rsZ " , & handle , & method_key , & method_key_len , & method_name ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
server = zend_list_find ( Z_LVAL_P ( handle ) , & type ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( type = = le_xmlrpc_server ) {
2003-01-14 21:02:14 +00:00
/* register with C engine. every method just calls our standard callback,
* and it then dispatches to php as necessary
*/
2008-08-24 00:45:20 +00:00
if ( XMLRPC_ServerRegisterMethod ( server - > server_ptr , method_key , php_xmlrpc_callback ) ) {
2003-01-14 21:02:14 +00:00
/* save for later use */
MAKE_STD_ZVAL ( method_name_save ) ;
* method_name_save = * * method_name ;
zval_copy_ctor ( method_name_save ) ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
/* register our php method */
2008-08-24 00:45:20 +00:00
add_zval ( server - > method_map , method_key , & method_name_save ) ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
RETURN_BOOL ( 1 ) ;
}
}
RETURN_BOOL ( 0 ) ;
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
2003-03-01 15:40:06 +00:00
/* {{{ proto bool xmlrpc_server_register_introspection_callback(resource server, string function)
2001-10-17 18:52:33 +00:00
Register a PHP function to generate documentation */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_server_register_introspection_callback )
{
2008-08-24 00:45:20 +00:00
zval * * method_name , * handle , * method_name_save ;
2003-01-14 21:02:14 +00:00
int type ;
xmlrpc_server_data * server ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " rZ " , & handle , & method_name ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
server = zend_list_find ( Z_LVAL_P ( handle ) , & type ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( type = = le_xmlrpc_server ) {
2003-01-14 21:02:14 +00:00
/* save for later use */
MAKE_STD_ZVAL ( method_name_save ) ;
* method_name_save = * * method_name ;
zval_copy_ctor ( method_name_save ) ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
/* register our php method */
add_zval ( server - > introspection_map , NULL , & method_name_save ) ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
RETURN_BOOL ( 1 ) ;
}
RETURN_BOOL ( 0 ) ;
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* this function is itchin for a re-write */
2008-08-24 00:45:20 +00:00
2003-03-01 15:40:06 +00:00
/* {{{ proto mixed xmlrpc_server_call_method(resource server, string xml, mixed user_data [, array output_options])
2001-10-17 18:52:33 +00:00
Parses XML requests and call methods */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_server_call_method )
{
2003-01-14 21:02:14 +00:00
xmlrpc_callback_data data = { 0 } ;
XMLRPC_REQUEST xRequest ;
STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS input_opts ;
xmlrpc_server_data * server ;
2008-08-24 00:45:20 +00:00
zval * * caller_params , * handle , * * output_opts = NULL ;
char * rawxml ;
int rawxml_len , type ;
2003-01-14 21:02:14 +00:00
php_output_options out ;
int argc = ZEND_NUM_ARGS ( ) ;
2007-07-12 10:04:42 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " rsZ|Z " , & handle , & rawxml , & rawxml_len , & caller_params , & output_opts ) ! = SUCCESS ) {
return ;
2003-01-14 21:02:14 +00:00
}
/* user output options */
2003-10-15 00:15:23 +00:00
if ( argc = = 3 ) {
set_output_options ( & out , NULL ) ;
2007-07-12 10:04:42 +00:00
} else {
2003-10-15 00:15:23 +00:00
set_output_options ( & out , * output_opts ) ;
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
server = zend_list_find ( Z_LVAL_P ( handle ) , & type ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( type = = le_xmlrpc_server ) {
2003-01-14 21:02:14 +00:00
/* 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 ) ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
/* generate an XMLRPC_REQUEST from the raw xml input */
2008-08-24 00:45:20 +00:00
xRequest = XMLRPC_REQUEST_FromXML ( rawxml , rawxml_len , & input_opts ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( xRequest ) {
2003-01-14 21:02:14 +00:00
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 ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
if ( ! methodname ) {
methodname = " " ;
}
2007-07-12 10:04:42 +00:00
2003-01-14 21:02:14 +00:00
/* 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 */
2008-08-24 00:45:20 +00:00
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 ) {
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
data . php_function = * php_function ;
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
/* 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 ) ;
2008-08-24 00:45:20 +00:00
if ( xAnswer & & out . b_php_out ) {
2003-01-14 21:02:14 +00:00
zval_dtor ( data . return_data ) ;
FREE_ZVAL ( data . return_data ) ;
data . return_data = XMLRPC_to_PHP ( xAnswer ) ;
2008-08-24 00:45:20 +00:00
} else if ( data . php_executed & & ! out . b_php_out ) {
2005-10-05 16:39:37 +00:00
xAnswer = PHP_to_XMLRPC ( data . return_data TSRMLS_CC ) ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
/* should we return data as xml? */
2008-08-24 00:45:20 +00:00
if ( ! out . b_php_out ) {
2003-01-14 21:02:14 +00:00
XMLRPC_REQUEST xResponse = XMLRPC_RequestNew ( ) ;
2008-08-24 00:45:20 +00:00
if ( xResponse ) {
2003-01-14 21:02:14 +00:00
char * outBuf = 0 ;
int buf_len = 0 ;
2001-09-06 04:13:30 +00:00
2001-10-30 02:33:13 +00:00
/* 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 ;
}
}
2003-01-14 21:02:14 +00:00
/* 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 */
outBuf = XMLRPC_REQUEST_ToXML ( xResponse , & buf_len ) ;
2008-08-24 00:45:20 +00:00
if ( outBuf ) {
2003-01-14 21:02:14 +00:00
RETVAL_STRINGL ( outBuf , buf_len , 1 ) ;
free ( outBuf ) ;
}
/* cleanup after ourselves. what a sty! */
XMLRPC_RequestFree ( xResponse , 0 ) ;
}
} else { /* or as native php types? */
* return_value = * data . return_data ;
zval_copy_ctor ( return_value ) ;
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
/* cleanup after ourselves. what a sty! */
2009-04-02 15:52:26 +00:00
zval_ptr_dtor ( & data . xmlrpc_method ) ;
2003-01-14 21:02:14 +00:00
zval_dtor ( data . return_data ) ;
FREE_ZVAL ( data . return_data ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( xAnswer ) {
2003-01-14 21:02:14 +00:00
XMLRPC_CleanupValue ( xAnswer ) ;
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
XMLRPC_RequestFree ( xRequest , 1 ) ;
}
}
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
2003-03-01 15:40:06 +00:00
/* {{{ proto int xmlrpc_server_add_introspection_data(resource server, array desc)
2001-10-17 18:52:33 +00:00
Adds introspection documentation */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_server_add_introspection_data )
{
2008-08-24 00:45:20 +00:00
zval * handle , * desc ;
2003-01-14 21:02:14 +00:00
int type ;
xmlrpc_server_data * server ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ra " , & handle , & desc ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
server = zend_list_find ( Z_LVAL_P ( handle ) , & type ) ;
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
if ( type = = le_xmlrpc_server ) {
2008-08-24 00:45:20 +00:00
XMLRPC_VALUE xDesc = PHP_to_XMLRPC ( desc TSRMLS_CC ) ;
2003-01-14 21:02:14 +00:00
if ( xDesc ) {
int retval = XMLRPC_ServerAddIntrospectionData ( server - > server_ptr , xDesc ) ;
XMLRPC_CleanupValue ( xDesc ) ;
RETURN_LONG ( retval ) ;
}
}
RETURN_LONG ( 0 ) ;
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* {{{ proto array xmlrpc_parse_method_descriptions(string xml)
2001-10-17 18:52:33 +00:00
Decodes XML into a list of method descriptions */
2001-09-06 04:13:30 +00:00
PHP_FUNCTION ( xmlrpc_parse_method_descriptions )
{
2008-08-24 00:45:20 +00:00
zval * retval ;
char * arg1 ;
int arg1_len ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & arg1 , & arg1_len ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( return_value_used ) {
2003-01-14 21:02:14 +00:00
STRUCT_XMLRPC_ERROR err = { 0 } ;
2008-08-24 00:45:20 +00:00
XMLRPC_VALUE xVal = XMLRPC_IntrospectionCreateDescription ( arg1 , & err ) ;
if ( xVal ) {
2003-01-14 21:02:14 +00:00
retval = XMLRPC_to_PHP ( xVal ) ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( retval ) {
2003-01-14 21:02:14 +00:00
* return_value = * retval ;
zval_copy_ctor ( return_value ) ;
}
/* dust, sweep, and mop */
XMLRPC_CleanupValue ( xVal ) ;
} else {
/* could not create description */
2008-08-24 00:45:20 +00:00
if ( err . xml_elem_error . parser_code ) {
2003-08-31 20:45:51 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " xml parse error: [line %ld, column %ld, message: %s] Unable to create introspection data " ,
2007-07-12 10:04:42 +00:00
err . xml_elem_error . column , err . xml_elem_error . line , err . xml_elem_error . parser_error ) ;
2003-01-14 21:02:14 +00:00
} else {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid xml structure. Unable to create introspection data " ) ;
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " xml parse error. no method description created " ) ;
}
}
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/************
2008-08-24 00:45:20 +00:00
* type data *
* * * * * * * * * * * */
2001-09-06 04:13:30 +00:00
# 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 */
2007-07-12 10:04:42 +00:00
static const char * * get_type_str_mapping ( void ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
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 ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* map an xmlrpc type to a string */
2007-07-12 10:04:42 +00:00
const char * xmlrpc_type_as_str ( XMLRPC_VALUE_TYPE type , XMLRPC_VECTOR_TYPE vtype ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
const char * * str_mapping = get_type_str_mapping ( ) ;
2002-03-14 12:20:53 +00:00
2007-07-12 10:04:42 +00:00
if ( vtype = = xmlrpc_vector_none ) {
return str_mapping [ type ] ;
} else {
return str_mapping [ XMLRPC_TYPE_COUNT + vtype ] ;
}
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* map a string to an xmlrpc type */
2007-07-12 10:04:42 +00:00
XMLRPC_VALUE_TYPE xmlrpc_str_as_type ( const char * str ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
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 ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* map a string to an xmlrpc vector type */
2007-07-12 10:04:42 +00:00
XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type ( const char * str ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
const char * * str_mapping = get_type_str_mapping ( ) ;
int i ;
2001-09-06 04:13:30 +00:00
2007-07-12 10:04:42 +00:00
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 ;
}
/* }}} */
2001-09-06 04:13:30 +00:00
/* 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 .
*/
2007-07-12 10:04:42 +00:00
int set_zval_xmlrpc_type ( zval * value , XMLRPC_VALUE_TYPE newtype ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
int bSuccess = FAILURE ;
TSRMLS_FETCH ( ) ;
/* 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 ) ;
2008-08-24 00:45:20 +00:00
if ( newtype = = xmlrpc_datetime ) {
2007-07-12 10:04:42 +00:00
XMLRPC_VALUE v = XMLRPC_CreateValueDateTime_ISO8601 ( NULL , value - > value . str . val ) ;
2008-08-24 00:45:20 +00:00
if ( v ) {
2009-05-14 12:30:06 +00:00
time_t timestamp = ( time_t ) php_parse_date ( ( char * ) XMLRPC_GetValueDateTime_ISO8601 ( v ) , NULL ) ;
2009-05-22 12:49:22 +00:00
if ( timestamp ! = - 1 ) {
2007-07-12 10:04:42 +00:00
zval * ztimestamp ;
MAKE_STD_ZVAL ( ztimestamp ) ;
ztimestamp - > type = IS_LONG ;
ztimestamp - > value . lval = timestamp ;
convert_to_object ( value ) ;
2008-08-24 00:45:20 +00:00
if ( SUCCESS = = zend_hash_update ( Z_OBJPROP_P ( value ) , OBJECT_TYPE_ATTR , sizeof ( OBJECT_TYPE_ATTR ) , ( void * ) & type , sizeof ( zval * ) , NULL ) ) {
2007-07-12 10:04:42 +00:00
bSuccess = zend_hash_update ( Z_OBJPROP_P ( value ) , OBJECT_VALUE_TS_ATTR , sizeof ( OBJECT_VALUE_TS_ATTR ) , ( void * ) & ztimestamp , sizeof ( zval * ) , NULL ) ;
}
2007-09-18 19:52:27 +00:00
} else {
zval_ptr_dtor ( & type ) ;
2007-07-12 10:04:42 +00:00
}
XMLRPC_CleanupValue ( v ) ;
2007-09-18 19:52:27 +00:00
} else {
zval_ptr_dtor ( & type ) ;
2007-07-12 10:04:42 +00:00
}
2008-08-24 00:45:20 +00:00
} else {
2007-07-12 10:04:42 +00:00
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 ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* return xmlrpc type of a php value */
2007-07-12 10:04:42 +00:00
XMLRPC_VALUE_TYPE get_zval_xmlrpc_type ( zval * value , zval * * newvalue ) /* { { { */
2002-03-14 12:20:53 +00:00
{
2007-07-12 10:04:42 +00:00
XMLRPC_VALUE_TYPE type = xmlrpc_none ;
TSRMLS_FETCH ( ) ;
if ( value ) {
switch ( Z_TYPE_P ( value ) ) {
case IS_NULL :
type = xmlrpc_base64 ;
break ;
2003-03-01 15:40:06 +00:00
# ifndef BOOL_AS_LONG
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
/* Right thing to do, but it breaks some legacy code. */
2007-07-12 10:04:42 +00:00
case IS_BOOL :
type = xmlrpc_boolean ;
break ;
2003-03-01 15:40:06 +00:00
# else
2007-07-12 10:04:42 +00:00
case IS_BOOL :
2003-03-01 15:40:06 +00:00
# endif
2007-07-12 10:04:42 +00:00
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 :
2008-08-24 00:45:20 +00:00
case IS_UNICODE :
2007-07-12 10:04:42 +00:00
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 ;
}
}
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
/* if requested, return an unmolested (magic removed) copy of the value */
if ( newvalue ) {
zval * * val ;
2001-09-06 04:13:30 +00:00
2002-03-14 12:20:53 +00:00
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 ;
2001-09-06 04:13:30 +00:00
}
2007-07-12 10:04:42 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* {{{ proto bool xmlrpc_set_type(string value, string type)
2001-10-17 18:52:33 +00:00
Sets xmlrpc type , base64 or datetime , for a PHP string value */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_set_type )
{
2008-08-24 00:45:20 +00:00
zval * * arg ;
char * type ;
int type_len ;
2003-01-14 21:02:14 +00:00
XMLRPC_VALUE_TYPE vtype ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " Zs " , & arg , & type , & type_len ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
vtype = xmlrpc_str_as_type ( type ) ;
2003-01-14 21:02:14 +00:00
if ( vtype ! = xmlrpc_none ) {
if ( set_zval_xmlrpc_type ( * arg , vtype ) = = SUCCESS ) {
RETURN_TRUE ;
}
} else {
2008-08-24 00:45:20 +00:00
zend_error ( E_WARNING , " invalid type '%s' passed to xmlrpc_set_type() " , type ) ;
2003-01-14 21:02:14 +00:00
}
RETURN_FALSE ;
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
/* {{{ proto string xmlrpc_get_type(mixed value)
2001-10-17 18:52:33 +00:00
Gets xmlrpc type for a PHP value . Especially useful for base64 and datetime strings */
2002-03-14 12:20:53 +00:00
PHP_FUNCTION ( xmlrpc_get_type )
{
2003-01-14 21:02:14 +00:00
zval * * arg ;
XMLRPC_VALUE_TYPE type ;
XMLRPC_VECTOR_TYPE vtype = xmlrpc_vector_none ;
2001-09-06 04:13:30 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " Z " , & arg ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2001-09-06 04:13:30 +00:00
2003-01-14 21:02:14 +00:00
type = get_zval_xmlrpc_type ( * arg , 0 ) ;
if ( type = = xmlrpc_vector ) {
2006-08-11 17:41:49 +00:00
vtype = determine_vector_type ( ( Z_TYPE_PP ( arg ) = = IS_OBJECT ) ? Z_OBJPROP_PP ( arg ) : Z_ARRVAL_PP ( arg ) ) ;
2003-01-14 21:02:14 +00:00
}
2007-07-12 10:04:42 +00:00
2003-01-14 21:02:14 +00:00
RETURN_STRING ( ( char * ) xmlrpc_type_as_str ( type , vtype ) , 1 ) ;
2001-09-06 04:13:30 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2001-09-06 04:13:30 +00:00
2003-07-19 19:11:01 +00:00
/* {{{ proto bool xmlrpc_is_fault(array)
2002-07-05 04:43:55 +00:00
Determines if an array value represents an XMLRPC fault . */
PHP_FUNCTION ( xmlrpc_is_fault )
{
2008-08-24 00:45:20 +00:00
zval * arg , * * val ;
2002-07-05 04:43:55 +00:00
2008-08-24 00:45:20 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " a " , & arg ) = = FAILURE ) {
return ;
2003-01-14 21:02:14 +00:00
}
2002-07-05 04:43:55 +00:00
2008-08-24 00:45:20 +00:00
/* 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 ;
2002-07-05 04:43:55 +00:00
}
2003-01-14 21:02:14 +00:00
RETURN_FALSE ;
2002-07-05 04:43:55 +00:00
}
2003-03-01 15:40:06 +00:00
/* }}} */
2002-07-05 04:43:55 +00:00
2001-09-06 04:13:30 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
*/