forked from extern/egroupware
0711abd82b
- converting to and from dateTime.iso8601 - converting cat_id-arrays to and from xmlrpc structs with cat-id / name pairs (and creating & updateing new cats) 2) removed unnecessary (and not standard conform) xmlrpc struc arround all responses 3) added detection to copy arrays (numerical keys 0,1,...) to xmlrpc arrays and not structs Note: 2+3 only apply to the _php class as the _epi class does this by itself
340 lines
9.0 KiB
PHP
340 lines
9.0 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 extends xmlrpc_server_shared
|
|
{
|
|
var $server = '';
|
|
var $authed = True;
|
|
var $log = False; //'/tmp/xmlrpc.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 = False)
|
|
{
|
|
if (!$r) // do we have a response, or we need to parse the request
|
|
{
|
|
$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;
|
|
}
|
|
*/
|
|
function xmlrpc_error($error_number, $error_string)
|
|
{
|
|
$r = CreateObject('phpgwapi.xmlrpcresp',
|
|
'',
|
|
$error_number,
|
|
$error_string . ': ' . $this->last_method
|
|
);
|
|
$this->service($r);
|
|
xmlrpc_server_destroy($GLOBALS['xmlrpc_server']);
|
|
exit;
|
|
}
|
|
}
|