b2evolution

Multilingual multiuser multiblog engine

b2evolution Technical Documentation (0.9.x) [ class tree: evocore ] [ index: evocore ] [ all elements ]

Source for file _functions_xmlrpcs.php

Documentation is available at _functions_xmlrpcs.php

  1. <?php
  2. /**
  3.  * @package evocore
  4.  * @subpackage xmlrpc {@link http://xmlrpc.usefulinc.com/doc/}
  5.  * @copyright Edd Dumbill <edd@usefulinc.com> (C) 1999-2002
  6.  */
  7. // by Edd Dumbill (C) 1999-2002
  8. // <edd@usefulinc.com>
  9. // $Id: _functions_xmlrpcs.php,v 1.4.2.6 2005/08/31 19:32:31 fplanque Exp $
  10.  
  11. // Copyright (c) 1999,2000,2002 Edd Dumbill.
  12. // All rights reserved.
  13. //
  14. // Redistribution and use in source and binary forms, with or without
  15. // modification, are permitted provided that the following conditions
  16. // are met:
  17. //
  18. //    * Redistributions of source code must retain the above copyright
  19. //      notice, this list of conditions and the following disclaimer.
  20. //
  21. //    * Redistributions in binary form must reproduce the above
  22. //      copyright notice, this list of conditions and the following
  23. //      disclaimer in the documentation and/or other materials provided
  24. //      with the distribution.
  25. //
  26. //    * Neither the name of the "XML-RPC for PHP" nor the names of its
  27. //      contributors may be used to endorse or promote products derived
  28. //      from this software without specific prior written permission.
  29. //
  30. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  33. // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  34. // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  35. // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  36. // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  37. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  41. // OF THE POSSIBILITY OF SUCH DAMAGE.
  42.  
  43. if!defined('DB_USER') ) die'Please, do not access this page directly.' );
  44.  
  45.     // XML RPC Server class
  46.     // requires: _xmlrpc.php
  47.  
  48.     // listMethods: either a string, or nothing
  49.     $_xmlrpcs_listMethods_sig=array(array($xmlrpcArray$xmlrpcString)array($xmlrpcArray));
  50.     $_xmlrpcs_listMethods_doc='This method lists all the methods that the XML-RPC server knows how to dispatch';
  51.     /**
  52.      * listMethods: either a string, or nothing
  53.      */
  54.     function _xmlrpcs_listMethods($server$m)
  55.     {
  56.         global $xmlrpcerr$xmlrpcstr$_xmlrpcs_dmap;
  57.         $v=new xmlrpcval();
  58.         $dmap=$server->dmap;
  59.         $outAr=array();
  60.         for(reset($dmap)list($key$val)=each($dmap))
  61.         {
  62.             $outAr[]=new xmlrpcval($key'string');
  63.         }
  64.         $dmap=$_xmlrpcs_dmap;
  65.         for(reset($dmap)list($key$val)=each($dmap))
  66.         {
  67.             $outAr[]=new xmlrpcval($key'string');
  68.         }
  69.         $v->addArray($outAr);
  70.         return new xmlrpcresp($v);
  71.     }
  72.  
  73.     $_xmlrpcs_methodSignature_sig=array(array($xmlrpcArray$xmlrpcString));
  74.     $_xmlrpcs_methodSignature_doc='Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature)';
  75.     /**
  76.      * {@internal _xmlrpcs_methodSignature(-)}}
  77.      */
  78.     function _xmlrpcs_methodSignature($server$m)
  79.     {
  80.         global $xmlrpcerr$xmlrpcstr$_xmlrpcs_dmap;
  81.  
  82.         $methName=$m->getParam(0);
  83.         $methName=$methName->scalarval();
  84.         if (ereg("^system\."$methName))
  85.         {
  86.             $dmap=$_xmlrpcs_dmap$sysCall=1;
  87.         }
  88.         else
  89.         {
  90.             $dmap=$server->dmap$sysCall=0;
  91.         }
  92.         //    print "<!-- ${methName} -->\n";
  93.         if (isset($dmap[$methName]))
  94.         {
  95.             if ($dmap[$methName]['signature'])
  96.             {
  97.                 $sigs=array();
  98.                 $thesigs=$dmap[$methName]['signature'];
  99.                 for($i=0$i<sizeof($thesigs)$i++)
  100.                 {
  101.                     $cursig=array();
  102.                     $inSig=$thesigs[$i];
  103.                     for($j=0$j<sizeof($inSig)$j++)
  104.                     {
  105.                         $cursig[]=new xmlrpcval($inSig[$j]'string');
  106.                     }
  107.                     $sigs[]=new xmlrpcval($cursig'array');
  108.                 }
  109.                 $r=new xmlrpcresp(new xmlrpcval($sigs'array'));
  110.             }
  111.             else
  112.             {
  113.                 $r=new xmlrpcresp(new xmlrpcval('undef''string'));
  114.             }
  115.         }
  116.         else
  117.         {
  118.             $r=new xmlrpcresp(0,$xmlrpcerr['introspect_unknown']$xmlrpcstr['introspect_unknown']);
  119.         }
  120.         return $r;
  121.     }
  122.  
  123.     $_xmlrpcs_methodHelp_sig=array(array($xmlrpcString$xmlrpcString));
  124.     $_xmlrpcs_methodHelp_doc='Returns help text if defined for the method passed, otherwise returns an empty string';
  125.     function _xmlrpcs_methodHelp($server$m)
  126.     {
  127.         global $xmlrpcerr$xmlrpcstr$_xmlrpcs_dmap;
  128.  
  129.         $methName=$m->getParam(0);
  130.         $methName=$methName->scalarval();
  131.         if (ereg("^system\."$methName))
  132.         {
  133.             $dmap=$_xmlrpcs_dmap$sysCall=1;
  134.         }
  135.         else
  136.         {
  137.             $dmap=$server->dmap$sysCall=0;
  138.         }
  139.         // print "<!-- ${methName} -->\n";
  140.         if (isset($dmap[$methName]))
  141.         {
  142.             if ($dmap[$methName]['docstring'])
  143.             {
  144.                 $r=new xmlrpcresp(new xmlrpcval($dmap[$methName]['docstring'])'string');
  145.             }
  146.             else
  147.             {
  148.                 $r=new xmlrpcresp(new xmlrpcval('''string'));
  149.             }
  150.         }
  151.         else
  152.         {
  153.             $r=new xmlrpcresp(0$xmlrpcerr['introspect_unknown']$xmlrpcstr['introspect_unknown']);
  154.         }
  155.         return $r;
  156.     }
  157.  
  158.     $_xmlrpcs_multicall_sig array(array($xmlrpcArray$xmlrpcArray));
  159.     $_xmlrpcs_multicall_doc 'Boxcar multiple RPC calls in one request. See http://www.xmlrpc.com/discuss/msgReader$1208 for details';
  160.  
  161.     function _xmlrpcs_multicall_error($err)
  162.     {
  163.         if (is_string($err))
  164.         {
  165.             global $xmlrpcerr$xmlrpcstr;
  166.             $str  $xmlrpcstr["multicall_${err}"];
  167.             $code $xmlrpcerr["multicall_${err}"];
  168.         }
  169.         else
  170.         {
  171.             $code $err->faultCode();
  172.             $str $err->faultString();
  173.         }
  174.         $struct['faultCode'new xmlrpcval($code'int');
  175.         $struct['faultString'new xmlrpcval($str'string');
  176.         return new xmlrpcval($struct'struct');
  177.     }
  178.  
  179.     function _xmlrpcs_multicall_do_call($server$call)
  180.     {
  181.         if ($call->kindOf(!= 'struct')
  182.         {
  183.             return _xmlrpcs_multicall_error('notstruct');
  184.         }
  185.         $methName $call->structmem('methodName');
  186.         if (!$methName)
  187.         {
  188.             return _xmlrpcs_multicall_error('nomethod');
  189.         }
  190.         if ($methName->kindOf(!= 'scalar' || $methName->scalartyp(!= 'string')
  191.         {
  192.             return _xmlrpcs_multicall_error('notstring');
  193.         }
  194.         if ($methName->scalarval(== 'system.multicall')
  195.         {
  196.             return _xmlrpcs_multicall_error('recursion');
  197.         }
  198.  
  199.         $params $call->structmem('params');
  200.         if (!$params)
  201.         {
  202.             return _xmlrpcs_multicall_error('noparams');
  203.         }
  204.         if ($params->kindOf(!= 'array')
  205.         {
  206.             return _xmlrpcs_multicall_error('notarray');
  207.         }
  208.         $numParams $params->arraysize();
  209.  
  210.         $msg new xmlrpcmsg($methName->scalarval());
  211.         for ($i 0$i $numParams$i++)
  212.         {
  213.             $msg->addParam($params->arraymem($i));
  214.         }
  215.  
  216.         $result $server->execute($msg);
  217.  
  218.         if ($result->faultCode(!= 0)
  219.         {
  220.             return _xmlrpcs_multicall_error($result);    // Method returned fault.
  221.         }
  222.  
  223.         return new xmlrpcval(array($result->value())'array');
  224.     }
  225.  
  226.     function _xmlrpcs_multicall($server$m)
  227.     {
  228.         $calls $m->getParam(0);
  229.         $numCalls $calls->arraysize();
  230.         $result array();
  231.  
  232.         for ($i 0$i $numCalls$i++)
  233.         {
  234.             $call $calls->arraymem($i);
  235.             $result[$i_xmlrpcs_multicall_do_call($server$call);
  236.         }
  237.  
  238.         return new xmlrpcresp(new xmlrpcval($result'array'));
  239.     }
  240.  
  241.     $_xmlrpcs_dmap=array(
  242.         'system.listMethods' => array(
  243.             'function' => '_xmlrpcs_listMethods',
  244.             'signature' => $_xmlrpcs_listMethods_sig,
  245.             'docstring' => $_xmlrpcs_listMethods_doc),
  246.         'system.methodHelp' => array(
  247.             'function' => '_xmlrpcs_methodHelp',
  248.             'signature' => $_xmlrpcs_methodHelp_sig,
  249.             'docstring' => $_xmlrpcs_methodHelp_doc),
  250.         'system.methodSignature' => array(
  251.             'function' => '_xmlrpcs_methodSignature',
  252.             'signature' => $_xmlrpcs_methodSignature_sig,
  253.             'docstring' => $_xmlrpcs_methodSignature_doc),
  254.         'system.multicall' => array(
  255.             'function' => '_xmlrpcs_multicall',
  256.             'signature' => $_xmlrpcs_multicall_sig,
  257.             'docstring' => $_xmlrpcs_multicall_doc
  258.         )
  259.     );
  260.  
  261.     /**
  262.      * Register a debugging message to be sent back in output
  263.      *
  264.      * evocore addition: make debug output optional
  265.      */
  266.     $_xmlrpc_debuginfo='';
  267.     function xmlrpc_debugmsg($m)
  268.     {
  269.         global $_xmlrpc_debuginfo;
  270.         $_xmlrpc_debuginfo=$_xmlrpc_debuginfo $m "\n";
  271.     }
  272.  
  273.     /**
  274.      * @package evocore
  275.      * @subpackage xmlrpc
  276.      */
  277.     class xmlrpc_server
  278.     {
  279.         var $dmap=array();
  280.  
  281.         /*
  282.          * Constructor:
  283.          */
  284.         function xmlrpc_server($dispMap=''$serviceNow=1)
  285.         {
  286.             global $HTTP_RAW_POST_DATA;
  287.             // dispMap is a dispatch array of methods
  288.             // mapped to function names and signatures
  289.             // if a method
  290.             // doesn't appear in the map then an unknown
  291.             // method error is generated
  292.             /* milosch - changed to make passing dispMap optional.
  293.              * instead, you can use the class add_to_map() function
  294.              * to add functions manually (borrowed from SOAPX4)
  295.              */
  296.             if($dispMap)
  297.             {
  298.                 $this->dmap = $dispMap;
  299.                 if($serviceNow)
  300.                 {
  301.                     $this->service();
  302.                 }
  303.             }
  304.         }
  305.  
  306.         function serializeDebug()
  307.         {
  308.             global $_xmlrpc_debuginfo;
  309.             if ($_xmlrpc_debuginfo!='')
  310.             {
  311.                 return "<!-- DEBUG INFO:\n\n" xmlrpc_encode_entitites($_xmlrpc_debuginfo"\n-->\n";
  312.             }
  313.             else
  314.             {
  315.                 return '';
  316.             }
  317.         }
  318.  
  319.         function service()
  320.         {
  321.             //global $xmlrpc_defencoding;
  322.  
  323.             $r=$this->parseRequest();
  324.             //$payload='<?xml version="1.0" encoding="' . $xmlrpc_defencoding . '"?' . '>' . "\n"
  325.             // TODO: charset:  encoding=\"iso-8859-1\"
  326.             $payload='<?xml version="1.0" ?' '>' "\n"
  327.                 . $this->serializeDebug()                            // Include debug info as comments
  328.                 . $r->serialize();
  329.             header('Content-Type: text/xml');
  330.             header('Content-Length: ' . (int)strlen($payload));
  331.             print $payload;
  332.         }
  333.  
  334.         /**
  335.          * add a method to the dispatch map
  336.          */
  337.         function add_to_map($methodname,$function,$sig,$doc)
  338.         {
  339.             $this->dmap[$methodnamearray(
  340.                 'function'  => $function,
  341.                 'signature' => $sig,
  342.                 'docstring' => $doc
  343.             );
  344.         }
  345.  
  346.         function verifySignature($in$sig)
  347.         {
  348.             for($i=0$i<sizeof($sig)$i++)
  349.             {
  350.                 // check each possible signature in turn
  351.                 $cursig=$sig[$i];
  352.                 if (sizeof($cursig)==$in->getNumParams()+1)
  353.                 {
  354.                     $itsOK=1;
  355.                     for($n=0$n<$in->getNumParams()$n++)
  356.                     {
  357.                         $p=$in->getParam($n);
  358.                         // print "<!-- $p -->\n";
  359.                         if ($p->kindOf(== 'scalar')
  360.                         {
  361.                             $pt=$p->scalartyp();
  362.                         }
  363.                         else
  364.                         {
  365.                             $pt=$p->kindOf();
  366.                         }
  367.                         // $n+1 as first type of sig is return type
  368.                         if ($pt != $cursig[$n+1])
  369.                         {
  370.                             $itsOK=0;
  371.                             $pno=$n+1$wanted=$cursig[$n+1]$got=$pt;
  372.                             break;
  373.                         }
  374.                     }
  375.                     if ($itsOK)
  376.                     {
  377.                         return array(1,'');
  378.                     }
  379.                 }
  380.             }
  381.             if (isset($wanted))
  382.                 return array(0"Wanted ${wanted}, got ${got} at param ${pno})");
  383.             else
  384.                 return array(0"No method signature matches number of parameters");
  385.         }
  386.  
  387.         /**
  388.          *
  389.          *
  390.          * {@internal parseRequest(-) }}
  391.          */
  392.         function parseRequest($data='')
  393.         {
  394.             global $_xh,$HTTP_RAW_POST_DATA;
  395.             global $xmlrpcerr$xmlrpcstr$xmlrpcerrxml$xmlrpc_defencoding,
  396.             $_xmlrpcs_dmap$xmlrpc_internalencoding;
  397.  
  398.             if ($data=='')
  399.             {
  400.                 $data=$HTTP_RAW_POST_DATA;
  401.             }
  402.             // xmlrpc_debugmsg( 'Data received: ['.$data.']' );
  403.  
  404.             // G. Giunta 2005/02/13: we do NOT expect to receive html entities
  405.             // so we do not try to convert them into xml character entities
  406.             //$data = xmlrpc_html_entity_xlate($data);
  407.             $parser xml_parser_create($xmlrpc_defencoding);
  408.  
  409.             $_xh[$parser]=array();
  410.             //$_xh[$parser]['st']='';
  411.             //$_xh[$parser]['cm']=0;
  412.             $_xh[$parser]['isf']=0;
  413.             $_xh[$parser]['isf_reason']='';
  414.             $_xh[$parser]['params']=array();
  415.             $_xh[$parser]['stack']=array();
  416.             $_xh[$parser]['valuestack'array();
  417.             $_xh[$parser]['method']='';
  418.  
  419.             // decompose incoming XML into request structure
  420.  
  421.             xml_parser_set_option($parserXML_OPTION_CASE_FOLDINGtrue);
  422.             // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell
  423.             // the xml parser to give us back data in the expected charset
  424.             xml_parser_set_option($parserXML_OPTION_TARGET_ENCODING$xmlrpc_internalencoding);
  425.  
  426.             xml_set_element_handler($parser'xmlrpc_se''xmlrpc_ee');
  427.             xml_set_character_data_handler($parser'xmlrpc_cd');
  428.             xml_set_default_handler($parser'xmlrpc_dh');
  429.             if (!xml_parse($parser$data1))
  430.             {
  431.                 // return XML error as a faultCode
  432.                 $r=new xmlrpcresp(0,
  433.                 $xmlrpcerrxml+xml_get_error_code($parser),
  434.                 sprintf('XML error: %s at line %d',
  435.                     xml_error_string(xml_get_error_code($parser)),
  436.                     xml_get_current_line_number($parser)));
  437.                 xml_parser_free($parser);
  438.             }
  439.             else
  440.             if ($_xh[$parser]['isf'])
  441.             {
  442.                 xml_parser_free($parser);
  443.                 $r=new xmlrpcresp(0,
  444.                     $xmlrpcerr['invalid_request'],
  445.                     $xmlrpcstr['invalid_request'' ' $_xh[$parser]['isf_reason']);
  446.             }
  447.             else
  448.             {
  449.                 xml_parser_free($parser);
  450.  
  451.                 $m=new xmlrpcmsg($_xh[$parser]['method']);
  452.                 // now add parameters in
  453.                 $plist='';
  454.                 //$allOK = 1;
  455.                 for($i=0$i<sizeof($_xh[$parser]['params'])$i++)
  456.                 {
  457.                     //print "<!-- " . $_xh[$parser]['params'][$i]. "-->\n";
  458.                     $plist.="$i - .  $_xh[$parser]['params'][$i]";\n";
  459.                     //$allOK = 0;
  460.                     //@eval('$m->addParam(' . $_xh[$parser]['params'][$i]. '); $allOK=1;');
  461.                     @$m->addParam($_xh[$parser]['params'][$i]);
  462.                     //if (!$allOK)
  463.                     //{
  464.                     //    break;
  465.                     //}
  466.                 }
  467.                 // uncomment this to really see what the server's getting!
  468.                 // xmlrpc_debugmsg($plist);
  469.                 //if (!$allOK)
  470.                 //{
  471.                 //    $r = new xmlrpcresp(0,
  472.                   //        $xmlrpcerr['incorrect_params'],
  473.                 //        $xmlrpcstr['incorrect_params'] . ": xml error in param " . $i);
  474.                 //}
  475.                 //else
  476.                 //{
  477.                     $r $this->execute($m);
  478.                 //}
  479.             }
  480.             return $r;
  481.         }
  482.  
  483.         function execute ($m)
  484.         {
  485.             global $xmlrpcerr$xmlrpcstr$_xmlrpcs_dmap;
  486.             // now to deal with the method
  487.             $methName $m->method();
  488.             logIO'I''Called method:'.$methName );
  489.             $sysCall ereg("^system\."$methName);
  490.             $dmap $sysCall $_xmlrpcs_dmap $this->dmap;
  491.  
  492.             if (!isset($dmap[$methName]['function']))
  493.             {
  494.                 // No such method
  495.                 return new xmlrpcresp(0,
  496.                     $xmlrpcerr['unknown_method'],
  497.                     $xmlrpcstr['unknown_method']);
  498.             }
  499.  
  500.             // Check signature.
  501.             if (isset($dmap[$methName]['signature']))
  502.             {
  503.                 $sig $dmap[$methName]['signature'];
  504.                 list($ok$errstr$this->verifySignature($m$sig);
  505.                 if(!$ok)
  506.                 {
  507.                     // Didn't match.
  508.                     return new xmlrpcresp(
  509.                         0,
  510.                         $xmlrpcerr['incorrect_params'],
  511.                         $xmlrpcstr['incorrect_params'": ${errstr}"
  512.                     );
  513.                 }
  514.             }
  515.  
  516.             $func $dmap[$methName]['function'];
  517.  
  518.             if ($sysCall)
  519.             {
  520.                 return call_user_func($func$this$m);
  521.             }
  522.             else
  523.             {
  524.                 return call_user_func($func$m);
  525.             }
  526.         }
  527.  
  528.         function echoInput()
  529.         {
  530.             global $HTTP_RAW_POST_DATA;
  531.  
  532.             // a debugging routine: just echos back the input
  533.             // packet as a string value
  534.  
  535.             $r=new xmlrpcresp;
  536.             $r->xv=new xmlrpcval"'Aha said I: '" $HTTP_RAW_POST_DATA'string');
  537.             print $r->serialize();
  538.         }
  539.     }
  540. ?>

Documentation generated on Tue, 20 May 2008 01:55:19 +0200 by phpDocumentor 1.4.2