예제 #1
0
파일: web_services.php 프로젝트: elgg/elgg
/**
 * Executes a method.
 * A method is a function which you have previously exposed using expose_function.
 *
 * @param string $method Method, e.g. "foo.bar"
 *
 * @return GenericResult The result of the execution.
 * @throws APIException|CallException
 * @access private
 */
function execute_method($method)
{
    global $API_METHODS;
    // method must be exposed
    if (!isset($API_METHODS[$method])) {
        $msg = elgg_echo('APIException:MethodCallNotImplemented', array($method));
        throw new APIException($msg);
    }
    // function must be callable
    $function = elgg_extract('function', $API_METHODS[$method]);
    if (!$function || !is_callable($function)) {
        $msg = elgg_echo('APIException:FunctionDoesNotExist', array($method));
        throw new APIException($msg);
    }
    // check http call method
    if (strcmp(get_call_method(), $API_METHODS[$method]["call_method"]) != 0) {
        $msg = elgg_echo('CallException:InvalidCallMethod', array($method, $API_METHODS[$method]["call_method"]));
        throw new CallException($msg);
    }
    $parameters = get_parameters_for_method($method);
    // may throw exception, which is not caught here
    verify_parameters($method, $parameters);
    $serialised_parameters = serialise_parameters($method, $parameters);
    // Execute function: Construct function and calling parameters
    $serialised_parameters = trim($serialised_parameters, ", ");
    // Sadly we probably can't get rid of this eval() in 2.x. Doing so would involve
    // replacing serialise_parameters(), which does a bunch of weird stuff we need to
    // stay BC with 2.x. There are tests for a lot of these quirks in ElggCoreWebServicesApiTest
    // particularly in testSerialiseParametersCasting().
    $arguments = eval("return [{$serialised_parameters}];");
    if ($API_METHODS[$method]['assoc']) {
        $argument = array_combine(_elgg_ws_get_parameter_names($method), $arguments);
        $result = call_user_func($function, $argument);
    } else {
        $result = call_user_func_array($function, $arguments);
    }
    $result = elgg_trigger_plugin_hook('rest:output', $method, $parameters, $result);
    // Sanity check result
    // If this function returns an api result itself, just return it
    if ($result instanceof GenericResult) {
        return $result;
    }
    if ($result === false) {
        $msg = elgg_echo('APIException:FunctionParseError', array($function, $serialised_parameters));
        throw new APIException($msg);
    }
    if ($result === NULL) {
        // If no value
        $msg = elgg_echo('APIException:FunctionNoReturn', array($function, $serialised_parameters));
        throw new APIException($msg);
    }
    // Otherwise assume that the call was successful and return it as a success object.
    return SuccessResult::getInstance($result);
}
예제 #2
0
/**
 * Executes a method.
 * A method is a function which you have previously exposed using expose_function.
 *
 * @param string $method Method, e.g. "foo.bar"
 *
 * @return GenericResult The result of the execution.
 * @throws APIException|CallException
 * @access private
 */
function execute_method($method)
{
    global $API_METHODS;
    // method must be exposed
    if (!isset($API_METHODS[$method])) {
        $msg = elgg_echo('APIException:MethodCallNotImplemented', array($method));
        throw new APIException($msg);
    }
    // function must be callable
    $function = null;
    if (isset($API_METHODS[$method]["function"])) {
        $function = $API_METHODS[$method]["function"];
        // allow array version of static callback
        if (is_array($function) && isset($function[0], $function[1]) && is_string($function[0]) && is_string($function[1])) {
            $function = "{$function[0]}::{$function[1]}";
        }
    }
    if (!is_string($function) || !is_callable($function)) {
        $msg = elgg_echo('APIException:FunctionDoesNotExist', array($method));
        throw new APIException($msg);
    }
    // check http call method
    if (strcmp(get_call_method(), $API_METHODS[$method]["call_method"]) != 0) {
        $msg = elgg_echo('CallException:InvalidCallMethod', array($method, $API_METHODS[$method]["call_method"]));
        throw new CallException($msg);
    }
    $parameters = get_parameters_for_method($method);
    // may throw exception, which is not caught here
    verify_parameters($method, $parameters);
    $serialised_parameters = serialise_parameters($method, $parameters);
    // Execute function: Construct function and calling parameters
    $serialised_parameters = trim($serialised_parameters, ", ");
    // @todo remove the need for eval()
    $result = eval("return {$function}({$serialised_parameters});");
    $result = elgg_trigger_plugin_hook('rest:output', $method, $parameters, $result);
    // Sanity check result
    // If this function returns an api result itself, just return it
    if ($result instanceof GenericResult) {
        return $result;
    }
    if ($result === false) {
        $msg = elgg_echo('APIException:FunctionParseError', array($function, $serialised_parameters));
        throw new APIException($msg);
    }
    if ($result === NULL) {
        // If no value
        $msg = elgg_echo('APIException:FunctionNoReturn', array($function, $serialised_parameters));
        throw new APIException($msg);
    }
    // Otherwise assume that the call was successful and return it as a success object.
    return SuccessResult::getInstance($result);
}
 public function testSerialiseParameters()
 {
     // int and bool
     $this->registerFunction();
     $parameters = array('param1' => 1, 'param2' => 0);
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ',1,false');
     // string
     $this->registerFunction(false, false, array('param1' => array('type' => 'string')));
     $parameters = array('param1' => 'testing');
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",'testing'");
     // test string with " in it
     $this->registerFunction(false, false, array('param1' => array('type' => 'string')));
     $parameters = array('param1' => 'test"ing');
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ',\'test"ing\'');
     // test string with ' in it
     $this->registerFunction(false, false, array('param1' => array('type' => 'string')));
     $parameters = array('param1' => 'test\'ing');
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",'test\\'ing'");
     // test string with \ in it
     $this->registerFunction(false, false, array('param1' => array('type' => 'string')));
     $parameters = array('param1' => 'test\\ing');
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",'test\\ing'");
     // test string with \' in it
     $this->registerFunction(false, false, array('param1' => array('type' => 'string')));
     $parameters = array('param1' => "test\\'ing");
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",'test\\\\'ing'");
     // test\\'ing
     // test string reported by twall in #1364
     $this->registerFunction(false, false, array('param1' => array('type' => 'string')));
     $parameters = array('param1' => '{"html":"<div><img src=\\"http://foo.com\\"/>Blah Blah</div>"}');
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",'{\"html\":\"<div><img src=\\\"http://foo.com\\\"/>Blah Blah</div>\"}'");
     // float
     $this->registerFunction(false, false, array('param1' => array('type' => 'float')));
     $parameters = array('param1' => 2.5);
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ',2.5');
     // indexed array of strings
     $this->registerFunction(false, false, array('param1' => array('type' => 'array')));
     $parameters = array('param1' => array('one', 'two'));
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",array('0'=>'one','1'=>'two')");
     // associative array of strings
     $this->registerFunction(false, false, array('param1' => array('type' => 'array')));
     $parameters = array('param1' => array('first' => 'one', 'second' => 'two'));
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",array('first'=>'one','second'=>'two')");
     // indexed array of strings
     $this->registerFunction(false, false, array('param1' => array('type' => 'array')));
     $parameters = array('param1' => array(1, 2));
     $s = serialise_parameters('test', $parameters);
     $this->assertIdentical($s, ",array('0'=>'1','1'=>'2')");
     // test unknown type
     $this->registerFunction(false, false, array('param1' => array('type' => 'bad')));
     $parameters = array('param1' => 'test');
     $this->expectException('APIException');
     $s = serialise_parameters('test', $parameters);
 }
