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

LTP GCOV extension - code coverage report
Current view: directory - xmlrpc - xmlrpc-epi-php.c
Test: PHP Code Coverage
Date: 2009-11-07 Instrumented lines: 576
Code covered: 72.6 % Executed lines: 418
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 07 Nov 2009 08:17:09 +0000 (15 hours ago)

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