summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/SQL.php6
-rw-r--r--lib/functions.php44
-rw-r--r--lib/kolab_admin_controller.php238
-rw-r--r--lib/kolab_admin_json_output.php45
-rw-r--r--lib/kolab_admin_service.php22
-rw-r--r--lib/kolab_admin_user_actions.php20
-rw-r--r--public_html/api/index.php20
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");
+
?>