From 83e460cdc3fc09867a3adb48c3d0894579dd3050 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 7 Jan 2012 08:21:00 -0800 Subject: Refactor to separate the framework from the app; drop message stuff, this app is just user management. Add a json view for individual users --- apps/um/lib/DB.class.php | 164 +++++++++++++++ apps/um/lib/Database.class.php | 403 ++++++++++++++++++++++++++++++++++++ apps/um/lib/Hasher.class.php | 18 ++ apps/um/lib/Login.class.php | 41 ++++ apps/um/lib/Plugin.class.php | 25 +++ apps/um/lib/PluginManager.class.php | 99 +++++++++ apps/um/lib/Singleton.class.php | 12 ++ apps/um/lib/Site.class.php | 32 +++ 8 files changed, 794 insertions(+) create mode 100644 apps/um/lib/DB.class.php create mode 100644 apps/um/lib/Database.class.php create mode 100644 apps/um/lib/Hasher.class.php create mode 100644 apps/um/lib/Login.class.php create mode 100644 apps/um/lib/Plugin.class.php create mode 100644 apps/um/lib/PluginManager.class.php create mode 100644 apps/um/lib/Singleton.class.php create mode 100644 apps/um/lib/Site.class.php (limited to 'apps/um/lib') diff --git a/apps/um/lib/DB.class.php b/apps/um/lib/DB.class.php new file mode 100644 index 0000000..ac8dafe --- /dev/null +++ b/apps/um/lib/DB.class.php @@ -0,0 +1,164 @@ +getConfString($key); + $someone_else_changed_it = + $value_fork != $value_base; + if ($someone_else_changed_it) { + if ($value == $value_fork) { + // we might as well not have + $we_changed_it = false; + } else { + $forked = true; + } + } + } + if (!$we_changed_it) { + $doit = false;// nothing to do + } + } + if ($doit) { + return $this->setConf($key, $value); + } + if ($forked) { + return $value_fork; + } + } + + public static function get($table, $unit, $key) { + switch ($table) { + case 'conf': + case 'plugins': + return self::admin_get($unit, $key); + break; + case 'users': + return self::user_get($unit, $key); + break; + default: + return false; + } + } + public static function raw_set($table, $unit, $key, $value) { + switch ($table) { + case 'conf': + case 'plugins': + return self::admin_get($unit, $key, $value); + break; + case 'users': + return self::user_set($unit, $key, $value); + break; + default: + return false; + } + } + + private static function user_get($uid, $key) { + $user = Auth::getInstance($uid); + $logged_in_user = Auth::getInstance(Login::isLoggedIn()); + + $post_key = $key."[$uid]"; + @$value = $_POST[$post_key]; + $editable = $user->canEdit(); + + switch ($key) { + case 'auth_uid': + $value = $user->getUID(); + $editable = false; + break; + case 'auth_name': + $value = $user->getName(); + break; + case 'auth_user': + $editable = $editable && $logged_in_user->isAdmin(); + $value = $user->isUser()?'true':'false'; + break; + case 'auth_admin': + $editable = $editable && $logged_in_user->isAdmin(); + $value = $user->isAdmin()?'true':'false'; + break; + case 'auth_delete': + $editable = $editable && $logged_in_user->isAdmin(); + $value = 'false'; + break; + default: + $value = $user->getConf($key); + if ($value===false) $value=''; + break; + } + + return array('value'=>$value, + 'post_key'=>$post_key, + 'editable'=>$editable); + } + private static function user_set($uid, $key, $value) { + $user = Auth::getInstance($uid); + + switch ($key) { + case 'auth_uid': + return false; + break; + case 'auth_name': + return $user->setName($value); + break; + case 'auth_user': + return $user->setUser($value=='true'); + break; + case 'auth_admin': + return $user->setAdmin($value=='true'); + break; + case 'auth_delete': + if ($value=='true') return $user->delete(); + default: + return $user->setConf($key, $value); + break; + } + } + + private static function admin_get($plugin, $key) { + $db = Database::getInstance(); + $user = Auth::getInstance(Login::isLoggedIn()); + if ($user->isAdmin()) { + $editable = true; + switch ($plugin) { + case 'system': + $value = $db->getSysConf($key); + break; + default: + $value = $db->getPluginConf($plugin, $key); + break; + } + } else { + $editable = false; + $value = false; + } + + return array('value'=>$value, + 'post_key'=>'to be implemented',// FIXME + 'editable'=>$editable); + } + private static function admin_set($plugin, $key, $value) { + $db = Database::getInstance(); + $user = Auth::getInstance(Login::isLoggedIn()); + if (!$user->isAdmin()) { + return false; + } + switch ($plugin) { + case 'system': + return $db->setSysConf($key, $value); + default: + return $db->setPluginConf($plugin, $key, $value); + } + } +} diff --git a/apps/um/lib/Database.class.php b/apps/um/lib/Database.class.php new file mode 100644 index 0000000..a76d891 --- /dev/null +++ b/apps/um/lib/Database.class.php @@ -0,0 +1,403 @@ +conf = $conf_file; + self::$me = $this; + } + public static function getInstance() { + return self::$me; + } + + // 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 = Hasher::getInstance(); + @$hash = $hasher->hash($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 = Hasher::getInstance(); + @$hash = $hasher->hash($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 = ($this->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); + } + + /** + * Strip out empty group names and duplicates, sort. + */ + private static 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 static function arrayToValue($list) { + $out_list = self::sanitizeArray($list); + return ','.implode(',', $out_list).','; + } + /** + * Translate a value from arrayToValue() back into an array. + */ + public static function valueToArray($value) { + $raw_list = explode(',', $value); + $out_list = self::sanitizeArray($raw_list); + return $out_list; + } + +} diff --git a/apps/um/lib/Hasher.class.php b/apps/um/lib/Hasher.class.php new file mode 100644 index 0000000..dc16d68 --- /dev/null +++ b/apps/um/lib/Hasher.class.php @@ -0,0 +1,18 @@ +pw_hash = new PasswordHash(8, false); + } + + public function hash($password) { + return $this->pw_hash->HashPassword($password); + } + public function check($password, $hash) { + return $this->pw_hash->CheckPassword($password, $hash); + } +} diff --git a/apps/um/lib/Login.class.php b/apps/um/lib/Login.class.php new file mode 100644 index 0000000..bb21928 --- /dev/null +++ b/apps/um/lib/Login.class.php @@ -0,0 +1,41 @@ +getUID($username); + if ($uid!==false && $db->getStatus($uid)>=3) + $uid=false; + if ($uid===false) { + // user does not exist + return 2; + } + $hash = $db->getPasswordHash($uid); + if ($hasher->check($password, $hash)) { + // success + $_SESSION['uid'] = $uid; + return 0; + } else { + // wrong password + return 1; + } + } + public static function isLoggedIn() { + if ( isset($_SESSION['uid']) && ($_SESSION['uid']!='') ) { + return $_SESSION['uid']; + } else { + return false; + } + } + public static function logout() { + $_SESSION['uid'] = ''; + } +} diff --git a/apps/um/lib/Plugin.class.php b/apps/um/lib/Plugin.class.php new file mode 100644 index 0000000..9d2fc2e --- /dev/null +++ b/apps/um/lib/Plugin.class.php @@ -0,0 +1,25 @@ +config[$param])) { + $this->config[$param]=$value; + } + } + + public function userConfig() { return array(); } + protected function addConfigGroup($arr, $group) { + if (!isset($arr[$group])) + $arr[$group] = array(); + } + + public abstract function init(); + + public function antispam_html() { return ''; } + public function antispam_verify() { return true; } +} diff --git a/apps/um/lib/PluginManager.class.php b/apps/um/lib/PluginManager.class.php new file mode 100644 index 0000000..ce5a3ef --- /dev/null +++ b/apps/um/lib/PluginManager.class.php @@ -0,0 +1,99 @@ + $type) { + $value = $db->getPluginConf($plugin_name, $param); + if ($value!==false) { + switch ($type) { + case 'text': + case 'password': + $value = "$value"; + break; + case 'int': + $value = (int)$value; + break; + } + $obj->configSet($param, $value); + } + } + return $obj; + } + + /** + * Return an array of available plugin names. + */ + public function listPlugins() { + $plugins = array(); + + $dirs = explode(PATH_SEPARATOR, PLUGINPATH); + foreach ($dirs as $dir) { + // Find all files in $dir with the ext `.class.php' + $files = glob($dir.'/*.class.php'); + foreach ($files as $file) { + $plugins[] = preg_replace('@\.class\.php$@', '$1', basename($file)); + } + } + + return $plugins; + } + + /** + * Return an array of enabled plugin names. + */ + public function getActivePlugins() { + $db = Database::getInstance(); + $string = $db->getSysConf('plugins'); + return $db->valueToArray($string); + } + + /** + * Set the enabled plugins. + */ + public function setActivePlugins($plugins) { + $db = Database::getInstance(); + $string = $db->arrayToValue($plugins); + return $db->setSysConf('plugins', $string); + } + + /** + * Load the enabled plugins. + */ + public function loadPlugins() { + if ($this->loaded) return; + $plugin_names = $this->getActivePlugins(); + foreach ($plugin_names as $name) { + $this->plugins[$name] = $this->loadPlugin($name); + } + $this->loaded = true; + } + + public function callHook($hook, $arg=null) { + $this->loadPlugins(); + $ret = array(); + foreach ($this->plugins as $name => $plugin) { + $ret[$name] = call_user_func(array($plugin, $hook), + &$arg); + } + return $ret; + } + + public function staticHook($plugin_name, $hook) { + require_once("$plugin_name.class.php"); + return call_user_func("$plugin_name::$hook"); + } + +} diff --git a/apps/um/lib/Singleton.class.php b/apps/um/lib/Singleton.class.php new file mode 100644 index 0000000..2f8c74f --- /dev/null +++ b/apps/um/lib/Singleton.class.php @@ -0,0 +1,12 @@ +/',$html,$matches); + $shortUrl = $matches[1]; + curl_close($ch); + return $shortUrl; + } + + public function baseUrl() { + $base = $_SERVER['REQUEST_URI']; + + $db = Database::getInstance(); + if ($db !== null) { + $b = $db->getSysConf('baseurl'); + if ($b != false) { + $base = $b; + } + } + + return $base; + } +} -- cgit v1.2.3-2-g168b