Files
server/usr/share/psa-pear/pear/php/Horde/Rpc.php
2026-01-07 20:52:11 +01:00

259 lines
8.3 KiB
PHP

<?php
/**
* Copyright 2002-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @author Jan Schneider <jan@horde.org>
* @package Rpc
*/
/**
* The Horde_Rpc class provides a set of server and client methods for RPC
* communication.
*
* TODO:
* - Introspection documentation and method signatures.
*
* EXAMPLE:
* <code>
* $response = Horde_Rpc::request('xmlrpc',
* 'http://localhost:80/horde/rpc.php',
* 'contacts.search',
* $transport_client,
* array(array('jan'), array('localsql'),
* array('name', 'email')));
* </code>
*
* @author Jan Schneider <jan@horde.org>
* @package Rpc
*/
class Horde_Rpc
{
/**
* All driver-specific parameters.
*
* @var array
*/
protected $_params = array();
/**
* Do we need an authenticated user?
*
* @var boolean
*/
protected $_requireAuthorization = true;
/**
* Whether we should exit if auth fails instead of requesting
* authorization credentials.
*
* @var boolean
*/
protected $_requestMissingAuthorization = true;
/**
* Request variables, cookies etc...
*
* @var Horde_Controller_Request_Http
*/
protected $_request;
/**
* Logging
*
* @var Horde_Log_Logger
*/
protected $_logger;
/**
* Constructor.
*
* @param Horde_Controller_Request_Http $request The request object.
* @param array $params A hash containing any additional configuration or
* connection parameters a subclass might need.
*/
public function __construct($request, $params = array())
{
// Create a stub if we don't have a useable logger.
if (isset($params['logger'])
&& is_callable(array($params['logger'], 'log'))) {
$this->_logger = $params['logger'];
unset($params['logger']);
} else {
$this->_logger = new Horde_Support_Stub;
}
$this->_params = $params;
$this->_request = $request;
if (isset($params['requireAuthorization'])) {
$this->_requireAuthorization = $params['requireAuthorization'];
}
if (isset($params['requestMissingAuthorization'])) {
$this->_requestMissingAuthorization = $params['requestMissingAuthorization'];
}
$this->_logger->debug('Horde_Rpc::__construct complete');
}
/**
* Check authentication. Different backends may handle
* authentication in different ways. The base class implementation
* checks for HTTP Authentication against the Horde auth setup.
*
* @return boolean Returns true if authentication is successful.
* Should send appropriate "not authorized" headers
* or other response codes/body if auth fails,
* and take care of exiting.
*/
public function authorize()
{
$this->_logger->debug('Horde_Rpc::authorize() starting');
if (!$this->_requireAuthorization) {
return true;
}
// @TODO: inject this
$auth = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Auth')->create();
$serverVars = $this->_request->getServerVars();
if (!empty($serverVars['PHP_AUTH_USER'])) {
$user = $serverVars['PHP_AUTH_USER'];
$pass = $serverVars['PHP_AUTH_PW'];
} elseif (!empty($serverVars['Authorization'])) {
$hash = str_replace('Basic ', '', $serverVars['Authorization']);
$hash = base64_decode($hash);
if (strpos($hash, ':') !== false) {
list($user, $pass) = explode(':', $hash, 2);
}
}
if (!isset($user)
|| !$auth->authenticate($user, array('password' => $pass))) {
if ($this->_requestMissingAuthorization) {
header('WWW-Authenticate: Basic realm="Horde RPC"');
}
header('HTTP/1.0 401 Unauthorized');
echo '401 Unauthorized';
exit;
}
$this->_logger->debug('Horde_Rpc::authorize() exiting');
return true;
}
/**
* Get the request body input. Different RPC backends can override
* this to return an open stream to php://stdin, for instance -
* whatever is easiest to handle in the getResponse() method.
*
* The base class implementation looks for $HTTP_RAW_POST_DATA and
* returns that if it's available; otherwise, it returns the
* contents of php://stdin.
*
* @return mixed The input - a string (default), a filehandle, etc.
*/
public function getInput()
{
if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
return $GLOBALS['HTTP_RAW_POST_DATA'];
} else {
return implode("\r\n", file('php://input'));
}
}
/**
* Sends an RPC request to the server implementation and returns the
* result.
*
* @param string The raw request string.
*
* @return string The response from the server.
*/
public function getResponse($request)
{
return 'not implemented';
}
/**
* Returns the Content-Type of the response.
*
* @return string The MIME Content-Type of the RPC response.
*/
public function getResponseContentType()
{
return 'text/xml';
}
/**
* Send the output back to the client
*
* @param string $output The output to send back to the client. Can be
* overridden in classes if needed.
*
* @return void
*/
public function sendOutput($output)
{
header('Content-Type: ' . $this->getResponseContentType());
header('Content-length: ' . strlen($output));
header('Accept-Charset: UTF-8');
echo $output;
}
/**
* Builds an RPC request and sends it to the RPC server.
*
* This statically called method is actually the RPC client.
*
* @param string $driver The protocol driver to use. Currently
* 'soap', 'xmlrpc' and 'jsonrpc' are
* available.
* @param string|Horde_Url $url The path to the RPC server on the called
* host.
* @param string $method The method to call.
* @param mixed $client An appropriate request client for the type
* of request. (Horde_Http_Request, SoapClient
* etc..)
* @param array $params A hash containing any necessary parameters
* for the method call.
*
* @return mixed The returned result from the method
* @throws Horde_Rpc_Exception
*/
public static function request($driver, $url, $method, $client,
$params = null)
{
$driver = Horde_String::ucfirst(basename($driver));
$class = 'Horde_Rpc_' . $driver;
if (class_exists($class)) {
return call_user_func(array($class, 'request'), $url, $method, $client, $params);
} else {
throw new Horde_Rpc_Exception('Class definition of ' . $class . ' not found.');
}
}
/**
* Attempts to return a concrete RPC server instance based on
* $driver.
*
* @param mixed $driver The type of concrete Horde_Rpc subclass to return.
* @param array $params A hash containing any additional configuration or
* connection parameters a subclass might need.
*
* @return Horde_Rpc The newly created concrete Horde_Rpc server instance,
* or an exception if there is an error.
*/
public static function factory($driver, $request, $params = null)
{
$driver = basename($driver);
$class = 'Horde_Rpc_' . $driver;
if (class_exists($class)) {
return new $class($request, $params);
} else {
throw new Horde_Rpc_Exception('Class definition of ' . $class . ' not found.');
}
}
}