예제 #4
0
/**
 * Executes a method.
 * A method is a function which you have previously exposed using expose_function.
 *
 * @param string $method Method, e.g. "foo.bar"
 *
 * @return GenericResult The result of the execution.
 * @throws APIException, CallException
 * @access private
 */
function execute_method($method)
{
    global $API_METHODS, $CONFIG;
    // method must be exposed
    if (!isset($API_METHODS[$method])) {
        $msg = elgg_echo('APIException:MethodCallNotImplemented', array($method));
        throw new APIException($msg);
    }
    // function must be callable
    if (!isset($API_METHODS[$method]["function"]) || !is_callable($API_METHODS[$method]["function"])) {
        $msg = elgg_echo('APIException:FunctionDoesNotExist', array($method));
        throw new APIException($msg);
    }
    // check http call method
    if (strcmp(get_call_method(), $API_METHODS[$method]["call_method"]) != 0) {
        $msg = elgg_echo('CallException:InvalidCallMethod', array($method, $API_METHODS[$method]["call_method"]));
        throw new CallException($msg);
    }
    $parameters = get_parameters_for_method($method);
    if (verify_parameters($method, $parameters) == false) {
        // if verify_parameters fails, it throws exception which is not caught here
    }
    $serialised_parameters = serialise_parameters($method, $parameters);
    // Execute function: Construct function and calling parameters
    $function = $API_METHODS[$method]["function"];
    $serialised_parameters = trim($serialised_parameters, ", ");
    // @todo document why we cannot use call_user_func_array here
    $result = eval("return {$function}({$serialised_parameters});");
    // Sanity check result
    // If this function returns an api result itself, just return it
    if ($result instanceof GenericResult) {
        return $result;
    }
    if ($result === false) {
        $msg = elgg_echo('APIException:FunctionParseError', array($function, $serialised_parameters));
        throw new APIException($msg);
    }
    if ($result === NULL) {
        // If no value
        $msg = elgg_echo('APIException:FunctionNoReturn', array($function, $serialised_parameters));
        throw new APIException($msg);
    }
    // Otherwise assume that the call was successful and return it as a success object.
    return SuccessResult::getInstance($result);
}
예제 #5
0
 public function testSerialiseParametersCasting()
 {
     $types = ['int' => [["0", 0], ["1", 1], [" 1", 1]], 'bool' => [["0", false], [" 1", true], [" false", false], ["true", false]], 'float' => [["1.65", 1.65], [" 1.65 ", 1.65]], 'array' => [[["2 ", " bar"], [2, "bar"]], [["' \""], ["' \\\""]]], 'string' => [[" foo ", "foo"]]];
     foreach ($types as $type => $tests) {
         foreach ($tests as $test) {
             set_input('param', $test[0]);
             $this->registerFunction(false, false, ['param' => ['type' => $type]]);
             $serialized = serialise_parameters('test', ['param' => get_input('param')]);
             $serialized = trim($serialized, ", ");
             // evaled
             $value = eval("return {$serialized};");
             $this->assertEqual($value, $test[1]);
         }
     }
 }