]> granicus.if.org Git - php/commitdiff
Refactoring ext/xmlrpc (incompleted)
authorXinchen Hui <laruence@php.net>
Mon, 12 May 2014 11:28:06 +0000 (19:28 +0800)
committerXinchen Hui <laruence@php.net>
Mon, 12 May 2014 11:28:06 +0000 (19:28 +0800)
ext/xmlrpc/libxmlrpc/xmlrpc.c
ext/xmlrpc/xmlrpc-epi-php.c

index ce70c2afd909b748f3ddc4560a1c3f882a498014..0f77ae24519209c109aceaebe9fba1d85b0dc570 100644 (file)
@@ -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);
       }
 
index 3fb2ba6bb663174a246097e2fc52a77009299cc7..7a9a1f170346f54f9fc06fe3370bc6ff8ec85767 100644 (file)
@@ -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++;
+                                                       }
+                                                       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--;
                                                        }
-                                                       zend_hash_move_forward(Z_ARRVAL_P(val_arr));
-                                               }       
+                                                       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;
-
-       /* 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};
-
-                                       /* return value should be a string */
-                                       convert_to_string(&retval);
-
-                                       xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err);
-
-                                       if (xData) {
-                                               if (!XMLRPC_ServerAddIntrospectionData(server, xData)) {
-                                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", php_function_name);
-                                               }
-                                               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);
-                                               }
+       ZVAL_COPY_VALUE(&callback_params[0], &pData->caller_params);
+
+       ZEND_HASH_FOREACH_VAL(Z_ARRVAL(pData->server->introspection_map), php_function) {
+               if (zend_is_callable(php_function, 0, &php_function_name TSRMLS_CC)) {
+                       /* php func prototype: function string user_func($user_params) */
+                       if (call_user_function(CG(function_table), NULL, php_function, &retval, 1, callback_params TSRMLS_CC) == SUCCESS) {
+                               XMLRPC_VALUE xData;
+                               STRUCT_XMLRPC_ERROR err = {0};
+
+                               /* return value should be a string */
+                               convert_to_string(&retval);
+
+                               xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err);
+
+                               if (xData) {
+                                       if (!XMLRPC_ServerAddIntrospectionData(server, xData)) {
+                                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", php_function_name->val);
                                        }
-                                       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);
-
-       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);
+       ZEND_FETCH_RESOURCE(server, xmlrpc_server_data*, handle, -1, "xmlrpc server", le_xmlrpc_server);
 
-                       /* register our php method */
-                       add_zval(server->method_map, method_key, &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 */
 
-                       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;
-
-                       /* setup some data to pass to the callback function */
-                       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);
-                       }
+       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);
 
-                       /* 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);
+               /* setup some data to pass to the callback function */
+               ZVAL_COPY_VALUE(&data.caller_params, caller_params);
+               data.php_executed = 0;
+               data.server = server;
+
+               /* We could just call the php method directly ourselves at this point, but we do this 
+                * with a C callback in case the xmlrpc library ever implements some cool usage stats,
+                * or somesuch.
+                */
+               xAnswer = XMLRPC_ServerCallMethod(server->server_ptr, xRequest, &data);
+               if (xAnswer && out.b_php_out) {
+                       XMLRPC_to_PHP(xAnswer, &data.return_data);
+               } else if (data.php_executed && !out.b_php_out && !xAnswer) {
+                       xAnswer = PHP_to_XMLRPC(&data.return_data TSRMLS_CC);
+               }
+
+               /* should we return data as xml? */
+               if (!out.b_php_out) {
+                       XMLRPC_REQUEST xResponse = XMLRPC_RequestNew();
+                       if (xResponse) {
+                               char *outBuf = 0;
+                               int buf_len = 0;
+
+                               /* automagically determine output serialization type from request type */
+                               if (out.b_auto_version) { 
+                                       XMLRPC_REQUEST_OUTPUT_OPTIONS opts = XMLRPC_RequestGetOutputOptions(xRequest);
+                                       if (opts) {
+                                               out.xmlrpc_out.version = opts->version;
                                        }
-                                       /* 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);
+                               /* 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_dtor(data.return_data);
-                       FREE_ZVAL(data.return_data);
-
-                       if (xAnswer) {
-                               XMLRPC_CleanupValue(xAnswer);
-                       }
+               /* cleanup after ourselves.  what a sty! */
+               zval_ptr_dtor(&data.xmlrpc_method);
+               zval_ptr_dtor(&data.return_data);
 
-                       XMLRPC_RequestFree(xRequest, 1);
+               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;
-
-                                               MAKE_STD_ZVAL(ztimestamp);
+                                               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;
        }