diff options
author | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2005-07-05 15:02:04 +0000 |
---|---|---|
committer | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2005-07-05 15:02:04 +0000 |
commit | 17ab54d284c6d82f96a5543fa5b5f8ee65e20307 (patch) | |
tree | ddee86b055667bed94e73dad8f105101415fa217 /modules/xmlrpc | |
parent | 224f007c59eab093bea69eb227faa64104ed4e15 (diff) | |
download | ampache-17ab54d284c6d82f96a5543fa5b5f8ee65e20307.tar.gz ampache-17ab54d284c6d82f96a5543fa5b5f8ee65e20307.tar.bz2 ampache-17ab54d284c6d82f96a5543fa5b5f8ee65e20307.zip |
updated xmlrpc library
Diffstat (limited to 'modules/xmlrpc')
-rw-r--r-- | modules/xmlrpc/ChangeLog | 267 | ||||
-rw-r--r-- | modules/xmlrpc/doc/index.html | 459 | ||||
-rwxr-xr-x | modules/xmlrpc/xmlrpc.inc | 794 | ||||
-rwxr-xr-x | modules/xmlrpc/xmlrpcs.inc | 61 |
4 files changed, 989 insertions, 592 deletions
diff --git a/modules/xmlrpc/ChangeLog b/modules/xmlrpc/ChangeLog index 05cf571e..f24bf866 100644 --- a/modules/xmlrpc/ChangeLog +++ b/modules/xmlrpc/ChangeLog @@ -1,3 +1,268 @@ +2005-06-28 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpcs.inc: fixed security vulnerability (PHP code injection) in handling of + BASE64 vals and NAME tags + + * xmlrpc.inc, xmlrpcs.inc: catch errors in evaluated PHP code and return an + error to the calling code in case any are found + + * testsuite.php: added a test case for caling methods without params, plus + a couple to test the code injection fixes + + * bumped up rev number and released as 1.1.1 + +2005-04-24 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpcs.inc: removed charset declaration from xml prologue of responses, + since we are now escaping all non-ascii chars in an encoding-independent way + + * bug_http.xml: modified to exercise some extra functonality of the lib + (it should now be failed by the current PEAR implementation of the lib) + + * xmlrpc.inc: bumped up rev. number to 1.1 + + * doc/xmlrpc_php.xml, doc/announce1_1.txt: documentation updates + + * Makefile: updated to reflect new xml doc source, modified filelist + +2005-04-17 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * client.php, agesort.php, introspect.php, introspect_demo.php, + which.php, test.pl, test.py: use as default target the server.php page hosted + on phpxmlrpc.sf.net + + * server.php: fix for register_globals off; refer to docs on phpxmlrpc.sf.net + +2005-04-15 Miles Lott <milos@groupwhere.org> + + code formatting and comments + +2005-04-03 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: make use of global var $xmlrpcName in building User_Agent HTTP + header (in conjunction with $xmlrpcVersion) + + * agesort.php, client.php, comment.php, dicuss.php, mail.php, server.php, + which.php: various janitorial fixes + + always html escape content received from xmlrpc server or from user input + + make the scripts run fine with register_globals off an register_long_arrays off + + always use the functions php_xmlrpc_en(de)code, even if the EPI extension + is not installed + + in mail.php, allow user to see script source even if support for .phps files + is not configured in the local web server + + * testsuite.php: better detection of local webserver hostname for running tests + against (if the user did not supply a webserver name) + +2005-03-21 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpcs.inc: revert to a PHP3 compatible script (change '=& new' to '= new') + + * xmlrpc.inc: revert to a PHP3 compatible script (lottsa fixes) + + * testsuite.php: default to using local server as test target if no user + provided values are available instead of heddley.com server + + * testsuite.php: play nice to PHP3 in retrieving user-passed values + + * testsuite.php: fix constructor method name for a type of tests + + * phpunit.php: fix all cases of call-time-pass-by-ref + + * phpunit.php: rename Exception class to _Exception if the script is run with + PHP 5 (exception is a reserverd word) + +2005-03-19 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: fixed bug in new http header parsing code in case there is + no correct separator between response headers and body + + * xmlrpc.inc: added recognizing and stripping of HTTP/1.1 100 response headers + + * xmlrpc.inc: strip extra whitespace from response body, as well as any junk + that comes after the last </MethodResponse> tag. It allows the server code to + be put on public providers that add e.g. javascript advertising to served pages + + * xmlrpc.inc: removed unused parts of code, trailing whitespace + + * xmlrpc.inc: fix possible bug (?) in xmlrpc_ee for BOOLEAN values: true was + being handled differently than false + + * testsuite.php: added a new file-based test to stress the response parsing + modifications recently introduced; enabled debugging for file based tests + +2005-03-15 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: fixed missing declaration of global vars in xmlrpc_dh, + sendpayloadhttps and sendpayloadhttp10 + + * xmlrpc.inc: changed error message for invalid responses: 'enable debugging' + is more clear that 'enabling debugging' (the user is being encouraged to do it) + + * xmlrpc.inc: rewrote HTTP response header parsing. It should be more tolerant + of invalid headers, give more accurate error messages and be marginally faster, + too. + + * xmlrpc.inc: cosmetic whitespace fixes and remove useless one-liners + + * xmlrpc.inc: build a shorter PHP command line to be evaluated for rebuilding + values from parsed xml: use '$val =& nex xmlrpcval("value")' for string values + instead of '$val =& nex xmlrpcval("value", $xmlrpcString)' + + * xmlrpc.inc: fix change introduced 2005/01/30 moving call to curl_close() + too early: it did not work on error situations + + * testsuite.php: fix name of testAddingTest method, renamed testErrosString + into testErrorString and removed useless warning for register_globals=off case + +2005-02-27 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: do not echo XML parsing error to screen (it is already dumped + into error log) + + * xmlrpc.inc: set hdrs field into response object in case of XML parsing error + (uniform behaviour with other responses) + +2005-02-26 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: use global var $xmlrpcVersion as number for user agent string + + * xmlrpcs.inc: eliminate server side PHP wanring and give back to caller + a better error msg in case the called method exists but no signature matches + the number of parameters + +2005-02-20 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: accept a + sign in front of floats / integers, since the spec + clearly mentions it + + * xmlrpc.inc, xmlrpcs.inc: renamed function XmlEntities to xmlrpc_encode_entitites, + to avoid using the same name as an array already defined + + * xmlrpc.inc: fix bug introduced with escaping of UTF8 chars in xmlrpc error + responses: correct behaviour is to escape chars inside serialize(), not when + calling the xmlrpcresp creator + + * testsuite.php: made test suite more friendly to modern PHP configs, allowing + register_globals to be off and to set in the URL all testing parameters; + added tests for newly introduced fixes; renamed existing tests acording to the + docs inside phpunit.php (e.g. no subclass of TestCase should have a name + starting with test...) + +2005-02-19 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: accept patch 683153 by mah0: if timeout is set, allow all socket + operations to timeout at the given time, not only the socket connection + +2005-02-13 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: be tolerant to double values received in exponential notation: + even though the spec forbids their usage PHP is fine with them + + * xmlrpc.inc: fix bug: new xmlrpcval('-1') was creating an empty value instead + of a string value! + + * xmlrpc.inc, xmlrpcs.inc: fix the payload encoding changes introduced by + Andres Salomon on 2004-03-17: sending named html entities inside an xml chunk + makes it invalid, and thus renders the lib absolutely non-interoperable with + any other xmlrpc implementation; moreover the current implementation only ever + worked for non-ascii requests, while breaking client-parsing of responses + containing non-ascii chars. + The principle of using entities is preserved though, because it allows the + client to send correct xml regardless of php internal charset encoding vs. + xml request charset encoding, but using 'character references' instead. + + * xmlrpc.inc: encode (non-ascii) chars into charset entities also for error + strings + + * xmlrpcs.inc: encode (non-ascii) chars into charset entities also for debug + messages + + * xmlrpcs.inc: added 'Accept-Charset' header in http request to let the server + know what kind of charset encoding we do expect to be used for responses + + * xmlrpc.inc, xmlrpcs.inc: explicitly tell the xml parser what charset the + application expects to receive content in (notably strings). A new variable, + $xmlrpc_internalencoding, (defaulting to ISO-8859-1) defines what charset the + parser will use for passing back string xmlrpcvals to the PHP application + (both server-side and client-side). + This allows transparent usage of e.g. UTF-8 for encoding xml messages between + server and client and ISO-8859-1 for internal string handling. + ISO-8859-1 is, AFAIK, PHP internal encoding for all installs except + mbstring-enabled ones. + +2005-02-12 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpcs.inc: use '$var =& new(' construct to assign objects: on older versions + of PHP objects are first built then copied over if the ampersand is omitted. + Using it should make the code a little bit faster... + + * doc/xmlrpc.php: update lib version number, release date in preparation for + next release + + * makefile: update lib version number in preparation for next release + + * xmlrpc.inc: split up parsing of xmlrpc INT and DOUBLE values. This allows + finer-grained control over valid values: now the '.' char is not allowed + any more inside int values. + + * xmlrpc.inc: fix for bug #560303: ints and doubles starting with '0' chars are + no more parsed as octal values + +2005-01-30 Gaetano Giunta <giunta.gaetano@sea-aeroportimilano.it> + + * xmlrpc.inc: Modifed last change by Miles: the functions php_xmlrpc_encode + and php_xmlrpc_decode are now always defined, regardless of the existence of + XMLRPC-EPI. This allows users to start using these functions as the 'default' + functions, and pave the way for future deprecation of xmlrpc_encode/encode + while maintaining a stable API. + + * xmlrpc.inc: use '$var =& new(' construct to assign objects: on older versions + of PHP objects are first built then copied over if the ampersand is omitted. + Using it should make the code a little bit faster... + + * xmlrpc.inc: close curl connection as soon as possible for https requests: + it could save some memory / resources. + + * xmlrpc.inc: added some extra info in the PHP error log message generated + when an invalid xmlrpc integer/float value is encountered and we try to + deserialize it. + + * xmlrpc.inc: added @ char before fsockopen to avoid echoing useless warnings + when connection to server fails; added the same to avoid echoing warnings when + deserializing data of an unknown type + + * xmlrpc.inc: reset the _xh array on each xmlrpc call: otherwise a new array + member is created for each consecutive call and never destroyed, thus making it + impossible to build an xmlrpc-client daemon beacuse of memory leaking. + + * xmlrpc.inc: declare global the variables that are used as 'constants', + so that xmlrpc.inc will work even if it is included from within a function + +2004-12-27 Miles Lott <milos@groupwhere.org> + * xmlrpc.inc: A new constant, XMLRPC_EPI_ENABLED, is defined depending on + the existence of the function, xmlrpc_decode. This function will exist in + PHP if the extension, XMLRPC-EPI (http://xmlrpc-epi.sourceforge.net), is + loaded. It defines the functions xmlrpc_encode and xmlrpc_decode, which + will conflict with functions of the same name in xmlrpc.inc. If this + extension is loaded, we instead use the names php_xmlrpc_encode and + php_xmlrpc_decode. Please look at server.php, testsuite.php, etc., for + how this should be handled if using these functions. + +2003-04-17 Andres Salomon <dilinger@voxel.net> + * xmlrpc.inc: encode strings using htmlentities() instead of + htmlspecialchars(), and add xmlrpc_html_entity_xlate(). This + should fix longstanding issues with sending weird chars (from + non-USASCII codesets like UTF-8, ISO-8859-1, etc) that caused + the xml parser to choke. Multi-byte chars are now changed to + entities before sending, so that the xmlrpc server doesn't need + to know the encoding type of the POST data. + * xmlrpcs.inc: call xmlrpc_html_entity_xlate before parsing + request packet. The parser chokes on unknown entities (the + entities created by htmlentities() are exactly that; html + entities, not xml entities), so they must be converted from + name form (é) to numerical form (é). + 2003-01-12 Andres Salomon <dilinger@voxel.net> * released 1.0.99.2. @@ -260,4 +525,4 @@ * Fixed bugs in the XML parsing and reworked it -$Id: ChangeLog,v 1.12 2003/01/13 08:34:18 dilinger Exp $ +$Id: ChangeLog,v 1.26 2005/04/24 18:32:22 ggiunta Exp $ diff --git a/modules/xmlrpc/doc/index.html b/modules/xmlrpc/doc/index.html index 6e91b313..f2cb5762 100644 --- a/modules/xmlrpc/doc/index.html +++ b/modules/xmlrpc/doc/index.html @@ -1,453 +1,6 @@ -<HTML -><HEAD -><TITLE ->XML-RPC for PHP</TITLE -><META -NAME="GENERATOR" -CONTENT="Modular DocBook HTML Stylesheet Version 1.77+"><LINK -REV="MADE" -HREF="edd@usefulinc.com"><LINK -REL="NEXT" -TITLE="Introduction" -HREF="introduction.html"></HEAD -><BODY -CLASS="BOOK" -BGCOLOR="#FFFFFF" -TEXT="#000000" -LINK="#0000FF" -VLINK="#840084" -ALINK="#0000FF" -><DIV -CLASS="BOOK" -><A -NAME="AEN1" -></A -><DIV -CLASS="TITLEPAGE" -><H1 -CLASS="TITLE" -><A -NAME="AEN2" -></A ->XML-RPC for PHP</H1 -><H2 -CLASS="SUBTITLE" ->version 1.1</H2 -><H3 -CLASS="AUTHOR" -><A -NAME="AEN7" -></A ->Edd Dumbill</H3 -><DIV -CLASS="AFFILIATION" -><SPAN -CLASS="ORGNAME" -><A -HREF="http://usefulinc.com/" -TARGET="_top" ->Useful - Information Company</A -><BR></SPAN -><DIV -CLASS="ADDRESS" -><P -CLASS="ADDRESS" -> <TT -CLASS="EMAIL" -><<A -HREF="mailto:edd@usefulinc.com" ->edd@usefulinc.com</A ->></TT -><br> - </P -></DIV -></DIV -><P -CLASS="COPYRIGHT" ->Copyright © 1999,2000,2001 Edd Dumbill, Useful Information Company</P -><DIV -CLASS="LEGALNOTICE" -><A -NAME="AEN18" -></A -><P -></P -><P -> All rights reserved. - </P -><P -> Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - </P -><P -> <P -></P -><UL -><LI -><P -> Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - </P -></LI -><LI -><P -> Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - </P -></LI -><LI -><P -> Neither the name of the "XML-RPC for PHP" nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - </P -></LI -></UL -> - </P -><P -> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - OF SUCH DAMAGE.</P -><P -></P -></DIV -><HR></DIV -><DIV -CLASS="TOC" -><DL -><DT -><B ->Table of Contents</B -></DT -><DT ->1. <A -HREF="introduction.html" ->Introduction</A -></DT -><DD -><DL -><DT -><A -HREF="introduction.html#AEN43" ->Acknowledgements</A -></DT -></DL -></DD -><DT ->2. <A -HREF="manifest.html" ->Files in the distribution</A -></DT -><DT ->3. <A -HREF="bugs.html" ->Bugs</A -></DT -><DT ->4. <A -HREF="support.html" ->Support</A -></DT -><DD -><DL -><DT -><A -HREF="support.html#AEN146" ->Online Support</A -></DT -><DT -><A -HREF="jellyfish.html" ->The Jellyfish Book</A -></DT -></DL -></DD -><DT ->5. <A -HREF="apidocs.html" ->Class documentation</A -></DT -><DD -><DL -><DT -><A -HREF="apidocs.html#XMLRPC-CLIENT" ->xmlrpc_client</A -></DT -><DD -><DL -><DT -><A -HREF="apidocs.html#AEN174" ->Creation</A -></DT -><DT -><A -HREF="apidocs.html#AEN191" ->Methods</A -></DT -></DL -></DD -><DT -><A -HREF="xmlrpcmsg.html" ->xmlrpcmsg</A -></DT -><DD -><DL -><DT -><A -HREF="xmlrpcmsg.html#AEN289" ->Creation</A -></DT -><DT -><A -HREF="xmlrpcmsg.html#AEN309" ->Methods</A -></DT -></DL -></DD -><DT -><A -HREF="xmlrpcresp.html" ->xmlrpcresp</A -></DT -><DD -><DL -><DT -><A -HREF="xmlrpcresp.html#AEN386" ->Creation</A -></DT -><DT -><A -HREF="xmlrpcresp.html#AEN408" ->Methods</A -></DT -></DL -></DD -><DT -><A -HREF="xmlrpcval.html" ->xmlrpcval</A -></DT -><DD -><DL -><DT -><A -HREF="xmlrpcval.html#AEN452" ->Notes on types</A -></DT -><DT -><A -HREF="xmlrpcval.html#XMLRPCVAL-CREATION" ->Creation</A -></DT -><DT -><A -HREF="xmlrpcval.html#XMLRPCVAL-METHODS" ->Methods</A -></DT -></DL -></DD -><DT -><A -HREF="xmlrpc-server.html" ->xmlrpc_server</A -></DT -><DD -><DL -><DT -><A -HREF="xmlrpc-server.html#AEN658" ->The dispatch map</A -></DT -><DT -><A -HREF="xmlrpc-server.html#SIGNATURES" ->Method signatures</A -></DT -><DT -><A -HREF="xmlrpc-server.html#AEN686" ->Delaying the server response</A -></DT -><DT -><A -HREF="xmlrpc-server.html#AEN692" ->Fault reporting</A -></DT -></DL -></DD -></DL -></DD -><DT ->6. <A -HREF="helpers.html" ->Helper functions</A -></DT -><DD -><DL -><DT -><A -HREF="helpers.html#AEN739" ->Date functions</A -></DT -><DD -><DL -><DT -><A -HREF="helpers.html#ISO8601ENCODE" ->iso8601_encode</A -></DT -><DT -><A -HREF="helpers.html#ISO8601DECODE" ->iso8601_decode</A -></DT -></DL -></DD -><DT -><A -HREF="arrayuse.html" ->Easy use with PHP arrays</A -></DT -><DD -><DL -><DT -><A -HREF="arrayuse.html#XMLRPCDECODE" ->xmlrpc_decode</A -></DT -><DT -><A -HREF="arrayuse.html#XMLRPCENCODE" ->xmlrpc_encode</A -></DT -></DL -></DD -><DT -><A -HREF="debugging.html" ->Debugging aids</A -></DT -><DD -><DL -><DT -><A -HREF="debugging.html#AEN811" ->xmlrpc_debugmsg</A -></DT -></DL -></DD -></DL -></DD -><DT ->7. <A -HREF="reserved.html" ->Reserved methods</A -></DT -><DD -><DL -><DT -><A -HREF="reserved.html#AEN827" ->system.listMethods</A -></DT -><DT -><A -HREF="sysmethodsig.html" ->system.methodSignature</A -></DT -><DT -><A -HREF="sysmethhelp.html" ->system.methodHelp</A -></DT -></DL -></DD -><DT ->8. <A -HREF="examples.html" ->Examples</A -></DT -><DD -><DL -><DT -><A -HREF="examples.html#STATENAME" ->XML-RPC client: state name query</A -></DT -></DL -></DD -></DL -></DIV -></DIV -><DIV -CLASS="NAVFOOTER" -><HR -ALIGN="LEFT" -WIDTH="100%"><TABLE -SUMMARY="Footer navigation table" -WIDTH="100%" -BORDER="0" -CELLPADDING="0" -CELLSPACING="0" -><TR -><TD -WIDTH="33%" -ALIGN="left" -VALIGN="top" -> </TD -><TD -WIDTH="34%" -ALIGN="center" -VALIGN="top" -> </TD -><TD -WIDTH="33%" -ALIGN="right" -VALIGN="top" -><A -HREF="introduction.html" -ACCESSKEY="N" ->Next</A -></TD -></TR -><TR -><TD -WIDTH="33%" -ALIGN="left" -VALIGN="top" -> </TD -><TD -WIDTH="34%" -ALIGN="center" -VALIGN="top" -> </TD -><TD -WIDTH="33%" -ALIGN="right" -VALIGN="top" ->Introduction</TD -></TR -></TABLE -></DIV -></BODY -></HTML ->
\ No newline at end of file +<html><head> + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>XML-RPC for PHP</title><link rel="stylesheet" href="html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.67.0"><link rel="start" href="index.html" title="XML-RPC for PHP"><link rel="next" href="ch01.html" title="Chapter 1. Introduction"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">XML-RPC for PHP</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ch01.html">Next</a></td></tr></table><hr></div><div class="book" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="d0e1"></a>XML-RPC for PHP</h1></div><div><h2 class="subtitle">version 1.1</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Edd</span> <span class="surname">Dumbill</span></h3><div class="affiliation"><span class="orgname"><a href="http://usefulinc.com/" target="_top">Useful Information Company</a><br></span><div class="address"><p><br> + <code class="email"><<a href="mailto:edd@usefulinc.com">edd@usefulinc.com</a>></code><br> + </p></div></div></div></div></div><div><p class="copyright">Copyright © 1999,2000,2001 Edd Dumbill, Useful Information Company</p></div><div><div class="legalnotice"><a name="d0e29"></a><p>All rights reserved.</p><p>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:</p><div class="itemizedlist"><ul type="disc"><li><p>Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.</p></li><li><p>Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.</p></li><li><p>Neither the name of the "XML-RPC for PHP" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.</p></li></ul></div><p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="chapter"><a href="ch01.html">1. Introduction</a></span></dt><dd><dl><dt><span class="sect1"><a href="ch01s01.html">1. Acknowledgements</a></span></dt></dl></dd><dt><span class="chapter"><a href="ch02.html">2. Files in the distribution</a></span></dt><dt><span class="chapter"><a href="ch03.html">3. Known bugs</a></span></dt><dt><span class="chapter"><a href="ch04.html">4. Support</a></span></dt><dd><dl><dt><span class="sect1"><a href="ch04s01.html">1. Online Support</a></span></dt><dt><span class="sect1"><a href="ch04s02.html">2. The Jellyfish Book</a></span></dt></dl></dd><dt><span class="chapter"><a href="ch05.html">5. Class documentation</a></span></dt><dd><dl><dt><span class="sect1"><a href="ch05s01.html">1. xmlrpc_client</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch05s01.html#d0e322">1.1. Creation</a></span></dt><dt><span class="sect2"><a href="ch05s01.html#d0e352">1.2. Methods</a></span></dt><dd><dl><dt><span class="sect3"><a href="ch05s01.html#xmlrpc-client-send">1.2.1. send</a></span></dt><dt><span class="sect3"><a href="ch05s01.html#d0e439">1.2.2. setCredentials</a></span></dt><dt><span class="sect3"><a href="ch05s01.html#d0e454">1.2.3. setCertificate</a></span></dt><dt><span class="sect3"><a href="ch05s01.html#d0e482">1.2.4. setSSLVerifyPeer</a></span></dt><dt><span class="sect3"><a href="ch05s01.html#d0e497">1.2.5. setSSLVerifyHost</a></span></dt><dt><span class="sect3"><a href="ch05s01.html#d0e512">1.2.6. setDebug</a></span></dt></dl></dd></dl></dd><dt><span class="sect1"><a href="ch05s02.html">2. xmlrpcmsg</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch05s02.html#d0e547">2.1. Creation</a></span></dt><dt><span class="sect2"><a href="ch05s02.html#d0e589">2.2. Methods</a></span></dt><dd><dl><dt><span class="sect3"><a href="ch05s02.html#d0e592">2.2.1. serialize</a></span></dt><dt><span class="sect3"><a href="ch05s02.html#d0e602">2.2.2. addParam</a></span></dt><dt><span class="sect3"><a href="ch05s02.html#d0e620">2.2.3. getParam</a></span></dt><dt><span class="sect3"><a href="ch05s02.html#d0e638">2.2.4. getNumParams</a></span></dt><dt><span class="sect3"><a href="ch05s02.html#d0e648">2.2.5. method</a></span></dt><dt><span class="sect3"><a href="ch05s02.html#d0e664">2.2.6. parseResponse</a></span></dt><dt><span class="sect3"><a href="ch05s02.html#d0e686">2.2.7. parseResponseFile</a></span></dt></dl></dd></dl></dd><dt><span class="sect1"><a href="ch05s03.html">3. xmlrpcresp</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch05s03.html#d0e722">3.1. Creation</a></span></dt><dt><span class="sect2"><a href="ch05s03.html#d0e764">3.2. Methods</a></span></dt><dd><dl><dt><span class="sect3"><a href="ch05s03.html#d0e767">3.2.1. faultCode</a></span></dt><dt><span class="sect3"><a href="ch05s03.html#d0e780">3.2.2. faultString</a></span></dt><dt><span class="sect3"><a href="ch05s03.html#d0e793">3.2.3. value</a></span></dt><dt><span class="sect3"><a href="ch05s03.html#d0e809">3.2.4. serialize</a></span></dt></dl></dd></dl></dd><dt><span class="sect1"><a href="ch05s04.html">4. xmlrpcval</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch05s04.html#d0e841">4.1. Notes on types</a></span></dt><dd><dl><dt><span class="sect3"><a href="ch05s04.html#d0e844">4.1.1. int</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e864">4.1.2. base64</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e869">4.1.3. boolean</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e886">4.1.4. string</a></span></dt></dl></dd><dt><span class="sect2"><a href="ch05s04.html#xmlrpcval-creation">4.2. Creation</a></span></dt><dt><span class="sect2"><a href="ch05s04.html#xmlrpcval-methods">4.3. Methods</a></span></dt><dd><dl><dt><span class="sect3"><a href="ch05s04.html#d0e980">4.3.1. addScalar</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1027">4.3.2. addArray</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1048">4.3.3. addStruct</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1069">4.3.4. kindOf</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1079">4.3.5. serialize</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1089">4.3.6. scalarval</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1102">4.3.7. scalartyp</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1121">4.3.8. arraymem</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1142">4.3.9. arraysize</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1158">4.3.10. structmem</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#d0e1179">4.3.11. structeach</a></span></dt><dt><span class="sect3"><a href="ch05s04.html#structreset">4.3.12. structreset</a></span></dt></dl></dd></dl></dd><dt><span class="sect1"><a href="ch05s05.html">5. xmlrpc_server</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch05s05.html#d0e1229">5.1. The dispatch map</a></span></dt><dt><span class="sect2"><a href="ch05s05.html#signatures">5.2. Method signatures</a></span></dt><dt><span class="sect2"><a href="ch05s05.html#d0e1280">5.3. Delaying the server response</a></span></dt><dt><span class="sect2"><a href="ch05s05.html#d0e1293">5.4. Fault reporting</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="ch06.html">6. Global variables</a></span></dt><dd><dl><dt><span class="sect1"><a href="ch06s01.html">1. "Constant" variables</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch06s01.html#d0e1418">1.1. $xmlrpcerruser</a></span></dt><dt><span class="sect2"><a href="ch06s01.html#d0e1428">1.2. $xmlrpcI4, $xmlrpcInt, $xmlrpcDouble, $xmlrpcString, $xmlrpcDateTime, $xmlrpcBase64 +, $xmlrpcArray, $xmlrpcStruct</a></span></dt><dt><span class="sect2"><a href="ch06s01.html#d0e1435">1.3. $xmlrpcTypes, $xmlEntities, $xmlrpcerr, $xmlrpcstr, $xmlrpcerrxml, $xmlrpc_backslash, $_xh</a></span></dt></dl></dd><dt><span class="sect1"><a href="ch06s02.html">2. Variables whose value can be modified</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch06s02.html#d0e1443">2.1. xmlrpc_defencoding</a></span></dt><dt><span class="sect2"><a href="ch06s02.html#d0e1463">2.2. xmlrpc_internalencoding</a></span></dt><dt><span class="sect2"><a href="ch06s02.html#d0e1473">2.3. xmlrpcName</a></span></dt><dt><span class="sect2"><a href="ch06s02.html#d0e1483">2.4. xmlrpcVersion</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="ch07.html">7. Helper functions</a></span></dt><dd><dl><dt><span class="sect1"><a href="ch07s01.html">1. Date functions</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch07s01.html#iso8601encode">1.1. iso8601_encode</a></span></dt><dt><span class="sect2"><a href="ch07s01.html#iso8601decode">1.2. iso8601_decode</a></span></dt></dl></dd><dt><span class="sect1"><a href="ch07s02.html">2. Easy use with PHP arrays</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch07s02.html#phpxmlrpcdecode">2.1. php_xmlrpc_decode</a></span></dt><dt><span class="sect2"><a href="ch07s02.html#phpxmlrpcencode">2.2. php_xmlrpc_encode</a></span></dt></dl></dd><dt><span class="sect1"><a href="ch07s03.html">3. Deprecated functions</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch07s03.html#xmlrpcdecode">3.1. xmlrpc_decode</a></span></dt><dt><span class="sect2"><a href="ch07s03.html#xmlrpcencode">3.2. xmlrpc_encode</a></span></dt></dl></dd><dt><span class="sect1"><a href="ch07s04.html">4. Debugging aids</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch07s04.html#d0e1694">4.1. xmlrpc_debugmsg</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="ch08.html">8. Reserved methods</a></span></dt><dd><dl><dt><span class="sect1"><a href="ch08s01.html">1. system.listMethods</a></span></dt><dt><span class="sect1"><a href="ch08s02.html">2. system.methodSignature</a></span></dt><dt><span class="sect1"><a href="ch08s03.html">3. system.methodHelp</a></span></dt></dl></dd><dt><span class="chapter"><a href="ch09.html">9. Examples</a></span></dt><dd><dl><dt><span class="sect1"><a href="ch09s01.html">1. XML-RPC client: state name query</a></span></dt></dl></dd></dl></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="ch01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top"> </td><td width="20%" align="center"> </td><td width="40%" align="right" valign="top"> Chapter 1. Introduction</td></tr></table></div></body></html>
\ No newline at end of file diff --git a/modules/xmlrpc/xmlrpc.inc b/modules/xmlrpc/xmlrpc.inc index 5b4c0150..bdb818e2 100755 --- a/modules/xmlrpc/xmlrpc.inc +++ b/modules/xmlrpc/xmlrpc.inc @@ -1,7 +1,7 @@ <?php // -*-c++-*- // by Edd Dumbill (C) 1999-2002 // <edd@usefulinc.com> -// $Id: xmlrpc.inc,v 1.20 2003/01/10 22:01:56 dilinger Exp $ +// $Id: xmlrpc.inc,v 1.40 2005/04/24 18:17:18 ggiunta Exp $ // Copyright (c) 1999,2000,2002 Edd Dumbill. @@ -49,6 +49,34 @@ } } + // G. Giunta 2005/01/29: declare global these variables, + // so that xmlrpc.inc will work even if included from within a function + // NB: it will give warnings in PHP3, so we comment it out + // Milosch: Next round, maybe we should explicitly request these via $GLOBALS where used. + if (phpversion() >= '4') + { + global $xmlrpcI4; + global $xmlrpcInt; + global $xmlrpcDouble; + global $xmlrpcString; + global $xmlrpcDateTime; + global $xmlrpcBase64; + global $xmlrpcArray; + global $xmlrpcStruct; + + global $xmlrpcTypes; + global $xmlEntities; + global $xmlrpcerr; + global $xmlrpcstr; + global $xmlrpc_defencoding; + global $xmlrpc_internalencoding; + global $xmlrpcName; + global $xmlrpcVersion; + global $xmlrpcerruser; + global $xmlrpcerrxml; + global $xmlrpc_backslash; + global $_xh; + } $xmlrpcI4='i4'; $xmlrpcInt='int'; $xmlrpcBoolean='boolean'; @@ -82,7 +110,7 @@ $xmlrpcerr['unknown_method']=1; $xmlrpcstr['unknown_method']='Unknown method'; $xmlrpcerr['invalid_return']=2; - $xmlrpcstr['invalid_return']='Invalid return payload: enabling debugging to examine incoming payload'; + $xmlrpcstr['invalid_return']='Invalid return payload: enable debugging to examine incoming payload'; $xmlrpcerr['incorrect_params']=3; $xmlrpcstr['incorrect_params']='Incorrect parameters passed to method'; $xmlrpcerr['introspect_unknown']=4; @@ -110,13 +138,18 @@ $xmlrpcerr['multicall_notarray'] = 14; $xmlrpcstr['multicall_notarray'] = 'params is not an array'; + // The charset encoding expected by the server for received messages and + // by the client for received responses $xmlrpc_defencoding='UTF-8'; + // The encoding used by PHP. + // String values received will be converted to this. + $xmlrpc_internalencoding='ISO-8859-1'; $xmlrpcName='XML-RPC for PHP'; - $xmlrpcVersion='1.0.99'; + $xmlrpcVersion='1.1.1'; // let user errors start at 800 - $xmlrpcerruser=800; + $xmlrpcerruser=800; // let XML parse errors start at 100 $xmlrpcerrxml=100; @@ -137,13 +170,19 @@ $_xh=array(); - if (!function_exists('xmlrpc_entity_decode')) { - + /** + * To help correct communication of non-ascii chars inside strings, regardless + * of the charset used when sending requests, parsing them, sending responses + * and parsing responses, convert all non-ascii chars present in the message + * into their equivalent 'charset entity'. Charset entities enumerated this way + * are independent of the charset encoding used to transmit them, and all XML + * parsers are bound to understand them. + */ function xmlrpc_entity_decode($string) { $top=split('&', $string); $op=''; - $i=0; + $i=0; while($i<sizeof($top)) { if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) @@ -168,8 +207,6 @@ return $op; } - } // if xmlrpc_entity_decode doesn't exist - function xmlrpc_lookup_entity($ent) { global $xmlEntities; @@ -185,6 +222,299 @@ return '?'; } + /** + * These entities originate from HTML specs (1.1, proposed 2.0, etc), + * and are taken directly from php-4.3.1/ext/mbstring/html_entities.c. + * Until php provides functionality to translate these entities in its + * core library, use this function. + */ + function xmlrpc_html_entity_xlate($data = '') + { + $entities = array( + " " => " ", + "¡" => "¡", + "¢" => "¢", + "£" => "£", + "¤" => "¤", + "¥" => "¥", + "¦" => "¦", + "§" => "§", + "¨" => "¨", + "©" => "©", + "ª" => "ª", + "«" => "«", + "¬" => "¬", + "­" => "­", + "®" => "®", + "¯" => "¯", + "°" => "°", + "±" => "±", + "²" => "²", + "³" => "³", + "´" => "´", + "µ" => "µ", + "¶" => "¶", + "·" => "·", + "¸" => "¸", + "¹" => "¹", + "º" => "º", + "»" => "»", + "¼" => "¼", + "½" => "½", + "¾" => "¾", + "¿" => "¿", + "À" => "À", + "Á" => "Á", + "Â" => "Â", + "Ã" => "Ã", + "Ä" => "Ä", + "Å" => "Å", + "Æ" => "Æ", + "Ç" => "Ç", + "È" => "È", + "É" => "É", + "Ê" => "Ê", + "Ë" => "Ë", + "Ì" => "Ì", + "Í" => "Í", + "Î" => "Î", + "Ï" => "Ï", + "Ð" => "Ð", + "Ñ" => "Ñ", + "Ò" => "Ò", + "Ó" => "Ó", + "Ô" => "Ô", + "Õ" => "Õ", + "Ö" => "Ö", + "×" => "×", + "Ø" => "Ø", + "Ù" => "Ù", + "Ú" => "Ú", + "Û" => "Û", + "Ü" => "Ü", + "Ý" => "Ý", + "Þ" => "Þ", + "ß" => "ß", + "à" => "à", + "á" => "á", + "â" => "â", + "ã" => "ã", + "ä" => "ä", + "å" => "å", + "æ" => "æ", + "ç" => "ç", + "è" => "è", + "é" => "é", + "ê" => "ê", + "ë" => "ë", + "ì" => "ì", + "í" => "í", + "î" => "î", + "ï" => "ï", + "ð" => "ð", + "ñ" => "ñ", + "ò" => "ò", + "ó" => "ó", + "ô" => "ô", + "õ" => "õ", + "ö" => "ö", + "÷" => "÷", + "ø" => "ø", + "ù" => "ù", + "ú" => "ú", + "û" => "û", + "ü" => "ü", + "ý" => "ý", + "þ" => "þ", + "ÿ" => "ÿ", + "Œ" => "Œ", + "œ" => "œ", + "Š" => "Š", + "š" => "š", + "Ÿ" => "Ÿ", + "ƒ" => "ƒ", + "ˆ" => "ˆ", + "˜" => "˜", + "Α" => "Α", + "Β" => "Β", + "Γ" => "Γ", + "Δ" => "Δ", + "Ε" => "Ε", + "Ζ" => "Ζ", + "Η" => "Η", + "Θ" => "Θ", + "Ι" => "Ι", + "Κ" => "Κ", + "Λ" => "Λ", + "Μ" => "Μ", + "Ν" => "Ν", + "Ξ" => "Ξ", + "Ο" => "Ο", + "Π" => "Π", + "Ρ" => "Ρ", + "Σ" => "Σ", + "Τ" => "Τ", + "Υ" => "Υ", + "Φ" => "Φ", + "Χ" => "Χ", + "Ψ" => "Ψ", + "Ω" => "Ω", + "β" => "β", + "γ" => "γ", + "δ" => "δ", + "ε" => "ε", + "ζ" => "ζ", + "η" => "η", + "θ" => "θ", + "ι" => "ι", + "κ" => "κ", + "λ" => "λ", + "μ" => "μ", + "ν" => "ν", + "ξ" => "ξ", + "ο" => "ο", + "π" => "π", + "ρ" => "ρ", + "ς" => "ς", + "σ" => "σ", + "τ" => "τ", + "υ" => "υ", + "φ" => "φ", + "χ" => "χ", + "ψ" => "ψ", + "ω" => "ω", + "ϑ" => "ϑ", + "ϒ" => "ϒ", + "ϖ" => "ϖ", + " " => " ", + " " => " ", + " " => " ", + "‌" => "‌", + "‍" => "‍", + "‎" => "‎", + "‏" => "‏", + "–" => "–", + "—" => "—", + "‘" => "‘", + "’" => "’", + "‚" => "‚", + "“" => "“", + "”" => "”", + "„" => "„", + "†" => "†", + "‡" => "‡", + "•" => "•", + "…" => "…", + "‰" => "‰", + "′" => "′", + "″" => "″", + "‹" => "‹", + "›" => "›", + "‾" => "‾", + "⁄" => "⁄", + "€" => "€", + "℘" => "℘", + "ℑ" => "ℑ", + "ℜ" => "ℜ", + "™" => "™", + "ℵ" => "ℵ", + "←" => "←", + "↑" => "↑", + "→" => "→", + "↓" => "↓", + "↔" => "↔", + "↵" => "↵", + "⇐" => "⇐", + "⇑" => "⇑", + "⇒" => "⇒", + "⇓" => "⇓", + "⇔" => "⇔", + "∀" => "∀", + "∂" => "∂", + "∃" => "∃", + "∅" => "∅", + "∇" => "∇", + "∈" => "∈", + "∉" => "∉", + "∋" => "∋", + "∏" => "∏", + "∑" => "∑", + "−" => "−", + "∗" => "∗", + "√" => "√", + "∝" => "∝", + "∞" => "∞", + "∠" => "∠", + "∧" => "∧", + "∨" => "∨", + "∩" => "∩", + "∪" => "∪", + "∫" => "∫", + "∴" => "∴", + "∼" => "∼", + "≅" => "≅", + "≈" => "≈", + "≠" => "≠", + "≡" => "≡", + "≤" => "≤", + "≥" => "≥", + "⊂" => "⊂", + "⊃" => "⊃", + "⊄" => "⊄", + "⊆" => "⊆", + "⊇" => "⊇", + "⊕" => "⊕", + "⊗" => "⊗", + "⊥" => "⊥", + "⋅" => "⋅", + "⌈" => "⌈", + "⌉" => "⌉", + "⌊" => "⌊", + "⌋" => "⌋", + "⟨" => "〈", + "⟩" => "〉", + "◊" => "◊", + "♠" => "♠", + "♣" => "♣", + "♥" => "♥", + "♦" => "♦"); + return strtr($data, $entities); + } + + function xmlrpc_encode_entitites($data) + { + $length = strlen($data); + $escapeddata = ""; + for($position = 0; $position < $length; $position++) + { + $character = substr($data, $position, 1); + $code = Ord($character); + switch($code) { + case 34: + $character = """; + break; + case 38: + $character = "&"; + break; + case 39: + $character = "'"; + break; + case 60: + $character = "<"; + break; + case 62: + $character = ">"; + break; + default: + if ($code < 32 || $code > 159) + $character = ("&#".strval($code).";"); + break; + } + $escapeddata .= $character; + } + return $escapeddata; + } + function xmlrpc_se($parser, $name, $attrs) { global $_xh, $xmlrpcDateTime, $xmlrpcString; @@ -196,12 +526,13 @@ $_xh[$parser]['st'].='array('; $_xh[$parser]['cm']++; // this last line turns quoting off - // this means if we get an empty array we'll + // this means if we get an empty array we'll // simply get a bit of whitespace in the eval $_xh[$parser]['qt']=0; break; case 'NAME': - $_xh[$parser]['st'].="'"; $_xh[$parser]['ac']=''; + $_xh[$parser]['st'].='"'; + $_xh[$parser]['ac']=''; break; case 'FAULT': $_xh[$parser]['isf']=1; @@ -278,11 +609,13 @@ $_xh[$parser]['cm']--; break; case 'NAME': - $_xh[$parser]['st'].= $_xh[$parser]['ac'] . "' => "; + $_xh[$parser]['st'].= $_xh[$parser]['ac'] . '" => '; break; case 'BOOLEAN': // special case here: we translate boolean 1 or 0 into PHP // constants true or false + // NB: this simple checks helps a lot sanitizing input, ie no + // security problems around here if ($_xh[$parser]['ac']=='1') { $_xh[$parser]['ac']='true'; @@ -290,9 +623,9 @@ else { $_xh[$parser]['ac']='false'; - $_xh[$parser]['vt']=strtolower($name); - // Drop through intentionally. } + $_xh[$parser]['vt']=strtolower($name); + // Drop through intentionally. case 'I4': case 'INT': case 'STRING': @@ -306,30 +639,48 @@ } elseif ($_xh[$parser]['qt']==2) { - $_xh[$parser]['st'].="base64_decode('". $_xh[$parser]['ac'] . "')"; + $_xh[$parser]['st'].='base64_decode("'. $_xh[$parser]['ac'] . '")'; } elseif ($name=='BOOLEAN') { $_xh[$parser]['st'].=$_xh[$parser]['ac']; } - else + elseif ($name=='DOUBLE') { - // we have an I4, INT or a DOUBLE + // we have a DOUBLE // we must check that only 0123456789-.<space> are characters here - if (!ereg("^\-?[0123456789 \t\.]+$", $_xh[$parser]['ac'])) + if (!ereg("^[+-]?[eE0123456789 \\t\\.]+$", $_xh[$parser]['ac'])) { // TODO: find a better way of throwing an error // than this! - error_log('XML-RPC: non numeric value received in INT or DOUBLE'); - $_xh[$parser]['st'].='ERROR_NON_NUMERIC_FOUND'; + error_log('XML-RPC: non numeric value received in DOUBLE: '.$_xh[$parser]['ac']); + $_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; } else { // it's ok, add it on - $_xh[$parser]['st'].=$_xh[$parser]['ac']; + $_xh[$parser]['st'].=(double)$_xh[$parser]['ac']; } } - $_xh[$parser]['ac']=''; $_xh[$parser]['qt']=0; + else + { + // we have an I4/INT + // we must check that only 0123456789-<space> are characters here + if (!ereg("^[+-]?[0123456789 \\t]+$", $_xh[$parser]['ac'])) + { + // TODO: find a better way of throwing an error + // than this! + error_log('XML-RPC: non numeric value received in INT: '.$_xh[$parser]['ac']); + $_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; + } + else + { + // it's ok, add it on + $_xh[$parser]['st'].=(int)$_xh[$parser]['ac']; + } + } + $_xh[$parser]['ac']=''; + $_xh[$parser]['qt']=0; $_xh[$parser]['lv']=3; // indicate we've found a value break; case 'VALUE': @@ -337,7 +688,7 @@ if (strlen($_xh[$parser]['ac'])>0 && $_xh[$parser]['vt']==$xmlrpcString) { - $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"'; + $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"'; } // This if() detects if no scalar was inside <VALUE></VALUE> // and pads an empty ''. @@ -345,17 +696,23 @@ { $_xh[$parser]['st'].= '""'; } - $_xh[$parser]['st'].=", '" . $_xh[$parser]['vt'] . "')"; + // G. Giunta 2005/03/12 save some chars in the reconstruction of string vals... + if ($_xh[$parser]['vt'] != $xmlrpcString) + $_xh[$parser]['st'].=", '" . $_xh[$parser]['vt'] . "')"; + else + $_xh[$parser]['st'].=")"; if ($_xh[$parser]['cm']) { $_xh[$parser]['st'].=','; } break; case 'MEMBER': - $_xh[$parser]['ac']=''; $_xh[$parser]['qt']=0; + $_xh[$parser]['ac']=''; + $_xh[$parser]['qt']=0; break; case 'DATA': - $_xh[$parser]['ac']=''; $_xh[$parser]['qt']=0; + $_xh[$parser]['ac']=''; + $_xh[$parser]['qt']=0; break; case 'PARAM': $_xh[$parser]['params'][]=$_xh[$parser]['st']; @@ -363,7 +720,8 @@ case 'METHODNAME': $_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+", '', $_xh[$parser]['ac']); break; - case 'BOOLEAN': + // BOOLEAN HAS BEEN ENUMERATED ABOVE! + /*case 'BOOLEAN': // special case here: we translate boolean 1 or 0 into PHP // constants true or false if ($_xh[$parser]['ac']=='1') @@ -375,7 +733,7 @@ $_xh[$parser]['ac']='false'; $_xh[$parser]['vt']=strtolower($name); } - break; + break;*/ default: break; } @@ -401,9 +759,9 @@ { // if we've found text and we're just in a <value> then // turn quoting on, as this will be a string - $_xh[$parser]['qt']=1; + $_xh[$parser]['qt']=1; // and say we've found a value - $_xh[$parser]['lv']=2; + $_xh[$parser]['lv']=2; } if(!@isset($_xh[$parser]['ac'])) { @@ -415,13 +773,13 @@ function xmlrpc_dh($parser, $data) { - global $_xh; + global $_xh, $xmlrpc_backslash; if (substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') { if ($_xh[$parser]['lv']==1) { - $_xh[$parser]['qt']=1; - $_xh[$parser]['lv']=2; + $_xh[$parser]['qt']=1; + $_xh[$parser]['lv']=2; } $_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data))); } @@ -433,7 +791,7 @@ var $server; var $port; var $errno; - var $errstring; + var $errstr; var $debug=0; var $username=''; var $password=''; @@ -512,20 +870,25 @@ function sendPayloadHTTP10($msg, $server, $port, $timeout=0,$username='', $password='') { - global $xmlrpcerr, $xmlrpcstr; + global $xmlrpcerr, $xmlrpcstr, $xmlrpcName, $xmlrpcVersion, $xmlrpc_defencoding; if ($port==0) { $port=80; } if($timeout>0) { - $fp=fsockopen($server, $port,$this->errno, $this->errstr, $timeout); + $fp=@fsockopen($server, $port,$this->errno, $this->errstr, $timeout); } else { - $fp=fsockopen($server, $port,$this->errno, $this->errstr); + $fp=@fsockopen($server, $port,$this->errno, $this->errstr); } - if (!$fp) + if ($fp) + { + if ($timeout>0 && function_exists('stream_set_timeout')) + stream_set_timeout($fp, $timeout); + } + else { $this->errstr='Connect error'; $r=new xmlrpcresp(0, $xmlrpcerr['http_error'],$xmlrpcstr['http_error']); @@ -545,9 +908,11 @@ $credentials='Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n"; } - $op= "POST " . $this->path. " HTTP/1.0\r\nUser-Agent: PHP XMLRPC 1.0\r\n" . - "Host: ". $this->server . "\r\n" . + $op= "POST " . $this->path. " HTTP/1.0\r\n" . + "User-Agent: " . $xmlrpcName . " " . $xmlrpcVersion . "\r\n" . + "Host: ". $server . "\r\n" . $credentials . + "Accept-Charset: " . $xmlrpc_defencoding . "\r\n" . "Content-Type: text/xml\r\nContent-Length: " . strlen($msg->payload) . "\r\n\r\n" . $msg->payload; @@ -567,7 +932,7 @@ // requires curl to be built into PHP function sendPayloadHTTPS($msg, $server, $port, $timeout=0,$username='', $password='', $cert='',$certpass='') { - global $xmlrpcerr, $xmlrpcstr; + global $xmlrpcerr, $xmlrpcstr, $xmlrpcVersion, $xmlrpc_internalencoding; if ($port == 0) { $port = 443; @@ -594,7 +959,7 @@ { curl_setopt($curl, CURLOPT_VERBOSE, 1); } - curl_setopt($curl, CURLOPT_USERAGENT, 'PHP XMLRPC 1.0'); + curl_setopt($curl, CURLOPT_USERAGENT, 'PHP XMLRPC '.$xmlrpcVersion); // required for XMLRPC curl_setopt($curl, CURLOPT_POST, 1); // post the data @@ -602,7 +967,7 @@ // the data curl_setopt($curl, CURLOPT_HEADER, 1); // return the header too - curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml')); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Accept-Charset: '.$xmlrpc_internalencoding)); // whether to verify remote host's cert curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer); // whether to verify cert's common name (CN); 0 for no, 1 to verify that it exists, and 2 to verify that it matches the hostname used @@ -635,12 +1000,13 @@ { $this->errstr='no response'; $resp=new xmlrpcresp(0, $xmlrpcerr['curl_fail'], $xmlrpcstr['curl_fail']. ': '. curl_error($curl)); + curl_close($curl); } else { + curl_close($curl); $resp = $msg->parseResponse($result); } - curl_close($curl); return $resp; } @@ -653,10 +1019,10 @@ $results = $this->_try_multicall($msgs, $timeout, $method); /* TODO - this is not php3-friendly */ // if($results !== false) - if($results != false) + if(is_array($results)) { // Either the system.multicall succeeded, or the send - // failed (e.g. due to HTTP timeout). In either case, + // failed (e.g. due to HTTP timeout). In either case, // we're done for now. return $results; } @@ -704,19 +1070,27 @@ // Attempt RPC call $result = $this->send($multicall, $timeout, $method); - if (!is_object($result)) + if(!is_object($result)) + { return ($result || 0); // transport failed + } - if ($result->faultCode() != 0) + if($result->faultCode() != 0) + { return false; // system.multicall failed + } // Unpack responses. $rets = $result->value(); - if ($rets->kindOf() != 'array') + if($rets->kindOf() != 'array') + { return false; // bad return type from system.multicall + } $numRets = $rets->arraysize(); - if ($numRets != count($msgs)) + if($numRets != count($msgs)) + { return false; // wrong number of return values. + } $response = array(); for ($i = 0; $i < $numRets; $i++) @@ -725,18 +1099,24 @@ switch ($val->kindOf()) { case 'array': - if ($val->arraysize() != 1) + if($val->arraysize() != 1) + { return false; // Bad value + } // Normal return value $response[$i] = new xmlrpcresp($val->arraymem(0)); break; case 'struct': $code = $val->structmem('faultCode'); - if ($code->kindOf() != 'scalar' || $code->scalartyp() != 'int') + if($code->kindOf() != 'scalar' || $code->scalartyp() != 'int') + { return false; + } $str = $val->structmem('faultString'); - if ($str->kindOf() != 'scalar' || $str->scalartyp() != 'string') + if($str->kindOf() != 'scalar' || $str->scalartyp() != 'string') + { return false; + } $response[$i] = new xmlrpcresp(0, $code->scalarval(), $str->scalarval()); break; default: @@ -760,12 +1140,13 @@ { // error $this->errno = $fcode; - $this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later. + $this->errstr = $fstr; + //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later. } - else if (!is_object($val)) + elseif (!is_object($val)) { // programmer error - error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to xmlrpcresp. Defaulting to empty value."); + error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to xmlrpcresp. Defaulting to empty value."); $this->val = new xmlrpcval(); } else @@ -795,6 +1176,7 @@ $result = "<methodResponse>\n"; if ($this->errno) { + // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients $result .= '<fault> <value> <struct> @@ -804,7 +1186,7 @@ </member> <member> <name>faultString</name> -<value><string>' . $this->errstr . '</string></value> +<value><string>' . xmlrpc_encode_entitites($this->errstr) . '</string></value> </member> </struct> </value> @@ -813,8 +1195,8 @@ else { $result .= "<params>\n<param>\n" . - $this->val->serialize() . - "</param>\n</params>"; + $this->val->serialize() . + "</param>\n</params>"; } $result .= "\n</methodResponse>"; return $result; @@ -842,7 +1224,7 @@ function xml_header() { - return "<?xml version=\"1.0\"?>\n<methodCall>\n"; + return "<?xml version=\"1.0\"?" . ">\n<methodCall>\n"; } function xml_footer() @@ -865,7 +1247,7 @@ $this->payload.="</params>\n"; // } $this->payload.=$this->xml_footer(); - $this->payload=str_replace("\n", "\r\n", $this->payload); + //$this->payload=str_replace("\n", "\r\n", $this->payload); } function method($meth='') @@ -900,24 +1282,7 @@ function parseResponse($data='') { global $_xh,$xmlrpcerr,$xmlrpcstr; - global $xmlrpc_defencoding; - - $parser = xml_parser_create($xmlrpc_defencoding); - - $_xh[$parser]=array(); - - $_xh[$parser]['st']=''; - $_xh[$parser]['cm']=0; - $_xh[$parser]['isf']=0; - $_xh[$parser]['ac']=''; - $_xh[$parser]['qt']=''; - $_xh[$parser]['headers'] = array(); - - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); - xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee'); - xml_set_character_data_handler($parser, 'xmlrpc_cd'); - xml_set_default_handler($parser, 'xmlrpc_dh'); - $xmlrpc_value=new xmlrpcval; + global $xmlrpc_defencoding, $xmlrpc_internalencoding; $hdrfnd = 0; if($this->debug) @@ -930,45 +1295,128 @@ { error_log('No response received from server.'); $r = new xmlrpcresp(0, $xmlrpcerr['no_data'], $xmlrpcstr['no_data']); - xml_parser_free($parser); return $r; } // see if we got an HTTP 200 OK, else bomb // but only do this if we're using the HTTP protocol. - if(ereg("^HTTP",$data) && !ereg("^HTTP/[0-9\.]+ 200 ", $data)) + if(ereg("^HTTP",$data)) { - $errstr= substr($data, 0, strpos($data, "\n")-1); - error_log('HTTP error, got response: ' .$errstr); - $r=new xmlrpcresp(0, $xmlrpcerr['http_error'], $xmlrpcstr['http_error']. ' (' . $errstr . ')'); - xml_parser_free($parser); - return $r; + // Strip HTTP 1.1 100 Continue header if present + while (ereg('^HTTP/1.1 1[0-9]{2}', $data)) + { + $pos = strpos($data, 'HTTP', 12); + // server sent a Continue header without any (valid) content following... + // give the client a chance to know it + if (!$pos && !is_int($pos)) // works fine in php 3, 4 and 5 + break; + $data = substr($data, $pos); + } + if (!ereg("^HTTP/[0-9\\.]+ 200 ", $data)) + { + $errstr= substr($data, 0, strpos($data, "\n")-1); + error_log('HTTP error, got response: ' .$errstr); + $r=new xmlrpcresp(0, $xmlrpcerr['http_error'], $xmlrpcstr['http_error']. ' (' . $errstr . ')'); + return $r; + } } + $parser = xml_parser_create($xmlrpc_defencoding); + + // G. Giunta 2004/04/06 + // Clean up the accumulator, or it will grow indefinitely long + // if making xmlrpc calls for a while + $_xh=array(); + $_xh[$parser]=array(); + $_xh[$parser]['headers'] = array(); // separate HTTP headers from data if (ereg("^HTTP", $data)) { - $ar = split("\r\n", $data); - while (($line = array_shift($ar))) + // be tolerant to usage of \n instead of \r\n to separate headers and data + // (even though it is not valid http) + $pos = strpos($data,"\r\n\r\n"); + if($pos || is_int($pos)) + $bd = $pos+4; + else { - if (strlen($line) < 1) + $pos = strpos($data,"\n\n"); + if($pos || is_int($pos)) + $bd = $pos+2; + else { - break; + // No separation between response headers and body: fault? + $bd = 0; } - $_xh[$parser]['headers'][] = $line; } - $data = join("\r\n", $ar); - } - - if ($this->debug && count($_xh[$parser]['headers'])) - { - print "<PRE>"; - foreach ($_xh[$parser]['headers'] as $header) + // be tolerant to line endings, and extra empty lines + $ar = split("\r?\n", trim(substr($data, 0, $pos))); + while (list(,$line) = @each($ar)) { - print "HEADER: $header\n"; + // take care of multi-line headers + $arr = explode(':',$line); + if(count($arr) > 1) + { + $header_name = trim($arr[0]); + // TO DO: some headers (the ones that allow a CSV list of values) + // do allow many values to be passed using multiple header lines. + // We should add content to $_xh[$parser]['headers'][$header_name] + // instead of replacing it for those... + $_xh[$parser]['headers'][$header_name] = $arr[1]; + for ($i = 2; $i < count($arr); $i++) + { + $_xh[$parser]['headers'][$header_name] .= ':'.$arr[$i]; + } // while + $_xh[$parser]['headers'][$header_name] = trim($_xh[$parser]['headers'][$header_name]); + } else if (isset($header_name)) + { + $_xh[$parser]['headers'][$header_name] .= ' ' . trim($line); + } + } + $data = substr($data, $bd); + + if ($this->debug && count($_xh[$parser]['headers'])) + { + print '<PRE>'; + //foreach ($_xh[$parser]['headers'] as $header) + @reset($_xh[$parser]['headers']); + while(list($header, $value) = @each($_xh[$parser]['headers'])) + { + print "HEADER: $header: $value\n"; + } + print "</PRE>\n"; } - print "</PRE>\n"; } + // be tolerant of extra whitespace in response body + $data = trim($data); + + // be tolerant of junk after methodResponse (e.g. javascript automatically inserted by free hosts) + // idea from Luca Mariano <luca.mariano@email.it> originally in PEARified version of the lib + $bd = false; + $pos = strpos($data, "</methodResponse>"); + while ($pos || is_int($pos)) + { + $bd = $pos+17; + $pos = strpos($data, "</methodResponse>", $bd); + } + if ($bd) + $data = substr($data, 0, $bd); + + $_xh[$parser]['st']=''; + $_xh[$parser]['cm']=0; + $_xh[$parser]['isf']=0; + $_xh[$parser]['ac']=''; + $_xh[$parser]['qt']=''; + + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell + // the xml parser to give us back data in the expected charset + xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $xmlrpc_internalencoding); + + xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee'); + xml_set_character_data_handler($parser, 'xmlrpc_cd'); + xml_set_default_handler($parser, 'xmlrpc_dh'); + //$xmlrpc_value=new xmlrpcval; + if (!xml_parse($parser, $data, sizeof($data))) { // thanks to Peter Kocks <peter.kocks@baygate.com> @@ -981,18 +1429,20 @@ $errstr = sprintf('XML error: %s at line %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser)); - error_log($errstr); - $r=new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return']); - xml_parser_free($parser); - echo $errstr; - return $r; } + error_log($errstr); + $r=new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return'].' ('.$errstr.')'); + xml_parser_free($parser); + if ($this->debug) + echo $errstr; + $r->hdrs = $_xh[$parser]['headers']; + return $r; } xml_parser_free($parser); if ($this->debug) { - print "<PRE>---EVALING---[" . - strlen($_xh[$parser]['st']) . " chars]---\n" . + print "<PRE>---EVALING---[" . + strlen($_xh[$parser]['st']) . " chars]---\n" . htmlspecialchars($_xh[$parser]['st']) . ";\n---END---</PRE>"; } if (strlen($_xh[$parser]['st'])==0) @@ -1005,7 +1455,13 @@ } else { - eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;'); + $allOK=0; + @eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;'); + if (!$allOK) + { + $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return']); + } + else if ($_xh[$parser]['isf']) { $errno_v = $v->structmem('faultCode'); @@ -1041,7 +1497,7 @@ global $xmlrpcTypes; $this->me=array(); $this->mytype=0; - if ($val!=-1 || $type!='') + if ($val!=-1 || !is_int($val) || $type!='') { if ($type=='') { @@ -1172,7 +1628,7 @@ $rs=''; global $xmlrpcTypes, $xmlrpcBase64, $xmlrpcString, $xmlrpcBoolean; - switch($xmlrpcTypes[$typ]) + switch(@$xmlrpcTypes[$typ]) { case 3: // struct @@ -1205,7 +1661,10 @@ $rs.="<${typ}>" . ($val ? '1' : '0') . "</${typ}>"; break; case $xmlrpcString: - $rs.="<${typ}>" . htmlspecialchars($val). "</${typ}>"; + // G. Giunta 2005/2/13: do NOT use htmlentities, since + // it will produce named html entities, which are invalid xml + $rs.="<${typ}>" . xmlrpc_encode_entitites($val). "</${typ}>"; + // $rs.="<${typ}>" . htmlentities($val). "</${typ}>"; break; default: $rs.="<${typ}>${val}</${typ}>"; @@ -1224,7 +1683,7 @@ function serializeval($o) { - global $xmlrpcTypes; + //global $xmlrpcTypes; $rs=''; $ar=$o->me; reset($ar); @@ -1292,7 +1751,7 @@ function scalarval() { - global $xmlrpcBoolean, $xmlrpcBase64; + //global $xmlrpcBoolean, $xmlrpcBase64; reset($this->me); list($a,$b)=each($this->me); return $b; @@ -1381,7 +1840,7 @@ * * * author: Dan Libby (dan@libby.com) * ****************************************************************/ - function old_xmlrpc_decode($xmlrpc_val) + function php_xmlrpc_decode($xmlrpc_val) { $kind = $xmlrpc_val->kindOf(); @@ -1396,9 +1855,9 @@ for($i = 0; $i < $size; $i++) { - $arr[]=old_xmlrpc_decode($xmlrpc_val->arraymem($i)); + $arr[] = php_xmlrpc_decode($xmlrpc_val->arraymem($i)); } - return $arr; + return $arr; } elseif($kind == 'struct') { @@ -1407,12 +1866,52 @@ while(list($key,$value)=$xmlrpc_val->structeach()) { - $arr[$key] = old_xmlrpc_decode($value); + $arr[$key] = php_xmlrpc_decode($value); } return $arr; } } + if(function_exists('xmlrpc_decode')) + { + define('XMLRPC_EPI_ENABLED','1'); + } + else + { + define('XMLRPC_EPI_ENABLED','0'); + function xmlrpc_decode($xmlrpc_val) + { + $kind = $xmlrpc_val->kindOf(); + + if($kind == 'scalar') + { + return $xmlrpc_val->scalarval(); + } + elseif($kind == 'array') + { + $size = $xmlrpc_val->arraysize(); + $arr = array(); + + for($i = 0; $i < $size; $i++) + { + $arr[]=xmlrpc_decode($xmlrpc_val->arraymem($i)); + } + return $arr; + } + elseif($kind == 'struct') + { + $xmlrpc_val->structreset(); + $arr = array(); + + while(list($key,$value)=$xmlrpc_val->structeach()) + { + $arr[$key] = xmlrpc_decode($value); + } + return $arr; + } + } + } + /**************************************************************** * xmlrpc_encode takes native php types and encodes them into * * xmlrpc PHP object format. * @@ -1425,7 +1924,7 @@ * * * author: Dan Libby (dan@libby.com) * ****************************************************************/ - function old_xmlrpc_encode($php_val) + function php_xmlrpc_encode($php_val) { global $xmlrpcInt; global $xmlrpcDouble; @@ -1444,7 +1943,7 @@ $arr = array(); while (list($k,$v) = each($php_val)) { - $arr[$k] = old_xmlrpc_encode($v); + $arr[$k] = php_xmlrpc_encode($v); } $xmlrpc_val->addStruct($arr); break; @@ -1463,14 +1962,67 @@ $xmlrpc_val->addScalar($php_val, $xmlrpcBoolean); break; // </G_Giunta_2001-02-29> - case 'unknown type': + // catch "resource", "NULL", "user function", "unknown type" + //case 'unknown type': default: // giancarlo pinerolo <ping@alt.it> // it has to return // an empty object in case (which is already // at this point), not a boolean. break; + } + return $xmlrpc_val; + } + + if(XMLRPC_EPI_ENABLED == '0') + { + function xmlrpc_encode($php_val) + { + global $xmlrpcInt; + global $xmlrpcDouble; + global $xmlrpcString; + global $xmlrpcArray; + global $xmlrpcStruct; + global $xmlrpcBoolean; + + $type = gettype($php_val); + $xmlrpc_val = new xmlrpcval; + + switch($type) + { + case 'array': + case 'object': + $arr = array(); + while (list($k,$v) = each($php_val)) + { + $arr[$k] = xmlrpc_encode($v); + } + $xmlrpc_val->addStruct($arr); + break; + case 'integer': + $xmlrpc_val->addScalar($php_val, $xmlrpcInt); + break; + case 'double': + $xmlrpc_val->addScalar($php_val, $xmlrpcDouble); + break; + case 'string': + $xmlrpc_val->addScalar($php_val, $xmlrpcString); + break; + // <G_Giunta_2001-02-29> + // Add support for encoding/decoding of booleans, since they are supported in PHP + case 'boolean': + $xmlrpc_val->addScalar($php_val, $xmlrpcBoolean); + break; + // </G_Giunta_2001-02-29> + //case 'unknown type': + default: + // giancarlo pinerolo <ping@alt.it> + // it has to return + // an empty object in case (which is already + // at this point), not a boolean. + break; + } + return $xmlrpc_val; } - return $xmlrpc_val; } ?> diff --git a/modules/xmlrpc/xmlrpcs.inc b/modules/xmlrpc/xmlrpcs.inc index 51411712..c361fe39 100755 --- a/modules/xmlrpc/xmlrpcs.inc +++ b/modules/xmlrpc/xmlrpcs.inc @@ -1,7 +1,7 @@ <?php // by Edd Dumbill (C) 1999-2002 // <edd@usefulinc.com> -// $Id: xmlrpcs.inc,v 1.7 2002/12/19 12:40:01 milosch Exp $ +// $Id: xmlrpcs.inc,v 1.17 2005/04/24 18:16:21 ggiunta Exp $ // Copyright (c) 1999,2000,2002 Edd Dumbill. // All rights reserved. @@ -283,7 +283,7 @@ global $_xmlrpc_debuginfo; if ($_xmlrpc_debuginfo!='') { - return "<!-- DEBUG INFO:\n\n" . $_xmlrpc_debuginfo . "\n-->\n"; + return "<!-- DEBUG INFO:\n\n" . xmlrpc_encode_entitites($_xmlrpc_debuginfo) . "\n-->\n"; } else { @@ -293,14 +293,15 @@ function service() { - global $xmlrpc_defencoding; + //global $xmlrpc_defencoding; $r=$this->parseRequest(); - $payload='<?xml version="1.0" encoding="' . $xmlrpc_defencoding . '"?>' . "\n" + //$payload='<?xml version="1.0" encoding="' . $xmlrpc_defencoding . '"?' . '>' . "\n" + $payload='<?xml version="1.0" ?' . '>' . "\n" . $this->serializeDebug() . $r->serialize(); - Header("Content-type: text/xml\r\nContent-length: " . - strlen($payload)); + header('Content-Type: text/xml'); + header('Content-Length: ' . (int)strlen($payload)); print $payload; } @@ -347,23 +348,29 @@ } if ($itsOK) { - return array(1); + return array(1,''); } } } - return array(0, "Wanted ${wanted}, got ${got} at param ${pno})"); + if (isset($wanted)) + return array(0, "Wanted ${wanted}, got ${got} at param ${pno})"); + else + return array(0, "No method signature matches number of parameters"); } function parseRequest($data='') { global $_xh,$HTTP_RAW_POST_DATA; global $xmlrpcerr, $xmlrpcstr, $xmlrpcerrxml, $xmlrpc_defencoding, - $_xmlrpcs_dmap; + $_xmlrpcs_dmap, $xmlrpc_internalencoding; if ($data=='') { $data=$HTTP_RAW_POST_DATA; } + // G. Giunta 2005/02/13: we do NOT expect to receive html entities + // so we do not try to convert them into xml character entities + //$data = xmlrpc_html_entity_xlate($data); $parser = xml_parser_create($xmlrpc_defencoding); $_xh[$parser]=array(); @@ -376,6 +383,10 @@ // decompose incoming XML into request structure xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell + // the xml parser to give us back data in the expected charset + xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $xmlrpc_internalencoding); + xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee'); xml_set_character_data_handler($parser, 'xmlrpc_cd'); xml_set_default_handler($parser, 'xmlrpc_dh'); @@ -395,16 +406,30 @@ $m=new xmlrpcmsg($_xh[$parser]['method']); // now add parameters in $plist=''; + $allOK = 1; for($i=0; $i<sizeof($_xh[$parser]['params']); $i++) { //print "<!-- " . $_xh[$parser]['params'][$i]. "-->\n"; - $plist.="$i - " . $_xh[$parser]['params'][$i]. " \n"; - eval('$m->addParam(' . $_xh[$parser]['params'][$i]. ');'); + $plist.="$i - " . $_xh[$parser]['params'][$i]. ";\n"; + $allOK = 0; + @eval('$m->addParam(' . $_xh[$parser]['params'][$i]. '); $allOK=1;'); + if (!$allOK) + { + break; + } } // uncomment this to really see what the server's getting! // xmlrpc_debugmsg($plist); - - $r = $this->execute($m); + if (!$allOK) + { + $r = new xmlrpcresp(0, + $xmlrpcerr['incorrect_params'], + $xmlrpcstr['incorrect_params'] . ": xml error in param " . $i); + } + else + { + $r = $this->execute($m); + } } return $r; } @@ -429,13 +454,15 @@ if (isset($dmap[$methName]['signature'])) { $sig = $dmap[$methName]['signature']; - list ($ok, $errstr) = $this->verifySignature($m, $sig); - if (!$ok) + list($ok, $errstr) = $this->verifySignature($m, $sig); + if(!$ok) { // Didn't match. - return new xmlrpcresp(0, + return new xmlrpcresp( + 0, $xmlrpcerr['incorrect_params'], - $xmlrpcstr['incorrect_params'] . ": ${errstr}"); + $xmlrpcstr['incorrect_params'] . ": ${errstr}" + ); } } |