diff options
author | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2011-12-06 12:48:54 (GMT) |
---|---|---|
committer | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2011-12-06 12:48:54 (GMT) |
commit | a5bda37b1243a287a8c14118b6898c23eed259db (patch) | |
tree | 22a8ba18cc6504840772e96ea985b6e035702608 | |
parent | 98562ba546ef3a378363679055132c134ca4e4d2 (diff) | |
download | kolab-wap-a5bda37b1243a287a8c14118b6898c23eed259db.tar.gz |
Check in initial version of Thomas' work
-rw-r--r-- | lib/SQL.php | 6 | ||||
-rw-r--r-- | lib/functions.php | 44 | ||||
-rw-r--r-- | lib/kolab_admin_controller.php | 238 | ||||
-rw-r--r-- | lib/kolab_admin_json_output.php | 45 | ||||
-rw-r--r-- | lib/kolab_admin_service.php | 22 | ||||
-rw-r--r-- | lib/kolab_admin_user_actions.php | 20 | ||||
-rw-r--r-- | public_html/api/index.php | 20 |
7 files changed, 367 insertions, 28 deletions
diff --git a/lib/SQL.php b/lib/SQL.php index 44cd600..6bcf7ed 100644 --- a/lib/SQL.php +++ b/lib/SQL.php @@ -8,6 +8,12 @@ /* Placeholder for the existing MySQL connection */ private $conn = FALSE; + private $sql_stats = Array( + 'queries' => 0, + 'query_time' => 0, + 'connections' => 0 + ); + /** * This implements the 'singleton' design pattern * diff --git a/lib/functions.php b/lib/functions.php index 09cf3a4..b0dd9a2 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -7,19 +7,26 @@ $GLOBALS['parse_start'] = ((float)$usec + (float)$sec); // Initialize some runtime variables - $ldap = Array(); - $sql = Array(); $messages = Array(); - $sql_stats = Array( - 'queries' => 0, - 'query_time' => 0, - 'connections' => 0 - ); - require_once('Session.php'); require_once('Conf.php'); + // register autoloader + function class_autoloader($classname) { + $classname = preg_replace('/(Net|MDB2)_(.+)/', "\\1/\\2", $classname); + + if ($fp = @fopen("$classname.php", 'r', true)) { + include_once("$classname.php"); + fclose($fp); + return true; + } + + return false; + } + + spl_autoload_register('class_autoloader'); + function query($query, $_conn = 'kolab_wap') { require_once('SQL.php'); @@ -28,6 +35,16 @@ return $sql->query($query); } + function need_login() { + print "You are not logged in<br/>"; + print '<form method="post">'; + print '<input type="text" name="username" /><br/>'; + print '<input type="password" name="password" /><br/>'; + print '<input type="submit" name="submit" value="Log in"/></form>'; + echo "<pre>"; print_r($_SESSION); echo "</pre>"; + exit; + } + function valid_login() { // The $_SESSION variable is controlled through lib/User.php's // _authenticate() @@ -42,15 +59,4 @@ } - function need_login() { - print "You are not logged in<br/>"; - print '<form method="post">'; - print '<input type="text" name="username" /><br/>'; - print '<input type="password" name="password" /><br/>'; - print '<input type="submit" name="submit" value="Log in"/></form>'; - echo "<pre>"; print_r($_SESSION); echo "</pre>"; - exit; - } - - ?> diff --git a/lib/kolab_admin_controller.php b/lib/kolab_admin_controller.php new file mode 100644 index 0000000..567731e --- /dev/null +++ b/lib/kolab_admin_controller.php @@ -0,0 +1,238 @@ +<?php + + /** + * Main controller class to serve the Kolab Admin API + */ + class kolab_admin_controller + { + public $output; + + private $uid; + private $docroot = '/'; + private $request = array(); + private $services = array(); + private $domains = array('localhost'); + + + public function __construct() + { + $this->output = new kolab_admin_json_output(); + + $this->docroot = self::slashify(substr(dirname($_SERVER['SCRIPT_FILENAME']), strlen($_SERVER['DOCUMENT_ROOT']))); + $this->request = explode('/', substr($_SERVER['REDIRECT_URL'], strlen($this->docroot))); + + // TODO: register services based on config or whatsoever + // $this->add_service('user', 'kolab_admin_user_actions'); + } + + + /** + * Register a class that serves a particular backend service + */ + public function add_service($service, $handler) + { + if ($this->services[$service]) { + error_log("Service $service is already registered."); + return false; + } + + $this->services[$service] = $handler; + } + + + /** + * Getter for a certain service object + */ + public function get_service($service) + { + // we are the system! + if ($service == 'system') + return $this; + + if ($handler = $this->services[$service]) { + if (is_string($handler)) + $handler = $this->services[$service] = new $handler($this); + + if (is_a($handler, 'kolab_admin_service')) + return $handler; + } + + throw new Exception("Unknown service", 400); + } + + + /** + * Getter for the authenticated user (ID) + */ + public function get_uid() + { + return $this->uid; + } + + + /** + * Process the request and dispatch it to the requested service + */ + public function dispatch($postdata) + { + $r = $this->request; + list($service, $method) = explode('.', array_shift($r)); + + // validate user session + if ($method != 'authenticate') { + if (!$this->session_validate($postdata)) { + throw new Exception("Invalid session", 403); + } + } + + // call service method + $service_handler = $this->get_service($service); + if (method_exists($service_handler, $method)) + $result = $service_handler->$method($r + $_GET, $postdata); + else + throw new Exception("Unknown method", 405); + + // send response + if ($result !== false) + $this->output->success($result); + else + $this->output->error("Internal error", 500); + } + + + /** + * Validate the submitted session token + */ + private function session_validate($postdata) + { + $sess_id = !empty($postdata['session_token']) ? $postdata['session_token'] : self::get_request_header('X-Session-Token'); + + if (empty($sess_id)) + return false; + + session_id($sess_id); + session_start(); + + if ($_SESSION['uid']) { + $this->uid = $_SESSION['uid']; + return true; + } + + return false; + } + + + /* ======== system.* method handlers ======== */ + + + /** + * Authenticate a user with the given credentials + * + * @param array GET request parameters + * @param array POST data + */ + private function authenticate($request, $postdata) + { + $valid = false; + + // destroy old session + if ($this->session_validate($postdata)) + session_destroy(); + + // TODO: authenticate user against auth backend + if (!empty($postdata['username'])) { + if ($postdata['username'] == 'admin' && $postdata['password'] == 'Welcome2KolabSystems') { + $this->uid = 'root@localhost'; + $valid = true; + } + } + + // start new (PHP) session + if ($valid) { + session_start(); + $_SESSION['uid'] = $this->uid; + $_SESSION['start'] = time(); + return array('user' => $this->uid, 'session_token' => session_id()); + } + + return false; + } + + + /** + * Provide a list of capabilities the backend provides to the current user + */ + private function capabilities() + { + $result = array(); + + // add capabilities of all registered services + foreach ($this->domains as $domain) { + // define our very own capabilities + $actions = array( + array('action' => 'system.quit', 'type' => 'w'), + ); + + foreach ($this->services as $sname => $handler) { + $service = $this->get_service($sname); + foreach ($service->capabilities($domain) as $method => $type) { + $actions[] = array('action' => "$sname.$method", 'type' => $type); + } + } + + $result[] = array('domain' => $domain, 'actions' => $actions); + } + + return array('capabilities' => $result); + } + + + /** + * End the current user ession + */ + private function quit() + { + session_destroy(); + return true; + } + + + /* ======== Utility functions ======== */ + + + /** + * Make sure the string ends with a slash + */ + public static function slashify($str) + { + return self::unslashify($str).'/'; + } + + /** + * Remove slash at the end of the string + */ + public static function unslashify($str) + { + return preg_replace('/\/$/', '', $str); + } + + /** + * Read a specific HTTP request header + * + * @param string $name Header name + * @return mixed Header value or null if not available + */ + public static function get_request_header($name) { + if (function_exists('getallheaders')) { + $hdrs = array_change_key_case(getallheaders(), CASE_UPPER); + $key = strtoupper($name); + } else { + $key = 'HTTP_' . strtoupper(strtr($name, '-', '_')); + $hdrs = array_change_key_case($_SERVER, CASE_UPPER); + } + + return $hdrs[$key]; + } + } + +?>
\ No newline at end of file diff --git a/lib/kolab_admin_json_output.php b/lib/kolab_admin_json_output.php new file mode 100644 index 0000000..9bc2c04 --- /dev/null +++ b/lib/kolab_admin_json_output.php @@ -0,0 +1,45 @@ +<?php + + /** + * View class generating JSON output + */ + class kolab_admin_json_output + { + + /** + * + */ + public function success($data) + { + if (!is_array($data)) + $data = array(); + + $this->send(array('status' => 'OK') + $data); + } + + + /** + * + */ + public function error($errdata, $code = 400) + { + if (is_string($errdata)) + $errdata = array('reason' => $errdata); + + $this->send(array('status' => 'ERROR', 'code' => $code) + $errdata); + } + + + /** + * + */ + public function send($data) + { + header("Content-Type: application/json"); + echo json_encode($data); + exit; + } + + } + +?>
\ No newline at end of file diff --git a/lib/kolab_admin_service.php b/lib/kolab_admin_service.php new file mode 100644 index 0000000..2d0cedc --- /dev/null +++ b/lib/kolab_admin_service.php @@ -0,0 +1,22 @@ +<?php + + /** + * Interface class for Kolab Admin Services + */ + abstract class kolab_admin_service + { + protected $controller; + + public function __construct($ctrl) + { + $this->controller = $ctrl; + } + + /** + * Advertise this service's capabilities + */ + abstract public function capabilities($domain); + + } + +?>
\ No newline at end of file diff --git a/lib/kolab_admin_user_actions.php b/lib/kolab_admin_user_actions.php new file mode 100644 index 0000000..544aaaf --- /dev/null +++ b/lib/kolab_admin_user_actions.php @@ -0,0 +1,20 @@ +<?php + + /** + * + */ + class kolab_admin_user_actions extends kolab_admin_service + { + public function capabilities($domain) + { + // TODO: check permissions of the authenticated user + $uid = $this->controller->get_uid(); + + return array( + 'list' => 'l', + 'info' => 'r', + ); + } + } + +?>
\ No newline at end of file diff --git a/public_html/api/index.php b/public_html/api/index.php index 5146e3d..dfde495 100644 --- a/public_html/api/index.php +++ b/public_html/api/index.php @@ -1,16 +1,18 @@ <?php require_once( dirname(__FILE__) . "/../../lib/functions.php"); - if (!valid_login()) { - need_login(); - } + // init frontend controller + $controller = new kolab_admin_controller; - if (!empty($_GET['object']) && !empty($_GET['action'])) { - if (function_exists($_GET['object'] . '_' . $_GET['action'])) { - call_user_func_array($_GET['object'] . '_' . $_GET['action']); - } elseif (file_exists(dirname(__FILE__) . "/../../lib/actions/" . $_GET['object'] . '_' . $_GET['action'] . ".php")) { - require_once(dirname(__FILE__) . "/../../lib/actions/" . $_GET['object'] . '_' . $_GET['action'] . ".php"); - } + try { + $postdata = $_SERVER['REQUEST_METHOD'] == 'POST' ? @json_decode(file_get_contents('php://input'), true) : null; + $controller->dispatch($postdata); + } catch(Exception $e) { + error_log($e->getMessage()); + $controller->output->error($e->getMessage(), $e->getCode()); } + // if we arrive here the controller didn't generate output + $controller->output->error("Invalid request"); + ?> |