summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Auth.class.php105
-rw-r--r--src/lib/ContactMethod.class.php35
-rw-r--r--src/lib/Controller.class.php80
-rw-r--r--src/lib/Group.class.php23
-rw-r--r--src/lib/MessageHandler.class.php55
-rw-r--r--src/lib/MessageManager.class.php489
-rw-r--r--src/lib/Mime.class.php45
-rw-r--r--src/lib/Model.class.php3
-rw-r--r--src/lib/Plugin.class.php16
-rw-r--r--src/lib/Router.class.php110
-rw-r--r--src/lib/SenderBroadcast.class.php7
-rw-r--r--src/lib/SenderPrivate.class.php7
-rw-r--r--src/lib/User.class.php25
13 files changed, 1000 insertions, 0 deletions
diff --git a/src/lib/Auth.class.php b/src/lib/Auth.class.php
new file mode 100644
index 0000000..4c2a9c6
--- /dev/null
+++ b/src/lib/Auth.class.php
@@ -0,0 +1,105 @@
+<?php
+require_once('MessageManager.class.php');
+
+class Auth {
+ protected $mm = null;
+ protected $uid = false;
+ public function __construct($uid) {
+ global $mm;
+ $this->mm = $mm;
+ $this->uid = $uid;
+ }
+ public function getUID() {
+ return $this->uid;
+ }
+
+ /**********************************************************************\
+ * The 'auth' table. *
+ \**********************************************************************/
+
+ // Row Type ////////////////////////////////////////////////////////////
+ /**
+ * @return 0=unverified 1=user 2=admin 3=group
+ */
+ protected function getType() {
+ $type = $this->mm->getStatus($this->uid);
+ return $type;
+ }
+ protected function setType($type) {
+ return $this->mm->setStatus($this->uid, $type);
+ }
+ public function isUser() {
+ $type = $this->getType();
+ return ($type===1) || ($type===2);
+ }
+ public function isAdmin() {
+ $type = $this->getType();
+ return ($type===2);
+ }
+ public function isGroup() {
+ $type = $this->getType();
+ return ($type===3);
+ }
+ public function setUser($is_user) {
+ $is_user = ($is_user?true:false);
+ if ($this->isUser() != $is_user) {
+ $this->setType($is_user?1:0);
+ }
+ }
+ public function setAdmin($is_admin) {
+ $is_admin = ($is_admin?true:false);
+ $is_user = $this->isUser();
+ $this->setType($is_admin?2:($is_user?1:0));
+ }
+
+ // Permissions /////////////////////////////////////////////////////////
+ public function canRead() {
+ $logged_in_uid = $this->mm->isLoggedIn();
+ $is_me = ($logged_in_uid === $this->uid);
+
+ $logged_in_obj = $this->mm->getAuthObj($logged_in_uid);
+ $is_user = $logged_in_obj->isUser();
+
+ return ($is_me || $is_user);
+ }
+ public function canEdit() {
+ $logged_in_uid = $this->mm->isLoggedIn();
+ $is_me = ($logged_in_uid === $this->uid);
+
+ $logged_in_obj = $this->mm->getAuthObj($logged_in_uid);
+ $is_admin = $logged_in_obj->isAdmin();
+
+ return ($is_me || $is_admin);
+ }
+
+ // [user|group]name ////////////////////////////////////////////////////
+ public function getName() {
+ if (!$this->canRead()) return false;
+ return $this->mm->getUsername($this->uid);
+ }
+ public function setName($new_name) {
+ if (!$this->canEdit()) return false;
+ return $this->mm->setUsername($this->uid, $new_name);
+ }
+
+ /**********************************************************************\
+ * The 'users' table. *
+ \**********************************************************************/
+
+ public function getConf($setting) {
+ if (!$this->canRead()) return false;
+ return $this->mm->getUserConf($this->uid, $setting);
+ }
+ public function setConf($setting, $value) {
+ if (!$this->canEdit()) return false;
+ return $this->mm->setUserConf($this->uid, $setting, $value);
+ }
+ public function getConfArray($setting) {
+ $string = $this->getConf($setting);
+ return $this->mm->valueToArray($string);
+ }
+ public function setConfArray($setting, $list) {
+ $string = $this->mm->arrayToValue($list);
+ return $this->setConf($setting, $string);
+ }
+}
diff --git a/src/lib/ContactMethod.class.php b/src/lib/ContactMethod.class.php
new file mode 100644
index 0000000..c01374e
--- /dev/null
+++ b/src/lib/ContactMethod.class.php
@@ -0,0 +1,35 @@
+<?php
+
+global $CONTACT_METHODS;
+if (!isset($CONTACT_METHODS)) {
+ $CONTACT_METHODS = array();
+}
+
+class ContactMethod {
+ public $verb_slug = ''; // sms
+ public $addr_slug = ''; // phone
+ public $verb_text = ''; // text message
+ public $addr_text = ''; // phone number
+
+ public $handler = null;
+
+ public function __construct($verb_slug, $addr_slug,
+ $verb_text, $addr_text)
+ {
+ $this->$verb_slug = $verb_slug;
+ $this->$addr_slug = $addr_slug;
+ $this->$verb_text = $verb_text;
+ $this->$addr_Text = $addr_text;
+
+ global $CONTACT_METHODS;
+ $CONTACT_METHODS[$slug] = $this;
+ }
+ public function setHandler($handler) {
+ $this->$handler = $handler;
+ }
+}
+
+new ContactMethod('sms' , 'phone' ,
+ 'text message', 'cell number' );
+new ContactMethod('email' , 'email' ,
+ 'email' , 'email address');
diff --git a/src/lib/Controller.class.php b/src/lib/Controller.class.php
new file mode 100644
index 0000000..592ea2c
--- /dev/null
+++ b/src/lib/Controller.class.php
@@ -0,0 +1,80 @@
+<?php
+
+class Controller {
+ /**
+ * Find the best view file to include based on file extension and HTTP
+ * 'Accept' headers.
+ */
+ private function _resolveView($view) {
+ require_once('Mime.class.php');
+ require_once('HTTP_Accept.class.php');
+
+ // Make a list of candidate views
+ $glob_string = VIEWPATH.'/pages/'.$view.'.*.php';
+ $files = glob($glob_string);
+
+ // Return false if there were no candidate views.
+ if (count($files) < 1) return false;
+
+ // $prefs is a associative array where the key is the file
+ // extension, and the value is how much we like that extension.
+ // Higher numbers are better.
+ $prefs = array();
+
+ // $accept will tell us how much we like a given mime type,
+ // based on the ACCEPT constant.
+ $accept = new HTTP_Accept(ACCEPT);
+
+ // Loop through the candidate views, and record how much we
+ // like each.
+ foreach ($files as $file) {
+ $ext = preg_replace('@[^.]*\.(.*)\.php$@','$1', $file);
+ $mimes = Mime::ext2mime($ext);
+ foreach ($mimes as $mime) {
+ $quality = $accept->getQuality($mime);
+ if (isset($final[$ext])) {
+ $quality = max($final[$ext], $quality);
+ }
+ $prefs[$ext] = $quality;
+ }
+ }
+
+ // Sort $prefs such that the entry with the highest value will
+ // appear first.
+ arsort($prefs);
+
+ // Return the first entry in $prefs.
+ foreach ($prefs as $ext => $quality) {
+ return VIEWPATH."/pages/$view.$ext.php";
+ }
+ }
+
+ /**
+ * Show a $view, in the most appropriate format (according to file
+ * extension and HTTP Accept header). Pass the array $vars to the view.
+ */
+ protected function showView($view, $vars=null) {
+ global $VARS, $mm;
+ if ($vars===null) { $vars = array(); }
+ $VARS = $vars;
+ $VARS['template'] = $mm->template();
+ include($this->_resolveView($view));
+ unset($VARS);
+ }
+
+ // Here be default handlers ////////////////////////////////////////////
+
+ public function index($routed, $remainder) {
+ header('Content-type: text/plain');
+ echo " == Generic Controller Index == \n\n";
+ $routed_str = implode('/', $routed);
+ $remainder_str = implode('/', $remainder);
+ echo "Full path: $routed_str/$remainder_str\n";
+ echo "Controller path: $routed_str\n";
+ echo "Remainder path: $remainder_str\n";
+ }
+ public function http404($routed, $remainder) {
+ $this->showView('http404', array('routed'=>$routed,
+ 'remainder'=>$remainder));
+ }
+}
diff --git a/src/lib/Group.class.php b/src/lib/Group.class.php
new file mode 100644
index 0000000..96c5e2c
--- /dev/null
+++ b/src/lib/Group.class.php
@@ -0,0 +1,23 @@
+<?php
+require_once('Auth.class.php');
+
+class User extends Auth {
+ public function __construct($uid) {
+ parent::__construct($uid);
+ }
+ public function getUID() {
+ return $this->uid;
+ }
+
+ /**********************************************************************\
+ * The 'auth' table. *
+ \**********************************************************************/
+
+ /**********************************************************************\
+ * The 'users' table. *
+ \**********************************************************************/
+
+ public function getMembers() {
+ return $this->mm->getUsersInGroup($this->getName());
+ }
+}
diff --git a/src/lib/MessageHandler.class.php b/src/lib/MessageHandler.class.php
new file mode 100644
index 0000000..2dce491
--- /dev/null
+++ b/src/lib/MessageHandler.class.php
@@ -0,0 +1,55 @@
+<?php
+
+
+require_once('send/SenderGVSMS.class.php');
+require_once('send/SenderIdentica.class.php');
+
+set_include_path(get_include_path().PATH_SEPARATOR."$BASE/src/plugins");
+
+class MessageHandler {
+ public function __constructor() {
+
+ }
+ public function loadPlugin($plugin_name) {
+ global $m;
+
+ require_once("$plugin.class.php");
+ $obj = new $plugin;
+ $params = call_user_func("$plugin::configList");
+ foreach ($params as $param => $type) {
+ $value = $m->getPluginConf($plugin, $param);
+ if ($value!==false) {
+ switch ($type) {
+ case 'text':
+ case 'password':
+ $value = "$value";
+ break;
+ case 'int':
+ $value = (int)$value;
+ break;
+ }
+ configSet($param, $value);
+ }
+ }
+ return $obj;
+ }
+ public function main() {
+ global $BASE;
+
+ $private_senders = array();
+ $broadcast_senders = array();
+
+ $plugin_list = $m->getSysConf('plugins');
+ $plugins = explode(',', $plugin_list);
+ foreach ($plugins as $plugin) {
+ require_once("$plugin.class.php");
+ if (is_subclass_of($plugin, 'SenderPrivate')) {
+ $private_senders[] = $this->loadPlugin($plugin);
+ }
+ if (is_subclass_of($plugin, 'SenderBroadcast')) {
+ $broadcast_senders[] = $this->loadPlugin($plugin);
+ }
+ }
+ //foreach ($private_senders)
+ }
+} \ No newline at end of file
diff --git a/src/lib/MessageManager.class.php b/src/lib/MessageManager.class.php
new file mode 100644
index 0000000..d9d9fbc
--- /dev/null
+++ b/src/lib/MessageManager.class.php
@@ -0,0 +1,489 @@
+<?php
+
+class MessageManager {
+ private $conf;
+ private $mysql;
+ private $db_prefix;
+ private $pw_hasher;
+ private $template;
+ private $base;
+ private $users = array();
+
+ // Low-Level SQL functions /////////////////////////////////////////////
+
+ private function mysql() {
+ if (!isset($this->mysql)) {
+ $this->mysql_init();
+ }
+ return $this->mysql;
+ }
+ private function mysql_init() {
+ global $db_config;
+ require($this->conf);
+ $this->mysql = mysql_connect($db_config['host'],
+ $db_config['user'],
+ $db_config['password']);
+ mysql_set_charset($db_config['charset'], $this->mysql);
+ mysql_select_db($db_config['name'], $this->mysql);
+ $this->db_prefix = $db_config['prefix'];
+ unset($db_config);
+ }
+ private function mysql_table($table_name) {
+ $mysql = $this->mysql();
+ $prefix = $this->db_prefix;
+ return $prefix.mysql_real_escape_string($table_name, $mysql);
+ }
+ private function mysql_escape($string) {
+ $mysql = $this->mysql();
+ return mysql_real_escape_string($string, $mysql);
+ }
+ private function mysql_query($query) {
+ $mysql = $this->mysql();
+ return mysql_query($query, $mysql);
+ }
+ public function mysql_error() {
+ $mysql = $this->mysql();
+ return mysql_error($mysql);
+ }
+
+ // High-Level SQL functions ////////////////////////////////////////////
+
+ // The 'auth' table
+
+ public function getUID($username) {
+ $t = $this->mysql_table('auth');
+ $v = $this->mysql_escape($username);
+ $query =
+ "SELECT * \n".
+ "FROM $t \n".
+ "WHERE name='$v' ;";
+ $q = $this->mysql_query($query);
+ $user = mysql_fetch_array($q);
+ if (isset($user['uid'])) {
+ return (int)$user['uid'];
+ } else {
+ return false;
+ }
+ }
+ public function getUsername($uid) {
+ if (!is_int($uid)) return false;
+ $t = $this->mysql_table('auth');
+ $query =
+ "SELECT * \n".
+ "FROM $t \n".
+ "WHERE uid=$uid ;";
+ $q = $this->mysql_query($query);
+ $user = mysql_fetch_array($q);
+ if (isset($user['name'])) {
+ return $user['name'];
+ } else {
+ return false;
+ }
+ }
+ public function setUsername($uid, $username) {
+ if (!is_int($uid)) return false;
+ if ($this->getUID($username) !== false) {
+ return false;
+ }
+ $table = $this->mysql_table('auth');
+ $name = $this->mysql_escape($username);
+ $query =
+ "UPDATE $table \n".
+ "SET name='$name' \n".
+ "WHERE uid=$uid ;";
+ $q = $this->mysql_query($query);
+ return ($q?true:false);
+ }
+ public function getPasswordHash($uid) {
+ if (!is_int($uid)) return false;
+
+ $table = $this->mysql_table('auth');
+ $query =
+ "SELECT * \n".
+ "FROM $table \n".
+ "WHERE uid=$uid ;";
+ $q = $this->mysql_query($query);
+ $user = mysql_fetch_array($q);
+ if (isset($user['hash'])) {
+ return $user['hash'];
+ } else {
+ return false;
+ }
+ }
+ public function setPassword($uid, $password) {
+ if (!is_int($uid)) return false;
+ $table = $this->mysql_table('auth');
+
+ $hasher = $this->hasher();
+ @$hash = $hasher->HashPassword($password);
+ $query =
+ "UPDATE $table \n".
+ "SET hash='$hash' \n".
+ "WHERE uid=$uid ;";
+ $q = $this->mysql_query($query);
+ return ($q?true:false);
+ }
+ public function addUser($username, $password) {
+ $user_exits = $this->getUID($username);
+ if ($user_exists) {
+ return false;
+ }
+
+ $table = $this->mysql_table('auth');
+ $user = $this->mysql_escape($username);
+ $hasher = $this->hasher();
+ @$hash = $hasher->HashPassword($password);
+ $status = 0;
+ $query =
+ "INSERT INTO $table ( name, hash , status) \n".
+ "VALUES ('$user', '$hash', $status) ;";
+ $this->mysql_query($query);
+ $uid = $this->getUID($username);
+ return $uid;
+ }
+ public function getStatus($uid) {
+ if (!is_int($uid)) return false;
+ $table = $this->mysql_table('auth');
+ $query =
+ "SELECT * \n".
+ "FROM $table \n".
+ "WHERE uid=$uid ;";
+ $q = $this->mysql_query($query);
+ $user = mysql_fetch_array($q);
+ if (isset($user['status'])) {
+ return (int)$user['status'];
+ } else {
+ return false;
+ }
+ }
+ public function setStatus($uid, $status) {
+ if (!is_int($uid)) return false;
+ $table = $this->mysql_table('auth');
+ $s = $this->mysql_escape($status);
+ $query =
+ "UPDATE $table * \n".
+ "SET status=$s \n".
+ "WHERE uid=$uid ;";
+ $q = $this->mysql_query($query);
+ return ($q?true:false);
+ }
+ public function countUsers() {
+ $table = $this->mysql_table('auth');
+ $query = "SELECT COUNT(*) FROM $table;";
+ $q = $this->mysql_query($query);
+ $row = mysql_fetch_array($q);
+ $count = $row[0];
+ return $count;
+ }
+ public function listGroups() {
+ $table = $this->mysql_table('auth');
+ $query =
+ "SELECT uid \n".
+ "FROM $table \n".
+ "WHERE status=3 ;";
+ $q = $this->mysql_query($query);
+ $groups = array();
+ while (($row = mysql_fetch_array($q)) !==false) {
+ $groups[] = (int)$row[0];
+ }
+ return $groups;
+ }
+ public function listGroupNames() {
+ $table = $this->mysql_table('auth');
+ $query =
+ "SELECT name \n".
+ "FROM $table \n".
+ "WHERE status=3 ;";
+ $q = $this->mysql_query($query);
+ $groups = array();
+ while (($row = mysql_fetch_array($q)) !==false) {
+ $groups[] = $row[0].'';
+ }
+ return $groups;
+ }
+ public function listUsers() {
+ $table = $this->mysql_table('auth');
+ $query =
+ "SELECT uid \n".
+ "FROM $table \n".
+ "WHERE status < 3 ;";
+ $q = $this->mysql_query($query);
+ $users = array();
+ while (($row = mysql_fetch_array($q)) !==false) {
+ $users[] = (int)$row[0];
+ }
+ return $users;
+ }
+
+ // The 'users' table
+
+ public function findUser($setting, $value) {
+ $t = $this->mysql_table('users');
+ $k = $this->mysql_escape($setting);
+ $v = $this->mysql_escape($value);
+ $query =
+ "SELECT * \n".
+ "FROM $t \n".
+ "WHERE k = '$k' \n".
+ "AND UPPER(v)=UPPER('$v') ;";
+ $q = $this->mysql_query($query);
+ $user = mysql_fetch_array($q);
+ if (isset($user['uid'])) {
+ return $user['uid'];
+ } else {
+ return false;
+ }
+ }
+ public function getUserConf($uid, $setting) {
+ if (!is_int($uid)) return false;
+ $t = $this->mysql_table('users');
+ $k = $this->mysql_escape($setting);
+ $query =
+ "SELECT * \n".
+ "FROM $t \n".
+ "WHERE k='$k' \n".
+ "AND uid=$uid ;";
+ $q = $this->mysql_query($query);
+ $row = mysql_fetch_array($q);
+ if (isset($row['v'])) {
+ return $row['v'];
+ } else {
+ return false;
+ }
+ }
+ public function setUserConf($uid, $setting, $value) {
+ if (!is_int($uid)) return false;
+ $isset = ($this->getUserConf($uid, $setting) !== false);
+ $t = $this->mysql_table('users');
+ $k = $this->mysql_escape($setting);
+ $v = $this->mysql_escape($value);
+ if ($isset) {
+ $query =
+ "UPDATE $t \n".
+ "SET v = '$v' \n".
+ "WHERE k = '$k' \n".
+ "AND uid = $uid ;";
+ } else {
+ $query =
+ "INSERT INTO $t ( uid, k , v ) \n".
+ "VALUES ($uid, '$k', '$v') ;";
+ }
+ $q = $this->mysql_query($query);
+ return ($q?true:false);
+ }
+ public function getUsersInGroup($groupname) {
+ $table = $this->mysql_table('users');
+ $group = $this->mysql_escape($groupname);
+ $query =
+ "SELECT uid \n".
+ "FROM $table \n".
+ "WHERE k='groups' \n".
+ "AND v LIKE '%,$group,%' ;";
+ $q = $this->mysql_query($query);
+ $users = array();
+ while (($row = mysql_fetch_array($q)) !==false) {
+ $users[] = $row[0];
+ }
+ return $users;
+ }
+
+ // The 'plugins' table
+
+ public function getPluginConf($plugin, $key) {
+ $t = $this->mysql_table('plugins');
+ $p = $this->mysql_escape($plugin);
+ $k = $this->mysql_escape($key);
+ $query =
+ "SELECT * \n".
+ "FROM $t \n".
+ "WHERE k='$k' \n".
+ "AND plugin='$p' ;";
+ $q = $this->mysql_query($query);
+ $row = mysql_fetch_array($q);
+ if (isset($row['v'])) {
+ return $row['v'];
+ } else {
+ return false;
+ }
+ }
+ public function setPluginConf($plugin, $key, $value) {
+ $isset = ($this->getPluginConf($plugin, $key) !== false);
+ $t = $this->mysql_table('plugins');
+ $p = $this->mysql_escape($plugin);
+ $k = $this->mysql_escape($key);
+ $v = $this->mysql_escape($value);
+ if ($isset) {
+ $query =
+ "UPDATE $t \n".
+ "SET v = '$v' \n".
+ "WHERE k = '$k' \n".
+ "AND plugin = '$p' ;";
+ } else {
+ $query =
+ "INSERT INTO $t (plugin, k , v ) \n".
+ "VALUES ('$p' , '$k', '$v') ;";
+ }
+ $q = $this->mysql_query($query);
+ return ($q?true:false);
+ }
+
+ // The 'conf' table
+
+ public function getSysConf($key) {
+ $t = $this->mysql_table('conf');
+ $k = $this->mysql_escape($key);
+ $query =
+ "SELECT * \n".
+ "FROM $t \n".
+ "WHERE k='$k' ;";
+ $q = $this->mysql_query($query);
+ $row = mysql_fetch_array($q);
+ if (isset($row['v'])) {
+ return $row['v'];
+ } else {
+ return false;
+ }
+ }
+ public function setSysConf($key, $value) {
+ $isset = (getSysConf($key) !== false);
+ $t = $this->mysql_table('conf');
+ $k = $this->mysql_escape($key);
+ $v = $this->mysql_escape($value);
+ if ($isset) {
+ $query =
+ "UPDATE $t \n".
+ "SET v = '$v' \n".
+ "WHERE k = '$k' ;";
+ } else {
+ $query =
+ "INSERT INTO $t ( k , v ) \n".
+ "VALUES ('$k', '$v') ;";
+ }
+ $q = $this->mysql_query($query);
+ return ($q?true:false);
+ }
+
+ // If the remaining code has to deal with SQL, you're doing it wrong. //
+
+ public function baseUrl() {
+ if (!isset($this->base)) {
+ $this->base = $this->getSysConf('baseurl');
+ }
+ return $this->base;
+ }
+ public function hasher() {
+ if (!isset($this->pw_hasher)) {
+ require_once('PasswordHash.class.php');
+ $this->pw_hasher = new PasswordHash(8, false);
+ }
+ return $this->pw_hasher;
+ }
+
+ public function template() {
+ if (!isset($this->template)) {
+ require_once(VIEWPATH.'/Template.class.php');
+ $this->template = new Template($this->baseUrl(), $this);
+ }
+ return $this->template;
+ }
+
+ public function login($username, $password) {
+ $uid = $this->getUID($username);
+ if ($uid===false) {
+ // user does not exist
+ return 2;
+ }
+ $hash = $this->getPasswordHash($uid);
+ $hasher = $this->hasher();
+ if ($hasher->CheckPassword($password, $hash)) {
+ // success
+ $_SESSION['uid'] = $uid;
+ return 0;
+ } else {
+ // wrong password
+ return 1;
+ }
+ }
+ public function isLoggedIn() {
+ if ( isset($_SESSION['uid']) && ($_SESSION['uid']!='') ) {
+ return $_SESSION['uid'];
+ } else {
+ return false;
+ }
+ }
+ public function logout() {
+ $_SESSION['uid'] = '';
+ }
+
+ public function shortUrl($longUrl) {
+ $ch = curl_init('http://ur1.ca');
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFILEDS,
+ 'longurl='.urlencode($longUrl));
+ $html = curl_exec();
+ preg_match('/Your ur1 is: <a href="([^"]*)">/',$html,$matches);
+ $shortUrl = $matches[1];
+ curl_close($ch);
+ return $shortUrl;
+ }
+
+ public function __construct($conf_file) {
+ $this->conf = $conf_file;
+ if (!file_exists($this->conf)) {
+ $this->base = $_SERVER['REQUEST_URI'];
+ $t = $this->template();
+ $t->header('Message Manager');
+ $t->paragraph(
+ 'Awe shiz, dude, conf.php doesn\'t exist, you '.
+ 'need to go through the '.
+ '<a href="installer">installer</a>.');
+ $t->footer();
+ exit();
+ }
+ session_start();
+ }
+
+ public function getAuthObj($uid) {
+ if (!isset($this->users[$uid])) {
+ $is_group = ($this->getStatus($uid)===3);
+ if ($is_group) {
+ require_once('Group.class.php');
+ $this->users[$uid] = new Group($uid);
+ } else {
+ require_once('User.class.php');
+ $this->users[$uid] = new User($uid);
+ }
+ }
+ return $this->users[$uid];
+ }
+ /**
+ * Strip out empty group names and duplicates, sort.
+ */
+ private function sanitizeArray($in) {
+ $out = array();
+ foreach ($in as $item) {
+ if (($item !== '')||(!in_array($item, $out))) {
+ $out[] = $item;
+ }
+ }
+ natsort($out);
+ return $out;
+ }
+ /**
+ * Translate an array into a value suitable to be stored into a
+ * key-value store in the database.
+ */
+ public function arrayToValue($list) {
+ $out_list = $this->sanitizeArray($list);
+ return ','.implode(',', $out_list).',';
+ }
+ /**
+ * Translate a value from arrayToValue() back into an array.
+ */
+ public function valueToArray($value) {
+ $raw_list = explode(',', $value);
+ $out_list = $this->sanitizeArray($raw_list);
+ return $out_list;
+ }
+}
diff --git a/src/lib/Mime.class.php b/src/lib/Mime.class.php
new file mode 100644
index 0000000..40562b4
--- /dev/null
+++ b/src/lib/Mime.class.php
@@ -0,0 +1,45 @@
+<?php
+
+class Mime {
+ public static $mimes = array(
+ 'csv' => array('text/x-comma-separated-values',
+ 'text/comma-separated-values',
+ 'application/octet-stream',
+ 'application/vnd.ms-excel',
+ 'text/x-csv', 'text/csv', 'application/csv',
+ 'application/excel', 'application/vnd.msexcel'),
+ 'xhtml' => array('text/html', 'application/xhtml+xml'),
+ 'bmp' => 'image/bmp',
+ 'gif' => 'image/gif',
+ 'jpeg' => array('image/jpeg', 'image/pjpeg'),
+ 'jpg' => array('image/jpeg', 'image/pjpeg'),
+ 'jpe' => array('image/jpeg', 'image/pjpeg'),
+ 'png' => array('image/png', 'image/x-png'),
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'css' => 'text/css',
+ 'html' => 'text/html',
+ 'htm' => 'text/html',
+ 'txt' => 'text/plain',
+ 'json' => array('application/json', 'text/json')
+ );
+
+ public static function ext2mime($ext) {
+ $mimes = self::$mimes;
+ $mime = $mimes[$ext];
+ if (!is_array($mime)) $mime = array($mime);
+ return $mime;
+ }
+ public static function mime2ext($my_mime) {
+ $ret = array();
+ foreach (self::mimes as $ext => $mime) {
+ if (is_array($mime)) {
+ $match = in_array($my_mime, $mime);
+ } else {
+ $match = $my_mime==$mime;
+ }
+ if ($match) $ret[] = $ext;
+ }
+ return $ret;
+ }
+} \ No newline at end of file
diff --git a/src/lib/Model.class.php b/src/lib/Model.class.php
new file mode 100644
index 0000000..523976e
--- /dev/null
+++ b/src/lib/Model.class.php
@@ -0,0 +1,3 @@
+<?php
+
+class Model {}
diff --git a/src/lib/Plugin.class.php b/src/lib/Plugin.class.php
new file mode 100644
index 0000000..f2251d2
--- /dev/null
+++ b/src/lib/Plugin.class.php
@@ -0,0 +1,16 @@
+<?php
+
+abstract class Plugin {
+ protected $config = Array();
+
+ public abstract static function configList();
+ public abstract static function description();
+
+ public function configSet($param, $value) {
+ if (isset($this->config[$param])) {
+ $this->config[$param]=$value;
+ }
+ }
+
+ public abstract function init();
+} \ No newline at end of file
diff --git a/src/lib/Router.class.php b/src/lib/Router.class.php
new file mode 100644
index 0000000..459034d
--- /dev/null
+++ b/src/lib/Router.class.php
@@ -0,0 +1,110 @@
+<?php
+
+require_once('Controller.class.php');
+
+class Router {
+ /**
+ * Array mapping URIs to controllers.
+ * A controller may register itself either by using
+ * Router::register($URI, $controller[, $function]);
+ * or by adding itself to the $ROUTER global.
+ *
+ * The default here just gives us a 404 handler.
+ */
+ private $routes = array('/*' => 'Http404');
+
+ /**
+ * Instantiate a router that looks for controllers in $controllerpath.
+ */
+ public function Router($controllerpath) {
+ // create a $ROUTES global that can be used to set up our
+ // $this->routes.
+ global $ROUTES;
+ $ROUTES = $this->routes;
+
+ // Split $controllerpath into directories, and load the
+ // controllers in each.
+ $dirs = explode(PATH_SEPARATOR, $controllerpath);
+ foreach ($dirs as $dir) {
+ // Find all files in $dir with the ext `.class.php'
+ $controllerfiles = glob($dir.'/*.class.php');
+ foreach ($controllerfiles as $file) {
+ // and include them
+ require_once($file);
+ }
+ }
+
+ $this->routes = $ROUTES;
+ unset($ROUTES);
+ }
+
+ /**
+ * Route the page at the relative URL $page to the appropriate
+ * controller, and call the appropriate function.
+ */
+ public function route($page) {
+ $parts = explode('/', $page);
+ $length = count($parts); // the # of segments in $controllerpart
+
+ // if $page ends in "/", strip that off
+ if ($parts[$length-1]=='') {
+ array_pop($parts);
+ $length--;
+ }
+
+ $controllerpart = implode('/', $parts);
+
+ // Keep shortening $controllerpart until it matches something in
+ // $this->routes. The shortest it will ever become is '/*'.
+ // If no key exists for '/*', that's an infinite loop.
+ // Fortunately, the default value of $this->routes directs '/*'
+ // to the Http404 controller.
+ while(!isset($this->routes[$controllerpart])) {
+ $some_parts = array_slice($parts, 0, $length);
+ $controllerpart = implode('/', $some_parts).'/*';
+ $length--;
+ }
+ $length++;
+
+ // Figure what function to call on what controller
+ // Grammar Nazi Warning: `what' or `which'?
+ $controller = $this->routes[$controllerpart];
+ if (strpos($controller, '->')===false) {
+ // imply function
+ $function = $parts[$length];
+ } else {
+ preg_match('/(.*)->(.*)/', $controller, $matches);
+ $controller = $matches[1];
+ $function = $matches[2];
+ }
+
+ // Default to the `index' function, provided by all controllers
+ if ($function=='') {
+ $function = 'index';
+ }
+
+ // We will pass these arrays to the function.
+ $routed = array_slice($parts, 0, $length);
+ $remainder = array_slice($parts, $length);
+
+ // Finally, run the controller
+ $obj = new $controller();
+ if (in_array($function, get_class_methods($obj))) {
+ call_user_func(array($obj, $function),
+ $routed, $remainder);
+ } else {
+ $obj->http404($routed, $remainder);
+ }
+ }
+
+ /**
+ * This is to allow controllers to register themselves to the router.
+ * If $function=='', then the function will be determined by the segment
+ * to the right of the last segment in $path
+ */
+ public static function register($path, $controller, $function='') {
+ $str = $controller.(($function=='')?'':'->'.$function);
+ global $ROUTES;
+ $ROUTES[$path] = $str;
+ }
+} \ No newline at end of file
diff --git a/src/lib/SenderBroadcast.class.php b/src/lib/SenderBroadcast.class.php
new file mode 100644
index 0000000..7510ff2
--- /dev/null
+++ b/src/lib/SenderBroadcast.class.php
@@ -0,0 +1,7 @@
+<?php
+
+require_once('Plugin.class.php');
+
+abstract class SenderBroadcast extends Plugin {
+ public abstract function send($id, $subject, $body);
+}
diff --git a/src/lib/SenderPrivate.class.php b/src/lib/SenderPrivate.class.php
new file mode 100644
index 0000000..e6f2807
--- /dev/null
+++ b/src/lib/SenderPrivate.class.php
@@ -0,0 +1,7 @@
+<?php
+
+require_once('Plugin.class.php');
+
+abstract class SenderPrivate extends Plugin {
+ public abstract function send($to, $id, $subject, $body);
+}
diff --git a/src/lib/User.class.php b/src/lib/User.class.php
new file mode 100644
index 0000000..c1888b5
--- /dev/null
+++ b/src/lib/User.class.php
@@ -0,0 +1,25 @@
+<?php
+require_once('Auth.class.php');
+
+class User extends Auth {
+ public function __construct($uid) {
+ parent::__construct($uid);
+ }
+ public function getUID() {
+ return $this->uid;
+ }
+
+ /**********************************************************************\
+ * The 'auth' table. *
+ \**********************************************************************/
+
+ public function setPassword($password) {
+ if (!$this->canEdit()) return false;
+ return $this->mm->setPassword($this->uid, $password);
+ }
+
+ /**********************************************************************\
+ * The 'users' table. *
+ \**********************************************************************/
+
+}