diff --git a/xmlrpc.php b/xmlrpc.php index 1487d3b2a0..f6f793b9dc 100644 --- a/xmlrpc.php +++ b/xmlrpc.php @@ -13,14 +13,6 @@ /* $Id$ */ /* $Source$ */ - // NOTE! This file is still in the experimental stages, use at your own risk! - // The only current documentation for it is the code and the comments - // A document explaining its usage should be done shortly - // PLEASE, do *NOT* make any changes to this file without talking to me - // directly first. Until I get it fully undercontrol. - // There might be possiable security holes in this, I haven't fully tested it - // (jengo) - $GLOBALS['phpgw_info'] = array(); $GLOBALS['phpgw_info']['flags'] = array( 'currentapp' => 'login', @@ -29,8 +21,15 @@ ); include('header.inc.php'); + $server = CreateObject('phpgwapi.xmlrpc_server'); + $server->authed = False; +// debug($server);exit; + + /* uncomment here if you want to show all of the testing functions for compatibility */ +// include(PHPGW_API_INC . '/xmlrpc.interop.php'); + // If XML-RPC isn't enabled in PHP, return an XML-RPC response stating so - if (! function_exists('xmlrpc_server_create')) + if(!function_exists('xmlrpc_server_create')) { echo "\n"; echo "\n"; @@ -57,232 +56,22 @@ exit; } - - // Return all PHP errors as faults - $GLOBALS['xmlrpc_server'] = xmlrpc_server_create(); - error_reporting(E_ERROR | E_WARNING | E_PARSE); - set_error_handler('xmlrpc_custom_error'); - + /* Note: this command only available under Apache */ $headers = getallheaders(); - if (ereg('Basic',$headers['Authorization'])) + + if(ereg('Basic',$headers['Authorization'])) { - $tmp = $headers['Authorization']; - $tmp = ereg_replace(' ','',$tmp); - $tmp = ereg_replace('Basic','',$tmp); + $tmp = $headers['Authorization']; + $tmp = ereg_replace(' ','',$tmp); + $tmp = ereg_replace('Basic','',$tmp); $auth = base64_decode(trim($tmp)); list($sessionid,$kp3) = split(':',$auth); - if ($GLOBALS['phpgw']->session->verify($sessionid,$kp3)) + if($GLOBALS['phpgw']->session->verify($sessionid,$kp3)) { - $GLOBALS['xmlrpc_server'] = xmlrpc_server_create(); - $request_xml = $HTTP_RAW_POST_DATA; - - // Find out what method they are calling - // This function is odd, you *NEED* to assign the results - // to a value, or $method is never returned. (jengo) - $null = xmlrpc_decode_request($request_xml, &$method); - $GLOBALS['phpgw']->session->xmlrpc_method_called = $method; - $GLOBALS['phpgw']->session->update_dla(); - - // Check permissions and load the class, register all methods - // for that class, and execute it - list($app,$class,$func) = explode('.',$method); - - if ($method == 'system.logout' || $GLOBALS['phpgw_info']['user']['apps'][$app] || $app == 'phpgwapi') - { - $GLOBALS['obj'] = CreateObject($app . '.' . $class); - - xmlrpc_server_register_method($xmlrpc_server,sprintf('%s.%s.%s',$app,$class,'listMethods'),'xmlrpc_list_methods'); - xmlrpc_server_register_method($xmlrpc_server,sprintf('%s.%s.%s',$app,$class,'describeMethods'),xmlrpc_describe_methods); - xmlrpc_server_register_method($xmlrpc_server,'system.logout','xmlrpc_logout'); - - while (list(,$new_method) = @each($obj->xmlrpc_methods)) - { - $full_method_name = sprintf('%s.%s.%s',$app,$class,$new_method['name']); - - xmlrpc_server_register_method($xmlrpc_server,$full_method_name,'xmlrpc_call_wrapper'); - // The following function is listed as being in the API, but doesn't actually exisit. - // This is more of a mental note to track down its exisitence - //xmlrpc_server_set_method_description($xmlrpc_server,$full_method_name,$new_method); - } - } - else if ($method != 'system.listMethods' && $method != 'system.describeMethods') - { - xmlrpc_error(1001,'Access not permitted'); - } - - echo xmlrpc_server_call_method($xmlrpc_server,$request_xml,''); - xmlrpc_server_destroy($xmlrpc_server); - } - else - { - // Session is invailed - xmlrpc_error(1001,'Session expired'); - } - } - else - { - // First, create a single method being system.login - // If they don't request this, then just return a failed session error - $xmlrpc_server = xmlrpc_server_create(); - $request_xml = $HTTP_RAW_POST_DATA; - - // Find out what method they are calling - // This function is odd, you *NEED* to assign the results - // to a value, or $method is never returned. (jengo) - $null = xmlrpc_decode_request($request_xml, &$method); - - if ($method == 'system.login') - { - xmlrpc_server_register_method($xmlrpc_server,'system.login','xmlrpc_login'); - echo xmlrpc_server_call_method($xmlrpc_server,$request_xml,''); - xmlrpc_server_destroy($xmlrpc_server); - - exit; - } - else - { - // They didn't request system.login and they didn't pass sessionid or - // kp3, this is an invailed session (The session could have also been killed or expired) - xmlrpc_error(1001,'Session expired'); + $server->authed = True; } } - // When PHP returns an error, return that error with a fault instead of - // HTML with will make most parsers fall apart - function xmlrpc_custom_error($error_number, $error_string, $filename, $line, $vars) - { - if (error_reporting() & $error_number) - { - $error_string .= sprintf("\nFilename: %s\nLine: %s",$filename,$line); - - xmlrpc_error(1005,$error_string); - } - } - - // This will create an XML-RPC error - // FIXME! This needs to be expanded to handle PHP errors themselfs - // it will make debugging easier - function xmlrpc_error($error_number, $error_string) - { - $values = array( - 'faultString' => $error_string, - 'faultCode' => $error_number - ); - - echo xmlrpc_encode_request(NULL,$values); - - xmlrpc_server_destroy($GLOBALS['xmlrpc_server']); - exit; - } - - // This will dynamicly create the avaiable methods for each class - function xmlrpc_list_methods($method) - { - list($app,$class,$func) = explode('.',$method); - $methods[] = 'system.login'; - $methods[] = 'system.logout'; - $methods[] = $method; - $methods[] = $app . '.' . $class . 'describeMethods'; - for ($i=0; $ixmlrpc_methods); $i++) - { - $methods[] = $GLOBALS['obj']->xmlrpc_methods[$i]['name']; - } - - return $methods; - } - - function xmlrpc_describe_methods($method) - { - list($app,$class,$func) = explode('.',$method); - // FIXME! Add the missing pre-defined methods, example: system.login - for ($i=0; $ixmlrpc_methods); $i++) - { - $methods[] = $GLOBALS['obj']->xmlrpc_methods[$i]; - } - - return $methods; - } - - // I know everyone hates wrappers, but this is the best way this can be done - // The XML-RPC functions pass method_name as the first parameter, which is - // unacceptable. - // Another reason for this, is it might be possiable to pass the sessionid - // and kp3 instead of using HTTP_AUTH features. - // Would be a nice workaround for librarys that don't support it, as its - // not in the XML-RPC spec. - function xmlrpc_call_wrapper($method_name, $parameters) - { - $a = explode('.',$method_name); - - if (count($parameters) == 0) - { - $return = $GLOBALS['obj']->$a[2](); - } - else if (count($parameters) == 1) - { - $return = $GLOBALS['obj']->$a[2]($parameters[0]); - } - else - { - for ($i=0; $i$a[2](' . implode(',',$p) . ');'); - } - - // This needs to be expanded and more fully tested - if (gettype($return) == 'NULL') - { - return xmlrpc_error(1002,'No return value detected'); - } - else - { - return $return; - } - } - - // The following are common functions used ONLY by XML-RPC - function xmlrpc_login($method_name, $parameters) - { - $p = $parameters[0]; - - if ($p['domain']) - { - $username = $p['username'] . '@' . $p['domain']; - } - else - { - $username = $p['username']; - } - - $sessionid = $GLOBALS['phpgw']->session->create($username,$p['password'],'text'); - $kp3 = $GLOBALS['phpgw']->session->kp3; - $domain = $GLOBALS['phpgw']->session->account_domain; - - if ($sessionid && $kp3) - { - return array( - 'sessionid' => $sessionid, - 'kp3' => $kp3, - 'domain' => $domain - ); - } - else - { - xmlrpc_error(1001,'Login failed'); - } - } - - function xmlrpc_logout($method, $parameters) - { - // We have already verified the session upon before this method is even created - // As long as nothing happens upon, its safe to destroy the session without - // fear of it being a hijacked session - $GLOBALS['phpgw']->session->destroy($GLOBALS['phpgw']->session->sessionid,$GLOBALS['phpgw']->session->kp3); - - return True; - } - - + $server->service($HTTP_SERVER_VARS['HTTP_RAW_POST_DATA']); +?> diff --git a/xmlrpc.php.old b/xmlrpc.php.old new file mode 100644 index 0000000000..fb345e2272 --- /dev/null +++ b/xmlrpc.php.old @@ -0,0 +1,290 @@ + * + * -------------------------------------------- * + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + \**************************************************************************/ + + /* $Id$ */ + /* $Source$ */ + + // NOTE! This file is still in the experimental stages, use at your own risk! + // The only current documentation for it is the code and the comments + // A document explaining its usage should be done shortly + // PLEASE, do *NOT* make any changes to this file without talking to me + // directly first. Until I get it fully undercontrol. + // There might be possiable security holes in this, I haven't fully tested it + // (jengo) + + exit; + + $GLOBALS['phpgw_info'] = array(); + $GLOBALS['phpgw_info']['flags'] = array( + 'currentapp' => 'login', + 'noheader' => True, + 'disable_Template_class' => True + ); + include('header.inc.php'); + + // If XML-RPC isn't enabled in PHP, return an XML-RPC response stating so + if (! function_exists('xmlrpc_server_create')) + { + echo "\n"; + echo "\n"; + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " faultString\n"; + echo " \n"; + echo " XML-RPC support NOT enabled in PHP installation\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " faultCode\n"; + echo " \n"; + echo " 1005\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n"; + echo "\n"; + + exit; + } + + + // Return all PHP errors as faults + $GLOBALS['xmlrpc_server'] = xmlrpc_server_create(); + error_reporting(E_ERROR | E_WARNING | E_PARSE); + set_error_handler('xmlrpc_custom_error'); + + $headers = getallheaders(); + if (ereg('Basic',$headers['Authorization'])) + { + $tmp = $headers['Authorization']; + $tmp = ereg_replace(' ','',$tmp); + $tmp = ereg_replace('Basic','',$tmp); + $auth = base64_decode(trim($tmp)); + list($sessionid,$kp3) = split(':',$auth); + + if ($GLOBALS['phpgw']->session->verify($sessionid,$kp3)) + { + $GLOBALS['xmlrpc_server'] = xmlrpc_server_create(); + $request_xml = $HTTP_RAW_POST_DATA; + + // Find out what method they are calling + // This function is odd, you *NEED* to assign the results + // to a value, or $method is never returned. (jengo) + $null = xmlrpc_decode_request($request_xml, &$method); + $GLOBALS['phpgw']->session->xmlrpc_method_called = $method; + $GLOBALS['phpgw']->session->update_dla(); + + // Check permissions and load the class, register all methods + // for that class, and execute it + list($app,$class,$func) = explode('.',$method); + + if ($method == 'system.logout' || $GLOBALS['phpgw_info']['user']['apps'][$app] || $app == 'phpgwapi') + { + $GLOBALS['obj'] = CreateObject($app . '.' . $class); + + xmlrpc_server_register_method($xmlrpc_server,sprintf('%s.%s.%s',$app,$class,'listMethods'),'xmlrpc_list_methods'); + xmlrpc_server_register_method($xmlrpc_server,sprintf('%s.%s.%s',$app,$class,'describeMethods'),xmlrpc_describe_methods); + xmlrpc_server_register_method($xmlrpc_server,'system.logout','xmlrpc_logout'); + + while (list(,$new_method) = @each($obj->xmlrpc_methods)) + { + $full_method_name = sprintf('%s.%s.%s',$app,$class,$new_method['name']); + + xmlrpc_server_register_method($xmlrpc_server,$full_method_name,'xmlrpc_call_wrapper'); + // The following function is listed as being in the API, but doesn't actually exisit. + // This is more of a mental note to track down its exisitence + //xmlrpc_server_set_method_description($xmlrpc_server,$full_method_name,$new_method); + } + } + else if ($method != 'system.listMethods' && $method != 'system.describeMethods') + { + xmlrpc_error(1001,'Access not permitted'); + } + + echo xmlrpc_server_call_method($xmlrpc_server,$request_xml,''); + xmlrpc_server_destroy($xmlrpc_server); + } + else + { + // Session is invailed + xmlrpc_error(1001,'Session expired'); + } + } + else + { + // First, create a single method being system.login + // If they don't request this, then just return a failed session error + $xmlrpc_server = xmlrpc_server_create(); + $request_xml = $HTTP_RAW_POST_DATA; + + // Find out what method they are calling + // This function is odd, you *NEED* to assign the results + // to a value, or $method is never returned. (jengo) + $null = xmlrpc_decode_request($request_xml, &$method); + + if ($method == 'system.login') + { + xmlrpc_server_register_method($xmlrpc_server,'system.login','xmlrpc_login'); + echo xmlrpc_server_call_method($xmlrpc_server,$request_xml,''); + xmlrpc_server_destroy($xmlrpc_server); + + exit; + } + else + { + // They didn't request system.login and they didn't pass sessionid or + // kp3, this is an invailed session (The session could have also been killed or expired) + xmlrpc_error(1001,'Session expired'); + } + } + + // When PHP returns an error, return that error with a fault instead of + // HTML with will make most parsers fall apart + function xmlrpc_custom_error($error_number, $error_string, $filename, $line, $vars) + { + if (error_reporting() & $error_number) + { + $error_string .= sprintf("\nFilename: %s\nLine: %s",$filename,$line); + + xmlrpc_error(1005,$error_string); + } + } + + // This will create an XML-RPC error + // FIXME! This needs to be expanded to handle PHP errors themselfs + // it will make debugging easier + function xmlrpc_error($error_number, $error_string) + { + $values = array( + 'faultString' => $error_string, + 'faultCode' => $error_number + ); + + echo xmlrpc_encode_request(NULL,$values); + + xmlrpc_server_destroy($GLOBALS['xmlrpc_server']); + exit; + } + + // This will dynamicly create the avaiable methods for each class + function xmlrpc_list_methods($method) + { + list($app,$class,$func) = explode('.',$method); + $methods[] = 'system.login'; + $methods[] = 'system.logout'; + $methods[] = $method; + $methods[] = $app . '.' . $class . 'describeMethods'; + for ($i=0; $ixmlrpc_methods); $i++) + { + $methods[] = $GLOBALS['obj']->xmlrpc_methods[$i]['name']; + } + + return $methods; + } + + function xmlrpc_describe_methods($method) + { + list($app,$class,$func) = explode('.',$method); + // FIXME! Add the missing pre-defined methods, example: system.login + for ($i=0; $ixmlrpc_methods); $i++) + { + $methods[] = $GLOBALS['obj']->xmlrpc_methods[$i]; + } + + return $methods; + } + + // I know everyone hates wrappers, but this is the best way this can be done + // The XML-RPC functions pass method_name as the first parameter, which is + // unacceptable. + // Another reason for this, is it might be possiable to pass the sessionid + // and kp3 instead of using HTTP_AUTH features. + // Would be a nice workaround for librarys that don't support it, as its + // not in the XML-RPC spec. + function xmlrpc_call_wrapper($method_name, $parameters) + { + $a = explode('.',$method_name); + + if (count($parameters) == 0) + { + $return = $GLOBALS['obj']->$a[2](); + } + else if (count($parameters) == 1) + { + $return = $GLOBALS['obj']->$a[2]($parameters[0]); + } + else + { + for ($i=0; $i$a[2](' . implode(',',$p) . ');'); + } + + // This needs to be expanded and more fully tested + if (gettype($return) == 'NULL') + { + return xmlrpc_error(1002,'No return value detected'); + } + else + { + return $return; + } + } + + // The following are common functions used ONLY by XML-RPC + function xmlrpc_login($method_name, $parameters) + { + $p = $parameters[0]; + + if ($p['domain']) + { + $username = $p['username'] . '@' . $p['domain']; + } + else + { + $username = $p['username']; + } + + $sessionid = $GLOBALS['phpgw']->session->create($username,$p['password'],'text'); + $kp3 = $GLOBALS['phpgw']->session->kp3; + $domain = $GLOBALS['phpgw']->session->account_domain; + + if ($sessionid && $kp3) + { + return array( + 'sessionid' => $sessionid, + 'kp3' => $kp3, + 'domain' => $domain + ); + } + else + { + xmlrpc_error(1001,'Login failed'); + } + } + + function xmlrpc_logout($method, $parameters) + { + // We have already verified the session upon before this method is even created + // As long as nothing happens upon, its safe to destroy the session without + // fear of it being a hijacked session + $GLOBALS['phpgw']->session->destroy($GLOBALS['phpgw']->session->sessionid,$GLOBALS['phpgw']->session->kp3); + + return True; + } + +