b2evolution

Multilingual multiuser multiblog engine

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

Source for file _functions_xmlrpc.php

Documentation is available at _functions_xmlrpc.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-2001
  6.  */
  7. // by Edd Dumbill (C) 1999-2002
  8. // <edd@usefulinc.com>
  9. // $Id: _functions_xmlrpc.php,v 1.9.2.6 2005/08/31 19:32:31 fplanque Exp $
  10.  
  11. // additional fixes for case of missing xml extension file by Michel Valdrighi <m@tidakada.com>
  12.  
  13. // Copyright (c) 1999,2000,2002 Edd Dumbill.
  14. // All rights reserved.
  15. //
  16. // Redistribution and use in source and binary forms, with or without
  17. // modification, are permitted provided that the following conditions
  18. // are met:
  19. //
  20. //    * Redistributions of source code must retain the above copyright
  21. //      notice, this list of conditions and the following disclaimer.
  22. //
  23. //    * Redistributions in binary form must reproduce the above
  24. //      copyright notice, this list of conditions and the following
  25. //      disclaimer in the documentation and/or other materials provided
  26. //      with the distribution.
  27. //
  28. //    * Neither the name of the "XML-RPC for PHP" nor the names of its
  29. //      contributors may be used to endorse or promote products derived
  30. //      from this software without specific prior written permission.
  31. //
  32. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  35. // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  36. // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  37. // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  38. // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  39. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  40. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  41. // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  43. // OF THE POSSIBILITY OF SUCH DAMAGE.
  44.  
  45. if!defined('DB_USER') ) die'Please, do not access this page directly.' );
  46.  
  47.     # b2 fix. some servers have stupid warnings
  48.     # error_reporting(0);
  49.  
  50.     /**
  51.      * logIO(-)
  52.      */
  53.     if (!function_exists('logIO'))
  54.     {
  55.         function logIO($m="",$n="")
  56.         {
  57.             return(true);
  58.         }
  59.     }
  60.  
  61.     // Original fix for missing extension file by "Michel Valdrighi" <m@tidakada.com>
  62.     if(function_exists('xml_parser_create'))
  63.     {
  64.         define("CANUSEXMLRPC"1);
  65.     }
  66.     elseif!(bool)ini_get('enable_dl'|| (bool)ini_get('safe_mode'))
  67.     // We'll not be able to do dynamic loading (fix by Sakichan)
  68.         /**
  69.          * @ignore
  70.          */
  71.         define("CANUSEXMLRPC"0);
  72.     }
  73.     elseif($WINDIR)
  74.     {    // Win 32 fix. From: "Leo West" <lwest@imaginet.fr>
  75.         if (@dl("php3_xml.dll"))
  76.         {
  77.             /**
  78.              * @ignore
  79.              */
  80.             define("CANUSEXMLRPC"1);
  81.         }
  82.         else
  83.         {
  84.             /**
  85.              * @ignore
  86.              */
  87.             define("CANUSEXMLRPC"0);
  88.         }
  89.     }
  90.     else
  91.     {
  92.         if (@dl("xml.so"))
  93.         {
  94.             /**
  95.              * @ignore
  96.              */
  97.             define("CANUSEXMLRPC"1);
  98.         }
  99.         else
  100.         {
  101.             /**
  102.              * @ignore
  103.              */
  104.             define("CANUSEXMLRPC"0);
  105.         }
  106.     }
  107.  
  108.     ifCANUSEXMLRPC == )
  109.     {
  110.         return;
  111.     }
  112.  
  113.  
  114.     // G. Giunta 2005/01/29: declare global these variables,
  115.     // so that xmlrpc.inc will work even if included from within a function
  116.     // NB: it will give warnings in PHP3, so we comment it out
  117.     // Milosch: Next round, maybe we should explicitly request these via $GLOBALS where used.
  118.     if (phpversion(>= '4')
  119.     {
  120.         global $xmlrpcI4;
  121.         global $xmlrpcInt;
  122.         global $xmlrpcDouble;
  123.         global $xmlrpcBoolean;
  124.         global $xmlrpcString;
  125.         global $xmlrpcDateTime;
  126.         global $xmlrpcBase64;
  127.         global $xmlrpcArray;
  128.         global $xmlrpcStruct;
  129.  
  130.         global $xmlrpcTypes;
  131.         global $xmlEntities;
  132.         global $xmlrpcerr;
  133.         global $xmlrpcstr;
  134.         global $xmlrpc_defencoding;
  135.         global $xmlrpc_internalencoding;
  136.         global $xmlrpcName;
  137.         global $xmlrpcVersion;
  138.         global $xmlrpcerruser;
  139.         global $xmlrpcerrxml;
  140.         global $xmlrpc_backslash;
  141.         global $_xh;
  142.     }
  143.     $xmlrpcI4='i4';
  144.     $xmlrpcInt='int';
  145.     $xmlrpcBoolean='boolean';
  146.     $xmlrpcDouble='double';
  147.     $xmlrpcString='string';
  148.     $xmlrpcDateTime='dateTime.iso8601';
  149.     $xmlrpcBase64='base64';
  150.     $xmlrpcArray='array';
  151.     $xmlrpcStruct='struct';
  152.  
  153.     $xmlrpcTypes=array(
  154.         $xmlrpcI4       => 1,
  155.         $xmlrpcInt      => 1,
  156.         $xmlrpcBoolean  => 1,
  157.         $xmlrpcString   => 1,
  158.         $xmlrpcDouble   => 1,
  159.         $xmlrpcDateTime => 1,
  160.         $xmlrpcBase64   => 1,
  161.         $xmlrpcArray    => 2,
  162.         $xmlrpcStruct   => 3
  163.     );
  164.  
  165.     $xmlrpc_valid_parents array(
  166.         'BOOLEAN' => array('VALUE'),
  167.         'I4' => array('VALUE'),
  168.         'INT' => array('VALUE'),
  169.         'STRING' => array('VALUE'),
  170.         'DOUBLE' => array('VALUE'),
  171.         'DATETIME.ISO8601' => array('VALUE'),
  172.         'BASE64' => array('VALUE'),
  173.         'ARRAY' => array('VALUE'),
  174.         'STRUCT' => array('VALUE'),
  175.         'PARAM' => array('PARAMS'),
  176.         'METHODNAME' => array('METHODCALL'),
  177.         'PARAMS' => array('METHODCALL''METHODRESPONSE'),
  178.         'MEMBER' => array('STRUCT'),
  179.         'NAME' => array('MEMBER'),
  180.         'DATA' => array('ARRAY'),
  181.         'FAULT' => array('METHODRESPONSE'),
  182.         'VALUE' => array('MEMBER''DATA''PARAM''FAULT'),
  183.     );
  184.  
  185.     $xmlEntities=array(
  186.         'amp'  => '&',
  187.         'quot' => '"',
  188.         'lt'   => '<',
  189.         'gt'   => '>',
  190.         'apos' => "'"
  191.     );
  192.     // These are left untranslated because they are sent back to the remote system
  193.     $xmlrpcerr['unknown_method']=1;
  194.     $xmlrpcstr['unknown_method']='Unknown method';
  195.     $xmlrpcerr['invalid_return']=2;
  196.     $xmlrpcstr['invalid_return']='Invalid return payload: enable debugging to examine incoming payload';
  197.     $xmlrpcerr['incorrect_params']=3;
  198.     $xmlrpcstr['incorrect_params']='Incorrect parameters passed to method';
  199.     $xmlrpcerr['introspect_unknown']=4;
  200.     $xmlrpcstr['introspect_unknown']="Can't introspect: method unknown";
  201.     $xmlrpcerr['http_error']=5;
  202.     $xmlrpcstr['http_error']="Didn't receive 200 OK from remote server.";
  203.     $xmlrpcerr['no_data']=6;
  204.     $xmlrpcstr['no_data']='No data received from server.';
  205.     $xmlrpcerr['no_ssl']=7;
  206.     $xmlrpcstr['no_ssl']='No SSL support compiled in.';
  207.     $xmlrpcerr['curl_fail']=8;
  208.     $xmlrpcstr['curl_fail']='CURL error';
  209.     $xmlrpcerr['invalid_request']=15;
  210.     $xmlrpcstr['invalid_request']='Invalid request payload';
  211.  
  212.     $xmlrpcerr['multicall_notstruct'9;
  213.     $xmlrpcstr['multicall_notstruct''system.multicall expected struct';
  214.     $xmlrpcerr['multicall_nomethod']  10;
  215.     $xmlrpcstr['multicall_nomethod']  'missing methodName';
  216.     $xmlrpcerr['multicall_notstring'11;
  217.     $xmlrpcstr['multicall_notstring''methodName is not a string';
  218.     $xmlrpcerr['multicall_recursion'12;
  219.     $xmlrpcstr['multicall_recursion''recursive system.multicall forbidden';
  220.     $xmlrpcerr['multicall_noparams']  13;
  221.     $xmlrpcstr['multicall_noparams']  'missing params';
  222.     $xmlrpcerr['multicall_notarray']  14;
  223.     $xmlrpcstr['multicall_notarray']  'params is not an array';
  224.  
  225.     // The charset encoding expected by the server for received messages and
  226.     // by the client for received responses
  227.     $xmlrpc_defencoding='UTF-8';
  228.     // The encoding used by PHP.
  229.     // String values received will be converted to this.
  230.     $xmlrpc_internalencoding='ISO-8859-1';
  231.  
  232.     $xmlrpcName='XML-RPC for PHP';
  233.     $xmlrpcVersion='1.2';
  234.  
  235.     // let user errors start at 800
  236.     $xmlrpcerruser=800;
  237.     // let XML parse errors start at 100
  238.     $xmlrpcerrxml=100;
  239.  
  240.     // formulate backslashes for escaping regexp
  241.     $xmlrpc_backslash=chr(92).chr(92);
  242.  
  243.     // used to store state during parsing
  244.     // quick explanation of components:
  245.     //   ac - used to accumulate values
  246.     //   isf - used to indicate a fault
  247.     //   lv - used to indicate "looking for a value": implements
  248.     //        the logic to allow values with no types to be strings
  249.     //   params - used to store parameters in method calls
  250.     //   method - used to store method name
  251.     //   stack - array with genealogy of xml elements names:
  252.     //           used to validate nesting of xmlrpc elements
  253.  
  254.     $_xh=array();
  255.  
  256.     /**
  257.     * To help correct communication of non-ascii chars inside strings, regardless
  258.     * of the charset used when sending requests, parsing them, sending responses
  259.     * and parsing responses, convert all non-ascii chars present in the message
  260.     * into their equivalent 'charset entity'. Charset entities enumerated this way
  261.     * are independent of the charset encoding used to transmit them, and all XML
  262.     * parsers are bound to understand them.
  263.     */
  264.     function xmlrpc_entity_decode($string)
  265.     {
  266.         $top=split('&'$string);
  267.         $op='';
  268.         $i=0;
  269.         while($i<sizeof($top))
  270.         {
  271.             if (ereg("^([#a-zA-Z0-9]+);"$top[$i]$regs))
  272.             {
  273.                 $op.=ereg_replace("^[#a-zA-Z0-9]+;",
  274.                 xmlrpc_lookup_entity($regs[1]),
  275.                 $top[$i]);
  276.             }
  277.             else
  278.             {
  279.                 if ($i==0)
  280.                 {
  281.                     $op=$top[$i];
  282.                 }
  283.                 else
  284.                 {
  285.                     $op.='&' $top[$i];
  286.                 }
  287.             }
  288.             $i++;
  289.         }
  290.         return $op;
  291.     }
  292.  
  293.     function xmlrpc_lookup_entity($ent)
  294.     {
  295.         global $xmlEntities;
  296.  
  297.         if (isset($xmlEntities[strtolower($ent)]))
  298.         {
  299.             return $xmlEntities[strtolower($ent)];
  300.         }
  301.         if (ereg("^#([0-9]+)$"$ent$regs))
  302.         {
  303.             return chr($regs[1]);
  304.         }
  305.         return '?';
  306.     }
  307.  
  308.     /**
  309.      * These entities originate from HTML specs (1.1, proposed 2.0, etc),
  310.      * and are taken directly from php-4.3.1/ext/mbstring/html_entities.c.
  311.      * Until php provides functionality to translate these entities in its
  312.      * core library, use this function.
  313.      */
  314.     function xmlrpc_html_entity_xlate($data '')
  315.     {
  316.         $entities array(
  317.             "&nbsp;" => "&#160;",
  318.             "&iexcl;" => "&#161;",
  319.             "&cent;" => "&#162;",
  320.             "&pound;" => "&#163;",
  321.             "&curren;" => "&#164;",
  322.             "&yen;" => "&#165;",
  323.             "&brvbar;" => "&#166;",
  324.             "&sect;" => "&#167;",
  325.             "&uml;" => "&#168;",
  326.             "&copy;" => "&#169;",
  327.             "&ordf;" => "&#170;",
  328.             "&laquo;" => "&#171;",
  329.             "&not;" => "&#172;",
  330.             "&shy;" => "&#173;",
  331.             "&reg;" => "&#174;",
  332.             "&macr;" => "&#175;",
  333.             "&deg;" => "&#176;",
  334.             "&plusmn;" => "&#177;",
  335.             "&sup2;" => "&#178;",
  336.             "&sup3;" => "&#179;",
  337.             "&acute;" => "&#180;",
  338.             "&micro;" => "&#181;",
  339.             "&para;" => "&#182;",
  340.             "&middot;" => "&#183;",
  341.             "&cedil;" => "&#184;",
  342.             "&sup1;" => "&#185;",
  343.             "&ordm;" => "&#186;",
  344.             "&raquo;" => "&#187;",
  345.             "&frac14;" => "&#188;",
  346.             "&frac12;" => "&#189;",
  347.             "&frac34;" => "&#190;",
  348.             "&iquest;" => "&#191;",
  349.             "&Agrave;" => "&#192;",
  350.             "&Aacute;" => "&#193;",
  351.             "&Acirc;" => "&#194;",
  352.             "&Atilde;" => "&#195;",
  353.             "&Auml;" => "&#196;",
  354.             "&Aring;" => "&#197;",
  355.             "&AElig;" => "&#198;",
  356.             "&Ccedil;" => "&#199;",
  357.             "&Egrave;" => "&#200;",
  358.             "&Eacute;" => "&#201;",
  359.             "&Ecirc;" => "&#202;",
  360.             "&Euml;" => "&#203;",
  361.             "&Igrave;" => "&#204;",
  362.             "&Iacute;" => "&#205;",
  363.             "&Icirc;" => "&#206;",
  364.             "&Iuml;" => "&#207;",
  365.             "&ETH;" => "&#208;",
  366.             "&Ntilde;" => "&#209;",
  367.             "&Ograve;" => "&#210;",
  368.             "&Oacute;" => "&#211;",
  369.             "&Ocirc;" => "&#212;",
  370.             "&Otilde;" => "&#213;",
  371.             "&Ouml;" => "&#214;",
  372.             "&times;" => "&#215;",
  373.             "&Oslash;" => "&#216;",
  374.             "&Ugrave;" => "&#217;",
  375.             "&Uacute;" => "&#218;",
  376.             "&Ucirc;" => "&#219;",
  377.             "&Uuml;" => "&#220;",
  378.             "&Yacute;" => "&#221;",
  379.             "&THORN;" => "&#222;",
  380.             "&szlig;" => "&#223;",
  381.             "&agrave;" => "&#224;",
  382.             "&aacute;" => "&#225;",
  383.             "&acirc;" => "&#226;",
  384.             "&atilde;" => "&#227;",
  385.             "&auml;" => "&#228;",
  386.             "&aring;" => "&#229;",
  387.             "&aelig;" => "&#230;",
  388.             "&ccedil;" => "&#231;",
  389.             "&egrave;" => "&#232;",
  390.             "&eacute;" => "&#233;",
  391.             "&ecirc;" => "&#234;",
  392.             "&euml;" => "&#235;",
  393.             "&igrave;" => "&#236;",
  394.             "&iacute;" => "&#237;",
  395.             "&icirc;" => "&#238;",
  396.             "&iuml;" => "&#239;",
  397.             "&eth;" => "&#240;",
  398.             "&ntilde;" => "&#241;",
  399.             "&ograve;" => "&#242;",
  400.             "&oacute;" => "&#243;",
  401.             "&ocirc;" => "&#244;",
  402.             "&otilde;" => "&#245;",
  403.             "&ouml;" => "&#246;",
  404.             "&divide;" => "&#247;",
  405.             "&oslash;" => "&#248;",
  406.             "&ugrave;" => "&#249;",
  407.             "&uacute;" => "&#250;",
  408.             "&ucirc;" => "&#251;",
  409.             "&uuml;" => "&#252;",
  410.             "&yacute;" => "&#253;",
  411.             "&thorn;" => "&#254;",
  412.             "&yuml;" => "&#255;",
  413.             "&OElig;" => "&#338;",
  414.             "&oelig;" => "&#339;",
  415.             "&Scaron;" => "&#352;",
  416.             "&scaron;" => "&#353;",
  417.             "&Yuml;" => "&#376;",
  418.             "&fnof;" => "&#402;",
  419.             "&circ;" => "&#710;",
  420.             "&tilde;" => "&#732;",
  421.             "&Alpha;" => "&#913;",
  422.             "&Beta;" => "&#914;",
  423.             "&Gamma;" => "&#915;",
  424.             "&Delta;" => "&#916;",
  425.             "&Epsilon;" => "&#917;",
  426.             "&Zeta;" => "&#918;",
  427.             "&Eta;" => "&#919;",
  428.             "&Theta;" => "&#920;",
  429.             "&Iota;" => "&#921;",
  430.             "&Kappa;" => "&#922;",
  431.             "&Lambda;" => "&#923;",
  432.             "&Mu;" => "&#924;",
  433.             "&Nu;" => "&#925;",
  434.             "&Xi;" => "&#926;",
  435.             "&Omicron;" => "&#927;",
  436.             "&Pi;" => "&#928;",
  437.             "&Rho;" => "&#929;",
  438.             "&Sigma;" => "&#931;",
  439.             "&Tau;" => "&#932;",
  440.             "&Upsilon;" => "&#933;",
  441.             "&Phi;" => "&#934;",
  442.             "&Chi;" => "&#935;",
  443.             "&Psi;" => "&#936;",
  444.             "&Omega;" => "&#937;",
  445.             "&beta;" => "&#946;",
  446.             "&gamma;" => "&#947;",
  447.             "&delta;" => "&#948;",
  448.             "&epsilon;" => "&#949;",
  449.             "&zeta;" => "&#950;",
  450.             "&eta;" => "&#951;",
  451.             "&theta;" => "&#952;",
  452.             "&iota;" => "&#953;",
  453.             "&kappa;" => "&#954;",
  454.             "&lambda;" => "&#955;",
  455.             "&mu;" => "&#956;",
  456.             "&nu;" => "&#957;",
  457.             "&xi;" => "&#958;",
  458.             "&omicron;" => "&#959;",
  459.             "&pi;" => "&#960;",
  460.             "&rho;" => "&#961;",
  461.             "&sigmaf;" => "&#962;",
  462.             "&sigma;" => "&#963;",
  463.             "&tau;" => "&#964;",
  464.             "&upsilon;" => "&#965;",
  465.             "&phi;" => "&#966;",
  466.             "&chi;" => "&#967;",
  467.             "&psi;" => "&#968;",
  468.             "&omega;" => "&#969;",
  469.             "&thetasym;" => "&#977;",
  470.             "&upsih;" => "&#978;",
  471.             "&piv;" => "&#982;",
  472.             "&ensp;" => "&#8194;",
  473.             "&emsp;" => "&#8195;",
  474.             "&thinsp;" => "&#8201;",
  475.             "&zwnj;" => "&#8204;",
  476.             "&zwj;" => "&#8205;",
  477.             "&lrm;" => "&#8206;",
  478.             "&rlm;" => "&#8207;",
  479.             "&ndash;" => "&#8211;",
  480.             "&mdash;" => "&#8212;",
  481.             "&lsquo;" => "&#8216;",
  482.             "&rsquo;" => "&#8217;",
  483.             "&sbquo;" => "&#8218;",
  484.             "&ldquo;" => "&#8220;",
  485.             "&rdquo;" => "&#8221;",
  486.             "&bdquo;" => "&#8222;",
  487.             "&dagger;" => "&#8224;",
  488.             "&Dagger;" => "&#8225;",
  489.             "&bull;" => "&#8226;",
  490.             "&hellip;" => "&#8230;",
  491.             "&permil;" => "&#8240;",
  492.             "&prime;" => "&#8242;",
  493.             "&Prime;" => "&#8243;",
  494.             "&lsaquo;" => "&#8249;",
  495.             "&rsaquo;" => "&#8250;",
  496.             "&oline;" => "&#8254;",
  497.             "&frasl;" => "&#8260;",
  498.             "&euro;" => "&#8364;",
  499.             "&weierp;" => "&#8472;",
  500.             "&image;" => "&#8465;",
  501.             "&real;" => "&#8476;",
  502.             "&trade;" => "&#8482;",
  503.             "&alefsym;" => "&#8501;",
  504.             "&larr;" => "&#8592;",
  505.             "&uarr;" => "&#8593;",
  506.             "&rarr;" => "&#8594;",
  507.             "&darr;" => "&#8595;",
  508.             "&harr;" => "&#8596;",
  509.             "&crarr;" => "&#8629;",
  510.             "&lArr;" => "&#8656;",
  511.             "&uArr;" => "&#8657;",
  512.             "&rArr;" => "&#8658;",
  513.             "&dArr;" => "&#8659;",
  514.             "&hArr;" => "&#8660;",
  515.             "&forall;" => "&#8704;",
  516.             "&part;" => "&#8706;",
  517.             "&exist;" => "&#8707;",
  518.             "&empty;" => "&#8709;",
  519.             "&nabla;" => "&#8711;",
  520.             "&isin;" => "&#8712;",
  521.             "&notin;" => "&#8713;",
  522.             "&ni;" => "&#8715;",
  523.             "&prod;" => "&#8719;",
  524.             "&sum;" => "&#8721;",
  525.             "&minus;" => "&#8722;",
  526.             "&lowast;" => "&#8727;",
  527.             "&radic;" => "&#8730;",
  528.             "&prop;" => "&#8733;",
  529.             "&infin;" => "&#8734;",
  530.             "&ang;" => "&#8736;",
  531.             "&and;" => "&#8743;",
  532.             "&or;" => "&#8744;",
  533.             "&cap;" => "&#8745;",
  534.             "&cup;" => "&#8746;",
  535.             "&int;" => "&#8747;",
  536.             "&there4;" => "&#8756;",
  537.             "&sim;" => "&#8764;",
  538.             "&cong;" => "&#8773;",
  539.             "&asymp;" => "&#8776;",
  540.             "&ne;" => "&#8800;",
  541.             "&equiv;" => "&#8801;",
  542.             "&le;" => "&#8804;",
  543.             "&ge;" => "&#8805;",
  544.             "&sub;" => "&#8834;",
  545.             "&sup;" => "&#8835;",
  546.             "&nsub;" => "&#8836;",
  547.             "&sube;" => "&#8838;",
  548.             "&supe;" => "&#8839;",
  549.             "&oplus;" => "&#8853;",
  550.             "&otimes;" => "&#8855;",
  551.             "&perp;" => "&#8869;",
  552.             "&sdot;" => "&#8901;",
  553.             "&lceil;" => "&#8968;",
  554.             "&rceil;" => "&#8969;",
  555.             "&lfloor;" => "&#8970;",
  556.             "&rfloor;" => "&#8971;",
  557.             "&lang;" => "&#9001;",
  558.             "&rang;" => "&#9002;",
  559.             "&loz;" => "&#9674;",
  560.             "&spades;" => "&#9824;",
  561.             "&clubs;" => "&#9827;",
  562.             "&hearts;" => "&#9829;",
  563.             "&diams;" => "&#9830;");
  564.         return strtr($data$entities);
  565.     }
  566.  
  567.     function xmlrpc_encode_entitites($data)
  568.     {
  569.         $length strlen($data);
  570.         $escapeddata "";
  571.         for($position 0$position $length$position++)
  572.         {
  573.             $character substr($data$position1);
  574.             $code Ord($character);
  575.             switch($code{
  576.                 case 34:
  577.                 $character "&quot;";
  578.                 break;
  579.                 case 38:
  580.                 $character "&amp;";
  581.                 break;
  582.                 case 39:
  583.                 $character "&apos;";
  584.                 break;
  585.                 case 60:
  586.                 $character "&lt;";
  587.                 break;
  588.                 case 62:
  589.                 $character "&gt;";
  590.                 break;
  591.                 default:
  592.                 if ($code 32 || $code 159)
  593.                     $character ("&#".strval($code).";");
  594.                 break;
  595.             }
  596.             $escapeddata .= $character;
  597.         }
  598.         return $escapeddata;
  599.     }
  600.  
  601.     function xmlrpc_se($parser$name$attrs)
  602.     {
  603.         global $_xh$xmlrpcDateTime$xmlrpcString$xmlrpc_valid_parents;
  604.  
  605.         // if invalid xmlrpc already detected, skip all processing
  606.         if ($_xh[$parser]['isf'2)
  607.         {
  608.  
  609.         // check for correct element nesting
  610.         // top level element can only be of 2 types
  611.         if (count($_xh[$parser]['stack']== 0)
  612.         {
  613.             if ($name != 'METHODRESPONSE' && $name != 'METHODCALL')
  614.             {
  615.                 $_xh[$parser]['isf'2;
  616.                 $_xh[$parser]['isf_reason''missing top level xmlrpc element';
  617.                 return;
  618.             }
  619.         }
  620.         else
  621.         {
  622.             // not top level element: see if parent is OK
  623.             if (!in_array($_xh[$parser]['stack'][0]$xmlrpc_valid_parents[$name]))
  624.             {
  625.                 $_xh[$parser]['isf'2;
  626.                 $_xh[$parser]['isf_reason'"xmlrpc element $name cannot be child of {$_xh[$parser]['stack'][0]}";
  627.                 return;
  628.             }
  629.         }
  630.  
  631.         switch($name)
  632.         {
  633.             case 'STRUCT':
  634.             case 'ARRAY':
  635.                 //$_xh[$parser]['st'].='array(';
  636.                 //$_xh[$parser]['cm']++;
  637.                 // this last line turns quoting off
  638.                 // this means if we get an empty array we'll
  639.                 // simply get a bit of whitespace in the eval
  640.                 //$_xh[$parser]['qt']=0;
  641.  
  642.                 // create an empty array to hold child values, and push it onto appropriate stack
  643.                 $cur_val array();
  644.                 $cur_val['values'array();
  645.                 $cur_val['type'$name;
  646.                 array_unshift($_xh[$parser]['valuestack']$cur_val);
  647.                 break;
  648.             case 'METHODNAME':
  649.             case 'NAME':
  650.                 //$_xh[$parser]['st'].='"';
  651.                 $_xh[$parser]['ac']='';
  652.                 break;
  653.             case 'FAULT':
  654.                 $_xh[$parser]['isf']=1;
  655.                 break;
  656.             case 'PARAM':
  657.                 //$_xh[$parser]['st']='';
  658.                 // clear value, so we can check later if no value will passed for this param/member
  659.                 $_xh[$parser]['value']=null;
  660.                 break;
  661.             case 'VALUE':
  662.                 //$_xh[$parser]['st'].='new xmlrpcval(';
  663.                 // look for a value: if this is still true by the
  664.                 // time we reach the end tag for value then the type is string
  665.                 // by implication
  666.                 $_xh[$parser]['vt']='value';
  667.                 $_xh[$parser]['ac']='';
  668.                 //$_xh[$parser]['qt']=0;
  669.                 $_xh[$parser]['lv']=1;
  670.                 break;
  671.             case 'I4':
  672.             case 'INT':
  673.             case 'STRING':
  674.             case 'BOOLEAN':
  675.             case 'DOUBLE':
  676.             case 'DATETIME.ISO8601':
  677.             case 'BASE64':
  678.                 if ($_xh[$parser]['vt']!='value')
  679.                 {
  680.                     //two data elements inside a value: an error occurred!
  681.                     $_xh[$parser]['isf'2;
  682.                     $_xh[$parser]['isf_reason'"$name element following a {$_xh[$parser]['vt']} element inside a single value";
  683.                     return;
  684.                 }
  685.  
  686.                 // reset the accumulator
  687.                 $_xh[$parser]['ac']='';
  688.  
  689.                 /*if ($name=='DATETIME.ISO8601' || $name=='STRING')
  690.                 {
  691.                     $_xh[$parser]['qt']=1;
  692.                     if ($name=='DATETIME.ISO8601')
  693.                     {
  694.                         $_xh[$parser]['vt']=$xmlrpcDateTime;
  695.                     }
  696.                 }
  697.                 elseif ($name=='BASE64')
  698.                 {
  699.                     $_xh[$parser]['qt']=2;
  700.                 }
  701.                 else
  702.                 {
  703.                     // No quoting is required here -- but
  704.                     // at the end of the element we must check
  705.                     // for data format errors.
  706.                     $_xh[$parser]['qt']=0;
  707.                 }*/
  708.                 break;
  709.             case 'MEMBER':
  710.                 //$_xh[$parser]['ac']='';
  711.                 // avoid warnings later on if no NAME is found before VALUE inside
  712.                 // a struct member predefining member name as NULL
  713.                 $_xh[$parser]['valuestack'][0]['name''';
  714.                 // clear value, so we can check later if no value will passed for this param/member
  715.                 $_xh[$parser]['value']=null;
  716.                 break;
  717.             case 'DATA':
  718.             case 'METHODCALL':
  719.             case 'METHODRESPONSE':
  720.             case 'PARAMS':
  721.                 // valid elements that add little to processing
  722.                 break;
  723.             default:
  724.                 /// INVALID ELEMENT: RAISE ISF so that it is later recognized!!!
  725.                 $_xh[$parser]['isf'2;
  726.                 $_xh[$parser]['isf_reason'"found not-xmlrpc xml element $name";
  727.                 break;
  728.         }
  729.  
  730.         // Save current element name to stack, to validate nesting
  731.         array_unshift($_xh[$parser]['stack']$name);
  732.  
  733.         if ($name!='VALUE')
  734.         {
  735.             $_xh[$parser]['lv']=0;
  736.         }
  737.         }
  738.     }
  739.  
  740.     function xmlrpc_ee($parser$name)
  741.     {
  742.         global $_xh,$xmlrpcTypes,$xmlrpcString,$xmlrpcDateTime;
  743.  
  744.         if ($_xh[$parser]['isf'2)
  745.         {
  746.  
  747.         // push this element name from stack
  748.         // NB: if XML validates, correct opening/closing is guaranteed and
  749.         // we do not have to check for $name == $curr_elem.
  750.         // we also checked for proper nesting at start of elements...
  751.         $curr_elem array_shift($_xh[$parser]['stack']);
  752.  
  753.         switch($name)
  754.         {
  755.             case 'STRUCT':
  756.             case 'ARRAY':
  757.                 //if ($_xh[$parser]['cm'] && substr($_xh[$parser]['st'], -1) ==',')
  758.                 //{
  759.                 //    $_xh[$parser]['st']=substr($_xh[$parser]['st'],0,-1);
  760.                 //}
  761.                 //$_xh[$parser]['st'].=')';
  762.  
  763.                 // fetch out of stack array of values, and promote it to current value
  764.                 $cur_val array_shift($_xh[$parser]['valuestack']);
  765.                 $_xh[$parser]['value'$cur_val['values'];
  766.  
  767.                 $_xh[$parser]['vt']=strtolower($name);
  768.                 //$_xh[$parser]['cm']--;
  769.                 break;
  770.             case 'NAME':
  771.                 //$_xh[$parser]['st'].= $_xh[$parser]['ac'] . '" => ';
  772.                 $_xh[$parser]['valuestack'][0]['name'$_xh[$parser]['ac'];
  773.                 break;
  774.             case 'BOOLEAN':
  775.             case 'I4':
  776.             case 'INT':
  777.             case 'STRING':
  778.             case 'DOUBLE':
  779.             case 'DATETIME.ISO8601':
  780.             case 'BASE64':
  781.                 $_xh[$parser]['vt']=strtolower($name);
  782.                 //if ($_xh[$parser]['qt']==1)
  783.                 if ($name=='STRING')
  784.                 {
  785.                     // we use double quotes rather than single so backslashification works OK
  786.                     //$_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"';
  787.                     $_xh[$parser]['value']=$_xh[$parser]['ac'];
  788.                 }
  789.                 elseif ($name=='DATETIME.ISO8601')
  790.                 {
  791.                     $_xh[$parser]['vt']=$xmlrpcDateTime;
  792.                     $_xh[$parser]['value']=$_xh[$parser]['ac'];
  793.                 }
  794.                 elseif ($name=='BASE64')
  795.                 {
  796.                     //$_xh[$parser]['st'].='base64_decode("'. $_xh[$parser]['ac'] . '")';
  797.  
  798.                     ///@todo check for failure of base64 decoding / catch warnings
  799.                     $_xh[$parser]['value']=base64_decode($_xh[$parser]['ac']);
  800.                 }
  801.                 elseif ($name=='BOOLEAN')
  802.                 {
  803.                     // special case here: we translate boolean 1 or 0 into PHP
  804.                     // constants true or false
  805.                     // NB: this simple checks helps a lot sanitizing input, ie no
  806.                     // security problems around here
  807.                     if ($_xh[$parser]['ac']=='1')
  808.                     {
  809.                         //$_xh[$parser]['ac']='true';
  810.                         $_xh[$parser]['value']=true;
  811.                     }
  812.                     else
  813.                     {
  814.                         //$_xh[$parser]['ac']='false';
  815.                         // log if receiveing something strange, even though we set the value to false anyway
  816.                         if ($_xh[$parser]['ac']!='0')
  817.                             error_log('XML-RPC: invalid value received in BOOLEAN: '.$_xh[$parser]['ac']);
  818.                         $_xh[$parser]['value']=false;
  819.                     }
  820.                     //$_xh[$parser]['st'].=$_xh[$parser]['ac'];
  821.                 }
  822.                 elseif ($name=='DOUBLE')
  823.                 {
  824.                     // we have a DOUBLE
  825.                     // we must check that only 0123456789-.<space> are characters here
  826.                     if (!ereg("^[+-]?[eE0123456789 \\t\\.]+$"$_xh[$parser]['ac']))
  827.                     {
  828.                         // TODO: find a better way of throwing an error
  829.                         // than this!
  830.                         error_log('XML-RPC: non numeric value received in DOUBLE: '.$_xh[$parser]['ac']);
  831.                         //$_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'";
  832.                         $_xh[$parser]['value']='ERROR_NON_NUMERIC_FOUND';
  833.                     }
  834.                     else
  835.                     {
  836.                         // it's ok, add it on
  837.                         //$_xh[$parser]['st'].=(double)$_xh[$parser]['ac'];
  838.                         $_xh[$parser]['value']=(double)$_xh[$parser]['ac'];
  839.                     }
  840.                 }
  841.                 else
  842.                 {
  843.                     // we have an I4/INT
  844.                     // we must check that only 0123456789-<space> are characters here
  845.                     if (!ereg("^[+-]?[0123456789 \\t]+$"$_xh[$parser]['ac']))
  846.                     {
  847.                         // TODO: find a better way of throwing an error
  848.                         // than this!
  849.                         error_log('XML-RPC: non numeric value received in INT: '.$_xh[$parser]['ac']);
  850.                         //$_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'";
  851.                         $_xh[$parser]['value']='ERROR_NON_NUMERIC_FOUND';
  852.                     }
  853.                     else
  854.                     {
  855.                         // it's ok, add it on
  856.                         //$_xh[$parser]['st'].=(int)$_xh[$parser]['ac'];
  857.                         $_xh[$parser]['value']=(int)$_xh[$parser]['ac'];
  858.                     }
  859.                 }
  860.                 $_xh[$parser]['ac']='';
  861.                 //$_xh[$parser]['qt']=0;
  862.                 $_xh[$parser]['lv']=3// indicate we've found a value
  863.                 break;
  864.             case 'VALUE':
  865.                 // This if() detects if no scalar was inside <VALUE></VALUE>
  866.                 if ($_xh[$parser]['vt']=='value')
  867.                 {
  868.                     $_xh[$parser]['value']=$_xh[$parser]['ac'];
  869.                     $_xh[$parser]['vt']=$xmlrpcString;
  870.                 }
  871.                 /*if (strlen($_xh[$parser]['ac'])>0 &&
  872.                     $_xh[$parser]['vt']==$xmlrpcString)
  873.                 {
  874.                     $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"';
  875.                 }
  876.                 // This if() detects if no scalar was inside <VALUE></VALUE>
  877.                 // and pads an empty ''.
  878.                 if($_xh[$parser]['st'][strlen($_xh[$parser]['st'])-1] == '(')
  879.                 {
  880.                     $_xh[$parser]['st'].= '""';
  881.                 }
  882.                 // G. Giunta 2005/03/12 save some chars in the reconstruction of string vals...
  883.                 if ($_xh[$parser]['vt'] != $xmlrpcString)
  884.                     $_xh[$parser]['st'].=", '" . $_xh[$parser]['vt'] . "')";
  885.                 else
  886.                     $_xh[$parser]['st'].=")";
  887.                 if ($_xh[$parser]['cm'])
  888.                 {
  889.                     $_xh[$parser]['st'].=',';
  890.                 }*/
  891.  
  892.                 // build the xmlrpc val out of the data received, and substitute it
  893.                 $temp new xmlrpcval($_xh[$parser]['value']$_xh[$parser]['vt']);
  894.                 // check if we are inside an array or struct:
  895.                 // if value just built is inside an array, let's move it into array on the stack
  896.                 if (count($_xh[$parser]['valuestack']&& $_xh[$parser]['valuestack'][0]['type']=='ARRAY')
  897.                 {
  898.                     $_xh[$parser]['valuestack'][0]['values'][$temp;
  899.                 }
  900.                 else
  901.                 {
  902.                     $_xh[$parser]['value'$temp;
  903.                 }
  904.                 break;
  905.             case 'MEMBER':
  906.                 $_xh[$parser]['ac']='';
  907.                 //$_xh[$parser]['qt']=0;
  908.                 // add to array in the stack the last element built
  909.                 // unless no VALUE was found
  910.                 if ($_xh[$parser]['value'])
  911.                     $_xh[$parser]['valuestack'][0]['values'][$_xh[$parser]['valuestack'][0]['name']] $_xh[$parser]['value'];
  912.                 else
  913.                     error_log('XML-RPC: missing VALUE inside STRUCT in received xml');
  914.                 break;
  915.             case 'DATA':
  916.                 $_xh[$parser]['ac']='';
  917.                 //$_xh[$parser]['qt']=0;
  918.                 break;
  919.             case 'PARAM':
  920.                 //$_xh[$parser]['params'][]=$_xh[$parser]['st'];
  921.                 if ($_xh[$parser]['value'])
  922.                     $_xh[$parser]['params'][]=$_xh[$parser]['value'];
  923.                 else
  924.                     error_log('XML-RPC: missing VALUE inside PARAM in received xml');
  925.                 break;
  926.             case 'METHODNAME':
  927.                 $_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+"''$_xh[$parser]['ac']);
  928.                 break;
  929.             case 'PARAMS':
  930.             case 'FAULT':
  931.             case 'METHODCALL':
  932.             case 'METHORESPONSE':
  933.                 break;
  934.             default:
  935.                 // End of INVALID ELEMENT!
  936.                 // shall we add an assert here for unreachable code???
  937.                 break;
  938.         }
  939.  
  940.         // if it's a valid type name, set the type
  941.         /*if (isset($xmlrpcTypes[strtolower($name)]))
  942.         {
  943.             $_xh[$parser]['vt']=strtolower($name);
  944.         }*/
  945.  
  946.         }
  947.  
  948.     }
  949.  
  950.     function xmlrpc_cd($parser$data)
  951.     {
  952.         global $_xh$xmlrpc_backslash;
  953.  
  954.         //if (ereg("^[\n\r \t]+$", $data)) return;
  955.         // print "adding [${data}]\n";
  956.  
  957.         // skip processing if xml fault already detected
  958.         if ($_xh[$parser]['isf'2)
  959.         {
  960.             if ($_xh[$parser]['lv']!=3)
  961.             {
  962.                 // "lookforvalue==3" means that we've found an entire value
  963.                 // and should discard any further character data
  964.                 if ($_xh[$parser]['lv']==1)
  965.                 {
  966.                     // if we've found text and we're just in a <value> then
  967.                     // turn quoting on, as this will be a string
  968.                     //$_xh[$parser]['qt']=1;
  969.                     // and say we've found a value
  970.                     $_xh[$parser]['lv']=2;
  971.                 }
  972.                 if(!@isset($_xh[$parser]['ac']))
  973.                 {
  974.                     $_xh[$parser]['ac''';
  975.                 }
  976.                 //$_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data)));
  977.                 $_xh[$parser]['ac'].=$data;
  978.             }
  979.         }
  980.     }
  981.  
  982.     function xmlrpc_dh($parser$data)
  983.     {
  984.         global $_xh$xmlrpc_backslash;
  985.  
  986.         // skip processing if xml fault already detected
  987.         if ($parser[$_xh]['isf'2)
  988.         {
  989.             if (substr($data01== '&' && substr($data-11== ';')
  990.             {
  991.                 if ($_xh[$parser]['lv']==1)
  992.                 {
  993.                     //$_xh[$parser]['qt']=1;
  994.                     $_xh[$parser]['lv']=2;
  995.                 }
  996.                 //$_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data)));
  997.                 $_xh[$parser]['ac'].=$data;
  998.             }
  999.         }
  1000.     }
  1001.  
  1002.     /**
  1003.      * @package evocore
  1004.      * @subpackage xmlrpc
  1005.      */
  1006.     class xmlrpc_client
  1007.     {
  1008.         var $path;
  1009.         var $server;
  1010.         var $port;
  1011.         var $errno;
  1012.         var $errstr;
  1013.         var $debug=0;
  1014.         var $username='';
  1015.         var $password='';
  1016.         var $cert='';
  1017.         var $certpass='';
  1018.         var $verifypeer=1;
  1019.         var $verifyhost=1;
  1020.         var $no_multicall=false;
  1021.  
  1022.         function xmlrpc_client($path$server$port=0)
  1023.         {
  1024.             $this->port=$port$this->server=$server$this->path=$path;
  1025.         }
  1026.  
  1027.         function setDebug($in)
  1028.         {
  1029.             if ($in)
  1030.             {
  1031.                 $this->debug=1;
  1032.             }
  1033.             else
  1034.             {
  1035.                 $this->debug=0;
  1036.             }
  1037.         }
  1038.  
  1039.         function setCredentials($u$p)
  1040.         {
  1041.             $this->username=$u;
  1042.             $this->password=$p;
  1043.         }
  1044.  
  1045.         function setCertificate($cert$certpass)
  1046.         {
  1047.             $this->cert = $cert;
  1048.             $this->certpass = $certpass;
  1049.         }
  1050.  
  1051.         function setSSLVerifyPeer($i)
  1052.         {
  1053.             $this->verifypeer = $i;
  1054.         }
  1055.  
  1056.         function setSSLVerifyHost($i)
  1057.         {
  1058.             $this->verifyhost = $i;
  1059.         }
  1060.  
  1061.         /*
  1062.          * xmlrpc_client->send(-)
  1063.          */
  1064.         function send($msg$timeout=0$method='http')
  1065.         {
  1066.             if (is_array($msg))
  1067.             {
  1068.                 // $msg is an array of xmlrpcmsg's
  1069.                 return $this->multicall($msg$timeout$method);
  1070.             }
  1071.  
  1072.             // where msg is an xmlrpcmsg
  1073.             $msg->debug=$this->debug;
  1074.  
  1075.             if ($method == 'https')
  1076.             {
  1077.                 return $this->sendPayloadHTTPS($msg,
  1078.                 $this->server,
  1079.                 $this->port$timeout,
  1080.                 $this->username$this->password,
  1081.                 $this->cert,
  1082.                 $this->certpass);
  1083.             }
  1084.             else
  1085.             {
  1086.                 return $this->sendPayloadHTTP10($msg$this->server$this->port,
  1087.                 $timeout$this->username,
  1088.                 $this->password);
  1089.             }
  1090.         }
  1091.  
  1092.         function sendPayloadHTTP10($msg$server$port$timeout=0,$username=''$password='')
  1093.         {
  1094.             global $xmlrpcerr$xmlrpcstr$xmlrpcName$xmlrpcVersion$xmlrpc_defencoding;
  1095.             if ($port==0)
  1096.             {
  1097.                 $port=80;
  1098.             }
  1099.             if($timeout>0)
  1100.             {
  1101.                 $fp=@fsockopen($server$port,$this->errno$this->errstr$timeout);
  1102.             }
  1103.             else
  1104.             {
  1105.                 $fp=@fsockopen($server$port,$this->errno$this->errstr);
  1106.             }
  1107.             if ($fp)
  1108.             {
  1109.                 if ($timeout>&& function_exists('stream_set_timeout'))
  1110.                     stream_set_timeout($fp$timeout);
  1111.             }
  1112.             else
  1113.             {
  1114.                 $this->errstr='Connect error';
  1115.                 $r=new xmlrpcresp(0$xmlrpcerr['http_error'],$xmlrpcstr['http_error']);
  1116.                 return $r;
  1117.             }
  1118.             // Only create the payload if it was not created previously
  1119.             if(empty($msg->payload))
  1120.             {
  1121.                 $msg->createPayload();
  1122.             }
  1123.  
  1124.             // thanks to Grant Rauscher <grant7@firstworld.net>
  1125.             // for this
  1126.             $credentials='';
  1127.             if ($username!='')
  1128.             {
  1129.                 $credentials='Authorization: Basic ' base64_encode($username ':' $password"\r\n";
  1130.             }
  1131.  
  1132.             $op"POST " $this->path" HTTP/1.0\r\n" .
  1133.                 "User-Agent: " $xmlrpcName " " $xmlrpcVersion "\r\n" .
  1134.                 "Host: "$server "\r\n" .
  1135.                 $credentials .
  1136.                 "Accept-Charset: " $xmlrpc_defencoding "\r\n" .
  1137.                 "Content-Type: text/xml\r\nContent-Length: " .
  1138.                 strlen($msg->payload"\r\n\r\n" .
  1139.                 $msg->payload;
  1140.  
  1141.             if (!fputs($fp$opstrlen($op)))
  1142.             {
  1143.                 $this->errstr='Write error';
  1144.                 $r=new xmlrpcresp(0$xmlrpcerr['http_error']$xmlrpcstr['http_error']);
  1145.                 return $r;
  1146.             }
  1147.             $resp=$msg->parseResponseFile($fp);
  1148.             fclose($fp);
  1149.             return $resp;
  1150.         }
  1151.  
  1152.         // contributed by Justin Miller <justin@voxel.net>
  1153.         // requires curl to be built into PHP
  1154.         function sendPayloadHTTPS($msg$server$port$timeout=0,$username=''$password=''$cert='',$certpass='')
  1155.         {
  1156.             global $xmlrpcerr$xmlrpcstr$xmlrpcVersion$xmlrpc_internalencoding;
  1157.             if ($port == 0)
  1158.             {
  1159.                 $port 443;
  1160.             }
  1161.  
  1162.             // Only create the payload if it was not created previously
  1163.             if(empty($msg->payload))
  1164.             {
  1165.                 $msg->createPayload();
  1166.             }
  1167.  
  1168.             if (!function_exists('curl_init'))
  1169.             {
  1170.                 $this->errstr='SSL unavailable on this install';
  1171.                 $r=new xmlrpcresp(0$xmlrpcerr['no_ssl']$xmlrpcstr['no_ssl']);
  1172.                 return $r;
  1173.             }
  1174.  
  1175.             $curl curl_init('https://' $server ':' $port $this->path);
  1176.  
  1177.             curl_setopt($curlCURLOPT_RETURNTRANSFER1);
  1178.             // results into variable
  1179.             if ($this->debug)
  1180.             {
  1181.                 curl_setopt($curlCURLOPT_VERBOSE1);
  1182.             }
  1183.             curl_setopt($curlCURLOPT_USERAGENT'PHP XMLRPC '.$xmlrpcVersion);
  1184.             // required for XMLRPC
  1185.             curl_setopt($curlCURLOPT_POST1);
  1186.             // post the data
  1187.             curl_setopt($curlCURLOPT_POSTFIELDS$msg->payload);
  1188.             // the data
  1189.             curl_setopt($curlCURLOPT_HEADER1);
  1190.             // return the header too
  1191.             curl_setopt($curlCURLOPT_HTTPHEADERarray('Content-Type: text/xml''Accept-Charset: '.$xmlrpc_internalencoding));
  1192.             // whether to verify remote host's cert
  1193.             curl_setopt($curlCURLOPT_SSL_VERIFYPEER$this->verifypeer);
  1194.             // 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
  1195.             curl_setopt($curlCURLOPT_SSL_VERIFYHOST$this->verifyhost);
  1196.             // required for XMLRPC
  1197.             if ($timeout)
  1198.             {
  1199.                 curl_setopt($curlCURLOPT_TIMEOUT$timeout == $timeout 1);
  1200.             }
  1201.             // timeout is borked
  1202.             if ($username && $password)
  1203.             {
  1204.                 curl_setopt($curlCURLOPT_USERPWD,"$username:$password");
  1205.             }
  1206.             // set auth stuff
  1207.             if ($cert)
  1208.             {
  1209.                 curl_setopt($curlCURLOPT_SSLCERT$cert);
  1210.             }
  1211.             // set cert file
  1212.             if ($certpass)
  1213.             {
  1214.                 curl_setopt($curlCURLOPT_SSLCERTPASSWD,$certpass);
  1215.             }
  1216.             // set cert password
  1217.  
  1218.             $result curl_exec($curl);
  1219.  
  1220.             if (!$result)
  1221.             {
  1222.                 $this->errstr='no response';
  1223.                 $resp=new xmlrpcresp(0$xmlrpcerr['curl_fail']$xmlrpcstr['curl_fail']': 'curl_error($curl));
  1224.                 curl_close($curl);
  1225.             }
  1226.             else
  1227.             {
  1228.                 curl_close($curl);
  1229.                 $resp $msg->parseResponse($result);
  1230.             }
  1231.             return $resp;
  1232.         }
  1233.  
  1234.         function multicall($msgs$timeout=0$method='http')
  1235.         {
  1236.             $results false;
  1237.  
  1238.             if ($this->no_multicall)
  1239.             {
  1240.                 $results $this->_try_multicall($msgs$timeout$method);
  1241.                 /* TODO - this is not php3-friendly */
  1242.                 // if($results !== false)
  1243.                 if(is_array($results))
  1244.                 {
  1245.                     // Either the system.multicall succeeded, or the send
  1246.                     // failed (e.g. due to HTTP timeout). In either case,
  1247.                     // we're done for now.
  1248.                     return $results;
  1249.                 }
  1250.                 else
  1251.                 {
  1252.                     // system.multicall unsupported by server,
  1253.                     // don't try it next time...
  1254.                     $this->no_multicall = true;
  1255.                 }
  1256.             }
  1257.  
  1258.             // system.multicall is unupported by server:
  1259.             //   Emulate multicall via multiple requests
  1260.             $results array();
  1261.             //foreach($msgs as $msg)
  1262.             @reset($msgs);
  1263.             while(list(,$msg@each($msgs))
  1264.             {
  1265.                 $results[$this->send($msg$timeout$method);
  1266.             }
  1267.             return $results;
  1268.         }
  1269.  
  1270.         // Attempt to boxcar $msgs via system.multicall.
  1271.         function _try_multicall($msgs$timeout$method)
  1272.         {
  1273.             // Construct multicall message
  1274.             $calls array();
  1275.             //foreach($msgs as $msg)
  1276.             @reset($msgs);
  1277.             while(list(,$msg@each($msgs))
  1278.             {
  1279.                 $call['methodName'new xmlrpcval($msg->method(),'string');
  1280.                 $numParams $msg->getNumParams();
  1281.                 $params array();
  1282.                 for ($i 0$i $numParams$i++)
  1283.                 {
  1284.                     $params[$i$msg->getParam($i);
  1285.                 }
  1286.                 $call['params'new xmlrpcval($params'array');
  1287.                 $calls[new xmlrpcval($call'struct');
  1288.             }
  1289.             $multicall new xmlrpcmsg('system.multicall');
  1290.             $multicall->addParam(new xmlrpcval($calls'array'));
  1291.  
  1292.             // Attempt RPC call
  1293.             $result $this->send($multicall$timeout$method);
  1294.             if(!is_object($result))
  1295.             {
  1296.                 return ($result || 0)// transport failed
  1297.             }
  1298.  
  1299.             if($result->faultCode(!= 0)
  1300.             {
  1301.                 return false;        // system.multicall failed
  1302.             }
  1303.  
  1304.             // Unpack responses.
  1305.             $rets $result->value();
  1306.             if($rets->kindOf(!= 'array')
  1307.             {
  1308.                 return false;        // bad return type from system.multicall
  1309.             }
  1310.             $numRets $rets->arraysize();
  1311.             if($numRets != count($msgs))
  1312.             {
  1313.                 return false;        // wrong number of return values.
  1314.             }
  1315.  
  1316.             $response array();
  1317.             for ($i 0$i $numRets$i++)
  1318.             {
  1319.                 $val $rets->arraymem($i);
  1320.                 switch ($val->kindOf())
  1321.                 {
  1322.                 case 'array':
  1323.                     if($val->arraysize(!= 1)
  1324.                     {
  1325.                         return false;        // Bad value
  1326.                     }
  1327.                     // Normal return value
  1328.                     $response[$inew xmlrpcresp($val->arraymem(0));
  1329.                     break;
  1330.                 case 'struct':
  1331.                     $code $val->structmem('faultCode');
  1332.                     if($code->kindOf(!= 'scalar' || $code->scalartyp(!= 'int')
  1333.                     {
  1334.                         return false;
  1335.                     }
  1336.                     $str $val->structmem('faultString');
  1337.                     if($str->kindOf(!= 'scalar' || $str->scalartyp(!= 'string')
  1338.                     {
  1339.                         return false;
  1340.                     }
  1341.                     $response[$inew xmlrpcresp(0$code->scalarval()$str->scalarval());
  1342.                     break;
  1343.                 default:
  1344.                     return false;
  1345.                 }
  1346.             }
  1347.             return $response;
  1348.         }
  1349.     // end class xmlrpc_client
  1350.  
  1351.     /**
  1352.      * @package evocore
  1353.      * @subpackage xmlrpc
  1354.      */
  1355.     class xmlrpcresp
  1356.     {
  1357.         var $val = 0;
  1358.         var $errno = 0;
  1359.         var $errstr = '';
  1360.         var $hdrs = array();
  1361.  
  1362.         function xmlrpcresp($val$fcode 0$fstr '')
  1363.         {
  1364.             if ($fcode != 0)
  1365.             {
  1366.                 // error
  1367.                 $this->errno = $fcode;
  1368.                 $this->errstr = $fstr;
  1369.                 //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later.
  1370.             }
  1371.             elseif (!is_object($val))
  1372.             {
  1373.                 // programmer error
  1374.                 error_log("Invalid type '" gettype($val"' (value: $val) passed to xmlrpcresp. Defaulting to empty value.");
  1375.                 $this->val = new xmlrpcval();
  1376.             }
  1377.             else
  1378.             {
  1379.                 // success
  1380.                 $this->val = $val;
  1381.             }
  1382.         }
  1383.  
  1384.         function faultCode()
  1385.         {
  1386.             return $this->errno;
  1387.         }
  1388.  
  1389.         function faultString()
  1390.         {
  1391.             return $this->errstr;
  1392.         }
  1393.  
  1394.         function value()
  1395.         {
  1396.             return $this->val;
  1397.         }
  1398.  
  1399.         function serialize()
  1400.         {
  1401.             $result "<methodResponse>\n";
  1402.             if ($this->errno)
  1403.             {
  1404.                 // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients
  1405.                 $result .= '<fault>
  1406.     <value>
  1407.         <struct>
  1408.             <member>
  1409.                 <name>faultCode</name>
  1410.                 <value><int>' $this->errno . '</int></value>
  1411.             </member>
  1412.             <member>
  1413.                 <name>faultString</name>
  1414.                 <value><string>' xmlrpc_encode_entitites($this->errstr'</string></value>
  1415.             </member>
  1416.         </struct>
  1417.     </value>
  1418. </fault>';
  1419.             }
  1420.             else
  1421.             {
  1422.                 $result .= "<params>\n<param>\n" .
  1423.                     $this->val->serialize(.
  1424.                     "</param>\n</params>";
  1425.             }
  1426.             $result .= "\n</methodResponse>";
  1427.             logIO("O",$result);
  1428.             return $result;
  1429.         }
  1430.     }
  1431.  
  1432.     /**
  1433.      * @package evocore
  1434.      * @subpackage xmlrpc
  1435.      */
  1436.     class xmlrpcmsg
  1437.     {
  1438.         var $payload;
  1439.         var $methodname;
  1440.         var $params=array();
  1441.         var $debug=0;
  1442.  
  1443.         function xmlrpcmsg($meth$pars=0)
  1444.         {
  1445.             $this->methodname=$meth;
  1446.             if (is_array($pars&& sizeof($pars)>0)
  1447.             {
  1448.                 for($i=0$i<sizeof($pars)$i++)
  1449.                 {
  1450.                     $this->addParam($pars[$i]);
  1451.                 }
  1452.             }
  1453.         }
  1454.  
  1455.         function xml_header()
  1456.         {
  1457.             // TODO: handle encoding
  1458.             // return "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?".">\n<methodCall>\n";
  1459.  
  1460.             return "<?xml version=\"1.0\"?" ">\n<methodCall>\n";
  1461.         }
  1462.  
  1463.         function xml_footer()
  1464.         {
  1465.             return "</methodCall>\n";
  1466.         }
  1467.  
  1468.         function createPayload()
  1469.         {
  1470.             $this->payload=$this->xml_header();
  1471.             $this->payload.='<methodName>' $this->methodname . "</methodName>\n";
  1472.             //    if (sizeof($this->params)) {
  1473.             $this->payload.="<params>\n";
  1474.             for($i=0$i<sizeof($this->params)$i++)
  1475.             {
  1476.                 $p=$this->params[$i];
  1477.                 $this->payload.="<param>\n" $p->serialize(.
  1478.                 "</param>\n";
  1479.             }
  1480.             $this->payload.="</params>\n";
  1481.             // }
  1482.             $this->payload.=$this->xml_footer();
  1483.             //$this->payload=str_replace("\n", "\r\n", $this->payload);
  1484.         }
  1485.  
  1486.         function method($meth='')
  1487.         {
  1488.             if ($meth!='')
  1489.             {
  1490.                 $this->methodname=$meth;
  1491.             }
  1492.             return $this->methodname;
  1493.         }
  1494.  
  1495.         function serialize()
  1496.         {
  1497.             $this->createPayload();
  1498.             logIO("O",$this->payload);
  1499.             return $this->payload;
  1500.         }
  1501.  
  1502.         function addParam($par$this->params[]=$par}
  1503.         function getParam($ireturn $this->params[$i]}
  1504.         function getNumParams(return sizeof($this->params)}
  1505.  
  1506.         function parseResponseFile($fp)
  1507.         {
  1508.             $ipd='';
  1509.             while($data=fread($fp32768))
  1510.             {
  1511.                 $ipd.=$data;
  1512.             }
  1513.             return $this->parseResponse($ipd);
  1514.         }
  1515.  
  1516.         function parseResponse($data='')
  1517.         {
  1518.             global $_xh,$xmlrpcerr,$xmlrpcstr;
  1519.             global $xmlrpc_defencoding$xmlrpc_internalencoding;
  1520.  
  1521.             $hdrfnd 0;
  1522.             if($this->debug)
  1523.             {
  1524.                 //by maHo, replaced htmlspecialchars with htmlentities
  1525.                 print "<PRE>---GOT---\n" htmlentities($data"\n---END---\n</PRE>";
  1526.             }
  1527.  
  1528.             if($data == '')
  1529.             {
  1530.                 error_log('No response received from server.');
  1531.                 $r new xmlrpcresp(0$xmlrpcerr['no_data']$xmlrpcstr['no_data']);
  1532.                 return $r;
  1533.             }
  1534.             // see if we got an HTTP 200 OK, else bomb
  1535.             // but only do this if we're using the HTTP protocol.
  1536.             if(ereg("^HTTP",$data))
  1537.             {
  1538.                 // Strip HTTP 1.1 100 Continue header if present
  1539.                 while (ereg('^HTTP/1.1 1[0-9]{2}'$data))
  1540.                 {
  1541.                     $pos strpos($data'HTTP'12);
  1542.                     // server sent a Continue header without any (valid) content following...
  1543.                     // give the client a chance to know it
  1544.                     if (!$pos && !is_int($pos)) // works fine in php 3, 4 and 5
  1545.                         break;
  1546.                     $data substr($data$pos);
  1547.                 }
  1548.                 if (!ereg("^HTTP/[0-9\\.]+ 200 "$data))
  1549.                 {
  1550.                     $errstrsubstr($data0strpos($data"\n")-1);
  1551.                     error_log('HTTP error, got response: ' .$errstr);
  1552.                     $r=new xmlrpcresp(0$xmlrpcerr['http_error']$xmlrpcstr['http_error']' (' $errstr ')');
  1553.                     return $r;
  1554.                 }
  1555.             }
  1556.             $parser xml_parser_create($xmlrpc_defencoding);
  1557.  
  1558.             // G. Giunta 2004/04/06
  1559.             // Clean up the accumulator, or it will grow indefinitely long
  1560.             // if making xmlrpc calls for a while
  1561.             $_xh=array();
  1562.             $_xh[$parser]=array();
  1563.             $_xh[$parser]['headers'array();
  1564.             $_xh[$parser]['stack'array();
  1565.             $_xh[$parser]['valuestack'array();
  1566.  
  1567.             // separate HTTP headers from data
  1568.             if (ereg("^HTTP"$data))
  1569.             {
  1570.                 // be tolerant to usage of \n instead of \r\n to separate headers and data
  1571.                 // (even though it is not valid http)
  1572.                 $pos strpos($data,"\r\n\r\n");
  1573.                 if($pos || is_int($pos))
  1574.                     $bd $pos+4;
  1575.                 else
  1576.                 {
  1577.                     $pos strpos($data,"\n\n");
  1578.                     if($pos || is_int($pos))
  1579.                         $bd $pos+2;
  1580.                     else
  1581.                     {
  1582.                         // No separation between response headers and body: fault?
  1583.                         $bd 0;
  1584.                     }
  1585.                 }
  1586.                 // be tolerant to line endings, and extra empty lines
  1587.                 $ar split("\r?\n"trim(substr($data0$pos)));
  1588.                 while (list(,$line@each($ar))
  1589.                 {
  1590.                     // take care of multi-line headers
  1591.                     $arr explode(':',$line);
  1592.                     if(count($arr1)
  1593.                     {
  1594.                         $header_name trim($arr[0]);
  1595.                         // TO DO: some headers (the ones that allow a CSV list of values)
  1596.                         // do allow many values to be passed using multiple header lines.
  1597.                         // We should add content to $_xh[$parser]['headers'][$header_name]
  1598.                         // instead of replacing it for those...
  1599.                         $_xh[$parser]['headers'][$header_name$arr[1];
  1600.                         for ($i 2$i count($arr)$i++)
  1601.                         {
  1602.                             $_xh[$parser]['headers'][$header_name.= ':'.$arr[$i];
  1603.                         // while
  1604.                         $_xh[$parser]['headers'][$header_nametrim($_xh[$parser]['headers'][$header_name]);
  1605.                     else if (isset($header_name))
  1606.                     {
  1607.                         $_xh[$parser]['headers'][$header_name.= ' ' trim($line);
  1608.                     }
  1609.                 }
  1610.                 $data substr($data$bd);
  1611.  
  1612.                 if ($this->debug && count($_xh[$parser]['headers']))
  1613.                 {
  1614.                     print '<PRE>';
  1615.                     //foreach ($_xh[$parser]['headers'] as $header)
  1616.                     @reset($_xh[$parser]['headers']);
  1617.                     while(list($header$value@each($_xh[$parser]['headers']))
  1618.                     {
  1619.                         print "HEADER: $header$value\n";
  1620.                     }
  1621.                     print "</PRE>\n";
  1622.                 }
  1623.             }
  1624.  
  1625.             // be tolerant of extra whitespace in response body
  1626.             $data trim($data);
  1627.  
  1628.             // be tolerant of junk after methodResponse (e.g. javascript automatically inserted by free hosts)
  1629.             // idea from Luca Mariano <luca.mariano@email.it> originally in PEARified version of the lib
  1630.             $bd false;
  1631.             $pos strpos($data"</methodResponse>");
  1632.             while ($pos || is_int($pos))
  1633.             {
  1634.                 $bd $pos+17;
  1635.                 $pos strpos($data"</methodResponse>"$bd);
  1636.             }
  1637.             if ($bd)
  1638.                 $data substr($data0$bd);
  1639.  
  1640.             //$_xh[$parser]['st']='';
  1641.             //$_xh[$parser]['cm']=0;
  1642.             $_xh[$parser]['isf']=0;
  1643.             $_xh[$parser]['isf_reason']=0;
  1644.             $_xh[$parser]['ac']='';
  1645.             //$_xh[$parser]['qt']='';
  1646.  
  1647.             xml_parser_set_option($parserXML_OPTION_CASE_FOLDINGtrue);
  1648.             // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell
  1649.             // the xml parser to give us back data in the expected charset
  1650.             xml_parser_set_option($parserXML_OPTION_TARGET_ENCODING$xmlrpc_internalencoding);
  1651.  
  1652.             xml_set_element_handler($parser'xmlrpc_se''xmlrpc_ee');
  1653.             xml_set_character_data_handler($parser'xmlrpc_cd');
  1654.             xml_set_default_handler($parser'xmlrpc_dh');
  1655.             //$xmlrpc_value=new xmlrpcval;
  1656.  
  1657.             if (!xml_parse($parser$datasizeof($data)))
  1658.             {
  1659.                 // thanks to Peter Kocks <peter.kocks@baygate.com>
  1660.                 if((xml_get_current_line_number($parser)) == 1)
  1661.                 {
  1662.                     $errstr 'XML error at line 1, check URL';
  1663.                 }
  1664.                 else
  1665.                 {
  1666.                     $errstr sprintf('XML error: %s at line %d',
  1667.                         xml_error_string(xml_get_error_code($parser)),
  1668.                         xml_get_current_line_number($parser));
  1669.                 }
  1670.                 error_log($errstr);
  1671.                 $r=new xmlrpcresp(0$xmlrpcerr['invalid_return']$xmlrpcstr['invalid_return'].' ('.$errstr.')');
  1672.                 xml_parser_free($parser);
  1673.                 if ($this->debug)
  1674.                     echo $errstr;
  1675.                 $r->hdrs $_xh[$parser]['headers'];
  1676.                 return $r;
  1677.             }
  1678.             xml_parser_free($parser);
  1679.  
  1680.             if ($_xh[$parser]['isf'1)
  1681.             {
  1682.                 if ($this->debug)
  1683.                 {
  1684.                     ///@todo echo something for user?
  1685.                 }
  1686.  
  1687.                 $r new xmlrpcresp(0$xmlrpcerr['invalid_return'],
  1688.                 $xmlrpcstr['invalid_return'' ' $_xh[$parser]['isf_reason']);
  1689.             }
  1690.             //else if (strlen($_xh[$parser]['st'])==0)
  1691.             else if (!is_object($_xh[$parser]['value']))
  1692.             {
  1693.                 // then something odd has happened
  1694.                 // and it's time to generate a client side error
  1695.                 // indicating something odd went on
  1696.                 $r=new xmlrpcresp(0$xmlrpcerr['invalid_return'],
  1697.                 $xmlrpcstr['invalid_return']);
  1698.             }
  1699.             else
  1700.             {
  1701.  
  1702.                 if ($this->debug)
  1703.                 {
  1704.                     //print "<PRE>---EVALING---[" .
  1705.                     //strlen($_xh[$parser]['st']) . " chars]---\n" .
  1706.                     //htmlspecialchars($_xh[$parser]['st']) . ";\n---END---</PRE>";
  1707.                     print "<PRE>---PARSED---\n" ;
  1708.                     var_dump($_xh[$parser]['value']);
  1709.                     print "\n---END---</PRE>";
  1710.                 }
  1711.  
  1712.                 //$allOK=0;
  1713.                 //@eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;');
  1714.                 //if (!$allOK)
  1715.                 //{
  1716.                 //    $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return']);
  1717.                 //}
  1718.                 //else
  1719.                 $v $_xh[$parser]['value'];
  1720.                 if ($_xh[$parser]['isf'])
  1721.                 {
  1722.                     $errno_v $v->structmem('faultCode');
  1723.                     $errstr_v $v->structmem('faultString');
  1724.                     $errno $errno_v->scalarval();
  1725.  
  1726.                     if ($errno == 0)
  1727.                     {
  1728.                         // FAULT returned, errno needs to reflect that
  1729.                         $errno = -1;
  1730.                     }
  1731.  
  1732.                     $r new xmlrpcresp($v$errno$errstr_v->scalarval());
  1733.                 }
  1734.                 else
  1735.                 {
  1736.                     $r=new xmlrpcresp($v);
  1737.                 }
  1738.             }
  1739.  
  1740.             $r->hdrs $_xh[$parser]['headers'];
  1741.             return $r;
  1742.         }
  1743.     }
  1744.  
  1745.     /**
  1746.      * @package evocore
  1747.      * @subpackage xmlrpc
  1748.      */
  1749.     class xmlrpcval
  1750.     {
  1751.         var $me=array();
  1752.         var $mytype=0;
  1753.  
  1754.         /*
  1755.          * Type will default to string
  1756.          */
  1757.         function xmlrpcval($val=-1$type='')
  1758.         {
  1759.             global $xmlrpcTypes;
  1760.             $this->me=array();
  1761.             $this->mytype=0;
  1762.             if ($val!=-|| !is_int($val|| $type!='')
  1763.             {
  1764.                 if ($type=='')
  1765.                 {
  1766.                     $type='string';
  1767.                 }
  1768.                 if ($xmlrpcTypes[$type]==1)
  1769.                 {
  1770.                     $this->addScalar($val,$type);
  1771.                 }
  1772.                 elseif ($xmlrpcTypes[$type]==2)
  1773.                 {
  1774.                     $this->addArray($val);
  1775.                 }
  1776.                 elseif ($xmlrpcTypes[$type]==3)
  1777.                 {
  1778.                     $this->addStruct($val);
  1779.                 }
  1780.             }
  1781.         }
  1782.  
  1783.         function addScalar($val$type='string')
  1784.         {
  1785.             global $xmlrpcTypes$xmlrpcBoolean;
  1786.  
  1787.             if ($this->mytype==1)
  1788.             {
  1789.                 echo '<strong>xmlrpcval</strong>: scalar can have only one value<br />';
  1790.                 return 0;
  1791.             }
  1792.             $typeof=$xmlrpcTypes[$type];
  1793.             if ($typeof!=1)
  1794.             {
  1795.                 echo '<strong>xmlrpcval</strong>: not a scalar type (${typeof})<br />';
  1796.                 return 0;
  1797.             }
  1798.  
  1799.             if ($type==$xmlrpcBoolean)
  1800.             {
  1801.                 if (strcasecmp($val,'true')==|| $val==|| ($val==true && strcasecmp($val,'false')))
  1802.                 {
  1803.                     $val=1;
  1804.                 }
  1805.                 else
  1806.                 {
  1807.                     $val=0;
  1808.                 }
  1809.             }
  1810.  
  1811.             if ($this->mytype==2)
  1812.             {
  1813.                 // we're adding to an array here
  1814.                 $ar=$this->me['array'];
  1815.                 $ar[]=new xmlrpcval($val$type);
  1816.                 $this->me['array']=$ar;
  1817.             }
  1818.             else
  1819.             {
  1820.                 // a scalar, so set the value and remember we're scalar
  1821.                 $this->me[$type]=$val;
  1822.                 $this->mytype=$typeof;
  1823.             }
  1824.             return 1;
  1825.         }
  1826.  
  1827.         function addArray($vals)
  1828.         {
  1829.             global $xmlrpcTypes;
  1830.             if ($this->mytype!=0)
  1831.             {
  1832.                 echo '<strong>xmlrpcval</strong>: already initialized as a [' $this->kindOf(']<br />';
  1833.                 return 0;
  1834.             }
  1835.  
  1836.             $this->mytype=$xmlrpcTypes['array'];
  1837.             $this->me['array']=$vals;
  1838.             return 1;
  1839.         }
  1840.  
  1841.         function addStruct($vals)
  1842.         {
  1843.             global $xmlrpcTypes;
  1844.             if ($this->mytype!=0)
  1845.             {
  1846.                 echo '<strong>xmlrpcval</strong>: already initialized as a [' $this->kindOf(']<br />';
  1847.                 return 0;
  1848.             }
  1849.             $this->mytype=$xmlrpcTypes['struct'];
  1850.             $this->me['struct']=$vals;
  1851.             return 1;
  1852.         }
  1853.  
  1854.         function dump($ar)
  1855.         {
  1856.             reset($ar);
  1857.             while list$key$val each$ar ) )
  1858.             {
  1859.                 echo "$key => $val<br />";
  1860.                 if ($key == 'array')
  1861.                 {
  1862.                     while list$key2$val2 each$val ) )
  1863.                     {
  1864.                         echo "-- $key2 => $val2<br />";
  1865.                     }
  1866.                 }
  1867.             }
  1868.         }
  1869.  
  1870.         function kindOf()
  1871.         {
  1872.             switch($this->mytype)
  1873.             {
  1874.                 case 3:
  1875.                     return 'struct';
  1876.                     break;
  1877.                 case 2:
  1878.                     return 'array';
  1879.                     break;
  1880.                 case 1:
  1881.                     return 'scalar';
  1882.                     break;
  1883.                 default:
  1884.                     return 'undef';
  1885.             }
  1886.         }
  1887.  
  1888.         function serializedata($typ$val)
  1889.         {
  1890.             $rs='';
  1891.             global $xmlrpcTypes$xmlrpcBase64$xmlrpcString,
  1892.             $xmlrpcBoolean;
  1893.             switch(@$xmlrpcTypes[$typ])
  1894.             {
  1895.                 case 3:
  1896.                     // struct
  1897.                     $rs.="<struct>\n";
  1898.                     reset($val);
  1899.                     while(list($key2$val2)=each($val))
  1900.                     {
  1901.                         $rs.="<member><name>${key2}</name>\n";
  1902.                         $rs.=$this->serializeval($val2);
  1903.                         $rs.="</member>\n";
  1904.                     }
  1905.                     $rs.='</struct>';
  1906.                     break;
  1907.                 case 2:
  1908.                     // array
  1909.                     $rs.="<array>\n<data>\n";
  1910.                     for($i=0$i<sizeof($val)$i++)
  1911.                     {
  1912.                         $rs.=$this->serializeval($val[$i]);
  1913.                     }
  1914.                     $rs.="</data>\n</array>";
  1915.                     break;
  1916.                 case 1:
  1917.                     switch ($typ)
  1918.                     {
  1919.                         case $xmlrpcBase64:
  1920.                             $rs.="<${typ}>base64_encode($val"</${typ}>";
  1921.                             break;
  1922.                         case $xmlrpcBoolean:
  1923.                             $rs.="<${typ}>($val '1' '0'"</${typ}>";
  1924.                             break;
  1925.                         case $xmlrpcString:
  1926.                             // G. Giunta 2005/2/13: do NOT use htmlentities, since
  1927.                             // it will produce named html entities, which are invalid xml
  1928.                             $rs.="<${typ}>xmlrpc_encode_entitites($val)"</${typ}>";
  1929.                             // $rs.="<${typ}>" . htmlentities($val). "</${typ}>";
  1930.                             break;
  1931.                         default:
  1932.                             $rs.="<${typ}>${val}</${typ}>";
  1933.                     }
  1934.                     break;
  1935.                 default:
  1936.                     break;
  1937.             }
  1938.             return $rs;
  1939.         }
  1940.  
  1941.         function serialize()
  1942.         {
  1943.             return $this->serializeval($this);
  1944.         }
  1945.  
  1946.         function serializeval($o)
  1947.         {
  1948.             //global $xmlrpcTypes;
  1949.             $rs='';
  1950.             $ar=$o->me;
  1951.             reset($ar);
  1952.             list($typ$valeach($ar);
  1953.             $rs.='<value>';
  1954.             $rs.=$this->serializedata($typ$val);
  1955.             $rs.="</value>\n";
  1956.             return $rs;
  1957.         }
  1958.  
  1959.         function structmem($m)
  1960.         {
  1961.             $nv=$this->me['struct'][$m];
  1962.             return $nv;
  1963.         }
  1964.  
  1965.         function structreset()
  1966.         {
  1967.             reset($this->me['struct']);
  1968.         }
  1969.  
  1970.         function structeach()
  1971.         {
  1972.             return each($this->me['struct']);
  1973.         }
  1974.  
  1975.         function getval()
  1976.         {
  1977.             // UNSTABLE
  1978.             global $xmlrpcBoolean$xmlrpcBase64;
  1979.             reset($this->me);
  1980.             list($a,$b)=each($this->me);
  1981.             // contributed by I Sofer, 2001-03-24
  1982.             // add support for nested arrays to scalarval
  1983.             // i've created a new method here, so as to
  1984.             // preserve back compatibility
  1985.  
  1986.             if (is_array($b))
  1987.             {
  1988.                 @reset($b);
  1989.                 while(list($id,$cont@each($b))
  1990.                 {
  1991.                     $b[$id$cont->scalarval();
  1992.                 }
  1993.             }
  1994.  
  1995.             // add support for structures directly encoding php objects
  1996.             if (is_object($b))
  1997.             {
  1998.                 $t get_object_vars($b);
  1999.                 @reset($t);
  2000.                 while(list($id,$cont@each($t))
  2001.                 {
  2002.                     $t[$id$cont->scalarval();
  2003.                 }
  2004.                 @reset($t);
  2005.                 while(list($id,$cont@each($t))
  2006.                 {
  2007.                     //eval('$b->'.$id.' = $cont;');
  2008.                     @$b->$id $cont;
  2009.                 }
  2010.             }
  2011.             // end contrib
  2012.             return $b;
  2013.         }
  2014.  
  2015.         function scalarval()
  2016.         {
  2017.             //global $xmlrpcBoolean, $xmlrpcBase64;
  2018.             reset($this->me);
  2019.             list($a,$b)=each($this->me);
  2020.             return $b;
  2021.         }
  2022.  
  2023.         function scalartyp()
  2024.         {
  2025.             global $xmlrpcI4$xmlrpcInt;
  2026.             reset($this->me);
  2027.             list($a,$b)=each($this->me);
  2028.             if ($a==$xmlrpcI4)
  2029.             {
  2030.                 $a=$xmlrpcInt;
  2031.             }
  2032.             return $a;
  2033.         }
  2034.  
  2035.         function arraymem($m)
  2036.         {
  2037.             $nv=$this->me['array'][$m];
  2038.             return $nv;
  2039.         }
  2040.  
  2041.         function arraysize()
  2042.         {
  2043.             reset($this->me);
  2044.             list($a,$b)=each($this->me);
  2045.             return sizeof($b);
  2046.         }
  2047.     }
  2048.  
  2049.     // date helpers
  2050.     function iso8601_encode($timet$utc=0)
  2051.     {
  2052.         // return an ISO8601 encoded string
  2053.         // really, timezones ought to be supported
  2054.         // but the XML-RPC spec says:
  2055.         //
  2056.         // "Don't assume a timezone. It should be specified by the server in its
  2057.         // documentation what assumptions it makes about timezones."
  2058.         //
  2059.         // these routines always assume localtime unless
  2060.         // $utc is set to 1, in which case UTC is assumed
  2061.         // and an adjustment for locale is made when encoding
  2062.         if (!$utc)
  2063.         {
  2064.             $t=strftime("%Y%m%dT%H:%M:%S"$timet);
  2065.         }
  2066.         else
  2067.         {
  2068.             if (function_exists('gmstrftime'))
  2069.             {
  2070.                 // gmstrftime doesn't exist in some versions
  2071.                 // of PHP
  2072.                 $t=gmstrftime("%Y%m%dT%H:%M:%S"$timet);
  2073.             }
  2074.             else
  2075.             {
  2076.                 $t=strftime("%Y%m%dT%H:%M:%S"$timet-date('Z'));
  2077.             }
  2078.         }
  2079.         return $t;
  2080.     }
  2081.  
  2082.     function iso8601_decode($idate$utc=0)
  2083.     {
  2084.         // return a timet in the localtime, or UTC
  2085.         $t=0;
  2086.         if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})"$idate$regs))
  2087.         {
  2088.             if ($utc)
  2089.             {
  2090.                 $t=gmmktime($regs[4]$regs[5]$regs[6]$regs[2]$regs[3]$regs[1]);
  2091.             }
  2092.             else
  2093.             {
  2094.                 $t=mktime($regs[4]$regs[5]$regs[6]$regs[2]$regs[3]$regs[1]);
  2095.             }
  2096.         }
  2097.         return $t;
  2098.     }
  2099.  
  2100.     /****************************************************************
  2101.     * xmlrpc_decode takes a message in PHP xmlrpc object format and *
  2102.     * tranlates it into native PHP types.                           *
  2103.     *                                                               *
  2104.     * author: Dan Libby (dan@libby.com)                             *
  2105.     ****************************************************************/
  2106.     /*
  2107.      * evocore: We add xmlrpc_decode_recurse because the default PHP implementation
  2108.      * of xmlrpc_decode won't recurse! Bleh!
  2109.      * update: XML-RPC for PHP now copes with this, but we keep a stub for backward compatibility
  2110.      */
  2111.     function xmlrpc_decode_recurse($xmlrpc_val)
  2112.     {
  2113.         return php_xmlrpc_decode($xmlrpc_val);
  2114.     }
  2115.  
  2116.     function php_xmlrpc_decode($xmlrpc_val)
  2117.     {
  2118.         $kind $xmlrpc_val->kindOf();
  2119.  
  2120.         if($kind == 'scalar')
  2121.         {
  2122.             return $xmlrpc_val->scalarval();
  2123.         }
  2124.         elseif($kind == 'array')
  2125.         {
  2126.             $size $xmlrpc_val->arraysize();
  2127.             $arr array();
  2128.  
  2129.             for($i 0$i $size$i++)
  2130.             {
  2131.                 $arr[php_xmlrpc_decode($xmlrpc_val->arraymem($i));
  2132.             }
  2133.             return $arr;
  2134.         }
  2135.         elseif($kind == 'struct')
  2136.         {
  2137.             $xmlrpc_val->structreset();
  2138.             $arr array();
  2139.  
  2140.             while(list($key,$value)=$xmlrpc_val->structeach())
  2141.             {
  2142.                 $arr[$keyphp_xmlrpc_decode($value);
  2143.                 // echo $key, '=>', $arr[$key], '<br />';
  2144.             }
  2145.             return $arr;
  2146.         }
  2147.     }
  2148.  
  2149.     if(function_exists('xmlrpc_decode'))
  2150.     {
  2151.         define('XMLRPC_EPI_ENABLED','1');
  2152.     }
  2153.     else
  2154.     {
  2155.         define('XMLRPC_EPI_ENABLED','0');
  2156.         function xmlrpc_decode($xmlrpc_val)
  2157.         {
  2158.             $kind $xmlrpc_val->kindOf();
  2159.  
  2160.             if($kind == 'scalar')
  2161.             {
  2162.                 return $xmlrpc_val->scalarval();
  2163.             }
  2164.             elseif($kind == 'array')
  2165.             {
  2166.                 $size $xmlrpc_val->arraysize();
  2167.                 $arr array();
  2168.  
  2169.                 for($i 0$i $size$i++)
  2170.                 {
  2171.                     $arr[]=xmlrpc_decode($xmlrpc_val->arraymem($i));
  2172.                 }
  2173.                 return $arr;
  2174.             }
  2175.             elseif($kind == 'struct')
  2176.             {
  2177.                 $xmlrpc_val->structreset();
  2178.                 $arr array();
  2179.  
  2180.                 while(list($key,$value)=$xmlrpc_val->structeach())
  2181.                 {
  2182.                     $arr[$keyxmlrpc_decode($value);
  2183.                 }
  2184.                 return $arr;
  2185.             }
  2186.         }
  2187.     }
  2188.  
  2189.     /****************************************************************
  2190.     * xmlrpc_encode takes native php types and encodes them into    *
  2191.     * xmlrpc PHP object format.                                     *
  2192.     * BUG: All sequential arrays are turned into structs.  I don't  *
  2193.     * know of a good way to determine if an array is sequential     *
  2194.     * only.                                                         *
  2195.     *                                                               *
  2196.     * feature creep -- could support more types via optional type   *
  2197.     * argument.                                                     *
  2198.     *                                                               *
  2199.     * author: Dan Libby (dan@libby.com)                             *
  2200.     ****************************************************************/
  2201.     function php_xmlrpc_encode($php_val)
  2202.     {
  2203.         global $xmlrpcInt;
  2204.         global $xmlrpcDouble;
  2205.         global $xmlrpcString;
  2206.         global $xmlrpcArray;
  2207.         global $xmlrpcStruct;
  2208.         global $xmlrpcBoolean;
  2209.  
  2210.         $type gettype($php_val);
  2211.         $xmlrpc_val new xmlrpcval;
  2212.  
  2213.         switch($type)
  2214.         {
  2215.             case 'array':
  2216.             case 'object':
  2217.                 $arr array();
  2218.                 while (list($k,$veach($php_val))
  2219.                 {
  2220.                     $arr[$kphp_xmlrpc_encode($v);
  2221.                 }
  2222.                 $xmlrpc_val->addStruct($arr);
  2223.                 break;
  2224.             case 'integer':
  2225.                 $xmlrpc_val->addScalar($php_val$xmlrpcInt);
  2226.                 break;
  2227.             case 'double':
  2228.                 $xmlrpc_val->addScalar($php_val$xmlrpcDouble);
  2229.                 break;
  2230.             case 'string':
  2231.                 $xmlrpc_val->addScalar($php_val$xmlrpcString);
  2232.                 break;
  2233.                 // <G_Giunta_2001-02-29>
  2234.                 // Add support for encoding/decoding of booleans, since they are supported in PHP
  2235.             case 'boolean':
  2236.                 $xmlrpc_val->addScalar($php_val$xmlrpcBoolean);
  2237.                 break;
  2238.                 // </G_Giunta_2001-02-29>
  2239.             // catch "resource", "NULL", "user function", "unknown type"
  2240.             //case 'unknown type':
  2241.             default:
  2242.                 // giancarlo pinerolo <ping@alt.it>
  2243.                 // it has to return
  2244.                 // an empty object in case (which is already
  2245.                 // at this point), not a boolean.
  2246.                 break;
  2247.             }
  2248.             return $xmlrpc_val;
  2249.     }
  2250.  
  2251.     if(XMLRPC_EPI_ENABLED == '0')
  2252.     {
  2253.         function xmlrpc_encode($php_val)
  2254.         {
  2255.             global $xmlrpcInt;
  2256.             global $xmlrpcDouble;
  2257.             global $xmlrpcString;
  2258.             global $xmlrpcArray;
  2259.             global $xmlrpcStruct;
  2260.             global $xmlrpcBoolean;
  2261.  
  2262.             $type gettype($php_val);
  2263.             $xmlrpc_val new xmlrpcval;
  2264.  
  2265.             switch($type)
  2266.             {
  2267.                 case 'array':
  2268.                 case 'object':
  2269.                     $arr array();
  2270.                     while (list($k,$veach($php_val))
  2271.                     {
  2272.                         $arr[$kxmlrpc_encode($v);
  2273.                     }
  2274.                     $xmlrpc_val->addStruct($arr);
  2275.                     break;
  2276.                 case 'integer':
  2277.                     $xmlrpc_val->addScalar($php_val$xmlrpcInt);
  2278.                     break;
  2279.                 case 'double':
  2280.                     $xmlrpc_val->addScalar($php_val$xmlrpcDouble);
  2281.                     break;
  2282.                 case 'string':
  2283.                     $xmlrpc_val->addScalar($php_val$xmlrpcString);
  2284.                     break;
  2285.                     // <G_Giunta_2001-02-29>
  2286.                     // Add support for encoding/decoding of booleans, since they are supported in PHP
  2287.                 case 'boolean':
  2288.                     $xmlrpc_val->addScalar($php_val$xmlrpcBoolean);
  2289.                     break;
  2290.                     // </G_Giunta_2001-02-29>
  2291.                 //case 'unknown type':
  2292.                 default:
  2293.                     // giancarlo pinerolo <ping@alt.it>
  2294.                     // it has to return
  2295.                     // an empty object in case (which is already
  2296.                     // at this point), not a boolean.
  2297.                     break;
  2298.             }
  2299.             return $xmlrpc_val;
  2300.         }
  2301.     }
  2302. ?>

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