Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.5.5

Bug #1604 'Unknow method' when xml is on one line
Submitted: 2004-06-10 13:03 UTC
From: sebastien dot person at easter-eggs dot com Assigned: toby
Status: Closed Package: XML_RPC
PHP Version: 4.3.4 OS: linux
Roadmaps: (Not assigned)    

 [2004-06-10 13:03 UTC] sebastien dot person at easter-eggs dot com
Description: ------------ XML_RPC 1.1.0 stable PEAR 1.3.1 stable I'm trying to access a WS created with pear XML_RPC and I get an 'unknown method' but the method exist. If the xml of the WS call, is on multiple line it works, but when all the xml stuff is on single line the method name is not found. I test it with several perl clients. Some works, other doesn't and the difference is in the xml file (one lines or multiples lines) Here's the modification I made to solve the problem : --- Server.php Thu Jun 10 15:01:03 2004 +++ Server.php.orig Thu Jun 10 15:00:20 2004 @@ -241,7 +241,6 @@ xml_set_element_handler($parser, "XML_RPC_se", "XML_RPC_ee"); xml_set_character_data_handler($parser, "XML_RPC_cd"); xml_set_default_handler($parser, "XML_RPC_dh"); - $data = str_replace( '><', ">\n<", $data); // if the if (!xml_parse($parser, $data, 1)) { // return XML error as a faultCode $r = new XML_RPC_Response(0, Reproduce code: --------------- SOAP::Transport::HTTP::Client::send_receive: POST http://localhost/~seb/ws/calc.php HTTP/1.1 Accept: text/xml Accept: multipart/* Content-Length: 197 Content-Type: text/xml <?xml version="1.0" encoding="UTF-8"?><methodCall><methodName>calc.add</methodName><params><param><value><int>1</int></value></param><param><value><int>3</int></value></param></params></methodCall> Expected result: ---------------- <methodResponse> <params> <param> <value><int>4</int></value> </param> </params> </methodResponse> Actual result: -------------- <methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value><int>1</int></value> </member> <member> <name>faultString</name> <value><string>Unknown method</string></value> </member> </struct> </value> </fault> </methodResponse>


 [2004-06-10 13:06 UTC] sebastien dot person at easter-eggs dot com
little mistake, the line must be added not removed. $data = str_replace( '><', ">\n<", $data);
 [2004-07-29 08:48 UTC] justin at jphil dot net
By using the patch mentioned here by Sebastien which forces the XML onto separate lines I have been able to follow the code execution when a method is called correctly, in contrast to when it throws "Unknown method" (where the XML is on one line). The differences between the two executions are as follows: ################### Firstly, here's what happens when execution results in "Unknown method" due to XML being on one line. In PEAR/XML/RPC.php - During parsing of the raw POST data sent to the XML RPC server, when the end element handler XML_RPC_ee is called with $name = "METHODNAME", the case statement on line 319 is fired. This statement sets $XML_RPC_xh[$parser]['method'] with the method name from the $XML_RPC_xh[$parser]['ac'] with some character replacement. Now, in this case, where we end up with "Unknown method", I found $XML_RPC_xh[$parser]['ac'] to be == "" ... so I then went to see where $XML_RPC_xh[$parser]['ac'] is set and found that it's in XML_RPC_cd and XML_RPC_dh. Function XML_RPC_cd takes $data as a param. So I started to debug this function and caught all the values for $data that were getting passed through. I found that my method name DOES actually get passed through, but never makes it into $XML_RPC_xh[$parser]['ac']. The code that prevents $XML_RPC_xh[$parser]['ac'] being set with $data (after some string replacement calls) is the following on line PEAR/XML/RPC.php 364: if (isset($XML_RPC_xh[$parser]['ac'])) { because isset($XML_RPC_xh[$parser]['ac'])==false . With that in mind now lets consider the other case where the call DOES work (i.e. the XML is on separate lines) ################### Again in PEAR/XML/RPC.php - The raw POST data is parsed, XML_RPC_ee is called with $name = "METHODNAME", the case statement on line 319 fires and this time $XML_RPC_xh[$parser]['ac'] actually contains the method name, so we get a valid $XML_RPC_xh[$parser]['method'] ! Now that's all and good, however if we go back to XML_RPC_cd where $XML_RPC_xh[$parser]['ac'] gets set, lets see why. As before XML_RPC_cd is called with $data various times during parsing. The first time it is called, $data is a line break (in my case - see XML in the message at the bottom). Execution moves down to line 364 but gets kicked to the else (line 368) cause isset($XML_RPC_xh[$parser]['ac'])==false . BUT ! Now in the else it gets set to '' empty string, so isset(...)==true!!!!! Now, next time XML_RPC_cd is called (with $data as my method name) because isset($XML_RPC_xh[$parser]['ac'])==true it follows that $XML_RPC_xh[$parser]['ac'] gets assigned with $data within the condition. So the method name gets through only because $XML_RPC_xh[$parser]['ac'] gets set by the line break data!!! So that why lines breaks are required! The code breaks when XML is only on one line because the first char data encountered is the method name which doesn't get assigned to $XML_RPC_xh[$parser]['ac'] because isset($XML_RPC_xh[$parser]['ac'])==false !!! HOWEVER the rest of the char data IS picked up because from then on isset($XML_RPC_xh[$parser]['ac'])==true !!! So in other words the code needs line breaks to trigger the lucky error: I think that line 364 of PEAR/XML/RPC.php: if (isset($XML_RPC_xh[$parser]['ac'])) { should be replaced with if (isset($data)) { because surely we want to assign data to $XML_RPC_xh[$parser]['ac'] if there is any to assign, not based on whether there is any there already? Thoughts??
 [2004-07-30 10:11 UTC] justin at jphil dot net
Just as a note. This bug states the relevant PHP version as 4.3.4. The bug is also in evidence in v.5.0.1 dev Build Date Jul 26 2004 10:14:07 and my fix is for this version (and possibly several prior versions inc. 4.3.4)
 [2004-08-12 06:37 UTC] christian at wenz dot org
I think both PHP version and OS are irrelevant :-)
 [2004-09-23 19:24 UTC] buschfunk at yahoo dot com
Hi, Justin's fix works for me, I use the org.apache.xmlrpc Java package. Boy, I searched for errors in my code for 3 days, so please put out a bugfix release qickly! *g* However, the following code should be inserted before his fix to avoid PHP notices (that would destroy the XML output): if( !array_key_exists('ac', $XML_RPC_xh[$parser]) ) { $XML_RPC_xh[$parser]['ac'] = ''; } Now it works even with high errorlevel. Michael
 [2004-10-08 20:49 UTC] lars dot berntzon at cecilia-data dot se
I made following patch to the RPC.php file. It resets the parser[ac] entry when the start element <methodname>. there by the method name will be picked up when handling </methodname> *** RPC.php 2004-10-08 22:37:21.000000000 +0200 --- 2004-10-08 22:19:04.000000000 +0200 *************** *** 170,179 **** $XML_RPC_xh[$parser]['st'] = ""; break; - case "METHODNAME": - $XML_RPC_xh[$parser]['ac'] = ""; - break; - case "VALUE": $XML_RPC_xh[$parser]['st'] .= "new XML_RPC_Value("; $XML_RPC_xh[$parser]['lv'] = 1; --- 170,175 ----
 [2004-11-29 20:02 UTC] toby
This bug seems to be resolved in CVS. Thanks to Jan Jonas <> for information.