PHP_ARG_WITH([http-magic-mime], [whether to enable response content type guessing],
[ --with-http-magic-mime[=LIBMAGICDIR]
HTTP: with magic mime response content type guessing], "no", "no")
+PHP_ARG_WITH([http-shared-deps], [whether to depend on shared extensions],
+[ --with-http-shared-deps HTTP: disable to not depend on shared extensions
+ like SPL, hash, iconv and session], $PHP_HTTP, $PHP_HTTP)
if test "$PHP_HTTP" != "no"; then
])
])
+ if test "PHP_HTTP_SHARED_DEPS" != "no"; then
+ AC_DEFINE([HTTP_SHARED_DEPS], [1], [ ])
+ else
+ AC_DEFINE([HTTP_SHARED_DEPS], [0], [ ])
+ endif
+
dnl -------
dnl HEADERS
dnl -------
/* {{{ http_module_dep */
#if ZEND_EXTENSION_API_NO >= 220050617
static zend_module_dep http_module_deps[] = {
-# ifdef HAVE_SPL
+# if defined(HAVE_SPL) && !HTTP_SHARED_EXT(SPL)
ZEND_MOD_REQUIRED("spl")
# endif
-# ifdef HTTP_HAVE_EXT_HASH
+# if defined(HTTP_HAVE_EXT_HASH) && !HTTP_SHARED_EXT(HASH)
ZEND_MOD_REQUIRED("hash")
# endif
-# ifdef HAVE_PHP_SESSION
+# if defined(HAVE_PHP_SESSION) && !HTTP_SHARED_EXT(PHP_SESSION)
ZEND_MOD_REQUIRED("session")
# endif
-# ifdef HAVE_ICONV
+# if defined(HAVE_ICONV) && !HTTP_SHARED_EXT(ICONV)
ZEND_MOD_REQUIRED("iconv")
# endif
{NULL, NULL, NULL, 0}
#include "ext/standard/php_string.h"
#include "zend_operators.h"
-#ifdef HAVE_PHP_SESSION
+#ifdef HAVE_PHP_SESSION && !HTTP_SHARED_EXT(PHP_SESSION)
# include "ext/session/php_session.h"
#endif
RETURN_FALSE;
}
-#ifdef HAVE_PHP_SESSION
+#ifdef HAVE_PHP_SESSION && !HTTP_SHARED_EXT(PHP_SESSION)
/* append session info */
if (session) {
if (!params) {
#include "php_http_request_api.h"
#include "php_http_request_object.h"
-#ifndef WONKY
-# ifdef HAVE_SPL
+#if defined(HAVE_SPL) && !HTTP_SHARED_EXT(SPL) && !defined(WONKY)
/* SPL doesn't install its headers */
extern PHPAPI zend_class_entry *spl_ce_Countable;
-# endif
#endif
#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpMessage, method, 0, req_args)
HTTP_REGISTER_CLASS_EX(HttpMessage, http_message_object, NULL, 0);
#ifndef WONKY
-# ifdef HAVE_SPL
+# if defined(HAVE_SPL) && !HTTP_SHARED_EXT(SPL)
zend_class_implements(http_message_object_ce TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator);
# else
zend_class_implements(http_message_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_iterator);
#include "php_http.h"
#include "php_variables.h"
-#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV && !HTTP_SHARED_EXT(ICONV)
# undef PHP_ATOM_INC
# include "ext/iconv/php_iconv.h"
# include "ext/standard/url.h"
static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC);
-#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV && !HTTP_SHARED_EXT(ICONV)
PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC)
{
HashPosition pos;
HTTP_ARG_VAL(delete, 0)
HTTP_END_ARGS;
-#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV && !HTTP_SHARED_EXT(ICONV)
HTTP_BEGIN_ARGS(xlate, 2)
HTTP_ARG_VAL(from_encoding, 0)
HTTP_ARG_VAL(to_encoding, 0)
#ifndef WONKY
HTTP_QUERYSTRING_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
#endif
-#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV && !HTTP_SHARED_EXT(ICONV)
HTTP_QUERYSTRING_ME(xlate, ZEND_ACC_PUBLIC)
#endif
HTTP_QUERYSTRING_GETTER(getObject, IS_OBJECT);
/* }}} */
-#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV && !HTTP_SHARED_EXT(ICONV)
/* {{{ proto bool HttpQueryString::xlate(string ie, string oe)
*
* Converts the query string from the source encoding ie to the target encoding oe.
* Usage:
* <code>
* <?php
- * $rpc = new XmlRpcClient('http://mike:secret@example.com/cgi-bin/vpop-xmlrpc', 'vpop');
- * $rpc->options = array(array('compress' => true));
+ * $rpc = new XmlRpcClient('http://mike:secret@example.com/cgi-bin/vpop-xmlrpc');
+ * $rpc->__request->setOptions(array('compress' => true));
* try {
- * print_r($rpc->listdomain(array('domain' => 'example.com')));
+ * print_r($rpc->vpop->listdomain(array('domain' => 'example.com')));
* } catch (Exception $ex) {
* echo $ex;
* }
* @copyright Michael Wallner, <mike@iworks.at>
* @license BSD, revised
* @package pecl/http
- * @version $Revision$
+ * @version $Revision$
*/
class XmlRpcClient
{
- /**
- * RPC namespace
- *
- * @var string
- */
- public $namespace;
-
- /**
- * HttpRequest instance
- *
- * @var HttpRequest
- */
- public $request;
-
- /**
- * Constructor
- *
- * @param string $url RPC endpoint
- * @param string $namespace RPC namespace
- */
- public function __construct($url, $namespace = '')
- {
- $this->namespace = $namespace;
- $this->request = new HttpRequest($url, HTTP_METH_POST);
- $this->request->setContentType('text/xml');
- }
-
- /**
- * RPC method proxy
- *
- * @param string $method RPC method name
- * @param array $params RPC method arguments
- * @return mixed decoded RPC response
- * @throws Exception
- */
- public function __call($method, array $params)
- {
- if ($this->namespace) {
- $method = $this->namespace .'.'. $method;
- }
-
- $data = xmlrpc_encode_request($method, $params);
- $this->request->setRawPostData($data);
-
- $response = $this->request->send();
- if ($response->getResponseCode() != 200) {
- throw new Exception(
- $response->getResponseStatus(),
- $response->getResponseCode()
- );
- }
- $data = xmlrpc_decode($response->getBody(), 'utf-8');
-
- if (isset($data['faultCode'], $data['faultString'])) {
- throw new Exception(
- $data['faultString'],
- $data['faultCode']
- );
- }
-
- return $data;
- }
-
- public function __set($what, $params)
- {
- return call_user_func_array(
- array($this->request, "set$what"),
- $params
- );
- }
-
- public function __get($what)
- {
- return call_user_func(
- array($this->request, "get$what")
- );
- }
+ /**
+ * RPC namespace
+ *
+ * @var string
+ */
+ public $__namespace;
+
+ /**
+ * HttpRequest instance
+ *
+ * @var HttpRequest
+ */
+ public $__request;
+
+ /**
+ * Client charset
+ *
+ * @var string
+ */
+ public $__encoding = "iso-8859-1";
+
+ /**
+ * Constructor
+ *
+ * @param string $url RPC endpoint
+ * @param string $namespace RPC namespace
+ * @param array $options HttpRequest options
+ */
+ public function __construct($url, $namespace = '', array $options = null)
+ {
+ $this->__request = new HttpRequest($url, HTTP_METH_POST);
+ $this->__request->setOptions($options);
+ $this->__namespace = $namespace;
+ }
+
+ /**
+ * RPC method proxy
+ *
+ * @param string $method RPC method name
+ * @param array $params RPC method arguments
+ * @return mixed decoded RPC response
+ * @throws Exception
+ */
+ public function __call($method, array $params)
+ {
+ if ($this->__namespace) {
+ $method = $this->__namespace .'.'. $method;
+ }
+ $this->__request->setContentType("text/xml; charset=". $this->__encoding);
+ $request = xmlrpc_encode_request($method, $params, array("encoding" => $this->__encoding));
+ $this->__request->setRawPostData($request);
+ $this->__request->send();
+ $response = $this->__request->getResponseMessage();
+ if ($response->getResponseCode() != 200) {
+ throw new Exception(
+ $response->getResponseStatus(),
+ $response->getResponseCode()
+ );
+ }
+
+ $data = xmlrpc_decode($response->getBody(), $this->__encoding);
+ if (xmlrpc_is_fault($data)) {
+ throw new Exception(
+ (string) $data['faultString'],
+ (int) $data['faultCode']
+ );
+ }
+
+ return $data;
+ }
+
+ /**
+ * Returns self, where namespace is set to variable name
+ *
+ * @param string $ns
+ * @return XmlRpcRequest
+ */
+ public function __get($ns)
+ {
+ $this->__namespace = $ns;
+ return $this;
+ }
}
?>
--- /dev/null
+<?php
+
+XmlRpcServer::setContentType("text/xml");
+XmlRpcServer::capture();
+
+/**
+ * XMLRPC Server, very KISS
+ * $Id$
+ *
+ * NOTE: requires ext/xmlrpc
+ *
+ * Usage:
+ * <code>
+ * <?php
+ * class Handler extends XmlRpcRequestHandlerStub {
+ * public function xmlrpcPing(array $values) {
+ * return true;
+ * }
+ * }
+ * try {
+ * XmlRpcServer::factory("namespace")->registerHandler(new Handler);
+ * XmlRpcServer::run();
+ * } catch (Exception $ex) {
+ * XmlRpcServer::error($ex->getCode(), $ex->getMessage());
+ * }
+ * </code>
+ *
+ * @copyright Michael Wallner, <mike@iworks.at>
+ * @license BSD, revised
+ * @package pecl/http
+ * @version $Revision$
+ */
+
+class XmlRpcServer extends HttpResponse
+{
+ /**
+ * Server charset
+ *
+ * @var string
+ */
+ public static $encoding = "iso-8859-1";
+
+ /**
+ * RPC namespace
+ *
+ * @var string
+ */
+ public $namespace;
+
+ /**
+ * RPC handler attached to this server instance
+ *
+ * @var XmlRpcRequestHandler
+ */
+ protected $handler;
+
+ private static $xmlreq;
+ private static $xmlrpc;
+ private static $refcnt = 0;
+ private static $handle = array();
+
+ /**
+ * Create a new XmlRpcServer instance
+ *
+ * @param string $namespace
+ * @param string $encoding
+ */
+ public function __construct($namespace) {
+ $this->namespace = $namespace;
+ self::initialize();
+ }
+
+ /**
+ * Destructor
+ */
+ public function __destruct() {
+ if (self::$refcnt && !--self::$refcnt) {
+ xmlrpc_server_destroy(self::$xmlrpc);
+ }
+ }
+
+ /**
+ * Static factory
+ *
+ * @param string $namespace
+ * @return XmlRpcServer
+ */
+ public static function factory($namespace) {
+ return new XmlRpcServer($namespace);
+ }
+
+ /**
+ * Run all servers and send response
+ *
+ * @param array $options
+ */
+ public static function run(array $options = null) {
+ self::initialize(false, true);
+ HttpResponse::setContentType("text/xml; charset=". self::$encoding);
+ echo xmlrpc_server_call_method(self::$xmlrpc, self::$xmlreq, null,
+ array("encoding" => self::$encoding) + (array) $options);
+ }
+
+ /**
+ * Test hook; call instead of XmlRpcServer::run()
+ *
+ * @param string $method
+ * @param array $params
+ * @param array $options
+ */
+ public static function test($method, array $params, array $options = null) {
+ self::$xmlreq = xmlrpc_encode_request($method, $params);
+ self::run();
+ }
+
+ /**
+ * Optional XMLRPC error handler
+ *
+ * @param int $code
+ * @param string $msg
+ */
+ public static function error($code, $msg) {
+ echo xmlrpc_encode(array("faultCode" => $code, "faultString" => $msg));
+ }
+
+ /**
+ * Register a single method
+ *
+ * @param string $name
+ * @param mixed $callback
+ * @param mixed $dispatch
+ * @param array $spec
+ */
+ public function registerMethod($name, $callback, $dispatch = null, array $spec = null) {
+ if (!is_callable($callback, false, $cb_name)) {
+ throw new Exception("$cb_name is not a valid callback");
+ }
+ if (isset($dispatch)) {
+ if (!is_callable($dispatch, false, $cb_name)) {
+ throw new Exception("$cb_name is not a valid callback");
+ }
+ xmlrpc_server_register_method(self::$xmlrpc, $name, $dispatch);
+ self::$handle[$name] = $callback;
+ } else {
+ xmlrpc_server_register_method(self::$xmlrpc, $name, $callback);
+ }
+
+ if (isset($spec)) {
+ xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
+ }
+ }
+
+ /**
+ * Register an XmlRpcRequestHandler for this server instance
+ *
+ * @param XmlRpcRequestHandler $handler
+ */
+ public function registerHandler(XmlRpcRequestHandler $handler) {
+ $this->handler = $handler;
+
+ foreach (get_class_methods($handler) as $method) {
+ if (!strncmp($method, "xmlrpc", 6)) {
+ $this->registerMethod(
+ $this->method($method, $handler->getNamespace()),
+ array($handler, $method), array($this, "dispatch"));
+ }
+ }
+
+ $handler->getIntrospectionData($spec);
+ if (is_array($spec)) {
+ xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
+ }
+ }
+
+ private function method($method, $namespace = null) {
+ if (!strlen($namespace)) {
+ $namespace = strlen($this->namespace) ? $this->namespace : "xmlrpc";
+ }
+ return $namespace .".". strtolower($method[6]) . substr($method, 7);
+ }
+
+ private function dispatch($method, array $params = null) {
+ if (array_key_exists($method, self::$handle)) {
+ return call_user_func(self::$handle[$method], $params);
+ }
+ throw new Exception("Unknown XMLRPC method: $method");
+ }
+
+ private static function initialize($server = true, $data = false) {
+ if ($data) {
+ if (!self::$xmlreq && !(self::$xmlreq = http_get_request_body())) {
+ throw new Exception("Failed to fetch XMLRPC request body");
+ }
+ }
+ if ($server) {
+ if (!self::$xmlrpc && !(self::$xmlrpc = xmlrpc_server_create())) {
+ throw new Exception("Failed to initialize XMLRPC server");
+ }
+ ++self::$refcnt;
+ }
+ }
+}
+
+/**
+ * XmlRpcRequestHandler
+ *
+ * Define XMLRPC methods with an "xmlrpc" prefix, eg:
+ * <code>
+ * class IntOp implements XmlRpcRequestHandler {
+ * public function getNamespace() {
+ * return "int";
+ * }
+ * public function getInstrospectionData(array &$spec = null) {
+ * }
+ * // XMLRPC method name: int.sumValues
+ * public function xmlrpcSumValues(array $values) {
+ * return array_sum($values);
+ * }
+ * }
+ * </code>
+ */
+interface XmlRpcRequestHandler {
+ public function getNamespace();
+ public function getIntrospectionData(array &$spec = null);
+}
+
+/**
+ * XmlRpcRequestHandlerStub
+ */
+abstract class XmlRpcRequestHandlerStub implements XmlRpcRequestHandler {
+ public function getNamespace() {
+ }
+ public function getIntrospectionData(array &$spec = null) {
+ }
+}
+
+?>
# define HTTP_G (&http_globals)
#endif
+#define HTTP_SHARED_EXT(EXT) (COMPILE_DL_##EXT && !HTTP_SHARED_DEPS)
+
PHP_FUNCTION(http_test);
PHP_FUNCTION(http_date);
PHP_FUNCTION(http_build_url);
#include "ext/standard/crc32.h"
#include "ext/standard/sha1.h"
#include "ext/standard/md5.h"
-#if defined(HTTP_HAVE_EXT_HASH)
-# include "php_hash.h"
-#elif defined(HTTP_HAVE_HASH_EXT_HASH)
-# define HTTP_HAVE_EXT_HASH
-# include "hash/php_hash.h"
-#elif defined(HTTP_HAVE_EXT_HASH_EXT_HASH)
-# define HTTP_HAVE_EXT_HASH
-# include "ext/hash/php_hash.h"
+#if !HTTP_SHARED_EXT(HASH)
+# if defined(HTTP_HAVE_EXT_HASH)
+# include "php_hash.h"
+# elif defined(HTTP_HAVE_HASH_EXT_HASH)
+# define HTTP_HAVE_EXT_HASH
+# include "hash/php_hash.h"
+# elif defined(HTTP_HAVE_EXT_HASH_EXT_HASH)
+# define HTTP_HAVE_EXT_HASH
+# include "ext/hash/php_hash.h"
+# endif
#endif
#define http_etag_digest(d, l) _http_etag_digest((d), (l))
void *ctx = NULL;
char *mode = HTTP_G->etag.mode;
-#ifdef HTTP_HAVE_EXT_HASH
+#if defined(HTTP_HAVE_EXT_HASH) && !HTTP_SHARED_EXT(HASH)
php_hash_ops *eho = NULL;
if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
unsigned char digest[128] = {0};
char *etag = NULL, *mode = HTTP_G->etag.mode;
-#ifdef HTTP_HAVE_EXT_HASH
+#if defined(HTTP_HAVE_EXT_HASH) && !HTTP_SHARED_EXT(HASH)
php_hash_ops *eho = NULL;
if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
static inline void _http_etag_update(void *ctx, const char *data_ptr, size_t data_len TSRMLS_DC)
{
char *mode = HTTP_G->etag.mode;
-#ifdef HTTP_HAVE_EXT_HASH
+#if defined(HTTP_HAVE_EXT_HASH) && !HTTP_SHARED_EXT(HASH)
php_hash_ops *eho = NULL;
if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
#ifndef PHP_HTTP_QUERYSTRING_API_H
#define PHP_HTTP_QUERYSTRING_API_H
-#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV && !HTTP_SHARED_EXT(ICONV)
#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC)
PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC);
#endif
PHP_METHOD(HttpQueryString, getString);
PHP_METHOD(HttpQueryString, getArray);
PHP_METHOD(HttpQueryString, getObject);
-#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV && !HTTP_SHARED_EXT(ICONV)
PHP_METHOD(HttpQueryString, xlate);
#endif
#ifndef WONKY