@@ -1383,12 +1383,11 @@ PHP_METHOD(SoapServer, handle)
13831383 sdlPtr old_sdl = NULL ;
13841384 soapServicePtr service ;
13851385 xmlDocPtr doc_request = NULL , doc_return = NULL ;
1386- zval function_name , * params , * soap_obj , retval ;
1386+ zval function_name , * params , retval ;
13871387 char cont_len [30 ];
13881388 uint32_t num_params = 0 ;
1389- int size , i , call_status = 0 ;
1389+ int size , i ;
13901390 xmlChar * buf ;
1391- HashTable * function_table ;
13921391 soapHeader * soap_headers = NULL ;
13931392 sdlFunctionPtr function ;
13941393 char * arg = NULL ;
@@ -1563,10 +1562,10 @@ PHP_METHOD(SoapServer, handle)
15631562
15641563 service -> soap_headers_ptr = & soap_headers ;
15651564
1566- soap_obj = NULL ;
1565+ zval * soap_obj = NULL ;
1566+ HashTable * function_table = NULL ;
15671567 if (service -> type == SOAP_OBJECT ) {
15681568 soap_obj = & service -> soap_object ;
1569- function_table = & ((Z_OBJCE_P (soap_obj ))-> function_table );
15701569 } else if (service -> type == SOAP_CLASS ) {
15711570 /* If persistent then set soap_obj from the previous created session (if available) */
15721571#ifdef SOAP_HAS_SESSION_SUPPORT
@@ -1590,7 +1589,7 @@ PHP_METHOD(SoapServer, handle)
15901589 }
15911590#endif
15921591
1593- /* If new session or something weird happned */
1592+ /* If new session or something weird happened */
15941593 if (soap_obj == NULL ) {
15951594 if (UNEXPECTED (object_init_ex (& tmp_soap , service -> soap_class .ce ) != SUCCESS )) {
15961595 php_output_discard ();
@@ -1628,7 +1627,6 @@ PHP_METHOD(SoapServer, handle)
16281627 soap_obj = & tmp_soap ;
16291628 }
16301629 }
1631- function_table = & ((Z_OBJCE_P (soap_obj ))-> function_table );
16321630 } else {
16331631 if (service -> soap_functions .functions_all ) {
16341632 function_table = EG (function_table );
@@ -1653,41 +1651,89 @@ PHP_METHOD(SoapServer, handle)
16531651 }
16541652 }
16551653#endif
1656- if (zend_hash_find_ptr_lc (function_table , Z_STR (h -> function_name )) != NULL ||
1657- ((service -> type == SOAP_CLASS || service -> type == SOAP_OBJECT ) &&
1658- zend_hash_str_exists (function_table , ZEND_CALL_FUNC_NAME , sizeof (ZEND_CALL_FUNC_NAME )- 1 ))) {
1659- call_status = call_user_function (NULL , soap_obj , & h -> function_name , & h -> retval , h -> num_params , h -> parameters );
1660- if (call_status != SUCCESS ) {
1661- php_error_docref (NULL , E_WARNING , "Function '%s' call failed" , Z_STRVAL (h -> function_name ));
1662- return ;
1654+ if (soap_obj ) {
1655+ /* This is because the object might define a __call() magic method */
1656+ zend_result method_call_result = zend_call_method_if_exists (
1657+ Z_OBJ_P (soap_obj ),
1658+ Z_STR (h -> function_name ),
1659+ & h -> retval ,
1660+ h -> num_params ,
1661+ h -> parameters
1662+ );
1663+ if (UNEXPECTED (method_call_result == FAILURE )) {
1664+ if (h -> mustUnderstand ) {
1665+ soap_server_fault_en ("MustUnderstand" ,"Header not understood" );
1666+ goto fail ;
1667+ }
1668+ ZVAL_NULL (& h -> retval );
1669+ continue ;
16631670 }
1664- if (Z_TYPE (h -> retval ) == IS_OBJECT &&
1665- instanceof_function (Z_OBJCE (h -> retval ), soap_fault_class_entry )) {
1666- php_output_discard ();
1667- soap_server_fault_ex (function , & h -> retval , h );
1668- soap_free_server_object (service , soap_obj );
1669- goto fail ;
1670- } else if (EG (exception )) {
1671- php_output_discard ();
1672- _soap_server_exception (service , function , ZEND_THIS );
1673- soap_free_server_object (service , soap_obj );
1674- goto fail ;
1671+ } else {
1672+ zend_function * header_fn = zend_hash_find_ptr_lc (function_table , Z_STR (h -> function_name ));
1673+ if (UNEXPECTED (header_fn == NULL )) {
1674+ if (h -> mustUnderstand ) {
1675+ soap_server_fault_en ("MustUnderstand" ,"Header not understood" );
1676+ goto fail ;
1677+ }
1678+ ZVAL_NULL (& h -> retval );
1679+ continue ;
16751680 }
1676- } else if (h -> mustUnderstand ) {
1677- soap_server_fault_en ("MustUnderstand" ,"Header not understood" );
1681+ zend_call_known_function (header_fn , NULL , NULL , & h -> retval , h -> num_params , h -> parameters , NULL );
1682+ }
1683+
1684+ if (Z_TYPE (h -> retval ) == IS_OBJECT &&
1685+ instanceof_function (Z_OBJCE (h -> retval ), soap_fault_class_entry )) {
1686+ php_output_discard ();
1687+ soap_server_fault_ex (function , & h -> retval , h );
1688+ soap_free_server_object (service , soap_obj );
1689+ goto fail ;
1690+ } else if (EG (exception )) {
1691+ php_output_discard ();
1692+ _soap_server_exception (service , function , ZEND_THIS );
1693+ soap_free_server_object (service , soap_obj );
1694+ goto fail ;
16781695 }
16791696 }
16801697 }
16811698
1682- if (zend_hash_find_ptr_lc (function_table , Z_STR (function_name )) != NULL ||
1683- ((service -> type == SOAP_CLASS || service -> type == SOAP_OBJECT ) &&
1684- zend_hash_str_exists (function_table , ZEND_CALL_FUNC_NAME , sizeof (ZEND_CALL_FUNC_NAME )- 1 ))) {
1685- call_status = call_user_function (NULL , soap_obj , & function_name , & retval , num_params , params );
1686- soap_free_server_object (service , soap_obj );
1699+ if (soap_obj ) {
1700+ char * error = NULL ;
1701+ /* This is because the object might define a __call() magic method */
1702+ zend_result method_call_result = zend_call_method_if_exists_ex (
1703+ Z_OBJ_P (soap_obj ),
1704+ Z_STR (function_name ),
1705+ & retval ,
1706+ num_params ,
1707+ params ,
1708+ NULL ,
1709+ & error
1710+ );
1711+ if (UNEXPECTED (method_call_result == FAILURE )) {
1712+ ZEND_ASSERT (error != NULL );
1713+ zend_throw_error (NULL , "Cannot call method %s::%s(): %s" ,
1714+ ZSTR_VAL (Z_OBJCE_P (soap_obj )-> name ),
1715+ Z_STRVAL (function_name ),
1716+ error
1717+ );
1718+ php_output_discard ();
1719+ _soap_server_exception (service , function , ZEND_THIS );
1720+ soap_free_server_object (service , soap_obj );
1721+ goto fail ;
1722+ }
16871723 } else {
1688- php_error (E_ERROR , "Function '%s' doesn't exist" , Z_STRVAL (function_name ));
1724+ zend_function * fn = zend_hash_find_ptr_lc (function_table , Z_STR (function_name ));
1725+ if (UNEXPECTED (fn == NULL )) {
1726+ zend_throw_error (NULL , "Call to undefined function %s()" , Z_STRVAL (function_name ));
1727+ php_output_discard ();
1728+ _soap_server_exception (service , function , ZEND_THIS );
1729+ soap_free_server_object (service , soap_obj );
1730+ goto fail ;
1731+ }
1732+ zend_call_known_function (fn , NULL , NULL , & retval , num_params , params , NULL );
16891733 }
16901734
1735+ soap_free_server_object (service , soap_obj );
1736+
16911737 if (EG (exception )) {
16921738 if (!zend_is_unwind_exit (EG (exception ))) {
16931739 php_output_discard ();
@@ -1697,32 +1743,27 @@ PHP_METHOD(SoapServer, handle)
16971743 goto fail ;
16981744 }
16991745
1700- if (call_status == SUCCESS ) {
1701- char * response_name ;
1746+ char * response_name ;
17021747
1703- if (Z_TYPE (retval ) == IS_OBJECT &&
1704- instanceof_function (Z_OBJCE (retval ), soap_fault_class_entry )) {
1705- php_output_discard ();
1706- soap_server_fault_ex (function , & retval , NULL );
1707- goto fail ;
1708- }
1709-
1710- bool has_response_name = function && function -> responseName ;
1711- if (has_response_name ) {
1712- response_name = function -> responseName ;
1713- } else {
1714- response_name = emalloc (Z_STRLEN (function_name ) + sizeof ("Response" ));
1715- memcpy (response_name ,Z_STRVAL (function_name ),Z_STRLEN (function_name ));
1716- memcpy (response_name + Z_STRLEN (function_name ),"Response" ,sizeof ("Response" ));
1717- }
1718- doc_return = serialize_response_call (function , response_name , service -> uri , & retval , soap_headers , soap_version );
1748+ if (Z_TYPE (retval ) == IS_OBJECT &&
1749+ instanceof_function (Z_OBJCE (retval ), soap_fault_class_entry )) {
1750+ php_output_discard ();
1751+ soap_server_fault_ex (function , & retval , NULL );
1752+ goto fail ;
1753+ }
17191754
1720- if (! has_response_name ) {
1721- efree ( response_name );
1722- }
1755+ bool has_response_name = function && function -> responseName ;
1756+ if ( has_response_name ) {
1757+ response_name = function -> responseName ;
17231758 } else {
1724- php_error_docref (NULL , E_WARNING , "Function '%s' call failed" , Z_STRVAL (function_name ));
1725- return ;
1759+ response_name = emalloc (Z_STRLEN (function_name ) + sizeof ("Response" ));
1760+ memcpy (response_name ,Z_STRVAL (function_name ),Z_STRLEN (function_name ));
1761+ memcpy (response_name + Z_STRLEN (function_name ),"Response" ,sizeof ("Response" ));
1762+ }
1763+ doc_return = serialize_response_call (function , response_name , service -> uri , & retval , soap_headers , soap_version );
1764+
1765+ if (!has_response_name ) {
1766+ efree (response_name );
17261767 }
17271768
17281769 if (EG (exception )) {
0 commit comments