123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- <?php
- namespace Elgg;
- class ActionsService {
-
-
- private $actions = array();
-
- private $currentAction = null;
-
-
- public function execute($action, $forwarder = "") {
- $action = rtrim($action, '/');
- $this->currentAction = $action;
-
-
-
-
-
-
- $exceptions = array(
- 'admin/plugins/disable',
- 'logout',
- 'file/download',
- );
-
- if (!in_array($action, $exceptions)) {
-
- action_gatekeeper($action);
- }
-
- $forwarder = str_replace(_elgg_services()->config->getSiteUrl(), "", $forwarder);
- $forwarder = str_replace("http://", "", $forwarder);
- $forwarder = str_replace("@", "", $forwarder);
- if (substr($forwarder, 0, 1) == "/") {
- $forwarder = substr($forwarder, 1);
- }
-
- if (!isset($this->actions[$action])) {
- register_error(_elgg_services()->translator->translate('actionundefined', array($action)));
- } elseif (!_elgg_services()->session->isAdminLoggedIn() && ($this->actions[$action]['access'] === 'admin')) {
- register_error(_elgg_services()->translator->translate('actionunauthorized'));
- } elseif (!_elgg_services()->session->isLoggedIn() && ($this->actions[$action]['access'] !== 'public')) {
- register_error(_elgg_services()->translator->translate('actionloggedout'));
- } else {
-
- if (_elgg_services()->hooks->trigger('action', $action, null, true)) {
- if (is_file($this->actions[$action]['file']) && is_readable($this->actions[$action]['file'])) {
- self::includeFile($this->actions[$action]['file']);
- } else {
- register_error(_elgg_services()->translator->translate('actionnotfound', array($action)));
- }
- }
- }
-
- $forwarder = empty($forwarder) ? REFERER : $forwarder;
- forward($forwarder);
- }
-
- protected static function includeFile($file) {
- include $file;
- }
-
-
- public function register($action, $filename = "", $access = 'logged_in') {
-
-
- $action = rtrim($action, '/');
-
- if (empty($filename)) {
-
- $path = _elgg_services()->config->get('path');
- if ($path === null) {
- $path = "";
- }
-
- $filename = $path . "actions/" . $action . ".php";
- }
-
- $this->actions[$action] = array(
- 'file' => $filename,
- 'access' => $access,
- );
- return true;
- }
-
-
- public function unregister($action) {
- if (isset($this->actions[$action])) {
- unset($this->actions[$action]);
- return true;
- } else {
- return false;
- }
- }
-
- public function validateActionToken($visible_errors = true, $token = null, $ts = null) {
- if (!$token) {
- $token = get_input('__elgg_token');
- }
-
- if (!$ts) {
- $ts = get_input('__elgg_ts');
- }
- $session_id = _elgg_services()->session->getId();
-
- if (($token) && ($ts) && ($session_id)) {
-
- $required_token = $this->generateActionToken($ts);
-
-
- $token_matches = _elgg_services()->crypto->areEqual($token, $required_token);
- if ($token_matches) {
- if ($this->validateTokenTimestamp($ts)) {
-
-
- $returnval = _elgg_services()->hooks->trigger('action_gatekeeper:permissions:check', 'all', array(
- 'token' => $token,
- 'time' => $ts
- ), true);
- if ($returnval) {
- return true;
- } else if ($visible_errors) {
- register_error(_elgg_services()->translator->translate('actiongatekeeper:pluginprevents'));
- }
- } else if ($visible_errors) {
-
- if (elgg_is_xhr()) {
- register_error(_elgg_services()->translator->translate('js:security:token_refresh_failed', array(_elgg_services()->config->getSiteUrl())));
- } else {
- register_error(_elgg_services()->translator->translate('actiongatekeeper:timeerror'));
- }
- }
- } else if ($visible_errors) {
-
- if (elgg_is_xhr()) {
- register_error(_elgg_services()->translator->translate('js:security:token_refresh_failed', array(_elgg_services()->config->getSiteUrl())));
- } else {
- register_error(_elgg_services()->translator->translate('actiongatekeeper:tokeninvalid'));
- }
- }
- } else {
- $req = _elgg_services()->request;
- $length = $req->server->get('CONTENT_LENGTH');
- $post_count = count($req->request);
- if ($length && $post_count < 1) {
-
- $error_msg = _elgg_services()->hooks->trigger('action_gatekeeper:upload_exceeded_msg', 'all', array(
- 'post_size' => $length,
- 'visible_errors' => $visible_errors,
- ), _elgg_services()->translator->translate('actiongatekeeper:uploadexceeded'));
- } else {
- $error_msg = _elgg_services()->translator->translate('actiongatekeeper:missingfields');
- }
- if ($visible_errors) {
- register_error($error_msg);
- }
- }
- return false;
- }
-
- protected function validateTokenTimestamp($ts) {
- $timeout = $this->getActionTokenTimeout();
- $now = time();
- return ($timeout == 0 || ($ts > $now - $timeout) && ($ts < $now + $timeout));
- }
-
- public function getActionTokenTimeout() {
- if (($timeout = _elgg_services()->config->get('action_token_timeout')) === null) {
-
- $timeout = 2;
- }
- $hour = 60 * 60;
- return (int)((float)$timeout * $hour);
- }
-
- public function gatekeeper($action) {
- if ($action === 'login') {
- if ($this->validateActionToken(false)) {
- return true;
- }
- $token = get_input('__elgg_token');
- $ts = (int)get_input('__elgg_ts');
- if ($token && $this->validateTokenTimestamp($ts)) {
-
-
- register_error(_elgg_services()->translator->translate('actiongatekeeper:crosssitelogin'));
- forward('login', 'csrf');
- }
-
- $this->validateActionToken();
- } else if ($this->validateActionToken()) {
- return true;
- }
- forward(REFERER, 'csrf');
- }
-
-
- public function generateActionToken($timestamp) {
- $session_id = _elgg_services()->session->getId();
- if (!$session_id) {
- return false;
- }
- $session_token = _elgg_services()->session->get('__elgg_session');
- return _elgg_services()->crypto->getHmac([(int)$timestamp, $session_id, $session_token], 'md5')
- ->getToken();
- }
-
-
- public function exists($action) {
- return (isset($this->actions[$action]) && file_exists($this->actions[$action]['file']));
- }
-
-
- public function ajaxForwardHook($hook, $reason, $return, $params) {
- if (elgg_is_xhr()) {
-
- $params = array_merge($params, array(
- 'output' => '',
- 'status' => 0,
- 'system_messages' => array(
- 'error' => array(),
- 'success' => array()
- )
- ));
-
-
- $output = ob_get_clean();
-
-
- $json = json_decode($output);
- if (isset($json)) {
- $params['output'] = $json;
- } else {
- $params['output'] = $output;
- }
-
-
- $system_messages = _elgg_services()->systemMessages->dumpRegister();
-
- if (isset($system_messages['success'])) {
- $params['system_messages']['success'] = $system_messages['success'];
- }
-
- if (isset($system_messages['error'])) {
- $params['system_messages']['error'] = $system_messages['error'];
- $params['status'] = -1;
- }
- if ($reason == 'walled_garden') {
- $reason = '403';
- }
- $httpCodes = array(
- '400' => 'Bad Request',
- '401' => 'Unauthorized',
- '403' => 'Forbidden',
- '404' => 'Not Found',
- '407' => 'Proxy Authentication Required',
- '500' => 'Internal Server Error',
- '503' => 'Service Unavailable',
- );
- if (isset($httpCodes[$reason])) {
- header("HTTP/1.1 $reason {$httpCodes[$reason]}", true);
- }
- $context = array('action' => $this->currentAction);
- $params = _elgg_services()->hooks->trigger('output', 'ajax', $context, $params);
-
-
-
-
-
- $http_accept = _elgg_services()->request->server->get('HTTP_ACCEPT');
- if (stripos($http_accept, 'application/json') === false) {
- header("Content-type: text/plain;charset=utf-8");
- } else {
- header("Content-type: application/json;charset=utf-8");
- }
-
- echo json_encode($params);
- exit;
- }
- }
-
-
- public function ajaxActionHook() {
- if (elgg_is_xhr()) {
- ob_start();
- }
- }
-
- public function getAllActions() {
- return $this->actions;
- }
- }
|