summaryrefslogtreecommitdiff
path: root/user.class
diff options
context:
space:
mode:
Diffstat (limited to 'user.class')
-rw-r--r--user.class511
1 files changed, 511 insertions, 0 deletions
diff --git a/user.class b/user.class
new file mode 100644
index 0000000..c0da429
--- /dev/null
+++ b/user.class
@@ -0,0 +1,511 @@
+<?php
+/*
+** $Id$
+**
+** it_user.class - User management and authentication
+**
+** ITools - the Internet Tools Library
+**
+** Copyright (C) 1995-2003 by the ITools Authors.
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of either the GNU General Public License
+** or the GNU Lesser General Public License, as published by the Free
+** Software Foundation. See http://www.gnu.org/licenses/ for details.
+*/
+
+/* PUBLIC and guaranteed to stay in same order (but not value) forever */
+define('IT_USER_STATUS_FAILED', 1); /* Wrong password given */
+define('IT_USER_STATUS_UNKNOWN', 2); /* Not logged in, no UID */
+define('IT_USER_STATUS_ANONYMOUS', 3); /* Not logged in, UID known */
+define('IT_USER_STATUS_KNOWN', 4); /* Not logged in, UID,username known */
+define('IT_USER_STATUS_SESSION', 5); /* Has a valid session */
+
+/* PRIVATE */
+define('_IT_USER_UID_COOKIE', 'UID');
+define('_IT_USER_UID_COOKIE_LIFETIME', 0x7FFFFFFF); /* Forever :-) */
+define('_IT_USER_STATUS_INVALID', 0); /* INTERNAL: Not yet evaluated */
+
+class it_user extends it_db_record
+{
+ /* PRIVATE */
+ var $status; /* Current status */
+ var $session; /* Currently active session */
+ var $sessioninitialized = false; /* Session already initialized? */
+
+ var $sessioncookiename; /* Name of cookie used to store session */
+ var $uidcookiename; /* Name of cookie used to store UID */
+
+ var $uid_field; /* Anonymous UID field in user database */
+ var $username_field; /* Username field in user database */
+ var $password_field; /* Password field in user database */
+
+ var $login_identifier_required = false;
+ var $login_identifier;
+ var $domain;
+ var $lifetime;
+ var $secret;
+ var $urlauthenticationcode = 'uac'; /* Name of UAC url parameter */
+
+ var $uid;
+ var $username;
+
+ /*
+ * Used by login(), contains unvalidated user data to give overloading
+ * functions way of accessing it.
+ */
+ var $workrecord;
+
+
+/* Constructor */
+function it_user($table, $username_field = "username", $password_field = "password", $uid_field = "")
+{
+ /* Default to uid being primary key, may change later */
+ $this->it_db_record($table, $uid_field);
+ $this->session = new it_session;
+ $this->status = _IT_USER_STATUS_INVALID;
+ $this->uidcookiename = _IT_USER_UID_COOKIE;
+
+ $this->uid_field = $uid_field;
+ $this->username_field = $username_field;
+ $this->password_field = $password_field;
+}
+
+
+/**
+ * Post processing, called by ITools after reading a database record
+ * @access private
+ */
+function _read_post_process()
+{
+ parent::_read_post_process();
+
+ /* If read succeeded, get UID. This is necessary because it's only set if a cookie is present (i.e. in web-context) */
+ if (isset($this->data[$this->uid_field]))
+ $this->uid = $this->data[$this->uid_field];
+
+ /* Get username from database field */
+ $this->username = $this->data[$this->username_field];
+}
+
+
+function set_session_cookie_name($sessioncookiename)
+{
+ $this->sessioncookiename = $sessioncookiename;
+}
+
+
+function set_uid_cookie_name($uidcookiename)
+{
+ $this->uidcookiename = $uidcookiename;
+}
+
+
+function set_domain($domain)
+{
+ $this->domain = $domain;
+}
+
+
+function set_session_lifetime($lifetime)
+{
+ $this->lifetime = $lifetime;
+}
+
+
+function set_login_identifier($login_identifier)
+{
+ $this->login_identifier_required = true;
+ $this->login_identifier = $login_identifier;
+}
+
+
+function _init_session()
+{
+ if (!$this->sessioninitialized)
+ {
+ /* Using a non-standard values for session? */
+ if ($this->sessioncookiename)
+ $this->session->set_cookiename($this->sessioncookiename);
+
+ if (isset($this->domain))
+ $this->session->set_domain($this->domain);
+
+ if (isset($this->lifetime))
+ $this->session->set_lifetime($this->lifetime);
+
+ if (isset($this->secret))
+ $this->session->set_secret($this->secret);
+
+ $this->session->init();
+ $this->sessioninitialized = true;
+ }
+}
+
+
+function get_status()
+{
+ if ($this->status == _IT_USER_STATUS_INVALID)
+ {
+ $this->_init_session();
+
+ if ($this->session->is_valid())
+ {
+ $this->status = IT_USER_STATUS_SESSION;
+ $this->_set_uid($this->session->get_uid());
+ $this->set_key_field($this->uid_field);
+ $this->read($this->uid);
+
+ /* username == uid means we don't have a username yet */
+ if ($this->username == $this->uid)
+ $this->username = "";
+ }
+ else if (isset($_COOKIE[$this->uidcookiename]) && ($this->uid = substr($_COOKIE[$this->uidcookiename], 0, 32)))
+ {
+ $this->set_key_field($this->uid_field);
+ $this->read($this->uid);
+
+ if ($this->username == $this->uid)
+ $this->username = "";
+
+ if ($this->username)
+ $this->status = IT_USER_STATUS_KNOWN;
+ else
+ $this->status = IT_USER_STATUS_ANONYMOUS;
+ }
+ else
+ {
+ $this->status = IT_USER_STATUS_UNKNOWN;
+ $this->username = '';
+
+ if ($this->uid_field)
+ $this->_set_uid($this->create_uid());
+ }
+ }
+
+ #debug("status $this->status");
+
+ return $this->status;
+}
+
+
+function get_username()
+{
+ return $this->username;
+}
+
+
+function get_uid()
+{
+ return $this->uid;
+}
+
+
+function _set_uid($uid)
+{
+ $this->uid = $uid;
+
+ if (!isset($_COOKIE[$this->uidcookiename]) || ($_COOKIE[$this->uidcookiename] != $uid))
+ {
+ @setcookie($this->uidcookiename, $uid, _IT_USER_UID_COOKIE_LIFETIME, "/", $this->domain);
+ $_COOKIE[$this->uidcookiename] = $uid;
+ }
+}
+
+
+/* Return session status of this user: Is she logged in? */
+function is_logged_in()
+{
+ return $this->status == IT_USER_STATUS_SESSION;
+}
+
+
+/*
+ * Try to log in user. Use get_status() to check result.
+ * NOTE: Must not be called AFTER get_status() has been used.
+ * @param $username User ID to login
+ * @param $password Password to authenticate login
+ * @param $ignorepassword True if you want to login anyway (e.g. 'su')
+ */
+function login($username, $password, $ignorepassword = false, $withsession = true)
+{
+ $result = false;
+
+ $this->_init_session();
+ $this->workrecord = new it_db_record($this->table, $this->username_field);
+
+ #debug("username '$username'");
+ if ($this->workrecord->read($username))
+ {
+ #debug("password '$password', '" . $this->workrecord->data[$this->password_field] . "'");
+ if ($ignorepassword || $this->check_password($password, $this->workrecord->data[$this->password_field]))
+ {
+ #debug("login_identifier '$this->login_identifier'");
+ $this->session->set_uid($this->workrecord->data[$this->uid_field]);
+ if ($withsession)
+ $result = $this->session->set_valid(true, $this->login_identifier_required, $this->login_identifier);
+ else
+ $result = $_COOKIE[$this->uidcookiename] = $this->session->get_uid();
+ }
+ #debug("result '$result'");
+ }
+
+ if ($result && ($this->session->get_uid() == $this->workrecord->data[$this->uid_field]))
+ $this->username = $this->workrecord->data[$this->username_field];
+
+ if ($result)
+ $this->status = _IT_USER_STATUS_INVALID;
+ else
+ $this->status = IT_USER_STATUS_FAILED;
+
+ return $result;
+}
+
+
+/*
+ * Logout user.
+ * NOTE: Must not be called AFTER get_status() has been used.
+ */
+function logout()
+{
+ $this->_init_session();
+ $this->session->set_valid(false);
+}
+
+
+/*
+ * Throw away all user information and restart from scratch...
+ */
+function purge()
+{
+ $this->status = _IT_USER_STATUS_INVALID;
+ $this->_set_uid($this->create_uid());
+ $this->username = "";
+ $this->session->purge();
+}
+
+
+/*
+ * Create user database record.
+ * @param $tags Fields to set (uid and username are optional)
+ * @see it_db_record
+ */
+function create($tags)
+{
+ $result;
+
+ /* Make sure UID is always set in database records */
+ if ($this->uid_field)
+ {
+ if (!$this->uid)
+ $this->_set_uid($this->create_uid());
+
+ $tags[$this->uid_field] = $this->uid;
+ }
+
+ /* Create dummy but unique username if none given */
+ if (!$tags[$this->username_field] && !$this->data[$this->username_field])
+ $tags[$this->username_field] = $this->uid;
+
+ if ($result = it_db_record::create($tags))
+ $this->_set_uid($this->data[$this->uid_field]);
+
+ return $result;
+}
+
+
+/*
+ * Create unique identifier used for anonymously users, Override if you want
+ * different type of UIDs.
+ * Returns newly created uid
+ */
+function create_uid()
+{
+ return md5(uniqid(rand())); /* random garbage */
+}
+
+
+/*
+ * Create a login identifier and set session to login identifier 'secret' value
+ * Returns a value to be put into the login <form> which has to be passed to
+ * login() to create a valid session
+ */
+function create_login_identifier()
+{
+ return $this->session->create_login_identifier();
+}
+
+
+/*
+ * Create a random password with given length.
+ */
+function create_password($length = 8, $charset = 'abcdefghjkpqrstuvwxyz23456789ABCDEFGHJKPRSTUVWXYZ')
+{
+ $result = "";
+
+ mt_srand((double)microtime() * 1000000);
+
+ for ($i = 0; $i < $length; $i++)
+ $result .= substr($charset, mt_rand(0, strlen($charset) - 1), 1);
+
+ return $result;
+}
+
+
+/*
+ * Crypt the password, same function is used in check_login_status
+ * You can use unencrypted passwords if you extend the user class and
+ * override this function.
+ */
+function crypt_password($password)
+{
+ $result = $this->table->db->safe_sql_query("SELECT PASSWORD('" . mysql_real_escape_string($password) . "')");
+ list($pw) = $this->table->db->fetch_array($result);
+
+ return $pw;
+}
+
+
+/*
+ * Crypt the password and compare it to cryptedpassword.
+ */
+function check_password($password, $cryptedpassword)
+{
+ return $this->crypt_password($password) == $cryptedpassword;
+}
+
+
+/*
+ * Check if cookies are enabled.
+ * NOTE: Only works if you used create_login_identifier() on previous page
+ */
+function has_cookies()
+{
+ return $this->session->has_cookies();
+}
+
+
+/*
+ * Check if $name would be an acceptable username
+ */
+function is_valid_username($name)
+{
+ if ((strlen($name) >= 2) && (strlen($name) <= 32))
+ {
+ if (!ereg('["\'\\&\$+]', $name))
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ * Check if $word would be an acceptable password
+ */
+function is_valid_password($word)
+{
+ if ((strlen($word) >= 2) && (strlen($word) <= 32))
+ {
+ if (!ereg('["\'\\&\$+]', $word))
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ * Sign string with current user id or session
+ * @param $text Text to be signed
+ * @param $withsession Sign with session if true, with uid if false
+ * @return Signature for $text
+ */
+function create_signature($text, $withsession = true)
+{
+ if ($withsession)
+ {
+ switch ($this->get_status())
+ {
+ case IT_USER_STATUS_SESSION:
+ $result = $this->session->create_signature($text);
+ break;
+
+ default:
+ $result = md5("$this->secret,$text,$this->secret");
+ break;
+ }
+ }
+ else
+ {
+ /* Sign with UID only */
+ $result = md5("$this->secret,$this->uid,$text,$this->secret");
+ }
+
+ return $result;
+}
+
+/*
+ * Check signature for string with current user id or session
+ * @param $text Text which was signed
+ * @param $signature Signature to be checked
+ * @param $withsession Signed with session if true, with uid if false
+ * @return True if signature ok, false otherwise
+ */
+function check_signature($text, $signature, $withsession = true)
+{
+ if ($withsession)
+ {
+ switch ($this->get_status())
+ {
+ case IT_USER_STATUS_SESSION:
+ $result = $this->session->check_signature($text, $signature);
+ break;
+
+ default:
+ $result = (md5("$this->secret,$text,$this->secret") == $signature);
+ break;
+ }
+ }
+ else
+ {
+ /* Sign with UID only */
+ $result = ($this->create_signature($text, false) == $signature);
+ }
+
+ return $result;
+}
+
+/*
+ * Sign an url with parameters
+ * @param $url URL to sign
+ * @param $withsession Signed with session if true, with uid if false
+ * @return Signed url
+ */
+function sign_url($url, $withsession = false)
+{
+ if (strstr($url, '?'))
+ $url .= "&amp;$this->urlauthenticationcode=" . $this->create_signature(str_replace('&amp;', '&', $url), $withsession);
+
+ return $url;
+}
+
+/*
+ * Check if url GET parameters are properly signed and not modified
+ * @param $withsession Signed with session if true, with uid if false
+ * @return False if url was modified
+ */
+function check_url($withsession = false)
+{
+ $result = true; /* Default to true for url without parameters */
+
+ if (!empty($_SERVER['QUERY_STRING']))
+ {
+ $url = ereg_replace("&?$this->urlauthenticationcode=[a-zA-Z0-9]*", '', $_SERVER['REQUEST_URI']);
+
+ $result = $this->check_signature($url, $GLOBALS[$this->urlauthenticationcode], $withsession);
+ }
+
+ return $result;
+}
+
+} /* End class it_user */
+
+?>