mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-25 16:18:57 +01:00
325 lines
8.6 KiB
PHP
325 lines
8.6 KiB
PHP
<?php
|
|
/**************************************************************************\
|
|
* eGroupWare API - XML-RPC Server *
|
|
* This file written by Miles Lott <milos@groupwhere.org> *
|
|
* Copyright (C) 2003 Miles Lott *
|
|
* -------------------------------------------------------------------------*
|
|
* This library is free software; you can redistribute it and/or modify it *
|
|
* under the terms of the GNU Lesser General Public License as published by *
|
|
* the Free Software Foundation; either version 2.1 of the License, *
|
|
* or any later version. *
|
|
* This library is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
* See the GNU Lesser General Public License for more details. *
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
|
* along with this library; if not, write to the Free Software Foundation, *
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
|
|
\**************************************************************************/
|
|
|
|
/* $Id$ */
|
|
|
|
class xmlrpc_server
|
|
{
|
|
var $server = '';
|
|
var $authed = True;
|
|
var $log = '/tmp/xmlrpc_request_log';
|
|
var $last_method = '';
|
|
|
|
function xmlrpc_server($dispMap='', $serviceNow=0)
|
|
{
|
|
$this->server = xmlrpc_server_create();
|
|
if($dispMap)
|
|
{
|
|
$this->dmap = $dispMap;
|
|
if($serviceNow)
|
|
{
|
|
$this->service();
|
|
}
|
|
}
|
|
}
|
|
|
|
function serializeDebug()
|
|
{
|
|
}
|
|
|
|
function service()
|
|
{
|
|
$r = $this->parseRequest();
|
|
if(!$r)
|
|
{
|
|
header('WWW-Authenticate: Basic realm="eGroupWare xmlrpc"');
|
|
header('HTTP/1.0 401 Unauthorized');
|
|
// for the log:
|
|
$payload = "WWW-Authenticate: Basic realm=\"eGroupWare xmlrpc\"\nHTTP/1.0 401 Unauthorized\n";
|
|
echo $payload;
|
|
}
|
|
else
|
|
{
|
|
// $payload = '<?xml version="1.0"?\>' . "\n" . $this->serializeDebug() . $r->serialize();
|
|
// Header("Content-type: text/xml\r\nContent-length: " . strlen($payload));
|
|
// print $payload;
|
|
echo $r;
|
|
}
|
|
|
|
if($this->log)
|
|
{
|
|
$fp = fopen($this->log,'a+');
|
|
fwrite($fp,"\n\n" . date('Y-m-d H:i:s') . " authorized="
|
|
. ($this->authed ? $GLOBALS['phpgw_info']['user']['account_lid'] : 'False')
|
|
. ", method='$this->last_method'\n");
|
|
fwrite($fp,"==== GOT ============================\n" . $GLOBALS['HTTP_RAW_POST_DATA']
|
|
. "\n==== RETURNED =======================\n");
|
|
fputs($fp,$payload);
|
|
fclose($fp);
|
|
}
|
|
|
|
if($this->debug)
|
|
{
|
|
$this->echoInput();
|
|
|
|
$fp = fopen('/tmp/xmlrpc_debug.out','a+');
|
|
fputs($fp,$payload);
|
|
fclose($fp);
|
|
}
|
|
}
|
|
|
|
function add_to_map($methodname,$function,$sig,$doc)
|
|
{
|
|
xmlrpc_server_register_method($this->server,$methodname,$function);
|
|
// xmlrpc_server_register_method($this->server,$methodname,'xmlrpc_call_wrapper');
|
|
// $descr = array(
|
|
// 'function' => $function,
|
|
// 'signature' => $sig,
|
|
// 'docstring' => $doc
|
|
// );
|
|
// xmlrpc_server_set_method_description($this->server,$methodname,$descr);
|
|
|
|
$this->dmap[$methodname] = array(
|
|
'function' => $function,
|
|
'signature' => $sig,
|
|
'docstring' => $doc
|
|
);
|
|
}
|
|
|
|
function verifySignature($in, $sig)
|
|
{
|
|
return array(1);
|
|
|
|
for($i=0; $i<sizeof($sig); $i++)
|
|
{
|
|
// check each possible signature in turn
|
|
$cursig = $sig[$i];
|
|
if (sizeof($cursig) == $in->getNumParams()+1)
|
|
{
|
|
$itsOK = 1;
|
|
for($n=0; $n<$in->getNumParams(); $n++)
|
|
{
|
|
$p = $in->getParam($n);
|
|
// print "<!-- $p -->\n";
|
|
if ($p->kindOf() == 'scalar')
|
|
{
|
|
$pt = $p->scalartyp();
|
|
}
|
|
else
|
|
{
|
|
$pt = $p->kindOf();
|
|
}
|
|
// $n+1 as first type of sig is return type
|
|
if ($pt != $cursig[$n+1])
|
|
{
|
|
$itsOK = 0;
|
|
$pno = $n+1;
|
|
$wanted = $cursig[$n+1];
|
|
$got = $pt;
|
|
break;
|
|
}
|
|
}
|
|
if ($itsOK)
|
|
{
|
|
return array(1);
|
|
}
|
|
}
|
|
}
|
|
return array(0, "Wanted $wanted, got $got at param $pno)");
|
|
}
|
|
|
|
function parseRequest($data='')
|
|
{
|
|
global $HTTP_RAW_POST_DATA;
|
|
|
|
if($data == '')
|
|
{
|
|
$data = $HTTP_RAW_POST_DATA;
|
|
}
|
|
// return $this->echoInput($data);
|
|
|
|
/* Decode to extract methodName */
|
|
$params = xmlrpc_decode_request($data, &$methName);
|
|
$this->last_method = $methName;
|
|
$syscall = 0;
|
|
|
|
/* Setup dispatch map based on the function, if this is a system call */
|
|
if(ereg('^system\.', $methName))
|
|
{
|
|
foreach($GLOBALS['_xmlrpcs_dmap'] as $meth => $dat)
|
|
{
|
|
$this->add_to_map($meth,$dat['function'],$dat['signature'],$dat['docstring']);
|
|
}
|
|
$sysCall = 1;
|
|
$dmap = $this->dmap;
|
|
}
|
|
elseif(ereg('^examples\.',$methName) ||
|
|
ereg('^validator1\.',$methName) ||
|
|
ereg('^interopEchoTests\.', $methName)
|
|
)
|
|
{
|
|
$dmap = $this->dmap;
|
|
$sysCall = 1;
|
|
}
|
|
|
|
/* verify dispatch map, or try to fix it for non-trivial system calls */
|
|
if(!isset($this->dmap[$methName]['function']))
|
|
{
|
|
if($sysCall)
|
|
{
|
|
/* Bad or non-existent system call, return error */
|
|
$r = CreateObject('phpgwapi.xmlrpcresp',
|
|
'',
|
|
$GLOBALS['xmlrpcerr']['unknown_method'],
|
|
$GLOBALS['xmlrpcstr']['unknown_method'] . ': ' . $methName
|
|
);
|
|
return $r;
|
|
}
|
|
if($this->authed)
|
|
{
|
|
$method = $methName;
|
|
list($app,$class,$method) = explode('.',$methName);
|
|
|
|
switch($app)
|
|
{
|
|
case 'server':
|
|
case 'phpgwapi':
|
|
/* Server role functions only - api access */
|
|
if($GLOBALS['phpgw']->acl->get_role() >= PHPGW_ACL_SERVER)
|
|
{
|
|
$dmap = ExecMethod(sprintf('%s.%s.%s','phpgwapi',$class,'list_methods'),'xmlrpc');
|
|
}
|
|
break;
|
|
case 'service':
|
|
/* Service functions, user-level */
|
|
$t = 'phpgwapi.' . $class . '.exec';
|
|
$dmap = ExecMethod($t,array($service,'list_methods','xmlrpc'));
|
|
break;
|
|
default:
|
|
/* User-level application access */
|
|
if($GLOBALS['phpgw']->acl->check('run',PHPGW_ACL_READ,$app))
|
|
{
|
|
$dmap = ExecMethod(sprintf('',$app,$class,'list_methods'),'xmlrpc');
|
|
}
|
|
else
|
|
{
|
|
$r = CreateObject('phpgwapi.xmlrpcresp',
|
|
'',
|
|
$GLOBALS['xmlrpcerr']['no_access'],
|
|
$GLOBALS['xmlrpcstr']['no_access']
|
|
);
|
|
return $r;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* add the functions from preset $dmap OR list_methods() to the server map */
|
|
foreach($dmap as $meth => $dat)
|
|
{
|
|
$this->add_to_map($meth,$dat['function'],$dat['signature'],$dat['docstring']);
|
|
}
|
|
|
|
/* _debug_array($this->dmap);exit; */
|
|
|
|
/* Now make the call */
|
|
if(isset($dmap[$methName]['function']))
|
|
{
|
|
// dispatch if exists
|
|
if(isset($dmap[$methName]['signature']))
|
|
{
|
|
$sr = $this->verifySignature($m, $dmap[$methName]['signature'] );
|
|
}
|
|
if((!isset($dmap[$methName]['signature'])) || $sr[0])
|
|
{
|
|
// if no signature or correct signature
|
|
$r = xmlrpc_server_call_method($this->server,$data,$params);
|
|
}
|
|
else
|
|
{
|
|
$r = CreateObject('phpgwapi.xmlrpcresp',
|
|
'',
|
|
$GLOBALS['xmlrpcerr']['incorrect_params'],
|
|
$GLOBALS['xmlrpcstr']['incorrect_params'] . ': ' . $sr[1]
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// else prepare error response
|
|
if(!$this->authed)
|
|
{
|
|
// $r = False;
|
|
// send 401 header to force authorization
|
|
$r = CreateObject('phpgwapi.xmlrpcresp',
|
|
CreateObject('phpgwapi.xmlrpcval',
|
|
'UNAUTHORIZED',
|
|
'string'
|
|
)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
$r = CreateObject('phpgwapi.xmlrpcresp',
|
|
'',
|
|
$GLOBALS['xmlrpcerr']['unknown_method'],
|
|
$GLOBALS['xmlrpcstr']['unknown_method'] . ': ' . $methName
|
|
);
|
|
}
|
|
}
|
|
xmlrpc_server_destroy($xmlrpc_server);
|
|
return $r;
|
|
}
|
|
|
|
function echoInput()
|
|
{
|
|
global $HTTP_RAW_POST_DATA;
|
|
|
|
// a debugging routine: just echos back the input
|
|
// packet as a string value
|
|
|
|
/* TODO */
|
|
// $r = CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',"'Aha said I: '" . $HTTP_RAW_POST_DATA,'string'));
|
|
return $HTTP_RAW_POST_DATA;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|