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 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2014-09-19 16:33:14 +00:00
|
|
|
| PHP Version 7 |
|
2001-09-06 04:13:30 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2014-01-03 03:08:10 +00:00
|
|
|
| Copyright (c) 1997-2014 The PHP Group |
|
2001-09-06 04:13:30 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2006-01-01 12:51:34 +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 12:51:34 +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"
|
2010-12-13 09:52:05 +00:00
|
|
|
#include "ext/standard/php_string.h"
|
2009-05-14 12:29:47 +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:05:59 +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-18 19:24:03 +00:00
|
|
|
ZEND_ARG_INFO(0, params)
|
2008-06-28 22:05:59 +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:00:48 +00:00
|
|
|
const zend_function_entry xmlrpc_functions[] = {
|
2008-06-28 22:05:59 +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)
|
2011-07-25 11:35:02 +00:00
|
|
|
PHP_FE_END
|
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:32:15 +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 {
|
2014-05-12 11:28:06 +00:00
|
|
|
zval method_map;
|
|
|
|
zval introspection_map;
|
2002-03-14 12:20:53 +00:00
|
|
|
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 {
|
2014-05-12 11:28:06 +00:00
|
|
|
zval xmlrpc_method;
|
|
|
|
zval php_function;
|
|
|
|
zval caller_params;
|
|
|
|
zval return_data;
|
2002-03-14 12:20:53 +00:00
|
|
|
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 *
|
|
|
|
***********************/
|
2014-05-12 11:28:06 +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);
|
2014-05-12 11:28:06 +00:00
|
|
|
void decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out, zval *retval);
|
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:15:46 +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
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
zval_ptr_dtor(&server->method_map);
|
|
|
|
zval_ptr_dtor(&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
|
|
|
}
|
|
|
|
|
|
|
|
/* 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. */
|
2014-05-12 11:28:06 +00:00
|
|
|
static void xmlrpc_server_destructor(zend_resource *rsrc TSRMLS_DC)
|
2001-10-21 17:23:39 +00:00
|
|
|
{
|
2002-03-14 12:20:53 +00:00
|
|
|
if (rsrc && rsrc->ptr) {
|
2014-05-19 09:11:20 +00:00
|
|
|
rsrc->gc.refcount++;
|
2008-08-15 22:15:46 +00:00
|
|
|
destroy_server_data((xmlrpc_server_data*) rsrc->ptr TSRMLS_CC);
|
2014-05-19 09:11:20 +00:00
|
|
|
rsrc->gc.refcount--;
|
2002-03-14 12:20:53 +00:00
|
|
|
}
|
2001-10-21 17:23:39 +00:00
|
|
|
}
|
|
|
|
|
2001-09-06 04:13:30 +00:00
|
|
|
/* module init */
|
|
|
|
PHP_MINIT_FUNCTION(xmlrpc)
|
|
|
|
{
|
2002-03-14 12:20:53 +00:00
|
|
|
le_xmlrpc_server = zend_register_list_destructors_ex(xmlrpc_server_destructor, NULL, "xmlrpc server", module_number);
|
2001-10-26 12:54:55 +00:00
|
|
|
|
2002-03-14 12:20:53 +00:00
|
|
|
return SUCCESS;
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* display info in phpinfo() */
|
|
|
|
PHP_MINFO_FUNCTION(xmlrpc)
|
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/*******************
|
|
|
|
* random utilities *
|
|
|
|
*******************/
|
|
|
|
|
|
|
|
/* 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) {
|
2014-08-25 17:24:55 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-04-15 11:40:40 +00:00
|
|
|
static int add_string(zval* list, char* id, char* string) {
|
|
|
|
if(id) return add_assoc_string(list, id, string);
|
|
|
|
else return add_next_index_string(list, string);
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
2014-04-15 11:40:40 +00:00
|
|
|
static int add_stringl(zval* list, char* id, char* string, uint length) {
|
|
|
|
if(id) return add_assoc_stringl(list, id, string, length);
|
|
|
|
else return add_next_index_stringl(list, string, length);
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
2001-10-25 06:51:13 +00:00
|
|
|
#endif
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
static void 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:13:57 +00:00
|
|
|
int id_len = strlen(id);
|
2014-08-25 17:24:55 +00:00
|
|
|
if (!(id_len > 1 && id[0] == '0') && is_numeric_string((char *)id, id_len, NULL, NULL, 0) == IS_LONG) {
|
2006-04-12 15:13:57 +00:00
|
|
|
long index = strtol(id, NULL, 0);
|
2014-05-12 11:28:06 +00:00
|
|
|
zend_hash_index_update(Z_ARRVAL_P(list), index, val);
|
2006-04-12 15:13:57 +00:00
|
|
|
} else {
|
2014-05-12 11:28:06 +00:00
|
|
|
zend_hash_str_update(Z_ARRVAL_P(list), (char*)id, strlen(id), val);
|
2006-04-12 15:13:57 +00:00
|
|
|
}
|
2002-03-14 12:20:53 +00:00
|
|
|
} else {
|
2014-05-12 11:28:06 +00:00
|
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(list), val);
|
2002-03-14 12:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*************************
|
|
|
|
* input / output options *
|
|
|
|
*************************/
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
static void set_output_options(php_output_options* options, zval* output_opts)
|
|
|
|
{
|
|
|
|
if (options) {
|
|
|
|
/* 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) {
|
2014-05-12 11:28:06 +00:00
|
|
|
zval* val;
|
2002-03-14 12:20:53 +00:00
|
|
|
|
|
|
|
/* type of output (xml/php) */
|
2014-05-12 11:28:06 +00:00
|
|
|
if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), OUTPUT_TYPE_KEY, OUTPUT_TYPE_KEY_LEN)) != NULL) {
|
|
|
|
if (Z_TYPE_P(val) == IS_STRING) {
|
|
|
|
if (!strcmp(Z_STRVAL_P(val), OUTPUT_TYPE_VALUE_PHP)) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->b_php_out = 1;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), OUTPUT_TYPE_VALUE_XML)) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->b_php_out = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* verbosity of generated xml */
|
2014-05-12 11:28:06 +00:00
|
|
|
if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), VERBOSITY_KEY, VERBOSITY_KEY_LEN)) != NULL) {
|
|
|
|
if (Z_TYPE_P(val) == IS_STRING) {
|
|
|
|
if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_NO_WHITE_SPACE)) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_no_white_space;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_NEWLINES_ONLY)) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_newlines_only;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_PRETTY)) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_pretty;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* version of xml to output */
|
2014-05-12 11:28:06 +00:00
|
|
|
if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), VERSION_KEY, VERSION_KEY_LEN)) != NULL) {
|
|
|
|
if (Z_TYPE_P(val) == IS_STRING) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->b_auto_version = 0;
|
2014-05-12 11:28:06 +00:00
|
|
|
if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_XMLRPC)) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->xmlrpc_out.version = xmlrpc_version_1_0;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_SIMPLE)) {
|
2002-03-14 12:20:53 +00:00
|
|
|
options->xmlrpc_out.version = xmlrpc_version_simple;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_SOAP11)) {
|
|
|
|
options->xmlrpc_out.version = xmlrpc_version_soap_1_1;
|
2002-03-14 12:20:53 +00:00
|
|
|
} else { /* if(!strcmp((*val)->value.str.val, VERSION_VALUE_AUTO)) { */
|
2014-05-12 11:28:06 +00:00
|
|
|
options->b_auto_version = 1;
|
2002-03-14 12:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
/* encoding code set */
|
|
|
|
if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN)) != NULL) {
|
|
|
|
if (Z_TYPE_P(val) == IS_STRING) {
|
|
|
|
options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_P(val));
|
|
|
|
}
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
/* escaping options */
|
|
|
|
if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN)) != NULL) {
|
|
|
|
/* multiple values allowed. check if array */
|
|
|
|
if (Z_TYPE_P(val) == IS_ARRAY) {
|
|
|
|
zval* iter_val;
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping;
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(val), iter_val) {
|
|
|
|
if (Z_TYPE_P(iter_val) == IS_STRING && Z_STRVAL_P(iter_val)) {
|
|
|
|
if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_CDATA)) {
|
2008-06-20 11:38:52 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_ASCII)) {
|
2008-06-20 11:38:52 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_PRINT)) {
|
2008-06-20 11:38:52 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_MARKUP)) {
|
2008-06-20 11:38:52 +00:00
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping;
|
|
|
|
}
|
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
/* else, check for single value */
|
|
|
|
} else if (Z_TYPE_P(val) == IS_STRING) {
|
|
|
|
if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_CDATA)) {
|
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping;
|
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_ASCII)) {
|
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping;
|
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_PRINT)) {
|
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping;
|
|
|
|
} else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_MARKUP)) {
|
|
|
|
options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping;
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-03-14 12:20:53 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************
|
|
|
|
* encode / decode *
|
|
|
|
******************/
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2002-03-14 12:20:53 +00:00
|
|
|
static XMLRPC_VECTOR_TYPE determine_vector_type (HashTable *ht)
|
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
int bArray = 0, bStruct = 0, bMixed = 0;
|
2014-09-12 14:39:09 +00:00
|
|
|
zend_ulong num_index, last_num = 0;
|
2014-05-12 11:28:06 +00:00
|
|
|
zend_string* my_key;
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_HASH_FOREACH_KEY(ht, num_index, my_key) {
|
|
|
|
if (my_key == NULL) {
|
2008-06-20 11:38:52 +00:00
|
|
|
if (bStruct) {
|
|
|
|
bMixed = 1;
|
|
|
|
break;
|
2009-11-25 02:03:02 +00:00
|
|
|
} else if (last_num > 0 && last_num != num_index-1) {
|
|
|
|
bStruct = 1;
|
|
|
|
break;
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
bArray = 1;
|
2009-11-25 02:03:02 +00:00
|
|
|
last_num = num_index;
|
2014-05-12 11:28:06 +00:00
|
|
|
} else {
|
2008-06-20 11:38:52 +00:00
|
|
|
if (bArray) {
|
|
|
|
bMixed = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
bStruct = 1;
|
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2008-06-20 11:38:52 +00:00
|
|
|
return bMixed ? xmlrpc_vector_mixed : (bStruct ? xmlrpc_vector_struct : xmlrpc_vector_array);
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* recursively convert php values into xmlrpc values */
|
2005-10-05 16:40:21 +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
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
XMLRPC_VALUE xReturn = NULL;
|
|
|
|
|
|
|
|
if (in_val) {
|
2014-05-12 11:28:06 +00:00
|
|
|
zval val;
|
2014-08-19 06:16:34 +00:00
|
|
|
XMLRPC_VALUE_TYPE type;
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_UNDEF(&val);
|
2014-08-19 06:16:34 +00:00
|
|
|
type = get_zval_xmlrpc_type(in_val, &val);
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (!Z_ISUNDEF(val)) {
|
2008-06-20 11:38:52 +00:00
|
|
|
switch (type) {
|
|
|
|
case xmlrpc_base64:
|
2014-05-12 11:28:06 +00:00
|
|
|
if (Z_TYPE(val) == IS_NULL) {
|
2008-06-20 11:38:52 +00:00
|
|
|
xReturn = XMLRPC_CreateValueEmpty();
|
2001-10-30 02:33:13 +00:00
|
|
|
XMLRPC_SetValueID(xReturn, key, 0);
|
2008-06-20 11:38:52 +00:00
|
|
|
} else {
|
2014-08-25 17:24:55 +00:00
|
|
|
xReturn = XMLRPC_CreateValueBase64(key, Z_STRVAL(val), Z_STRLEN(val));
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case xmlrpc_datetime:
|
2014-05-12 11:28:06 +00:00
|
|
|
convert_to_string(&val);
|
|
|
|
xReturn = XMLRPC_CreateValueDateTime_ISO8601(key, Z_STRVAL(val));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_boolean:
|
2014-05-12 11:28:06 +00:00
|
|
|
convert_to_boolean(&val);
|
|
|
|
xReturn = XMLRPC_CreateValueBoolean(key, Z_TYPE(val) == IS_TRUE);
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_int:
|
2014-08-25 19:51:49 +00:00
|
|
|
convert_to_long(&val);
|
2014-08-25 17:24:55 +00:00
|
|
|
xReturn = XMLRPC_CreateValueInt(key, Z_LVAL(val));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_double:
|
2014-05-12 11:28:06 +00:00
|
|
|
convert_to_double(&val);
|
|
|
|
xReturn = XMLRPC_CreateValueDouble(key, Z_DVAL(val));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_string:
|
2014-05-12 11:28:06 +00:00
|
|
|
convert_to_string(&val);
|
2014-08-25 17:24:55 +00:00
|
|
|
xReturn = XMLRPC_CreateValueString(key, Z_STRVAL(val), Z_STRLEN(val));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_vector:
|
|
|
|
{
|
2014-09-12 14:39:09 +00:00
|
|
|
zend_ulong num_index;
|
2014-05-12 11:28:06 +00:00
|
|
|
zval* pIter;
|
|
|
|
zend_string* my_key;
|
2008-06-20 11:38:52 +00:00
|
|
|
HashTable *ht = NULL;
|
2014-05-12 11:28:06 +00:00
|
|
|
zval val_arr;
|
2009-11-25 02:03:02 +00:00
|
|
|
XMLRPC_VECTOR_TYPE vtype;
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ht = HASH_OF(&val);
|
|
|
|
if (ht && ht->u.v.nApplyCount > 1) {
|
2008-06-20 11:38:52 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_ERROR, "XML-RPC doesn't support circular references");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_COPY(&val_arr, &val);
|
|
|
|
convert_to_array(&val_arr);
|
2009-11-24 11:32:31 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
vtype = determine_vector_type(Z_ARRVAL(val_arr));
|
2009-11-25 02:03:02 +00:00
|
|
|
xReturn = XMLRPC_CreateVector(key, vtype);
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(val_arr), num_index, my_key, pIter) {
|
|
|
|
ht = HASH_OF(pIter);
|
|
|
|
if (ht) {
|
|
|
|
ht->u.v.nApplyCount++;
|
|
|
|
}
|
|
|
|
if (my_key == NULL) {
|
|
|
|
char *num_str = NULL;
|
|
|
|
|
|
|
|
if (vtype != xmlrpc_vector_array) {
|
|
|
|
spprintf(&num_str, 0, "%ld", num_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(num_str, pIter, depth++ TSRMLS_CC));
|
|
|
|
if (num_str) {
|
|
|
|
efree(num_str);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(my_key->val, pIter, depth++ TSRMLS_CC));
|
|
|
|
}
|
|
|
|
if (ht) {
|
|
|
|
ht->u.v.nApplyCount--;
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2009-11-24 11:32:31 +00:00
|
|
|
zval_ptr_dtor(&val_arr);
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return xReturn;
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
2005-10-05 16:40:21 +00:00
|
|
|
static XMLRPC_VALUE PHP_to_XMLRPC(zval* root_val TSRMLS_DC)
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
return PHP_to_XMLRPC_worker(NULL, root_val, 0 TSRMLS_CC);
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* recursively convert xmlrpc values into php values */
|
2014-05-12 11:28:06 +00:00
|
|
|
static void XMLRPC_to_PHP(XMLRPC_VALUE el, zval *elem)
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
const char* pStr;
|
|
|
|
|
|
|
|
if (el) {
|
|
|
|
XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(el);
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
switch (type) {
|
2008-06-20 11:38:52 +00:00
|
|
|
case xmlrpc_empty:
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_NULL(elem);
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_string:
|
|
|
|
pStr = XMLRPC_GetValueString(el);
|
|
|
|
if (pStr) {
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_STRINGL(elem, pStr, XMLRPC_GetValueStringLen(el));
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_int:
|
2014-08-25 17:24:55 +00:00
|
|
|
ZVAL_LONG(elem, XMLRPC_GetValueInt(el));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_boolean:
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_BOOL(elem, XMLRPC_GetValueBoolean(el));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_double:
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_DOUBLE(elem, XMLRPC_GetValueDouble(el));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_datetime:
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_STRINGL(elem, XMLRPC_GetValueDateTime_ISO8601(el), XMLRPC_GetValueStringLen(el));
|
2008-06-20 11:38:52 +00:00
|
|
|
break;
|
|
|
|
case xmlrpc_base64:
|
|
|
|
pStr = XMLRPC_GetValueBase64(el);
|
2008-08-24 00:47:22 +00:00
|
|
|
if (pStr) {
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_STRINGL(elem, pStr, XMLRPC_GetValueStringLen(el));
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case xmlrpc_vector:
|
|
|
|
array_init(elem);
|
|
|
|
{
|
|
|
|
XMLRPC_VALUE xIter = XMLRPC_VectorRewind(el);
|
|
|
|
|
|
|
|
while( xIter ) {
|
2014-05-12 11:28:06 +00:00
|
|
|
zval val;
|
|
|
|
ZVAL_UNDEF(&val);
|
|
|
|
XMLRPC_to_PHP(xIter, &val);
|
|
|
|
if (!Z_ISUNDEF(val)) {
|
2008-06-20 11:38:52 +00:00
|
|
|
add_zval(elem, XMLRPC_GetValueID(xIter), &val);
|
|
|
|
}
|
|
|
|
xIter = XMLRPC_VectorNext(el);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2008-06-20 11:38:52 +00:00
|
|
|
set_zval_xmlrpc_type(elem, type);
|
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
2008-06-28 21:36:39 +00:00
|
|
|
/* {{{ proto string xmlrpc_encode_request(string method, mixed params [, array output_options])
|
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-06-28 21:36:39 +00:00
|
|
|
char *outBuf;
|
2009-08-18 00:41:43 +00:00
|
|
|
zval *vals, *out_opts = NULL;
|
|
|
|
char *method = NULL;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t method_len;
|
2003-01-14 21:02:14 +00:00
|
|
|
php_output_options out;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2009-08-18 00:41:43 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!z|a", &method, &method_len, &vals, &out_opts) == FAILURE) {
|
2008-06-28 21:36:39 +00:00
|
|
|
return;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2009-03-19 00:18:48 +00:00
|
|
|
set_output_options(&out, out_opts ? out_opts : 0);
|
2001-10-30 02:33:13 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (USED_RET()) {
|
2003-01-14 21:02:14 +00:00
|
|
|
xRequest = XMLRPC_RequestNew();
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-08-24 00:47:22 +00:00
|
|
|
if (xRequest) {
|
2003-01-14 21:02:14 +00:00
|
|
|
XMLRPC_RequestSetOutputOptions(xRequest, &out.xmlrpc_out);
|
2009-08-18 00:41:43 +00:00
|
|
|
if (method == NULL) {
|
2003-01-14 21:02:14 +00:00
|
|
|
XMLRPC_RequestSetRequestType(xRequest, xmlrpc_request_response);
|
|
|
|
} else {
|
2009-08-18 00:41:43 +00:00
|
|
|
XMLRPC_RequestSetMethodName(xRequest, method);
|
2003-01-14 21:02:14 +00:00
|
|
|
XMLRPC_RequestSetRequestType(xRequest, xmlrpc_request_call);
|
|
|
|
}
|
2009-08-18 00:41:43 +00:00
|
|
|
if (Z_TYPE_P(vals) != IS_NULL) {
|
|
|
|
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:47:22 +00:00
|
|
|
if (outBuf) {
|
2014-05-12 11:28:06 +00:00
|
|
|
RETVAL_STRING(outBuf);
|
2003-01-14 21:02:14 +00:00
|
|
|
free(outBuf);
|
|
|
|
}
|
|
|
|
XMLRPC_RequestFree(xRequest, 1);
|
|
|
|
}
|
|
|
|
}
|
2005-06-30 22:29:36 +00:00
|
|
|
|
2008-12-27 19:06:48 +00:00
|
|
|
if (strcmp(out.xmlrpc_out.xml_elem_opts.encoding, ENCODING_DEFAULT) != 0) {
|
2006-11-13 12:49:28 +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;
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *arg1;
|
2003-01-14 21:02:14 +00:00
|
|
|
char *outBuf;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg1) == FAILURE) {
|
2008-06-28 21:36:39 +00:00
|
|
|
return;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (USED_RET()) {
|
2003-01-14 21:02:14 +00:00
|
|
|
/* convert native php type to xmlrpc type */
|
2014-05-12 11:28:06 +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:47:22 +00:00
|
|
|
if (xOut) {
|
|
|
|
if (outBuf) {
|
2014-05-12 11:28:06 +00:00
|
|
|
RETVAL_STRING(outBuf);
|
2003-01-14 21:02:14 +00:00
|
|
|
free(outBuf);
|
|
|
|
}
|
|
|
|
/* cleanup */
|
|
|
|
XMLRPC_CleanupValue(xOut);
|
|
|
|
}
|
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
void decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out, zval *retval) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
XMLRPC_REQUEST response;
|
|
|
|
STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS opts = {{0}};
|
2010-03-13 18:40:29 +00:00
|
|
|
const char *method_name;
|
2008-06-28 21:36:39 +00:00
|
|
|
opts.xml_elem_opts.encoding = encoding_in ? utf8_get_encoding_id_from_string(encoding_in) : ENCODING_DEFAULT;
|
2008-06-20 11:38:52 +00:00
|
|
|
|
|
|
|
/* generate XMLRPC_REQUEST from raw xml */
|
2008-06-28 21:36:39 +00:00
|
|
|
response = XMLRPC_REQUEST_FromXML(xml_in, xml_in_len, &opts);
|
2008-06-20 11:38:52 +00:00
|
|
|
if (response) {
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_NULL(retval);
|
2008-06-20 11:38:52 +00:00
|
|
|
/* convert xmlrpc data to native php types */
|
2014-05-12 11:28:06 +00:00
|
|
|
XMLRPC_to_PHP(XMLRPC_RequestGetData(response), retval);
|
2008-06-20 11:38:52 +00:00
|
|
|
|
|
|
|
if (XMLRPC_RequestGetRequestType(response) == xmlrpc_request_call) {
|
|
|
|
if (method_name_out) {
|
2010-03-13 18:40:29 +00:00
|
|
|
method_name = XMLRPC_RequestGetMethodName(response);
|
|
|
|
if (method_name) {
|
2014-05-12 11:28:06 +00:00
|
|
|
zval_ptr_dtor(method_name_out);
|
|
|
|
ZVAL_STRING(method_name_out, method_name);
|
|
|
|
} else {
|
|
|
|
zval_ptr_dtor(retval);
|
2014-05-12 12:39:52 +00:00
|
|
|
ZVAL_NULL(retval);
|
2010-03-13 18:40:29 +00:00
|
|
|
}
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dust, sweep, and mop */
|
|
|
|
XMLRPC_RequestFree(response, 1);
|
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
2008-08-24 00:47:22 +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-06-28 21:36:39 +00:00
|
|
|
char *xml, *encoding = NULL;
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *method;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t xml_len, encoding_len = 0;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-06-05 12:04:11 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/|s", &xml, &xml_len, &method, &encoding, &encoding_len) == FAILURE) {
|
2008-06-28 21:36:39 +00:00
|
|
|
return;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (USED_RET()) {
|
|
|
|
decode_request_worker(xml, xml_len, encoding_len ? encoding : NULL, method, return_value);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
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-06-28 21:36:39 +00:00
|
|
|
char *arg1, *arg2 = NULL;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t arg1_len, arg2_len = 0;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-28 21:36:39 +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
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (USED_RET()) {
|
|
|
|
decode_request_worker(arg1, arg1_len, arg2_len ? arg2 : NULL, NULL, return_value);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/*************************
|
|
|
|
* server related methods *
|
|
|
|
*************************/
|
|
|
|
|
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-03-10 22:15:36 +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
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (USED_RET()) {
|
2003-01-14 21:02:14 +00:00
|
|
|
xmlrpc_server_data *server = emalloc(sizeof(xmlrpc_server_data));
|
|
|
|
|
|
|
|
/* allocate server data. free'd in destroy_server_data() */
|
2014-05-12 11:28:06 +00:00
|
|
|
array_init(&server->method_map);
|
|
|
|
array_init(&server->introspection_map);
|
2003-01-14 21:02:14 +00:00
|
|
|
server->server_ptr = XMLRPC_ServerCreate();
|
|
|
|
|
|
|
|
XMLRPC_ServerRegisterIntrospectionCallback(server->server_ptr, php_xmlrpc_introspection_callback);
|
|
|
|
|
|
|
|
/* store for later use */
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_REGISTER_RESOURCE(return_value, server, le_xmlrpc_server);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
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-06-28 21:36:39 +00:00
|
|
|
zval *arg1;
|
2014-05-12 11:28:06 +00:00
|
|
|
int bSuccess = FAILURE;
|
2008-07-02 23:48:22 +00:00
|
|
|
xmlrpc_server_data *server;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-28 21:36:39 +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
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, arg1, -1, "xmlrpc server", le_xmlrpc_server);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (server) {
|
|
|
|
bSuccess = zend_list_close(Z_RES_P(arg1));
|
2008-06-28 21:36:39 +00:00
|
|
|
/* called by hashtable destructor
|
|
|
|
* destroy_server_data(server);
|
|
|
|
*/
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
RETURN_BOOL(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.
|
|
|
|
*/
|
2008-08-24 00:47:22 +00:00
|
|
|
static XMLRPC_VALUE php_xmlrpc_callback(XMLRPC_SERVER server, XMLRPC_REQUEST xRequest, void* data) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data;
|
2014-05-12 11:28:06 +00:00
|
|
|
zval* php_function;
|
|
|
|
zval xmlrpc_params;
|
|
|
|
zval callback_params[3];
|
2014-10-15 07:37:55 +00:00
|
|
|
TSRMLS_FETCH();
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
zval_ptr_dtor(&pData->xmlrpc_method);
|
|
|
|
zval_ptr_dtor(&pData->return_data);
|
2010-01-17 17:19:38 +00:00
|
|
|
|
2008-06-20 11:38:52 +00:00
|
|
|
/* convert xmlrpc to native php types */
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_STRING(&pData->xmlrpc_method, XMLRPC_RequestGetMethodName(xRequest));
|
|
|
|
XMLRPC_to_PHP(XMLRPC_RequestGetData(xRequest), &xmlrpc_params);
|
2010-01-17 17:19:38 +00:00
|
|
|
|
|
|
|
/* check if the called method has been previous registered */
|
2014-05-12 11:28:06 +00:00
|
|
|
if ((php_function = zend_hash_find(Z_ARRVAL(pData->server->method_map), Z_STR(pData->xmlrpc_method))) != NULL) {
|
|
|
|
ZVAL_COPY_VALUE(&pData->php_function, php_function);
|
2010-01-17 17:19:38 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-20 11:38:52 +00:00
|
|
|
/* setup data hoojum */
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_COPY_VALUE(&callback_params[0], &pData->xmlrpc_method);
|
|
|
|
ZVAL_COPY_VALUE(&callback_params[1], &xmlrpc_params);
|
|
|
|
ZVAL_COPY_VALUE(&callback_params[2], &pData->caller_params);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-20 11:38:52 +00:00
|
|
|
/* Use same C function for all methods */
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-20 11:38:52 +00:00
|
|
|
/* php func prototype: function user_func($method_name, $xmlrpc_params, $user_params) */
|
2014-05-12 11:28:06 +00:00
|
|
|
call_user_function(CG(function_table), NULL, &pData->php_function, &pData->return_data, 3, callback_params TSRMLS_CC);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-20 11:38:52 +00:00
|
|
|
pData->php_executed = 1;
|
2001-10-30 02:33:13 +00:00
|
|
|
|
2008-06-20 11:38:52 +00:00
|
|
|
zval_ptr_dtor(&xmlrpc_params);
|
2002-04-17 07:33:39 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
return PHP_to_XMLRPC(&pData->return_data TSRMLS_CC);
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
2008-08-24 00:47:22 +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
|
|
|
|
*/
|
2008-08-24 00:47:22 +00:00
|
|
|
static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2014-05-12 11:28:06 +00:00
|
|
|
zval retval, *php_function;
|
|
|
|
zval callback_params[1];
|
|
|
|
zend_string *php_function_name;
|
2008-06-20 11:38:52 +00:00
|
|
|
xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data;
|
2014-10-15 07:37:55 +00:00
|
|
|
TSRMLS_FETCH();
|
2008-06-20 11:38:52 +00:00
|
|
|
|
|
|
|
/* setup data hoojum */
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_COPY_VALUE(&callback_params[0], &pData->caller_params);
|
|
|
|
|
|
|
|
ZEND_HASH_FOREACH_VAL(Z_ARRVAL(pData->server->introspection_map), php_function) {
|
|
|
|
if (zend_is_callable(php_function, 0, &php_function_name TSRMLS_CC)) {
|
|
|
|
/* 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};
|
|
|
|
|
|
|
|
/* return value should be a string */
|
|
|
|
convert_to_string(&retval);
|
|
|
|
|
|
|
|
xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err);
|
|
|
|
|
|
|
|
if (xData) {
|
|
|
|
if (!XMLRPC_ServerAddIntrospectionData(server, xData)) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", php_function_name->val);
|
2008-07-18 19:24:03 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
XMLRPC_CleanupValue(xData);
|
2008-06-20 11:38:52 +00:00
|
|
|
} else {
|
2014-05-12 11:28:06 +00:00
|
|
|
/* could not create description */
|
|
|
|
if (err.xml_elem_error.parser_code) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %s()",
|
|
|
|
err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, php_function_name->val);
|
|
|
|
} else {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s()", php_function_name->val);
|
|
|
|
}
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
zval_ptr_dtor(&retval);
|
2008-07-18 19:24:03 +00:00
|
|
|
} else {
|
2014-05-12 11:28:06 +00:00
|
|
|
/* user func failed */
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling user introspection callback: %s()", php_function_name->val);
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-05-12 11:28:06 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid callback '%s' passed", php_function_name->val);
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_string_release(php_function_name);
|
2014-05-12 11:28:06 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2008-07-18 19:24:03 +00:00
|
|
|
|
2008-06-20 11:38:52 +00:00
|
|
|
/* so we don't call the same callbacks ever again */
|
2014-05-12 11:28:06 +00:00
|
|
|
zend_hash_clean(Z_ARRVAL(pData->server->introspection_map));
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
2008-08-24 00:47:22 +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-06-28 21:36:39 +00:00
|
|
|
char *method_key;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t method_key_len;
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *handle, *method_name;
|
2003-01-14 21:02:14 +00:00
|
|
|
xmlrpc_server_data* server;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz", &handle, &method_key, &method_key_len, &method_name) == FAILURE) {
|
2008-06-28 21:36:39 +00:00
|
|
|
return;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
/* register with C engine. every method just calls our standard callback,
|
|
|
|
* and it then dispatches to php as necessary
|
|
|
|
*/
|
|
|
|
if (XMLRPC_ServerRegisterMethod(server->server_ptr, method_key, php_xmlrpc_callback)) {
|
|
|
|
/* save for later use */
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (Z_REFCOUNTED_P(method_name)) {
|
|
|
|
Z_ADDREF_P(method_name);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
/* register our php method */
|
|
|
|
add_zval(&server->method_map, method_key, method_name);
|
|
|
|
|
|
|
|
RETURN_TRUE;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
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)
|
|
|
|
{
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *method_name, *handle;
|
2003-01-14 21:02:14 +00:00
|
|
|
xmlrpc_server_data* server;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &handle, &method_name) == FAILURE) {
|
2008-06-28 21:36:39 +00:00
|
|
|
return;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (Z_REFCOUNTED_P(method_name)) {
|
|
|
|
Z_ADDREF_P(method_name);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
/* register our php method */
|
|
|
|
add_zval(&server->introspection_map, NULL, method_name);
|
|
|
|
|
|
|
|
RETURN_TRUE;
|
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 */
|
|
|
|
|
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_REQUEST xRequest;
|
2014-05-12 11:28:06 +00:00
|
|
|
xmlrpc_callback_data data;
|
2003-01-14 21:02:14 +00:00
|
|
|
STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS input_opts;
|
|
|
|
xmlrpc_server_data* server;
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *caller_params, *handle, *output_opts = NULL;
|
2008-06-28 21:36:39 +00:00
|
|
|
char *rawxml;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t rawxml_len;
|
2003-01-14 21:02:14 +00:00
|
|
|
php_output_options out;
|
2014-05-12 11:28:06 +00:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
2003-01-14 21:02:14 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|a", &handle, &rawxml, &rawxml_len, &caller_params, &output_opts) != SUCCESS) {
|
2008-06-28 21:36:39 +00:00
|
|
|
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);
|
2008-06-28 21:36:39 +00:00
|
|
|
} else {
|
2009-08-18 00:41:43 +00:00
|
|
|
set_output_options(&out, output_opts);
|
2003-10-15 00:15:23 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +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
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
/* generate an XMLRPC_REQUEST from the raw xml input */
|
|
|
|
xRequest = XMLRPC_REQUEST_FromXML(rawxml, rawxml_len, &input_opts);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (xRequest) {
|
|
|
|
const char* methodname = XMLRPC_RequestGetMethodName(xRequest);
|
|
|
|
XMLRPC_VALUE xAnswer = NULL;
|
|
|
|
ZVAL_NULL(&data.xmlrpc_method); /* init. very important. spent a frustrating day finding this out. */
|
|
|
|
ZVAL_NULL(&data.return_data);
|
|
|
|
ZVAL_NULL(&data.return_data); /* in case value is never init'd, we don't dtor to think it is a string or something */
|
|
|
|
ZVAL_NULL(&data.xmlrpc_method);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
/* setup some data to pass to the callback function */
|
|
|
|
ZVAL_COPY_VALUE(&data.caller_params, caller_params);
|
|
|
|
data.php_executed = 0;
|
|
|
|
data.server = server;
|
|
|
|
|
|
|
|
/* We could just call the php method directly ourselves at this point, but we do this
|
|
|
|
* with a C callback in case the xmlrpc library ever implements some cool usage stats,
|
|
|
|
* or somesuch.
|
|
|
|
*/
|
|
|
|
xAnswer = XMLRPC_ServerCallMethod(server->server_ptr, xRequest, &data);
|
|
|
|
if (xAnswer && out.b_php_out) {
|
|
|
|
XMLRPC_to_PHP(xAnswer, &data.return_data);
|
|
|
|
} else if (data.php_executed && !out.b_php_out && !xAnswer) {
|
|
|
|
xAnswer = PHP_to_XMLRPC(&data.return_data TSRMLS_CC);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* should we return data as xml? */
|
|
|
|
if (!out.b_php_out) {
|
|
|
|
XMLRPC_REQUEST xResponse = XMLRPC_RequestNew();
|
|
|
|
if (xResponse) {
|
|
|
|
char *outBuf = 0;
|
|
|
|
int buf_len = 0;
|
|
|
|
|
|
|
|
/* automagically determine output serialization type from request type */
|
|
|
|
if (out.b_auto_version) {
|
|
|
|
XMLRPC_REQUEST_OUTPUT_OPTIONS opts = XMLRPC_RequestGetOutputOptions(xRequest);
|
|
|
|
if (opts) {
|
|
|
|
out.xmlrpc_out.version = opts->version;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-12 11:28:06 +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);
|
|
|
|
if (outBuf) {
|
|
|
|
RETVAL_STRINGL(outBuf, buf_len);
|
|
|
|
free(outBuf);
|
|
|
|
}
|
|
|
|
/* cleanup after ourselves. what a sty! */
|
|
|
|
XMLRPC_RequestFree(xResponse, 0);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
} else { /* or as native php types? */
|
|
|
|
ZVAL_COPY(return_value, &data.return_data);
|
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
/* cleanup after ourselves. what a sty! */
|
|
|
|
zval_ptr_dtor(&data.xmlrpc_method);
|
|
|
|
zval_ptr_dtor(&data.return_data);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (xAnswer) {
|
|
|
|
XMLRPC_CleanupValue(xAnswer);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2014-05-12 11:28:06 +00:00
|
|
|
|
|
|
|
XMLRPC_RequestFree(xRequest, 1);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
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-06-28 21:36:39 +00:00
|
|
|
zval *handle, *desc;
|
2003-01-14 21:02:14 +00:00
|
|
|
xmlrpc_server_data* server;
|
2014-08-19 06:16:34 +00:00
|
|
|
XMLRPC_VALUE xDesc;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-28 21:36:39 +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
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server);
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-08-19 06:16:34 +00:00
|
|
|
xDesc = PHP_to_XMLRPC(desc TSRMLS_CC);
|
2014-05-12 11:28:06 +00:00
|
|
|
if (xDesc) {
|
|
|
|
int retval = XMLRPC_ServerAddIntrospectionData(server->server_ptr, xDesc);
|
|
|
|
XMLRPC_CleanupValue(xDesc);
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(retval);
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2014-08-25 17:24:55 +00:00
|
|
|
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-06-28 21:36:39 +00:00
|
|
|
char *arg1;
|
2014-08-27 17:25:28 +00:00
|
|
|
size_t arg1_len;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-28 21:36:39 +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
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (USED_RET()) {
|
2003-01-14 21:02:14 +00:00
|
|
|
STRUCT_XMLRPC_ERROR err = {0};
|
2008-06-28 21:36:39 +00:00
|
|
|
XMLRPC_VALUE xVal = XMLRPC_IntrospectionCreateDescription(arg1, &err);
|
2008-08-24 00:47:22 +00:00
|
|
|
if (xVal) {
|
2014-05-12 11:28:06 +00:00
|
|
|
XMLRPC_to_PHP(xVal, return_value);
|
2003-01-14 21:02:14 +00:00
|
|
|
/* dust, sweep, and mop */
|
|
|
|
XMLRPC_CleanupValue(xVal);
|
|
|
|
} else {
|
|
|
|
/* could not create description */
|
2008-08-24 00:47:22 +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",
|
2008-08-24 00:47:22 +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
|
|
|
|
|
|
|
/************
|
|
|
|
* type data *
|
|
|
|
************/
|
|
|
|
|
|
|
|
#define XMLRPC_TYPE_COUNT 9
|
|
|
|
#define XMLRPC_VECTOR_TYPE_COUNT 4
|
|
|
|
#define TYPE_STR_MAP_SIZE (XMLRPC_TYPE_COUNT + XMLRPC_VECTOR_TYPE_COUNT)
|
|
|
|
|
|
|
|
/* return a string matching a given xmlrpc type */
|
2008-08-24 00:47:22 +00:00
|
|
|
static const char** get_type_str_mapping(void) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +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
|
|
|
}
|
2008-08-24 00:47:22 +00:00
|
|
|
/* }}} */
|
2001-09-06 04:13:30 +00:00
|
|
|
|
|
|
|
/* map an xmlrpc type to a string */
|
2008-08-24 00:47:22 +00:00
|
|
|
const char* xmlrpc_type_as_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
const char** str_mapping = get_type_str_mapping();
|
2002-03-14 12:20:53 +00:00
|
|
|
|
2008-06-20 11:38:52 +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
|
|
|
}
|
2008-08-24 00:47:22 +00:00
|
|
|
/* }}} */
|
2001-09-06 04:13:30 +00:00
|
|
|
|
|
|
|
/* map a string to an xmlrpc type */
|
2008-08-24 00:47:22 +00:00
|
|
|
XMLRPC_VALUE_TYPE xmlrpc_str_as_type(const char* str) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +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
|
|
|
}
|
2008-08-24 00:47:22 +00:00
|
|
|
/* }}} */
|
2001-09-06 04:13:30 +00:00
|
|
|
|
|
|
|
/* map a string to an xmlrpc vector type */
|
2008-08-24 00:47:22 +00:00
|
|
|
XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type(const char* str) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
const char** str_mapping = get_type_str_mapping();
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
for (i = XMLRPC_TYPE_COUNT; i < TYPE_STR_MAP_SIZE; i++) {
|
|
|
|
if (!strcmp(str_mapping[i], str)) {
|
|
|
|
return (XMLRPC_VECTOR_TYPE) (i - XMLRPC_TYPE_COUNT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return xmlrpc_none;
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
2008-08-24 00:47:22 +00:00
|
|
|
/* }}} */
|
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.
|
|
|
|
*/
|
2008-08-24 00:47:22 +00:00
|
|
|
int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE newtype) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
int bSuccess = FAILURE;
|
2014-10-15 07:37:55 +00:00
|
|
|
TSRMLS_FETCH();
|
2008-06-20 11:38:52 +00:00
|
|
|
|
|
|
|
/* we only really care about strings because they can represent
|
2008-08-24 00:47:22 +00:00
|
|
|
* base64 and datetime. all other types have corresponding php types
|
|
|
|
*/
|
2008-06-20 11:38:52 +00:00
|
|
|
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);
|
2014-05-12 11:28:06 +00:00
|
|
|
zval type;
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_STRING(&type, typestr);
|
2008-06-20 11:38:52 +00:00
|
|
|
|
|
|
|
if (newtype == xmlrpc_datetime) {
|
2014-05-12 11:28:06 +00:00
|
|
|
XMLRPC_VALUE v = XMLRPC_CreateValueDateTime_ISO8601(NULL, Z_STRVAL_P(value));
|
2008-06-20 11:38:52 +00:00
|
|
|
if (v) {
|
2009-05-14 12:29:47 +00:00
|
|
|
time_t timestamp = (time_t) php_parse_date((char *)XMLRPC_GetValueDateTime_ISO8601(v), NULL);
|
2009-05-22 12:49:40 +00:00
|
|
|
if (timestamp != -1) {
|
2014-05-12 11:28:06 +00:00
|
|
|
zval ztimestamp;
|
2008-06-20 11:38:52 +00:00
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
ZVAL_LONG(&ztimestamp, timestamp);
|
2008-06-20 11:38:52 +00:00
|
|
|
|
|
|
|
convert_to_object(value);
|
2014-05-12 11:28:06 +00:00
|
|
|
if (zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1, &type)) {
|
|
|
|
bSuccess = zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_VALUE_TS_ATTR, sizeof(OBJECT_VALUE_TS_ATTR) - 1, &ztimestamp) != NULL;
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
zval_ptr_dtor(&type);
|
|
|
|
}
|
|
|
|
XMLRPC_CleanupValue(v);
|
|
|
|
} else {
|
|
|
|
zval_ptr_dtor(&type);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
convert_to_object(value);
|
2014-05-12 11:28:06 +00:00
|
|
|
bSuccess = zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1, &type) != NULL;
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bSuccess;
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
2008-08-24 00:47:22 +00:00
|
|
|
/* }}} */
|
2001-09-06 04:13:30 +00:00
|
|
|
|
|
|
|
/* return xmlrpc type of a php value */
|
2014-05-12 11:28:06 +00:00
|
|
|
XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval* newvalue) /* {{{ */
|
2002-03-14 12:20:53 +00:00
|
|
|
{
|
2008-06-20 11:38:52 +00:00
|
|
|
XMLRPC_VALUE_TYPE type = xmlrpc_none;
|
2014-10-15 07:37:55 +00:00
|
|
|
TSRMLS_FETCH();
|
2008-06-20 11:38:52 +00:00
|
|
|
|
|
|
|
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:47:22 +00:00
|
|
|
/* Right thing to do, but it breaks some legacy code. */
|
2014-05-12 11:28:06 +00:00
|
|
|
case IS_TRUE:
|
|
|
|
case IS_FALSE:
|
2008-06-20 11:38:52 +00:00
|
|
|
type = xmlrpc_boolean;
|
|
|
|
break;
|
2003-03-01 15:40:06 +00:00
|
|
|
#else
|
2008-06-20 11:38:52 +00:00
|
|
|
case IS_BOOL:
|
2003-03-01 15:40:06 +00:00
|
|
|
#endif
|
2014-08-25 17:24:55 +00:00
|
|
|
case IS_LONG:
|
2008-06-20 11:38:52 +00:00
|
|
|
case IS_RESOURCE:
|
|
|
|
type = xmlrpc_int;
|
|
|
|
break;
|
|
|
|
case IS_DOUBLE:
|
|
|
|
type = xmlrpc_double;
|
|
|
|
break;
|
|
|
|
case IS_CONSTANT:
|
|
|
|
type = xmlrpc_string;
|
|
|
|
break;
|
|
|
|
case IS_STRING:
|
|
|
|
type = xmlrpc_string;
|
|
|
|
break;
|
|
|
|
case IS_ARRAY:
|
|
|
|
type = xmlrpc_vector;
|
|
|
|
break;
|
|
|
|
case IS_OBJECT:
|
|
|
|
{
|
2014-05-12 11:28:06 +00:00
|
|
|
zval* attr;
|
2008-06-20 11:38:52 +00:00
|
|
|
type = xmlrpc_vector;
|
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if ((attr = zend_hash_str_find(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1)) != NULL) {
|
|
|
|
if (Z_TYPE_P(attr) == IS_STRING) {
|
|
|
|
type = xmlrpc_str_as_type(Z_STRVAL_P(attr));
|
2008-06-20 11:38:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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) {
|
2014-05-12 11:28:06 +00:00
|
|
|
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) {
|
2014-05-12 11:28:06 +00:00
|
|
|
if ((val = zend_hash_str_find(Z_OBJPROP_P(value), OBJECT_VALUE_ATTR, sizeof(OBJECT_VALUE_ATTR) - 1)) != NULL) {
|
|
|
|
ZVAL_COPY_VALUE(newvalue, val);
|
2002-03-14 12:20:53 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-05-12 11:28:06 +00:00
|
|
|
ZVAL_COPY_VALUE(newvalue, value);
|
2002-03-14 12:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return type;
|
2001-09-06 04:13:30 +00:00
|
|
|
}
|
2008-08-24 00:47:22 +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)
|
|
|
|
{
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *arg;
|
2008-06-28 21:36:39 +00:00
|
|
|
char *type;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t type_len;
|
2003-01-14 21:02:14 +00:00
|
|
|
XMLRPC_VALUE_TYPE vtype;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-06-05 12:04:11 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/s", &arg, &type, &type_len) == FAILURE) {
|
2008-06-28 21:36:39 +00:00
|
|
|
return;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2008-06-28 21:36:39 +00:00
|
|
|
vtype = xmlrpc_str_as_type(type);
|
2003-01-14 21:02:14 +00:00
|
|
|
if (vtype != xmlrpc_none) {
|
2014-05-12 11:28:06 +00:00
|
|
|
if (set_zval_xmlrpc_type(arg, vtype) == SUCCESS) {
|
2003-01-14 21:02:14 +00:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
} else {
|
2008-06-28 21:36:39 +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)
|
|
|
|
{
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *arg;
|
2003-01-14 21:02:14 +00:00
|
|
|
XMLRPC_VALUE_TYPE type;
|
|
|
|
XMLRPC_VECTOR_TYPE vtype = xmlrpc_vector_none;
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
|
2008-06-28 21:36:39 +00:00
|
|
|
return;
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
type = get_zval_xmlrpc_type(arg, 0);
|
2003-01-14 21:02:14 +00:00
|
|
|
if (type == xmlrpc_vector) {
|
2014-05-12 11:28:06 +00:00
|
|
|
vtype = determine_vector_type((Z_TYPE_P(arg) == IS_OBJECT) ? Z_OBJPROP_P(arg) : Z_ARRVAL_P(arg));
|
2003-01-14 21:02:14 +00:00
|
|
|
}
|
2001-09-06 04:13:30 +00:00
|
|
|
|
2014-05-12 11:28:06 +00:00
|
|
|
RETURN_STRING((char*) xmlrpc_type_as_str(type, vtype));
|
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)
|
|
|
|
{
|
2014-05-12 11:28:06 +00:00
|
|
|
zval *arg;
|
2002-07-05 04:43:55 +00:00
|
|
|
|
2008-06-28 21:36:39 +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-06-28 21:36:39 +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.
|
|
|
|
*/
|
2014-05-12 11:28:06 +00:00
|
|
|
if (zend_hash_str_exists(Z_ARRVAL_P(arg), FAULT_CODE, FAULT_CODE_LEN) &&
|
|
|
|
zend_hash_str_exists(Z_ARRVAL_P(arg), FAULT_STRING, FAULT_STRING_LEN)) {
|
2008-06-28 21:36:39 +00:00
|
|
|
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:
|
|
|
|
*/
|
|
|
|
|