add setOption/getOption and co to Client and Server
authorgggeek <giunta.gaetano@gmail.com>
Mon, 30 Jan 2023 15:24:22 +0000 (15:24 +0000)
committergggeek <giunta.gaetano@gmail.com>
Mon, 30 Jan 2023 15:24:22 +0000 (15:24 +0000)
NEWS.md
src/Client.php
src/Server.php

diff --git a/NEWS.md b/NEWS.md
index 1107569..ebcfc69 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -68,8 +68,8 @@
 * new: method `PhpXmlRpc::useInteropFaults()` can be used to make the library change the error codes it generates to
   match the spec described at https://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
 
-* new: added the `Client::setTimeout` method, meant to replace usage of the `$timeout` argument in calls to `send`
-  and `multicall`
+* new: added methods `getOption`, `setOption`, `setOptions` and `getOptions` to both Client and Server, meant to replace
+  direct access to _all public properties_ as well as the `$timeout` argument in calls to `Client::send` and `Client::multicall`
 
 * new: method `Client::getUrl()`
 
index 396e0eb..532c5ee 100644 (file)
@@ -3,13 +3,12 @@
 namespace PhpXmlRpc;
 
 //use PhpXmlRpc\Helper\Charset;
+use PhpXmlRpc\Exception\ValueErrorException;
 use PhpXmlRpc\Helper\XMLParser;
 use PhpXmlRpc\Traits\LoggerAware;
 
 /**
  * Used to represent a client of an XML-RPC server.
- *
- * @todo add a setTimeout method, in the vein of other options which can be set to the Client
  */
 class Client
 {
@@ -19,6 +18,37 @@ class Client
     const USE_CURL_ALWAYS = 1;
     const USE_CURL_AUTO = 2;
 
+    const OPT_ACCEPTED_CHARSET_ENCODINGS = 'accepted_charset_encodings';
+    const OPT_ACCEPTED_COMPRESSION = 'accepted_compression';
+    const OPT_AUTH_TYPE = 'authtype';
+    const OPT_CA_CERT = 'cacert';
+    const OPT_CA_CERT_DIR = 'cacertdir';
+    const OPT_CERT = 'cert';
+    const OPT_CERT_PASS = 'certpass';
+    const OPT_COOKIES = 'cookies';
+    const OPT_DEBUG = 'debug';
+    const OPT_EXTRA_CURL_OPTS = 'extracurlopts';
+    const OPT_KEEPALIVE = 'keepalive';
+    const OPT_KEY = 'key';
+    const OPT_KEY_PASS = 'keypass';
+    const OPT_NO_MULTICALL = 'no_multicall';
+    const OPT_PASSWORD = 'password';
+    const OPT_PROXY = 'proxy';
+    const OPT_PROXY_AUTH_TYPE = 'proxy_authtype';
+    const OPT_PROXY_PASS = 'proxy_pass';
+    const OPT_PROXY_PORT = 'proxyport';
+    const OPT_PROXY_USER = 'proxy_user';
+    const OPT_REQUEST_CHARSET_ENCODING = 'request_charset_encoding';
+    const OPT_REQUEST_COMPRESSION = 'request_compression';
+    const OPT_RETURN_TYPE = 'return_type';
+    const OPT_SSL_VERSION = 'sslversion';
+    const OPT_TIMEOUT = 'timeout';
+    const OPT_USERNAME = 'username';
+    const OPT_USER_AGENT = 'user_agent';
+    const OPT_USE_CURL = 'use_curl';
+    const OPT_VERIFY_HOST = 'verifyhost';
+    const OPT_VERIFY_PEER = 'verifypeer';
+
     /** @var string */
     protected static $requestClass = '\\PhpXmlRpc\\Request';
     /** @var string */
@@ -39,143 +69,135 @@ class Client
 
     /**
      * @var string
-     * @internal use getUrl
+     * @internal use getUrl/__construct
      */
     public $method = 'http';
     /**
      * @var string
-     * @internal use getUrl
+     * @internal use getUrl/__construct
      */
     public $server;
     /**
      * @var int
-     * @internal use getUrl
+     * @internal use getUrl/__construct
      */
     public $port = 0;
     /**
      * @var string
-     * @internal use getUrl
+     * @internal use getUrl/__construct
      */
     public $path;
 
     /**
      * @var int
-     * @internal use setDebug
+     * @internal use setOption/getOption
      */
     public $debug = 0;
-
     /**
      * @var string
-     * @internal use setCredentials
+     * @internal use setCredentials/getOption
      */
     public $username = '';
     /**
      * @var string
-     * @internal use setCredentials
+     * @internal use setCredentials/getOption
      */
     public $password = '';
     /**
      * @var int
-     * @internal use setCredentials
+     * @internal use setCredentials/getOption
      */
     public $authtype = 1;
-
     /**
      * @var string
-     * @internal use setCertificate
+     * @internal use setCertificate/getOption
      */
     public $cert = '';
     /**
      * @var string
-     * @internal use setCertificate
+     * @internal use setCertificate/getOption
      */
     public $certpass = '';
     /**
      * @var string
-     * @internal use setCaCertificate
+     * @internal use setCaCertificate/getOption
      */
     public $cacert = '';
     /**
      * @var string
-     * @internal use setCaCertificate
+     * @internal use setCaCertificate/getOption
      */
     public $cacertdir = '';
     /**
      * @var string
-     * @internal use setKey
+     * @internal use setKey/getOption
      */
     public $key = '';
     /**
      * @var string
-     * @internal use setKey
+     * @internal use setKey/getOption
      */
     public $keypass = '';
     /**
      * @var bool
-     * @internal use setSSLVerifyPeer
+     * @internal use setOption/getOption
      */
     public $verifypeer = true;
     /**
      * @var int
-     * @internal use setSSLVerifyHost
+     * @internal use setOption/getOption
      */
     public $verifyhost = 2;
     /**
      * @var int
-     * @internal use setSSLVersion
+     * @internal use setOption/getOption
      */
     public $sslversion = 0; // corresponds to CURL_SSLVERSION_DEFAULT
-
     /**
      * @var string
-     * @internal use setProxy
+     * @internal use setProxy/getOption
      */
     public $proxy = '';
     /**
      * @var int
-     * @internal use setProxy
+     * @internal use setProxy/getOption
      */
     public $proxyport = 0;
     /**
      * @var string
-     * @internal use setProxy
+     * @internal use setProxy/getOption
      */
     public $proxy_user = '';
     /**
      * @var string
-     * @internal use setProxy
+     * @internal use setProxy/getOption
      */
     public $proxy_pass = '';
     /**
      * @var int
-     * @internal use setProxy
+     * @internal use setProxy/getOption
      */
     public $proxy_authtype = 1;
-
     /**
      * @var array
-     * @internal use setCookie
+     * @internal use setCookie/getOption
      */
     public $cookies = array();
-
     /**
      * @var array
-     * @internal use setCurlOptions
+     * @internal use setOption/getOption
      */
     public $extracurlopts = array();
-
     /**
      * @var int
-     * @internal use setTimeout
+     * @internal use setOption/getOption
      */
     public $timeout = 0;
-
     /**
      * @var int
-     * @internal use setUseCurl
+     * @internal use setOption/getOption
      */
     public $use_curl = self::USE_CURL_AUTO;
-
     /**
      * @var bool
      *
@@ -183,9 +205,10 @@ class Client
      * to dispatch to the server an array of requests in a single http roundtrip or simply execute many consecutive http
      * calls. Defaults to FALSE, but it will be enabled automatically on the first failure of execution of
      * system.multicall.
+     *
+     * @internal use setOption/getOption
      */
     public $no_multicall = false;
-
     /**
      * @var array
      *
@@ -196,34 +219,34 @@ class Client
      * decide the compression methods it supports. You might check for the presence of 'zlib' in the output of
      * curl_version() to determine whether compression is supported or not
      *
-     * @internal use setAcceptedCompression
+     * @internal use setAcceptedCompression/getOption
      */
     public $accepted_compression = array();
-
     /**
      * @var string|null
      *
      * Name of compression scheme to be used for sending requests.
      * Either null, 'gzip' or 'deflate'.
      *
-     * @internal use setRequestCompression
+     * @internal use setOption/getOption
      */
     public $request_compression = '';
-
     /**
      * @var bool
      *
-     * Whether to use persistent connections for http 1.1 and https. Value set at constructor time
+     * Whether to use persistent connections for http 1.1 and https. Value set at constructor time.
+     *
+     * @internal use setOption/getOption
      */
     public $keepalive = false;
-
     /**
      * @var string[]
      *
      * Charset encodings that can be decoded without problems by the client. Value set at constructor time
+     *
+     * @internal use setOption/getOption
      */
     public $accepted_charset_encodings = array();
-
     /**
      * @var string
      *
@@ -233,9 +256,10 @@ class Client
      * in the transfer, a CR-LF will be preserved as well as a singe LF).
      * Valid values are 'US-ASCII', 'UTF-8' and 'ISO-8859-1'.
      * For the fastest mode of operation, set your both your app internal encoding and this to UTF-8.
+     *
+     * @internal use setOption/getOption
      */
     public $request_charset_encoding = '';
-
     /**
      * @var string
      *
@@ -250,15 +274,16 @@ class Client
      * Note that the 'phpvals' setting will yield faster execution times, but some of the information from the original
      * response will be lost. It will be e.g. impossible to tell whether a particular php string value was sent by the
      * server as an xml-rpc string or base64 value.
+     *
+     * @internal use setOption/getOption
      */
     public $return_type = XMLParser::RETURN_XMLRPCVALS;
-
     /**
      * @var string
      *
      * Sent to servers in http headers. Value set at constructor time.
      *
-     * @internal use setUserAgent
+     * @internal use setOption/getOption
      */
     public $user_agent;
 
@@ -268,6 +293,42 @@ class Client
      */
     public $xmlrpc_curl_handle = null;
 
+    /**
+     * @var array
+     */
+    protected $options = array(
+        self::OPT_ACCEPTED_CHARSET_ENCODINGS,
+        self::OPT_ACCEPTED_COMPRESSION,
+        self::OPT_AUTH_TYPE,
+        self::OPT_CA_CERT,
+        self::OPT_CA_CERT_DIR,
+        self::OPT_CERT,
+        self::OPT_CERT_PASS,
+        self::OPT_COOKIES,
+        self::OPT_DEBUG,
+        self::OPT_EXTRA_CURL_OPTS,
+        self::OPT_KEEPALIVE,
+        self::OPT_KEY,
+        self::OPT_KEY_PASS,
+        self::OPT_NO_MULTICALL,
+        self::OPT_PASSWORD,
+        self::OPT_PROXY,
+        self::OPT_PROXY_AUTH_TYPE,
+        self::OPT_PROXY_PASS,
+        self::OPT_PROXY_USER,
+        self::OPT_PROXY_PORT,
+        self::OPT_REQUEST_CHARSET_ENCODING,
+        self::OPT_REQUEST_COMPRESSION,
+        self::OPT_RETURN_TYPE,
+        self::OPT_SSL_VERSION,
+        self::OPT_TIMEOUT,
+        self::OPT_USE_CURL,
+        self::OPT_USER_AGENT,
+        self::OPT_USERNAME,
+        self::OPT_VERIFY_HOST,
+        self::OPT_VERIFY_PEER,
+    );
+
     /**
      * @param string $path either the PATH part of the xml-rpc server URL, or complete server URL (in which case you
      *                     should use and empty string for all other parameters)
@@ -347,6 +408,212 @@ class Client
         $this->user_agent = PhpXmlRpc::$xmlrpcName . ' ' . PhpXmlRpc::$xmlrpcVersion;
     }
 
+    /**
+     * @param string $name
+     * @param mixed $value
+     * @return $this
+     * @throws ValueErrorException on unsupported option
+     */
+    public function setOption($name, $value)
+    {
+        switch ($name) {
+            case self::OPT_ACCEPTED_CHARSET_ENCODINGS:
+                $this->accepted_charset_encodings = $value;
+                break;
+            case self::OPT_ACCEPTED_COMPRESSION:
+                $this->accepted_compression = $value;
+                break;
+            case self::OPT_AUTH_TYPE:
+                $this->authtype = $value;
+                break;
+            case self::OPT_CA_CERT:
+                $this->cacert = $value;
+                break;
+            case self::OPT_CA_CERT_DIR:
+                $this->cacertdir = $value;
+                break;
+            case self::OPT_CERT:
+                $this->cert = $value;
+                break;
+            case self::OPT_CERT_PASS:
+                $this->certpass = $value;
+                break;
+            case self::OPT_COOKIES:
+                $this->cookies = $value;
+                break;
+            case self::OPT_DEBUG:
+                $this->debug = $value;
+                break;
+            case self::OPT_EXTRA_CURL_OPTS:
+                $this->extracurlopts = $value;
+                break;
+            case self::OPT_KEEPALIVE:
+                $this->keepalive = $value;
+                break;
+            case self::OPT_KEY:
+                $this->key = $value;
+                break;
+            case self::OPT_KEY_PASS:
+                $this->keypass = $value;
+                break;
+            case self::OPT_NO_MULTICALL:
+                $this->no_multicall = $value;
+                break;
+            case self::OPT_PASSWORD:
+                $this->password = $value;
+                break;
+            case self::OPT_PROXY:
+                $this->proxy = $value;
+                break;
+            case self::OPT_PROXY_AUTH_TYPE:
+                $this->proxy_authtype = $value;
+                break;
+            case self::OPT_PROXY_PASS:
+                $this->proxy_pass = $value;
+                break;
+            case self::OPT_PROXY_PORT:
+                $this->proxyport = $value;
+                break;
+            case self::OPT_PROXY_USER:
+                $this->proxy_user = $value;
+                break;
+            case self::OPT_REQUEST_CHARSET_ENCODING:
+                $this->request_charset_encoding = $value;
+                break;
+            case self::OPT_REQUEST_COMPRESSION:
+                $this->request_compression = $value;
+                break;
+            case self::OPT_RETURN_TYPE:
+                $this->return_type = $value;
+                break;
+            case self::OPT_SSL_VERSION:
+                $this->sslversion = $value;
+                break;
+            case self::OPT_TIMEOUT:
+                $this->timeout = $value;
+                break;
+            case self::OPT_USERNAME:
+                $this->username = $value;
+                break;
+            case self::OPT_USER_AGENT:
+                $this->user_agent = $value;
+                break;
+            case self::OPT_USE_CURL:
+                $this->use_curl = $value;
+                break;
+            case self::OPT_VERIFY_HOST:
+                $this->verifyhost = $value;
+                break;
+            case self::OPT_VERIFY_PEER:
+                $this->verifypeer = $value;
+                break;
+            default:
+                throw new ValueErrorException("Unsupported option '$name'");
+        }
+
+        return $this;
+    }
+
+    /**
+     * @param string $name
+     * @return mixed
+     * @throws ValueErrorException on unsupported option
+     */
+    public function getOption($name)
+    {
+        switch ($name) {
+            case self::OPT_ACCEPTED_CHARSET_ENCODINGS:
+                return $this->accepted_charset_encodings;
+            case self::OPT_ACCEPTED_COMPRESSION:
+                return $this->accepted_compression;
+            case self::OPT_AUTH_TYPE:
+                return $this->authtype;
+            case self::OPT_CA_CERT:
+                return $this->cacert;
+            case self::OPT_CA_CERT_DIR:
+                return $this->cacertdir;
+            case self::OPT_CERT:
+                return $this->cert;
+            case self::OPT_CERT_PASS:
+                return $this->certpass;
+            case self::OPT_COOKIES:
+                return $this->cookies;
+            case self::OPT_DEBUG:
+                return $this->debug;
+            case self::OPT_EXTRA_CURL_OPTS:
+                return $this->extracurlopts;
+            case self::OPT_KEEPALIVE:
+                return $this->keepalive;
+            case self::OPT_KEY:
+                return $this->key;
+            case self::OPT_KEY_PASS:
+                return $this->keypass;
+            case self::OPT_NO_MULTICALL:
+                return $this->no_multicall;
+            case self::OPT_PASSWORD:
+                return $this->password;
+            case self::OPT_PROXY:
+                return $this->proxy;
+            case self::OPT_PROXY_AUTH_TYPE:
+                return $this->proxy_authtype;
+            case self::OPT_PROXY_PASS:
+                return $this->proxy_pass;
+            case self::OPT_PROXY_PORT:
+                return $this->proxyport;
+            case self::OPT_PROXY_USER:
+                return $this->proxy_user;
+            case self::OPT_REQUEST_CHARSET_ENCODING:
+                return $this->request_charset_encoding;
+            case self::OPT_REQUEST_COMPRESSION:
+                return $this->request_compression;
+            case self::OPT_RETURN_TYPE:
+                return $this->return_type;
+            case self::OPT_SSL_VERSION:
+                return $this->sslversion;
+            case self::OPT_TIMEOUT:
+                return $this->timeout;
+            case self::OPT_USERNAME:
+                return $this->username;
+            case self::OPT_USER_AGENT:
+                return $this->user_agent;
+            case self::OPT_USE_CURL:
+                return $this->use_curl;
+            case self::OPT_VERIFY_HOST:
+                return $this->verifyhost;
+            case self::OPT_VERIFY_PEER:
+                return $this->verifypeer;
+            default:
+                throw new ValueErrorException("Unsupported option '$name'");
+        }
+    }
+
+    /**
+     * Returns the complete list of Client options.
+     * @return array
+     */
+    public function getOptions()
+    {
+        $values = array();
+        foreach($this->options as $opt) {
+            $values[$opt] = $this->getOption($opt);
+        }
+        return $values;
+    }
+
+    /**
+     * @param array $options
+     * @return $this
+     * @throws ValueErrorException on unsupported option
+     */
+    public function setOptions($options)
+    {
+        foreach($options as $name => $value) {
+            $this->setOption($name, $value);
+        }
+
+        return $this;
+    }
+
     /**
      * Enable/disable the echoing to screen of the xml-rpc responses received. The default is not to output anything.
      *
@@ -362,6 +629,7 @@ class Client
      *
      * @param integer $level values -1, 0, 1 and 2 are supported
      * @return $this
+     * @deprecated use setOption
      */
     public function setDebug($level)
     {
@@ -455,6 +723,7 @@ class Client
      *
      * @param bool $i enable/disable verification of peer certificate
      * @return $this
+     * @deprecated use setOption
      */
     public function setSSLVerifyPeer($i)
     {
@@ -469,6 +738,7 @@ class Client
      *
      * @param int $i Set to 1 to only the existence of a CN, not that it matches
      * @return $this
+     * @deprecated use setOption
      */
     public function setSSLVerifyHost($i)
     {
@@ -481,6 +751,7 @@ class Client
      *
      * @param int $i
      * @return $this
+     * @deprecated use setOption
      */
     public function setSSLVersion($i)
     {
@@ -543,6 +814,7 @@ class Client
      *
      * @param string $compMethod either 'gzip', 'deflate' or ''
      * @return $this
+     * @deprecated use setOption
      */
     public function setRequestCompression($compMethod)
     {
@@ -591,6 +863,7 @@ class Client
      *
      * @param array $options
      * @return $this
+     * @deprecated use setOption
      */
     public function setCurlOptions($options)
     {
@@ -601,6 +874,7 @@ class Client
     /**
      * @param int $useCurlMode self::USE_CURL_ALWAYS, self::USE_CURL_AUTO or self::USE_CURL_NEVER
      * @return $this
+     * @deprecated use setOption
      */
     public function setUseCurl($useCurlMode)
     {
@@ -616,6 +890,7 @@ class Client
      *
      * @param string $agentString
      * @return $this
+     * @deprecated use setOption
      */
     public function setUserAgent($agentString)
     {
@@ -623,16 +898,6 @@ class Client
         return $this;
     }
 
-    /**
-     * @param int $timeout
-     * @return $this
-     */
-    public function setTimeout($timeout)
-    {
-        $this->timeout = $timeout;
-        return $this;
-    }
-
     /**
      * @return string
      */
@@ -663,7 +928,7 @@ class Client
      *                                      containing the complete xml representation of the request. It is e.g. useful
      *                                      when, for maximal speed of execution, the request is serialized into a
      *                                      string using the native php xml-rpc functions (see http://www.php.net/xmlrpc)
-     * @param integer $timeout deprecated. Connection timeout, in seconds, If unspecified, the timeout set with setTimeout
+     * @param integer $timeout deprecated. Connection timeout, in seconds, If unspecified, the timeout set with setOption
      *                         will be used. If that is 0, a platform specific timeout will apply.
      *                         This timeout value is passed to fsockopen(). It is also used for detecting server
      *                         timeouts during communication (i.e. if the server does not send anything to the client
@@ -702,7 +967,7 @@ class Client
 
             return $r;
         } elseif (is_string($req)) {
-            $n = new  static::$requestClass('');
+            $n = new static::$requestClass('');
             $n->payload = $req;
             $req = $n;
         }
@@ -933,7 +1198,7 @@ class Client
             $uri = $this->path;
         }
 
-        // Cookie generation, as per rfc2965 (version 1 cookies) or netscape's rules (version 0 cookies)
+        // Cookie generation, as per rfc2965
         $cookieHeader = '';
         if (count($this->cookies)) {
             $version = '';
index e10210a..db590bc 100644 (file)
@@ -3,6 +3,7 @@
 namespace PhpXmlRpc;
 
 use PhpXmlRpc\Exception\NoSuchMethodException;
+use PhpXmlRpc\Exception\ValueErrorException;
 use PhpXmlRpc\Helper\Http;
 use PhpXmlRpc\Helper\Interop;
 use PhpXmlRpc\Helper\Logger;
@@ -20,6 +21,15 @@ class Server
     use LoggerAware;
     use ParserAware;
 
+    const OPT_ACCEPTED_COMPRESSION = 'accepted_compression';
+    const OPT_ALLOW_SYSTEM_FUNCS = 'allow_system_funcs';
+    const OPT_COMPRESS_RESPONSE = 'compress_response';
+    const OPT_DEBUG = 'debug';
+    const OPT_EXCEPTION_HANDLING = 'exception_handling';
+    const OPT_FUNCTIONS_PARAMETERS_TYPE = 'functions_parameters_type';
+    const OPT_PHPVALS_ENCODING_OPTIONS = 'phpvals_encoding_options';
+    const OPT_RESPONSE_CHARSET_ENCODING = 'response_charset_encoding';
+
     /**
      * @var string
      * Defines how functions in $dmap will be invoked: either using an xml-rpc Request object or plain php values.
@@ -113,6 +123,17 @@ class Server
      */
     protected $dmap = array();
 
+    protected $options = array(
+        self::OPT_ACCEPTED_COMPRESSION,
+        self::OPT_ALLOW_SYSTEM_FUNCS,
+        self::OPT_COMPRESS_RESPONSE,
+        self::OPT_DEBUG,
+        self::OPT_EXCEPTION_HANDLING,
+        self::OPT_FUNCTIONS_PARAMETERS_TYPE,
+        self::OPT_PHPVALS_ENCODING_OPTIONS,
+        self::OPT_RESPONSE_CHARSET_ENCODING,
+    );
+
     /**
      * Storage for internal debug info.
      */
@@ -163,6 +184,102 @@ class Server
         }
     }
 
+    /**
+     * @param string $name
+     * @param mixed $value
+     * @return $this
+     * @throws ValueErrorException on unsupported option
+     */
+    public function setOption($name, $value)
+    {
+        switch ($name) {
+            case self::OPT_ACCEPTED_COMPRESSION :
+                $this->accepted_charset_encodings = $value;
+                break;
+            case self::OPT_ALLOW_SYSTEM_FUNCS:
+                $this->allow_system_funcs = $value;
+                break;
+            case self::OPT_COMPRESS_RESPONSE:
+                $this->compress_response = $value;
+                break;
+            case self::OPT_DEBUG:
+                $this->debug = $value;
+                break;
+            case self::OPT_EXCEPTION_HANDLING:
+                $this->exception_handling = $value;
+                break;
+            case self::OPT_FUNCTIONS_PARAMETERS_TYPE:
+                $this->functions_parameters_type = $value;
+                break;
+            case self::OPT_PHPVALS_ENCODING_OPTIONS:
+                $this->phpvals_encoding_options = $value;
+                break;
+            case self::OPT_RESPONSE_CHARSET_ENCODING:
+                $this->response_charset_encoding = $value;
+                break;
+            default:
+                throw new ValueErrorException("Unsupported option '$name'");
+        }
+
+        return $this;
+    }
+
+    /**
+     * @param string $name
+     * @return mixed
+     * @throws ValueErrorException on unsupported option
+     */
+    public function getOption($name)
+    {
+        switch ($name) {
+            case self::OPT_ACCEPTED_COMPRESSION:
+                return $this->accepted_compression;
+            case self::OPT_ALLOW_SYSTEM_FUNCS:
+                return $this->allow_system_funcs;
+            case self::OPT_COMPRESS_RESPONSE:
+                return $this->compress_response;
+            case self::OPT_DEBUG:
+                return $this->debug;
+            case self::OPT_EXCEPTION_HANDLING:
+                return $this->exception_handling;
+            case self::OPT_FUNCTIONS_PARAMETERS_TYPE:
+                return $this->functions_parameters_type;
+            case self::OPT_PHPVALS_ENCODING_OPTIONS:
+                return $this->phpvals_encoding_options;
+            case self::OPT_RESPONSE_CHARSET_ENCODING:
+                return $this->response_charset_encoding;
+            default:
+                throw new ValueErrorException("Unsupported option '$name'");
+        }
+    }
+
+    /**
+     * Returns the complete list of Client options.
+     * @return array
+     */
+    public function getOptions()
+    {
+        $values = array();
+        foreach($this->options as $opt) {
+            $values[$opt] = $this->getOption($opt);
+        }
+        return $values;
+    }
+
+    /**
+     * @param array $options
+     * @return $this
+     * @throws ValueErrorException on unsupported option
+     */
+    public function setOptions($options)
+    {
+        foreach($options as $name => $value) {
+            $this->setOption($name, $value);
+        }
+
+        return $this;
+    }
+
     /**
      * Set debug level of server.
      *
@@ -177,6 +294,7 @@ class Server
      *                    execution anymore, but just end up logged in the xml-rpc response)
      *                    Note that info added at level 2 and 3 will be base64 encoded
      * @return $this
+     * @deprecated use setOption
      */
     public function setDebug($level)
     {