@@ -1374,12 +1374,11 @@ PHP_METHOD(SoapServer, handle)
13741374 sdlPtr old_sdl = NULL ;
13751375 soapServicePtr service ;
13761376 xmlDocPtr doc_request = NULL , doc_return = NULL ;
1377- zval function_name , * params , * soap_obj , retval ;
1377+ zval function_name , * params , retval ;
13781378 char cont_len [30 ];
13791379 uint32_t num_params = 0 ;
1380- int size , i , call_status = 0 ;
1380+ int size , i ;
13811381 xmlChar * buf ;
1382- HashTable * function_table ;
13831382 soapHeader * soap_headers = NULL ;
13841383 sdlFunctionPtr function ;
13851384 char * arg = NULL ;
@@ -1554,10 +1553,10 @@ PHP_METHOD(SoapServer, handle)
15541553
15551554 service -> soap_headers_ptr = & soap_headers ;
15561555
1557- soap_obj = NULL ;
1556+ zval * soap_obj = NULL ;
1557+ HashTable * function_table = NULL ;
15581558 if (service -> type == SOAP_OBJECT ) {
15591559 soap_obj = & service -> soap_object ;
1560- function_table = & ((Z_OBJCE_P (soap_obj ))-> function_table );
15611560 } else if (service -> type == SOAP_CLASS ) {
15621561 /* If persistent then set soap_obj from the previous created session (if available) */
15631562#ifdef SOAP_HAS_SESSION_SUPPORT
@@ -1581,7 +1580,7 @@ PHP_METHOD(SoapServer, handle)
15811580 }
15821581#endif
15831582
1584- /* If new session or something weird happned */
1583+ /* If new session or something weird happened */
15851584 if (soap_obj == NULL ) {
15861585 if (UNEXPECTED (object_init_ex (& tmp_soap , service -> soap_class .ce ) != SUCCESS )) {
15871586 php_output_discard ();
@@ -1619,7 +1618,6 @@ PHP_METHOD(SoapServer, handle)
16191618 soap_obj = & tmp_soap ;
16201619 }
16211620 }
1622- function_table = & ((Z_OBJCE_P (soap_obj ))-> function_table );
16231621 } else {
16241622 if (service -> soap_functions .functions_all ) {
16251623 function_table = EG (function_table );
@@ -1644,52 +1642,72 @@ PHP_METHOD(SoapServer, handle)
16441642 }
16451643 }
16461644#endif
1647- if (zend_hash_find_ptr_lc (function_table , Z_STR (h -> function_name )) != NULL ||
1648- ((service -> type == SOAP_CLASS || service -> type == SOAP_OBJECT ) &&
1649- zend_hash_str_exists (function_table , ZEND_CALL_FUNC_NAME , sizeof (ZEND_CALL_FUNC_NAME )- 1 ))) {
1650- call_status = call_user_function (NULL , soap_obj , & h -> function_name , & h -> retval , h -> num_params , h -> parameters );
1651- if (call_status != SUCCESS ) {
1652- php_error_docref (NULL , E_WARNING , "Function '%s' call failed" , Z_STRVAL (h -> function_name ));
1653- return ;
1654- }
1655- if (Z_TYPE (h -> retval ) == IS_OBJECT &&
1656- instanceof_function (Z_OBJCE (h -> retval ), soap_fault_class_entry )) {
1657- php_output_discard ();
1658- soap_server_fault_ex (function , & h -> retval , h );
1659- if (service -> type == SOAP_CLASS && soap_obj ) {
1660- if (service -> soap_class .persistence != SOAP_PERSISTENCE_SESSION ) {
1661- zval_ptr_dtor (soap_obj );
1662- }
1645+
1646+ if (soap_obj ) {
1647+ /* This is because the object might define a __call() magic method */
1648+ zend_result method_call_result = zend_call_method_if_exists (Z_OBJ_P (soap_obj ), Z_STR (h -> function_name ), & h -> retval , h -> num_params , h -> parameters );
1649+ if (UNEXPECTED (method_call_result == FAILURE )) {
1650+ if (h -> mustUnderstand ) {
1651+ soap_server_fault_en ("MustUnderstand" ,"Header not understood" );
1652+ goto fail ;
16631653 }
1664- goto fail ;
1665- } else if ( EG ( exception )) {
1666- php_output_discard ();
1667- _soap_server_exception ( service , function , ZEND_THIS );
1668- if (service -> type == SOAP_CLASS && soap_obj ) {
1669- if (service -> soap_class . persistence != SOAP_PERSISTENCE_SESSION ) {
1670- zval_ptr_dtor ( soap_obj );
1671- }
1654+ continue ;
1655+ }
1656+ } else {
1657+ zend_function * header_fn = zend_hash_find_ptr_lc ( function_table , Z_STR ( h -> function_name ) );
1658+ if (UNEXPECTED ( header_fn == NULL ) ) {
1659+ if (h -> mustUnderstand ) {
1660+ soap_server_fault_en ( "MustUnderstand" , "Header not understood" );
1661+ goto fail ;
16721662 }
1673- goto fail ;
1663+ continue ;
16741664 }
1675- } else if (h -> mustUnderstand ) {
1676- soap_server_fault_en ("MustUnderstand" ,"Header not understood" );
1665+ zend_call_known_function (header_fn , NULL , NULL , & h -> retval , h -> num_params , h -> parameters , NULL );
1666+ }
1667+
1668+ if (Z_TYPE (h -> retval ) == IS_OBJECT &&
1669+ instanceof_function (Z_OBJCE (h -> retval ), soap_fault_class_entry )) {
1670+ php_output_discard ();
1671+ soap_server_fault_ex (function , & h -> retval , h );
1672+ if (service -> type == SOAP_CLASS && soap_obj ) {zval_ptr_dtor (soap_obj );}
1673+ goto fail ;
1674+ } else if (EG (exception )) {
1675+ php_output_discard ();
1676+ _soap_server_exception (service , function , ZEND_THIS );
1677+ if (service -> type == SOAP_CLASS && soap_obj ) {zval_ptr_dtor (soap_obj );}
1678+ goto fail ;
16771679 }
16781680 }
16791681 }
16801682
1681- if (zend_hash_find_ptr_lc (function_table , Z_STR (function_name )) != NULL ||
1682- ((service -> type == SOAP_CLASS || service -> type == SOAP_OBJECT ) &&
1683- zend_hash_str_exists (function_table , ZEND_CALL_FUNC_NAME , sizeof (ZEND_CALL_FUNC_NAME )- 1 ))) {
1684- call_status = call_user_function (NULL , soap_obj , & function_name , & retval , num_params , params );
1685- if (service -> type == SOAP_CLASS ) {
1686- if (service -> soap_class .persistence != SOAP_PERSISTENCE_SESSION ) {
1683+ if (soap_obj ) {
1684+ /* This is because the object might define a __call() magic method */
1685+ zend_result method_call_result = zend_call_method_if_exists (Z_OBJ_P (soap_obj ), Z_STR (function_name ), & retval , num_params , params );
1686+ if (UNEXPECTED (method_call_result == FAILURE )) {
1687+ zend_throw_error (NULL , "Call to undefined method %s::%s()" , ZSTR_VAL (Z_OBJCE_P (soap_obj )-> name ), Z_STRVAL (function_name ));
1688+ php_output_discard ();
1689+ _soap_server_exception (service , function , ZEND_THIS );
1690+ if (service -> type == SOAP_CLASS ) {
16871691 zval_ptr_dtor (soap_obj );
1688- soap_obj = NULL ;
16891692 }
1693+ goto fail ;
16901694 }
16911695 } else {
1692- php_error (E_ERROR , "Function '%s' doesn't exist" , Z_STRVAL (function_name ));
1696+ zend_function * fn = zend_hash_find_ptr_lc (function_table , Z_STR (function_name ));
1697+ if (UNEXPECTED (fn == NULL )) {
1698+ zend_throw_error (NULL , "Call to undefined function %s()" , Z_STRVAL (function_name ));
1699+ php_output_discard ();
1700+ _soap_server_exception (service , function , ZEND_THIS );
1701+ goto fail ;
1702+ }
1703+ zend_call_known_function (fn , NULL , NULL , & retval , num_params , params , NULL );
1704+ }
1705+
1706+ if (service -> type == SOAP_CLASS ) {
1707+ if (service -> soap_class .persistence != SOAP_PERSISTENCE_SESSION ) {
1708+ zval_ptr_dtor (soap_obj );
1709+ soap_obj = NULL ;
1710+ }
16931711 }
16941712
16951713 if (EG (exception )) {
@@ -1705,32 +1723,27 @@ PHP_METHOD(SoapServer, handle)
17051723 goto fail ;
17061724 }
17071725
1708- if (call_status == SUCCESS ) {
1709- char * response_name ;
1726+ char * response_name ;
17101727
1711- if (Z_TYPE (retval ) == IS_OBJECT &&
1712- instanceof_function (Z_OBJCE (retval ), soap_fault_class_entry )) {
1713- php_output_discard ();
1714- soap_server_fault_ex (function , & retval , NULL );
1715- goto fail ;
1716- }
1717-
1718- bool has_response_name = function && function -> responseName ;
1719- if (has_response_name ) {
1720- response_name = function -> responseName ;
1721- } else {
1722- response_name = emalloc (Z_STRLEN (function_name ) + sizeof ("Response" ));
1723- memcpy (response_name ,Z_STRVAL (function_name ),Z_STRLEN (function_name ));
1724- memcpy (response_name + Z_STRLEN (function_name ),"Response" ,sizeof ("Response" ));
1725- }
1726- doc_return = serialize_response_call (function , response_name , service -> uri , & retval , soap_headers , soap_version );
1728+ if (Z_TYPE (retval ) == IS_OBJECT &&
1729+ instanceof_function (Z_OBJCE (retval ), soap_fault_class_entry )) {
1730+ php_output_discard ();
1731+ soap_server_fault_ex (function , & retval , NULL );
1732+ goto fail ;
1733+ }
17271734
1728- if (! has_response_name ) {
1729- efree ( response_name );
1730- }
1735+ bool has_response_name = function && function -> responseName ;
1736+ if ( has_response_name ) {
1737+ response_name = function -> responseName ;
17311738 } else {
1732- php_error_docref (NULL , E_WARNING , "Function '%s' call failed" , Z_STRVAL (function_name ));
1733- return ;
1739+ response_name = emalloc (Z_STRLEN (function_name ) + sizeof ("Response" ));
1740+ memcpy (response_name ,Z_STRVAL (function_name ),Z_STRLEN (function_name ));
1741+ memcpy (response_name + Z_STRLEN (function_name ),"Response" ,sizeof ("Response" ));
1742+ }
1743+ doc_return = serialize_response_call (function , response_name , service -> uri , & retval , soap_headers , soap_version );
1744+
1745+ if (!has_response_name ) {
1746+ efree (response_name );
17341747 }
17351748
17361749 if (EG (exception )) {
0 commit comments