diff --git a/ext/xmlrpc/libxmlrpc/xmlrpc.c b/ext/xmlrpc/libxmlrpc/xmlrpc.c index ce70c2afd90..0f77ae24519 100644 --- a/ext/xmlrpc/libxmlrpc/xmlrpc.c +++ b/ext/xmlrpc/libxmlrpc/xmlrpc.c @@ -2394,7 +2394,7 @@ void XMLRPC_ServerDestroy(XMLRPC_SERVER server) { my_free(sm); sm = Q_Next(&server->methodlist); } - if(server->xIntrospection) { + if (server->xIntrospection) { XMLRPC_CleanupValue(server->xIntrospection); } diff --git a/ext/xmlrpc/xmlrpc-epi-php.c b/ext/xmlrpc/xmlrpc-epi-php.c index 3fb2ba6bb66..7a9a1f17034 100644 --- a/ext/xmlrpc/xmlrpc-epi-php.c +++ b/ext/xmlrpc/xmlrpc-epi-php.c @@ -184,8 +184,8 @@ ZEND_GET_MODULE(xmlrpc) /* per server data */ typedef struct _xmlrpc_server_data { - zval* method_map; - zval* introspection_map; + zval method_map; + zval introspection_map; XMLRPC_SERVER server_ptr; } xmlrpc_server_data; @@ -199,10 +199,10 @@ typedef struct _php_output_options { /* data passed to C callback */ typedef struct _xmlrpc_callback_data { - zval* xmlrpc_method; - zval* php_function; - zval* caller_params; - zval* return_data; + zval xmlrpc_method; + zval php_function; + zval caller_params; + zval return_data; xmlrpc_server_data* server; char php_executed; } xmlrpc_callback_data; @@ -251,10 +251,10 @@ typedef struct _xmlrpc_callback_data { /*********************** * forward declarations * ***********************/ -XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue); +XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval* newvalue); static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data); int sset_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE type); -zval* decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out); +void decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out, zval *retval); const char* xmlrpc_type_as_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype); XMLRPC_VALUE_TYPE xmlrpc_str_as_type(const char* str); XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type(const char* str); @@ -269,11 +269,8 @@ static void destroy_server_data(xmlrpc_server_data *server TSRMLS_DC) if (server) { XMLRPC_ServerDestroy(server->server_ptr); - zval_dtor(server->method_map); - FREE_ZVAL(server->method_map); - - zval_dtor(server->introspection_map); - FREE_ZVAL(server->introspection_map); + zval_ptr_dtor(&server->method_map); + zval_ptr_dtor(&server->introspection_map); efree(server); } @@ -281,7 +278,7 @@ static void destroy_server_data(xmlrpc_server_data *server TSRMLS_DC) /* called when server is being destructed. either when xmlrpc_server_destroy * is called, or when request ends. */ -static void xmlrpc_server_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) +static void xmlrpc_server_destructor(zend_resource *rsrc TSRMLS_DC) { if (rsrc && rsrc->ptr) { destroy_server_data((xmlrpc_server_data*) rsrc->ptr TSRMLS_CC); @@ -338,28 +335,23 @@ static int add_stringl(zval* list, char* id, char* string, uint length) { #endif -static int add_zval(zval* list, const char* id, zval** val) +static void add_zval(zval* list, const char* id, zval* val) { if (list && val) { if (id) { int id_len = strlen(id); if (!(id_len > 1 && id[0] == '0') && is_numeric_string((char *)id, id_len, NULL, NULL, 0) == IS_LONG) { long index = strtol(id, NULL, 0); - return zend_hash_index_update(Z_ARRVAL_P(list), index, (void *) val, sizeof(zval **), NULL); + zend_hash_index_update(Z_ARRVAL_P(list), index, val); } else { - return zend_hash_update(Z_ARRVAL_P(list), (char*) id, strlen(id) + 1, (void *) val, sizeof(zval **), NULL); + zend_hash_str_update(Z_ARRVAL_P(list), (char*)id, strlen(id), val); } } else { - return zend_hash_next_index_insert(Z_ARRVAL_P(list), (void *) val, sizeof(zval **), NULL); + zend_hash_next_index_insert(Z_ARRVAL_P(list), val); } } - /* what is the correct return on error? */ - return 0; } -#define my_zend_hash_get_current_key(ht, my_key, num_index) zend_hash_get_current_key(ht, my_key, num_index, 0) - - /************************* * input / output options * *************************/ @@ -369,7 +361,6 @@ static int add_zval(zval* list, const char* id, zval** val) static void set_output_options(php_output_options* options, zval* output_opts) { if (options) { - /* defaults */ options->b_php_out = 0; options->b_auto_version = 1; @@ -379,92 +370,86 @@ static void set_output_options(php_output_options* options, zval* output_opts) options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping | xml_elem_non_ascii_escaping | xml_elem_non_print_escaping; if (output_opts && Z_TYPE_P(output_opts) == IS_ARRAY) { - zval** val; + zval* val; /* type of output (xml/php) */ - if (zend_hash_find(Z_ARRVAL_P(output_opts), OUTPUT_TYPE_KEY, OUTPUT_TYPE_KEY_LEN + 1, (void**) &val) == SUCCESS) { - if (Z_TYPE_PP(val) == IS_STRING) { - if (!strcmp(Z_STRVAL_PP(val), OUTPUT_TYPE_VALUE_PHP)) { + if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), OUTPUT_TYPE_KEY, OUTPUT_TYPE_KEY_LEN)) != NULL) { + if (Z_TYPE_P(val) == IS_STRING) { + if (!strcmp(Z_STRVAL_P(val), OUTPUT_TYPE_VALUE_PHP)) { options->b_php_out = 1; - } else if (!strcmp(Z_STRVAL_PP(val), OUTPUT_TYPE_VALUE_XML)) { + } else if (!strcmp(Z_STRVAL_P(val), OUTPUT_TYPE_VALUE_XML)) { options->b_php_out = 0; } } } /* verbosity of generated xml */ - if (zend_hash_find(Z_ARRVAL_P(output_opts), VERBOSITY_KEY, VERBOSITY_KEY_LEN + 1, (void**) &val) == SUCCESS) { - if (Z_TYPE_PP(val) == IS_STRING) { - if (!strcmp(Z_STRVAL_PP(val), VERBOSITY_VALUE_NO_WHITE_SPACE)) { + if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), VERBOSITY_KEY, VERBOSITY_KEY_LEN)) != NULL) { + if (Z_TYPE_P(val) == IS_STRING) { + if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_NO_WHITE_SPACE)) { options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_no_white_space; - } else if (!strcmp(Z_STRVAL_PP(val), VERBOSITY_VALUE_NEWLINES_ONLY)) { + } else if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_NEWLINES_ONLY)) { options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_newlines_only; - } else if (!strcmp(Z_STRVAL_PP(val), VERBOSITY_VALUE_PRETTY)) { + } else if (!strcmp(Z_STRVAL_P(val), VERBOSITY_VALUE_PRETTY)) { options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_pretty; } } } /* version of xml to output */ - if (zend_hash_find(Z_ARRVAL_P(output_opts), VERSION_KEY, VERSION_KEY_LEN + 1, (void**) &val) == SUCCESS) { - if (Z_TYPE_PP(val) == IS_STRING) { + if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), VERSION_KEY, VERSION_KEY_LEN)) != NULL) { + if (Z_TYPE_P(val) == IS_STRING) { options->b_auto_version = 0; - if (!strcmp(Z_STRVAL_PP(val), VERSION_VALUE_XMLRPC)) { + if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_XMLRPC)) { options->xmlrpc_out.version = xmlrpc_version_1_0; - } else if (!strcmp(Z_STRVAL_PP(val), VERSION_VALUE_SIMPLE)) { + } else if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_SIMPLE)) { options->xmlrpc_out.version = xmlrpc_version_simple; - } else if (!strcmp((*val)->value.str.val, VERSION_VALUE_SOAP11)) { - options->xmlrpc_out.version = xmlrpc_version_soap_1_1; + } else if (!strcmp(Z_STRVAL_P(val), VERSION_VALUE_SOAP11)) { + options->xmlrpc_out.version = xmlrpc_version_soap_1_1; } else { /* if(!strcmp((*val)->value.str.val, VERSION_VALUE_AUTO)) { */ - options->b_auto_version = 1; + options->b_auto_version = 1; } } - } - /* encoding code set */ - if (zend_hash_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN + 1, (void**)&val) == SUCCESS) { - if (Z_TYPE_PP(val) == IS_STRING) { - options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_PP(val)); + /* encoding code set */ + if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN)) != NULL) { + if (Z_TYPE_P(val) == IS_STRING) { + options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_P(val)); + } } - } - /* escaping options */ - if (zend_hash_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN + 1, (void**)&val) == SUCCESS) { - /* multiple values allowed. check if array */ - if (Z_TYPE_PP(val) == IS_ARRAY) { - zval** iter_val; + /* escaping options */ + if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN)) != NULL) { + /* multiple values allowed. check if array */ + if (Z_TYPE_P(val) == IS_ARRAY) { + zval* iter_val; - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(val)); - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping; + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping; - while (1) { - if (zend_hash_get_current_data(Z_ARRVAL_PP(val), (void**)&iter_val) == SUCCESS) { - if (Z_TYPE_PP(iter_val) == IS_STRING && Z_STRVAL_PP(iter_val)) { - if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_CDATA)) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(val), iter_val) { + if (Z_TYPE_P(iter_val) == IS_STRING && Z_STRVAL_P(iter_val)) { + if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_CDATA)) { options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping; - } else if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_NON_ASCII)) { + } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_ASCII)) { options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping; - } else if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_NON_PRINT)) { + } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_PRINT)) { options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping; - } else if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_MARKUP)) { + } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_MARKUP)) { options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping; } } - } else { - break; + } ZEND_HASH_FOREACH_END(); + /* else, check for single value */ + } else if (Z_TYPE_P(val) == IS_STRING) { + if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_CDATA)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping; + } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_ASCII)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping; + } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_PRINT)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping; + } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_MARKUP)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping; } - zend_hash_move_forward(Z_ARRVAL_PP(val)); - } - /* else, check for single value */ - } else if (Z_TYPE_PP(val) == IS_STRING) { - if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_CDATA)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping; - } else if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_NON_ASCII)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping; - } else if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_NON_PRINT)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping; - } else if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_MARKUP)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping; } } } @@ -486,13 +471,10 @@ static XMLRPC_VECTOR_TYPE determine_vector_type (HashTable *ht) { int bArray = 0, bStruct = 0, bMixed = 0; unsigned long num_index, last_num = 0; - char* my_key; + zend_string* my_key; - zend_hash_internal_pointer_reset(ht); - while (1) { - int res = my_zend_hash_get_current_key(ht, &my_key, &num_index); - - if (res == HASH_KEY_IS_LONG) { + ZEND_HASH_FOREACH_KEY(ht, num_index, my_key) { + if (my_key == NULL) { if (bStruct) { bMixed = 1; break; @@ -502,17 +484,14 @@ static XMLRPC_VECTOR_TYPE determine_vector_type (HashTable *ht) } bArray = 1; last_num = num_index; - } else if (res == HASH_KEY_NON_EXISTENT) { - break; - } else if (res == HASH_KEY_IS_STRING) { + } else { if (bArray) { bMixed = 1; break; } bStruct = 1; } - zend_hash_move_forward(ht); - } + } ZEND_HASH_FOREACH_END(); return bMixed ? xmlrpc_vector_mixed : (bStruct ? xmlrpc_vector_struct : xmlrpc_vector_array); } @@ -522,94 +501,85 @@ static XMLRPC_VALUE PHP_to_XMLRPC_worker (const char* key, zval* in_val, int dep XMLRPC_VALUE xReturn = NULL; if (in_val) { - zval* val = NULL; + zval val; + ZVAL_UNDEF(&val); XMLRPC_VALUE_TYPE type = get_zval_xmlrpc_type(in_val, &val); - if (val) { + if (!Z_ISUNDEF(val)) { switch (type) { case xmlrpc_base64: - if (Z_TYPE_P(val) == IS_NULL) { + if (Z_TYPE(val) == IS_NULL) { xReturn = XMLRPC_CreateValueEmpty(); XMLRPC_SetValueID(xReturn, key, 0); } else { - xReturn = XMLRPC_CreateValueBase64(key, Z_STRVAL_P(val), Z_STRLEN_P(val)); + xReturn = XMLRPC_CreateValueBase64(key, Z_STRVAL(val), Z_STRLEN(val)); } break; case xmlrpc_datetime: - convert_to_string(val); - xReturn = XMLRPC_CreateValueDateTime_ISO8601(key, Z_STRVAL_P(val)); + convert_to_string(&val); + xReturn = XMLRPC_CreateValueDateTime_ISO8601(key, Z_STRVAL(val)); break; case xmlrpc_boolean: - convert_to_boolean(val); - xReturn = XMLRPC_CreateValueBoolean(key, Z_TYPE_P(val) == IS_TRUE); + convert_to_boolean(&val); + xReturn = XMLRPC_CreateValueBoolean(key, Z_TYPE(val) == IS_TRUE); break; case xmlrpc_int: - convert_to_long(val); - xReturn = XMLRPC_CreateValueInt(key, Z_LVAL_P(val)); + convert_to_long(&val); + xReturn = XMLRPC_CreateValueInt(key, Z_LVAL(val)); break; case xmlrpc_double: - convert_to_double(val); - xReturn = XMLRPC_CreateValueDouble(key, Z_DVAL_P(val)); + convert_to_double(&val); + xReturn = XMLRPC_CreateValueDouble(key, Z_DVAL(val)); break; case xmlrpc_string: - convert_to_string(val); - xReturn = XMLRPC_CreateValueString(key, Z_STRVAL_P(val), Z_STRLEN_P(val)); + convert_to_string(&val); + xReturn = XMLRPC_CreateValueString(key, Z_STRVAL(val), Z_STRLEN(val)); break; case xmlrpc_vector: { unsigned long num_index; - zval** pIter; - char* my_key; + zval* pIter; + zend_string* my_key; HashTable *ht = NULL; - zval *val_arr; + zval val_arr; XMLRPC_VECTOR_TYPE vtype; - ht = HASH_OF(val); - if (ht && ht->nApplyCount > 1) { + ht = HASH_OF(&val); + if (ht && ht->u.v.nApplyCount > 1) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "XML-RPC doesn't support circular references"); return NULL; } - MAKE_STD_ZVAL(val_arr); - MAKE_COPY_ZVAL(&val, val_arr); - convert_to_array(val_arr); + ZVAL_COPY(&val_arr, &val); + convert_to_array(&val_arr); - vtype = determine_vector_type(Z_ARRVAL_P(val_arr)); + vtype = determine_vector_type(Z_ARRVAL(val_arr)); xReturn = XMLRPC_CreateVector(key, vtype); - zend_hash_internal_pointer_reset(Z_ARRVAL_P(val_arr)); - while(zend_hash_get_current_data(Z_ARRVAL_P(val_arr), (void**)&pIter) == SUCCESS) { - int res = my_zend_hash_get_current_key(Z_ARRVAL_P(val_arr), &my_key, &num_index); - - switch (res) { - case HASH_KEY_NON_EXISTENT: - break; - case HASH_KEY_IS_STRING: - case HASH_KEY_IS_LONG: - ht = HASH_OF(*pIter); - if (ht) { - ht->nApplyCount++; - } - if (res == HASH_KEY_IS_LONG) { - char *num_str = NULL; - - if (vtype != xmlrpc_vector_array) { - spprintf(&num_str, 0, "%ld", num_index); - } - XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(num_str, *pIter, depth++ TSRMLS_CC)); - if (num_str) { - efree(num_str); - } - } else { - XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(my_key, *pIter, depth++ TSRMLS_CC)); - } - if (ht) { - ht->nApplyCount--; - } - break; + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(val_arr), num_index, my_key, pIter) { + ht = HASH_OF(pIter); + if (ht) { + ht->u.v.nApplyCount++; } - zend_hash_move_forward(Z_ARRVAL_P(val_arr)); - } + if (my_key == NULL) { + char *num_str = NULL; + + if (vtype != xmlrpc_vector_array) { + spprintf(&num_str, 0, "%ld", num_index); + } + + XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(num_str, pIter, depth++ TSRMLS_CC)); + if (num_str) { + efree(num_str); + } + } else { + XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(my_key->val, pIter, depth++ TSRMLS_CC)); + } + if (ht) { + ht->u.v.nApplyCount--; + } + break; + } ZEND_HASH_FOREACH_END(); zval_ptr_dtor(&val_arr); } break; @@ -627,51 +597,39 @@ static XMLRPC_VALUE PHP_to_XMLRPC(zval* root_val TSRMLS_DC) } /* recursively convert xmlrpc values into php values */ -static zval* XMLRPC_to_PHP(XMLRPC_VALUE el) +static void XMLRPC_to_PHP(XMLRPC_VALUE el, zval *elem) { - zval* elem = NULL; const char* pStr; if (el) { XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(el); - MAKE_STD_ZVAL(elem); /* init. very important. spent a frustrating day finding this out. */ - - switch(type) { + switch (type) { case xmlrpc_empty: - Z_TYPE_P(elem) = IS_NULL; + ZVAL_NULL(elem); break; case xmlrpc_string: pStr = XMLRPC_GetValueString(el); if (pStr) { - Z_STRLEN_P(elem) = XMLRPC_GetValueStringLen(el); - Z_STRVAL_P(elem) = estrndup(pStr, Z_STRLEN_P(elem)); - Z_TYPE_P(elem) = IS_STRING; + ZVAL_STRINGL(elem, pStr, XMLRPC_GetValueStringLen(el)); } break; case xmlrpc_int: - Z_LVAL_P(elem) = XMLRPC_GetValueInt(el); - Z_TYPE_P(elem) = IS_LONG; + ZVAL_LONG(elem, XMLRPC_GetValueInt(el)); break; case xmlrpc_boolean: - Z_LVAL_P(elem) = XMLRPC_GetValueBoolean(el); - Z_TYPE_P(elem) = IS_BOOL; + ZVAL_BOOL(elem, XMLRPC_GetValueBoolean(el)); break; case xmlrpc_double: - Z_DVAL_P(elem) = XMLRPC_GetValueDouble(el); - Z_TYPE_P(elem) = IS_DOUBLE; + ZVAL_DOUBLE(elem, XMLRPC_GetValueDouble(el)); break; case xmlrpc_datetime: - Z_STRLEN_P(elem) = XMLRPC_GetValueStringLen(el); - Z_STRVAL_P(elem) = estrndup(XMLRPC_GetValueDateTime_ISO8601(el), Z_STRLEN_P(elem)); - Z_TYPE_P(elem) = IS_STRING; + ZVAL_STRINGL(elem, XMLRPC_GetValueDateTime_ISO8601(el), XMLRPC_GetValueStringLen(el)); break; case xmlrpc_base64: pStr = XMLRPC_GetValueBase64(el); if (pStr) { - Z_STRLEN_P(elem) = XMLRPC_GetValueStringLen(el); - Z_STRVAL_P(elem) = estrndup(pStr, Z_STRLEN_P(elem)); - Z_TYPE_P(elem) = IS_STRING; + ZVAL_STRINGL(elem, pStr, XMLRPC_GetValueStringLen(el)); } break; case xmlrpc_vector: @@ -680,8 +638,10 @@ static zval* XMLRPC_to_PHP(XMLRPC_VALUE el) XMLRPC_VALUE xIter = XMLRPC_VectorRewind(el); while( xIter ) { - zval *val = XMLRPC_to_PHP(xIter); - if (val) { + zval val; + ZVAL_UNDEF(&val); + XMLRPC_to_PHP(xIter, &val); + if (!Z_ISUNDEF(val)) { add_zval(elem, XMLRPC_GetValueID(xIter), &val); } xIter = XMLRPC_VectorNext(el); @@ -693,7 +653,6 @@ static zval* XMLRPC_to_PHP(XMLRPC_VALUE el) } set_zval_xmlrpc_type(elem, type); } - return elem; } /* {{{ proto string xmlrpc_encode_request(string method, mixed params [, array output_options]) @@ -713,7 +672,7 @@ PHP_FUNCTION(xmlrpc_encode_request) set_output_options(&out, out_opts ? out_opts : 0); - if (return_value_used) { + if (USED_RET()) { xRequest = XMLRPC_RequestNew(); if (xRequest) { @@ -730,7 +689,7 @@ PHP_FUNCTION(xmlrpc_encode_request) outBuf = XMLRPC_REQUEST_ToXML(xRequest, 0); if (outBuf) { - RETVAL_STRING(outBuf, 1); + RETVAL_STRING(outBuf); free(outBuf); } XMLRPC_RequestFree(xRequest, 1); @@ -748,23 +707,23 @@ PHP_FUNCTION(xmlrpc_encode_request) PHP_FUNCTION(xmlrpc_encode) { XMLRPC_VALUE xOut = NULL; - zval **arg1; + zval *arg1; char *outBuf; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg1) == FAILURE) { return; } - if (return_value_used) { + if (USED_RET()) { /* convert native php type to xmlrpc type */ - xOut = PHP_to_XMLRPC(*arg1 TSRMLS_CC); + xOut = PHP_to_XMLRPC(arg1 TSRMLS_CC); /* generate raw xml from xmlrpc data */ outBuf = XMLRPC_VALUE_ToXML(xOut, 0); if (xOut) { if (outBuf) { - RETVAL_STRING(outBuf, 1); + RETVAL_STRING(outBuf); free(outBuf); } /* cleanup */ @@ -774,9 +733,8 @@ PHP_FUNCTION(xmlrpc_encode) } /* }}} */ -zval* decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out) /* {{{ */ +void decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out, zval *retval) /* {{{ */ { - zval* retval = NULL; XMLRPC_REQUEST response; STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS opts = {{0}}; const char *method_name; @@ -785,20 +743,18 @@ zval* decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zva /* generate XMLRPC_REQUEST from raw xml */ response = XMLRPC_REQUEST_FromXML(xml_in, xml_in_len, &opts); if (response) { + ZVAL_NULL(retval); /* convert xmlrpc data to native php types */ - retval = XMLRPC_to_PHP(XMLRPC_RequestGetData(response)); + XMLRPC_to_PHP(XMLRPC_RequestGetData(response), retval); if (XMLRPC_RequestGetRequestType(response) == xmlrpc_request_call) { if (method_name_out) { method_name = XMLRPC_RequestGetMethodName(response); if (method_name) { - zval_dtor(method_name_out); - Z_TYPE_P(method_name_out) = IS_STRING; - Z_STRVAL_P(method_name_out) = estrdup(method_name); - Z_STRLEN_P(method_name_out) = strlen(Z_STRVAL_P(method_name_out)); - } else if (retval) { - zval_ptr_dtor(&retval); - retval = NULL; + zval_ptr_dtor(method_name_out); + ZVAL_STRING(method_name_out, method_name); + } else { + zval_ptr_dtor(retval); } } } @@ -806,7 +762,6 @@ zval* decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zva /* dust, sweep, and mop */ XMLRPC_RequestFree(response, 1); } - return retval; } /* }}} */ @@ -815,20 +770,17 @@ zval* decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zva PHP_FUNCTION(xmlrpc_decode_request) { char *xml, *encoding = NULL; - zval **method; + zval *method; int xml_len, encoding_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ|s", &xml, &xml_len, &method, &encoding, &encoding_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|s", &xml, &xml_len, &method, &encoding, &encoding_len) == FAILURE) { return; } + ZVAL_DEREF(method); - if (return_value_used) { - zval* retval = decode_request_worker(xml, xml_len, encoding_len ? encoding : NULL, *method); - if (retval) { - *return_value = *retval; - FREE_ZVAL(retval); - } + if (USED_RET()) { + decode_request_worker(xml, xml_len, encoding_len ? encoding : NULL, method, return_value); } } /* }}} */ @@ -844,12 +796,8 @@ PHP_FUNCTION(xmlrpc_decode) return; } - if (return_value_used) { - zval* retval = decode_request_worker(arg1, arg1_len, arg2_len ? arg2 : NULL, NULL); - if (retval) { - *return_value = *retval; - FREE_ZVAL(retval); - } + if (USED_RET()) { + decode_request_worker(arg1, arg1_len, arg2_len ? arg2 : NULL, NULL, return_value); } } /* }}} */ @@ -866,24 +814,18 @@ PHP_FUNCTION(xmlrpc_server_create) return; } - if (return_value_used) { - zval *method_map, *introspection_map; + if (USED_RET()) { xmlrpc_server_data *server = emalloc(sizeof(xmlrpc_server_data)); - MAKE_STD_ZVAL(method_map); - MAKE_STD_ZVAL(introspection_map); - - array_init(method_map); - array_init(introspection_map); /* allocate server data. free'd in destroy_server_data() */ - server->method_map = method_map; - server->introspection_map = introspection_map; + array_init(&server->method_map); + array_init(&server->introspection_map); server->server_ptr = XMLRPC_ServerCreate(); XMLRPC_ServerRegisterIntrospectionCallback(server->server_ptr, php_xmlrpc_introspection_callback); /* store for later use */ - ZEND_REGISTER_RESOURCE(return_value,server, le_xmlrpc_server); + ZEND_REGISTER_RESOURCE(return_value, server, le_xmlrpc_server); } } /* }}} */ @@ -893,23 +835,22 @@ PHP_FUNCTION(xmlrpc_server_create) PHP_FUNCTION(xmlrpc_server_destroy) { zval *arg1; - int bSuccess = FAILURE, type; + int bSuccess = FAILURE; xmlrpc_server_data *server; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) { return; } - server = zend_list_find(Z_LVAL_P(arg1), &type); - - if (server && type == le_xmlrpc_server) { - bSuccess = zend_list_delete(Z_LVAL_P(arg1)); + ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, arg1, -1, "xmlrpc server", le_xmlrpc_server); + if (server) { + bSuccess = zend_list_close(Z_RES_P(arg1)); /* called by hashtable destructor * destroy_server_data(server); */ } - RETVAL_LONG(bSuccess == SUCCESS); + RETURN_BOOL(bSuccess == SUCCESS); } /* }}} */ @@ -919,42 +860,39 @@ PHP_FUNCTION(xmlrpc_server_destroy) static XMLRPC_VALUE php_xmlrpc_callback(XMLRPC_SERVER server, XMLRPC_REQUEST xRequest, void* data) /* {{{ */ { xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data; - zval** php_function; - zval* xmlrpc_params; - zval* callback_params[3]; + zval* php_function; + zval xmlrpc_params; + zval callback_params[3]; TSRMLS_FETCH(); - zval_dtor(pData->xmlrpc_method); - zval_dtor(pData->return_data); + zval_ptr_dtor(&pData->xmlrpc_method); + zval_ptr_dtor(&pData->return_data); /* convert xmlrpc to native php types */ - ZVAL_STRING(pData->xmlrpc_method, XMLRPC_RequestGetMethodName(xRequest), 1); - xmlrpc_params = XMLRPC_to_PHP(XMLRPC_RequestGetData(xRequest)); + ZVAL_STRING(&pData->xmlrpc_method, XMLRPC_RequestGetMethodName(xRequest)); + XMLRPC_to_PHP(XMLRPC_RequestGetData(xRequest), &xmlrpc_params); /* check if the called method has been previous registered */ - if(zend_hash_find(Z_ARRVAL_P(pData->server->method_map), - Z_STRVAL_P(pData->xmlrpc_method), - Z_STRLEN_P(pData->xmlrpc_method) + 1, - (void**)&php_function) == SUCCESS) { - - pData->php_function = *php_function; + if ((php_function = zend_hash_find(Z_ARRVAL(pData->server->method_map), Z_STR(pData->xmlrpc_method))) != NULL) { + ZVAL_COPY_VALUE(&pData->php_function, php_function); } /* setup data hoojum */ - callback_params[0] = pData->xmlrpc_method; - callback_params[1] = xmlrpc_params; - callback_params[2] = pData->caller_params; + ZVAL_COPY_VALUE(&callback_params[0], &pData->xmlrpc_method); + ZVAL_COPY_VALUE(&callback_params[1], &xmlrpc_params); + ZVAL_COPY_VALUE(&callback_params[2], &pData->caller_params); /* Use same C function for all methods */ /* php func prototype: function user_func($method_name, $xmlrpc_params, $user_params) */ - call_user_function(CG(function_table), NULL, pData->php_function, pData->return_data, 3, callback_params TSRMLS_CC); + call_user_function(CG(function_table), NULL, &pData->php_function, &pData->return_data, 3, callback_params TSRMLS_CC); pData->php_executed = 1; zval_ptr_dtor(&xmlrpc_params); + zval_ptr_dtor(&pData->xmlrpc_method); - return PHP_to_XMLRPC(pData->return_data TSRMLS_CC); + return PHP_to_XMLRPC(&pData->return_data TSRMLS_CC); } /* }}} */ @@ -963,61 +901,54 @@ static XMLRPC_VALUE php_xmlrpc_callback(XMLRPC_SERVER server, XMLRPC_REQUEST xRe */ static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data) /* {{{ */ { - zval retval, **php_function; - zval *callback_params[1]; - char *php_function_name; + zval retval, *php_function; + zval callback_params[1]; + zend_string *php_function_name; xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data; TSRMLS_FETCH(); /* setup data hoojum */ - callback_params[0] = pData->caller_params; + ZVAL_COPY_VALUE(&callback_params[0], &pData->caller_params); - /* loop through and call all registered callbacks */ - zend_hash_internal_pointer_reset(Z_ARRVAL_P(pData->server->introspection_map)); - while (1) { - if (zend_hash_get_current_data(Z_ARRVAL_P(pData->server->introspection_map), (void**)&php_function) == SUCCESS) { - if (zend_is_callable(*php_function, 0, &php_function_name TSRMLS_CC)) { - /* php func prototype: function string user_func($user_params) */ - if (call_user_function(CG(function_table), NULL, *php_function, &retval, 1, callback_params TSRMLS_CC) == SUCCESS) { - XMLRPC_VALUE xData; - STRUCT_XMLRPC_ERROR err = {0}; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL(pData->server->introspection_map), php_function) { + if (zend_is_callable(php_function, 0, &php_function_name TSRMLS_CC)) { + /* php func prototype: function string user_func($user_params) */ + if (call_user_function(CG(function_table), NULL, php_function, &retval, 1, callback_params TSRMLS_CC) == SUCCESS) { + XMLRPC_VALUE xData; + STRUCT_XMLRPC_ERROR err = {0}; - /* return value should be a string */ - convert_to_string(&retval); + /* return value should be a string */ + convert_to_string(&retval); - xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err); + xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err); - if (xData) { - if (!XMLRPC_ServerAddIntrospectionData(server, xData)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", php_function_name); - } - XMLRPC_CleanupValue(xData); - } else { - /* could not create description */ - if (err.xml_elem_error.parser_code) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %s()", - err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, php_function_name); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s()", php_function_name); - } + if (xData) { + if (!XMLRPC_ServerAddIntrospectionData(server, xData)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", php_function_name->val); } - zval_dtor(&retval); + XMLRPC_CleanupValue(xData); } else { - /* user func failed */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling user introspection callback: %s()", php_function_name); + /* could not create description */ + if (err.xml_elem_error.parser_code) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %s()", + err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, php_function_name->val); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s()", php_function_name->val); + } } + zval_ptr_dtor(&retval); } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid callback '%s' passed", php_function_name); + /* user func failed */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling user introspection callback: %s()", php_function_name->val); } - efree(php_function_name); } else { - break; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid callback '%s' passed", php_function_name->val); } - zend_hash_move_forward(Z_ARRVAL_P(pData->server->introspection_map)); - } + STR_RELEASE(php_function_name); + } ZEND_HASH_FOREACH_END(); /* so we don't call the same callbacks ever again */ - zend_hash_clean(Z_ARRVAL_P(pData->server->introspection_map)); + zend_hash_clean(Z_ARRVAL(pData->server->introspection_map)); } /* }}} */ @@ -1027,32 +958,29 @@ PHP_FUNCTION(xmlrpc_server_register_method) { char *method_key; int method_key_len; - zval *handle, *method_name_save, **method_name; - int type; + zval *handle, *method_name; xmlrpc_server_data* server; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZ", &handle, &method_key, &method_key_len, &method_name) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz", &handle, &method_key, &method_key_len, &method_name) == FAILURE) { return; } - server = zend_list_find(Z_LVAL_P(handle), &type); + ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server); - if (type == le_xmlrpc_server) { - /* register with C engine. every method just calls our standard callback, - * and it then dispatches to php as necessary - */ - if (XMLRPC_ServerRegisterMethod(server->server_ptr, method_key, php_xmlrpc_callback)) { - /* save for later use */ - ALLOC_ZVAL(method_name_save); - MAKE_COPY_ZVAL(method_name, method_name_save); + /* register with C engine. every method just calls our standard callback, + * and it then dispatches to php as necessary + */ + if (XMLRPC_ServerRegisterMethod(server->server_ptr, method_key, php_xmlrpc_callback)) { + /* save for later use */ - /* register our php method */ - add_zval(server->method_map, method_key, &method_name_save); - - RETURN_BOOL(1); + if (Z_REFCOUNTED_P(method_name)) { + Z_ADDREF_P(method_name); } + /* register our php method */ + add_zval(&server->method_map, method_key, method_name); + + RETURN_TRUE; } - RETURN_BOOL(0); } /* }}} */ @@ -1060,27 +988,22 @@ PHP_FUNCTION(xmlrpc_server_register_method) Register a PHP function to generate documentation */ PHP_FUNCTION(xmlrpc_server_register_introspection_callback) { - zval **method_name, *handle, *method_name_save; - int type; + zval *method_name, *handle; xmlrpc_server_data* server; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &handle, &method_name) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &handle, &method_name) == FAILURE) { return; } - server = zend_list_find(Z_LVAL_P(handle), &type); + ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server); - if (type == le_xmlrpc_server) { - /* save for later use */ - ALLOC_ZVAL(method_name_save); - MAKE_COPY_ZVAL(method_name, method_name_save); - - /* register our php method */ - add_zval(server->introspection_map, NULL, &method_name_save); - - RETURN_BOOL(1); + if (Z_REFCOUNTED_P(method_name)) { + Z_ADDREF_P(method_name); } - RETURN_BOOL(0); + /* register our php method */ + add_zval(&server->introspection_map, NULL, method_name); + + RETURN_TRUE; } /* }}} */ @@ -1090,17 +1013,17 @@ PHP_FUNCTION(xmlrpc_server_register_introspection_callback) Parses XML requests and call methods */ PHP_FUNCTION(xmlrpc_server_call_method) { - xmlrpc_callback_data data = {0}; XMLRPC_REQUEST xRequest; + xmlrpc_callback_data data; STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS input_opts; xmlrpc_server_data* server; - zval **caller_params, *handle, *output_opts = NULL; + zval *caller_params, *handle, *output_opts = NULL; char *rawxml; - int rawxml_len, type; + int rawxml_len; php_output_options out; - int argc =ZEND_NUM_ARGS(); + int argc = ZEND_NUM_ARGS(); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZ|a", &handle, &rawxml, &rawxml_len, &caller_params, &output_opts) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|a", &handle, &rawxml, &rawxml_len, &caller_params, &output_opts) != SUCCESS) { return; } /* user output options */ @@ -1110,87 +1033,80 @@ PHP_FUNCTION(xmlrpc_server_call_method) set_output_options(&out, output_opts); } - server = zend_list_find(Z_LVAL_P(handle), &type); + ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server); - if (type == le_xmlrpc_server) { - /* HACK: use output encoding for now */ - input_opts.xml_elem_opts.encoding = utf8_get_encoding_id_from_string(out.xmlrpc_out.xml_elem_opts.encoding); + /* HACK: use output encoding for now */ + input_opts.xml_elem_opts.encoding = utf8_get_encoding_id_from_string(out.xmlrpc_out.xml_elem_opts.encoding); - /* generate an XMLRPC_REQUEST from the raw xml input */ - xRequest = XMLRPC_REQUEST_FromXML(rawxml, rawxml_len, &input_opts); + /* generate an XMLRPC_REQUEST from the raw xml input */ + xRequest = XMLRPC_REQUEST_FromXML(rawxml, rawxml_len, &input_opts); - if (xRequest) { - const char* methodname = XMLRPC_RequestGetMethodName(xRequest); - XMLRPC_VALUE xAnswer = NULL; - MAKE_STD_ZVAL(data.xmlrpc_method); /* init. very important. spent a frustrating day finding this out. */ - MAKE_STD_ZVAL(data.return_data); - Z_TYPE_P(data.return_data) = IS_NULL; /* in case value is never init'd, we don't dtor to think it is a string or something */ - Z_TYPE_P(data.xmlrpc_method) = IS_NULL; + if (xRequest) { + const char* methodname = XMLRPC_RequestGetMethodName(xRequest); + XMLRPC_VALUE xAnswer = NULL; + ZVAL_NULL(&data.xmlrpc_method); /* init. very important. spent a frustrating day finding this out. */ + ZVAL_NULL(&data.return_data); + ZVAL_NULL(&data.return_data); /* in case value is never init'd, we don't dtor to think it is a string or something */ + ZVAL_NULL(&data.xmlrpc_method); - /* setup some data to pass to the callback function */ - data.caller_params = *caller_params; - data.php_executed = 0; - data.server = server; + /* setup some data to pass to the callback function */ + ZVAL_COPY_VALUE(&data.caller_params, caller_params); + data.php_executed = 0; + data.server = server; - /* We could just call the php method directly ourselves at this point, but we do this - * with a C callback in case the xmlrpc library ever implements some cool usage stats, - * or somesuch. - */ - xAnswer = XMLRPC_ServerCallMethod(server->server_ptr, xRequest, &data); - if (xAnswer && out.b_php_out) { - zval_dtor(data.return_data); - FREE_ZVAL(data.return_data); - data.return_data = XMLRPC_to_PHP(xAnswer); - } else if (data.php_executed && !out.b_php_out && !xAnswer) { - xAnswer = PHP_to_XMLRPC(data.return_data TSRMLS_CC); - } - - /* should we return data as xml? */ - if (!out.b_php_out) { - XMLRPC_REQUEST xResponse = XMLRPC_RequestNew(); - if (xResponse) { - char *outBuf = 0; - int buf_len = 0; - - /* automagically determine output serialization type from request type */ - if (out.b_auto_version) { - XMLRPC_REQUEST_OUTPUT_OPTIONS opts = XMLRPC_RequestGetOutputOptions(xRequest); - if (opts) { - out.xmlrpc_out.version = opts->version; - } - } - /* set some required request hoojum */ - XMLRPC_RequestSetOutputOptions(xResponse, &out.xmlrpc_out); - XMLRPC_RequestSetRequestType(xResponse, xmlrpc_request_response); - XMLRPC_RequestSetData(xResponse, xAnswer); - XMLRPC_RequestSetMethodName(xResponse, methodname); - - /* generate xml */ - outBuf = XMLRPC_REQUEST_ToXML(xResponse, &buf_len); - if (outBuf) { - RETVAL_STRINGL(outBuf, buf_len, 1); - free(outBuf); - } - /* cleanup after ourselves. what a sty! */ - XMLRPC_RequestFree(xResponse, 0); - } - } else { /* or as native php types? */ - *return_value = *data.return_data; - zval_copy_ctor(return_value); - } - - /* cleanup after ourselves. what a sty! */ - zval_ptr_dtor(&data.xmlrpc_method); - - zval_dtor(data.return_data); - FREE_ZVAL(data.return_data); - - if (xAnswer) { - XMLRPC_CleanupValue(xAnswer); - } - - XMLRPC_RequestFree(xRequest, 1); + /* We could just call the php method directly ourselves at this point, but we do this + * with a C callback in case the xmlrpc library ever implements some cool usage stats, + * or somesuch. + */ + xAnswer = XMLRPC_ServerCallMethod(server->server_ptr, xRequest, &data); + if (xAnswer && out.b_php_out) { + XMLRPC_to_PHP(xAnswer, &data.return_data); + } else if (data.php_executed && !out.b_php_out && !xAnswer) { + xAnswer = PHP_to_XMLRPC(&data.return_data TSRMLS_CC); } + + /* should we return data as xml? */ + if (!out.b_php_out) { + XMLRPC_REQUEST xResponse = XMLRPC_RequestNew(); + if (xResponse) { + char *outBuf = 0; + int buf_len = 0; + + /* automagically determine output serialization type from request type */ + if (out.b_auto_version) { + XMLRPC_REQUEST_OUTPUT_OPTIONS opts = XMLRPC_RequestGetOutputOptions(xRequest); + if (opts) { + out.xmlrpc_out.version = opts->version; + } + } + /* set some required request hoojum */ + XMLRPC_RequestSetOutputOptions(xResponse, &out.xmlrpc_out); + XMLRPC_RequestSetRequestType(xResponse, xmlrpc_request_response); + XMLRPC_RequestSetData(xResponse, xAnswer); + XMLRPC_RequestSetMethodName(xResponse, methodname); + + /* generate xml */ + outBuf = XMLRPC_REQUEST_ToXML(xResponse, &buf_len); + if (outBuf) { + RETVAL_STRINGL(outBuf, buf_len); + free(outBuf); + } + /* cleanup after ourselves. what a sty! */ + XMLRPC_RequestFree(xResponse, 0); + } + } else { /* or as native php types? */ + ZVAL_COPY(return_value, &data.return_data); + } + + /* cleanup after ourselves. what a sty! */ + zval_ptr_dtor(&data.xmlrpc_method); + zval_ptr_dtor(&data.return_data); + + if (xAnswer) { + XMLRPC_CleanupValue(xAnswer); + } + + XMLRPC_RequestFree(xRequest, 1); } } /* }}} */ @@ -1200,22 +1116,19 @@ PHP_FUNCTION(xmlrpc_server_call_method) PHP_FUNCTION(xmlrpc_server_add_introspection_data) { zval *handle, *desc; - int type; xmlrpc_server_data* server; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra", &handle, &desc) == FAILURE) { return; } - server = zend_list_find(Z_LVAL_P(handle), &type); + ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server); - if (type == le_xmlrpc_server) { - XMLRPC_VALUE xDesc = PHP_to_XMLRPC(desc TSRMLS_CC); - if (xDesc) { - int retval = XMLRPC_ServerAddIntrospectionData(server->server_ptr, xDesc); - XMLRPC_CleanupValue(xDesc); - RETURN_LONG(retval); - } + XMLRPC_VALUE xDesc = PHP_to_XMLRPC(desc TSRMLS_CC); + if (xDesc) { + int retval = XMLRPC_ServerAddIntrospectionData(server->server_ptr, xDesc); + XMLRPC_CleanupValue(xDesc); + RETURN_LONG(retval); } RETURN_LONG(0); } @@ -1225,7 +1138,6 @@ PHP_FUNCTION(xmlrpc_server_add_introspection_data) Decodes XML into a list of method descriptions */ PHP_FUNCTION(xmlrpc_parse_method_descriptions) { - zval *retval; char *arg1; int arg1_len; @@ -1233,15 +1145,11 @@ PHP_FUNCTION(xmlrpc_parse_method_descriptions) return; } - if (return_value_used) { + if (USED_RET()) { STRUCT_XMLRPC_ERROR err = {0}; XMLRPC_VALUE xVal = XMLRPC_IntrospectionCreateDescription(arg1, &err); if (xVal) { - retval = XMLRPC_to_PHP(xVal); - - if (retval) { - RETVAL_ZVAL(retval, 1, 1); - } + XMLRPC_to_PHP(xVal, return_value); /* dust, sweep, and mop */ XMLRPC_CleanupValue(xVal); } else { @@ -1355,29 +1263,22 @@ int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE newtype) /* {{{ */ if (Z_TYPE_P(value) == IS_STRING) { if (newtype == xmlrpc_base64 || newtype == xmlrpc_datetime) { const char* typestr = xmlrpc_type_as_str(newtype, xmlrpc_vector_none); - zval* type; + zval type; - MAKE_STD_ZVAL(type); - - Z_TYPE_P(type) = IS_STRING; - Z_STRVAL_P(type) = estrdup(typestr); - Z_STRLEN_P(type) = strlen(typestr); + ZVAL_STRING(&type, typestr); if (newtype == xmlrpc_datetime) { - XMLRPC_VALUE v = XMLRPC_CreateValueDateTime_ISO8601(NULL, value->value.str.val); + XMLRPC_VALUE v = XMLRPC_CreateValueDateTime_ISO8601(NULL, Z_STRVAL_P(value)); if (v) { time_t timestamp = (time_t) php_parse_date((char *)XMLRPC_GetValueDateTime_ISO8601(v), NULL); if (timestamp != -1) { - zval* ztimestamp; + zval ztimestamp; - MAKE_STD_ZVAL(ztimestamp); - - ztimestamp->type = IS_LONG; - ztimestamp->value.lval = timestamp; + ZVAL_LONG(&ztimestamp, timestamp); convert_to_object(value); - if (SUCCESS == zend_hash_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void *) &type, sizeof(zval *), NULL)) { - bSuccess = zend_hash_update(Z_OBJPROP_P(value), OBJECT_VALUE_TS_ATTR, sizeof(OBJECT_VALUE_TS_ATTR), (void *) &ztimestamp, sizeof(zval *), NULL); + if (zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1, &type)) { + bSuccess = zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_VALUE_TS_ATTR, sizeof(OBJECT_VALUE_TS_ATTR) - 1, &ztimestamp) != NULL; } } else { zval_ptr_dtor(&type); @@ -1388,7 +1289,7 @@ int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE newtype) /* {{{ */ } } else { convert_to_object(value); - bSuccess = zend_hash_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void *) &type, sizeof(zval *), NULL); + bSuccess = zend_hash_str_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1, &type) != NULL; } } } @@ -1398,7 +1299,7 @@ int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE newtype) /* {{{ */ /* }}} */ /* return xmlrpc type of a php value */ -XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue) /* {{{ */ +XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval* newvalue) /* {{{ */ { XMLRPC_VALUE_TYPE type = xmlrpc_none; TSRMLS_FETCH(); @@ -1411,7 +1312,8 @@ XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue) /* {{{ */ #ifndef BOOL_AS_LONG /* Right thing to do, but it breaks some legacy code. */ - case IS_BOOL: + case IS_TRUE: + case IS_FALSE: type = xmlrpc_boolean; break; #else @@ -1435,12 +1337,12 @@ XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue) /* {{{ */ break; case IS_OBJECT: { - zval** attr; + zval* attr; type = xmlrpc_vector; - if (zend_hash_find(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void**) &attr) == SUCCESS) { - if (Z_TYPE_PP(attr) == IS_STRING) { - type = xmlrpc_str_as_type(Z_STRVAL_PP(attr)); + if ((attr = zend_hash_str_find(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR) - 1)) != NULL) { + if (Z_TYPE_P(attr) == IS_STRING) { + type = xmlrpc_str_as_type(Z_STRVAL_P(attr)); } } break; @@ -1449,14 +1351,14 @@ XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue) /* {{{ */ /* if requested, return an unmolested (magic removed) copy of the value */ if (newvalue) { - zval** val; + zval* val; if ((type == xmlrpc_base64 && Z_TYPE_P(value) != IS_NULL) || type == xmlrpc_datetime) { - if (zend_hash_find(Z_OBJPROP_P(value), OBJECT_VALUE_ATTR, sizeof(OBJECT_VALUE_ATTR), (void**) &val) == SUCCESS) { - *newvalue = *val; + if ((val = zend_hash_str_find(Z_OBJPROP_P(value), OBJECT_VALUE_ATTR, sizeof(OBJECT_VALUE_ATTR) - 1)) != NULL) { + ZVAL_COPY_VALUE(newvalue, val); } } else { - *newvalue = value; + ZVAL_COPY_VALUE(newvalue, value); } } } @@ -1469,18 +1371,20 @@ XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue) /* {{{ */ Sets xmlrpc type, base64 or datetime, for a PHP string value */ PHP_FUNCTION(xmlrpc_set_type) { - zval **arg; + zval *arg; char *type; int type_len; XMLRPC_VALUE_TYPE vtype; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &arg, &type, &type_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &arg, &type, &type_len) == FAILURE) { return; } + ZVAL_DEREF(arg); + vtype = xmlrpc_str_as_type(type); if (vtype != xmlrpc_none) { - if (set_zval_xmlrpc_type(*arg, vtype) == SUCCESS) { + if (set_zval_xmlrpc_type(arg, vtype) == SUCCESS) { RETURN_TRUE; } } else { @@ -1494,20 +1398,20 @@ PHP_FUNCTION(xmlrpc_set_type) Gets xmlrpc type for a PHP value. Especially useful for base64 and datetime strings */ PHP_FUNCTION(xmlrpc_get_type) { - zval **arg; + zval *arg; XMLRPC_VALUE_TYPE type; XMLRPC_VECTOR_TYPE vtype = xmlrpc_vector_none; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { return; } - type = get_zval_xmlrpc_type(*arg, 0); + type = get_zval_xmlrpc_type(arg, 0); if (type == xmlrpc_vector) { - vtype = determine_vector_type((Z_TYPE_PP(arg) == IS_OBJECT) ? Z_OBJPROP_PP(arg) : Z_ARRVAL_PP(arg)); + vtype = determine_vector_type((Z_TYPE_P(arg) == IS_OBJECT) ? Z_OBJPROP_P(arg) : Z_ARRVAL_P(arg)); } - RETURN_STRING((char*) xmlrpc_type_as_str(type, vtype), 1); + RETURN_STRING((char*) xmlrpc_type_as_str(type, vtype)); } /* }}} */ @@ -1515,7 +1419,7 @@ PHP_FUNCTION(xmlrpc_get_type) Determines if an array value represents an XMLRPC fault. */ PHP_FUNCTION(xmlrpc_is_fault) { - zval *arg, **val; + zval *arg; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arg) == FAILURE) { return; @@ -1527,8 +1431,8 @@ PHP_FUNCTION(xmlrpc_is_fault) * array, which is rather expensive, especially if it was * a big array. Thus, we resort to this not so clever hackery. */ - if (zend_hash_find(Z_ARRVAL_P(arg), FAULT_CODE, FAULT_CODE_LEN + 1, (void**) &val) == SUCCESS && - zend_hash_find(Z_ARRVAL_P(arg), FAULT_STRING, FAULT_STRING_LEN + 1, (void**) &val) == SUCCESS) { + if (zend_hash_str_exists(Z_ARRVAL_P(arg), FAULT_CODE, FAULT_CODE_LEN) && + zend_hash_str_exists(Z_ARRVAL_P(arg), FAULT_STRING, FAULT_STRING_LEN)) { RETURN_TRUE; }