/** * 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); }
/** * 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); }
/** * 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); }
throw new SecurityException(elgg_echo('SecurityException:APIAccessDenied')); } // Register some default PAM methods, plugins can add their own register_pam_handler('pam_auth_session_or_hmac'); // Command must either be authenticated by a hmac or the user is already logged in register_pam_handler('pam_auth_usertoken', 'required'); // Either token present and valid OR method doesn't require one. register_pam_handler('pam_auth_anonymous_method'); // Support anonymous functions // Get parameter variables $method = get_input('method'); $result = null; // Authenticate session if (pam_authenticate()) { // Authenticated somehow, now execute. $token = ""; $params = get_parameters_for_method($method); // Use $CONFIG->input instead of $_REQUEST since this is called by the pagehandler if (isset($params['auth_token'])) { $token = $params['auth_token']; } $result = execute_method($method, $params, $token); } else { throw new SecurityException(elgg_echo('SecurityException:NoAuthMethods')); } // Finally output if (!$result instanceof GenericResult) { throw new APIException(elgg_echo('APIException:ApiResultUnknown')); } // Output the result page_draw($method, elgg_view("api/output", array("result" => $result)));
/** * This function looks at the super-global variable $_SERVER and extracts the various * header variables needed to pass to the validation functions after performing basic validation. * * @return stdClass Containing all the values. * @throws APIException Detailing any error. */ function get_and_validate_api_headers() { $result = new stdClass(); $result->method = get_call_method(); if ($result->method != "GET" && $result->method != "POST") { // Only allow these methods throw new APIException(elgg_echo('APIException:NotGetOrPost')); } $result->api_key = $_SERVER['HTTP_X_ELGG_APIKEY']; if ($result->api_key == "") { throw new APIException(elgg_echo('APIException:MissingAPIKey')); } $result->hmac = $_SERVER['HTTP_X_ELGG_HMAC']; if ($result->hmac == "") { throw new APIException(elgg_echo('APIException:MissingHmac')); } $result->hmac_algo = $_SERVER['HTTP_X_ELGG_HMAC_ALGO']; if ($result->hmac_algo == "") { throw new APIException(elgg_echo('APIException:MissingHmacAlgo')); } $result->time = $_SERVER['HTTP_X_ELGG_TIME']; if ($result->time == "") { throw new APIException(elgg_echo('APIException:MissingTime')); } if ($result->time < microtime(true) - 86400.0 || $result->time > microtime(true) + 86400.0) { // Basic timecheck, think about making this smaller if we get loads of users and the cache gets really big. throw new APIException(elgg_echo('APIException:TemporalDrift')); } $result->get_variables = get_parameters_for_method(get_input('method')); //$_SERVER['QUERY_STRING']; if ($result->get_variables == "") { throw new APIException(elgg_echo('APIException:NoQueryString')); } if ($result->method == "POST") { $result->posthash = $_SERVER['HTTP_X_ELGG_POSTHASH']; if ($result->posthash == "") { throw new APIException(elgg_echo('APIException:MissingPOSTHash')); } $result->posthash_algo = $_SERVER['HTTP_X_ELGG_POSTHASH_ALGO']; if ($result->posthash_algo == "") { throw new APIException(elgg_echo('APIException:MissingPOSTAlgo')); } $result->content_type = $_SERVER['CONTENT_TYPE']; if ($result->content_type == "") { throw new APIException(elgg_echo('APIException:MissingContentType')); } } return $result; }