PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/xmlrpc - xmlrpc-epi-php.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 416 529 78.6 %
Date: 2016-09-18 Functions: 29 33 87.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of, or distributed with, libXMLRPC - a C library for
       3             :   xml-encoded function calls.
       4             : 
       5             :   Author: Dan Libby (dan@libby.com)
       6             :   Epinions.com may be contacted at feedback@epinions-inc.com
       7             : */
       8             : 
       9             : /*
      10             :   Copyright 2001 Epinions, Inc.
      11             : 
      12             :   Subject to the following 3 conditions, Epinions, Inc.  permits you, free
      13             :   of charge, to (a) use, copy, distribute, modify, perform and display this
      14             :   software and associated documentation files (the "Software"), and (b)
      15             :   permit others to whom the Software is furnished to do so as well.
      16             : 
      17             :   1) The above copyright notice and this permission notice shall be included
      18             :   without modification in all copies or substantial portions of the
      19             :   Software.
      20             : 
      21             :   2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
      22             :   ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
      23             :   IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
      24             :   PURPOSE OR NONINFRINGEMENT.
      25             : 
      26             :   3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
      27             :   SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
      28             :   OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
      29             :   NEGLIGENCE), EVEN IF EPINIONS, INC.  IS AWARE OF THE POSSIBILITY OF SUCH
      30             :   DAMAGES.
      31             : 
      32             : */
      33             : 
      34             : /* auto-generated portions of this file are also subject to the php license */
      35             : 
      36             : /*
      37             :    +----------------------------------------------------------------------+
      38             :    | PHP Version 7                                                        |
      39             :    +----------------------------------------------------------------------+
      40             :    | Copyright (c) 1997-2016 The PHP Group                                |
      41             :    +----------------------------------------------------------------------+
      42             :    | This source file is subject to version 3.01 of the PHP license,      |
      43             :    | that is bundled with this package in the file LICENSE, and is        |
      44             :    | available through the world-wide-web at the following url:           |
      45             :    | http://www.php.net/license/3_01.txt                                  |
      46             :    | If you did not receive a copy of the PHP license and are unable to   |
      47             :    | obtain it through the world-wide-web, please send a note to          |
      48             :    | license@php.net so we can mail you a copy immediately.               |
      49             :    +----------------------------------------------------------------------+
      50             :    | Author: Dan Libby                                                    |
      51             :    +----------------------------------------------------------------------+
      52             :  */
      53             : 
      54             : /* $Id$ */
      55             : 
      56             : /**********************************************************************
      57             : * BUGS:                                                               *
      58             : *  - when calling a php user function, there appears to be no way to  *
      59             : *    distinguish between a return value of null, and no return value  *
      60             : *    at all.  The xml serialization layer(s) will then return a value *
      61             : *    of null, when the right thing may be no value at all. (SOAP)     *
      62             : **********************************************************************/
      63             : 
      64             : #ifdef HAVE_CONFIG_H
      65             : #include "config.h"
      66             : #endif
      67             : 
      68             : #include "php.h"
      69             : #include "ext/standard/info.h"
      70             : #include "ext/standard/php_string.h"
      71             : #include "ext/date/php_date.h"
      72             : #include "php_ini.h"
      73             : #include "php_xmlrpc.h"
      74             : #include "xmlrpc.h"
      75             : 
      76             : static int le_xmlrpc_server;
      77             : 
      78             : /* {{{ arginfo */
      79             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_encode, 0, 0, 1)
      80             :         ZEND_ARG_INFO(0, value)
      81             : ZEND_END_ARG_INFO()
      82             : 
      83             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_decode, 0, 0, 1)
      84             :         ZEND_ARG_INFO(0, value)
      85             :         ZEND_ARG_INFO(0, encoding)
      86             : ZEND_END_ARG_INFO()
      87             : 
      88             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_decode_request, 0, 0, 2)
      89             :         ZEND_ARG_INFO(0, xml)
      90             :         ZEND_ARG_INFO(1, method)
      91             :         ZEND_ARG_INFO(0, encoding)
      92             : ZEND_END_ARG_INFO()
      93             : 
      94             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_encode_request, 0, 0, 2)
      95             :         ZEND_ARG_INFO(0, method)
      96             :         ZEND_ARG_INFO(0, params)
      97             :         ZEND_ARG_INFO(0, output_options)
      98             : ZEND_END_ARG_INFO()
      99             : 
     100             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_set_type, 0, 0, 2)
     101             :         ZEND_ARG_INFO(1, value)
     102             :         ZEND_ARG_INFO(0, type)
     103             : ZEND_END_ARG_INFO()
     104             : 
     105             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_is_fault, 0, 0, 1)
     106             :         ZEND_ARG_INFO(0, arg)
     107             : ZEND_END_ARG_INFO()
     108             : 
     109             : ZEND_BEGIN_ARG_INFO(arginfo_xmlrpc_server_create, 0)
     110             : ZEND_END_ARG_INFO()
     111             : 
     112             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_destroy, 0, 0, 1)
     113             :         ZEND_ARG_INFO(0, server)
     114             : ZEND_END_ARG_INFO()
     115             : 
     116             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_register_method, 0, 0, 3)
     117             :         ZEND_ARG_INFO(0, server)
     118             :         ZEND_ARG_INFO(0, method_name)
     119             :         ZEND_ARG_INFO(0, function)
     120             : ZEND_END_ARG_INFO()
     121             : 
     122             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_call_method, 0, 0, 3)
     123             :         ZEND_ARG_INFO(0, server)
     124             :         ZEND_ARG_INFO(0, xml)
     125             :         ZEND_ARG_INFO(0, user_data)
     126             :         ZEND_ARG_INFO(0, output_options)
     127             : ZEND_END_ARG_INFO()
     128             : 
     129             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_parse_method_descriptions, 0, 0, 1)
     130             :         ZEND_ARG_INFO(0, xml)
     131             : ZEND_END_ARG_INFO()
     132             : 
     133             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_add_introspection_data, 0, 0, 2)
     134             :         ZEND_ARG_INFO(0, server)
     135             :         ZEND_ARG_INFO(0, desc)
     136             : ZEND_END_ARG_INFO()
     137             : 
     138             : ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_register_introspection_callback, 0, 0, 2)
     139             :         ZEND_ARG_INFO(0, server)
     140             :         ZEND_ARG_INFO(0, function)
     141             : ZEND_END_ARG_INFO()
     142             : /* }}} */
     143             : 
     144             : const zend_function_entry xmlrpc_functions[] = {
     145             :         PHP_FE(xmlrpc_encode,                                                                   arginfo_xmlrpc_encode)
     146             :         PHP_FE(xmlrpc_decode,                                                                   arginfo_xmlrpc_decode)
     147             :         PHP_FE(xmlrpc_decode_request,                                                   arginfo_xmlrpc_decode_request)
     148             :         PHP_FE(xmlrpc_encode_request,                                                   arginfo_xmlrpc_encode_request)
     149             :         PHP_FE(xmlrpc_get_type,                                                                 arginfo_xmlrpc_encode)
     150             :         PHP_FE(xmlrpc_set_type,                                                                 arginfo_xmlrpc_set_type)
     151             :         PHP_FE(xmlrpc_is_fault,                                                                 arginfo_xmlrpc_is_fault)
     152             :         PHP_FE(xmlrpc_server_create,                                                    arginfo_xmlrpc_server_create)
     153             :         PHP_FE(xmlrpc_server_destroy,                                                   arginfo_xmlrpc_server_destroy)
     154             :         PHP_FE(xmlrpc_server_register_method,                                   arginfo_xmlrpc_server_register_method)
     155             :         PHP_FE(xmlrpc_server_call_method,                                               arginfo_xmlrpc_server_call_method)
     156             :         PHP_FE(xmlrpc_parse_method_descriptions,                                arginfo_xmlrpc_parse_method_descriptions)
     157             :         PHP_FE(xmlrpc_server_add_introspection_data,                    arginfo_xmlrpc_server_add_introspection_data)
     158             :         PHP_FE(xmlrpc_server_register_introspection_callback,   arginfo_xmlrpc_server_register_introspection_callback)
     159             :         PHP_FE_END
     160             : };
     161             : 
     162             : zend_module_entry xmlrpc_module_entry = {
     163             :         STANDARD_MODULE_HEADER,
     164             :         "xmlrpc",
     165             :         xmlrpc_functions,
     166             :         PHP_MINIT(xmlrpc),
     167             :         NULL,
     168             :         NULL,
     169             :         NULL,
     170             :         PHP_MINFO(xmlrpc),
     171             :         PHP_XMLRPC_VERSION,
     172             :         STANDARD_MODULE_PROPERTIES
     173             : };
     174             : 
     175             : #ifdef COMPILE_DL_XMLRPC
     176             : ZEND_GET_MODULE(xmlrpc)
     177             : #endif
     178             : 
     179             : /*******************************
     180             : * local structures and defines *
     181             : *******************************/
     182             : 
     183             : /* per server data */
     184             : typedef struct _xmlrpc_server_data {
     185             :         zval method_map;
     186             :         zval introspection_map;
     187             :         XMLRPC_SERVER server_ptr;
     188             : } xmlrpc_server_data;
     189             : 
     190             : 
     191             : /* how to format output */
     192             : typedef struct _php_output_options {
     193             :         int b_php_out;
     194             :         int b_auto_version;
     195             :         STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS xmlrpc_out;
     196             : } php_output_options;
     197             : 
     198             : /* data passed to C callback */
     199             : typedef struct _xmlrpc_callback_data {
     200             :         zval xmlrpc_method;
     201             :         zval php_function;
     202             :         zval caller_params;
     203             :         zval return_data;
     204             :         xmlrpc_server_data* server;
     205             :         char php_executed;
     206             : } xmlrpc_callback_data;
     207             : 
     208             : /* output options */
     209             : #define OUTPUT_TYPE_KEY       "output_type"
     210             : #define OUTPUT_TYPE_KEY_LEN   (sizeof(OUTPUT_TYPE_KEY) - 1)
     211             : #define OUTPUT_TYPE_VALUE_PHP "php"
     212             : #define OUTPUT_TYPE_VALUE_XML "xml"
     213             : 
     214             : #define VERBOSITY_KEY                  "verbosity"
     215             : #define VERBOSITY_KEY_LEN              (sizeof(VERBOSITY_KEY) - 1)
     216             : #define VERBOSITY_VALUE_NO_WHITE_SPACE "no_white_space"
     217             : #define VERBOSITY_VALUE_NEWLINES_ONLY  "newlines_only"
     218             : #define VERBOSITY_VALUE_PRETTY         "pretty"
     219             : 
     220             : #define ESCAPING_KEY             "escaping"
     221             : #define ESCAPING_KEY_LEN         (sizeof(ESCAPING_KEY) - 1)
     222             : #define ESCAPING_VALUE_CDATA     "cdata"
     223             : #define ESCAPING_VALUE_NON_ASCII "non-ascii"
     224             : #define ESCAPING_VALUE_NON_PRINT "non-print"
     225             : #define ESCAPING_VALUE_MARKUP    "markup"
     226             : 
     227             : #define VERSION_KEY          "version"
     228             : #define VERSION_KEY_LEN      (sizeof(VERSION_KEY) - 1)
     229             : #define VERSION_VALUE_SIMPLE "simple"
     230             : #define VERSION_VALUE_XMLRPC "xmlrpc"
     231             : #define VERSION_VALUE_SOAP11 "soap 1.1"
     232             : #define VERSION_VALUE_AUTO   "auto"
     233             : 
     234             : #define ENCODING_KEY     "encoding"
     235             : #define ENCODING_KEY_LEN (sizeof(ENCODING_KEY) - 1)
     236             : #define ENCODING_DEFAULT "iso-8859-1"
     237             : 
     238             : /* value types */
     239             : #define OBJECT_TYPE_ATTR  "xmlrpc_type"
     240             : #define OBJECT_VALUE_ATTR "scalar"
     241             : #define OBJECT_VALUE_TS_ATTR "timestamp"
     242             : 
     243             : /* faults */
     244             : #define FAULT_CODE       "faultCode"
     245             : #define FAULT_CODE_LEN   (sizeof(FAULT_CODE) - 1)
     246             : #define FAULT_STRING     "faultString"
     247             : #define FAULT_STRING_LEN (sizeof(FAULT_STRING) - 1)
     248             : 
     249             : /***********************
     250             : * forward declarations *
     251             : ***********************/
     252             : XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval* newvalue);
     253             : static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data);
     254             : int sset_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE type);
     255             : void decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out, zval *retval);
     256             : const char* xmlrpc_type_as_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype);
     257             : XMLRPC_VALUE_TYPE xmlrpc_str_as_type(const char* str);
     258             : XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type(const char* str);
     259             : int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE type);
     260             : 
     261             : /*********************
     262             : * startup / shutdown *
     263             : *********************/
     264             : 
     265          10 : static void destroy_server_data(xmlrpc_server_data *server)
     266             : {
     267          10 :         if (server) {
     268          10 :                 XMLRPC_ServerDestroy(server->server_ptr);
     269             : 
     270          10 :                 zval_ptr_dtor(&server->method_map);
     271          10 :                 zval_ptr_dtor(&server->introspection_map);
     272             : 
     273          10 :                 efree(server);
     274             :         }
     275          10 : }
     276             : 
     277             : /* called when server is being destructed. either when xmlrpc_server_destroy
     278             :  * is called, or when request ends.  */
     279          10 : static void xmlrpc_server_destructor(zend_resource *rsrc)
     280             : {
     281          10 :         if (rsrc && rsrc->ptr) {
     282          10 :                 rsrc->gc.refcount++;
     283          10 :                 destroy_server_data((xmlrpc_server_data*) rsrc->ptr);
     284          10 :                 rsrc->gc.refcount--;
     285             :         }
     286          10 : }
     287             : 
     288             : /* module init */
     289       23922 : PHP_MINIT_FUNCTION(xmlrpc)
     290             : {
     291       23922 :         le_xmlrpc_server = zend_register_list_destructors_ex(xmlrpc_server_destructor, NULL, "xmlrpc server", module_number);
     292             : 
     293       23922 :         return SUCCESS;
     294             : }
     295             : 
     296             : /* display info in phpinfo() */
     297         150 : PHP_MINFO_FUNCTION(xmlrpc)
     298             : {
     299         150 :         php_info_print_table_start();
     300         150 :         php_info_print_table_row(2, "core library version", XMLRPC_GetVersionString());
     301         150 :         php_info_print_table_row(2, "php extension version", PHP_XMLRPC_VERSION);
     302         150 :         php_info_print_table_row(2, "author", "Dan Libby");
     303         150 :         php_info_print_table_row(2, "homepage", "http://xmlrpc-epi.sourceforge.net");
     304         150 :         php_info_print_table_row(2, "open sourced by", "Epinions.com");
     305         150 :         php_info_print_table_end();
     306         150 : }
     307             : 
     308             : /*******************
     309             : * random utilities *
     310             : *******************/
     311             : 
     312             : /* Utility functions for adding data types to arrays, with or without key (assoc, non-assoc).
     313             :  * Could easily be further generalized to work with objects.
     314             :  */
     315             : #if 0
     316             : static int add_long(zval* list, char* id, int num) {
     317             :         if(id) return add_assoc_long(list, id, num);
     318             :         else   return add_next_index_long(list, num);
     319             : }
     320             : 
     321             : static int add_double(zval* list, char* id, double num) {
     322             :         if(id) return add_assoc_double(list, id, num);
     323             :         else   return add_next_index_double(list, num);
     324             : }
     325             : 
     326             : static int add_string(zval* list, char* id, char* string) {
     327             :         if(id) return add_assoc_string(list, id, string);
     328             :         else   return add_next_index_string(list, string);
     329             : }
     330             : 
     331             : static int add_stringl(zval* list, char* id, char* string, uint length) {
     332             :         if(id) return add_assoc_stringl(list, id, string, length);
     333             :         else   return add_next_index_stringl(list, string, length);
     334             : }
     335             : 
     336             : #endif
     337             : 
     338          42 : static void add_zval(zval* list, const char* id, zval* val)
     339             : {
     340          42 :         if (list && val) {
     341          42 :                 if (id) {
     342          23 :                         int id_len = strlen(id);
     343          57 :                         if (!(id_len > 1 && id[0] == '0') && is_numeric_string((char *)id, id_len, NULL, NULL, 0) == IS_LONG) {
     344          11 :                                 long index = strtol(id, NULL, 0);
     345          11 :                                 zend_hash_index_update(Z_ARRVAL_P(list), index, val);
     346             :                         } else {
     347          12 :                                 zend_hash_str_update(Z_ARRVAL_P(list), (char*)id, strlen(id), val);
     348             :                         }
     349             :                 } else {
     350          19 :                         zend_hash_next_index_insert(Z_ARRVAL_P(list), val);
     351             :                 }
     352             :         }
     353          42 : }
     354             : 
     355             : /*************************
     356             : * input / output options *
     357             : *************************/
     358             : 
     359             : /* parse an array (user input) into output options suitable for use by xmlrpc engine
     360             :  * and determine whether to return data as xml or php vars */
     361          23 : static void set_output_options(php_output_options* options, zval* output_opts)
     362             : {
     363          23 :         if (options) {
     364             :                 /* defaults */
     365          23 :                 options->b_php_out = 0;
     366          23 :                 options->b_auto_version = 1;
     367          23 :                 options->xmlrpc_out.version = xmlrpc_version_1_0;
     368          23 :                 options->xmlrpc_out.xml_elem_opts.encoding = ENCODING_DEFAULT;
     369          23 :                 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_pretty;
     370          23 :                 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping | xml_elem_non_ascii_escaping | xml_elem_non_print_escaping;
     371             : 
     372          26 :                 if (output_opts && Z_TYPE_P(output_opts) == IS_ARRAY) {
     373             :                         zval* val;
     374             : 
     375             :                         /* type of output (xml/php) */
     376           3 :                         if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), OUTPUT_TYPE_KEY, OUTPUT_TYPE_KEY_LEN)) != NULL) {
     377           2 :                                 if (Z_TYPE_P(val) == IS_STRING) {
     378           2 :                                         if (!strcmp(Z_STRVAL_P(val), OUTPUT_TYPE_VALUE_PHP)) {
     379           0 :                                                 options->b_php_out = 1;
     380           2 :                                         } else if (!strcmp(Z_STRVAL_P(val), OUTPUT_TYPE_VALUE_XML)) {
     381           2 :                                                 options->b_php_out = 0;
     382             :                                         }
     383             :                                 }
     384             :                         }
     385             : 
     386             :                         /* verbosity of generated xml */
     387           3 :                         if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), VERBOSITY_KEY, VERBOSITY_KEY_LEN)) != NULL) {
     388           0 :                                 if (Z_TYPE_P(val) == IS_STRING) {
     389           0 :                                         if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_NO_WHITE_SPACE)) {
     390           0 :                                                 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_no_white_space;
     391           0 :                                         } else if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_NEWLINES_ONLY)) {
     392           0 :                                                 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_newlines_only;
     393           0 :                                         } else if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_PRETTY)) {
     394           0 :                                                 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_pretty;
     395             :                                         }
     396             :                                 }
     397             :                         }
     398             : 
     399             :                         /* version of xml to output */
     400           3 :                         if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), VERSION_KEY, VERSION_KEY_LEN)) != NULL) {
     401           2 :                                 if (Z_TYPE_P(val) == IS_STRING) {
     402           2 :                                         options->b_auto_version = 0;
     403           2 :                                         if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_XMLRPC)) {
     404           2 :                                                 options->xmlrpc_out.version = xmlrpc_version_1_0;
     405           0 :                                         } else if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_SIMPLE)) {
     406           0 :                                                 options->xmlrpc_out.version = xmlrpc_version_simple;
     407           0 :                                         } else if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_SOAP11)) {
     408           0 :                                                 options->xmlrpc_out.version = xmlrpc_version_soap_1_1;
     409             :                                         } else { /* if(!strcmp(Z_STRVAL_P(val), VERSION_VALUE_AUTO)) { */
     410           0 :                                                 options->b_auto_version = 1;
     411             :                                         }
     412             :                                 }
     413             : 
     414             :                         }
     415             : 
     416             :                         /* encoding code set */
     417           3 :                         if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN)) != NULL) {
     418           1 :                                 if (Z_TYPE_P(val) == IS_STRING) {
     419           1 :                                         options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_P(val));
     420             :                                 }
     421             :                         }
     422             : 
     423             :                         /* escaping options */
     424           3 :                         if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN)) != NULL) {
     425             :                                 /* multiple values allowed.  check if array */
     426           1 :                                 if (Z_TYPE_P(val) == IS_ARRAY) {
     427             :                                         zval* iter_val;
     428             : 
     429           0 :                                         options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping;
     430             : 
     431           0 :                                         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(val), iter_val) {
     432           0 :                                                 if (Z_TYPE_P(iter_val) == IS_STRING && Z_STRVAL_P(iter_val)) {
     433           0 :                                                         if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_CDATA)) {
     434           0 :                                                                 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping;
     435           0 :                                                         } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_ASCII)) {
     436           0 :                                                                 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping;
     437           0 :                                                         } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_PRINT)) {
     438           0 :                                                                 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping;
     439           0 :                                                         } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_MARKUP)) {
     440           0 :                                                                 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping;
     441             :                                                         }
     442             :                                                 }
     443             :                                         } ZEND_HASH_FOREACH_END();
     444             :                                         /* else, check for single value */
     445           1 :                                 } else if (Z_TYPE_P(val) == IS_STRING) {
     446           1 :                                         if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_CDATA)) {
     447           0 :                                                 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping;
     448           1 :                                         } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_ASCII)) {
     449           0 :                                                 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping;
     450           1 :                                         } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_PRINT)) {
     451           0 :                                                 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping;
     452           1 :                                         } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_MARKUP)) {
     453           1 :                                                 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping;
     454             :                                         }
     455             :                                 }
     456             :                         }
     457             :                 }
     458             :         }
     459          23 : }
     460             : 
     461             : 
     462             : /******************
     463             : * encode / decode *
     464             : ******************/
     465             : 
     466             : /* php arrays have no distinction between array and struct types.
     467             :  * they even allow mixed.  Thus, we determine the type by iterating
     468             :  * through the entire array and figuring out each element.
     469             :  * room for some optimation here if we stop after a specific # of elements.
     470             :  */
     471          22 : static XMLRPC_VECTOR_TYPE determine_vector_type (HashTable *ht)
     472             : {
     473          22 :         int bArray = 0, bStruct = 0, bMixed = 0;
     474          22 :         zend_ulong num_index, last_num = 0;
     475             :         zend_string* my_key;
     476             : 
     477         103 :         ZEND_HASH_FOREACH_KEY(ht, num_index, my_key) {
     478          40 :                 if (my_key == NULL) {
     479          28 :                         if (bStruct) {
     480           1 :                                 bMixed = 1;
     481           1 :                                 break;
     482          27 :                         } else if (last_num > 0 && last_num != num_index-1) {
     483           2 :                                 bStruct = 1;
     484           2 :                                 break;
     485             :                         }
     486          25 :                         bArray = 1;
     487          25 :                         last_num = num_index;
     488             :                 } else {
     489          12 :                         if (bArray) {
     490           2 :                                 bMixed = 1;
     491           2 :                                 break;
     492             :                         }
     493          10 :                         bStruct = 1;
     494             :                 }
     495             :         } ZEND_HASH_FOREACH_END();
     496          22 :         return bMixed ? xmlrpc_vector_mixed : (bStruct ? xmlrpc_vector_struct : xmlrpc_vector_array);
     497             : }
     498             : 
     499             : /* recursively convert php values into xmlrpc values */
     500          74 : static XMLRPC_VALUE PHP_to_XMLRPC_worker (const char* key, zval* in_val, int depth)
     501             : {
     502          74 :         XMLRPC_VALUE xReturn = NULL;
     503             : 
     504          74 :         if (in_val) {
     505             :                 zval val;
     506             :                 XMLRPC_VALUE_TYPE type;
     507             : 
     508          74 :                 ZVAL_UNDEF(&val);
     509          74 :                 type = get_zval_xmlrpc_type(in_val, &val);
     510             : 
     511          74 :                 if (!Z_ISUNDEF(val)) {
     512          74 :                         switch (type) {
     513             :                                 case xmlrpc_base64:
     514           1 :                                         if (Z_TYPE(val) == IS_NULL) {
     515           0 :                                                 xReturn = XMLRPC_CreateValueEmpty();
     516           0 :                                                 XMLRPC_SetValueID(xReturn, key, 0);
     517             :                                         } else {
     518           1 :                                                 if (Z_TYPE(val) != IS_STRING) {
     519             :                                                         zval newvalue;
     520           1 :                                                         ZVAL_DUP(&newvalue, &val);
     521           1 :                                                         convert_to_string(&newvalue);
     522           1 :                                                         xReturn = XMLRPC_CreateValueBase64(key, Z_STRVAL(newvalue), Z_STRLEN(newvalue));
     523             :                                                         zval_dtor(&newvalue);
     524             :                                                 } else {
     525           0 :                                                         xReturn = XMLRPC_CreateValueBase64(key, Z_STRVAL(val), Z_STRLEN(val));
     526             :                                                 }
     527             :                                         }
     528           1 :                                         break;
     529             :                                 case xmlrpc_datetime:
     530           4 :                                         convert_to_string(&val);
     531           4 :                                         xReturn = XMLRPC_CreateValueDateTime_ISO8601(key, Z_STRVAL(val));
     532           4 :                                         break;
     533             :                                 case xmlrpc_boolean:
     534           0 :                                         convert_to_boolean(&val);
     535           0 :                                         xReturn = XMLRPC_CreateValueBoolean(key, Z_TYPE(val) == IS_TRUE);
     536           0 :                                         break;
     537             :                                 case xmlrpc_int:
     538          36 :                                         ZVAL_LONG(&val, zval_get_long(&val));
     539          18 :                                         xReturn = XMLRPC_CreateValueInt(key, Z_LVAL(val));
     540          18 :                                         break;
     541             :                                 case xmlrpc_double:
     542           3 :                                         convert_to_double(&val);
     543           3 :                                         xReturn = XMLRPC_CreateValueDouble(key, Z_DVAL(val));
     544           3 :                                         break;
     545             :                                 case xmlrpc_string:
     546          31 :                                         convert_to_string(&val);
     547          31 :                                         xReturn = XMLRPC_CreateValueString(key, Z_STRVAL(val), Z_STRLEN(val));
     548          31 :                                         break;
     549             :                                 case xmlrpc_vector:
     550             :                                         {
     551             :                                                 zend_ulong num_index;
     552             :                                                 zval* pIter;
     553             :                                                 zend_string* my_key;
     554          17 :                                                 HashTable *ht = NULL;
     555             :                                                 zval val_arr;
     556             :                                                 XMLRPC_VECTOR_TYPE vtype;
     557             : 
     558          18 :                                                 ht = HASH_OF(&val);
     559          17 :                                                 if (ht && ht->u.v.nApplyCount > 1) {
     560           0 :                                                         zend_throw_error(NULL, "XML-RPC doesn't support circular references");
     561           0 :                                                         return NULL;
     562             :                                                 }
     563             : 
     564          17 :                                                 ZVAL_COPY(&val_arr, &val);
     565          17 :                                                 convert_to_array(&val_arr);
     566             : 
     567          17 :                                                 vtype = determine_vector_type(Z_ARRVAL(val_arr));
     568          17 :                                                 xReturn = XMLRPC_CreateVector(key, vtype);
     569             : 
     570          95 :                                                 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(val_arr), num_index, my_key, pIter) {
     571          35 :                                                         ZVAL_DEREF(pIter);
     572          69 :                                                         ht = HASH_OF(pIter);
     573          35 :                                                         if (ht) {
     574           4 :                                                                 ht->u.v.nApplyCount++;
     575             :                                                         }
     576          35 :                                                         if (my_key == NULL) {
     577          26 :                                                                 char *num_str = NULL;
     578             : 
     579          26 :                                                                 if (vtype != xmlrpc_vector_array) {
     580          12 :                                                                         spprintf(&num_str, 0, ZEND_LONG_FMT, num_index);
     581             :                                                                 }
     582             : 
     583          26 :                                                                 XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(num_str, pIter, depth++));
     584          26 :                                                                 if (num_str) {
     585          12 :                                                                         efree(num_str);
     586             :                                                                 }
     587             :                                                         } else {
     588           9 :                                                                 XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(ZSTR_VAL(my_key), pIter, depth++));
     589             :                                                         }
     590          35 :                                                         if (ht) {
     591           4 :                                                                 ht->u.v.nApplyCount--;
     592             :                                                         }
     593             :                                                 } ZEND_HASH_FOREACH_END();
     594          17 :                                                 zval_ptr_dtor(&val_arr);
     595             :                                         }
     596             :                                         break;
     597             :                                 default:
     598             :                                         break;
     599             :                         }
     600             :                 }
     601             :         }
     602          74 :         return xReturn;
     603             : }
     604             : 
     605          39 : static XMLRPC_VALUE PHP_to_XMLRPC(zval* root_val)
     606             : {
     607          39 :         return PHP_to_XMLRPC_worker(NULL, root_val, 0);
     608             : }
     609             : 
     610             : /* recursively convert xmlrpc values into php values */
     611          56 : static void XMLRPC_to_PHP(XMLRPC_VALUE el, zval *elem)
     612             : {
     613             :         const char* pStr;
     614             : 
     615          56 :         if (el) {
     616          55 :                 XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(el);
     617             : 
     618          55 :                 switch (type) {
     619             :                         case xmlrpc_empty:
     620           1 :                                 ZVAL_NULL(elem);
     621           1 :                                 break;
     622             :                         case xmlrpc_string:
     623          20 :                                 pStr = XMLRPC_GetValueString(el);
     624          20 :                                 if (pStr) {
     625          40 :                                         ZVAL_STRINGL(elem, pStr, XMLRPC_GetValueStringLen(el));
     626             :                                 }
     627          20 :                                 break;
     628             :                         case xmlrpc_int:
     629           8 :                                 ZVAL_LONG(elem, XMLRPC_GetValueInt(el));
     630           8 :                                 break;
     631             :                         case xmlrpc_boolean:
     632           0 :                                 ZVAL_BOOL(elem, XMLRPC_GetValueBoolean(el));
     633           0 :                                 break;
     634             :                         case xmlrpc_double:
     635           0 :                                 ZVAL_DOUBLE(elem, XMLRPC_GetValueDouble(el));
     636           0 :                                 break;
     637             :                         case xmlrpc_datetime:
     638          14 :                                 ZVAL_STRINGL(elem, XMLRPC_GetValueDateTime_ISO8601(el), XMLRPC_GetValueStringLen(el));
     639           7 :                                 break;
     640             :                         case xmlrpc_base64:
     641           0 :                                 pStr = XMLRPC_GetValueBase64(el);
     642           0 :                                 if (pStr) {
     643           0 :                                         ZVAL_STRINGL(elem, pStr, XMLRPC_GetValueStringLen(el));
     644             :                                 }
     645           0 :                                 break;
     646             :                         case xmlrpc_vector:
     647          19 :                                 array_init(elem);
     648             :                                 {
     649          19 :                                         XMLRPC_VALUE xIter = XMLRPC_VectorRewind(el);
     650             : 
     651          65 :                                         while( xIter ) {
     652             :                                                 zval val;
     653          27 :                                                 ZVAL_UNDEF(&val);
     654          27 :                                                 XMLRPC_to_PHP(xIter, &val);
     655          27 :                                                 if (!Z_ISUNDEF(val)) {
     656          27 :                                                         add_zval(elem, XMLRPC_GetValueID(xIter), &val);
     657             :                                                 }
     658          27 :                                                 xIter = XMLRPC_VectorNext(el);
     659             :                                         }
     660             :                                 }
     661             :                                 break;
     662             :                         default:
     663             :                                 break;
     664             :                 }
     665          55 :                 set_zval_xmlrpc_type(elem, type);
     666             :         }
     667          56 : }
     668             : 
     669             : /* {{{ proto string xmlrpc_encode_request(string method, mixed params [, array output_options])
     670             :    Generates XML for a method request */
     671          16 : PHP_FUNCTION(xmlrpc_encode_request)
     672             : {
     673          16 :         XMLRPC_REQUEST xRequest = NULL;
     674             :         char *outBuf;
     675          16 :         zval *vals, *out_opts = NULL;
     676          16 :         char *method = NULL;
     677             :         size_t method_len;
     678             :         php_output_options out;
     679             : 
     680          16 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!z|a", &method, &method_len, &vals, &out_opts) == FAILURE) {
     681           2 :                 return;
     682             :         }
     683             : 
     684          14 :         set_output_options(&out, out_opts ? out_opts : 0);
     685             : 
     686          14 :         if (USED_RET()) {
     687          14 :                 xRequest = XMLRPC_RequestNew();
     688             : 
     689          14 :                 if (xRequest) {
     690          14 :                         XMLRPC_RequestSetOutputOptions(xRequest, &out.xmlrpc_out);
     691          14 :                         if (method == NULL) {
     692           0 :                                 XMLRPC_RequestSetRequestType(xRequest, xmlrpc_request_response);
     693             :                         } else {
     694          14 :                                 XMLRPC_RequestSetMethodName(xRequest, method);
     695          14 :                                 XMLRPC_RequestSetRequestType(xRequest, xmlrpc_request_call);
     696             :                         }
     697          28 :                         if (Z_TYPE_P(vals) != IS_NULL) {
     698          14 :                                 XMLRPC_RequestSetData(xRequest, PHP_to_XMLRPC(vals));
     699             :                         }
     700             : 
     701          14 :                         outBuf = XMLRPC_REQUEST_ToXML(xRequest, 0);
     702          14 :                         if (outBuf) {
     703          28 :                                 RETVAL_STRING(outBuf);
     704          14 :                                 free(outBuf);
     705             :                         }
     706          14 :                         XMLRPC_RequestFree(xRequest, 1);
     707             :                 }
     708             :         }
     709             : 
     710          14 :         if (strcmp(out.xmlrpc_out.xml_elem_opts.encoding, ENCODING_DEFAULT) != 0) {
     711           1 :                 efree((char *)out.xmlrpc_out.xml_elem_opts.encoding);
     712             :         }
     713             : }
     714             : /* }}} */
     715             : 
     716             : /* {{{ proto string xmlrpc_encode(mixed value)
     717             :    Generates XML for a PHP value */
     718          17 : PHP_FUNCTION(xmlrpc_encode)
     719             : {
     720          17 :         XMLRPC_VALUE xOut = NULL;
     721             :         zval *arg1;
     722             :         char *outBuf;
     723             : 
     724          17 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &arg1) == FAILURE) {
     725           0 :                 return;
     726             :         }
     727             : 
     728          17 :         if (USED_RET()) {
     729             :                 /* convert native php type to xmlrpc type */
     730          17 :                 xOut = PHP_to_XMLRPC(arg1);
     731             : 
     732             :                 /* generate raw xml from xmlrpc data */
     733          17 :                 outBuf = XMLRPC_VALUE_ToXML(xOut, 0);
     734             : 
     735          17 :                 if (xOut) {
     736          17 :                         if (outBuf) {
     737          34 :                                 RETVAL_STRING(outBuf);
     738          17 :                                 free(outBuf);
     739             :                         }
     740             :                         /* cleanup */
     741          17 :                         XMLRPC_CleanupValue(xOut);
     742             :                 }
     743             :         }
     744             : }
     745             : /* }}} */
     746             : 
     747          20 : void decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out, zval *retval) /* {{{ */
     748             : {
     749             :         XMLRPC_REQUEST response;
     750          20 :         STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS opts = {{0}};
     751             :         const char *method_name;
     752          20 :         opts.xml_elem_opts.encoding = encoding_in ? utf8_get_encoding_id_from_string(encoding_in) : ENCODING_DEFAULT;
     753             : 
     754             :         /* generate XMLRPC_REQUEST from raw xml */
     755          20 :         response = XMLRPC_REQUEST_FromXML(xml_in, xml_in_len, &opts);
     756          20 :         if (response) {
     757          20 :                 ZVAL_NULL(retval);
     758             :                 /* convert xmlrpc data to native php types */
     759          20 :                 XMLRPC_to_PHP(XMLRPC_RequestGetData(response), retval);
     760             : 
     761          20 :                 if (XMLRPC_RequestGetRequestType(response) == xmlrpc_request_call) {
     762           5 :                         if (method_name_out) {
     763           5 :                                 method_name = XMLRPC_RequestGetMethodName(response);
     764           5 :                                 if (method_name) {
     765           4 :                                         zval_ptr_dtor(method_name_out);
     766           8 :                                         ZVAL_STRING(method_name_out, method_name);
     767             :                                 } else {
     768           1 :                                         zval_ptr_dtor(retval);
     769           1 :                                         ZVAL_NULL(retval);
     770             :                                 }
     771             :                         }
     772             :                 }
     773             : 
     774             :                 /* dust, sweep, and mop */
     775          20 :                 XMLRPC_RequestFree(response, 1);
     776             :         }
     777          20 : }
     778             : /* }}} */
     779             : 
     780             : /* {{{ proto array xmlrpc_decode_request(string xml, string& method [, string encoding])
     781             :    Decodes XML into native PHP types */
     782           6 : PHP_FUNCTION(xmlrpc_decode_request)
     783             : {
     784           6 :         char *xml, *encoding = NULL;
     785             :         zval *method;
     786           6 :         size_t xml_len, encoding_len = 0;
     787             : 
     788           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/|s", &xml, &xml_len, &method, &encoding, &encoding_len) == FAILURE) {
     789           0 :                 return;
     790             :         }
     791             : 
     792           6 :         if (USED_RET()) {
     793           6 :                 decode_request_worker(xml, xml_len, encoding_len ? encoding : NULL, method, return_value);
     794             :         }
     795             : }
     796             : /* }}} */
     797             : 
     798             : /* {{{ proto array xmlrpc_decode(string xml [, string encoding])
     799             :    Decodes XML into native PHP types */
     800          14 : PHP_FUNCTION(xmlrpc_decode)
     801             : {
     802          14 :         char *arg1, *arg2 = NULL;
     803          14 :         size_t arg1_len, arg2_len = 0;
     804             : 
     805          14 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &arg1, &arg1_len, &arg2, &arg2_len) == FAILURE) {
     806           0 :                 return;
     807             :         }
     808             : 
     809          14 :         if (USED_RET()) {
     810          14 :                 decode_request_worker(arg1, arg1_len, arg2_len ? arg2 : NULL, NULL, return_value);
     811             :         }
     812             : }
     813             : /* }}} */
     814             : 
     815             : /*************************
     816             : * server related methods *
     817             : *************************/
     818             : 
     819             : /* {{{ proto resource xmlrpc_server_create(void)
     820             :    Creates an xmlrpc server */
     821          10 : PHP_FUNCTION(xmlrpc_server_create)
     822             : {
     823          10 :         if (zend_parse_parameters_none() == FAILURE) {
     824           0 :                 return;
     825             :         }
     826             : 
     827          10 :         if (USED_RET()) {
     828          10 :                 xmlrpc_server_data *server = emalloc(sizeof(xmlrpc_server_data));
     829             : 
     830             :                 /* allocate server data.  free'd in destroy_server_data() */
     831          10 :                 array_init(&server->method_map);
     832          10 :                 array_init(&server->introspection_map);
     833          10 :                 server->server_ptr = XMLRPC_ServerCreate();
     834             : 
     835          10 :                 XMLRPC_ServerRegisterIntrospectionCallback(server->server_ptr, php_xmlrpc_introspection_callback);
     836             : 
     837             :                 /* store for later use */
     838          10 :                 RETURN_RES(zend_register_resource(server, le_xmlrpc_server));
     839             :         }
     840             : }
     841             : /* }}} */
     842             : 
     843             : /* {{{ proto int xmlrpc_server_destroy(resource server)
     844             :    Destroys server resources */
     845           0 : PHP_FUNCTION(xmlrpc_server_destroy)
     846             : {
     847             :         zval *arg1;
     848           0 :         int bSuccess = FAILURE;
     849             :         xmlrpc_server_data *server;
     850             : 
     851           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) {
     852           0 :                 return;
     853             :         }
     854             : 
     855           0 :         if ((server = (xmlrpc_server_data *)zend_fetch_resource(Z_RES_P(arg1), "xmlrpc server", le_xmlrpc_server)) == NULL) {
     856           0 :                 RETURN_FALSE;
     857             :         }
     858             : 
     859           0 :         bSuccess = zend_list_close(Z_RES_P(arg1));
     860             :         /* called by hashtable destructor
     861             :          * destroy_server_data(server);
     862             :          */
     863           0 :         RETURN_BOOL(bSuccess == SUCCESS);
     864             : }
     865             : /* }}} */
     866             : 
     867             : /* called by xmlrpc C engine as method handler for all registered methods.
     868             :  * it then calls the corresponding PHP function to handle the method.
     869             :  */
     870           8 : static XMLRPC_VALUE php_xmlrpc_callback(XMLRPC_SERVER server, XMLRPC_REQUEST xRequest, void* data) /* {{{ */
     871             : {
     872           8 :         xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data;
     873             :         zval* php_function;
     874             :         zval xmlrpc_params;
     875             :         zval callback_params[3];
     876             : 
     877           8 :         zval_ptr_dtor(&pData->xmlrpc_method);
     878           8 :         zval_ptr_dtor(&pData->return_data);
     879             : 
     880             :         /* convert xmlrpc to native php types */
     881          16 :         ZVAL_STRING(&pData->xmlrpc_method, XMLRPC_RequestGetMethodName(xRequest));
     882           8 :         XMLRPC_to_PHP(XMLRPC_RequestGetData(xRequest), &xmlrpc_params);
     883             : 
     884             :         /* check if the called method has been previous registered */
     885           8 :         if ((php_function = zend_hash_find(Z_ARRVAL(pData->server->method_map), Z_STR(pData->xmlrpc_method))) != NULL) {
     886           8 :                 ZVAL_COPY_VALUE(&pData->php_function, php_function);
     887             :         }
     888             : 
     889             :         /* setup data hoojum */
     890           8 :         ZVAL_COPY_VALUE(&callback_params[0], &pData->xmlrpc_method);
     891           8 :         ZVAL_COPY_VALUE(&callback_params[1], &xmlrpc_params);
     892           8 :         ZVAL_COPY_VALUE(&callback_params[2], &pData->caller_params);
     893             : 
     894             :         /* Use same C function for all methods */
     895             : 
     896             :         /* php func prototype: function user_func($method_name, $xmlrpc_params, $user_params) */
     897           8 :         call_user_function(CG(function_table), NULL, &pData->php_function, &pData->return_data, 3, callback_params);
     898             : 
     899           8 :         pData->php_executed = 1;
     900             : 
     901           8 :         zval_ptr_dtor(&xmlrpc_params);
     902             : 
     903           8 :         return PHP_to_XMLRPC(&pData->return_data);
     904             : }
     905             : /* }}} */
     906             : 
     907             : /* called by the C server when it first receives an introspection request.  We pass this on to
     908             :  * our PHP listeners, if any
     909             :  */
     910           2 : static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data) /* {{{ */
     911             : {
     912             :         zval retval, *php_function;
     913             :         zval callback_params[1];
     914             :         zend_string *php_function_name;
     915           2 :         xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data;
     916             : 
     917             :         /* setup data hoojum */
     918           2 :         ZVAL_COPY_VALUE(&callback_params[0], &pData->caller_params);
     919             : 
     920          12 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL(pData->server->introspection_map), php_function) {
     921           5 :                 if (zend_is_callable(php_function, 0, &php_function_name)) {
     922             :                         /* php func prototype: function string user_func($user_params) */
     923           1 :                         if (call_user_function(CG(function_table), NULL, php_function, &retval, 1, callback_params) == SUCCESS) {
     924             :                                 XMLRPC_VALUE xData;
     925           1 :                                 STRUCT_XMLRPC_ERROR err = {0};
     926             : 
     927             :                                 /* return value should be a string */
     928           1 :                                 convert_to_string(&retval);
     929             : 
     930           1 :                                 xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err);
     931             : 
     932           1 :                                 if (xData) {
     933           0 :                                         if (!XMLRPC_ServerAddIntrospectionData(server, xData)) {
     934           0 :                                                 php_error_docref(NULL, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", ZSTR_VAL(php_function_name));
     935             :                                         }
     936           0 :                                         XMLRPC_CleanupValue(xData);
     937             :                                 } else {
     938             :                                         /* could not create description */
     939           1 :                                         if (err.xml_elem_error.parser_code) {
     940           1 :                                                 php_error_docref(NULL, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %s()",
     941           1 :                                                                 err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, ZSTR_VAL(php_function_name));
     942             :                                         } else {
     943           0 :                                                 php_error_docref(NULL, E_WARNING, "Unable to add introspection data returned from %s()", ZSTR_VAL(php_function_name));
     944             :                                         }
     945             :                                 }
     946           1 :                                 zval_ptr_dtor(&retval);
     947             :                         } else {
     948             :                                 /* user func failed */
     949           0 :                                 php_error_docref(NULL, E_WARNING, "Error calling user introspection callback: %s()", ZSTR_VAL(php_function_name));
     950             :                         }
     951             :                 } else {
     952           4 :                         php_error_docref(NULL, E_WARNING, "Invalid callback '%s' passed", ZSTR_VAL(php_function_name));
     953             :                 }
     954           5 :                 zend_string_release(php_function_name);
     955             :         } ZEND_HASH_FOREACH_END();
     956             : 
     957             :         /* so we don't call the same callbacks ever again */
     958           2 :         zend_hash_clean(Z_ARRVAL(pData->server->introspection_map));
     959           2 : }
     960             : /* }}} */
     961             : 
     962             : /* {{{ proto bool xmlrpc_server_register_method(resource server, string method_name, string function)
     963             :    Register a PHP function to handle method matching method_name */
     964           9 : PHP_FUNCTION(xmlrpc_server_register_method)
     965             : {
     966             :         char *method_key;
     967             :         size_t method_key_len;
     968             :         zval *handle, *method_name;
     969             :         xmlrpc_server_data* server;
     970             : 
     971           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz", &handle, &method_key, &method_key_len, &method_name) == FAILURE) {
     972           0 :                 return;
     973             :         }
     974             : 
     975           9 :         if ((server = (xmlrpc_server_data *)zend_fetch_resource(Z_RES_P(handle), "xmlrpc server", le_xmlrpc_server)) == NULL) {
     976           0 :                 RETURN_FALSE;
     977             :         }
     978             : 
     979             :         /* register with C engine. every method just calls our standard callback,
     980             :          * and it then dispatches to php as necessary
     981             :          */
     982           9 :         if (XMLRPC_ServerRegisterMethod(server->server_ptr, method_key, php_xmlrpc_callback)) {
     983             :                 /* save for later use */
     984             : 
     985           9 :                 if (Z_REFCOUNTED_P(method_name)) {
     986           2 :                         Z_ADDREF_P(method_name);
     987             :                 }
     988             :                 /* register our php method */
     989           9 :                 add_zval(&server->method_map, method_key, method_name);
     990             : 
     991           9 :                 RETURN_TRUE;
     992             :         }
     993             : }
     994             : /* }}} */
     995             : 
     996             : /* {{{ proto bool xmlrpc_server_register_introspection_callback(resource server, string function)
     997             :    Register a PHP function to generate documentation */
     998           6 : PHP_FUNCTION(xmlrpc_server_register_introspection_callback)
     999             : {
    1000             :         zval *method_name, *handle;
    1001             :         xmlrpc_server_data* server;
    1002             : 
    1003           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &handle, &method_name) == FAILURE) {
    1004           0 :                 return;
    1005             :         }
    1006             : 
    1007           6 :         if ((server = (xmlrpc_server_data *)zend_fetch_resource(Z_RES_P(handle), "xmlrpc server", le_xmlrpc_server)) == NULL) {
    1008           0 :                 RETURN_FALSE;
    1009             :         }
    1010             : 
    1011           6 :         if (Z_REFCOUNTED_P(method_name)) {
    1012           3 :                 Z_ADDREF_P(method_name);
    1013             :         }
    1014             :         /* register our php method */
    1015           6 :         add_zval(&server->introspection_map, NULL, method_name);
    1016             : 
    1017           6 :         RETURN_TRUE;
    1018             : }
    1019             : /* }}} */
    1020             : 
    1021             : /* this function is itchin for a re-write */
    1022             : 
    1023             : /* {{{ proto mixed xmlrpc_server_call_method(resource server, string xml, mixed user_data [, array output_options])
    1024             :    Parses XML requests and call methods */
    1025           9 : PHP_FUNCTION(xmlrpc_server_call_method)
    1026             : {
    1027             :         XMLRPC_REQUEST xRequest;
    1028             :         xmlrpc_callback_data data;
    1029             :         STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS input_opts;
    1030             :         xmlrpc_server_data* server;
    1031           9 :         zval *caller_params, *handle, *output_opts = NULL;
    1032             :         char *rawxml;
    1033             :         size_t rawxml_len;
    1034             :         php_output_options out;
    1035           9 :         int argc = ZEND_NUM_ARGS();
    1036             : 
    1037           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz|a", &handle, &rawxml, &rawxml_len, &caller_params, &output_opts) != SUCCESS) {
    1038           0 :                 return;
    1039             :         }
    1040             :         /* user output options */
    1041           9 :         if (argc == 3) {
    1042           7 :                 set_output_options(&out, NULL);
    1043             :         } else {
    1044           2 :                 set_output_options(&out, output_opts);
    1045             :         }
    1046             : 
    1047           9 :         if ((server = (xmlrpc_server_data *)zend_fetch_resource(Z_RES_P(handle), "xmlrpc server", le_xmlrpc_server)) == NULL) {
    1048           0 :                 RETURN_FALSE;
    1049             :         }
    1050             : 
    1051             :         /* HACK: use output encoding for now */
    1052           9 :         input_opts.xml_elem_opts.encoding = utf8_get_encoding_id_from_string(out.xmlrpc_out.xml_elem_opts.encoding);
    1053             : 
    1054             :         /* generate an XMLRPC_REQUEST from the raw xml input */
    1055           9 :         xRequest = XMLRPC_REQUEST_FromXML(rawxml, rawxml_len, &input_opts);
    1056             : 
    1057           9 :         if (xRequest) {
    1058           9 :                 const char* methodname = XMLRPC_RequestGetMethodName(xRequest);
    1059           9 :                 XMLRPC_VALUE xAnswer = NULL;
    1060           9 :                 ZVAL_NULL(&data.xmlrpc_method); /* init. very important.  spent a frustrating day finding this out. */
    1061           9 :                 ZVAL_NULL(&data.return_data);
    1062           9 :                 ZVAL_NULL(&data.return_data);  /* in case value is never init'd, we don't dtor to think it is a string or something */
    1063           9 :                 ZVAL_NULL(&data.xmlrpc_method);
    1064             : 
    1065             :                 /* setup some data to pass to the callback function */
    1066           9 :                 ZVAL_COPY_VALUE(&data.caller_params, caller_params);
    1067           9 :                 data.php_executed = 0;
    1068           9 :                 data.server = server;
    1069             : 
    1070             :                 /* We could just call the php method directly ourselves at this point, but we do this
    1071             :                  * with a C callback in case the xmlrpc library ever implements some cool usage stats,
    1072             :                  * or somesuch.
    1073             :                  */
    1074           9 :                 xAnswer = XMLRPC_ServerCallMethod(server->server_ptr, xRequest, &data);
    1075           9 :                 if (xAnswer && out.b_php_out) {
    1076           0 :                         XMLRPC_to_PHP(xAnswer, &data.return_data);
    1077           9 :                 } else if (data.php_executed && !out.b_php_out && !xAnswer) {
    1078           0 :                         xAnswer = PHP_to_XMLRPC(&data.return_data);
    1079             :                 }
    1080             : 
    1081             :                 /* should we return data as xml? */
    1082           9 :                 if (!out.b_php_out) {
    1083           9 :                         XMLRPC_REQUEST xResponse = XMLRPC_RequestNew();
    1084           9 :                         if (xResponse) {
    1085           9 :                                 char *outBuf = 0;
    1086           9 :                                 int buf_len = 0;
    1087             : 
    1088             :                                 /* automagically determine output serialization type from request type */
    1089           9 :                                 if (out.b_auto_version) {
    1090           7 :                                         XMLRPC_REQUEST_OUTPUT_OPTIONS opts = XMLRPC_RequestGetOutputOptions(xRequest);
    1091           7 :                                         if (opts) {
    1092           7 :                                                 out.xmlrpc_out.version = opts->version;
    1093             :                                         }
    1094             :                                 }
    1095             :                                 /* set some required request hoojum */
    1096           9 :                                 XMLRPC_RequestSetOutputOptions(xResponse, &out.xmlrpc_out);
    1097           9 :                                 XMLRPC_RequestSetRequestType(xResponse, xmlrpc_request_response);
    1098           9 :                                 XMLRPC_RequestSetData(xResponse, xAnswer);
    1099           9 :                                 XMLRPC_RequestSetMethodName(xResponse, methodname);
    1100             : 
    1101             :                                 /* generate xml */
    1102           9 :                                 outBuf = XMLRPC_REQUEST_ToXML(xResponse, &buf_len);
    1103           9 :                                 if (outBuf) {
    1104          18 :                                         RETVAL_STRINGL(outBuf, buf_len);
    1105           9 :                                         free(outBuf);
    1106             :                                 }
    1107             :                                 /* cleanup after ourselves.  what a sty! */
    1108           9 :                                 XMLRPC_RequestFree(xResponse, 0);
    1109             :                         }
    1110             :                 } else { /* or as native php types? */
    1111           0 :                         ZVAL_COPY(return_value, &data.return_data);
    1112             :                 }
    1113             : 
    1114             :                 /* cleanup after ourselves.  what a sty! */
    1115           9 :                 zval_ptr_dtor(&data.xmlrpc_method);
    1116           9 :                 zval_ptr_dtor(&data.return_data);
    1117             : 
    1118           9 :                 if (xAnswer) {
    1119           9 :                         XMLRPC_CleanupValue(xAnswer);
    1120             :                 }
    1121             : 
    1122           9 :                 XMLRPC_RequestFree(xRequest, 1);
    1123             :         }
    1124             : }
    1125             : /* }}} */
    1126             : 
    1127             : /* {{{ proto int xmlrpc_server_add_introspection_data(resource server, array desc)
    1128             :    Adds introspection documentation  */
    1129           0 : PHP_FUNCTION(xmlrpc_server_add_introspection_data)
    1130             : {
    1131             :         zval *handle, *desc;
    1132             :         xmlrpc_server_data* server;
    1133             :         XMLRPC_VALUE xDesc;
    1134             : 
    1135           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &handle, &desc) == FAILURE) {
    1136           0 :                 return;
    1137             :         }
    1138             : 
    1139           0 :         if ((server = (xmlrpc_server_data *)zend_fetch_resource(Z_RES_P(handle), "xmlrpc server", le_xmlrpc_server)) == NULL) {
    1140           0 :                 RETURN_FALSE;
    1141             :         }
    1142             : 
    1143           0 :         xDesc = PHP_to_XMLRPC(desc);
    1144           0 :         if (xDesc) {
    1145           0 :                 int retval = XMLRPC_ServerAddIntrospectionData(server->server_ptr, xDesc);
    1146           0 :                 XMLRPC_CleanupValue(xDesc);
    1147           0 :                 RETURN_LONG(retval);
    1148             :         }
    1149           0 :         RETURN_LONG(0);
    1150             : }
    1151             : /* }}} */
    1152             : 
    1153             : /* {{{ proto array xmlrpc_parse_method_descriptions(string xml)
    1154             :    Decodes XML into a list of method descriptions */
    1155           1 : PHP_FUNCTION(xmlrpc_parse_method_descriptions)
    1156             : {
    1157             :         char *arg1;
    1158             :         size_t arg1_len;
    1159             : 
    1160           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg1, &arg1_len) == FAILURE) {
    1161           0 :                 return;
    1162             :         }
    1163             : 
    1164           1 :         if (USED_RET()) {
    1165           1 :                 STRUCT_XMLRPC_ERROR err = {0};
    1166           1 :                 XMLRPC_VALUE xVal = XMLRPC_IntrospectionCreateDescription(arg1, &err);
    1167           1 :                 if (xVal) {
    1168           1 :                         XMLRPC_to_PHP(xVal, return_value);
    1169             :                         /* dust, sweep, and mop */
    1170           1 :                         XMLRPC_CleanupValue(xVal);
    1171             :                 } else {
    1172             :                         /* could not create description */
    1173           0 :                         if (err.xml_elem_error.parser_code) {
    1174           0 :                                 php_error_docref(NULL, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to create introspection data",
    1175             :                                                 err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error);
    1176             :                         } else {
    1177           0 :                                 php_error_docref(NULL, E_WARNING, "Invalid xml structure. Unable to create introspection data");
    1178             :                         }
    1179             : 
    1180           0 :                         php_error_docref(NULL, E_WARNING, "xml parse error. no method description created");
    1181             :                 }
    1182             :         }
    1183             : }
    1184             : /* }}} */
    1185             : 
    1186             : /************
    1187             : * type data *
    1188             : ************/
    1189             : 
    1190             : #define XMLRPC_TYPE_COUNT 9
    1191             : #define XMLRPC_VECTOR_TYPE_COUNT 4
    1192             : #define TYPE_STR_MAP_SIZE (XMLRPC_TYPE_COUNT + XMLRPC_VECTOR_TYPE_COUNT)
    1193             : 
    1194             : /* return a string matching a given xmlrpc type */
    1195          29 : static const char** get_type_str_mapping(void) /* {{{ */
    1196             : {
    1197             :         static const char* str_mapping[TYPE_STR_MAP_SIZE];
    1198             :         static int first = 1;
    1199          29 :         if (first) {
    1200             :                 /* warning. do not add/delete without changing size define */
    1201           9 :                 str_mapping[xmlrpc_none]     = "none";
    1202           9 :                 str_mapping[xmlrpc_empty]    = "empty";
    1203           9 :                 str_mapping[xmlrpc_base64]   = "base64";
    1204           9 :                 str_mapping[xmlrpc_boolean]  = "boolean";
    1205           9 :                 str_mapping[xmlrpc_datetime] = "datetime";
    1206           9 :                 str_mapping[xmlrpc_double]   = "double";
    1207           9 :                 str_mapping[xmlrpc_int]      = "int";
    1208           9 :                 str_mapping[xmlrpc_string]   = "string";
    1209           9 :                 str_mapping[xmlrpc_vector]   = "vector";
    1210           9 :                 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_none]   = "none";
    1211           9 :                 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_array]  = "array";
    1212           9 :                 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_mixed]  = "mixed";
    1213           9 :                 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_struct] = "struct";
    1214           9 :                 first = 0;
    1215             :         }
    1216          29 :         return (const char**)str_mapping;
    1217             : }
    1218             : /* }}} */
    1219             : 
    1220             : /* map an xmlrpc type to a string */
    1221          18 : const char* xmlrpc_type_as_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) /* {{{ */
    1222             : {
    1223          18 :         const char** str_mapping = get_type_str_mapping();
    1224             : 
    1225          18 :         if (vtype == xmlrpc_vector_none) {
    1226          13 :                 return str_mapping[type];
    1227             :         } else {
    1228           5 :                 return str_mapping[XMLRPC_TYPE_COUNT + vtype];
    1229             :         }
    1230             : }
    1231             : /* }}} */
    1232             : 
    1233             : /* map a string to an xmlrpc type */
    1234          11 : XMLRPC_VALUE_TYPE xmlrpc_str_as_type(const char* str) /* {{{ */
    1235             : {
    1236          11 :         const char** str_mapping = get_type_str_mapping();
    1237             :         int i;
    1238             : 
    1239          11 :         if (str) {
    1240          53 :                 for (i = 0; i < XMLRPC_TYPE_COUNT; i++) {
    1241          53 :                         if (!strcmp(str_mapping[i], str)) {
    1242          11 :                                 return (XMLRPC_VALUE_TYPE) i;
    1243             :                         }
    1244             :                 }
    1245             :         }
    1246           0 :         return xmlrpc_none;
    1247             : }
    1248             : /* }}} */
    1249             : 
    1250             : /* map a string to an xmlrpc vector type */
    1251           0 : XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type(const char* str) /* {{{ */
    1252             : {
    1253           0 :         const char** str_mapping = get_type_str_mapping();
    1254             :         int i;
    1255             : 
    1256           0 :         if (str) {
    1257           0 :                 for (i = XMLRPC_TYPE_COUNT; i < TYPE_STR_MAP_SIZE; i++) {
    1258           0 :                         if (!strcmp(str_mapping[i], str)) {
    1259           0 :                                 return (XMLRPC_VECTOR_TYPE) (i - XMLRPC_TYPE_COUNT);
    1260             :                         }
    1261             :                 }
    1262             :         }
    1263           0 :         return xmlrpc_none;
    1264             : }
    1265             : /* }}} */
    1266             : 
    1267             : /* set a given value to a particular type.
    1268             :  * note: this only works on strings, and only for date and base64,
    1269             :  *       which do not have native php types. black magic lies herein.
    1270             :  */
    1271          61 : int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE newtype) /* {{{ */
    1272             : {
    1273          61 :         int bSuccess = FAILURE;
    1274             : 
    1275             :         /* we only really care about strings because they can represent
    1276             :          * base64 and datetime.  all other types have corresponding php types
    1277             :          */
    1278          61 :         if (Z_TYPE_P(value) == IS_STRING) {
    1279          33 :                 if (newtype == xmlrpc_base64 || newtype == xmlrpc_datetime) {
    1280          13 :                         const char* typestr = xmlrpc_type_as_str(newtype, xmlrpc_vector_none);
    1281             :                         zval type;
    1282             : 
    1283          26 :                         ZVAL_STRING(&type, typestr);
    1284             : 
    1285          13 :                         if (newtype == xmlrpc_datetime) {
    1286          13 :                                 XMLRPC_VALUE v = XMLRPC_CreateValueDateTime_ISO8601(NULL, Z_STRVAL_P(value));
    1287          13 :                                 if (v) {
    1288          13 :                                         time_t timestamp = (time_t) php_parse_date((char *)XMLRPC_GetValueDateTime_ISO8601(v), NULL);
    1289          13 :                                         if (timestamp != -1) {
    1290             :                                                 zval ztimestamp;
    1291             : 
    1292          12 :                                                 ZVAL_LONG(&ztimestamp, timestamp);
    1293             : 
    1294          12 :                                                 convert_to_object(value);
    1295          12 :                                                 if (zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1, &type)) {
    1296          12 :                                                         bSuccess = (zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_VALUE_TS_ATTR, sizeof(OBJECT_VALUE_TS_ATTR) - 1, &ztimestamp) != NULL)? SUCCESS : FAILURE;
    1297             :                                                 }
    1298             :                                         } else {
    1299           1 :                                                 zval_ptr_dtor(&type);
    1300             :                                         }
    1301          13 :                                         XMLRPC_CleanupValue(v);
    1302             :                                 } else {
    1303           0 :                                         zval_ptr_dtor(&type);
    1304             :                                 }
    1305             :                         } else {
    1306           0 :                                 convert_to_object(value);
    1307           0 :                                 bSuccess = (zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1, &type) != NULL)? SUCCESS : FAILURE;
    1308             :                         }
    1309             :                 }
    1310             :         }
    1311             : 
    1312          61 :         return bSuccess;
    1313             : }
    1314             : /* }}} */
    1315             : 
    1316             : /* return xmlrpc type of a php value */
    1317          79 : XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval* newvalue) /* {{{ */
    1318             : {
    1319          79 :         XMLRPC_VALUE_TYPE type = xmlrpc_none;
    1320             : 
    1321          79 :         if (value) {
    1322          79 :                 switch (Z_TYPE_P(value)) {
    1323             :                         case IS_NULL:
    1324           0 :                                 type = xmlrpc_base64;
    1325           0 :                                 break;
    1326             : #ifndef BOOL_AS_LONG
    1327             : 
    1328             :                         /* Right thing to do, but it breaks some legacy code. */
    1329             :                         case IS_TRUE:
    1330             :                         case IS_FALSE:
    1331           0 :                                 type = xmlrpc_boolean;
    1332           0 :                                 break;
    1333             : #else
    1334             :                         case IS_BOOL:
    1335             : #endif
    1336             :                         case IS_LONG:
    1337             :                         case IS_RESOURCE:
    1338          18 :                                 type = xmlrpc_int;
    1339          18 :                                 break;
    1340             :                         case IS_DOUBLE:
    1341           3 :                                 type = xmlrpc_double;
    1342           3 :                                 break;
    1343             :                         case IS_CONSTANT:
    1344           0 :                                 type = xmlrpc_string;
    1345           0 :                                 break;
    1346             :                         case IS_STRING:
    1347          31 :                                 type = xmlrpc_string;
    1348          31 :                                 break;
    1349             :                         case IS_ARRAY:
    1350          20 :                                 type = xmlrpc_vector;
    1351          20 :                                 break;
    1352             :                         case IS_OBJECT:
    1353             :                                 {
    1354             :                                         zval* attr;
    1355           7 :                                         type = xmlrpc_vector;
    1356             : 
    1357           7 :                                         if ((attr = zend_hash_str_find(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1)) != NULL) {
    1358           5 :                                                 if (Z_TYPE_P(attr) == IS_STRING) {
    1359           5 :                                                         type = xmlrpc_str_as_type(Z_STRVAL_P(attr));
    1360             :                                                 }
    1361             :                                         }
    1362             :                                         break;
    1363             :                                 }
    1364             :                 }
    1365             : 
    1366             :                 /* if requested, return an unmolested (magic removed) copy of the value */
    1367          79 :                 if (newvalue) {
    1368             :                         zval* val;
    1369             : 
    1370          80 :                         if ((type == xmlrpc_base64 && Z_TYPE_P(value) == IS_OBJECT) || type == xmlrpc_datetime) {
    1371           5 :                                 if ((val = zend_hash_str_find(Z_OBJPROP_P(value), OBJECT_VALUE_ATTR, sizeof(OBJECT_VALUE_ATTR) - 1)) != NULL) {
    1372           5 :                                         ZVAL_COPY_VALUE(newvalue, val);
    1373             :                                 }
    1374             :                         } else {
    1375          69 :                                 ZVAL_COPY_VALUE(newvalue, value);
    1376             :                         }
    1377             :                 }
    1378             :         }
    1379             : 
    1380          79 :         return type;
    1381             : }
    1382             : /* }}} */
    1383             : 
    1384             : /* {{{ proto bool xmlrpc_set_type(string value, string type)
    1385             :    Sets xmlrpc type, base64 or datetime, for a PHP string value */
    1386           6 : PHP_FUNCTION(xmlrpc_set_type)
    1387             : {
    1388             :         zval *arg;
    1389             :         char *type;
    1390             :         size_t type_len;
    1391             :         XMLRPC_VALUE_TYPE vtype;
    1392             : 
    1393           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/s", &arg, &type, &type_len) == FAILURE) {
    1394           0 :                 return;
    1395             :         }
    1396             : 
    1397           6 :         vtype = xmlrpc_str_as_type(type);
    1398           6 :         if (vtype != xmlrpc_none) {
    1399           6 :                 if (set_zval_xmlrpc_type(arg, vtype) == SUCCESS) {
    1400           5 :                         RETURN_TRUE;
    1401             :                 }
    1402             :         } else {
    1403           0 :                 zend_error(E_WARNING,"invalid type '%s' passed to xmlrpc_set_type()", type);
    1404             :         }
    1405           1 :         RETURN_FALSE;
    1406             : }
    1407             : /* }}} */
    1408             : 
    1409             : /* {{{ proto string xmlrpc_get_type(mixed value)
    1410             :    Gets xmlrpc type for a PHP value. Especially useful for base64 and datetime strings */
    1411           5 : PHP_FUNCTION(xmlrpc_get_type)
    1412             : {
    1413             :         zval *arg;
    1414             :         XMLRPC_VALUE_TYPE type;
    1415           5 :         XMLRPC_VECTOR_TYPE vtype = xmlrpc_vector_none;
    1416             : 
    1417           5 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &arg) == FAILURE) {
    1418           0 :                 return;
    1419             :         }
    1420             : 
    1421           5 :         type = get_zval_xmlrpc_type(arg, 0);
    1422           5 :         if (type == xmlrpc_vector) {
    1423          10 :                 vtype = determine_vector_type((Z_TYPE_P(arg) == IS_OBJECT) ? Z_OBJPROP_P(arg) : Z_ARRVAL_P(arg));
    1424             :         }
    1425             : 
    1426          10 :         RETURN_STRING((char*) xmlrpc_type_as_str(type, vtype));
    1427             : }
    1428             : /* }}} */
    1429             : 
    1430             : /* {{{ proto bool xmlrpc_is_fault(array arg)
    1431             :    Determines if an array value represents an XMLRPC fault. */
    1432           0 : PHP_FUNCTION(xmlrpc_is_fault)
    1433             : {
    1434             :         zval *arg;
    1435             : 
    1436           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &arg) == FAILURE) {
    1437           0 :                 return;
    1438             :         }
    1439             : 
    1440             :         /* The "correct" way to do this would be to call the xmlrpc
    1441             :          * library XMLRPC_ValueIsFault() func.  However, doing that
    1442             :          * would require us to create an xmlrpc value from the php
    1443             :          * array, which is rather expensive, especially if it was
    1444             :          * a big array.  Thus, we resort to this not so clever hackery.
    1445             :          */
    1446           0 :         if (zend_hash_str_exists(Z_ARRVAL_P(arg), FAULT_CODE, FAULT_CODE_LEN) &&
    1447           0 :                         zend_hash_str_exists(Z_ARRVAL_P(arg), FAULT_STRING, FAULT_STRING_LEN)) {
    1448           0 :                 RETURN_TRUE;
    1449             :         }
    1450             : 
    1451           0 :         RETURN_FALSE;
    1452             : }
    1453             : /* }}} */
    1454             : 
    1455             : /*
    1456             :  * Local variables:
    1457             :  * tab-width: 4
    1458             :  * c-basic-offset: 4
    1459             :  * End:
    1460             :  */
    1461             : 

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:19 +0000 (7 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.