diff --git a/lang/en_utf8/debug.php b/lang/en_utf8/debug.php index 959b96b35da..11bcd8c1ad3 100644 --- a/lang/en_utf8/debug.php +++ b/lang/en_utf8/debug.php @@ -16,6 +16,7 @@ $string['fixsetting'] = 'Please fix your settings in config.php:

You have:

type == PARAM_BOOL) { + // special case for PARAM_BOOL - we want true/false instead of the usual 1/0 - we can not be too strict here ;-) + if (is_bool($response) or $response === 0 or $response === 1 or $response === '0' or $response === '1') { + return (bool)$response; + } + } + return validate_param($response, $description->type, $description->allownull, get_string('errorinvalidresponseapi', 'webservice')); + + } else if ($description instanceof external_single_structure) { + if (!is_array($response)) { + throw new invalid_response_exception(get_string('erroronlyarray', 'webservice')); + } + $result = array(); + foreach ($description->keys as $key=>$subdesc) { + if (!array_key_exists($key, $response)) { + if ($subdesc->required == VALUE_REQUIRED) { + throw new invalid_response_exception(get_string('errormissingkey', 'webservice', $key)); + } + if ($subdesc instanceof external_value) { + if ($subdesc->required == VALUE_DEFAULT) { + try { + $result[$key] = self::clean_returnvalue($subdesc, $subdesc->default); + } catch (invalid_response_exception $e) { + throw new webservice_parameter_exception('invalidextresponse',$key); + } + } + } + } else { + try { + $result[$key] = self::clean_returnvalue($subdesc, $response[$key]); + } catch (invalid_response_exception $e) { + //it's ok to display debug info as here the information is useful for ws client/dev + throw new webservice_parameter_exception('invalidextresponse',$key." (".$e->debuginfo.")"); + } + } + unset($response[$key]); + } + + return $result; + + } else if ($description instanceof external_multiple_structure) { + if (!is_array($response)) { + throw new invalid_response_exception(get_string('erroronlyarray', 'webservice')); + } + $result = array(); + foreach ($response as $param) { + $result[] = self::clean_returnvalue($description->content, $param); + } + return $result; + + } else { + throw new invalid_response_exception(get_string('errorinvalidresponsedesc', 'webservice')); + } + } + /** * Makes sure user may execute functions in this context. * @param object $context diff --git a/lib/setuplib.php b/lib/setuplib.php index 8170784180d..9ef3b0cbcc8 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -154,6 +154,22 @@ class invalid_parameter_exception extends moodle_exception { } } +/** + * Exception indicating malformed response problem. + * This exception is not supposed to be thrown when processing + * user submitted data in forms. It is more suitable + * for WS and other low level stuff. + */ +class invalid_response_exception extends moodle_exception { + /** + * Constructor + * @param string $debuginfo some detailed information + */ + function __construct($debuginfo=null) { + parent::__construct('invalidresponse', 'debug', '', null, $debuginfo); + } +} + /** * An exception that indicates something really weird happened. For example, * if you do switch ($context->contextlevel), and have one case for each diff --git a/webservice/lib.php b/webservice/lib.php index a9b5c4420f0..662c07a0fbb 100644 --- a/webservice/lib.php +++ b/webservice/lib.php @@ -261,9 +261,6 @@ abstract class webservice_zend_server extends webservice_server { // execute and return response, this sends some headers too $response = $this->zend_server->handle(); - //hook for cleaning response (if necessary) - $response = $this->clean_response($response); - // session cleanup $this->session_cleanup(); @@ -457,9 +454,11 @@ class '.$classname.' { * @return string body of the method for $function ie. everything within the {} of the method declaration. */ protected function service_class_method_body($function, $params){ - return ' return '.$function->classname.'::'.$function->methodname.'('.$params.');'; + $descriptionmethod = $function->methodname.'_returns()'; + $callforreturnvaluedesc = $function->classname.'::'.$descriptionmethod; + return ' return external_api::clean_returnvalue('.$callforreturnvaluedesc.', '.$function->classname.'::'.$function->methodname.'('.$params.'));'; } - + /** * Set up zend service class * @return void @@ -547,15 +546,6 @@ class '.$classname.' { } } - /** - * Hook needed for cleaning the response (xml-rpc, soap,...). - * @param array $response the response to clean - * @return array $response the cleaned response - */ - protected function clean_response($response) { - return $response; - } - } /** diff --git a/webservice/xmlrpc/locallib.php b/webservice/xmlrpc/locallib.php index e9942d77c2a..4489f0c6a10 100644 --- a/webservice/xmlrpc/locallib.php +++ b/webservice/xmlrpc/locallib.php @@ -50,97 +50,6 @@ class webservice_xmlrpc_server extends webservice_zend_server { Zend_XmlRpc_Server_Fault::attachFaultException('moodle_exception'); } - /** - * Clean XML-RPC reponse - * @param array $response the response to clean - * @return array $response the cleaned response - */ - protected function clean_response($response) { - //check that the response is not an exception/server fault - if (!($response instanceof Zend_XmlRpc_Server_Fault)) { - $methodname = $this->zend_server->getRequest()->getMethod(); //retrieve the method name called by the client - $function = external_function_info($methodname); //retrieve the description of the method name - if (is_object($function)) { //if the method is not an object (no description found), - // do not make any change on the response - $returnvalue = $response->getReturnValue(); - $returnvalue = $this->clean_returnvalue($function->returns_desc, $returnvalue); - $response->setReturnValue($returnvalue); - } - } - return $response; - } - - - /** - * Clean response, if anything is incorrect - * invalid_parameter_exception is thrown, if an attribut is unknow from the description, - * just ignore it. - * Note: this is a recursive method - * @param external_description $description description of parameters - * @param mixed $response the actual parameters - * @return mixed params with added defaults for optional items, invalid_parameters_exception thrown if any problem found - */ - private function clean_returnvalue(external_description $description, $response) { - if ($description instanceof external_value) { - if (is_array($response) or is_object($response)) { - throw new invalid_parameter_exception(get_string('errorscalartype', 'webservice')); - } - - if ($description->type == PARAM_BOOL) { - // special case for PARAM_BOOL - we want true/false instead of the usual 1/0 - we can not be too strict here ;-) - if (is_bool($response) or $response === 0 or $response === 1 or $response === '0' or $response === '1') { - return (bool)$response; - } - } - return validate_param($response, $description->type, $description->allownull, get_string('errorinvalidparamsapi', 'webservice')); - - } else if ($description instanceof external_single_structure) { - if (!is_array($response)) { - throw new invalid_parameter_exception(get_string('erroronlyarray', 'webservice')); - } - $result = array(); - foreach ($description->keys as $key=>$subdesc) { - if (!array_key_exists($key, $response)) { - if ($subdesc->required == VALUE_REQUIRED) { - throw new invalid_parameter_exception(get_string('errormissingkey', 'webservice', $key)); - } - if ($subdesc instanceof external_value) { - if ($subdesc->required == VALUE_DEFAULT) { - try { - $result[$key] = $this->clean_returnvalue($subdesc, $subdesc->default); - } catch (invalid_parameter_exception $e) { - throw new webservice_parameter_exception('invalidextparam',$key); - } - } - } - } else { - try { - $result[$key] = $this->clean_returnvalue($subdesc, $response[$key]); - } catch (invalid_parameter_exception $e) { - //it's ok to display debug info as here the information is useful for ws client/dev - throw new webservice_parameter_exception('invalidextparam',$key." (".$e->debuginfo.")"); - } - } - unset($response[$key]); - } - - return $result; - - } else if ($description instanceof external_multiple_structure) { - if (!is_array($response)) { - throw new invalid_parameter_exception(get_string('erroronlyarray', 'webservice')); - } - $result = array(); - foreach ($response as $param) { - $result[] = $this->clean_returnvalue($description->content, $param); - } - return $result; - - } else { - throw new invalid_parameter_exception(get_string('errorinvalidparamsdesc', 'webservice')); - } - } - } /**